89 lines
8.9 KiB
Markdown
89 lines
8.9 KiB
Markdown
# Scanner Endpoint Registration Matrix
|
|
|
|
Last updated: 2026-02-23 (Sprint `20260222.057`, tasks `SCAN-TEN-08`, `SCAN-TEN-11`, `SCAN-TEN-12`, and `SCAN-TEN-13`).
|
|
|
|
This file is the Scanner WebService source-of-truth for endpoint registration intent and authorization posture.
|
|
|
|
## Active endpoint maps (registered in `Program.cs`)
|
|
|
|
| Map method | Base path | Authorization posture | Notes |
|
|
| --- | --- | --- | --- |
|
|
| `MapHealthEndpoints` | `/healthz`, `/readyz` | `scanner.scans.read` | Health and readiness are authenticated. |
|
|
| `MapObservabilityEndpoints` | `/metrics` | `AllowAnonymous` | Prometheus scrape path is explicitly anonymous. |
|
|
| `MapOfflineKitEndpoints` | `/offline-kit` | Mixed explicit policies | Offline import/status/manifest/validate policies are explicit per route. |
|
|
| `MapScanEndpoints` | `/api/v1/scans` | Explicit policies per route | Includes nested scan maps (`callgraphs`, `sbom`, `reachability`, `export`, `evidence`, `approval`, `manifest`, `github-code-scanning`). |
|
|
| `MapSourcesEndpoints` | `/api/v1/sources` | `scanner.sources.read/write/admin` | Tenant-aware source CRUD and source-run operations (`sbom_source_runs` reads/writes are tenant-filtered). |
|
|
| `MapWebhookEndpoints` | `/api/v1/webhooks` | `AllowAnonymous` | External provider ingress; tenant-scoped source resolution for name routes. |
|
|
| `MapSbomUploadEndpoints` | `/api/v1/sbom` | Explicit policies per route | Includes SBOM upload and hot lookup maps. |
|
|
| `MapReachabilityDriftRootEndpoints` | `/api/v1/reachability` | `scanner.scans.read/write` | Root drift query/compute routes. |
|
|
| `MapDeltaCompareEndpoints` | `/api/v1/delta` | Explicit policies per route | Delta compare operations. |
|
|
| `MapSmartDiffEndpoints` | `/api/v1/smart-diff` | Explicit policies per route | Smart diff + VEX candidate workflows. |
|
|
| `MapBaselineEndpoints` | `/api/v1/baselines` | Explicit policies per route | Baseline operations. |
|
|
| `MapActionablesEndpoints` | `/api/v1/actionables` | Explicit policies per route | Actionable findings operations. |
|
|
| `MapCounterfactualEndpoints` | `/api/v1/counterfactuals` | Explicit policies per route | Counterfactual analysis operations. |
|
|
| `MapProofSpineEndpoints` | `/api/v1/spines` | Explicit policies per route | Proof spine APIs. |
|
|
| `MapReplayEndpoints` | `/api/v1/replay` | Explicit policies per route | Replay command and verification APIs. |
|
|
| `MapScoreReplayEndpoints` (feature-gated) | `/api/v1/replay/score` | Explicit policies per route | Enabled only when `scanner:scoreReplay:enabled=true`. |
|
|
| `MapWitnessEndpoints` | `/api/v1/witnesses` | Explicit policies per route | Witness management APIs. |
|
|
| `MapEpssEndpoints` | `/api/v1/epss` | Explicit policies per route | EPSS ingestion/query APIs. |
|
|
| `MapTriageStatusEndpoints` | `/api/v1/triage` | `scanner.triage.read/write` | Triage status workflows. |
|
|
| `MapTriageInboxEndpoints` | `/api/v1/triage` | `scanner.triage.read/write` | Triage inbox workflows. |
|
|
| `MapBatchTriageEndpoints` | `/api/v1/triage` | `scanner.triage.read/write` | Bulk triage operations. |
|
|
| `MapProofBundleEndpoints` | `/api/v1/triage` | `scanner.triage.read` | Triage proof bundle retrieval. |
|
|
| `MapUnknownsEndpoints` | `/api/v1/unknowns` | `scanner.scans.read` | Tenant-scoped unknown listing/detail/evidence/history/stats/bands routes. |
|
|
| `MapSecretDetectionSettingsEndpoints` | `/api/v1/secrets/config` | `scanner.secret-settings.*` / `scanner.secret-exceptions.*` | Secret detection config APIs with tenant-scoped exception get/update/delete lookups. |
|
|
| `MapSecurityAdapterEndpoints` | `/api/v1/security` | Explicit policies per route | Security adapter read-model routes. |
|
|
| `MapPolicyEndpoints` (feature-gated) | `/api/v1/policy` | Explicit policies per route | Enabled only when policy preview feature flag is true. |
|
|
| `MapReportEndpoints` | `/api/v1/reports` | `scanner.reports` | Report generation and retrieval routes. |
|
|
| `MapRuntimeEndpoints` | `/api/v1/runtime` | `scanner.runtime.ingest` and scan policies | Runtime ingest/reconcile APIs. |
|
|
| `MapSliceEndpoints` | `/api/slices` | Explicit policies per route | Reachability slice query/replay APIs. |
|
|
|
|
## Webhook tenant contract (name routes)
|
|
|
|
- Name-based webhook routes are:
|
|
- `POST /api/v1/webhooks/docker/{sourceName}`
|
|
- `POST /api/v1/webhooks/github/{sourceName}`
|
|
- `POST /api/v1/webhooks/gitlab/{sourceName}`
|
|
- `POST /api/v1/webhooks/harbor/{sourceName}`
|
|
- Tenant context is required for name-based routes (claim or `X-StellaOps-Tenant`/compatibility alias). Missing tenant returns `400` with `tenant_missing`; claim/header mismatch returns `400` with `tenant_conflict`.
|
|
- Source lookup is tenant-scoped via `GetByNameAsync(tenantId, sourceName)`, so same-name sources in different tenants cannot cross-dispatch.
|
|
- `POST /api/v1/webhooks/{sourceId}` accepts optional tenant context; if present and it does not match source ownership, the endpoint returns `404`.
|
|
|
|
## Triage tenant contract
|
|
|
|
- Triage and finding-evidence routes resolve tenant context via `ScannerRequestContextResolver`.
|
|
- Resolution precedence: claim (`tenant`, compatibility aliases `tid`/`tenant_id`), then headers (`X-StellaOps-Tenant`, `X-Stella-Tenant`, `X-Tenant-Id`), then fallback tenant `default` for triage flows configured with `allowDefaultTenant`.
|
|
- If multiple claim/header values conflict, Scanner returns `400` with `tenant_conflict`.
|
|
- Triage-facing contracts now require tenant input (`ITriageStatusService`, `ITriageQueryService`, `IFindingQueryService`, `IGatingReasonService`, `IUnifiedEvidenceService`, `IReplayCommandService`, `IFindingRationaleService`) and enforce tenant-filtered data access.
|
|
- Triage persistence is tenant partitioned (`triage_scan.tenant_id`, `triage_finding.tenant_id`), and the active-case uniqueness key includes `tenant_id` to avoid cross-tenant collisions.
|
|
- Cross-tenant finding lookups are treated as deterministic not-found responses (`404`) on triage/finding endpoints.
|
|
|
|
## Unknowns tenant contract
|
|
|
|
- Unknowns routes resolve tenant context via `ScannerRequestContextResolver` using canonical and compatibility claim/header paths with conflict detection.
|
|
- Unknown queries are tenant-scoped by data access predicates (`tenant_id::text = @tenantId`) in the Scanner WebService query service.
|
|
- Missing records across tenant boundaries resolve as deterministic `404` for detail/evidence/history endpoints.
|
|
|
|
## Reachability + SmartDiff tenant contract (SCAN-TEN-11)
|
|
|
|
- Reachability drift routes (`/api/v1/scans/{scanId}/drift`, `/api/v1/drift/{driftId}/sinks`) now resolve tenant context via `ScannerRequestContextResolver` before repository access.
|
|
- Drift persistence/retrieval paths are tenant-parameterized end-to-end (`call_graph_snapshots`, `code_changes`, `reachability_drift_results`, `drifted_sinks`) instead of using a fixed tenant scope.
|
|
- SmartDiff routes (`/api/v1/smart-diff/**`) now resolve tenant context and pass it explicitly to material-change and VEX-candidate stores.
|
|
- SmartDiff persistence/retrieval paths are tenant-parameterized (`material_risk_changes`, `vex_candidates`), so candidate ID collisions across tenants resolve as deterministic not-found.
|
|
- Remaining reachability/SmartDiff storage adapters used by these flows are tenant-parameterized as well (`risk_state_snapshots`, `reachability_results`), removing fixed-tenant constants from Postgres adapter implementations.
|
|
|
|
## Source-runs + secret-exception tenant contract (SCAN-TEN-13)
|
|
|
|
- Source run routes (`/api/v1/sources/{sourceId}/runs`, `/api/v1/sources/{sourceId}/runs/{runId}`) now pass resolved tenant context into `ISbomSourceRunRepository` and SQL predicates (`tenant_id = @tenantId`) for `scanner.sbom_source_runs`.
|
|
- Secret exception routes (`/api/v1/secrets/config/exceptions/{tenantId}/{exceptionId}`) now use tenant-scoped repository methods for get/update/delete against `secret_exception_pattern` rather than ID-only lookups.
|
|
- The generic webhook route (`POST /api/v1/webhooks/{sourceId}`) remains compatibility-tolerant for missing tenant context, but enforces ownership match when tenant context is present.
|
|
|
|
## Deferred endpoint maps (not registered by design)
|
|
|
|
| Map method | Current state | Reason for deferral | Activation prerequisite |
|
|
| --- | --- | --- | --- |
|
|
| `MapValidationEndpoints` | Deferred | Validation endpoint stack is not wired in `Program.cs` (validator service graph and option bindings are not part of default webservice startup contract). | Add explicit validation DI and contract docs, then register in `Program.cs`. |
|
|
| `MapReachabilityEvidenceEndpoints` | Deferred | Legacy standalone `/api/reachability` surface is not part of current `/api/v1/scans`/triage scanner API contract. | Contract decision to promote or remove this surface. |
|
|
| `MapReachabilityStackEndpoints` | Deferred | Stack endpoints depend on optional repository path and are not part of the current public API registration set. | Contract decision and stable backing repository implementation. |
|
|
| `MapFidelityEndpoints` | Deferred | Fidelity analyzer endpoints are experimental and require explicit analyzer service contract decisions before exposure. | Product sign-off and DI contract hardening. |
|