target-revenue/specs/TrustServiceOnboarding.md
tegwick ee4cf14cbc Define and implement multi-repo onboarding mechanism (WP-0006-T07)
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.
2026-07-29 22:00:34 +02:00

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

  1. Author the Phase Manifest locally, conforming to specs/PhaseManifestSpecification.md and schemas/phase_manifest.schema.json, following the shape already established by examples/phase-001/manifest.json.
  2. Validate offline before doing anything elsepython -m target_revenue.validation equivalent via scripts/trf_onboard.py validate <manifest-path> (wraps validation.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).
  3. 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.
  4. 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), then POST /phases.
  5. 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.
  6. Monitor via the public, unauthenticated read endpointsscripts/trf_onboard.py status --url ... --phase-id ... (wraps GET /phases/{id}/metrics) — no token needed for this step, since metrics are public per FR-9/FR-10.
  7. 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 a railiance-* repo registers first, or which Milestone Release qualifies — workplans/TREV-WP-0008-governance-and-pilot-rollout.md T02/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.