Skip to content

Control Plane — Security

Target

This page describes intended behaviour or structure. No implementation is claimed unless a section is explicitly marked Current implementation or Evidence.

Identity

  • Humans authenticate at the Authorization Server (OpenIddict, canonical ADR-0101) and reach the Control Plane with a bearer token through GW-01 or, from the Studio, a delegated token through GW-03. The Control Plane validates signature, audience, expiry and the tenant claim; it never issues tokens (ApiTokenService is external-canonical for that reason).
  • Services authenticate with workload identities: the runtime worker, the Studio BFF, partner agents (A2A) and generated products carry SPIFFE-style identities issued by the Authorization Server. A per-run token derived from the lease authorizes the runtime's calls for one attempt only.
  • Platform admin is a tenant-wide claim of the Identity Platform; the six project roles are memberships in ProjectService.

Tenancy

Canonical ADR-0100 modes are selected per installation (Multitenancy:DeploymentKind): SharedDb with NHibernate tenant filters by default, DatabasePerTenant and ResidencySilo for regulated tenants, DedicatedSingleTenant on-prem. Every table carries TenantId; every query runs under the request's trusted tenant; every event carries tenantId in the envelope. Platform-published assets belong to the platform tenant and are readable by all.

Roles and permissions (ADR-0015, D18)

Capability Requester Reviewer Asset maintainer Operator Workspace admin Platform admin Observer
Submit and cancel own runs yes yes yes yes
Decide approvals (not own runs) yes yes break-glass with reason
Submit and validate release candidates yes yes
Publish, deprecate, move aliases (after Reviewer approval) yes yes
Freeze and unfreeze environments yes yes yes
Memberships, delegations, source scope, close project yes yes
Budgets and thresholds (only tighter than platform) yes yes
Subscription and invoices yes read
Read everything in scope yes yes yes yes yes yes yes

Separation of duties: a Reviewer or Workspace admin never decides an approval of a run they requested; an Asset maintainer never approves their own release. Delegations are time-bound, same-or-lesser role, with a reason, revocable and audited. Project policy overrides only tighten platform policy.

Scopes

factory.projects.{read,write,admin,delegate}, factory.assets.{read,write,publish}, factory.runs.{read,submit,cancel}, factory.approvals.{read,decide}, factory.usage.{read,admin}, factory.commercial.{read,admin}, factory.agents.{discover,invoke}, factory.health.read, factory.meta.read. A route lists its scope on the APIs catalog; the gateway enforces presence, the module enforces the role behind it.

Action classes and approvals (D21)

Class Autonomous Needs approval
read, sandbox yes
shared-write, external, production, publication one approval per action bound to the exact proposal version
spend below the threshold above the threshold, bound to the estimate

The environment class raises the class of an action (Production environments make writes production actions); a Frozen environment refuses them altogether. Decisions are validated against the policy revision in force at decision time, and the proposal hash guarantees that what was approved is what runs.

Secrets and credentials

No Factory table stores a credential. Host secrets live in Key Vault and are mounted through workload identity; integration credentials are references to BC-16 connections and, later, short-lived credentials from the Secret Broker (BC-40). Manifest signing keys rotate yearly, store and transport credentials quarterly, payment-provider credentials half-yearly (see each service's security section).

Data classification and logging (D31)

Data Classification Handling
Projects, memberships, releases, runs, usage internal tenant-isolated, 1-year default retention, export in open formats
Subscription and invoices confidential commercial scope only, 7-year retention
Prompts, model responses, artifact content tenant data never logged by the Control Plane; referenced by hash and artifact id
Audit trail restricted append-only in BC-19, 7 years, redacted identifiers

Audit

Every command, decision, alias move, freeze, delegation and subscription change is published on the envelope and consumed by AuditService (BC-19). The audit entry names actor, scope, action, target version and reason; it is the evidence a tenant exports on request.

Threats the design answers

  • Prompt injection cannot change scope, release or policy: those are pinned from trusted context, not from model output.
  • A stale decision cannot authorize a changed proposal: requests are version-bound and become Stale.
  • A lost lease cannot commit a second outcome: fencing tokens reject the late holder.
  • A moved alias cannot alter an accepted run: aliases select at submission only.
  • A partner agent cannot exceed its tenant's membership: A2A tasks run with the caller's delegated scope and are budget-reserved like any run.