Skip to content

fix(app-registry): delegate registry reads to the applications-service so self-registered MFEs render (#533) - #547

Merged
izzywdev merged 6 commits into
masterfrom
claude/app-registry-read-write-split-533
Aug 4, 2026
Merged

fix(app-registry): delegate registry reads to the applications-service so self-registered MFEs render (#533)#547
izzywdev merged 6 commits into
masterfrom
claude/app-registry-read-write-split-533

Conversation

@izzywdev

@izzywdev izzywdev commented Aug 4, 2026

Copy link
Copy Markdown
Owner

Fixes #533 — the host-backend app-registry read/write split-brain that kept every self-registering MFE (FuzePicker's picker, and others) out of the shell.

Root cause

Two routers mount at /api/v1/app-registry (backend/src/index.ts): the local-DB adapter (routes/appRegistry.ts) first, then the applications-service proxy (routes/app-registry.ts). The mount comment says the adapter should pass unmatched requests through to the proxy via next() — but GET /apps answered unconditionally from the local apps table and never called next(), so it shadowed the proxy for the one read the shell uses.

Meanwhile self-registration (POST /apps, PUT /apps/<slug>, POST /apps/<slug>/activate) is only defined on the adapter as GET /apps, so those verbs already fall through to the proxy → the applications-service store. Net: writes landed in the applications-service; the read came from the host backend's local table. Two stores → self-registered apps never appear in the shell → FederatedAppLoader errors App 'picker' not found or not activated.

Fix

backend/src/routes/appRegistry.ts: GET /apps now delegates to the proxy by default (return next()), so the read comes from the same store writes target. The local adapter becomes an opt-in CI / no-applications-service fallback, enabled with APP_REGISTRY_LOCAL_ADAPTER=1.

Why an explicit flag and not APPLICATIONS_SERVICE_URL: the issue suggested keying on APPLICATIONS_SERVICE_URL, but deploy/helm/fuzefront/templates/backend.yaml does not set that env — the proxy defaults it to http://fuzefront-applications:3003. So keying on it would leave process.env.APPLICATIONS_SERVICE_URL undefined in prod and the adapter would keep shadowing the proxy — the bug would survive. Inverting the default (delegate unless explicitly told to use the local table) is correct in prod with no env change, and the issue explicitly allows the flag form.

  • docker-compose.yml + docker-compose.e2e.yml: set APP_REGISTRY_LOCAL_ADAPTER=1 on the backend — neither stack runs an applications-service, so they keep serving reads from the local table (criterion 5).

Tests

backend/tests/app-registry-delegation.test.ts (pure unit, axios + db + auth mocked):

  • flag unsetGET /apps forwards to the applications-service (returns the proxy's picker, not the local table; token forwarded verbatim to /api/v1/app-registry/apps?status=activated).
  • flag set → served from the local apps table, proxy never called.

Acceptance criteria

  1. ✅ With the applications-service reachable (prod default, flag unset), GET /api/v1/app-registry/apps returns the applications-service contents — covered by the unit test and the inverted default.
  2. / 3. Self-registered MFE (picker) appears and mounts at /app/picker — runtime outcomes that this read-path fix enables; verifiable in prod after deploy.
  3. ✅ Unit test asserts the adapter delegates to the proxy by default. Note: the full self-registration e2e (init-container → applications-service → shell mount) is not added here — the e2e stack (docker-compose.e2e.yml) contains no applications-service and no registration init-container, so there's nothing to register against. Standing that up is a separate e2e-infra change; flagged rather than faked.
  4. ✅ CI / local (no applications-service) still served by the local adapter via the flag.

Cross-repo

Originator: FuzePicker (Jira FPK-7, epic FPK-6). FuzePicker's half is already merged (izzywdev/FuzePicker#46). After this merges and releases, picker and other self-registered MFEs render in the portal.

🤖 Generated with Claude Code

…e proxy (#533)

The host backend's local-DB adapter answered GET /apps unconditionally,
shadowing the proxy so the shell read a different store than writes land
in — self-registered MFEs (e.g. picker) were active in the applications-
service but absent from the shell. Delegate by default; keep the local
adapter as an opt-in CI/no-service fallback (APP_REGISTRY_LOCAL_ADAPTER).
@github-actions
github-actions Bot enabled auto-merge (squash) August 4, 2026 08:35
Comment thread backend/src/routes/appRegistry.ts Fixed
@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Automated code review (gate-code-review)

Credit balance is too low

Report-only — this check never blocks merge.

@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Automated code review (gate-code-review)

Credit balance is too low

Report-only — this check never blocks merge.

@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Automated code review (gate-code-review)

Credit balance is too low

Report-only — this check never blocks merge.

@izzywdev
izzywdev merged commit 615a339 into master Aug 4, 2026
57 checks passed
@izzywdev
izzywdev deleted the claude/app-registry-read-write-split-533 branch August 4, 2026 08:55
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.

app-registry read/write store split: self-registered MFEs (picker) never appear in the shell

2 participants