feat: Implement console session management with tenant and profile handling
- Add ConsoleSessionStore for managing console session state including tenants, profile, and token information. - Create OperatorContextService to manage operator context for orchestrator actions. - Implement OperatorMetadataInterceptor to enrich HTTP requests with operator context metadata. - Develop ConsoleProfileComponent to display user profile and session details, including tenant information and access tokens. - Add corresponding HTML and SCSS for ConsoleProfileComponent to enhance UI presentation. - Write unit tests for ConsoleProfileComponent to ensure correct rendering and functionality.
This commit is contained in:
		
							
								
								
									
										124
									
								
								docs/policy/gateway.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										124
									
								
								docs/policy/gateway.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,124 @@ | ||||
| # Policy Gateway | ||||
|  | ||||
| > **Delivery scope:** `StellaOps.Policy.Gateway` minimal API service fronting Policy Engine pack CRUD + activation endpoints for UI/CLI clients. Sender-constrained with DPoP and tenant headers, suitable for online and Offline Kit deployments. | ||||
|  | ||||
| ## 1 · Responsibilities | ||||
|  | ||||
| - Proxy policy pack CRUD and activation requests to Policy Engine while enforcing scope policies (`policy:read`, `policy:author`, `policy:review`, `policy:operate`, `policy:activate`). | ||||
| - Normalise responses (DTO + `ProblemDetails`) so Console, CLI, and automation receive consistent payloads. | ||||
| - Guard activation actions with structured logging and metrics so approvals are auditable. | ||||
| - Support dual auth modes: | ||||
|   - Forwarded caller tokens (Console/CLI) with DPoP proofs + `X-Stella-Tenant` header. | ||||
|   - Gateway client credentials (DPoP) for service automation or Offline Kit flows when no caller token is present. | ||||
|  | ||||
| ## 2 · Endpoints | ||||
|  | ||||
| | Route | Method | Description | Required scope(s) | | ||||
| |-------|--------|-------------|-------------------| | ||||
| | `/api/policy/packs` | `GET` | List policy packs and revisions for the active tenant. | `policy:read` | | ||||
| | `/api/policy/packs` | `POST` | Create a policy pack shell or upsert display metadata. | `policy:author` | | ||||
| | `/api/policy/packs/{packId}/revisions` | `POST` | Create or update a policy revision (draft/approved). | `policy:author` | | ||||
| | `/api/policy/packs/{packId}/revisions/{version}:activate` | `POST` | Activate a revision, enforcing single/two-person approvals. | `policy:operate`, `policy:activate` | | ||||
|  | ||||
| ### Response shapes | ||||
|  | ||||
| - Successful responses return camel-case DTOs matching `PolicyPackDto`, `PolicyRevisionDto`, or `PolicyRevisionActivationDto` as described in the Policy Engine API doc (`/docs/api/policy.md`). | ||||
| - Errors always return RFC 7807 `ProblemDetails` with deterministic fields (`title`, `detail`, `status`). Missing caller credentials now surface `401` with `"Upstream authorization missing"` detail. | ||||
|  | ||||
| ## 3 · Authentication & headers | ||||
|  | ||||
| | Header | Source | Notes | | ||||
| |--------|--------|-------| | ||||
| | `Authorization` | Forwarded caller token *or* gateway client credentials. | Caller tokens must include tenant scope; gateway tokens default to `DPoP` scheme. | | ||||
| | `DPoP` | Caller or gateway. | Required when Authority mandates proof-of-possession (default). Generated per request; gateway keeps ES256/ES384 key material under `etc/policy-gateway-dpop.pem`. | | ||||
| | `X-Stella-Tenant` | Caller | Tenant isolation header. Forwarded unchanged; gateway automation omits it. | | ||||
|  | ||||
| Gateway client credentials are configured in `policy-gateway.yaml`: | ||||
|  | ||||
| ```yaml | ||||
| policyEngine: | ||||
|   baseAddress: "https://policy-engine.internal" | ||||
|   audience: "api://policy-engine" | ||||
|   clientCredentials: | ||||
|     enabled: true | ||||
|     clientId: "policy-gateway" | ||||
|     clientSecret: "<secret>" | ||||
|     scopes: | ||||
|       - policy:read | ||||
|       - policy:author | ||||
|       - policy:review | ||||
|       - policy:operate | ||||
|       - policy:activate | ||||
|   dpop: | ||||
|     enabled: true | ||||
|     keyPath: "../etc/policy-gateway-dpop.pem" | ||||
|     algorithm: "ES256" | ||||
| ``` | ||||
|  | ||||
| > 🔐 **DPoP key** – store the private key alongside Offline Kit secrets; rotate it whenever the gateway identity or Authority configuration changes. | ||||
|  | ||||
| ## 4 · Metrics & logging | ||||
|  | ||||
| All activation calls emit: | ||||
|  | ||||
| - `policy_gateway_activation_requests_total{outcome,source}` – counter labelled with `outcome` (`activated`, `pending_second_approval`, `already_active`, `bad_request`, `not_found`, `unauthorized`, `forbidden`, `error`) and `source` (`caller`, `service`). | ||||
| - `policy_gateway_activation_latency_ms{outcome,source}` – histogram measuring proxy latency. | ||||
|  | ||||
| Structured logs (category `StellaOps.Policy.Gateway.Activation`) include `PackId`, `Version`, `Outcome`, `Source`, and upstream status code for audit trails. | ||||
|  | ||||
| ## 5 · Sample `curl` workflows | ||||
|  | ||||
| Assuming you already obtained a DPoP-bound access token (`$TOKEN`) for tenant `acme`: | ||||
|  | ||||
| ```bash | ||||
| # Generate a DPoP proof for GET via the CLI helper | ||||
| DPoP_PROOF=$(stella auth dpop proof \ | ||||
|   --htu https://gateway.example.com/api/policy/packs \ | ||||
|   --htm GET \ | ||||
|   --token "$TOKEN") | ||||
|  | ||||
| curl -sS https://gateway.example.com/api/policy/packs \ | ||||
|   -H "Authorization: DPoP $TOKEN" \ | ||||
|   -H "DPoP: $DPoP_PROOF" \ | ||||
|   -H "X-Stella-Tenant: acme" | ||||
|  | ||||
| # Draft a new revision | ||||
| DPoP_PROOF=$(stella auth dpop proof \ | ||||
|   --htu https://gateway.example.com/api/policy/packs/policy.core/revisions \ | ||||
|   --htm POST \ | ||||
|   --token "$TOKEN") | ||||
|  | ||||
| curl -sS https://gateway.example.com/api/policy/packs/policy.core/revisions \ | ||||
|   -H "Authorization: DPoP $TOKEN" \ | ||||
|   -H "DPoP: $DPoP_PROOF" \ | ||||
|   -H "X-Stella-Tenant: acme" \ | ||||
|   -H "Content-Type: application/json" \ | ||||
|   -d '{"version":5,"requiresTwoPersonApproval":true,"initialStatus":"Draft"}' | ||||
|  | ||||
| # Activate revision 5 (returns 202 when awaiting the second approver) | ||||
| DPoP_PROOF=$(stella auth dpop proof \ | ||||
|   --htu https://gateway.example.com/api/policy/packs/policy.core/revisions/5:activate \ | ||||
|   --htm POST \ | ||||
|   --token "$TOKEN") | ||||
|  | ||||
| curl -sS https://gateway.example.com/api/policy/packs/policy.core/revisions/5:activate \ | ||||
|   -H "Authorization: DPoP $TOKEN" \ | ||||
|   -H "DPoP: $DPoP_PROOF" \ | ||||
|   -H "X-Stella-Tenant: acme" \ | ||||
|   -H "Content-Type: application/json" \ | ||||
|   -d '{"comment":"Rollout baseline"}' | ||||
| ``` | ||||
|  | ||||
| For air-gapped environments, bundle `policy-gateway.yaml` and the DPoP key in the Offline Kit (see `/docs/24_OFFLINE_KIT.md` §5.7). | ||||
|  | ||||
| > **DPoP proof helper:** Use `stella auth dpop proof` to mint sender-constrained proofs locally. The command accepts `--htu`, `--htm`, and `--token` arguments and emits a ready-to-use header value. Teams maintaining alternate tooling (for example, `scripts/make-dpop.sh`) can substitute it as long as the inputs and output match the CLI behaviour. | ||||
|  | ||||
| ## 6 · Offline Kit guidance | ||||
|  | ||||
| - Include `policy-gateway.yaml.sample` and the resolved runtime config in the Offline Kit’s `config/` tree. | ||||
| - Place the DPoP private key under `secrets/policy-gateway-dpop.pem` with restricted permissions; document rotation steps in the manifest. | ||||
| - When building verification scripts, use the gateway endpoints above instead of hitting Policy Engine directly. The Offline Kit validator now expects `policy_gateway_activation_requests_total` metrics in the Prometheus snapshot. | ||||
|  | ||||
| ## 7 · Change log | ||||
|  | ||||
| - **2025-10-27 – Sprint 18.5**: Initial gateway bootstrap + activation metrics + DPoP client credentials. | ||||
		Reference in New Issue
	
	Block a user