Policy Governance & Least Privilege
Audience: Security Guild, Policy Guild, Authority Core, auditors. Scope: Scopes, RBAC, approval controls, tenancy, auditing, and compliance requirements for Policy Engine v2.
1 · Governance Principles
- Least privilege by scope – API clients receive only the
policy:*scopes required for their role;effective:writereserved for service identity. - Immutable history – All policy changes, approvals, runs, and suppressions produce audit artefacts retrievable offline.
- Separation of duties – Authors cannot approve their own submissions; approvers require distinct scope and should not have deployment rights.
- Deterministic verification – Simulations, determinism checks, and incident replay bundles provide reproducible evidence for auditors.
- Tenant isolation – Policies, runs, and findings scoped to tenants; cross-tenant access requires explicit admin scopes and is logged.
- Offline parity – Air-gapped sites follow the same governance workflow with sealed-mode safeguards and signed bundles.
2 · Authority Scopes & Role Mapping
The canonical scope catalogue is StellaOpsScopes in src/Authority/StellaOps.Authority/StellaOps.Auth.Abstractions/StellaOpsScopes.cs. The Policy scopes below are real constants; the Enforced column records where the scope actually gates an endpoint today (verified against src/Policy/** route registrations). Scopes marked advertised only are issued and recognised by the Policy Gateway resource server but do not yet gate a server-side route handler — treat them as roadmap surface.
| Scope | Description | Enforced (verified in src/Policy) | Recommended role |
|---|---|---|---|
policy:read | View policies, packs, runs, conflicts, findings, attestation reports. | Yes — read routes across Policy Engine + Gateway. | Readers, auditors. |
policy:write | Create policy drafts; write attestation-report content. | Yes — AttestationReportEndpoints. | role/policy-author. |
policy:edit | Edit policy configs, pack bundles, violations, conflicts; backwards-compat fallback for effective:write on materialisation routes. | Yes. | role/policy-author. |
policy:author | Author Policy Studio workspaces, risk profiles, gates, exceptions. | Yes — Gateway GovernanceEndpoints, GatesEndpoints, ExceptionEndpoints. | role/policy-author. |
policy:simulate | Run simulations, coverage runs, batch evaluations, shadow toggles. | Yes — ConsoleSimulationEndpoint, OverlaySimulationEndpoint, Gateway PolicySimulationEndpoints. | Authors, reviewers, CI. |
policy:review | Reserved for review / request-changes workflow. | No — advertised in RequiredScopes and CLI stella policy review exists, but no server route gates on it. | role/policy-reviewer. |
policy:submit | Reserved for submit-for-review workflow. | No — CLI stella policy submit exists; no server route gates on it. | Authors. |
policy:approve | Approve / override the promotion gate. | Partial — gates only the promotion-gate override route (audited as gate bypass). | role/policy-approver. |
policy:operate | Manage exception lifecycle and budget operations. | Yes — Gateway ExceptionEndpoints, BudgetEndpoints. | role/policy-operator, automation bots. |
policy:audit | Access governance audit events and gate audit history. | Yes — Gateway GovernanceEndpoints audit routes, GatesEndpoints. | role/policy-auditor, compliance teams. |
policy:run | Trigger runs, deltas, gate evaluation, score gates. | Yes — Gateway DeltasEndpoints, GateEndpoints, ScoreGateEndpoints. | Operators, automation bots. |
policy:activate | Activate / deprecate risk profiles and policy revisions. | Yes — Gateway GovernanceEndpoints activate/deprecate routes. | Runtime operators / release managers. |
policy:publish | Reserved: publish approved version with attested artefacts. | No server route gates on it; CLI stella policy publish exists. | Release managers. |
policy:promote | Reserved: promote attestations between environments. | No server route gates on it; CLI stella policy promote exists. | Release managers. |
findings:read | View effective findings / advisory source projections. | Yes — Gateway AdvisorySourceEndpoints and effective-finding read routes. | Analysts, auditors, CLI. |
findings:write | Append Findings ledger entries via public fixture/import APIs. | Lives in the Findings module, not enforced inside src/Policy. | Service / import tooling. |
effective:write | Service only (EffectivePolicyEndpoints) — materialise effective findings; policy:edit accepted as a temporary backwards-compat fallback. | Yes. | Policy Engine service principal. |
Naming note: scope values are colon-form (
policy:read,effective:write); ASP.NET policies are built viaRequireStellaOpsScopes(...). Role names such asrole/policy-authorare illustrative RBAC labels, not Authority-defined objects. The Console role editor draws fromauthority.permissions(seeded byS002_seed_full_scope_permissions.sql), which is not consulted at token issuance — issuance filters requested scopes againstauthority.clients.allowed_scopes.
effective:writeservice-identity guard (verified): Authority rejectseffective:writein the client-credentials grant unless the client document carries theserviceIdentityproperty set topolicy-engine(ClientCredentialsHandlers.cslines 1157–1164; constantStellaOpsServiceIdentities.PolicyEngine). The rejection isunauthorized_client: “Scope ‘effective:write’ is reserved for the Policy Engine service identity.” See Authority scopes for the full scope catalogue.
3 · Workflow Controls
Implementation note: the strongest, code-verified governance controls today live in the exception approval workflow, not a generic policy-submission pipeline.
ExceptionApprovalRule(tablepolicy.exception_approval_rules) carries per-gate-level minimum-approver counts, required approver roles, maximum TTL days, a self-approval flag, and evidence / compensating-control requirements;ApprovalWorkflowServiceandExceptionServiceenforce them (e.g.SelfApprovalNotAllowed). The bullets below describe the intended end-to-end policy governance flow; treat items not tied to a concrete service/route as roadmap.
- Submit gate (roadmap): the intent is that CLI/UI require fresh lint + simulation artefacts before submission.
stella policy submitexists as a CLI verb, but no server route enforces apolicy:submitscope or a freshness window today. - Review quorum (exceptions: implemented; policies: roadmap): for exceptions, per-tenant rules enforce minimum approver counts and required approver roles. A general policy-revision review quorum is not yet enforced server-side (
policy:reviewis advertised but ungated). - Approval guard: for exceptions, separation-of-duty is enforced — the approver must differ from the requester (self-approval rejected; configurable via
AllowSelfApproval, default-deny in prod). For policy revisions,policy:approvecurrently gates only the promotion-gate override route. - Activation guard: activation/deprecation routes are gated by
policy:activate(GatewayGovernanceEndpoints). The specific “refuse activation when latest full run is not success / backlog aged beyond SLA” rule is not a verified gate — confirm against the activation handler before relying on it. - Rollback policy:
stella policy rollbackexists as a CLI verb. The literalpolicy.rollbackaudit-event name is unverified; canonical audit actions live underAuditActions.Policy.*.
4 · Tenancy & Data Access
- Policies stored per tenant;
tenant-globalused for shared baselines. - Policy Engine resolves tenant from the
X-StellaOps-TenantIdrequest header viaTenantContextMiddleware(TenantContextConstants.TenantHeader,src/Policy/StellaOps.Policy.Engine/Tenancy/). WhenRequireTenantHeaderis enabled (default), a missing header is rejected with error codePOLICY_TENANT_HEADER_REQUIRED; otherwise the request falls back to the default tenant. - NOT IMPLEMENTED: there is no
policy:tenant-adminscope. It does not appear inStellaOpsScopesand no Policy route gates on it. Cross-tenant administration is governed by the Authority tenant-management scopes (authority:tenants.read/authority:tenants.write), not by a Policy-module scope. RawX-Tenant-Id/X-StellaOps-TenantIdheaders are stripped at ingress for normal callers, so a token cannot self-elevate to another tenant. - Effective findings rows include a
tenantcolumn and unique indexes preventing cross-tenant writes. - CLI/Console display tenant context prominently; switching tenant triggers warnings when active policy differs.
- Offline bundles encode tenant metadata; import commands validate compatibility before applying.
5 · Audit & Evidence
- Storage (PostgreSQL,
policy.*schema — not MongoDB collections): the Policy persistence library (src/Policy/__Libraries/StellaOps.Policy.Persistence/Migrations/) owns tables includingpolicy.packs,policy.pack_versions,policy.rules,policy.risk_profiles/policy.risk_profile_history,policy.evaluation_runs,policy.explanations,policy.violation_events,policy.conflicts,policy.exceptions(+policy.exception_events,policy.exception_approval_requests,policy.exception_approval_audit),policy.budget_ledger,policy.ledger_exports, andpolicy.audit. Policy run jobs live in the Scheduler schema (scheduler.policy_run_jobs); effective findings are materialised into the Findings module store. The earlierpolicies/policy_reviews/policy_history/policy_runs/policy_run_eventscollection names predate the PostgreSQL migration and no longer exist. - Audit events: governance/audit events are emitted through the unified audit-emission pipeline (
StellaOps.Audit.Emission,AuditActions.Policy.*) and surfaced via Timeline’s unified audit store (/api/v1/audit/events?modules=policy). The standalone Gateway governance audit routes are deprecated in favour of that successor (Sunset 2027-10-19). The previously listed literal event names (policy.submitted,policy.review.requested,policy.approved, …) are not the canonicalAuditActions.Policy.*identifiers — verify exact action names againstsrc/__Libraries/StellaOps.Audit.Emission/AuditActions.csbefore relying on them. - Explain traces: stored for findings via
policy.explanations; available via CLI/UI for auditors (requiresfindings:read). - Offline evidence: there is no
stella policy bundle exportcommand. Audit/evidence bundling is produced bystella audit ...(which can include a policy snapshot) and by the Policy DSL signing surface (stella policy sign/stella policy verify-signature). Replay and gate-bypass audit rows are persisted (migrations003_gate_decisions_history.sql,004_replay_audit.sql). - Retention: configurable per compliance requirements. The “default 365 days / incident mode 30 days minimum” figures are guidance only — they are not pinned to a verified Policy retention config key; confirm against the deployed retention configuration.
6 · Secrets & Configuration Hygiene
- Policy Engine configuration loaded from environment/secret stores; no secrets in repo.
- CLI auth state is held in the CLI profile/config (
StellaOps.Cli/Configuration/CliProfile.cs); store credentials via the OS secret store rather than in plaintext config. Correction:stella profilemanages risk profiles (stella profile list/show/...), not CLI authentication tokens, and exposes noset --secretflag — the previous reference was inaccurate. - UI/CLI logs redact tokens, reviewer emails, and attachments.
- Rotating tokens/keys: follow
authority-scopes.mdfor the scope catalogue and rotation guidance. Policy scopes are advertised through Authority’s standard OpenID discovery / scope metadata. - There is no Policy scope that “disables self-service simulation.” Incident-time throttling of simulation is an operational control (rate limits / feature flags), not a
policy:operatecapability — do not rely on a scope toggle here.
7 · Incident Response
- Trigger incident mode for determinism violations, backlog surges, or suspected policy abuse.
- Capture replay evidence for affected runs. NOT IMPLEMENTED as written: there is no
stella policy run replaycommand. Deterministic re-execution is exposed via the top-levelstella scan replayverb (replay a scan with explicit hashes), and run history is available viastella policy history; replay/gate-decision audit rows are persisted by Policy migrations003/004. - Coordinate with Observability dashboards (see Policy telemetry guide) to monitor queue depth and failures.
- After resolution, document remediation in Lifecycle guide (§8) and attach to approval history.
8 · Offline / Air-Gapped Governance
- Same Policy scopes apply; tokens issued by the local Authority. Air-gap operations use dedicated scopes —
airgap:seal(seal/unseal),airgap:import(offline bundle import), andairgap:status:read— enforced by Policy EngineAirGapNotificationEndpoints(verified). - Approvers must use offline UI/CLI to sign submissions; attachments stored locally.
- Bundle import/export must be signed. CLI warns if signatures are missing.
- Sealed-mode banner reminds operators to refresh bundles when staleness thresholds are exceeded.
- Offline audits rely on evidence bundles and the local PostgreSQL
policy.*snapshot (run jobs inscheduler.policy_run_jobs); there is nopolicy_runscollection.
9 · Compliance Checklist
- [ ] Scope mapping reviewed: Authority issuer config updated; RBAC matrix stored with change request.
- [ ] Separation enforced: Automated checks block self-approval; review quorum satisfied.
- [ ] Activation guard documented: Operators trained on run health checks before promoting.
- [ ] Audit exports tested: Evidence bundles verified (hash/signature) and stored per compliance policy.
- [ ] Incident drills rehearsed: Replay/rollback procedures executed and logged.
- [ ] Offline parity confirmed: Air-gapped site executes submit/approve flow with sealed-mode guidance.
- [ ] Documentation cross-links: References to lifecycle, runs, observability, CLI, and API docs validated.
Last updated: 2025-10-26 (Sprint 20). Reconciled against src/Policy and src/Authority (scope catalogue StellaOpsScopes.cs): scope table rebuilt with verified enforcement column; policy:tenant-admin marked not implemented; MongoDB-era “collections” replaced with the PostgreSQL policy.* schema; non-existent CLI commands (stella policy bundle export, stella policy run replay, stella profile set --secret) corrected.
