Skip to content

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

Merged
rubenvdlinde merged 2 commits into
developmentfrom
fix/register-declaration
Aug 5, 2026
Merged

fix(register): the portaliq register could never be created on a clean install#40
rubenvdlinde merged 2 commits into
developmentfrom
fix/register-declaration

Conversation

@rubenvdlinde

Copy link
Copy Markdown
Contributor

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

lib/Settings/portaliq_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, the
$data['components']['registers'] loop) -- so a clean install created 9 schemas
and ZERO registers, and then skipped all 5 seed objects, whose @self.register
is resolved through the registersMap that section populates.

Reproduced on a disposable Nextcloud 34 + OpenRegister main (0.2.19):

occ app:enable portaliq -> "portaliq 0.1.8 enabled"
GET /api/registers -> HTTP 200, 0 registers
GET /api/schemas -> HTTP 200, 9 schemas
GET /api/objects/portaliq/portalPage -> HTTP 404
{"message":"Register not found: 'portaliq'"}

The failure is silent: the import itself reports success, and every object
route 404s with a message that reads like a routing problem rather than a
missing register.

After this change, on the same clean install (register absent BEFORE enable,
which is the evidence the fix stands on its own):

register 'portaliq' present AFTER enable: True
id=1 title='Portaliq Register' version=0.12.0 schemas=9
9/9 expected schema slugs present AND bound into the register
9/9 GET /api/objects/portaliq/ -> HTTP 200

The slug is derived, not invented: lib/ and the seed objects address
objects/portaliq/<schema> and all 5 seed objects carry
@self.register: "portaliq".

The schema list is the EXACT union of the register document's schemas, by
SLUG. That distinction is load-bearing: ImportHandler keys its schemasMap by
$schema->getSlug() (ImportHandler.php:1397/1477), not by the components.schemas
object key. For portaliq the two coincide; in decidesk, openbuild and scholiq
they do not, and a register listing the keys binds ZERO schemas while still
looking correctly declared.

info.version 0.11.0 -> 0.12.0 so OpenRegister's version-gated importFromApp
actually re-imports; a frozen version would never pick up later schemas.

appinfo/info.xml already lists InitializeSettings under as well as
, so portaliq does NOT have the second, independent gap where
a register import is declared post-migration-only and therefore never runs on
a fresh install (Installer::installAppLastSteps() guards both the pre- and
post-migration blocks with if ($previousVersion !== '')).

…n install

lib/Settings/portaliq_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, the
$data['components']['registers'] loop) -- so a clean install created 9 schemas
and ZERO registers, and then skipped all 5 seed objects, whose @self.register
is resolved through the registersMap that section populates.

Reproduced on a disposable Nextcloud 34 + OpenRegister main (0.2.19):

  occ app:enable portaliq              -> "portaliq 0.1.8 enabled"
  GET /api/registers                   -> HTTP 200, 0 registers
  GET /api/schemas                     -> HTTP 200, 9 schemas
  GET /api/objects/portaliq/portalPage -> HTTP 404
                                          {"message":"Register not found: 'portaliq'"}

The failure is silent: the import itself reports success, and every object
route 404s with a message that reads like a routing problem rather than a
missing register.

After this change, on the same clean install (register absent BEFORE enable,
which is the evidence the fix stands on its own):

  register 'portaliq' present AFTER enable: True
    id=1 title='Portaliq Register' version=0.12.0 schemas=9
  9/9 expected schema slugs present AND bound into the register
  9/9 GET /api/objects/portaliq/<schema> -> HTTP 200

The slug is derived, not invented: lib/ and the seed objects address
`objects/portaliq/<schema>` and all 5 seed objects carry
`@self.register: "portaliq"`.

The schema list is the EXACT union of the register document's schemas, by
SLUG. That distinction is load-bearing: ImportHandler keys its schemasMap by
$schema->getSlug() (ImportHandler.php:1397/1477), not by the components.schemas
object key. For portaliq the two coincide; in decidesk, openbuild and scholiq
they do not, and a register listing the keys binds ZERO schemas while still
looking correctly declared.

info.version 0.11.0 -> 0.12.0 so OpenRegister's version-gated importFromApp
actually re-imports; a frozen version would never pick up later schemas.

appinfo/info.xml already lists InitializeSettings under <install> as well as
<post-migration>, so portaliq does NOT have the second, independent gap where
a register import is declared post-migration-only and therefore never runs on
a fresh install (Installer::installAppLastSteps() guards both the pre- and
post-migration blocks with `if ($previousVersion !== '')`).
@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/portaliq @ 64b692c

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

Quality workflow — 2026-08-04 20:00 UTC

Download the full PDF report from the workflow artifacts.

…assertion

PortaliqRegisterConfigTest pinned info.version to 0.11.0, so bumping it to
0.12.0 (needed for OpenRegister's version-gated importFromApp to re-import at
all) turned that test red. Updated, with the reason recorded alongside the
existing per-version notes.

Adds testRegisterDeclaresItselfWithExactlyItsOwnSchemaSlugs, which is the
actual gate: it asserts components.registers.portaliq exists, that its version
tracks info.version, and that its schema list is EXACTLY the set of schema
SLUGS (falling back to the components.schemas key only when a schema declares
none). Slugs, not keys, because ImportHandler keys its schemasMap by
$schema->getSlug() — a register listing the keys binds zero schemas while
still looking correctly declared, which is how this defect stayed invisible.

Verified as a positive control, not assumed: against the pre-change
portaliq_register.json the new test FAILS with "Failed asserting that an array
has the key 'portaliq'"; with the fix the class is 9 tests / 50 assertions
green.
@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/portaliq @ ce2dac9

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

Quality workflow — 2026-08-04 20:15 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 cacbba7 into development Aug 5, 2026
33 of 35 checks passed
@rubenvdlinde
rubenvdlinde deleted the fix/register-declaration branch August 14, 2026 09:47
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