80 lines
4 KiB
Markdown
80 lines
4 KiB
Markdown
|
|
# Repository navigation contract 1.0.0
|
||
|
|
|
||
|
|
Status: frozen for HUB-WP-0006 T02 on 2026-08-22.
|
||
|
|
|
||
|
|
The packaged contract is `helixforge.repository-navigation` version `1.0.0`.
|
||
|
|
It consumes only `helixforge.repository-classification-projection` version
|
||
|
|
`1.0.0`, representing `RMGR-CONTRACT-CLASSIFICATION-0001` version `1.0`.
|
||
|
|
Unsupported versions are rejected; hub-core does not coerce them.
|
||
|
|
|
||
|
|
## Authority and identity
|
||
|
|
|
||
|
|
Repository `.repo-classification.yaml` files remain authoritative. Repo Manager
|
||
|
|
validates and publishes them. Hub-core owns only rebuildable navigation rows,
|
||
|
|
facets, query cursors, diagnostics, and temporary compatibility aliases.
|
||
|
|
|
||
|
|
Every change carries the registrar's stable `repository_id` UUID. Slugs may
|
||
|
|
change and are display/routing labels, not identity. The Repo Manager adapter
|
||
|
|
adds that UUID when converting its local observation into this envelope.
|
||
|
|
`locations`, `repo_root`, work-record bodies, credentials, and other host-local
|
||
|
|
or authority-bearing data are forbidden by the closed schemas.
|
||
|
|
|
||
|
|
## Pages, snapshots, and changes
|
||
|
|
|
||
|
|
All pages in a transfer have the same `snapshot_id`, `mode`, `generated_at`,
|
||
|
|
`source_revision`, and `total_repository_count`. Entries are ordered by
|
||
|
|
`repository_id`; duplicate IDs in one transfer are invalid.
|
||
|
|
|
||
|
|
- The first page has a null `page_cursor`.
|
||
|
|
- `next_cursor` is null exactly when `final_page` is true.
|
||
|
|
- Cursors are opaque, signed or equivalently integrity-protected, bound to the
|
||
|
|
snapshot and normalized filter set, and never parsed by clients.
|
||
|
|
- A full snapshot consists of upserts. Absence means deletion only after every
|
||
|
|
page validates and the final page is accepted.
|
||
|
|
- An incremental snapshot contains explicit idempotent upsert/delete changes.
|
||
|
|
A change is newer only by its source observation/revision semantics; duplicate
|
||
|
|
delivery has no effect.
|
||
|
|
- `total_repository_count` is required for a full snapshot and may be null for
|
||
|
|
incremental delivery.
|
||
|
|
|
||
|
|
Activation is atomic. Hub-core builds into a new generation, derives all six
|
||
|
|
facet kinds, computes SHA-256 over canonical JSON repository rows ordered by
|
||
|
|
UUID, and swaps the active generation only after the complete transfer passes
|
||
|
|
schema and semantic validation. A failed full rebuild never deletes or partly
|
||
|
|
replaces the last accepted generation.
|
||
|
|
|
||
|
|
## Failure and diagnostics
|
||
|
|
|
||
|
|
An error diagnostic, malformed page, inconsistent snapshot metadata,
|
||
|
|
unsupported version, duplicate identity, invalid controlled value, or upstream
|
||
|
|
failure rejects that transfer. The last accepted projection remains readable
|
||
|
|
as `stale`, includes a diagnostic and `source_checked_at`, and readiness reports
|
||
|
|
the Repo Manager dependency as degraded. If no accepted generation exists, the
|
||
|
|
query port returns `503`. Successful acceptance restores `current`.
|
||
|
|
|
||
|
|
Provenance on every repository includes the Repo Manager URI, classification
|
||
|
|
contract version, source fingerprint, observed time, and repository revision.
|
||
|
|
The response also carries the source snapshot/revision and rebuild content
|
||
|
|
hash. Diagnostics must not include secrets or unbounded source content.
|
||
|
|
|
||
|
|
## Query semantics
|
||
|
|
|
||
|
|
Repositories are returned in ascending UUID order. Repeated values within one
|
||
|
|
filter family are ORed; different filter families are ANDed. The six families
|
||
|
|
are primary domain, secondary domain, category, capability tag, business stake,
|
||
|
|
and business mechanic. An unknown value produces `400`; an empty match is a
|
||
|
|
successful empty page.
|
||
|
|
|
||
|
|
Response cursors are bound to both the active content hash and normalized
|
||
|
|
filters. Reusing a cursor after a rebuild or with different filters returns
|
||
|
|
`409 cursor_snapshot_mismatch`, so a client restarts from the first page.
|
||
|
|
|
||
|
|
## Legacy topic aliases
|
||
|
|
|
||
|
|
`legacy_topic_aliases` is temporary, read-only compatibility metadata. Each
|
||
|
|
entry maps one State Hub topic UUID/slug to one derived facet and must name an
|
||
|
|
`expires_at` time and `residual_owner`. It cannot create, update, or delete
|
||
|
|
classification. Expired aliases return `410` until removed; there are no write
|
||
|
|
operations in the navigation OpenAPI surface. STATE-WP-0079 owns alias expiry
|
||
|
|
and the consumer route switch.
|