-
Notifications
You must be signed in to change notification settings - Fork 0
docs(adr): record ecosystem admin-web architecture (Keyverse SSO + Keyvault) #1675
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
seonghobae
merged 5 commits into
main
from
docs/ecosystem-admin-web-sso-keyvault-adr-20260902
Sep 3, 2026
Merged
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
69884ac
docs(adr): record ecosystem admin-web architecture (Keyverse SSO + Ke…
seonghobae d8d8cbd
docs(adr-0021): correct stale claim that contextual-orchestrator#1010…
seonghobae 1124797
Merge remote-tracking branch 'origin/main' into docs/ecosystem-admin-…
seonghobae 297eedf
fix(adr): renumber ADR-0021 to ADR-0026 to resolve a numbering collision
seonghobae 97a70a8
Merge branch 'main' into docs/ecosystem-admin-web-sso-keyvault-adr-20…
seonghobae File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,166 @@ | ||
| # ADR-0026: Ecosystem admin-web architecture — Keyverse SSO and Keyvault | ||
|
|
||
| - **Status:** Accepted | ||
| - **Date:** 2026-09-02 | ||
| - **Scope:** cross-repository admin-web architecture for `noema`, `contextual-orchestrator`, and `keyverse` | ||
|
|
||
| ## Context | ||
|
|
||
| The owner asked for admin web UIs across three repositories | ||
| (`noema`, `contextual-orchestrator`, `keyverse`) and for mutual | ||
| integration so `keyverse` — currently a Keycloak-fronting central Identity | ||
| Provider — can also be used as a Keyvault (secrets/credential management, | ||
| analogous to Azure Key Vault or HashiCorp Vault), later expanded by the | ||
| owner to two further Keyverse capabilities: service-to-service ABAC/RBAC, | ||
| and a "login credential store" for service-account/machine credentials. | ||
|
|
||
| Direct repository research (cloned fresh, not assumed) found: | ||
|
|
||
| - **`contextual-orchestrator`** already runs a real, serving `/admin` | ||
| operator console (`admin.py`, inline stdlib HTML/JS, eight Figma-grounded | ||
| screens) with no per-model LLM timeout control — the exact gap | ||
| `docs/product-goal-directive.md` §8 already names. An `admin_ui/` | ||
| React+Storybook scaffold exists but is confirmed (by direct inspection, | ||
| matching that repo's own planning ADR 0036, superseded) to be the | ||
| unmodified Vite demo output — no admin-web work in flight there. This | ||
| was the readiest of the three repos: it already had a serving console, | ||
| an established KV/audit pattern (`credentials.py`, `model_group` | ||
| family), and an explicit product requirement to build against. | ||
| - **`keyverse`** had no encrypted secrets store (`kv_store.py`'s | ||
| `idp_config_entries` is its own internal, unencrypted config — never a | ||
| generic secrets product surface) and no frontend of any kind. PR #103 | ||
| (open, Draft) already implements most of the requested service | ||
| ABAC/RBAC capability (`authorization_plane.py`, `org_authorization.py`, | ||
| ADRs 0010–0012) but is not currently mergeable. | ||
|
Comment on lines
+31
to
+34
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| - **`noema`** is a Cloudflare Worker OIDC/credential-exchange broker with | ||
| only `/health`, `/ready`, `/exchange` and Durable-Object-only internal | ||
| state — no admin-readable HTTP surface exists to build a console on top | ||
| of today. The least ready of the three. | ||
|
|
||
| Per this repo's own scoping guidance for genuinely multi-week product | ||
| work, the correct first iteration is the smallest real, honestly-scoped | ||
| slice per repo — not three parallel half-built admin webs. | ||
|
|
||
| ## Decision | ||
|
|
||
| 1. **Keyverse is the shared SSO provider for every admin web in this | ||
| ecosystem.** It is already the org's central IdP; admins authenticate | ||
| to each product's admin console via Keyverse OIDC rather than a | ||
| per-repo local admin credential. This is itself the "상호 연계" | ||
| (mutual integration) the owner asked for, independent of the Keyvault | ||
| question. **Design only in this iteration** — `contextual-orchestrator`'s | ||
| `/admin` still uses its existing shared-bearer-token session model | ||
| (`/admin/session`); wiring Keyverse OIDC in is the next concrete step | ||
| for that console, tracked as an explicit open item rather than | ||
| silently deferred. | ||
| 2. **Each repo's admin web stays a thin frontend over that repo's own | ||
| backend API**, not a shared cross-repo frontend package — there is no | ||
| second consumer of shared UI primitives yet (matching | ||
| `contextual-orchestrator`'s own ADR 0033 reasoning for why Storybook/ | ||
| component tooling stays deferred there specifically). | ||
| 3. **Keyverse's Keyvault is a bounded context separate from its IdP | ||
| identity/config modules**, sharing only the KV storage *pattern* | ||
| (Protocol + in-memory/SQLite backends) already proven in that repo, | ||
| not any shared table. `contextual-orchestrator`'s existing | ||
| `CredentialBackend` Protocol (pluggable backends, KV-not-env | ||
| discipline) is the natural adapter target for a future | ||
| `KeyverseCredentialBackend` — the motivating first consumer, not | ||
| implemented in this pass. Full reasoning: `keyverse` ADR-0014. | ||
| 4. **Service ABAC/RBAC is not rebuilt here.** Keycloak's built-in | ||
| Authorization Services (UMA 2.0) exist but are unconfigured in this | ||
| deployment and do not natively cover the hierarchical org-path | ||
| inheritance CWL's Orgmetra-owned org tree requires; PR #103 already | ||
| implements that hierarchy. Recommendation: reconcile and land PR #103 | ||
| rather than duplicate it. Full reasoning: `keyverse` ADR-0015. | ||
| 5. **"Login credential store" is Keyvault plus per-service | ||
| Anti-Corruption Layers, not a fourth Keyverse module.** Centralizing | ||
| secret *storage* in Keyverse while each consuming service keeps its | ||
| own credential-taxonomy knowledge (via its own Protocol adapter, e.g. | ||
| `contextual-orchestrator`'s `CredentialBackend`) avoids growing | ||
| Keyverse into a service that must change whenever any consumer's | ||
| credential schema changes. Full reasoning: `keyverse` ADR-0016. | ||
| 6. **The first implemented slice is `contextual-orchestrator`'s per-model | ||
| LLM timeout admin surface** (view/set/clear/restore, units, priority/ | ||
| inheritance, validation, audit history, API contract — the exact §8 | ||
| requirement), extending the existing `/admin` console in place per its | ||
| own ADR 0033/0042. `keyverse`'s Keyvault (write/read/delete/list APIs, | ||
| encryption at rest via Fernet, audit logging) is implemented alongside | ||
| it as the second slice, since it was independently ready and directly | ||
| answers the Keyvault half of the owner's request. `noema` gets no code | ||
| change this iteration — it has no admin-relevant state to expose yet; | ||
| the honest next step there is deciding what operational state (OIDC | ||
| exchange health/rate, App-token issuance evidence) is worth exposing | ||
| before building a console around it. | ||
|
|
||
| ## Consequences | ||
|
|
||
| - No repo gained a half-built parallel admin frontend; each shipped | ||
| either a real, tested slice or an explicit, evidenced "not yet, and | ||
| here is why" record. | ||
| - Cross-repo SSO and the Keyvault-as-credential-backend consolidation are | ||
| both real, next, concretely-scoped follow-ups — not vague future work — | ||
| recorded here and in the two repos' own ADRs so the next iteration does | ||
| not have to re-derive this research. | ||
| - `keyverse` PR #103 (service authorization) is now more clearly the | ||
| blocking dependency for capability #2 of the owner's three-capability | ||
| Keyverse request; this ADR does not change its status, only records | ||
| that a competing implementation was deliberately not built. | ||
|
|
||
| ## Rejected alternatives | ||
|
|
||
| - **Build out `admin_ui/` (React+Storybook) for `contextual-orchestrator` | ||
| instead of extending `admin.py`.** Rejected: contradicts that repo's own | ||
| operative ADR 0033, and no revisit trigger from that ADR is met by this | ||
| work. | ||
| - **Build a from-scratch policy engine for Keyverse service ABAC/RBAC.** | ||
| Rejected: PR #103 already implements the actual (hierarchical, | ||
| org-path-aware) requirement; a second implementation would duplicate | ||
| ~2,000 lines of already-written, already-tested domain logic. | ||
| - **Centralize per-service credential semantics inside Keyverse.** | ||
| Rejected: violates this org's minimal-Shared-Kernel/Anti-Corruption-Layer | ||
| DDD convention and would couple Keyverse's deploy cadence to every | ||
| consuming service's credential taxonomy. | ||
| - **Force a code change into all three repos this iteration regardless of | ||
| readiness.** Rejected per this org's own genuinely-multi-week scoping | ||
| guidance: `noema` had no admin-relevant surface to build against yet, | ||
| and forcing one would have meant fabricating state or shipping a | ||
| console with nothing real to show. | ||
|
|
||
| ## Update — 2026-09-03: `contextual-orchestrator#1010` closed, not merged | ||
|
|
||
| Decision item 6 above named `contextual-orchestrator#1010` (per-model LLM | ||
| timeout admin surface) as this iteration's first implemented slice. That PR | ||
| was subsequently **closed unmerged by the repo owner the same day** (2026-09-02, | ||
| `closed_at` 05:10:46Z — after this ADR PR was opened at 03:40:12Z), on a | ||
| categorical objection independent of this ADR's design: "the current manual | ||
| timeout-setting semantics must not become production authority," plus four | ||
| distinct unresolved correctness findings in the PR's live-enforcement wiring | ||
| (local queue path ignores the override, passthrough/tool requests bypass it, | ||
| failed persistence can leave the live timeout mutated, and admin-refresh races | ||
| can misreport/stale audit state). A subsequent repair-policy recheck (recorded | ||
| on the PR and in `docs/product-technical-gap-baseline.md`) confirmed this | ||
| closure is valid under the org's repair-not-close policy's "explicit user | ||
| instruction" ground, and that the PR's delta is preserved (not orphaned) on | ||
| its own closed branch for selective future reuse once a research-/standard-backed | ||
| timeout allocator exists to host it — not revived as-is. | ||
|
|
||
| **This ADR's own architecture decisions (1–5) are unaffected** — they concern | ||
| the SSO/Keyvault/ABAC-RBAC/credential-store shape, not the timeout-surface | ||
| implementation. Only decision item 6's specific claim that the timeout slice | ||
| was "implemented" is now stale. `keyverse#129` (Keyvault, this iteration's | ||
| second slice) is unaffected by this and remains open. Left as an update rather | ||
| than rewriting the original decision record, so the historical reasoning | ||
| trail (what was true when each decision was made) stays intact. | ||
|
|
||
| ## References | ||
|
|
||
| - `contextual-orchestrator` planning ADR 0033 (admin console UI tooling | ||
| boundary), 0036 (superseded React/Storybook proposal), 0042 (per-model | ||
| timeout admin surface — this iteration's `contextual-orchestrator` | ||
| slice, subsequently closed unmerged; see Update above). | ||
| - `keyverse` ADR-0014 (Keyvault bounded context), ADR-0015 (service | ||
| authorization plane), ADR-0016 (login credential store). | ||
| - `docs/product-technical-gap-baseline.md`, 2026-09-02 entry (repair-policy | ||
| recheck of `contextual-orchestrator#1010`'s closure). | ||
| - `docs/product-goal-directive.md` §8 (LLM/orchestration; the per-model | ||
| timeout admin requirement this ADR's first slice attempted to close). | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🔍 Keyverse admin direction remains contradictory
The plan includes a Keyverse admin web, while the master context permits configuration-as-code and Admin REST only. Reconcile these durable decisions.
Was this helpful? React with 👍 or 👎 to provide feedback.