Some checks failed
		
		
	
	Docs CI / lint-and-preview (push) Has been cancelled
				
			- Added `SchedulerWorkerOptions` class to encapsulate configuration for the scheduler worker. - Introduced `PlannerBackgroundService` to manage the planner loop, fetching and processing planning runs. - Created `PlannerExecutionService` to handle the execution logic for planning runs, including impact targeting and run persistence. - Developed `PlannerExecutionResult` and `PlannerExecutionStatus` to standardize execution outcomes. - Implemented validation logic within `SchedulerWorkerOptions` to ensure proper configuration. - Added documentation for the planner loop and impact targeting features. - Established health check endpoints and authentication mechanisms for the Signals service. - Created unit tests for the Signals API to ensure proper functionality and response handling. - Configured options for authority integration and fallback authentication methods.
		
			
				
	
	
		
			204 lines
		
	
	
		
			9.6 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
			
		
		
	
	
			204 lines
		
	
	
		
			9.6 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
| # Authority Scopes & Tenancy — AOC Update
 | ||
| 
 | ||
| > **Audience:** Authority Core, platform security engineers, DevOps owners.  
 | ||
| > **Scope:** Scope taxonomy, tenancy enforcement, rollout guidance for the Aggregation-Only Contract (Sprint 19).
 | ||
| 
 | ||
| Authority issues short-lived tokens bound to tenants and scopes. Sprint 19 introduces new scopes to support the AOC guardrails in Concelier and Excititor. This document lists the canonical scope catalogue, describes tenancy propagation, and outlines operational safeguards.
 | ||
| 
 | ||
| ---
 | ||
| 
 | ||
| ## 1 · Scope catalogue (post AOC)
 | ||
| 
 | ||
| | Scope | Surface | Purpose | Notes |
 | ||
| |-------|---------|---------|-------|
 | ||
| | `advisory:ingest` | Concelier ingestion APIs | Append-only writes to `advisory_raw` collections. | Requires tenant claim; blocked for global clients. |
 | ||
| | `advisory:read` | `/aoc/verify`, Concelier dashboards, CLI | Read-only access to stored advisories and guard results. | Needed alongside `aoc:verify` for CLI/console verification. |
 | ||
| | `vex:ingest` | Excititor ingestion APIs | Append-only writes to `vex_raw`. | Mirrors `advisory:ingest`; tenant required. |
 | ||
| | `vex:read` | `/aoc/verify`, Excititor dashboards, CLI | Read-only access to stored VEX material. | Pair with `aoc:verify` for guard checks. |
 | ||
| | `aoc:verify` | CLI/CI pipelines, Console verification jobs | Execute Aggregation-Only Contract guard runs. | Always issued with tenant; read-only combined with `advisory:read`/`vex:read`. |
 | ||
| | `graph:write` | Cartographer pipeline | Enqueue graph build/overlay jobs. | Reserved for Cartographer service identity; tenant required. |
 | ||
| | `graph:read` | Graph API, Scheduler overlays, UI | Read graph projections/overlays. | Tenant required; granted to Cartographer, Graph API, Scheduler. |
 | ||
| | `graph:export` | Graph export endpoints | Stream GraphML/JSONL artefacts. | UI/gateway automation only; tenant required. |
 | ||
| | `graph:simulate` | Policy simulation overlays | Trigger what-if overlays on graphs. | Restricted to automation; tenant required. |
 | ||
| | `effective:write` | Policy Engine | Create/update `effective_finding_*` collections. | **Only** the Policy Engine service client may hold this scope; tenant required. |
 | ||
| | `findings:read` | Console, CLI, exports | Read derived findings materialised by Policy Engine. | Shared across tenants with RBAC; tenant claim still enforced. |
 | ||
| | `vuln:read` | Vuln Explorer API/UI | Read normalized vulnerability data. | Tenant required. |
 | ||
| | Existing scopes | (e.g., `policy:*`, `concelier.jobs.trigger`) | Unchanged. | Review `/docs/security/policy-governance.md` for policy-specific scopes. |
 | ||
| 
 | ||
| ### 1.1 Scope bundles (roles)
 | ||
| 
 | ||
| - **`role/concelier-ingest`** → `advisory:ingest`, `advisory:read`.
 | ||
| - **`role/excititor-ingest`** → `vex:ingest`, `vex:read`.
 | ||
| - **`role/aoc-operator`** → `aoc:verify`, `advisory:read`, `vex:read`.
 | ||
| - **`role/policy-engine`** → `effective:write`, `findings:read`.
 | ||
| - **`role/cartographer-service`** → `graph:write`, `graph:read`.
 | ||
| - **`role/graph-gateway`** → `graph:read`, `graph:export`, `graph:simulate`.
 | ||
| - **`role/console`** → `advisory:read`, `vex:read`, `aoc:verify`, `findings:read`, `vuln:read`.
 | ||
| 
 | ||
| Roles are declared per tenant in `authority.yaml`:
 | ||
| 
 | ||
| ```yaml
 | ||
| tenants:
 | ||
|   - name: default
 | ||
|     roles:
 | ||
|       concelier-ingest:
 | ||
|         scopes: [advisory:ingest, advisory:read]
 | ||
|       aoc-operator:
 | ||
|         scopes: [aoc:verify, advisory:read, vex:read]
 | ||
|       policy-engine:
 | ||
|         scopes: [effective:write, findings:read]
 | ||
| ```
 | ||
| 
 | ||
| ---
 | ||
| 
 | ||
| ## 2 · Tenancy enforcement
 | ||
| 
 | ||
| ### 2.1 Token claims
 | ||
| 
 | ||
| Tokens now include:
 | ||
| 
 | ||
| - `tenant` claim (string) — required for all ingestion and verification scopes.
 | ||
| - `service_identity` (optional) — e.g., `policy-engine`, `cartographer`. Required when requesting `effective:write` or `graph:write`.
 | ||
| - `delegation_allowed` (boolean) — defaults `false`. Prevents console tokens from delegating ingest scopes.
 | ||
| 
 | ||
| Authority rejects requests when:
 | ||
| 
 | ||
| - `tenant` is missing while requesting `advisory:ingest`, `advisory:read`, `vex:ingest`, `vex:read`, or `aoc:verify` scopes.
 | ||
| - `service_identity != policy-engine` but `effective:write` is present (`ERR_AOC_006` enforcement).
 | ||
| - `service_identity != cartographer` but `graph:write` is present (graph pipeline enforcement).
 | ||
| - Tokens attempt to combine `advisory:ingest` with `effective:write` (separation of duties).
 | ||
| 
 | ||
| ### 2.2 Propagation
 | ||
| 
 | ||
| - API Gateway forwards `tenant` claim as header (`X-Stella-Tenant`). Services refuse requests lacking the header.
 | ||
| - Concelier/Excititor stamp tenant into raw documents and structured logs.
 | ||
| - Policy Engine copies `tenant` from tokens into `effective_finding_*` collections.
 | ||
| 
 | ||
| ### 2.3 Cross-tenant scenarios
 | ||
| 
 | ||
| - Platform operators with `tenant:admin` can assume other tenants via `/authority/tenant/switch` if explicitly permitted.
 | ||
| - CLI commands accept `--tenant <id>` to override environment default; Authority logs tenant switch events (`authority.tenant.switch`).
 | ||
| - Console tenant picker uses delegated token exchange (`/token/exchange`) to obtain scoped tenant tokens without exposing raw credentials.
 | ||
| 
 | ||
| ---
 | ||
| 
 | ||
| ## 3 · Configuration changes
 | ||
| 
 | ||
| ### 3.1 Authority configuration (`authority.yaml`)
 | ||
| 
 | ||
| Add new scopes and optional claims transformations:
 | ||
| 
 | ||
| ```yaml
 | ||
| security:
 | ||
|   scopes:
 | ||
|     - name: advisory:ingest
 | ||
|       description: Concelier raw ingestion (append-only)
 | ||
|     - name: advisory:read
 | ||
|       description: Read Concelier advisories and guard verdicts
 | ||
|     - name: vex:ingest
 | ||
|       description: Excititor raw ingestion
 | ||
|     - name: vex:read
 | ||
|       description: Read Excititor VEX records
 | ||
|     - name: aoc:verify
 | ||
|       description: Run AOC verification
 | ||
|     - name: effective:write
 | ||
|       description: Policy Engine materialisation
 | ||
|     - name: findings:read
 | ||
|       description: Read derived findings
 | ||
|     - name: graph:write
 | ||
|       description: Cartographer build submissions
 | ||
|     - name: graph:read
 | ||
|       description: Read graph overlays
 | ||
|     - name: graph:export
 | ||
|       description: Export graph artefacts
 | ||
|     - name: graph:simulate
 | ||
|       description: Run graph what-if simulations
 | ||
|     - name: vuln:read
 | ||
|       description: Read Vuln Explorer data
 | ||
|   claimTransforms:
 | ||
|     - match: { scope: "effective:write" }
 | ||
|       require:
 | ||
|         serviceIdentity: policy-engine
 | ||
|     - match: { scope: "graph:write" }
 | ||
|       require:
 | ||
|         serviceIdentity: cartographer
 | ||
| ```
 | ||
| 
 | ||
| ### 3.2 Client registration
 | ||
| 
 | ||
| Update service clients:
 | ||
| 
 | ||
| - `Concelier.WebService` → request `advisory:ingest`, `advisory:read`.
 | ||
| - `Excititor.WebService` → request `vex:ingest`, `vex:read`.
 | ||
| - `Policy.Engine` → request `effective:write`, `findings:read`; set `properties.serviceIdentity=policy-engine`.
 | ||
| - `Cartographer.Service` → request `graph:write`, `graph:read`; set `properties.serviceIdentity=cartographer`.
 | ||
| - `Graph API Gateway` → request `graph:read`, `graph:export`, `graph:simulate`; tenant hint required.
 | ||
| - `Console` → request `advisory:read`, `vex:read`, `aoc:verify`, `findings:read`, `vuln:read` plus existing UI scopes.
 | ||
| - `CLI automation` → request `aoc:verify`, `advisory:read`, `vex:read` as needed.
 | ||
| 
 | ||
| Client definition snippet:
 | ||
| 
 | ||
| ```yaml
 | ||
| clients:
 | ||
|   - clientId: concelier-web
 | ||
|     grantTypes: [client_credentials]
 | ||
|     scopes: [advisory:ingest, advisory:read]
 | ||
|     tenants: [default]
 | ||
|   - clientId: policy-engine
 | ||
|     grantTypes: [client_credentials]
 | ||
|     scopes: [effective:write, findings:read]
 | ||
|     properties:
 | ||
|       serviceIdentity: policy-engine
 | ||
|   - clientId: cartographer-service
 | ||
|     grantTypes: [client_credentials]
 | ||
|     scopes: [graph:write, graph:read]
 | ||
|     properties:
 | ||
|       serviceIdentity: cartographer
 | ||
| ```
 | ||
| 
 | ||
| ---
 | ||
| 
 | ||
| ## 4 · Operational safeguards
 | ||
| 
 | ||
| - **Audit events:** Authority emits `authority.scope.granted` and `authority.scope.revoked` events with `scope` and `tenant`. Monitor for unexpected grants.
 | ||
| - **Rate limiting:** Apply stricter limits on `/token` endpoints for clients requesting `advisory:ingest` or `vex:ingest` to mitigate brute-force ingestion attempts.
 | ||
| - **Incident response:** Link AOC alerts to Authority audit logs to confirm whether violations come from expected identities.
 | ||
| - **Rotation:** Rotate ingest client secrets alongside guard deployments; add rotation steps to `ops/authority-key-rotation.md`.
 | ||
| - **Testing:** Integration tests must fail if tokens lacking `tenant` attempt ingestion; add coverage in Concelier/Excititor smoke suites (see `CONCELIER-CORE-AOC-19-013`).
 | ||
| 
 | ||
| ---
 | ||
| 
 | ||
| ## 5 · Offline & air-gap notes
 | ||
| 
 | ||
| - Offline Kit bundles include tenant-scoped service credentials. Ensure ingest bundles ship without `advisory:ingest` scopes unless strictly required.
 | ||
| - CLI verification in offline environments uses pre-issued `aoc:verify` tokens; document expiration and renewal processes.
 | ||
| - Authority replicas in air-gapped environments should restrict scope issuance to known tenants and log all `/token` interactions for later replay.
 | ||
| 
 | ||
| ---
 | ||
| 
 | ||
| ## 6 · References
 | ||
| 
 | ||
| - [Aggregation-Only Contract reference](../ingestion/aggregation-only-contract.md)
 | ||
| - [Architecture overview](../architecture/overview.md)
 | ||
| - [Concelier architecture](../ARCHITECTURE_CONCELIER.md)
 | ||
| - [Excititor architecture](../ARCHITECTURE_EXCITITOR.md)
 | ||
| - [Policy governance](policy-governance.md)
 | ||
| - [Authority key rotation playbook](../ops/authority-key-rotation.md)
 | ||
| 
 | ||
| ---
 | ||
| 
 | ||
| ## 7 · Compliance checklist
 | ||
| 
 | ||
| - [ ] Scope catalogue updated in Authority configuration templates.
 | ||
| - [ ] Role mappings documented for each tenant profile.
 | ||
| - [ ] Claim transforms enforce `serviceIdentity` for `effective:write`.
 | ||
| - [ ] Claim transforms enforce `serviceIdentity` for `graph:write`.
 | ||
| - [ ] Concelier/Excititor smoke tests cover missing tenant rejection.
 | ||
| - [ ] Offline kit credentials reviewed for least privilege.
 | ||
| - [ ] Audit/monitoring guidance validated with Observability Guild.
 | ||
| - [ ] Authority Core sign-off recorded (owner: @authority-core, due 2025-10-28).
 | ||
| 
 | ||
| ---
 | ||
| 
 | ||
| *Last updated: 2025-10-27 (Sprint 19).* 
 |