This repository has been archived on 2026-07-08. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
core-hub/docs/specs/ops-evidence-contract.md
2026-06-27 23:56:34 +02:00

174 lines
10 KiB
Markdown

# Ops Evidence Contract
## Purpose
Define the Core Hub-owned operations evidence contract that replaces the old
standalone ops-hub model list from `CUST-WP-0025-T14`.
This contract reconciles the Custodian service inventory lane, Core Hub v2
registry resources, activity-core probe output, migration/cutover evidence, and
non-secret credential-custody rules. It is intentionally API-first: CLI and UI
surfaces must consume these resources instead of inventing their own evidence
shape.
## Scope
In scope:
- runtime service and endpoint readiness evidence;
- Core Hub registry/bootstrap evidence for ops-hub replacement work;
- activity-core Core Hub sink proof;
- migration import, deployment, outcome, and cutover readiness evidence;
- non-secret credential and access metadata.
Out of scope for this contract:
- secret value retrieval or vending;
- SSH certificate issuance;
- operator approval itself;
- the full future ops-hub product boundary if post-cutover work proves a
separate service is needed.
## Source Inputs
| Source | Current artifact | Core Hub use |
| --- | --- | --- |
| Custodian service inventory | `CUST-WP-0047` service/location/evidence records | Seed widgets and interaction events; preserve source ids in metadata. |
| Core Hub v2 resources | hubs, manifests, API consumers, API keys, widgets, events, migration runs | Canonical API/read model for replacement evidence. |
| activity-core probe output | `core-hub-interaction-event` sink reports | Append `interaction_events` with source run and verification metadata. |
| Migration tooling | `scripts/core_hub_migrate.py`, `MigrationRun` | Store bundle hash, source, dry-run flag, counts, diagnostics, status. |
| Operator CLI | `deployed-smoke`, `ops-bootstrap-status`, `migration`, `readiness-summary` | Non-secret evidence report generator over the same API resources. |
## Canonical API Resources
### Implemented Now
| Resource | API path | Purpose | Required non-secret fields |
| --- | --- | --- | --- |
| Hub | `/api/v2/hubs` | Domain hub or replacement runtime record. | id, slug, name, domain, hubKind, hubFamily, vsmFunction, vsmSystem, status. |
| Hub capability manifest | `/api/v2/hub-capability-manifests` | Declared widgets/events/scopes/endpoints for a hub. | id, hubId, hubSlug, manifestVersion, status, declared widget/event/policy lists. |
| API consumer | `/api/v2/api-consumers` | Runtime or operator consumer metadata. | id, slug, name, hubCapabilityManifestId, rate/quota values, keyPrefix, status. |
| API key issuance result | `/api/v2/api-consumers/{consumer_id}/api-keys` | One-time generated key plus stored hash/prefix. | returned full key only at creation; persist only id, consumer id, keyPrefix, hash, scopes, status. |
| Widget | `/api/v2/widgets` | Operator-facing evidence target/read model item. | id, hubId, name, widgetType, capabilityRef, viewContext, policyScope, status. |
| Interaction event | `/api/v2/interaction-events` | Append-only operational evidence. | id, widgetId, eventType, viewContext, metadata, createdAt if exposed. |
| Hub registry | `/api/v2/hub-registry` | Read model for hubs and manifests. | hubs[], hubCapabilityManifests[]. |
| Migration run | stored as `migration_runs` | Import/validate evidence. | id, source, schemaVersion, bundleSha256, dryRun, status, counts, diagnostics, createdAt. |
### Required Read-Model Gaps
These are the gaps that must close before broad UI expansion or cutover claims:
| Gap | Required path or behavior | Why it matters |
| --- | --- | --- |
| Migration run read API | `GET /api/v2/migration-runs` and optional `GET /api/v2/migration-runs/{id}` | UI and readiness reports need to inspect import evidence without reading the database directly. |
| Deployment records | Replace deferred empty `/api/v2/deployment-records` with persisted non-secret deployment facts. | Deployed smoke and cutover readiness need image/tag/runtime state evidence. |
| Outcome signals | Replace deferred empty `/api/v2/outcome-signals` with persisted pass/fail/degraded signals. | Operator screens need to distinguish evidence from result interpretation. |
| Service inventory mapping | Persist or derive a mapping from Custodian service ids to Core Hub widget ids/events. | Lets `CUST-WP-0047` inventory become Core Hub evidence without losing provenance. |
| Interaction-event filters | Add query filters for `hubId`, `widgetId`, `eventType`, `viewContext`, and time window. | Needed for compact evidence streams and activity-core sink verification. |
| Registry containment summary | Expose counts and containment booleans now computed by smoke reports. | Avoids each CLI/UI consumer re-deriving the same readiness checks. |
## Evidence Vocabulary
Event types should be explicit and versioned through the catalog once promoted.
Initial operational event types:
| Event type | Producer | Meaning | Required metadata |
| --- | --- | --- | --- |
| `ops-endpoint-verified` | deployed smoke, ops probe, operator CLI | A service endpoint or registry path responded as expected. | runId, source, endpoint label, status code or health state, verified boolean. |
| `core-hub-deployed-smoke` | `scripts/core_hub_deployed_smoke.py` | Deployed Core Hub API smoke result. | runId, hub id/slug, manifest id/status, API consumer id/status/keyPrefix, widget id/count, event id/type, registry containment booleans. |
| `core-hub-activity-sink-verified` | activity-core | activity-core posted and verified a Core Hub interaction event. | runId, widget id, event id, eventType, status, verified boolean, source workplan/task if available. |
| `core-hub-migration-validated` | migration CLI | A bundle validation completed without import. | source, schemaVersion, bundleSha256, dryRun true, counts, diagnostics summary. |
| `core-hub-migration-imported` | migration CLI | A non-dry-run import completed. | source, schemaVersion, bundleSha256, dryRun false, counts, diagnostics summary, migrationRunId. |
| `core-hub-cutover-gate` | operator CLI | A readiness summary evaluated a gate. | gate name, ok boolean, reason, evidence ids/counts, report path or State Hub progress id. |
All event `metadata` and body fields must be non-secret. Allowed access metadata:
- key prefixes;
- key hash algorithm labels or stored hash ids;
- OpenBao path/version labels only when they do not reveal values;
- route catalog ids;
- token accessor ids only when explicitly approved by the owning subsystem;
- Kubernetes Secret name and populated-key count, not secret data.
Forbidden fields:
- API keys, bearer tokens, SSH private keys, database passwords, OIDC refresh
tokens, cookie values, raw Authorization headers, or copied Secret manifests;
- one-time API key material after the creation response has left the operator
process;
- plaintext excerpts from secret files or OpenBao responses.
## Service Inventory Mapping
`CUST-WP-0047` service inventory rows map into Core Hub as follows:
| Inventory concept | Core Hub target |
| --- | --- |
| service id / slug | `Hub.slug` when the service is itself a hub; otherwise `Widget.body.serviceId`. |
| service display name | `Hub.name` or `Widget.name`. |
| service domain/location | `Hub.domain`, `Widget.viewContext`, and event metadata. |
| evidence type | `InteractionEvent.eventType`. |
| evidence source path | `InteractionEvent.metadata.sourcePath` or `sourceWorkplan`. |
| readiness or blocker state | `Widget.status`, event metadata, and later outcome signals. |
| credential route | metadata route id only, never a credential value. |
Mapping rules:
- Keep original inventory ids in metadata so State Hub/Custodian references stay
traceable.
- Prefer one widget per operator-visible evidence target, not one widget per log
line.
- Append interaction events for observations; only change widget status when the
latest stable operator-facing state changes.
- Activity-core may append events to existing widgets only after the widget id
mapping is explicitly configured.
## Readiness Summary Inputs
`readiness-summary` is the cutover-facing aggregation. Required gates:
| Gate | Source report | Required evidence |
| --- | --- | --- |
| deployed_api_smoke | `make deployed-smoke` or operator CLI deployed-smoke | ok true, runId, check count, event id. |
| staging_import | migration import report | ok true, dryRun false, bundleSha256, counts, migrationRunId. |
| activity_core_sink | activity-core sink report | at least one posted and verified event. |
Optional but useful gate:
- `legacy_inter_hub_reference`: explicit rollback/compatibility evidence while
Inter-Hub remains available.
Cutover is not ready until every required gate is true and the operator records
an approval decision outside this contract.
## API / CLI / UI Order
1. API resources and read routes are canonical.
2. CLI wrappers generate and summarize evidence over the same API.
3. UI screens are read-heavy views over API and CLI-compatible summaries.
The `/console` rebuild must not read migration tables directly once the
`migration-runs` API exists.
## Implementation Backlog
| Priority | Item | Acceptance |
| --- | --- | --- |
| P0 | Add migration run read routes. | `/api/v2/migration-runs` lists stored runs with source, bundle hash, dryRun, status, counts, diagnostics summary. |
| P0 | Add interaction-event filters. | API supports filtering by event type, widget id, view context, and time window. |
| P0 | Define service inventory import fixture. | A fixture maps at least one Custodian inventory service into a widget plus event with provenance metadata. |
| P1 | Persist deployment records. | `/api/v2/deployment-records` stops returning only an empty compatibility collection. |
| P1 | Persist outcome signals. | `/api/v2/outcome-signals` can store non-secret pass/fail/degraded signals linked to events or migration runs. |
| P1 | Registry readiness summary route. | API exposes counts/containment booleans used by deployed smoke and UI readiness overview. |
## Acceptance For CUST-WP-0025-T14
This spec closes the T14 definition gate. Implementation remains in follow-up
Core Hub tasks and the deployed evidence gates:
- `CUST-WP-0025-T16` for deployed Core Hub and activity-core smokes;
- `CUST-WP-0025-T17` for cutover/legacy coupling;
- `CUST-WP-0025-T18` for the UI rebuild after API/CLI evidence is stable;
- `CORE-WP-0005` for staging import and cutover readiness;
- future Core Hub work for the P0/P1 read-model gaps above.