Accept WP-0008-T05 for trsl:phase:info-tech-canon-service-surface (history/260805-T05-GoLive-info-tech-canon.md). Finish WP-0013 remission automation and WP-0014 extension/breach/attestation Control Plane UI. Update SCOPE, README, and pilot-candidate notes for pilot Stage 1.
232 lines
11 KiB
Markdown
232 lines
11 KiB
Markdown
# Phase Lifecycle Use Cases
|
||
|
||
`workplans/TREV-WP-0012-phase-provenance-and-policy-modeling.md` T01.
|
||
Written after using the Control Plane UI (WP-0009-T04) for the first time
|
||
surfaced that the Phase Manifest schema and the UI built on top of it
|
||
don't yet cover several use cases the framework's own normative documents
|
||
already commit to. This document enumerates those use cases systematically
|
||
— **as a map of what exists, what's missing, and what's out of scope by
|
||
design** — before T02–T05 turn any of the gaps into schema or UI
|
||
decisions.
|
||
|
||
This is a documentation-only artifact. It does not itself change any
|
||
schema, code, or UI.
|
||
|
||
---
|
||
|
||
## 1. First Phase ever declared for a repo
|
||
|
||
The common case today: a repo has never had a Phase before, and one is
|
||
declared for its first governed Milestone Release.
|
||
|
||
**Real examples** (`examples/pilot-candidates/*/manifest.json`,
|
||
`specs/PilotPhaseCandidateSurvey.md`): `net-kingdom-local-identity`,
|
||
`railiance-vergabe-teilnahme`, `info-tech-canon-service-surface`. All
|
||
three currently use a `trsl:phase:draft-...` id — none has actually been
|
||
registered against the hosted Trust Service. That's intentional: no real
|
||
Phase go-live is authorized yet
|
||
(`workplans/TREV-WP-0008-governance-and-pilot-rollout.md` T05).
|
||
|
||
**What the manifest captures today**: `milestone_release.name` (a free-text
|
||
label, e.g. `"vergabe-teilnahme-v1 (RAILIANCE-WP-0002/RAILIANCE-WP-0014)"`)
|
||
and `milestone_release.source_revision` (a bare short SHA, e.g.
|
||
`"398b0fe"`). **What it does not capture**: which repo, or which Forgejo
|
||
instance, that revision belongs to. The workplan references embedded in
|
||
the `name` string are the only thing tying a Phase back to its source
|
||
today, and they're prose, not structured data — a human convention, not
|
||
something the schema or the UI can rely on.
|
||
|
||
**Gap → WP-0012-T02** (repo identification fields).
|
||
|
||
---
|
||
|
||
## 2. A successive Phase on a repo that already had an earlier Phase
|
||
|
||
FR-11 (`specs/ProductRequirementsDocument.md`) requires the framework to
|
||
"support multiple independently governed, sequential Phases over a
|
||
software's lifetime, each identifying its base release, included change
|
||
set, Milestone Release, Initial Target, Future License, degeneration
|
||
policy, and ledger." Rule 7 (`specs/TargetRevenueFrameworkCore.md` §4)
|
||
then requires that rights already granted by an earlier converted
|
||
Milestone Release can never be withdrawn or restricted by a later Phase.
|
||
|
||
**None of this is modeled in the schema today.** There is no field
|
||
anywhere in `phase_manifest.schema.json` for "the Phase this one
|
||
succeeds" or "the base release this Phase's change set is measured
|
||
against." A second Phase for the same repo today would look, structurally,
|
||
identical to a completely unrelated repo's first Phase — the only
|
||
difference would be human-readable text in `milestone_release.name`.
|
||
|
||
This matters concretely: `railiance-vergabe-teilnahme`'s candidate manifest
|
||
already names two workplans (`RAILIANCE-WP-0002/RAILIANCE-WP-0014`)
|
||
inside a single Milestone Release's `name` — a preview of exactly this
|
||
use case arriving before the schema was ready for it.
|
||
|
||
**Open question this use case raises, not yet answered**: what does a
|
||
first-ever Phase put in a "base Phase" field that a successive Phase
|
||
would use? A null/absent value works structurally, but the Trust
|
||
Service's fold and validation logic downstream should treat "no prior
|
||
Phase" and "prior Phase exists" as two branches it explicitly recognizes,
|
||
not an accidentally-empty string.
|
||
|
||
**Gap → WP-0012-T02** (repo identification fields, same task — the two
|
||
questions are tightly coupled: "which repo" and "which prior Phase for
|
||
that repo" are really one provenance model, not two).
|
||
|
||
---
|
||
|
||
## 3. Operator registers a Phase; Contributor proposes; Operator/Admin reviews
|
||
|
||
**Already built** (`workplans/TREV-WP-0009-target-revenue-control-plane.md`,
|
||
all four tasks done). Included here for completeness and cross-reference,
|
||
not to redesign it:
|
||
|
||
- Rights model: Viewer / Contributor / Operator / Admin, ordinal via
|
||
`registry.RIGHTS_TIERS`/`has_right()`
|
||
(`specs/TargetRevenueControlPlaneConcept.md` §2's table).
|
||
- Operator+ registers a Phase (`control_plane.register_phase`) and
|
||
appends Development Credit directly
|
||
(`control_plane.append_development_credit`).
|
||
- Contributor submits a proposed entry instead
|
||
(`control_plane.propose_ledger_entry`); Operator+ approves (appending
|
||
under the *reviewer's own* credential,
|
||
`control_plane.approve_proposed_entry`) or rejects
|
||
(`control_plane.reject_proposed_entry`).
|
||
- Every action is recorded in the Control Plane's own audit log
|
||
(`control_plane.record_audit_event`/`get_audit_log`), independent of
|
||
the Trust Service's own signed records, which only ever attest "the
|
||
`binky` tenant acted," never which individual human.
|
||
- UI: `service/control_plane_app.py` + `service/control_plane_templates/`
|
||
(WP-0009-T04).
|
||
|
||
No gap here, no follow-up workplan.
|
||
|
||
---
|
||
|
||
## 4. Remission Credit accrual over time under the active degeneration policy
|
||
|
||
`trsl:policy:linear-longstop-v0` (the accepted v1 norm,
|
||
`specs/OpenQuestions-WorkingDefaults.md` Q7) defines
|
||
`R(t) = T0 × clamp((t − t0)/(tL − t0), 0, 1)`, with discrete
|
||
`remission-credit` ledger entries computed on a published schedule. FR-6
|
||
(`specs/ProductRequirementsDocument.md`) requires this to actually happen.
|
||
|
||
**Nothing in this codebase computes or writes these entries.**
|
||
`fold.py` can *consume* a `remission-credit` entry if one exists in the
|
||
ledger; nothing produces one. This is not a Control Plane UI gap — it
|
||
predates the UI entirely, and was never in scope for WP-0006 (Trust
|
||
Service) either. It surfaced now only because working through this
|
||
use-case list prompted a fuller look at what a Phase's lifecycle actually
|
||
requires end to end, not because anything about the recent UI work
|
||
introduced it.
|
||
|
||
**Gap → `workplans/TREV-WP-0013-remission-credit-automation.md`**
|
||
(its own workplan, not folded into this modeling pass, since it's a
|
||
missing *implementation*, not a missing *decision*).
|
||
|
||
---
|
||
|
||
## 5. Conversion Event fires; Attestation published
|
||
|
||
FR-7 defines the Conversion Event as the objective moment Outstanding
|
||
Target reaches zero, computable from the Manifest + Ledger alone, with no
|
||
Trust Service declaration required (`attestation.py`'s module docstring:
|
||
"a Conversion Event is true the instant the ledger fold first reaches
|
||
Outstanding Target = 0, independent of whether anything ever publishes an
|
||
attestation about it"). `attestation.publish_attestation` is implemented,
|
||
tested, and exposed at `GET /phases/{id}/attestation` — idempotent,
|
||
publish-on-first-observation, never regenerated.
|
||
|
||
**Resolved 2026-08-05** (WP-0014-T03): `phase_detail.html` shows the
|
||
Conversion Attestation (Future License, final credits, ledger checkpoint,
|
||
signature) via idempotent `get_or_publish_attestation` on page load.
|
||
|
||
---
|
||
|
||
## 6. Monetization Extension registration and canonical-status review
|
||
|
||
FR-4 defines the six-field extension contract; `registry.register_extension`
|
||
and `registry.promote_extension_canonical` are implemented and tested.
|
||
Canonicalization is a governance action (`set_extension_status`,
|
||
SECURITY DEFINER, never a plain `UPDATE`) — the same pattern already used
|
||
for credential revocation and proposed-entry review elsewhere in this
|
||
project.
|
||
|
||
**Resolved 2026-08-05** (`workplans/TREV-WP-0014-control-plane-extensions-breach-attestation-ui.md`
|
||
T01, all four tasks finished):
|
||
|
||
- Control Plane UI: `GET/POST /extensions`, Admin promote-to-canonical.
|
||
- Rights (now in `specs/TargetRevenueControlPlaneConcept.md` §2):
|
||
**Operator+** registers; **Admin** promotes to canonical. Trust Service
|
||
`POST /extensions` remains open to any authenticated tenant token —
|
||
Control Plane policy is layered on top.
|
||
|
||
---
|
||
|
||
## 7. Breach/Compliance Record publication
|
||
|
||
FR-10 and License V1C1 §7.4: a Licensor's own breach/termination
|
||
determination, anonymized (Phase + category only) by default, named only
|
||
with an explicit Commercial Use Agreement opt-in.
|
||
`breach_record.publish_breach_event`/`get_breach_records` are implemented
|
||
and tested. Rights tier is Operator+
|
||
(`specs/TargetRevenueControlPlaneConcept.md` §2).
|
||
|
||
**Resolved 2026-08-05** (WP-0014-T02): Control Plane form + list on
|
||
`phase_detail.html`; named disclosure requires explicit CUA-authorization
|
||
affirmation (records the assertion; does not verify CUA text).
|
||
|
||
---
|
||
|
||
## 8. A second Licensor tenant besides `binky` onboards
|
||
|
||
Today, `binky` is the only Licensor identity in every environment (test
|
||
fixtures, the local dev instance, presumably any eventual deployment).
|
||
`registry.create_licensor_identity`/`issue_sub_credential` support a
|
||
second tenant structurally and are exercised in tests, but never in any
|
||
real onboarding flow — there is no "onboard a new Licensor" use case
|
||
documented anywhere, only "issue another credential for the Licensor that
|
||
already exists."
|
||
|
||
**Judged not to need its own workplan** (per the decision recorded in
|
||
`workplans/TREV-WP-0012-phase-provenance-and-policy-modeling.md`'s
|
||
closing section) — this is squarely a governance matter and belongs under
|
||
`workplans/TREV-WP-0008-governance-and-pilot-rollout.md` if and when a
|
||
second real tenant is actually on the table. Revisit that call if it
|
||
turns out to need real design work once that happens, rather than
|
||
speculatively designing it now.
|
||
|
||
---
|
||
|
||
## 9. An external auditor verifies a Phase's evidence package offline
|
||
|
||
FR-8/FR-9: a complete Phase evidence package (manifest, ledger,
|
||
extensions, attestation) can be exported in an open format and
|
||
independently verified — recomputing the fold, checking the Ed25519
|
||
signature chain — **without trusting, or even being able to reach, the
|
||
Trust Service or the Control Plane at all** (NFR-1 determinism/
|
||
reproducibility; `attestation.py`'s own docstring makes the same point
|
||
about conversion status specifically).
|
||
|
||
**This use case has, by design, no Control Plane UI surface.** Recording
|
||
it here explicitly so it doesn't get silently miscounted as "not yet
|
||
built" alongside cases 4–7 above, which *are* real gaps. `fold.py` and
|
||
`hashing.py` are the offline-verifiable surface this use case depends on;
|
||
both are already implemented, tested, and covered by the hosted
|
||
conformance suite (`tests/test_hosted_conformance.py`).
|
||
|
||
---
|
||
|
||
## Summary table
|
||
|
||
| # | Use case | Status |
|
||
|---|---|---|
|
||
| 1 | First Phase for a repo | Done (WP-0015 provenance fields) |
|
||
| 2 | Successive Phase, same repo | Done (WP-0015 `base_phase_id`) |
|
||
| 3 | Register / propose / review (rights model) | Done (WP-0009) |
|
||
| 4 | Remission Credit accrual | Done (WP-0013) |
|
||
| 5 | Conversion Attestation view | Done (WP-0014-T03) |
|
||
| 6 | Extension registration/canonicalization | Done (WP-0014-T01) |
|
||
| 7 | Breach/Compliance Record | Done (WP-0014-T02) |
|
||
| 8 | Second Licensor tenant onboarding | Structurally supported, no onboarding flow — deferred to WP-0008 |
|
||
| 9 | Offline evidence verification | Done by design, no UI needed |
|