feat: freeze repository navigation contract
Assistant: codex Assistant-Model: gpt-5.6-sol Assistant-Session: 01a0230c-b06c-7641-808a-e191b6d1da49
This commit is contained in:
parent
b27de6e5bf
commit
a701dc89cf
15 changed files with 1053 additions and 4 deletions
79
docs/repository-navigation-contract.md
Normal file
79
docs/repository-navigation-contract.md
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
# 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.
|
||||
Loading…
Add table
Add a link
Reference in a new issue