specs/TrustServiceOnboarding.md defines the mechanism: a Phase Manifest file is committed to the declaring repo (durable, independently foldable forever) and separately registered with the hosted service; once registered, the Ledger's live authoritative copy is the hosted service only, not a second competing file. Licensor token bootstrapping is explicitly out of scope here (a WP-0008-T01 governance action). scripts/trf_onboard.py: a dependency-light CLI (stdlib urllib + target_revenue.validation only, no FastAPI/psycopg needed to onboard a Phase) with validate/register-phase/append-entry/status subcommands. The Licensor token is read only from a named environment variable, never accepted as a literal argument. tests/test_trf_onboard.py (4 tests, no network/Docker) proves invalid-manifest and missing-token-env cases fail before any HTTP attempt, by monkeypatching the request function to raise if called. tests/test_onboarding_hosted.py (1 Docker-gated test) runs an actual uvicorn server on a real socket and drives the full register -> append -> status round trip through the CLI as an external repo would invoke it.
7.1 KiB
Trust Service Onboarding: Multi-Repo Registration Mechanism
Status: Draft v0.1
Date: 2026-07-29
Workplan: workplans/TREV-WP-0006-trust-service-implementation.md T07
Primary artifacts: specs/PhaseManifestSpecification.md, specs/TargetLedgerSpecification.md, specs/TrustServiceProductRequirementsDocument.md, docs/adr/ADR-0002-hosted-trust-service-stack.md, scripts/trf_onboard.py
Scope note: this document defines the mechanism by which any repo
registers a Phase against a running hosted Trust Service instance. It does
not select which repos or Phases go first — that is
workplans/TREV-WP-0008-governance-and-pilot-rollout.md T02 (repo/Phase
survey) and T03 (draft pilot manifests), which use this mechanism rather
than redefine it. It also does not authorize any real Phase to go live —
that remains gated behind WP-0008-T05 regardless of how well this
mechanism works.
1. What a repo commits to itself vs. submits to the Trust Service
A recurring confusion this document exists to close: a Phase Manifest is not solely a Trust Service database row. It has two authoritative copies with different roles, and both are required, not just one:
| Artifact | Lives in | Role |
|---|---|---|
Phase Manifest file (e.g. trf/phase-<slug>.json) |
The declaring repo's own version control, committed | The repo's own durable, git-history-backed record of what it declared and when — survives independent of any Trust Service instance's uptime or even existence (TSD §1.2's offline-verifiability property applies here too: this file alone, plus its ledger export, must remain independently foldable forever). |
| The same Phase Manifest, registered | The hosted Trust Service's phase_manifests table (migrations/0001_registries.sql) |
The multi-tenant, queryable, publicly-servable copy other parties (Customers, auditors, Enforcement Partners) read without needing access to the declaring repo at all. |
| Target Ledger entries | The hosted Trust Service's ledger_entries table only |
Per ADR-0002, the Ledger's authoritative live copy is the hosted service once a Phase is registered there — a repo does not also maintain a second, competing ledger file post-registration (that would reintroduce exactly the "which copy is authoritative" ambiguity Stage 0's single-golden-fixture model never had to answer). A repo may keep periodic exports for its own archival/offline-verification purposes (§4 below), but those are copies, not a second source of truth. |
| Extension registrations, Conversion Attestation | The hosted Trust Service, per T03/T06 | Same reasoning as the Ledger. |
Rule of thumb: anything that must exist and remain meaningful even if this Trust Service instance is retired, replaced, or briefly down belongs committed to the repo (the Manifest declaration itself). Anything that must be a single, live, multi-party-queryable authority belongs exclusively in the hosted service once registered (the Ledger).
2. Licensor bootstrapping (out of band, not part of this mechanism)
Before any repo can register a Phase, its Licensor identity must already
be resolved (workplans/TREV-WP-0008-governance-and-pilot-rollout.md T01)
and a row must exist in the licensors table with an issued API token
(migrations/0001_registries.sql). This document assumes that step has
already happened; it is a governance action, not a mechanical one, and is
explicitly out of this task's scope. The token itself must never be
committed to the repo — it is a deployment secret (CI secret store,
environment variable at declaration time), referenced by name in the
repo's own tooling, never by value.
3. Step-by-step mechanism
- Author the Phase Manifest locally, conforming to
specs/PhaseManifestSpecification.mdandschemas/phase_manifest.schema.json, following the shape already established byexamples/phase-001/manifest.json. - Validate offline before doing anything else —
python -m target_revenue.validationequivalent viascripts/trf_onboard.py validate <manifest-path>(wrapsvalidation.validate_phase_manifest, the same check the hosted service itself runs at registration, so a rejection is caught locally with the identical field-by-field diff rather than discovered only via a failed network call). - Commit the Manifest file to the repo before registering it — this preserves a git-history record of intent to declare, independent of whether registration succeeds on the first attempt.
- Register:
scripts/trf_onboard.py register-phase --url <trust-service-url> --token-env <ENV_VAR_NAME> --manifest <path>. Performs the same offline validation as step 2 again (defense in depth — a manifest edited after step 2 but before this step must still be caught), thenPOST /phases. - Append Ledger entries as commercial payments are recognized. In
practice this step is automated by whatever billing/payment pipeline
the product line already uses, not run manually per payment —
scripts/trf_onboard.py append-entry --url ... --token-env ... --phase-id ... --entry <path>is the mechanism that pipeline calls, or a template for it. - Monitor via the public, unauthenticated read endpoints —
scripts/trf_onboard.py status --url ... --phase-id ...(wrapsGET /phases/{id}/metrics) — no token needed for this step, since metrics are public per FR-9/FR-10. - Conversion and Attestation require no onboarding action at all.
Per WP-0006-T06, the moment the ledger fold reaches
Outstanding Target = 0, conversion is already true; the Trust Service publishes the Attestation on first observation. Nothing in this mechanism gates on, waits for, or triggers that separately.
4. Offline verifiability remains intact after hosting
Any party — including the declaring repo itself, independent of the
Trust Service's continued availability — can export a Phase's current
Ledger via GET /phases/{id}/ledger (public) and independently recompute
Outstanding Target with target_revenue.fold.fold_outstanding_target
against the committed Manifest file. This is the same offline-first
property docs/adr/ADR-0002-hosted-trust-service-stack.md and
specs/TrustServiceProductRequirementsDocument.md §3 require the hosted
service to preserve, not a new guarantee invented for onboarding — this
section just makes explicit that a repo can exercise it as part of its own
routine (e.g., a periodic CI job that exports and re-verifies), not only a
theoretical possibility.
5. Explicit non-goals
- Selecting which of
coulomb-loop,net-kingdom,helix-forge, or arailiance-*repo registers first, or which Milestone Release qualifies —workplans/TREV-WP-0008-governance-and-pilot-rollout.mdT02/T03. - Resolving Licensor identity — WP-0008-T01.
- Authorizing any registration performed via this mechanism to bind real money or a real License header change — WP-0008-T05, unaffected by this mechanism existing or working correctly.
- A CI/CD template for automated payment-pipeline integration — a reasonable future deliverable once a real pilot Phase's billing pipeline is known, not invented speculatively here.