OverviewFilesCommitsIssuesDocsReleasesPeers

hyper-social commits / 1511fa7

docs: mark the URI/room reconciliation done, and what it leaves downstream
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
1511fa72c8e4b8eb406b812535ec439d2a43baa9
by plankatron <fleeky@gmail.com> · 2026-09-05T19:54:36.000Z

Changed files (2) +100 -19

docs/ATPROTO-P2P-BRIDGE.md +91 -13
……@@ -7,6 +7,14 @@ blocks. **This** doc is the deeper architecture: build the real thing
77sync in a **little-heap** way, and treat bsky as *one network to bridge
88to at the edge* — not the home.
99
10> ⛔ **SUPERSEDED IN PART — 2026-08-31.** §1's thesis ("adopt AT Proto's *data
11> model and lexicons*") was the decision that made atproto favela's CANONICAL
12> P2P path. That is now reversed: **the canonical record is a markdown
13> document, and atproto + ActivityPub are both projections derived from it.**
14> atproto's machinery stays — at the BRIDGE/RELAY layer, which is where this
15> doc is still correct. See `favela-markdown/spec/design.md` and
16> `favela-web/spec/record-vocabulary.md` §0.
17
1018Status: **design / research synthesis** (2026-06-19). Nothing here is
1119built yet. Several entries correct earlier assumptions — see
1220[Corrections](#corrections-things-that-look-true-but-arent).
……@@ -93,22 +101,38 @@ The PLC directory is being spun out to a neutral Swiss association +
93101gaining a mirroring API; we can also mirror it locally for our own
94102reads.
95103
96### The handle is the stubborn part (a *separate* hostname problem)
104### Handles — AUTHORITATIVE (settled 2026-07-01; stop re-deriving this)
97105
98A handle must be a **hostname** — paths are illegal, one handle per
99account (upstream rejected multi-handle, [#2206]). So per-user *verified
100pretty* handles fundamentally need a hostname each:
106Handle resolution returns the account's **specific DID** via one of two
107methods ([handle spec](https://atproto.com/specs/handle); the resolver tries
108DNS first, then HTTPS). A handle must be a **hostname**, one per account
109([#2206]). The two methods differ ONLY in where that per-user DID is served:
101110
102| Handle option (no subdomain) | bsky accepts? | Verified @name? | Multi-user? |
111| Method | Per-user artifact | TLS cert on handle host? | Scale story |
103112|---|---|---|---|
104| Bare apex `@7rnx.net` | ✅ | ✅ | ❌ one user |
105| Bring-your-own domain | ✅ | ✅ | ✅ (user owns a domain) |
106| Invalid / no handle | ✅ followable by DID | ❌ shows ⚠ | ✅ but all ⚠ |
107| Subdomain `@alice.7rnx.net` | ✅ | ✅ | ✅ — needs wildcard cert **or** cert-free DNS-TXT |
108
109So: **identity without a subdomain is solved (did:plc); a verified
110pretty handle is not** — it's bare-apex (1), BYO-domain, unverified, or
111subdomain (wildcard TLS cert, or DNS-TXT with delegated DNS control).
113| **DNS-TXT** `_atproto.<handle>` = `did=<their DID>` | one DNS TXT record per user | **none** | one DNS write per user (automatable with a DNS API) |
114| **HTTPS well-known** `https://<handle>/.well-known/atproto-did` → plain DID | none (one server answers all by `Host` header) | **wildcard cert** for `*.<domain>` | add users in-app, zero DNS writes |
115
116**Bottom line for us (do not relitigate):**
117- **No wildcard TLS cert is required.** Certless verified pretty handles work
118 via DNS-TXT — *proven live*: `jay.bsky.team` resolves on real bsky with **no
119 A record and no web server/cert at all** (see
120 `scripts/atproto-handle-resolution-test.sh`).
121- **The ONLY required cert is the PDS data host** (`pds.7rnx.net`) — one
122 ordinary single-name cert, NOT a wildcard.
123- **A wildcard cert is OPTIONAL convenience only.** Its sole benefit is
124 onboarding many users without a per-user DNS write; it is how `bsky.social`
125 serves `*.bsky.social` (HTTP resolution — bnewbold,
126 [discussion #1661](https://github.com/bluesky-social/atproto/discussions/1661)).
127 Skip it for the prototype; adopt it later only if per-user DNS writes become a
128 chore.
129- **did:web path-based remains a dead end** (see Corrections); identity is
130 did:plc and needs no hostname at all.
131
132So: identity (did:plc) needs no hostname; a *verified pretty handle* needs a
133hostname each but **no cert** via DNS-TXT. Options: bare-apex `@7rnx.net`
134(1 user); BYO-domain (user owns it); subdomain `@alice.7rnx.net` via DNS-TXT
135(certless) or the optional wildcard-cert well-known path for hands-off scale.
112136
113137### 7rnx.net facts (verified live)
114138
……@@ -230,6 +254,60 @@ only applies at the optional main-bsky bridge.
230254
231255---
232256
257## 8b. Migration path — stock PDS now, Hypercore PDS later
258
259The Hypercore PDS does **not** have to exist before we federate. Run a
260**stock PDS** first (reference PDS or `millipds`, §10) to get real accounts +
261verified handles live today, then migrate accounts to our Hypercore PDS once it
262passes the fidelity gate. **This is atproto's first-class account-migration
263flow — not a custom hack** ([guide](https://atproto.com/guides/account-migration)):
264
2651. `com.atproto.server.createAccount` on the **new** (Hypercore) PDS, proving
266 control of the existing DID.
2672. `com.atproto.sync.getRepo` (CAR) from the stock PDS →
268 `com.atproto.repo.importRepo` into ours; blobs moved one-by-one via
269 `com.atproto.sync.listBlobs` / `com.atproto.repo.listMissingBlobs`.
2703. Re-point identity: `requestPlcOperationSignature` → `signPlcOperation` →
271 `submitPlcOperation` — a **signed PLC op** updating the DID doc's
272 `serviceEndpoint` (PDS host) + repo signing verificationMethod.
273
274**What does NOT change:** the **DID** (`did:plc:…`) and the **handle**
275(`@alice.7rnx.net`, DNS-TXT). Both bind to the *identity*, not the PDS host — so
276the stock-PDS + wildcard-handle work done now carries over 1:1 and is not
277throwaway. Migration is **per-account and reversible** (migrate one test user,
278migrate back if it misbehaves — no big-bang).
279
280**The gating test (this is the real work, and it's the §3/§9 crux):** migration
281round-trips the repo **through a CAR file** that the relay re-crawls. So the
282make-or-break is whether our Hypercore PDS emits a **byte-exact canonical MST /
283DAG-CBOR / signed-commit** repo that survives `importRepo` and relay
284acceptance. The migration *ceremony* is trivial and proven; **MST fidelity is
285the unproven piece.** Good news: `importRepo` + relay-accept is a clean pass/fail
286harness — validate fidelity by migrating one real account and checking it
287round-trips and re-indexes.
288
289### Deployment topology (local PDS + 7rnx + gateway) — no new risk
290
291The PDS runs **locally** (tabertron); its **public face is `https://7rnx.net`**
292(apex, HTTP-01 cert) via the 7rnx Apache reverse proxy; the **hyperident-gateway
293VPN (10.22.0.0/16) is the internal backhaul** — identical to how pear-git /
294wirecore are already served. The relay only ever talks to `https://7rnx.net`;
295the VPN is invisible to it. Rules:
296
297- **`serviceEndpoint` = the PUBLIC URL** (`https://7rnx.net` or a single-name
298 `https://pds.7rnx.net` — an easy HTTP-01 cert, *not* the wildcard problem),
299 **never a `10.22.0.x` VPN IP** (the relay can't reach it).
300- The PDS wants root-level paths (`/xrpc/*`, `/.well-known/*`) — give it the apex
301 root (`--root-path /`) or its own host so it doesn't collide with `/git`,
302 `/wirecore`.
303- `com.atproto.sync.subscribeRepos` is a **long-lived WebSocket** firehose. Apache
304 already proxies WS (`RewriteRule → ws://`); the one thing to watch is the
305 **alpha gateway's connection stability** (a VPN flap drops the firehose — relays
306 reconnect by cursor, so it's resilient but flapping = indexing lag) and **MTU**
307 on large `getRepo`/CAR pulls.
308
309---
310
233311## 9. Corrections (things that look true but aren't)
234312
235313- **Path-based did:web is NOT valid in AT Proto.** Spec: *"only
docs/SOCIAL-MODEL.md +9 -6
……@@ -154,11 +154,11 @@ imitating a system that cannot do them.
1541542. **The atproto projection must GATHER.** With the repo no longer the source, `bridge:bsky` collects
155155 public rooms into a repo instead of reading one. That inverts hpp's shape and is a larger change
156156 than the encoding it accompanies.
1573. **⛔ It contradicts a decision already taken.** `favela-markdown/spec/interaction.md` §3.4 settled
158 the native URI as `favela://<identity-root>/<collection>/<rkey>`. If the room is the container, a
159 record's address must name the **room**. For a personal room the key is derivable from the
160 identity root, so both can hold — but this is **unreconciled** and §3.4 must not be treated as
161 final until it is (§10 #1).
1573. ~~**It contradicts a decision already taken.**~~ **RECONCILED 2026-09-05.** `interaction.md` §3.4
158 now reads `favela://<roomKey>/<collection>/<rkey>`, with the identity root as the **personal-room**
159 case rather than the general one. Also reconciled: §0.1 (one log → rooms), §4.5 (the computed
160 audience bound dissolves into structure), `design.md` §5.1 (`visibility` is a place, `reach` stays
161 a field), `identity.md` §7.6 (favela-peer is a fission of hpp).
1621624. **Discovery is harder without a global index**, which `AUTO-DISCOVERY.md` and
163163 `ROOMS-ARE-THE-COMPUTER.md` already accept and answer with registry rooms, DM room-shares, DHT
164164 topics and local MI.
……@@ -167,7 +167,10 @@ imitating a system that cannot do them.
167167
168168## 10. Open
169169
1701. **Reconcile the URI with rooms** (§9 #3). Blocking for `interaction.md`.
1701. ~~**Reconcile the URI with rooms**~~ **DONE 2026-09-05** (§9 #3). Still open downstream:
171 `record-vocabulary.md` §3/§5 (hyper-social #57 B1–B3) is now a room-model rewrite as well as a
172 `visibility`/`reach` rename, and the store layout is still a flat `records/<collection>/<rkey>`
173 per DID with no room segment.
1711742. **Retention as a room property** (§6) — what the vocabulary is, and who may set it.
1721753. **Cross-room identity of one record.** A post quoted into another room: one record with two
173176 addresses, or two records with an alias edge? The alias mechanism exists (`interaction.md` §3.3).