Assistant: codex Assistant-Model: gpt-6-astra Assistant-Session: 01a0e747-8f27-7242-8df8-8bc44f88c929
236 lines
16 KiB
Markdown
236 lines
16 KiB
Markdown
# Hub Core and extension access through NetKingdom
|
|
|
|
Status: reviewed source blueprint; owner/live acceptance pending, 2026-09-28. Owner: `hub-core`.
|
|
Execution record: [HUB-WP-0012](../workplans/HUB-WP-0012-netkingdom-platform-root-access.md).
|
|
Requested outcome: the person signing in as `platform-root` can access and
|
|
administer the whole platform, including Hub Core, its extensions, and Railiance.
|
|
Other human users are denied initially. Public exposure follows proven access
|
|
enforcement. Fine-grained delegation is a later phase of the same workplan.
|
|
|
|
The [access profile candidate](access-profile-v1.md) records the subsequent source
|
|
implementation and remaining integration gates. The table below is the original
|
|
pre-implementation baseline, not a claim that the new enforcement is deployed.
|
|
|
|
## Findings and evidence boundary
|
|
|
|
This is a source/configuration review plus read-only runtime observation, not
|
|
an authenticated platform-root acceptance test. No account, token, role,
|
|
policy, public listener, or production workload was changed.
|
|
|
|
| Boundary | Observed state on 2026-09-28 | Consequence |
|
|
| --- | --- | --- |
|
|
| Hub Core | `runtime/app.py` mounts `ports.py` without a global authorization dependency; native registration, messaging, events and generic projections lack a verified subject/tenant context | Enforce access in the service and SDK, not only at Ingress |
|
|
| Compatibility API | `runtime/compat.py::_protected` accepts a shared configured bearer or an imported consumer key; no resource/tenant decision follows | Replace broad bearer authority with authenticated principal plus action authorization |
|
|
| MCP | Separate runtime/transport and reusable host wrapper | Inventory every tool and carry caller identity to the same protected API; no server-wide root token |
|
|
| Inbox pilot | Snapshot GET reader uses the shared token and literal `state-hub` recipient | Keep private; caller migration remains HUB-WP-0011, not a completed retirement slice |
|
|
| Extension conformance | HUB-WP-0009 finished C2/C7/C9/C10; its explicit tenant-isolation gap has no implementation | This workplan owns the new security profile; 0.1 conformance is insufficient for exposure |
|
|
| Identity | Live issuer discovery at `https://kc.coulomb.social` advertises S256, authorization code and client credentials; KeyCape, Authelia, LLDAP and identity-provisioner Deployments Ready | Reuse the issuer; no second identity database or new IdP |
|
|
| User and tenant management | User Engine and Tenant Engine Deployments Ready; USER-WP-0030 and NK-WP-0038 finished | Reuse account lifecycle and tenant authority; readiness does not prove this root account's effective grants |
|
|
| Policy | Six service-specific flex-auth Deployments Ready; none for Hub Core | Register a protected system and owner-managed policy deployment; don't borrow another consumer's PDP/credentials |
|
|
| Hosting | Core Hub legacy/candidate/publisher Ready; revision 28 has Ingress off | Keep private until the new admission gate; the earlier public grant alone does not satisfy this request |
|
|
| Current external blockers | Public host presents Traefik default certificate; publisher accepts 113/123 with nine private-source errors and an identity-canon registry mismatch | Existing RAPPCOREHUB-WP-0002/0003 retain these operational obligations |
|
|
|
|
Source findings use the current checkout. Live hub image remains the September 5
|
|
pin, so later source conformance changes are not claimed deployed. The root
|
|
account's immutable subject, effective memberships, MFA and revocation behavior
|
|
still require an attended, non-secret acceptance receipt.
|
|
|
|
## Authority and request path
|
|
|
|
```mermaid
|
|
flowchart TD
|
|
Human[Human: platform-root] --> Login[KeyCape OIDC login]
|
|
Login --> Client[Hub browser session or CLI]
|
|
Users[User Engine: account and membership lifecycle] --> Facts[Verified account and tenant facts]
|
|
Tenants[Tenant Engine: tenant lifecycle and capability roles] --> Facts
|
|
Client --> Hub[Hub Core API: authenticate and enforce]
|
|
Workload[Named service or agent identity] --> Hub
|
|
Facts --> Policy[flex-auth: action and resource decision]
|
|
Hub --> Policy
|
|
Hub --> Extension[Extension API: authenticate and enforce]
|
|
Extension --> Policy
|
|
Extension --> Owner[Railiance or domain owner: execute and enforce]
|
|
Owner --> Audit[Durable audit evidence]
|
|
Hub --> Audit
|
|
```
|
|
|
|
KeyCape owns authentication and signed IAM claims. User Engine owns account,
|
|
application profile and membership lifecycle. Tenant Engine owns tenant state
|
|
and capability roles. NetKingdom owns the IAM profile and identity integration.
|
|
`flex-auth` owns decisions; the announced `access-engine` rename changes a repo
|
|
coordinate, not current runtime names or audiences (NK-WP-0039).
|
|
|
|
Hub Core and every extension enforce decisions locally. Domain services retain
|
|
their data, commands and approvals. Railiance retains infrastructure execution;
|
|
ops-warden retains SSH certificate issuance; approval-engine retains durable
|
|
approval lifecycle; OpenBao/platform owners retain credential custody. Hub Core
|
|
does not become a privileged Kubernetes or OpenBao proxy merely by hosting UI.
|
|
|
|
## M1: full platform-root access
|
|
|
|
Bind the existing platform-root account by verified `(issuer, subject)`, resolved
|
|
through its owning identity/account records. A username or email is only a
|
|
display/lookup hint, never the privilege check. Do not fabricate a subject UUID,
|
|
auto-promote the first login, or grant every `platform-operator` root access.
|
|
User Engine currently uses `platform-operator` for some administrative gates;
|
|
T02 must map the specific root account's entitlement into those existing policy
|
|
vocabularies rather than assume a universal `platform-root` role already exists.
|
|
|
|
M1 grants that principal all registered platform actions and resources through
|
|
each service's normal enforcement path, including Hub Core registry, messaging,
|
|
events, projections, work/repository operations via owners, extension surfaces,
|
|
tenant administration, and Railiance administration. Where full administration
|
|
requires crossing tenant boundaries, record an explicit platform-root grant
|
|
and audit both actor tenant and target tenant. Root remains `tenant:platform`;
|
|
it does not impersonate a tenant member. Tenant admins and ordinary users gain
|
|
no platform access in M1. Workloads retain only their individually registered
|
|
service/agent permissions and cannot inherit the human grant.
|
|
|
|
Use a versioned, owner-reviewed action/resource catalog and entitlement, not a
|
|
hardcoded middleware bypass. New actions require catalog/policy review before
|
|
they become routable. Fine-grained human roles are deferred, but signature
|
|
validation, deny-by-default, tenant attribution and audit are M1 requirements.
|
|
Full access does not waive existing confirmations, approval obligations,
|
|
single-writer controls, secret non-disclosure, or emergency custody rules.
|
|
|
|
The estate access matrix must enumerate every active platform service and
|
|
management surface from owner/Fabric inventories. Seed it with Hub Core,
|
|
ops-hub, repo-manager, activity-core, User/Tenant Engine, identity administration,
|
|
policy/approval/audit surfaces, Forgejo, OpenBao/secrets operations, and
|
|
Railiance Kubernetes, deployment/GitOps, SSH and observability. Each row names
|
|
owner, resource/realm, audience, enforcement point, grant, safe test, and receipt.
|
|
Existing native/SSH/attended paths may satisfy a row; a generic hub token may
|
|
not. M1 is not complete while any inventoried platform surface is inaccessible
|
|
or untested. Non-hub services need integration, not reclassification as hubs.
|
|
|
|
## Authentication and session contract
|
|
|
|
Use accepted [IAM Profile v0.3](../../net-kingdom/canon/standards/iam-profile_v0.3.md).
|
|
The browser uses Authorization Code + PKCE S256 through a confidential session
|
|
backend with exact registered redirects, state/nonce, Secure HttpOnly cookies,
|
|
CSRF protection and logout. Store tokens server-side, not browser local storage.
|
|
CLI/MCP clients use an issuer-supported flow and their own audience-bound
|
|
credentials; do not assume device flow or token exchange exists without proof.
|
|
The OAuth design follows [RFC 9700](https://www.rfc-editor.org/rfc/rfc9700.html).
|
|
|
|
The API validates access-token type, issuer, audience, allowed algorithm,
|
|
signature, key rotation, expiry/not-before and required IAM claims. ID tokens
|
|
are not API credentials. Missing/invalid authentication returns 401; verified
|
|
but disallowed access returns 403; unavailable authorization returns a bounded
|
|
503 without executing work. Resolve trusted resource/tenant facts on the server;
|
|
ignore user-supplied subject, role, tenant headers and purported verified flags.
|
|
|
|
Platform-root requires AAL2 or stronger per IAM v0.3 and NK-ADR-0016; an ordinary
|
|
SSO session does not establish that. Reuse the accepted enrollment/recovery
|
|
journeys and attest the privileged login. NK-WP-0042's per-request step-up and
|
|
IAM v0.4 are proposed, not available guarantees. M1 can use the existing
|
|
per-client privileged MFA path only after its usability/return journey is
|
|
accepted; otherwise remain private and record that blocker.
|
|
|
|
T02 fixes measurable token/session lifetimes, assurance freshness and maximum
|
|
grant-revocation delay. Proposed upper bound: five minutes for ordinary root
|
|
access; privileged mutations recheck current root entitlement and tenant state
|
|
at execution and fail closed when unavailable. Logout invalidates the local
|
|
session immediately; expired or revoked authority cannot survive refresh.
|
|
Use authoritative owner APIs for high-stakes tenant capability facts;
|
|
`tenant_roles` in a token is only a cache. Test user suspension, grant removal,
|
|
tenant suspension and issuer/policy outages, not just successful sign-in.
|
|
|
|
## Authorization, forwarding and extension contract
|
|
|
|
Every request carries server-established actor, calling workload, target
|
|
tenant, action, resource, assurance and correlation identity. The service
|
|
authenticates to flex-auth using an admitted workload identity separately from
|
|
the end user's identity. Caller TokenReview alone must not authorize arbitrary
|
|
claims asserted by that caller. Adopt the current fact-provenance and binding
|
|
contracts (FLEX-WP-0025, FLEX-WP-0017).
|
|
|
|
Verify the decision's request binding, action/resource/tenant, validity,
|
|
policy version, obligations and authenticated origin. Require a signed decision
|
|
and trusted rotating verification keys per FLEX-WP-0024, or an explicitly
|
|
reviewed equivalent authenticated channel. An unsigned development decision is
|
|
not sufficient for public M1. Signing code being finished does not prove a
|
|
production signing-key custody lane exists; owner delivery is a T03 gate.
|
|
Audit allow/deny/error with actor, caller, tenant, action/resource, policy and
|
|
decision IDs, correlation and outcome; never tokens or message bodies. Required
|
|
audit failure prevents privileged mutation; bounded durable buffering must be
|
|
specified rather than silently dropping evidence.
|
|
|
|
Expose one reusable enforcement/context seam for embedded routers, native
|
|
`/ports`, `/api/v2`, aliases, docs/catalogs, projection APIs, browser and MCP.
|
|
Only minimal liveness and the exact login/callback mechanics may be unauthenticated;
|
|
detailed readiness is internal. Test direct Service requests as well as Ingress.
|
|
Legacy keys get explicit private, bounded migration lanes with named owners;
|
|
they must not become a public bypass or be distributed to extensions.
|
|
|
|
An extension manifest declares protected-system identity, token audience,
|
|
action/resource namespaces, tenant behavior and required security-contract
|
|
version. Extensions validate their own audience and enforce their own policy;
|
|
Hub Core cannot forward a bearer to an unrelated audience. Use only a proven
|
|
issuer delegation/exchange mechanism, or a reviewed authenticated workload call
|
|
with integrity-bound end-user delegation. If neither exists, use a separate
|
|
client login and leave delegation unsupported. Never relay root's bearer as a
|
|
generic backend credential. Service-initiated events bind producer/address to
|
|
the authenticated workload; payload `sender` is not authority.
|
|
|
|
Version the security profile and extend conformance beyond HUB-WP-0009.
|
|
Cover list/filter/detail, exports, caches, pagination, broadcasts, aliases,
|
|
streaming/MCP and event replay; no cross-tenant existence/count leak. Classify
|
|
legacy unlabelled records explicitly as platform-owned or quarantine them;
|
|
never infer their tenant from the current viewer. Platform-root may administer
|
|
them through its explicit platform grant. Non-root multi-tenant admission waits
|
|
for Phase 2 data migration and isolation tests.
|
|
|
|
## Retirement integration and sequencing
|
|
|
|
| Existing owner record | Relationship to this work |
|
|
| --- | --- |
|
|
| HUB-WP-0004/0005, CORE-WP-0010 | Runtime selection/absorption already decided; implement here, retain Core Hub rollback privately; no new feature lane in Core Hub |
|
|
| HUB-WP-0009 | Existing contract checks stay finished; this work owns the missing identity/tenant conformance profile |
|
|
| HUB-WP-0011 | Reuse the new caller/context seam for T02; inbox freshness, retention, recipient/alias semantics and reader switch stay there |
|
|
| STATE-WP-0079 | Authentication does not close its 425-item disposition, single-writer, parity, metering or retirement gates; apply the security gate per slice |
|
|
| RMGR-WP-0001/0002/0003 | Git/file authority stays in Repo Manager; Hub Core views and invokes governed owner APIs |
|
|
| OPS-WP-0003; ACTIVITY-WP-0029 | Existing extension and event/schedule alignment finished; add security conformance/caller migration without reopening completed tasks |
|
|
| FIN-WP-0003; RAIL-FAB-WP-0028 | Fabric authority stays specialized; hosted Fabric is blocked independently; integrate the available owner surface and report missing runtime evidence |
|
|
| RAPPCOREHUB-WP-0002/0003/0004 | Packaging/exposure, publisher credential gate and completed private inbox pilot retain their owners |
|
|
| NK-WP-0038/0039/0042; USER-WP-0030; TEN-WP-0012 | Reuse delivered identity/admin behavior; respect pending coordinate, step-up and tenant conformance work rather than claim them complete |
|
|
|
|
Implement shared contracts and platform-root access privately first. Exercise
|
|
one extension (ops-hub), actual workload callers and Railiance owner paths, then
|
|
complete the platform access matrix. Gate each State Hub reader/writer move on
|
|
the same identity checks plus that slice's existing data/freshness gates.
|
|
Do not add permanent authentication/tenant authority to retiring State Hub.
|
|
|
|
Public enablement is a separate final gate under RAPPCOREHUB-WP-0002: authenticated
|
|
root success, ordinary-user/anonymous denial, direct-path denial, MFA, revocation,
|
|
policy failure, audit, all published route/tool coverage, current image pins,
|
|
TLS issuance and consumer tests, then explicit exposure approval. Fix release
|
|
configuration so routine upgrades preserve the approved exposure mode while
|
|
new installations default private. Do not expose the legacy rollback service.
|
|
Rollback retracts public access before restoring any image lacking enforcement;
|
|
it never restores an anonymously reachable older runtime. No full historical
|
|
Helm rollback that silently revives the old public configuration.
|
|
|
|
## Later phase retained in the same plan
|
|
|
|
After M1, define tenant-admin and ordinary-user grants, delegated agents,
|
|
per-extension/action permissions, recipient ACLs and tenant-scoped storage,
|
|
queries, caches and retention. Preserve the root entitlement as an explicit
|
|
policy grant. Phase 2 is open work, not a prerequisite for proving the coarse
|
|
root-only model, and must not be silently dropped when M1 closes.
|
|
|
|
## Source map
|
|
|
|
- `hub-core/hub_core/runtime/{app,ports,compat,config,inbox_projection}.py`,
|
|
`hub_core/mcp/server.py`, `docs/runtime.md`, `docs/conformance.md`.
|
|
- NetKingdom `docs/platform-identity-security-architecture.md`, accepted IAM
|
|
v0.3, `docs/adr/ADR-0016-mfa-user-preference-and-workload-step-up.md`.
|
|
- User Engine `wiki/ArchitectureBlueprint.md`, `docs/development.md`;
|
|
flex-auth `docs/iam-profile-consumption.md`, decision binding/signature and
|
|
inbound caller-auth contracts. The older consumption doc's v0.2 reference
|
|
does not supersede accepted additive v0.3.
|
|
- Retirement project `architecture/hub-extension-architecture_v0.1.md`,
|
|
`architecture/child-workplan-map_v0.1.md`, and owner workplans in the table.
|
|
Historical map statuses are not treated as current delivery evidence.
|
|
- Runtime checks: deployment readiness listing, issuer discovery, and
|
|
`rapp-core-hub/docs/evidence/loose-end-review-20260928.md`.
|