# Follow-on Cure finding — the participant-designation clear path (sanitized)

_Source: `system/cure/docs/EPP_T3_SWEEP_RESULTS.md`. Client-identifying data redacted: the synthetic
test tenant identifier and the production hostname are replaced with placeholders; one unrelated,
still-unmerged finding is omitted (see the manifest redaction record). The mechanism below is retained
because it is the evidence._

After the build merged, Cure exercised the **running** external-participant surface — not the branch
reports — against the deployed CrewOS production surface, using a **synthetic test tenant only**
(`<synthetic-test-tenant>`). The sweep drove 204 capability-grant-denial cells; the boundary held on
every drivable cell (0 boundary failures).

## EPP-01 — a durable designation with a write path and no clear path — RESOLVED

The follow-on work surfaced a real gap in the external-participant portal:

- A participant could be given a durable "rung-3" designation, intentionally independent of any single
  grant's lifecycle. The four designation triggers had a **write path but no clear path** — an owner
  could *move* an assignment but never *remove* one.
- **Fix:** ship the missing inverse operation — `clear_participant_designation_atomic` (a
  security-definer, service-role-only, account-fenced, in-transaction-audited RPC), a
  `GET` + `DELETE /api/capabilities/designations` endpoint pair, and a per-row Clear control, swept
  across all four designation sites.
- **Re-verified end-to-end on the deployed surface:** issue a resource-scoped grant → designation
  stamped; revoke the grant → designation unchanged (durable by design); call the clear endpoint →
  `200 {ok:true, cleared:true}`; re-read the column → `null`, cleared.

**A contract detail worth keeping** (it cost a wasted probe): the endpoint's `GET` reads query
parameters while `DELETE` reads the JSON body — a `DELETE` sent with query params returns a `400` that
*looks* like the endpoint rejecting a valid request but is really a client-side contract mismatch.

## Why this matters as evidence

The construction result did not disappear at merge. It remained subject to running-system verification
against the deployed surface, that verification found a real behavioural gap in a shipped capability, and
the gap was closed with the authorization boundary enforced in the database rather than the UI.
