Parent: OoP
Blocked by: OoP-1
Description
Give every shared service a network surface so the whole business tier (file-parser, simple-user-settings,
mini-chat, oagw) can go OoP. Two groups, by trust-coupling:
Embeds in each OoP pod (no REST endpoint needed):
- AuthN Resolver — stateless JWT validation (JWKS cache only), zero network latency.
Stays in the Platform Host pod (trust-coupled — SecurityContext::anonymous() over the in-process RG boundary):
- AuthZ Resolver and Tenant Resolver — AuthZ chains to TR→RG, and TR's
rg-tr-plugin reads RG's DB.
Embedding either in an OoP pod would require shared RG DB access — rejected. Exposed over REST instead.
Separate pods (no trust-coupling; see DESIGN § Platform Host Composition):
- Types Registry — seeded from link-time inventory inside each binary, so an OoP gear's GTS types are
absent from the Platform Host registry. OoP gears must register remotely at startup via the existing
POST /types-registry/v1/entities route (no new write path), and post_init graph validation must work
across the distributed set. No DB; heartbeat re-registration handles pod restarts.
- CredStore — stateless, plugin-based secret lookups (no DB). Runs as a separate pod with REST endpoint.
Needed by oagw for upstream auth. Alternative: embed CredStore directly in OoP pods (like AuthN Resolver)
to avoid secrets in transit. Feasible because it is stateless; depends only on Types Registry for plugin discovery.
Without this phase, only gears with zero shared-service dependencies (e.g., file-parser) can go OoP.
With it, mini-chat, OAGW, and simple-user-settings become OoP-eligible.
The SecurityContext::anonymous() used internally by AuthZ→TR→RG stays within the Platform Host process
and is safe — it never crosses a network boundary.
Effort: Medium (Large only if the codegen from PR #4084 is unavailable and the four Rest*Clients must be hand-written; types-registry REST already exists. Only depends on OoP-1; can run in parallel with OoP-4–6)
Codegen note (PR #4084). The four Rest*Clients (8.2 / 8.4 / 8.6 / 8.7) can be generated by #4084's #[toolkit::rest_contract] once the existing SDK traits (AuthZResolverClient, TenantResolverClient, TypesRegistryClient, CredStoreClientV1) are annotated with per-method HTTP attributes — mechanical, but required. Hand-writing them is the fallback if the macro is unavailable. Note types-registry already exposes REST routes (register/list/get), so 8.5 is largely covered.
Design: DESIGN.md § Platform Host Composition
Tasks
AuthZ REST endpoint:
Tenant Resolver REST endpoint:
Types Registry REST:
CredStore REST:
account-management platform-plane migration:
Shared:
Acceptance Criteria
- OoP gear resolves
AuthZResolverClient, TenantResolverClient, TypesRegistryClient, and CredStoreClientV1 from ClientHub, calls them over REST, gets valid responses
PolicyEnforcer works identically whether AuthZ is in-process or REST-backed
- An OoP gear's GTS types register with the central Types Registry over REST and are visible to other gears
- oagw as OoP pod resolves tenant hierarchy, enforces authorization, and retrieves secrets via REST
- mini-chat / simple-user-settings as OoP pods enforce authorization via the Platform Host AuthZ REST endpoint
Parent: OoP
Blocked by: OoP-1
Description
Give every shared service a network surface so the whole business tier (file-parser, simple-user-settings,
mini-chat, oagw) can go OoP. Two groups, by trust-coupling:
Embeds in each OoP pod (no REST endpoint needed):
Stays in the Platform Host pod (trust-coupled —
SecurityContext::anonymous()over the in-process RG boundary):rg-tr-pluginreads RG's DB.Embedding either in an OoP pod would require shared RG DB access — rejected. Exposed over REST instead.
Separate pods (no trust-coupling; see DESIGN § Platform Host Composition):
absent from the Platform Host registry. OoP gears must register remotely at startup via the existing
POST /types-registry/v1/entitiesroute (no new write path), andpost_initgraph validation must workacross the distributed set. No DB; heartbeat re-registration handles pod restarts.
Needed by oagw for upstream auth. Alternative: embed CredStore directly in OoP pods (like AuthN Resolver)
to avoid secrets in transit. Feasible because it is stateless; depends only on Types Registry for plugin discovery.
Without this phase, only gears with zero shared-service dependencies (e.g.,
file-parser) can go OoP.With it, mini-chat, OAGW, and simple-user-settings become OoP-eligible.
The
SecurityContext::anonymous()used internally by AuthZ→TR→RG stays within the Platform Host processand is safe — it never crosses a network boundary.
Effort: Medium (Large only if the codegen from PR #4084 is unavailable and the four
Rest*Clients must be hand-written;types-registryREST already exists. Only depends on OoP-1; can run in parallel with OoP-4–6)Tasks
AuthZ REST endpoint:
AuthZResolverClient::evaluate()in the Platform Host:POST /authz-resolver/v1/evaluate— acceptsEvaluationRequest, returnsEvaluationResponsesecctx_middleware(OoP-1) — caller must present a valid JWTAuthZResolverClient(which chains to TR→RG in-process)RestAuthZResolverClient— REST client implementing theAuthZResolverClientSDK trait:attach_bearer_http(OoP-1) to propagate the caller's JWT on outbound callsClientHubsoPolicyEnforcerworks transparentlyTenant Resolver REST endpoint:
TenantResolverClientoperations in the Platform Host:TenantResolverClientsurface under/tenant-resolver/v1/...(e.g.GET /tenant-resolver/v1/root,GET /tenant-resolver/v1/hierarchy?tenant_id=...); the generated client covers all 6 trait methodssecctx_middleware(OoP-1)TenantResolverClientRestTenantResolverClient— REST client implementing theTenantResolverClientSDK trait:attach_bearer_http(OoP-1) to propagate the caller's JWTClientHubso OAGW and other consumers work transparentlyTypes Registry REST:
POST /types-registry/v1/entitiesregister, plus list/get) — no new write path:POST /types-registry/v1/entitiesat startuppost_initgraph validation works across the now-distributed set of registered types; add read/query endpoints only if a concrete gap is foundRestTypesRegistryClient(SDK trait), registered inClientHub; OoP bootstrap callsregisterat startup before serving.CredStore REST:
RestCredStoreClientV1registered inClientHub.account-management platform-plane migration:
for_gear_initpath (gears/system/account-management/.../domain/system_actor.rs) off the nil-tenantSecurityContextshim ontoPlatformSecurityContext(OoP-2). Tenant-boundam.systemflows (for_bootstrap/for_provisioning_reaper/for_retention_sweep/for_user_groups_cascade) stay on the tenant plane via S2S client-credentials — unchanged.Shared:
PolicyEnforcerparityTenantResolverClientparitypost_initvalidatesfor_gear_initglobal RG-type registration works underPlatformSecurityContext; tenant-bound flows unchangedAcceptance Criteria
AuthZResolverClient,TenantResolverClient,TypesRegistryClient, andCredStoreClientV1fromClientHub, calls them over REST, gets valid responsesPolicyEnforcerworks identically whether AuthZ is in-process or REST-backed