--- id: TREV-WP-0012 type: workplan title: "Phase provenance, ledger reference, and degeneration-policy modeling" domain: infotech repo: target-revenue status: finished owner: claude topic_slug: infotech created: "2026-07-30" updated: "2026-08-03" state_hub_workstream_id: "763a31ee-85fe-43d0-9040-1e6fd432601c" --- # Phase provenance, ledger reference, and degeneration-policy modeling Triggered by using the Control Plane UI for the first time (WP-0009-T04): the Phase registration form asked for a bare `source_revision` with no repo attribution, a hand-typed `ledger` URI, and an opaque `degeneration_policy` id with no way to see what it actually specifies. These aren't UI bugs — the Phase Manifest schema (`schemas/phase_manifest.schema.json`) itself doesn't yet carry the structure the UI would need to show any of this properly, and FR-11 (Successive Phases, `specs/ProductRequirementsDocument.md`) already commits the framework to base-release/prior-Phase provenance that the schema has never modeled either. This is a **modeling-only** workplan: it produces documents (a use-cases spec and a discussable spec addendum) and decisions, not schema or UI changes. Implementation follows in later workplans once the addendum is reviewed (T05). ```task id: TREV-WP-0012-T01 status: done priority: high state_hub_task_id: "2871b8ff-b845-4ed4-aaa1-8fdfd1f601b7" ``` **Write the use-cases document**, as its own spec file (not folded into `specs/PhaseManifestSpecification.md`) — working title `specs/PhaseLifecycleUseCases.md`. Cover, systematically, at minimum: 1. First Phase ever declared for a repo (the three real pilot candidates: `net-kingdom`, `railiance-vergabe-teilnahme`, `info-tech-canon`). 2. A successive Phase on a repo that already had an earlier, converted Phase (FR-11) — including what "base release" means when the prior Phase's Milestone Release is itself the base. 3. Operator registers a Phase; Contributor proposes a Development Credit; Operator/Admin reviews (already built, WP-0009 — include for completeness/cross-reference, not to redesign it). 4. Remission Credit accrual over time under the active degeneration policy — note as an open gap for WP-0013, not solved here. 5. Conversion Event fires, Attestation published — note as a UI gap for WP-0014. 6. Monetization Extension registration and canonical-status review — note as a UI gap for WP-0014. 7. Breach/Compliance Record publication — note as a UI gap for WP-0014. 8. A second Licensor tenant besides `binky` onboards. 9. An external auditor verifies a Phase's evidence package offline, without needing to trust or even reach the Control Plane UI (FR-8/FR-9 — call out explicitly that this use case has *no* UI surface by design, so it doesn't get silently forgotten as "not yet built"). **Result:** `specs/PhaseLifecycleUseCases.md` written, covering all nine use cases. Two findings worth flagging beyond the original scope: (a) use case 2 (successive Phases) and use case 1 (first Phase) turned out to share one underlying provenance model rather than being separate concerns, so T02 below covers both together; (b) cross-checking `specs/TargetRevenueControlPlaneConcept.md` §2's rights table while writing use cases 6–7 found that breach-record publication already has a decided rights tier (Operator+) but extension registration/canonicalization does not — that's now recorded as an explicit open question for WP-0014-T01 rather than something to assume while building that UI. ```task id: TREV-WP-0012-T02 status: done priority: high human_accept_required: true human_accepted_by: Bernd human_accepted_at: "2026-07-30" state_hub_task_id: "1d888dc7-360d-4ee5-8f4c-d1173670b0f7" ``` **Decide repo identification and Phase-provenance fields (human gate).** Per direction already given: identity rests on the Forgejo instance ("home hub") plus the repo's own stable id within that instance, *and* the Forgejo service URI and repo name are also retained (not derived) — so a rename or instance move stays repairable rather than silently breaking a Phase's provenance link. Concretely decide and record: - Field names/shape for `milestone_release`: a hub identifier, a Forgejo-internal repo id, the Forgejo service URI, and the repo name (owner/repo slug) — four values, not one string. - Whether this is required or recommended for Stage 0 (precedent: `longstop_at` moved from recommended to required under a working default, `specs/OpenQuestions-WorkingDefaults.md` Q8). - How a successive Phase (use case 2 above) references its base — a `trsl:phase:...` id, and what a first-ever Phase puts there instead (null, or an explicit "no prior Phase" marker — decide which is cleaner for fold/validation logic downstream). - Whether any of this is retroactively backfillable for the three existing pilot-candidate example manifests, or only required going forward. **Result (accepted 2026-07-30):** Grounded against the real Forgejo instance before deciding, not assumed — confirmed live that `forgejo.coulomb.social` assigns every repo a stable numeric id (`target-revenue` is `103`, via `GET /api/v1/repos/coulomb/target-revenue`) that survives renames, and confirmed it has **no** instance-level identity endpoint (`/api/v1/nodeinfo` → 404, `/api/v1/version` returns only a version string) — so unlike the repo id, a hub identifier is necessarily something this project mints, not something Forgejo already provides. Decided: - `phase.milestone_release` gains four **required** fields: `repo_hub` (a stable slug, e.g. `"forgejo-coulomb"`), `repo_hub_uri` (the Forgejo service URL, e.g. `"https://forgejo.coulomb.social"`), `repo_id` (Forgejo's own numeric repo id), `repo_name` (`"owner/repo"` slug). Required immediately, not merely recommended — no grace period, unlike `target_basis`'s current recommended-only status. - `phase.base_phase_id` (optional, `trsl:phase:...` pattern) references a prior Phase for a successive Phase; simply **absent** for a first-ever Phase — no sentinel value, matching how `ledger_entry.schema.json`'s `reverses` is already optional-only-when- applicable. - **Important refinement from the maintainer's own steer**: the `repo_hub` → `repo_hub_uri` mapping is *not* static data checked into this repo. `target-revenue` is the generic framework, not a specific deployment's list of repos it happens to monetize — that mapping is operational data owned by the **hosted Trust Service** (a new table, analogous to `licensor_identities`, auto-populated the first time a hub is seen), never a file in this git repo. A Phase Manifest stays fully self-describing and offline-verifiable regardless (it carries `repo_hub_uri`/`repo_name` directly at registration time, per use case 9) — the hosted table exists purely as an admin/repair convenience if a hub's URI ever needs correcting after the fact, not a validation dependency. - The three existing example manifests will be backfilled — deferred until after T03/T04 and the T05 spec addendum, since the schema change is shared across all three decision tasks and the maintainer's own process (item f, chat 2026-07-30) calls for the addendum to be discussed before any implementation, including this backfill. ```task id: TREV-WP-0012-T03 status: done priority: high human_accept_required: true human_accepted_by: Bernd human_accepted_at: "2026-07-30" state_hub_task_id: "dbbabc02-8694-4e7d-8a15-c626ff72875b" ``` **Decide the degeneration-policy / calculation-model spec-file convention (human gate).** Per direction already given: every policy or calculation model (this includes the Development Effort Calculator's own Candidate A formula, `specs/DevelopmentEffortCalculatorConcept.md`, not just degeneration policies) corresponds to a markdown specification file with a simple, distinct name, an id, and a revision — built on git's own mechanisms (commit hash and/or file path, no new versioning infrastructure). Concretely decide: - Where these spec files live (likely already `specs/*.md` — decide whether a dedicated subdirectory or naming convention is needed so a policy id like `trsl:policy:linear-longstop-v0` maps unambiguously to one file). - What "id and revision, built on git internals" means precisely — e.g. the policy id embeds the file path and a pinned commit hash, or the file's own frontmatter carries an id/revision pair that a human commits to alongside code changes (check how `the-custodian`/state-hub already present read-only reference-documentation views linked by id, per the user's explicit steer to reuse that pattern rather than invent a new one, and follow whichever mechanism is actually in use there). - How the Control Plane UI links a policy id shown next to a Phase to a **read-only** rendered view of that spec file — no in-UI editing, consistent with every other governance-action pattern in this project. - Whether this same convention should also cover the six canonical monetization profiles (`specs/CanonicalMonetizationProfiles.md`) for consistency, or is scoped to degeneration policies and calculators only for now. **Result (accepted 2026-07-30):** Checked the maintainer's specific `state-hub` reference before deciding — it's `dashboard/src/docs/*.md`, built via Observable Framework into static HTML, opened as a standalone page or in a "?" context-help overlay iframe (`dashboard/src/docs/reference.md`). That's a real static-site build pipeline, materially heavier than anything else in this repo. Decided to carry the *spirit* (markdown spec → rendered read-only view, linked contextually from wherever the id appears) without adopting that toolchain, since `target-revenue`'s Control Plane is a lightweight FastAPI+Jinja2 app with no existing build step to hang a static-site generator off of. Decided: - New `specs/policies/` subdirectory, one file per degeneration policy — e.g. `specs/policies/linear-longstop-v0.md` — extracted out of Q7's prose in `specs/OpenQuestions-WorkingDefaults.md` (which stays as the index of *decisions about* policies, not the policies' own content). Each file's frontmatter carries the full versioned policy id (e.g. `policy_id: trsl:policy:linear-longstop-v0@1.0`), so the id→file mapping is explicit and machine-checkable, not merely inferred from the filename. - `specs/DevelopmentEffortCalculatorConcept.md` already conforms as-is — one file, one model, distinct name — no move. Add/confirm an `id`+`revision`-shaped frontmatter field for consistency with the new policy files (there's no `trsl:...` schema id for calculators today, since they aren't referenced by id from inside a Phase Manifest the way `degeneration_policy` is — this is a documentation-traceability convention only, not a new schema value). - Extend the same convention to the six canonical monetization profiles now, in this same pass — a new `specs/profiles/` subdirectory, one file per profile (development, operations, ideation, service, consulting, sponsorship), splitting them out of the shared `specs/CanonicalMonetizationProfiles.md`, even though nothing currently links to a profile by bare id from the UI the way `degeneration_policy` is linked. `id`+`revision` frontmatter, matching the policy files. - "Id and revision, built on git internals" means: the id is the stable policy/profile identifier already used in Phase Manifests today (including its existing `@version` suffix, e.g. `...@1.0`), mapped to exactly one file by naming convention; the revision/audit trail is simply that file's own git history (`git log -- specs/policies/ linear-longstop-v0.md`) — no new versioning table, no pinned-commit scheme, nothing beyond what git already provides for free. - Control Plane UI rendering: a small Python markdown library, one new read-only route (e.g. `GET /reference/policies/{slug}`, and equivalently for profiles/calculators), rendering the spec file's current content server-side at request time. A plain link next to wherever a policy id already appears (`phase_detail.html`, `phase_new.html`) — never in-UI editable, matching every other governance-action pattern already established in this project. As with T02, no files are moved or created yet — `specs/policies/`, `specs/profiles/`, and the new render route are implementation, deferred to after T04 and the T05 spec addendum per the maintainer's own established sequencing (item f, chat 2026-07-30). ```task id: TREV-WP-0012-T04 status: done priority: medium human_accept_required: true human_accepted_by: Bernd human_accepted_at: "2026-08-03" state_hub_task_id: "a1cf0180-2dc7-44bb-a34f-99b5e92f5144" ``` **Decide the ledger's UI treatment (human gate).** Per direction already given: keep the `ledger` field in the schema — not as something the standard Phase view surfaces, but as an internal reference reachable only via an explicit drill-down/details action. This is intentional groundwork for eventually supporting more than one ledger per Phase (federation, `specs/ProductRequirementsDocument.md` NFR-3), not just a display preference. Decide: - What the drill-down actually shows (the raw ledger URI/reference plus a link to `GET /phases/{id}/ledger`'s live data, or something more), and where it lives in the Control Plane's navigation (a "details" link on `phase_detail.html` rather than a top-level field). - Whether the Phase registration form still needs a `ledger` input at all going forward, or whether the Trust Service should compute/assign it automatically now that it is always the ledger's host in Stage 0 — distinct from the schema question of whether the field stays. **Result (accepted 2026-08-03):** - The Phase registration form (`phase_new.html`) drops the `ledger` input entirely. The Trust Service auto-computes and assigns the canonical `/phases/{id}/ledger` reference at registration time — no human ever types it in v0. The schema field itself is untouched by this decision (still present, still federation-ready for a future Phase whose ledger genuinely lives elsewhere) — this is a Control Plane UI simplification, not a schema change, and needs no addendum-level review of its own. - The drill-down view shows only the raw `ledger` reference/URI as stored in the manifest, plus — only when it resolves to this same Trust Service instance — a link to `GET /phases/{id}/ledger`'s live JSON. No new rendering of ledger *data*: `phase_detail.html`'s existing Ledger entries table already covers that and stays exactly as prominent as it is today; this decision only concerns the otherwise- invisible raw reference string, reachable via a small "ledger reference" link/disclosure on `phase_detail.html` rather than a top-level field. All four T02–T04 decisions now feed T05's spec addendum draft. ```task id: TREV-WP-0012-T05 status: done priority: high state_hub_task_id: "152b54a6-08a9-4ced-a5f6-d5638d102900" ``` **Draft the spec addendum** reflecting T01–T04's accepted decisions, for review before any implementation — schema changes (`schemas/ phase_manifest.schema.json`), the policy-spec-file convention, and the Control Plane UI changes it implies. Do not implement anything from this task; it produces a reviewable document only. Once accepted, file the implementation work as its own workplan(s), consistent with how WP-0009 and WP-0010 were split from a single combined plan. **Result:** `specs/PhaseProvenanceSpecAddendum.md` written — six sections covering the schema diff (§1), the `specs/policies/`/ `specs/profiles/` extraction with concrete file lists and frontmatter shapes (§2), the ledger UI change (§3), a new `forgejo_hubs` migration sketch for the hub-registry decision from T02 (§4), the backfill plan for the three example manifests (§5), and a suggested implementation task breakdown (§6) for whatever workplan follows once this addendum is reviewed. **Not yet accepted** — this is the document to discuss before any implementation work is filed or started. All five WP-0012 tasks are now done; this workplan is finished pending that discussion, which happens outside this workplan's own task list. Use cases 4, 6, and 7 above are bigger than a modeling exercise — they are missing implementation, not missing documentation — and are tracked separately rather than folded in here: - `workplans/TREV-WP-0013-remission-credit-automation.md` — use case 4. - `workplans/TREV-WP-0014-control-plane-extensions-breach-attestation-ui.md` — use cases 5, 6, 7. Use case 8 (second Licensor tenant onboarding) is judged small enough to stay under `workplans/TREV-WP-0008-governance-and-pilot-rollout.md` rather than warrant its own workplan — revisit that call if it turns out to need real design work once a second tenant is actually on the table.