Skip to content

feat(console): one console, many services — the cross-service registry#81

Merged
omercelikdev merged 2 commits into
mainfrom
feat/u4-service-registry
Jul 27, 2026
Merged

feat(console): one console, many services — the cross-service registry#81
omercelikdev merged 2 commits into
mainfrom
feat/u4-service-registry

Conversation

@omercelikdev

Copy link
Copy Markdown
Owner

U4 slice 1.

Within one app there is nothing to configure — fleets are store-discovered and the app's admin surface speaks for all of them. Across services there is nothing to discover: a payments service cannot know a claims service exists. So the registry is config, read from console.config.json next to the console.

  • Adding a service is a config change, never a rebuild — the dist is the same for every adopter.
  • ?base= stays the dev override and the way to point the console at a service that did not serve it.
  • No file at all means one same-origin service, which is normal, not a fault (no warning).
  • A registry that cannot be read is announced. An operator who configured four services and quietly sees one is looking at the wrong console — exactly when they are hunting an outage.

Switching service re-discovers: each service gets its own console instance keyed by name, so a payments panel can never be drawn under a claims heading because the shell reused a component.

Proof

The smoke already runs three real apps; it now writes a registry naming them and Playwright switches between them:

service what the console must say
open the panels, discovered
auth-floored every section NAMED as forbidden, with the server's reason
tenant-scoped "composed here but refused this request", with the server's reason

…and back to open, freshly discovered. 16/16 green; console unit 115 (14 new).

The registry file is per-deployment config, so the smoke writes its own and .gitignore keeps it out of the tree.

🤖 Generated with Claude Code

U4 slice 1. Within one app there is nothing to configure: fleets are store-discovered and
the app's admin surface speaks for all of them. ACROSS services there is nothing to
discover — a payments service cannot know a claims service exists — so the registry is
config, read from `console.config.json` next to the console. Adding a service is a config
change, never a rebuild; `?base=` stays the dev override; no file at all means one
same-origin service, which is normal rather than a fault.

Switching service RE-DISCOVERS: each service gets its own console instance keyed by name,
so a payments panel can never be drawn under a claims heading because the shell reused a
component.

A registry that cannot be read is announced, not swallowed. An operator who configured
four services and quietly sees one is looking at the wrong console — which is exactly when
they are trying to find an outage.

Proof: the smoke writes a registry naming the THREE real apps it already runs (open,
auth-floored, tenant-scoped) and Playwright switches between them — each refusing in its
own way, each re-discovered on arrival. 16/16 green; console unit 115.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@omercelikdev

Copy link
Copy Markdown
Owner Author

Review agent v1 — 1 finding(s). The human decides; hard-stop labels need explicit resolution.

  • R1 (high) ui/console/src/registry.ts:55 — A partially malformed registry (some entries missing/blank name) is silently filtered down to fewer services with no warning, contradicting the PR's own stated invariant.
    • evidence: PR description / RFC: 'an operator who configured four services and quietly sees one is looking at the wrong console — exactly when they are hunting an outage.' The code only sets problem when ALL entries fail (services.length === 0, line 62); a mix of valid + invalid entries drops the bad ones silently (line 60) with no banner. registry.test.ts only exercises the all-invalid case, not partial drop. · action: Report a problem (or list which entries were dropped) whenever any registry entry is discarded for lacking a usable name, not only when none remain — and add a test for the partial-drop case.

Calibration: mark each finding accepted/dismissed in a reply — dismiss rate >40%/class revises that class (strategy §5).

The invariant I wrote in the same PR — an operator who configured four services must not
quietly see fewer — held only when EVERY entry was unusable. A registry with one bad entry
among good ones dropped it silently: the console still works, still looks right, and is
missing a service. That is the dangerous shape, not the empty one.

Nameless entries are now counted and named, and the banner distinguishes the two cases:
fell back to this service only, versus incomplete.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@omercelikdev

Copy link
Copy Markdown
Owner Author

R1 accepted — and it caught my own stated invariant failing: the report fired only when every entry was unusable. A registry with one bad entry among good ones dropped it silently, which is the dangerous shape (the console still works and still looks right). Nameless entries are now counted and named, and the banner distinguishes "fell back to this service only" from "incomplete — missing a service you configured". Three new tests, including the singular/plural count.

@omercelikdev
omercelikdev merged commit 8366a00 into main Jul 27, 2026
3 checks passed
@omercelikdev
omercelikdev deleted the feat/u4-service-registry branch July 27, 2026 11:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant