diff --git a/plans/abstractions.md b/plans/abstractions.md index 2c12fdcd..5e43ff81 100644 --- a/plans/abstractions.md +++ b/plans/abstractions.md @@ -65,16 +65,26 @@ Anything short → _Watching_ (what's missing) or _Rejected_ (why). ## Watching (real but not yet through the gate) ### W1 · Federation scaffold (merge / ingest / backfill / trust-gate) -- **Consumer count NOW met (4):** `feed/lib/feed/fed.sx` (60L/7 defs), - `search/lib/search/fed.sx` (16L/1), `mod/lib/mod/fed.sx` (145L/19), - `acl/lib/acl/federation.sx` (61L/5). -- **BUT structural identity unverified — and the size spread (16→145 lines) is a red - flag.** search/fed is just relabel+merge of an index; mod/fed is 19 defs; - these may be *superficially* similar (all "federation") not structurally identical. -- **Next pass (highest-value thread):** read all 4 side by side, extract the common - shape (if any) with file:line evidence — trust-gate? injected transport? merge vs - ingest split? — before this can move to Proposed. Do NOT propose on the name alone. -- **Home when ripe:** `fed-sx` (NOT lib/guest). +- **FAILS the structural-identity gate (deep-dived 2026-06-06, all 4 read).** Consumer + count is met (4) but they are *superficially* similar, not structurally identical — + the federated unit and merge op differ fundamentally: + + | Subsystem (file) | Federated unit | Merge op | Trust gate | Injected transport | + |---|---|---|---|---| + | feed (`fed.sx:14,18,40`) | activity streams | dedupe by `(actor verb object)` | none (visibility via `permit?` separately) | `send-fn`, `fetch-fn` | + | search (`fed.sx:8`) | inverted indices | relabel DocId `peer*1000+local` + union posting lists | none | none (pure merge fn) | + | mod (`fed.sx:11-14,99`) | moderation decisions | advisory-list vs applied-list; bind iff `mod/trusted?` | **yes — runtime list** `mod/trusted? peer scope` | mock outbox / `fed-send!` | + | acl (`federation.sx:43,56`) | Datalog delegate facts | pull facts, gate by `trust`/`level_covers` rule, re-saturate | **yes — Datalog rule** at query time | `transport` dict | + +- **The ONLY real commonality is the injection seam**, not extractable code: every one + says "the real transport is `fed-sx`'s job; inject `send-fn`/`fetch-fn`/`transport`/ + outbox and mock it in tests." That is an architectural *convention the fleet already + follows*, and the trust gate (where present) is implemented two incompatible ways + (runtime list vs declarative rule). No shared merge, no shared trust mechanism. +- **Disposition:** do NOT extract a shared "federation lib." When `fed-sx` ships its + real transport, these 4 become its *consumers* (wiring `send-fn`/`fetch-fn`/`transport` + to it) — that work belongs to each subsystem's loop + the `fed-sx` loop, not a + cross-cutting extraction. Stop re-proposing on the shared name. Home: `fed-sx`. ### W2 · Per-viewer visibility / permission filter - **2 shipped consumers, same shape** — `filter `: