From e47346da61d5cddbfd74f41e0af33c2050cd4a03 Mon Sep 17 00:00:00 2001 From: Bretton Date: Wed, 19 Aug 2026 21:38:42 -0700 Subject: [PATCH] docs: close the three chunk-2 contract-level doc criticals MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - federation.json (the shape Coves' settings UI writes against) promised that both deleteRemote paths restore the default-on state under the same identity — false since 17d: the destructive purge tombstones the actor and setEnabled refuses re-enablement forever. The description now states the irreversibility and tells a UI to present deleteRemote as permanent; the soft-tier re-enable promise is kept, scoped to the soft tier. MANIFEST.sha256 regenerated for the one file. - README's opt-out section said the consumer records deleteRemote intent "but does not act on it until task 17's destructive tier is wired" — contradicting its own CONSUMER_ENABLED row two sections up. It now describes the wired tier and the refused re-enable. - README's host-router paragraph claimed bare IPs reach the bridge; the router 421s public IP literals by design (isServiceHost admits only loopback) — a security-posture doc asserting the opposite of the dedicated test. Reworded to loopback-only with the 421 stated. Co-Authored-By: Claude Opus 4.8 --- README.md | 23 +++++++++++--------- lexicons/MANIFEST.sha256 | 2 +- lexicons/social/coves/bridge/federation.json | 2 +- 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 6191649..b0934d3 100644 --- a/README.md +++ b/README.md @@ -603,12 +603,14 @@ ABSENCE means enabled and it only ever exists to turn federation down. When enforces it: `enabled: false` is a **soft disable** — the actor stops resolving via WebFinger and stops delivering, while its actor document and already-federated references stay intact. Adding `deleteRemote: true` escalates -to the destructive tier (ask peers to delete the user's federated content — -irreversible on their side); the consumer **records** that intent in -`federation_prefs` but does not act on it until task 17's destructive tier is -wired, so the request survives a crash and is honored once that seam lands. -Deleting the record, or writing `enabled: true`, restores the default under the -SAME actor identity: the local part is frozen at creation and never re-derived. +to the destructive tier, which **is wired** (task 17d): the bridge sends +`Delete{Person, removeData: true}` to every inbox that ever received the +user's content, tombstones the actor (410), and stamps the identity purged — +irreversible on both sides. For a **soft** opt-out, deleting the record or +writing `enabled: true` restores the default under the SAME actor identity +(the local part is frozen at creation and never re-derived); after a +destructive purge, re-enablement is **refused** — the tombstoned identity +never federates again. With `CONSUMER_ENABLED` off (the default), nothing reads the record and federation stays on for every minted actor — the lexicon is still published so Coves' settings UI can write against a stable shape ahead of the switch. @@ -638,10 +640,11 @@ Lemmy edit that rebuilds a record carries an existing `bridgedStats` forward. Coves users get ActivityPub identities of their own, served on `AP_USER_ORIGIN` — a **second origin on the same listener**, distinct from the bridge's `BRIDGE_HOSTNAME` surface. A `Host` router splits the two: the bridge -hostname and its bridged-handle subdomains (plus `localhost`, bare IPs, and an -absent `Host` — container healthchecks) reach the bridge; the user origin's own -`Host` reaches the user surface; anything else is refused with **421 Misdirected -Request** unless `AP_HOST_FALLTHROUGH_DEV` is on. When both names resolve to one +hostname and its bridged-handle subdomains (plus `localhost`, **loopback** IPs, +and an absent `Host` — container healthchecks) reach the bridge; the user +origin's own `Host` reaches the user surface; anything else — including a +public bare-IP `Host`, which names no configured surface — is refused with +**421 Misdirected Request** unless `AP_HOST_FALLTHROUGH_DEV` is on. When both names resolve to one authority (the dev default, `localhost:8091`), the split falls back to the path: the user surface answers first and its 404s fall through to the bridge. diff --git a/lexicons/MANIFEST.sha256 b/lexicons/MANIFEST.sha256 index c1051cb..bdb7a2c 100644 --- a/lexicons/MANIFEST.sha256 +++ b/lexicons/MANIFEST.sha256 @@ -21,7 +21,7 @@ d26df0b986f1e21b2c13c1905c60257ae19e79e812a474b6d032c083939eff1c social/coves/a d3e077e34c9b9ccd8a8892148fe4ce7ab1de65873250a8906aec510d040bfa4c social/coves/aggregator/revokeApiKey.json 0ca7c339793fc8063a312bf39619983d98414fba498b05fee92c135c7ebea0fd social/coves/aggregator/service.json d688327a711491aeb58b75187f468f213d270adad0c0ca59b96fbef0229cd3f4 social/coves/aggregator/updateConfig.json -5a0ee9495bb2c0949f960a1d080af9f5f23cf696aea72187e02cdbeedd069151 social/coves/bridge/federation.json +5aced9b10f4dbc9d540e47ab9b671dd50b7d553c5d3ae8714a0adb91d5d2d726 social/coves/bridge/federation.json 020b4a33837455e17e1b0e258304f11241931d14929be099f33ca67a88fc2f49 social/coves/bridge/getVoteAggregates.json 94ef1e9a8c6c879697a787f53a48ebeed7edc3a05a90926991667df5a67008f5 social/coves/community/acceptance.json 88fb6259698d0097995200ed5d3a7887165f9cd29907c1c60880150c6568aebf social/coves/community/block.json diff --git a/lexicons/social/coves/bridge/federation.json b/lexicons/social/coves/bridge/federation.json index 48fe4db..e16088b 100644 --- a/lexicons/social/coves/bridge/federation.json +++ b/lexicons/social/coves/bridge/federation.json @@ -4,7 +4,7 @@ "defs": { "main": { "type": "record", - "description": "A Coves user's ActivityPub federation preference, read by the Tidepool bridge. This record is an OPT-OUT: federation is on by default and its ABSENCE means enabled, so the record only ever exists to turn federation down. enabled=false is a soft disable — the user's AP actor stops resolving via WebFinger and stops delivering, while the actor document and its already-federated references stay intact. Adding deleteRemote=true escalates to the destructive tier, asking peers to delete the user's federated content. Re-enabling is either deleting this record or writing enabled=true; both restore the default-on state under the SAME actor identity, because the local part is frozen at creation and never re-derived.", + "description": "A Coves user's ActivityPub federation preference, read by the Tidepool bridge. This record is an OPT-OUT: federation is on by default and its ABSENCE means enabled, so the record only ever exists to turn federation down. enabled=false is a soft disable — the user's AP actor stops resolving via WebFinger and stops delivering, while the actor document and its already-federated references stay intact. Adding deleteRemote=true escalates to the destructive tier, asking peers to delete the user's federated content — IRREVERSIBLE: once the purge runs, the actor is tombstoned and re-enablement is refused forever; a UI offering deleteRemote must present it as permanent. After a soft disable only, re-enabling is either deleting this record or writing enabled=true; both restore the default-on state under the SAME actor identity, because the local part is frozen at creation and never re-derived.", "key": "literal:self", "record": { "type": "object", -- 2.51.2