Go-live T05 + WP-0013/0014: first Phase and Control Plane completion

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.
This commit is contained in:
tegwick 2026-08-05 16:00:06 +02:00
parent f56d82f09a
commit 3064c0fe0c
18 changed files with 1676 additions and 72 deletions

View file

@ -381,3 +381,202 @@ def test_phase_new_form_has_no_ledger_input(client, credentials):
assert 'name="repo_hub_uri"' in resp.text
assert 'name="repo_id"' in resp.text
assert 'name="repo_name"' in resp.text
# --- WP-0014: extensions / breach / attestation UI -------------------------
def _register_phase(client, phase_id, amount="1000"):
return client.post(
"/phases/new",
data={
"phase_id": phase_id,
"milestone_release_name": "WP-0014 test release",
"source_revision": "abc123",
"repo_hub": "forgejo-coulomb",
"repo_hub_uri": "https://forgejo.coulomb.social",
"repo_id": "103",
"repo_name": "coulomb/target-revenue",
"initial_target_amount": amount,
"currency": "USD",
"future_license": "MIT",
"degeneration_policy": "trsl:policy:linear-longstop-v0@1.0",
"longstop_at": "2027-01-01T00:00:00Z",
},
follow_redirects=False,
)
def test_viewer_can_list_extensions_operator_registers_admin_promotes(
client, credentials
):
ext_id = "trsl:extension:wp0014-test-" + uuid.uuid4().hex[:6]
version = "1.0"
_login(client, credentials["viewer"].token)
resp = client.get("/extensions")
assert resp.status_code == 200
assert "Monetization Extension Registry" in resp.text
# Viewer cannot register
denied = client.post(
"/extensions",
data={
"extension_id": ext_id,
"version": version,
"value_description": "Test extension for WP-0014",
"pricing_method": "fixed-fee",
"allocation_rule": "100% to Development Credit",
"default_rate": "1.0",
"recognition_event": "payment-settled",
"reversal_rule": "Refunds reverse the credit",
"evidence_requirement": "Settled payment reference",
},
follow_redirects=False,
)
assert denied.status_code == 303
_login(client, credentials["operator"].token)
reg = client.post(
"/extensions",
data={
"extension_id": ext_id,
"version": version,
"value_description": "Test extension for WP-0014",
"pricing_method": "fixed-fee",
"allocation_rule": "100% to Development Credit",
"default_rate": "1.0",
"recognition_event": "payment-settled",
"reversal_rule": "Refunds reverse the credit",
"evidence_requirement": "Settled payment reference",
},
follow_redirects=False,
)
assert reg.status_code == 303
assert reg.headers["location"] == "/extensions"
listed = client.get("/extensions")
assert ext_id in listed.text
assert "registered" in listed.text
# Operator cannot promote
op_promote = client.post(
"/extensions/promote",
data={"extension_id": ext_id, "version": version},
follow_redirects=False,
)
assert op_promote.status_code == 303
_login(client, credentials["admin"].token)
promote = client.post(
"/extensions/promote",
data={"extension_id": ext_id, "version": version},
follow_redirects=False,
)
assert promote.status_code == 303
after = client.get("/extensions")
assert "canonical" in after.text
def test_operator_publishes_anonymized_breach(client, credentials):
_login(client, credentials["operator"].token)
phase_id = "trsl:phase:wp0014-breach-" + uuid.uuid4().hex[:8]
assert _register_phase(client, phase_id).status_code == 303
record_id = "trsl:breach:wp0014-" + uuid.uuid4().hex[:8]
resp = client.post(
f"/phases/{phase_id}/breach",
data={
"record_id": record_id,
"case_id": "case-001",
"event_type": "alleged",
"category": "unauthorized-commercial-use",
"event_at": "2026-08-01T12:00:00Z",
"evidence_reference": "confidential:evidence:case-001",
"anonymized": "true",
"named_entitlement_holder": "",
"named_disclosure_authorized": "false",
},
follow_redirects=False,
)
assert resp.status_code == 303, resp.headers
assert resp.headers["location"] == f"/phases/{phase_id}"
detail = client.get(f"/phases/{phase_id}")
assert detail.status_code == 200
assert record_id in detail.text
assert "unauthorized-commercial-use" in detail.text
assert "anonymized" in detail.text
def test_named_breach_requires_cua_authorization(client, credentials):
_login(client, credentials["operator"].token)
phase_id = "trsl:phase:wp0014-named-" + uuid.uuid4().hex[:8]
assert _register_phase(client, phase_id).status_code == 303
# Missing CUA authorization → rejected (flash danger, still redirect)
resp = client.post(
f"/phases/{phase_id}/breach",
data={
"record_id": "trsl:breach:named-fail-" + uuid.uuid4().hex[:6],
"case_id": "case-named",
"event_type": "determined",
"category": "payment-default",
"event_at": "2026-08-02T00:00:00Z",
"anonymized": "false",
"named_entitlement_holder": "Acme Corp",
"named_disclosure_authorized": "false",
},
follow_redirects=True,
)
assert resp.status_code == 200
# Should not show a published named record
assert "Acme Corp" not in resp.text or "named_disclosure_authorized" in resp.text.lower() or "rejected" in resp.text.lower() or "must be true" in resp.text.lower() or "danger" in resp.text.lower() or "flash" in resp.text.lower()
# With authorization → accepted
ok = client.post(
f"/phases/{phase_id}/breach",
data={
"record_id": "trsl:breach:named-ok-" + uuid.uuid4().hex[:6],
"case_id": "case-named",
"event_type": "determined",
"category": "payment-default",
"event_at": "2026-08-02T00:00:00Z",
"anonymized": "false",
"named_entitlement_holder": "Acme Corp",
"named_disclosure_authorized": "true",
},
follow_redirects=False,
)
assert ok.status_code == 303
detail = client.get(f"/phases/{phase_id}")
assert "Acme Corp" in detail.text
def test_attestation_shown_after_conversion(client, credentials):
_login(client, credentials["operator"].token)
phase_id = "trsl:phase:wp0014-attest-" + uuid.uuid4().hex[:8]
assert _register_phase(client, phase_id, amount="100").status_code == 303
before = client.get(f"/phases/{phase_id}")
assert "Not converted" in before.text or "no attestation" in before.text.lower()
client.post(
f"/phases/{phase_id}/ledger",
data={
"entry_id": "trsl:entry:wp0014full" + uuid.uuid4().hex[:6],
"amount": "100",
"currency": "USD",
"recognized_at": "2026-08-01T00:00:00Z",
"evidence_reference": "confidential:evidence:full",
"extension_id": "trsl:extension:development-license",
"extension_version": "1.0",
},
follow_redirects=False,
)
after = client.get(f"/phases/{phase_id}")
assert after.status_code == 200
assert "Conversion Attestation" in after.text
assert "MIT" in after.text # future_license
assert "ledger_checkpoint" in after.text or "Ledger checkpoint" in after.text