feat: Implement Scheduler Worker Options and Planner Loop
- 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.
This commit is contained in:
		@@ -49,15 +49,17 @@ Authority persists every issued token in MongoDB so operators can audit or revok
 | 
			
		||||
### Expectations for resource servers
 | 
			
		||||
Resource servers (Concelier WebService, Backend, Agent) **must not** assume in-memory caches are authoritative. They should:
 | 
			
		||||
 | 
			
		||||
- cache `/jwks` and `/revocations/export` responses within configured lifetimes;
 | 
			
		||||
- cache `/jwks` and `/revocations/export` responses within configured lifetimes;
 | 
			
		||||
- honour `revokedReason` metadata when shaping audit trails;
 | 
			
		||||
- treat `status != "valid"` or missing tokens as immediate denial conditions.
 | 
			
		||||
- propagate the `tenant` claim (`X-Stella-Tenant` header in REST calls) and reject requests when the tenant supplied by Authority does not match the resource server's scope; Concelier and Excititor guard endpoints refuse cross-tenant tokens.
 | 
			
		||||
 | 
			
		||||
### Tenant propagation
 | 
			
		||||
 | 
			
		||||
- Client provisioning (bootstrap or plug-in) accepts a `tenant` hint. Authority normalises the value (`trim().ToLowerInvariant()`) and persists it alongside the registration. Clients without an explicit tenant remain global.
 | 
			
		||||
- Issued principals include the `stellaops:tenant` claim. `PersistTokensHandler` mirrors this claim into `authority_tokens.tenant`, enabling per-tenant revocation and reporting.
 | 
			
		||||
- Rate limiter metadata now tags requests with `authority.tenant`, unlocking per-tenant throughput metrics and diagnostic filters. Audit events (`authority.client_credentials.grant`, `authority.password.grant`, bootstrap flows) surface the tenant and login attempt documents index on `{tenant, occurredAt}` for quick queries.
 | 
			
		||||
- Client credentials that request `advisory:ingest`, `advisory:read`, `vex:ingest`, `vex:read`, or `aoc:verify` now fail fast when the client registration lacks a tenant hint. Issued tokens are re-validated against persisted tenant metadata, and Authority rejects any cross-tenant replay (`invalid_client`/`invalid_token`), ensuring aggregation-only workloads remain tenant-scoped.
 | 
			
		||||
- Password grant flows reuse the client registration's tenant and enforce the configured scope allow-list. Requested scopes outside that list (or mismatched tenants) trigger `invalid_scope`/`invalid_client` failures, ensuring cross-tenant access is denied before token issuance.
 | 
			
		||||
 | 
			
		||||
### Default service scopes
 | 
			
		||||
@@ -66,7 +68,7 @@ Resource servers (Concelier WebService, Backend, Agent) **must not** assume in-m
 | 
			
		||||
|----------------------|---------------------------------------|--------------------------------------|-------------------|-----------------|
 | 
			
		||||
| `concelier-ingest`   | Concelier raw advisory ingestion      | `advisory:ingest`, `advisory:read`   | `dpop`            | `tenant-default` |
 | 
			
		||||
| `excitor-ingest`     | Excititor raw VEX ingestion           | `vex:ingest`, `vex:read`             | `dpop`            | `tenant-default` |
 | 
			
		||||
| `aoc-verifier`       | Aggregation-only contract verification | `aoc:verify`                         | `dpop`            | `tenant-default` |
 | 
			
		||||
| `aoc-verifier`       | Aggregation-only contract verification | `aoc:verify`, `advisory:read`, `vex:read` | `dpop`            | `tenant-default` |
 | 
			
		||||
| `cartographer-service` | Graph snapshot construction             | `graph:write`, `graph:read`          | `dpop`            | `tenant-default` |
 | 
			
		||||
| `graph-api`          | Graph Explorer gateway/API            | `graph:read`, `graph:export`, `graph:simulate` | `dpop` | `tenant-default` |
 | 
			
		||||
| `vuln-explorer-ui`   | Vuln Explorer UI/API                  | `vuln:read`                          | `dpop`            | `tenant-default` |
 | 
			
		||||
@@ -188,6 +190,13 @@ POST /internal/clients
 | 
			
		||||
 | 
			
		||||
For environments with multiple tenants, repeat the call per tenant-specific client (e.g. `concelier-tenant-a`, `concelier-tenant-b`) or append suffixes to the client identifier.
 | 
			
		||||
 | 
			
		||||
### Aggregation-only verification tokens
 | 
			
		||||
 | 
			
		||||
- Issue a dedicated client (e.g. `aoc-verifier`) with the scopes `aoc:verify`, `advisory:read`, and `vex:read` for each tenant that runs guard checks. Authority refuses to mint tokens for these scopes unless the client registration provides a tenant hint.
 | 
			
		||||
- The CLI (`stella aoc verify --tenant <tenant>`) and Console verification panel both call `/aoc/verify` on Concelier and Excititor. Tokens that omit the tenant claim or present a tenant that does not match the stored registration are rejected with `invalid_client`/`invalid_token`.
 | 
			
		||||
- Verification responses map guard failures to `ERR_AOC_00x` codes and Authority emits `authority.client_credentials.grant` + `authority.token.validate_access` audit records containing the tenant and scopes so operators can trace who executed a run.
 | 
			
		||||
- For air-gapped or offline replicas, pre-issue verification tokens per tenant and rotate them alongside ingest credentials; the guard endpoints never mutate data and remain safe to expose through the offline kit schedule.
 | 
			
		||||
 | 
			
		||||
## 7. Configuration Reference
 | 
			
		||||
 | 
			
		||||
| Section | Key | Description | Notes |
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user