fix(usage): let an operator clear a participation the collector never accepted
Probing the live collector to settle the delete-sequence question turned up something else: usage.picpeak.app answers a valid usage.v2 registration with INVALID_PACKET while the identical v1 flow is accepted. It does not speak v2 yet — which the deployment notes already require, but the consequence of getting that order wrong was worse than "reports do not send". Opting in to v2 against a v1-only collector left the installation stuck. Registration was refused, so nothing existed at the collector at all; the row sat in activation_pending, disable moved it to deletion_pending, retry was futile forever, and enable refused because the row was not `disabled`. The abandon hatch added earlier did not apply: it was gated on SIGNING_KEY_UNREADABLE. So the most harmless possible failure — nothing registered anywhere — was the one an operator could not clear. The gate is now the property that actually matters: a participation the collector has provably never accepted (sequence 0, no receipt) with a failing delivery can be discarded, from activation_pending as well as deletion_pending. Its receipt records `never-registered` rather than an unconfirmed deletion, because nothing remote exists to be unsure about. A participation the collector *did* accept keeps the old narrow gate and its explicit warning — clearing local state while the collector still holds reports must stay a deliberate, warned-about act. A collector that rejects a registration or a deletion outright now reports SCHEMA_NOT_ACCEPTED instead of DELIVERY_FAILED, and the settings page says the collector does not accept this report version yet. Retrying cannot fix that, and sending the operator to look for a network fault they do not have was wrong. Verified end to end against the live collector: v2 opt-in reports SCHEMA_NOT_ACCEPTED, the exit is offered immediately, the receipt says never-registered, and joining again on v1 registers, reports and withdraws with a collector-confirmed deletion.
This commit is contained in:
+14
-1
@@ -77,7 +77,20 @@ state. It erases the local identity, key material and markers and records an
|
||||
abandonment receipt marked `collector-unconfirmed`: the collector was never
|
||||
told, so it keeps the reports already accepted, and the receipt says so rather
|
||||
than claiming a deletion that did not happen. Participation can be started
|
||||
again afterwards with a fresh identity. Keys live in a dedicated database
|
||||
again afterwards with a fresh identity.
|
||||
|
||||
The same exit covers the other way a participation can become impossible to
|
||||
finish: a collector that rejects the packet outright. Opting in to usage.v2
|
||||
against a collector that still only speaks usage.v1 — the deployment order
|
||||
this document warns about above — is answered with `INVALID_PACKET`, which is
|
||||
surfaced as `SCHEMA_NOT_ACCEPTED` rather than a generic delivery failure,
|
||||
because retrying cannot resolve it. Nothing is registered in that case, so
|
||||
**Discard local identity** is offered immediately and its receipt records
|
||||
`never-registered` rather than an unconfirmed deletion. The exit is never
|
||||
offered while a participation the collector *did* accept could still be
|
||||
deleted remotely; that case keeps the explicit warning.
|
||||
|
||||
Keys live in a dedicated database
|
||||
table, not the generic readable settings. A random mode-0600 file at
|
||||
`getStoragePath()/usage-instance.key` binds the database to its local storage.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user