| … | … | @@ -118,6 +118,101 @@ discovery key — the topology is proven, not hypothetical. |
| 118 | 118 | That makes retention a **room property**, and it must be in the model rather than discovered later. |
| 119 | 119 | This is the one place §3's "six primitives and no more" takes on a modifier. |
| 120 | 120 | |
| 121 | ## 6.5 Retention — the one room property beyond membership |
| 122 | |
| 123 | Tempo (§6) makes retention a room setting: chat wants a bounded window, posts want durability. It |
| 124 | belongs in the room's custom metadata (`ROOMS-ARE-THE-COMPUTER.md`'s `_hs:room-meta` convention) and |
| 125 | is set by admins, like any other room config. |
| 126 | |
| 127 | ⛔ **Retention must TOMBSTONE, never silently drop.** Dropping a record's bytes while its pointer is |
| 128 | still converged produces exactly the state the signer's forward-only gate treats as *"pointer |
| 129 | present, bytes unreplicated — behind — SKIP"*: the chain stalls rather than advancing. A retention |
| 130 | policy that deletes without a tombstone would freeze signing for the whole room, and the freeze would |
| 131 | look like a replication problem. |
| 132 | |
| 133 | Absence is ambiguous in a replicated log; expiry has to be **positive evidence** for the same reason |
| 134 | deletion is. |
| 135 | |
| 136 | ## 6.6 Media — bytes are already solved; VARIANTS are the open question |
| 137 | |
| 138 | **Peer-to-peer media needs nothing new.** Blobs live in hyper-overlay, content-addressed, and any |
| 139 | peer holding the bytes can serve them. No downsampling, no negotiation, full fidelity. |
| 140 | |
| 141 | **Downsampling is a BRIDGE concern.** It exists because other networks have ceilings we do not. That |
| 142 | places it exactly where `strip()` is: **downsampling is to media what the strip is to text** — a |
| 143 | lossy, pure, boundary-time projection that must report what it lost (`library.md` §4). Not an |
| 144 | authoring decision, and not stored. |
| 145 | |
| 146 | ⚠ **This refines `design.md` §8 #1**, which says media policy *"is an AUTHORING-time decision of the |
| 147 | native record"*. That is right about *choosing what to attach* and wrong about *fidelity*: fidelity is |
| 148 | per-target, and baking a target's ceiling into the canonical record is the shape this whole model |
| 149 | exists to refuse. |
| 150 | |
| 151 | ### 6.6.1 A variant is not a duplicate — it is an EDGE |
| 152 | |
| 153 | The worry is that storing a downsampled copy breaks content-addressing. It does not, and the reason |
| 154 | is worth stating precisely: |
| 155 | |
| 156 | **Dedup was never "one file per logical image." It was "identical bytes stored once."** A downsample |
| 157 | has different bytes, so it is a different object by definition. What is actually lost is the |
| 158 | *automatic* knowledge that two objects are the same picture at different fidelities — and that is a |
| 159 | relation, which this model already has a primitive for. |
| 160 | |
| 161 | ``` |
| 162 | (variant, variant-of, original) + the parameters that produced it |
| 163 | ``` |
| 164 | |
| 165 | Exactly the shape of an `alias` edge (`interaction.md` §3.3): alias says *two names, one thing*; |
| 166 | `variant-of` says *two byte-sets, one image at different fidelities*. Same mechanism, and it makes |
| 167 | the relation explicit and inspectable instead of implicit and lost. |
| 168 | |
| 169 | ⛔ **A variant records WHO derived it.** §8's rule — *"never re-encode a record you did not author"* — |
| 170 | cost two of wj62's posts. A bridge-produced downsample is a derived artifact and must never be |
| 171 | attributed as the author's bytes; the `variant-of` edge carries the deriver. That keeps the wj62 |
| 172 | failure class out of media. |
| 173 | |
| 174 | ### 6.6.2 Three tiers, and the one we cannot have yet |
| 175 | |
| 176 | | | when | cost | |
| 177 | |---|---|---| |
| 178 | | **derive on demand** | bridges | CPU per delivery; the bridge must hold full bytes. **The default** — no storage concept at all | |
| 179 | | **stored variant + `variant-of` edge** | a peer that genuinely cannot hold or fetch full fidelity (a phone) | a second blob, explicitly related. Dedup intact | |
| 180 | | **sparse fetch of one blob** | *the shape we would want* | ⛔ **not expressible today** | |
| 181 | |
| 182 | The third is the elegant one: a progressive format lets a byte prefix decode as a lower resolution, |
| 183 | so one blob serves every fidelity with no variants at all. **hyper-overlay blocks it** — it addresses |
| 184 | a file by a whole-file blake2b `contentHash`, so a prefix cannot be authenticated against the |
| 185 | registered oid. Getting there needs per-blob merkle verification, which the overlay does not have. |
| 186 | |
| 187 | Worth recording as the thing to want, because it would delete tier two entirely. |
| 188 | |
| 189 | ## 6.7 Moderation — rooms and edges, no new primitive |
| 190 | |
| 191 | `COMMUNITY-MODERATION.md` already answers this, and it lands on the room model exactly. |
| 192 | |
| 193 | - **Roles are keet-core roles.** admin / moderator / member / read-only. No new permission system. |
| 194 | - **Listings, not content.** A community moderator delists a room from the community; they **cannot** |
| 195 | moderate inside it. Two rooms, two scopes — which is what the room model gives for free. |
| 196 | - **The accountability gap is deliberate.** *"The room admin is a bartender… the community admin is a |
| 197 | neighborhood association — they decide which bars are listed in the directory, they don't enter the |
| 198 | bars."* This is what stops governance becoming surveillance. |
| 199 | - **A room in two communities has two governance contexts.** Federation, not hierarchy. |
| 200 | - **Signals, not enforcement.** A flag is information; each community applies its own context. |
| 201 | *"What's spam in a dev community might be on-topic in a crypto community."* |
| 202 | |
| 203 | **In this model a moderation signal is an EDGE** — `(moderator, flag, room)` with a reason — written |
| 204 | in the moderation room, so **its audience is that room's subscribers by construction**. Subscribing to |
| 205 | another community's signals is joining their room. Delisting is a tombstone on a listing record. |
| 206 | |
| 207 | Nothing here needs a mechanism the six primitives do not already have, which is the strongest |
| 208 | evidence so far that the primitive set is the right size. |
| 209 | |
| 210 | ⚠ **`flag` projects asymmetrically**, and the asymmetry is semantic rather than technical: atproto has |
| 211 | a real equivalent — a signed `com.atproto.label`, which we already emit |
| 212 | (`atproto-room/lib/label-room.js`, `label-signer.js`) — while AS2's `Flag` is a *report to the origin |
| 213 | server's moderators*, which means something different and must not be conflated with a shared signal. |
| 214 | So `flag` → atproto label; `flag` → fediverse **nothing**, with a `loss[]` entry. |
| 215 | |
| 121 | 216 | ## 7. Translating outward |
| 122 | 217 | |
| 123 | 218 | Bridges map *our* model onto theirs. The mapping quality is not uniform, and the asymmetry is |
| … | … | @@ -171,14 +266,15 @@ imitating a system that cannot do them. |
| 171 | 266 | `record-vocabulary.md` §3/§5 (hyper-social #57 B1–B3) is now a room-model rewrite as well as a |
| 172 | 267 | `visibility`/`reach` rename, and the store layout is still a flat `records/<collection>/<rkey>` |
| 173 | 268 | per DID with no room segment. |
| 174 | | 2. **Retention as a room property** (§6) — what the vocabulary is, and who may set it. |
| 269 | 2. ~~**Retention as a room property**~~ **RESOLVED 2026-09-05** — §6.5. Room metadata, set by admins, |
| 270 | and it must tombstone rather than drop. |
| 175 | 271 | 3. **Cross-room identity of one record.** A post quoted into another room: one record with two |
| 176 | 272 | addresses, or two records with an alias edge? The alias mechanism exists (`interaction.md` §3.3). |
| 177 | 273 | 4. **Room-per-audience proliferation.** Does every follower subset become a room, and if so who |
| 178 | 274 | manages them? This is the model's ergonomic risk and it is not addressed. |
| 179 | | 5. **Moderation** — `COMMUNITY-MODERATION.md` is 30KB and has not been read into this model. Room |
| 180 | | roles are the mechanism; *"moderation is shared context, not rules"* is the principle; the |
| 181 | | connection between them is unwritten. |
| 275 | 5. ~~**Moderation**~~ **RESOLVED 2026-09-05** — §6.7. It needs no new primitive: roles are keet roles, |
| 276 | a signal is an edge, delisting is a tombstone. What remains open is the *frustum* view model |
| 277 | (`COMMUNITY-MODERATION.md` §"view frustum", 350 lines) which has not been read into this model. |
| 182 | 278 | 6. **Where governance of a public room lives** when its membership is "anyone". |
| 183 | 279 | |
| 184 | 280 | ## 11. What this does not claim |