Record the verified publisher image digest and track wrapper rollout separately. Register existing CORE-WP, DISCTL-WP, and REPO-WP owners and retain the outstanding instruction correction. Assistant: codex Assistant-Model: gpt-6-astra Assistant-Session: 01a100de-2e1c-7e23-9ae9-2da0e0499411
147 lines
5.9 KiB
Markdown
147 lines
5.9 KiB
Markdown
# Repository classification publisher
|
|
|
|
Repo Manager publishes the frozen
|
|
`helixforge.repository-classification-projection` 1.0.0 envelope at:
|
|
|
|
```text
|
|
GET /ports/repositories/classifications?cursor=<opaque>
|
|
```
|
|
|
|
The route is read-only. It contains registrar UUID, slug, lifecycle,
|
|
classification, Git revision, source fingerprint, and observation time. Local
|
|
paths, remotes, work records, source bodies, and credentials never enter the
|
|
envelope.
|
|
|
|
## Forgejo-backed registry
|
|
|
|
Publication joins repository-owned `.repo-classification.yaml` files to a
|
|
stable repository registry. Production uses the committed
|
|
`config/repository-registry.yaml`; it contains registrar UUIDs and canonical
|
|
Forgejo identities, but no credentials or host paths:
|
|
|
|
```yaml
|
|
schema: repo-manager.repository-registry.v1
|
|
repositories:
|
|
- repository_id: a9d105c6-10fa-4cf9-8bc1-e248476698d3
|
|
slug: repo-manager
|
|
lifecycle: active
|
|
forgejo_repository: coulomb/repo-manager
|
|
```
|
|
|
|
Bootstrap current stable identities from the retiring primary State Hub:
|
|
|
|
```bash
|
|
rmgr publisher import-registry \
|
|
--root /home/operator \
|
|
--api-base http://127.0.0.1:8000 \
|
|
--source forgejo \
|
|
--output ~/.repo-manager/repository-registry.yaml
|
|
```
|
|
|
|
The import verifies `instance_role=primary`, discovers only classified Git
|
|
working copies below the selected root, and uses bounded direct identity reads.
|
|
It does not use State Hub's expensive bulk repository projection and does not
|
|
trust State Hub host paths. Transient reads retry; locally classified but
|
|
unregistered checkouts are retained as warnings and omitted rather than being
|
|
assigned invented identities. Any other failure prevents replacement of the
|
|
registry file.
|
|
|
|
The import is a migration/bootstrap path. Normal governed registration must
|
|
maintain the committed UUID-to-Forgejo mapping after State Hub registrar
|
|
retirement. The publisher contract does not change.
|
|
|
|
### Deliver registry corrections
|
|
|
|
`Containerfile` copies the committed registry into the publisher image. A Git
|
|
push or `rmgr sync` updates source/work-record projections; it does not refresh
|
|
the registry in an already running publisher. After a repository rename:
|
|
|
|
1. Verify the canonical Forgejo `full_name` and preserve the registrar UUID.
|
|
2. Update the registry coordinates, commit, and build an image from that clean
|
|
commit with `make container-build IMAGE_TAG=<full-commit-sha>`.
|
|
3. Verify the embedded registry and observe the renamed sources from the image,
|
|
then push the image and record its immutable digest.
|
|
4. Track the deployment in the consuming wrapper (`rapp-core-hub`). Pin the new
|
|
digest and deploy through its approved release procedure, then run
|
|
`make verify-publisher` before enabling `publisher.connectCandidate`.
|
|
|
|
Keep the exact identity check strict: an old Forgejo URL redirecting to a new
|
|
repository name is evidence to update the registry, not permission to silently
|
|
change published identity. Source correction and live rollout need separate
|
|
completion evidence. The October 3 refresh is tracked in `RMGR-WP-0018`.
|
|
|
|
## Run
|
|
|
|
Set runtime configuration through the environment:
|
|
|
|
```text
|
|
REPO_MANAGER_REGISTRY_PATH=~/.repo-manager/repository-registry.yaml
|
|
REPO_MANAGER_CURSOR_SECRET=<at-least-32-byte-secret>
|
|
REPO_MANAGER_API_TOKEN=<optional-bearer-token>
|
|
REPO_MANAGER_FORGEJO_BASE_URL=https://forgejo.coulomb.social
|
|
REPO_MANAGER_FORGEJO_TOKEN_FILE=/var/run/secrets/repo-manager/forgejo/token
|
|
REPO_MANAGER_FORGEJO_WORKERS=8
|
|
REPO_MANAGER_FORGEJO_TIMEOUT_SECONDS=10
|
|
REPO_MANAGER_FORGEJO_RETRIES=2
|
|
REPO_MANAGER_PROJECTION_PAGE_SIZE=100
|
|
REPO_MANAGER_PROJECTION_MAX_SNAPSHOTS=4
|
|
```
|
|
|
|
The Forgejo token is optional for public repositories and required for private
|
|
repositories. It must have only `read:repository`; mount it from the platform
|
|
credential path rather than putting it in an environment value, Git, or logs.
|
|
The cursor secret may be omitted for a single-replica runtime, in which case a
|
|
fresh process-local key is generated and in-flight cursors expire on restart.
|
|
Start the API with:
|
|
|
|
```bash
|
|
rmgr publisher api --host 0.0.0.0 --port 8020
|
|
```
|
|
|
|
`GET /healthz` is process liveness. `GET /readyz` verifies that configuration
|
|
and the registry are usable. When `REPO_MANAGER_API_TOKEN` is set, the
|
|
projection route requires the matching bearer token.
|
|
|
|
## Snapshot and failure semantics
|
|
|
|
A first-page request observes the complete registry into an immutable in-memory
|
|
snapshot. Repositories are ordered by registrar UUID. Subsequent page cursors
|
|
carry snapshot ID, offset, and page size protected by HMAC-SHA256. Only a small
|
|
bounded set of in-flight snapshots is retained; an invalid, tampered, or
|
|
expired cursor returns `409`.
|
|
|
|
For each repository the publisher reads metadata, resolves the default branch
|
|
to an exact commit SHA, and then reads `.repo-classification.yaml` at that SHA.
|
|
Missing/private repositories, invalid classifications, or unavailable
|
|
revisions are emitted as bounded error diagnostics. Hub-core rejects any such
|
|
transfer and keeps the last accepted generation, so a partial observation
|
|
never becomes the active navigation projection.
|
|
|
|
## Hub-core client
|
|
|
|
Configure the hub-core runtime with:
|
|
|
|
```text
|
|
HUB_CORE_REPO_MANAGER_BASE_URL=http://repo-manager:8020
|
|
HUB_CORE_REPO_MANAGER_API_TOKEN=<same-optional-bearer-token>
|
|
HUB_CORE_REPO_MANAGER_TIMEOUT_SECONDS=10
|
|
HUB_CORE_REPO_PROJECTION_REFRESH_SECONDS=300
|
|
```
|
|
|
|
Hub-core refreshes once at startup and then on the configured interval. A
|
|
failed refresh marks the dependency stale while preserving the last accepted
|
|
generation. Setting the refresh interval to `0` disables the background loop.
|
|
|
|
## Verification
|
|
|
|
```bash
|
|
make test
|
|
make publisher-snapshot \
|
|
REGISTRY=~/.repo-manager/repository-registry.yaml \
|
|
CURSOR_SECRET='<runtime-secret>'
|
|
```
|
|
|
|
The workstation conformance accepted all 123 local classifications. Forgejo
|
|
conformance resolves 114 public repositories without credentials and correctly
|
|
rejects the nine private `rapp-*` sources until a least-privilege source-read
|
|
token is mounted. No State Hub classification table is read at runtime.
|