generated from coulomb/repo-seed
174 lines
10 KiB
Markdown
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.
|