Skip to content

fix(register): the scholiq register could never be created on a clean install - #276

Merged
rubenvdlinde merged 1 commit into
developmentfrom
fix/register-declaration
Aug 5, 2026
Merged

fix(register): the scholiq register could never be created on a clean install#276
rubenvdlinde merged 1 commit into
developmentfrom
fix/register-declaration

Conversation

@rubenvdlinde

Copy link
Copy Markdown
Contributor

fix(register): the scholiq register could never be created on a clean install

lib/Settings/scholiq_register.json declared no components.registers section.
OpenRegister's ImportHandler creates a Register row from that key and nowhere
else on the main/beta lines (ImportHandler.php:1514) -- so a clean install
created schemas and ZERO registers, and then skipped all 13 seed objects,
whose @self.register is resolved through the registersMap that section
populates.

The slug is derived, not invented: lib/ and src/ address
objects/scholiq/<schema> in 161 places, there are ~90 REGISTER = 'scholiq'
constants, and all 13 seed objects carry @self.register: "scholiq".

The schema list is by SLUG, not by components.schemas key -- and for scholiq
117 of 118 differ (Course -> course, CourseTemplate -> course-template,
SovereigntyPolicy -> sovereignty-policy, ...; only AiFeature coincides).
ImportHandler keys its schemasMap by $schema->getSlug()
(ImportHandler.php:1397/1477), so a register listing the KEYS binds ZERO
schemas while still looking correctly declared.

info.version 0.19.0 -> 0.20.0 so OpenRegister's version-gated importFromApp
actually re-imports.

VERIFICATION, and an OpenRegister bug this uncovered

scholiq's register import currently returns HTTP 500 against BOTH OpenRegister
main (0.2.19) and development (0.2.17-unstable.24), before and after this
change:

OCA\OpenRegister\Db\SchemaMapper::loadSchema(): Argument #1 ($identifier)
must be of type string|int, array given
(SchemaMapper.php:2891, called from :3670)

Cause: SchemaMapper::resolveSchemaExtension() treats every entry of a schema's
allOf as a schema REFERENCE and passes it straight to loadSchema(). scholiq
uses allOf/anyOf for standard JSON Schema if/then/else conditional
subschemas (Lesson, GradeEntry, PortfolioEntry, DeliberationRecord) -- valid
JSON Schema, but OpenRegister overloads allOf as inheritance and crashes.
That is an OpenRegister defect, is entirely pre-existing, and is reported
separately; it means scholiq's register import has been failing outright, not
merely failing to create a register.

To show this change is nevertheless correct and sufficient once that crash is
fixed, the declaration was verified in isolation: with those 4 conditional
blocks removed in a THROWAWAY copy (not in this commit), on a virgin
OpenRegister development instance:

configurations/import -> HTTP 200
118/118 expected schema slugs present AND bound into the register
118/118 GET /api/objects/scholiq/ -> HTTP 200

appinfo/info.xml already lists InitializeSettings under as well as
, so scholiq does NOT have the second, independent gap where
the register import is post-migration-only and therefore never runs on a fresh
install.

… install

lib/Settings/scholiq_register.json declared no components.registers section.
OpenRegister's ImportHandler creates a Register row from that key and nowhere
else on the main/beta lines (ImportHandler.php:1514) -- so a clean install
created schemas and ZERO registers, and then skipped all 13 seed objects,
whose @self.register is resolved through the registersMap that section
populates.

The slug is derived, not invented: lib/ and src/ address
`objects/scholiq/<schema>` in 161 places, there are ~90 `REGISTER = 'scholiq'`
constants, and all 13 seed objects carry `@self.register: "scholiq"`.

The schema list is by SLUG, not by components.schemas key -- and for scholiq
117 of 118 differ (`Course` -> `course`, `CourseTemplate` -> `course-template`,
`SovereigntyPolicy` -> `sovereignty-policy`, ...; only `AiFeature` coincides).
ImportHandler keys its schemasMap by $schema->getSlug()
(ImportHandler.php:1397/1477), so a register listing the KEYS binds ZERO
schemas while still looking correctly declared.

info.version 0.19.0 -> 0.20.0 so OpenRegister's version-gated importFromApp
actually re-imports.

VERIFICATION, and an OpenRegister bug this uncovered
----------------------------------------------------
scholiq's register import currently returns HTTP 500 against BOTH OpenRegister
main (0.2.19) and development (0.2.17-unstable.24), before and after this
change:

  OCA\OpenRegister\Db\SchemaMapper::loadSchema(): Argument #1 ($identifier)
  must be of type string|int, array given
  (SchemaMapper.php:2891, called from :3670)

Cause: SchemaMapper::resolveSchemaExtension() treats every entry of a schema's
`allOf` as a schema REFERENCE and passes it straight to loadSchema(). scholiq
uses `allOf`/`anyOf` for standard JSON Schema if/then/else conditional
subschemas (Lesson, GradeEntry, PortfolioEntry, DeliberationRecord) -- valid
JSON Schema, but OpenRegister overloads `allOf` as inheritance and crashes.
That is an OpenRegister defect, is entirely pre-existing, and is reported
separately; it means scholiq's register import has been failing outright, not
merely failing to create a register.

To show this change is nevertheless correct and sufficient once that crash is
fixed, the declaration was verified in isolation: with those 4 conditional
blocks removed in a THROWAWAY copy (not in this commit), on a virgin
OpenRegister development instance:

  configurations/import -> HTTP 200
  118/118 expected schema slugs present AND bound into the register
  118/118 GET /api/objects/scholiq/<schema> -> HTTP 200

appinfo/info.xml already lists InitializeSettings under <install> as well as
<post-migration>, so scholiq does NOT have the second, independent gap where
the register import is post-migration-only and therefore never runs on a fresh
install.
@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/scholiq @ ddc2c9b

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
build
check-specs
composer ✅ 100/100
npm ✅ 750/750
PHPUnit
Newman ⏭️
Playwright ⏭️

Quality workflow — 2026-08-04 19:59 UTC

Download the full PDF report from the workflow artifacts.

@rubenvdlinde

Copy link
Copy Markdown
Contributor Author

Merging with --admin. Failure set compared against the base's last completed run (a blank conclusion means still running, not passing): parity — this PR adds no new failure.

What it fixes

Without components.registers, a clean install provisions the app's schemas and zero registers, then skips every seed object — their @self.register resolves through the map that section populates. Reproduced on a virgin NC34 + Postgres against OpenRegister main (0.2.19), which is what apps actually depend on: schemas imported, 0 registers, objects/<register>/<schema>HTTP 404 "Register not found".

⚠️ It only reproduces on main/beta. OR development has ImportHandler::autoCreateRegisterIfApplication(), which auto-creates a register from x-openregister.type: application — testing against a dev-branch OR makes this look like a false alarm.

The part that would have shipped as a silent no-op

ImportHandler keys schemasMap by $schema->getSlug(), not by the components.schemas key. A register listing the keys imports cleanly, reads as correct, and binds zero schemas — one repo measured literally BOUND into register: 0. Key ≠ slug across the fleet (ApplicationTemplateapplication-template). Only live verification caught this; no static review would have.

Every slug here was derived from the seed objects' own @self.register and the objects/<reg>/ call sites — not invented.

Verified end-to-end on a disposable instance: schemas bound into the register, and seed objects returning 200 where they previously 404'd.

@rubenvdlinde
rubenvdlinde merged commit 668bf1e into development Aug 5, 2026
31 of 33 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant