diff --git a/docs/explorations/0319_[x]_BLOG_POST_LEGO_FOR_ALL_DATA_ON_THE_WEB.md b/docs/explorations/0319_[x]_BLOG_POST_LEGO_FOR_ALL_DATA_ON_THE_WEB.md new file mode 100644 index 000000000..cf350c99e --- /dev/null +++ b/docs/explorations/0319_[x]_BLOG_POST_LEGO_FOR_ALL_DATA_ON_THE_WEB.md @@ -0,0 +1,681 @@ +# Blog Post: LEGO for All Data on the Web + +> The genius of the 1958 brick was never the brick. It was the coupling. + +## Problem Statement + +The user wants a blog post framing xNet as **LEGO for all data on the web**: +a universal namespace for any and all data that syncs peer-to-peer and +preserves strong access controls and permissions — *you control who and what +gets to play with your legos*. The brief asks three questions the essay must +answer in order: + +1. **What new forms of software, tooling, and interaction does a universal, + composable, permissioned data substrate enable?** +2. **How were we limited by prior siloed, non-composable forms of data on + the internet?** +3. **What limits still remain, even in xNet?** (The honest section — the one + that buys credibility for the other two.) + +The hard constraint is series overlap. The blog already has fourteen essays, +and two of them own adjacent ground: + +- **#10, "The Workshop and the Walled Garden"** owns *moddability* and + capability-scoped third-party code. +- **#11, "The Vault and the View"** owns the *vertical* axis: apps as + disposable views over a durable data substrate, the Codd→Solid→local-first + lineage, and the AI-cheap-views inversion. + +This essay must therefore claim the **horizontal axis**: not "the app is a +view over the data" but "**every datum can snap to every other datum**" — +the connection standard itself. LEGO is the right metaphor precisely because +LEGO's genius is not the brick (any company can mould plastic) but the +**frozen coupling geometry** — the stud-and-tube interface patented on +28 January 1958 — plus the *System of Play*: every set, every theme, every +decade, one interface. A brick moulded in 1958 still snaps to a brick moulded +today. And, crucially for this essay, the metaphor's neglected half: +**clutch power is friction, not weld**. Bricks hold firmly *and come apart +by hand*. That is what permissions are — composability with consent. + +The failure mode to avoid: a breathless "everything connects to everything" +manifesto. The Semantic Web already wrote that one, and §"External Research" +below documents where it went. Every claim needs a repo receipt, and the +limits section needs real teeth. + +## Executive Summary + +- **The essay's spine: the coupling, not the brick.** xNet's answer to "what + is the stud geometry of data?" is concrete and citable: every node has + exactly four universal fields (`id`, `schemaId`, `createdAt`, `createdBy`, + per [docs/specs/protocol/02-data-model.md](../specs/protocol/02-data-model.md)); + every schema lives in one namespace + (`xnet://authority/Name@semver` — the `SchemaIRI`, + [packages/data/src/schema/node.ts](../../packages/data/src/schema/node.ts)); + every mutation is a signed change folded by one merge rule (LWW with a + grinding-resistant tiebreak, + [packages/core/src/lww.ts](../../packages/core/src/lww.ts)); every + access decision runs one authorization algebra declared *on the data + itself* ([docs/specs/protocol/04-authorization.md](../specs/protocol/04-authorization.md)). + Four frozen interfaces. Everything else — schemas, views, apps, agents — + is a brick that snaps onto them. +- **The namespace is genuinely universal, not aspirational.** The + `SchemaIRI` authority can be `xnet.fyi` (the ~60 built-in schema modules: + pages, tasks, CRM, ledger, chat, canvas…), a domain, or *any DID* — + `xnet://did:key:z6Mk…/Recipe@1.0.0` means anyone can mint types without + asking anyone. Identity is `did:key` (self-sovereign), content addressing + is BLAKE3 `cid:`s, and foreign data gets landing schemas + (`ExternalReference`, `feed-item`, importers, the Slack-compat package) so + even other people's silos become bricks. +- **The permissions half is the differentiator.** Prior "LEGO for software" + essays (and prior universal-data attempts) skip the question the user's + brief centres: *who gets to play?* xNet's answer has three interlocking + mechanisms, all data-native: schema authorization blocks with roles, + actions, and deny-wins expressions; `Grant` nodes and UCAN delegation + chains (attenuable capabilities — hand someone three bricks, not the + crate); and E2E encryption where **the ability to decrypt is the access + control** — per-recipient key wraps in + [packages/crypto/src/envelope.ts](../../packages/crypto/src/envelope.ts). + Enforcement happens at the sync boundary, so the rules travel with the + data, not with any app. +- **Question 1 (what it enables) has live receipts:** cross-schema relations + (`relation` properties point at *any* node); sidecars — your private + annotations riding on data you don't own + ([packages/data/src/schema/sidecar.ts](../../packages/data/src/schema/sidecar.ts)); + overlays — extending someone else's schema without permission or forking + ([packages/data/src/schema/extension.ts](../../packages/data/src/schema/extension.ts)); + agents as first-class players via the MCP surface + ([packages/cli/src/commands/mcp.ts](../../packages/cli/src/commands/mcp.ts)) + and capability-scoped connectors + ([packages/plugins/src/connectors/define-connector.ts](../../packages/plugins/src/connectors/define-connector.ts)); + and the user-side network effect: every datum you add makes *all* your + tools better, instead of making one platform's moat deeper. +- **Question 2 (how we were limited) is a documented history**, not + editorialising: mashup-era APIs opened (Flickr 2004) and then slammed shut + once graphs became the asset — Facebook's Friends API (30 April 2015), + Twitter's free API (9 February 2023, ~a week's notice), Reddit's + $0.24/1k-call pricing that killed Apollo (2023). Below the API layer: + Plaid built a company on screen-scraping bank logins because no first-class + data-sharing primitive existed; GDPR Article 20 grants a right to + portability but no format, so "portability" means a ZIP file no other + software can parse. Copy-paste remains the web's only universal connector. +- **Question 3 (remaining limits) is the essay's credibility engine.** Six + honest limits, each with a receipt: reading is copying (no revocation of + what's been seen — clutch power holds, it doesn't imprison); schema + agreement is social, not technical (lenses make disagreement *cheap*, they + don't make coordination free); frozen interfaces have a real maintenance + bill (the protocol-v4 tiebreak change rippled through four conformance + kernels); a generic substrate pays a performance tax the silo never pays + (our own query-perf sagas are the invoice); somebody still hosts the relay + (Moxie's "people do not want to run their own servers" is conceded, hub as + optional relay is the answer, economics still real); and moderation / + discovery in a permissioned p2p world remains per-space and unsolved at + network scale. +- **Recommendation:** ship blog post #15 as **"Clutch Power"** — bricks that + hold *and* come apart — cold-opening on the 1958 patent and a 68-year-old + brick snapping onto a new set, closing on the difference between a weld + and a grip. `.astro` page + `posts[]` entry, tags + `['essay', 'protocol', 'decentralization', 'philosophy']`, authors + `['crs48', 'claude']`, ~14 min read, en-GB, vendored assets only. + +## Current State In The Repository + +### The four frozen interfaces (the essay's "stud geometry") + +| LEGO | xNet | Receipt | +| --- | --- | --- | +| One brick footprint | Four universal node fields: `id`, `schemaId`, `createdAt`, `createdBy` | [docs/specs/protocol/02-data-model.md](../specs/protocol/02-data-model.md) §1; [packages/data/src/schema/node.ts](../../packages/data/src/schema/node.ts) | +| One catalogue of parts | `SchemaIRI = xnet://authority/Name@semver`; authority may be a DID | [02-data-model.md](../specs/protocol/02-data-model.md) §4; `parseSchemaIRI` in [node.ts](../../packages/data/src/schema/node.ts) | +| One way bricks join | Signed, hash-chained `Change` log folded by LWW (+ BLAKE3 tiebreak, protocol v4) | [packages/sync/src/change.ts](../../packages/sync/src/change.ts); [packages/core/src/lww.ts](../../packages/core/src/lww.ts) | +| One rule for whose hands | Authorization declared on schemas/nodes, evaluated identically everywhere, enforced at the sync boundary | [docs/specs/protocol/04-authorization.md](../specs/protocol/04-authorization.md); [packages/data/src/auth/evaluator.ts](../../packages/data/src/auth/evaluator.ts) | + +The protocol spec ([docs/specs/protocol/00-overview.md](../specs/protocol/00-overview.md)) +is normative and layered (L0 primitives → L1 data model → L2 replication → +L3 authorization), with golden vectors in `conformance/vectors/` so an +independent implementation in another language can prove it moulds +compatible bricks — that *is* the System of Play, stated as RFC-2119 +conformance clauses. + +### The namespace, end to end + +- **Identity:** `did:key` over Ed25519 + ([packages/identity/src/did.ts](../../packages/identity/src/did.ts); + type in [packages/core/src/auth-types.ts](../../packages/core/src/auth-types.ts)). + Names are minted, not granted. +- **Content:** `cid:blake3:…` content ids + ([packages/core/src/content.ts](../../packages/core/src/content.ts), + [hashing.ts](../../packages/core/src/hashing.ts)). +- **Nodes:** opaque nanoid ids, ~126 bits + ([packages/data/src/schema/node.ts](../../packages/data/src/schema/node.ts)). +- **Schemas:** `SchemaRegistry` singleton + ([packages/data/src/schema/registry.ts](../../packages/data/src/schema/registry.ts)) + lazy-loading ~60 built-in schema modules from + [packages/data/src/schema/schemas/](../../packages/data/src/schema/schemas/) + — Page, Task, the full CRM set, ledger accounts, Channel/ChatMessage, + Canvas, Map, Meeting. (Blog phrasing: "dozens of built-in schemas"; + the raw registry map holds 168 IRI entries but many are versioned + aliases — don't quote that number.) +- **Property vocabulary** (the stud *types*): `text`, `number`, `relation`, + `person` (a DID), `rollup`, `formula`, `file`, … in + [packages/data/src/schema/types.ts](../../packages/data/src/schema/types.ts). + `relation` is the load-bearing one for the essay: it can point at any node + of any schema — a CRM deal can relate to a chat message can relate to a + canvas. +- **Groups/boundaries:** Spaces (`xnet://xnet.fyi/Space@1.0.0`, + [space.ts](../../packages/data/src/schema/schemas/space.ts)) nest, carry a + `private|unlisted|public` dial, and act as the security boundary the + cascade inherits from. + +### The permissions machinery ("who plays with your legos") + +- **Actions** `read, create, update, write, delete, share, admin`, with + create/update as refinements of write (exploration 0304) — spec + [04-authorization.md](../specs/protocol/04-authorization.md) §1. +- **Roles + expressions:** four role-resolver kinds (`creator`, `property`, + `relation`, `membership`), deny-wins expression AST, presets + (`private()`, `publicRead()`, `spaceCascadeAuthorization()`) in + [packages/data/src/auth/presets.ts](../../packages/data/src/auth/presets.ts). +- **Grants + UCAN:** `Grant` nodes + ([grant.ts](../../packages/data/src/schema/schemas/grant.ts)) with + issuer/grantee/resource/actions/expiry/revocation; UCAN 1.0 delegation + chains in [packages/identity/src/ucan.ts](../../packages/identity/src/ucan.ts). + Attenuation is the "hand over three bricks, not the crate" beat. +- **E2E encryption as read control:** per-recipient X25519 key wraps, + XChaCha20-Poly1305 payloads + ([packages/crypto/src/envelope.ts](../../packages/crypto/src/envelope.ts)); + a `PUBLIC` sentinel recipient unifies the public/private code paths. + For an unauthorised party the brick *physically doesn't snap*. +- **Share links:** the link's private key rides in the URL fragment (never + sent to servers), claimed as a UCAN delegation — + [packages/identity/src/sharing/link-delegation.ts](../../packages/identity/src/sharing/link-delegation.ts). +- **Enforcement point:** the hub authorizes every `subscribe`/`publish` + before relaying ([docs/specs/protocol/03-replication.md](../specs/protocol/03-replication.md) §6; + [packages/hub/src/server.ts](../../packages/hub/src/server.ts)). + +### The composability surfaces (question 1's receipts) + +- **Overlay / sidecar / promote** (exploration 0188): extend anyone's + schema without forking (`ext:` keys, + [extension.ts](../../packages/data/src/schema/extension.ts)); attach your + *own* private data to nodes you don't own, under your own authz + ([sidecar.ts](../../packages/data/src/schema/sidecar.ts), deterministic + `sidecarId`); graduate an overlay into a core property via a lens + ([lens-builders.ts](../../packages/data/src/schema/lens-builders.ts)). +- **Cross-version coexistence:** bidirectional lenses after Cambria, additive + minor versions, unknown-field round-tripping — + [docs/specs/protocol/05-schema-evolution.md](../specs/protocol/05-schema-evolution.md). + This is the "1958 brick still snaps in 2026" mechanism, stated normatively. +- **Views:** `table|board|list|gallery|calendar|timeline|form` as first-class + nodes ([packages/data/src/database/view-types.ts](../../packages/data/src/database/view-types.ts)) + — one sentence in the essay, then a pointer to #11 (its territory). +- **Hooks:** `useQuery`/`useMutate`/`useCan` + ([packages/react/src/hooks/](../../packages/react/src/hooks/)) — one + sentence, pointer to #8 ("The Tip of the Hook"). +- **Agents as players:** `xnet mcp serve` exposes the workspace to any MCP + client over stdio or hardened loopback HTTP + ([packages/cli/src/commands/mcp.ts](../../packages/cli/src/commands/mcp.ts)); + connectors contribute `agentTools` + ([packages/plugins/src/agent-tools.ts](../../packages/plugins/src/agent-tools.ts)); + the devkit bridge sits on port 31416 + ([packages/devkit/src/bridge.ts](../../packages/devkit/src/bridge.ts)). + (Two ports: 31416 = devkit bridge, 31415 = agent/MCP local API — don't + conflate in the essay.) +- **Connectors:** `defineConnector` requires declared `schemaWrite` IRIs and + an explicit `network` host allowlist — capabilities enforced, closed by + default; the runner stamps the target `space` so the cascade holds + ([define-connector.ts](../../packages/plugins/src/connectors/define-connector.ts)). +- **Foreign bricks:** CSV/JSON import-export + ([packages/data/src/database/import/](../../packages/data/src/database/import/)), + Slack-compat ([packages/slack-compat/src/](../../packages/slack-compat/src/)), + landing schemas `ExternalReference`/`external-item`/`feed-item`. JMAP email + is exploration-stage only (0308, `[_]`) — do not claim it as shipped. + +### Overlap audit against the existing series + +| Essay | Its claim | #15's distinct claim | +| --- | --- | --- | +| #11 The Vault and the View | Vertical: apps are disposable views; data is the heirloom | Horizontal: **data snaps to data**; the coupling standard + permissions | +| #10 Workshop / Walled Garden | Third-party *code* is safe when scoped | One paragraph hand-off for plugin scoping; #15 focuses on *data-to-data* and *person-to-person* composition | +| #8 The Tip of the Hook | The developer surface (hooks) | Cited, not re-explained | +| #7 The Loom You Can Read | The change log internals | Cited, not re-explained | +| #12 Timeout | Presence/absence semantics | Untouched | +| #2 Data Should Work Like Soil | Ecology metaphor for the substrate | Different metaphor family; no mechanism overlap | + +The seam: #11 argued the data should outlive the app. #15 argues the data +should *compose* — with other data, other people, and other people's +software — and that composition without permission control is how you get +strip-mined (the lesson of the open-API era). + +## External Research + +(Verified by web research during this exploration; URLs in References.) + +### The metaphor's load-bearing facts + +- LEGO patented the **stud-and-tube** coupling on **28 January 1958**; the + hollow tubes under the top studs are what create **clutch power** — grip + strong enough to hold a model together, gentle enough that a child can + take it apart. Bricks moulded in 1958 still interlock with current + production: one frozen interface, seven decades of compatible parts, the + "System of Play." +- The sceptic's rebuttal exists and should be pre-empted, not dodged: + "LEGO as a Metaphor for Software Reuse — Does the Data Stack Up?" + (Safety Dave, 2021) argues software recombines far less cleanly than + bricks because interfaces evolve. Exactly — which is why the essay's + centre of gravity is the *frozen* interface set (four universal fields, + one merge rule) plus a *specified* evolution mechanism (additive minors, + lenses), not vibes about modularity. +- Trademark note: "LEGO" is a fiercely defended trademark. Editorial, + nominative use is fine; the LEGO Group's own style guidance prefers + "LEGO bricks" over "Legos." Recommended: title avoids the mark + ("Clutch Power"), body uses "LEGO bricks" for the metaphor with plain + nominative references, no logos or set imagery in the hero. + +### The lineage of universal-data attempts (question 2's history) + +- **Unix pipes** — McIlroy's 1964 memo, Thompson's 1973 `|`; "expect the + output of every program to become the input to another, as yet unknown, + program" (published 1978). Composability's clearest historical win — for + *streams of bytes* between programs one user already trusts. No namespace, + no permissions, no sync: the trivial case, and still the high-water mark. +- **Xanadu (1960–2014)** — Nelson's docuverse and transclusion: universal + addressing proposed, never shipped at scale; *Wired* (1995) called it the + longest-running vaporware in computing. Lesson: a universal namespace + without a working substrate is a manifesto. +- **OpenDoc vs OLE (1992–1997)** — compound documents; died when it required + every vendor to rewrite apps around a shared substrate that the platform + incumbent had no reason to bless. Lesson: composability must arrive + *inside* software people already want (a lesson local-first re-learned and + xNet inherits). +- **Semantic Web / RDF (2001–~2010)** — Berners-Lee's agents-reasoning-over- + the-web vision; stalled on the economics of annotation, ontology + coordination, and a steep stack. By 2006 Berners-Lee himself pivoted to + "Linked Data" — less ontology, more data. Its afterlife (schema.org, + Wikidata) fed the Knowledge Graph — i.e. recentralised one layer up. +- **The open-API era and its shutdown** — Flickr's REST API (Aug 2004) + begat mashup culture; then platforms discovered the graph was the asset: + Facebook Friends API closed 30 April 2015; Twitter ended free API access + 9 February 2023 with roughly a week's notice; Reddit's 2023 pricing + ($0.24/1k calls, ~$2M/month for Apollo) killed the third-party clients + and triggered the subreddit blackout. An API is a drawbridge: composability + at the platform's pleasure, revocable at a week's notice. +- **RSS** — ubiquitous by the late 2000s, Google Reader killed 1 July 2013; + survives as podcasting's unmediated backbone. Proof that open composability + can *persist* where no single owner can revoke it. +- **Screen-scraping economy** — Mint (2006) and Plaid (2013) built on users + handing over bank passwords for HTML scraping, because no first-class + data-sharing primitive existed. The market priced the missing primitive + at billions. +- **GDPR Article 20** — a right to portability with no format; studies of + real-world requests document widespread partial/incomplete responses. + Portability without composability is a ZIP file. + +### The contemporary cohort (and the gap xNet aims at) + +- **Solid** — pods with per-resource ACLs; stewardship moved to the Open + Data Institute in October 2024; Project Liberty integration talks + disclosed March 2025. Alive, enterprise/pilot-stage; still fighting the + OpenDoc adoption problem. +- **ATProto / Bluesky** — the closest thing to a shipped universal + namespace: user repos (PDS) + Lexicon, a federated schema registry under + reverse-DNS authorities. But the firehose model is **public-by-default**; + private data / auth scopes are still at the proposal/working-group stage. + The sharpest available proof that *a shared namespace and user-controlled + permissions are different features*, and most shipped systems have only + the first. This is xNet's precise differentiation and deserves a full + paragraph. +- **IPFS/IPLD** — content addressing solves integrity/durability, not + access control or liveness. +- **Matrix / ActivityPub** — working federation; scoped to chat/social; + moderation per-instance with defederation as the only (blunt) lever. +- **Local-first (Ink & Switch, Onward! 2019)** — the seven ideals; ideal #5 + (longevity) and #7 (user control) are this essay's ancestors. #11 already + owns this citation; #15 references it once. +- **CRDTs** — Yjs (~920k weekly downloads) vs Automerge (~85k): the merge + machinery is commoditising; the differentiators have moved up-stack to + namespace + authz — convenient framing for why xNet's spec spends its + normativity on L1/L3. +- **UCAN** — delegable, attenuable capability tokens; the "hand over three + bricks, not the crate" mechanism, shipped in xNet. +- **Google Zanzibar (USENIX ATC 2019)** — relationship-tuple authz backing + Drive/Photos/YouTube: >2 trillion ACL checks, 95% under 10ms. Existence + proof that fine-grained relationship-based authorization works at + planetary scale — *inside one company's fence*. The open problem xNet + takes on is the same semantics with nobody owning the graph, which is + why L3's decision semantics are normative (two implementations must reach + identical allow/deny on the same graph). + +### Honest-limits research (question 3's backbone) + +- **Reading is copying.** No cryptographic scheme prevents a legitimate + reader from copying decrypted data out of the system. Capability systems + mitigate confused-deputy delegation abuse; they cannot un-show something. + Revocation stops *future* reads only. The essay must say this plainly — + it is also the metaphor's grace note: clutch power grips, it doesn't weld, + and a system that promised weld-strength control over shared data would + be promising DRM. +- **Ontology coordination is social.** No single party can model the world; + competing ontologies recreate silos (semantic-web literature's own + finding; schema.org absorbing GoodRelations in 2012 is the rare + convergence). Lenses/overlays make disagreement cheap; they do not make + agreement free. +- **Moderation/discovery in p2p** — per-instance moderation with + defederation as the only lever is documented as structurally weak + (Carnegie 2025; ACM "Will Admins Cope?"). xNet's spaces are the + moderation boundary today; network-scale discovery and abuse handling are + open. +- **Hosting economics** — someone pays to keep bytes available; p2p storage + networks need proof-of-storage machinery consumer systems don't build. + xNet's stance: local replica primary, hub as optional paid relay. +- **The frozen-interface bill** — LEGO froze one physical coupling and + iterates everything else. Protocols pay for that continuously: xNet's own + protocol-v4 LWW tiebreak change (hash-grinding mitigation, exploration + 0305) rippled through four conformance kernels and the serializer + registry. Freezing the interface is a standing engineering commitment, + not a one-time patent. + +## Key Findings + +1. **The essay's fresh contribution is the second half of the metaphor.** + "LEGO for software" is a worn trope; every prior use is about + modularity. None is about *clutch power* — the grip that holds without + welding, i.e. composability that preserves the owner's ability to take + the model apart, refuse a hand, or leave the table. Framing permissions + as a *property of the coupling itself* (authz declared on data, enforced + at sync, encryption as the snap) is the argument the sources don't make. +2. **ATProto is the perfect foil.** It shipped the universal namespace and + proved demand; its public-by-default firehose shows namespace ≠ + permissions. One respectful paragraph does more differentiation work + than any amount of silo-bashing. +3. **The three brief questions map cleanly onto essay movements** — + (2) history first (silos → drawbridge APIs → scraping → ZIP-file + portability), (1) then what the coupling enables (with repo receipts), + (3) then the six honest limits. History-first keeps it from reading as + a product pitch. +4. **Every enabling claim has a shipped receipt** except JMAP email + (exploration-stage) and anything security-sensitive from exploration + 0307 (see Risks). The essay should only claim what's on `main`. +5. **The series' fact-check discipline applies** (exploration 0247): all + dates and quotes above came from live web verification during this + exploration; re-verify any *new* quote added at draft time. en-GB prose, + `.astro` page, vendored hero, nothing third-party on the page. + +## Options And Tradeoffs + +### Framing options + +| Option | Shape | Pros | Cons | +| --- | --- | --- | --- | +| **A. Coupling-first** ("the stud, not the brick") | 1958 patent → the four frozen interfaces → what snaps on → who gets to play → limits | Distinct from #10/#11; mechanism-rich; metaphor earns its keep | Needs discipline to keep LEGO from becoming a gimmick | +| B. History-first polemic | Silo era → API betrayals → xNet | Emotionally strong openings (Apollo's death) | Overlaps #11's Google Reader cold open; angrier than the series' register | +| C. "New software" catalogue | Lead with what becomes possible | Concrete, optimistic | Reads as a feature tour; weakest thesis | +| D. Permissions-first ("who plays") | Lead with consent/control | The freshest half | Buries the composability half the user's brief leads with | + +**A, with B compressed into one movement and D as the essay's second act.** +The brief's three questions become acts 2, 1→3 ordering inside frame A +(history as act one, enablement as act two, limits as act three). + +### Title options + +| Title | Notes | +| --- | --- | +| **"Clutch Power"** ✅ | The metaphor's payload in two words: grip without weld = composability with consent. Avoids the trademark in the title. Series-compatible (cf. "Timeout", "Weights You Can Hold") | +| "The Stud and the Tube" | Series pair-form; the tube (hidden half, = permissions) is elegant but the phrase reads oddly cold | +| "A Box of Bricks" | Warm but generic; weak on the permissions half | +| "Bricks That Still Snap" | Good backwards-compat hook; misses permissions | + +### Cold-open options + +1. **The 1958 patent + the 68-year-old brick** ✅ — a brick moulded the + year before the moon race still snaps onto a set bought this morning; + what was patented was not a brick but a *coupling*; pivot: the web never + patented its coupling for data. +2. Apollo-app shutdown day (2023) — strong but angry, and #11 already + cold-opened on a platform death (Google Reader). +3. A child's brick bin — every set ever bought, one bin, everything + combines — warm, but slower to the thesis. + +## Recommendation + +Write **blog post #15, "Clutch Power"**, framing A: + +1. **Cold open:** 28 January 1958 — the stud-and-tube patent. The genius + was never the brick; it was the coupling — and the grip that holds + firmly yet yields to a child's fingers. Sixty-eight years of parts, + one interface. Then the turn: the web never standardised a coupling for + *data* — so every app moulded bricks that only fit its own set. +2. **Act one — the bin we never got** (question 2): silos as sets that + don't combine; the API era as drawbridges (Flickr 2004 → Facebook 2015 / + Twitter 2023 / Reddit 2023); Plaid pricing the missing primitive in the + billions; GDPR's ZIP-file portability; copy-paste as the web's only + universal connector. One paragraph nods to Xanadu/OpenDoc/Semantic Web: + universal data has been proposed for sixty years; what was always + missing was a shipped coupling *with a permission model*. +3. **Act two — the coupling** (question 1): the four frozen interfaces + (universal node fields, `xnet://` SchemaIRI namespace anyone — even a + DID — can mint into, one merge rule, one authz algebra), then what + snaps on once they exist: relations across schemas; overlays on data you + don't own; sidecars carrying *your* private notes on *their* nodes; + lenses letting a 2026 client edit a 1958 document; agents as + first-class players through the MCP surface; connectors that turn Slack + exports and CSVs into bricks. Then the second half: **who gets to + play** — authorization as data (grants are nodes that sync like + everything else), UCAN attenuation (three bricks, not the crate), + encryption as the snap itself, share links whose secret never touches a + server, enforcement at the sync boundary so the rules travel with the + data. The user-side network effect closes the act: in a silo, your data + compounds the platform's moat; on a common coupling, it compounds *your* + toolbox. +4. **Act three — what the coupling cannot do** (question 3): six limits, + plainly. Reading is copying — revocation stops future reads, never past + ones, and anything stronger would be DRM, which the grip deliberately + isn't. Schema agreement stays social — lenses cheapen disagreement, they + don't abolish coordination. Frozen interfaces bill forever — the + protocol-v4 ripple as receipt. Generic substrates pay a performance tax + — our query-perf sagas as invoice. Somebody hosts — Moxie conceded, hub + as optional relay, economics not hand-waved. Moderation and discovery + are per-space, unsolved at network scale. +5. **Close:** the difference between a weld and a grip. A weld is a + platform: strong, permanent, and you don't get to take it apart. A grip + is a protocol: it holds because the geometry is right, and it lets go + because the bricks are yours. Build accordingly. + +Mechanics: `site/src/pages/blog/clutch-power.astro` + `posts[]` entry in +[site/src/data/blog.ts](../../site/src/data/blog.ts), tags +`['essay', 'protocol', 'decentralization', 'philosophy']`, authors +`['crs48', 'claude']`, bespoke vendored hero (abstract stud-grid motif — +no LEGO imagery), one Mermaid diagram, one `CodeFigure`, ~14 min read, +en-GB, changelog fragment via `scripts/changelog/new.mjs`, `skip-changelog` +not applicable (site change → Changelog Check applies; no changeset — site +is not a publishable package). + +```mermaid +flowchart TB + subgraph coupling["The coupling (frozen, normative)"] + N["Node: id · schemaId · createdAt · createdBy"] + IRI["Namespace: xnet://authority/Name@semver
(authority may be any DID)"] + LWW["One merge rule: signed change log → LWW fold"] + AUTHZ["One authz algebra: roles · actions · grants · UCAN
enforced at the sync boundary"] + end + subgraph bricks["Bricks (open-ended)"] + T["Task"] ; C["Contact"] ; M["ChatMessage"] ; X["ext: overlay
on someone else's node"] + S["sidecar: your private notes
on their data"] ; F["ExternalReference
(imported silo data)"] + end + subgraph players["Players"] + APP["Apps (views — see essay #11)"] + AGT["Agents (MCP surface)"] + PPL["People (DIDs, share links)"] + end + bricks -->|snap onto| coupling + players -->|"play, if permitted"| coupling +``` + +```mermaid +sequenceDiagram + participant O as Owner (DID) + participant H as Hub (relay) + participant G as Guest (DID) + O->>O: create node (E2E encrypted,
key wrapped per recipient) + O->>H: publish signed change + Note over H: no grant for Guest →
not relayed; no key → no snap + O->>G: share link (secret in URL fragment) + G->>H: claim → UCAN delegation (attenuated: read only) + H-->>G: relay changes for that resource + G->>G: unwrap key, decrypt — the brick snaps + O->>O: revoke grant + Note over G: future changes stop.
What was already read is already copied —
the grip is not a weld. +``` + +## Example Code + +The essay's central exhibit — composition across ownership boundaries +without forking or asking (real APIs from +[extension.ts](../../packages/data/src/schema/extension.ts) / +[sidecar.ts](../../packages/data/src/schema/sidecar.ts)): + +```typescript +// Their brick: a Contact node someone else created and governs. +// Your stud: an overlay attribute in your authority's namespace, +// riding on the node, syncing and merging like any property. +await mutate.update(contactId, { + [extKey('yourapp.example', 'vip')]: true +}) + +// Your private brick on their public one: a sidecar — a separate +// node with ITS OWN authorization (they never see your notes), +// deterministically addressed so every device finds the same one. +const noteId = sidecarId('yourapp.example', contactId) +await mutate.create(SidecarSchema, { + id: noteId, + target: contactId, // relation → any node, any schema + body: 'Met at the 1958 patent anniversary. Buys bricks in bulk.' +}) +``` + +## Risks And Open Questions + +- **Do not publish security specifics from exploration 0307.** The audit + found real authorization gaps (wildcard-UCAN handling, unwired + `authEvaluator` paths). The essay's limits section must stay at design + level ("enforcement is only as strong as the relay's evaluation, and we + are still hardening it") and must not describe unfixed weaknesses or + their mechanics. Check 0307's remediation status at draft time; if the + gaps are closed, a "we audited ourselves and fixed X" line is *stronger* + than silence. +- **Trademark.** Nominative use of "LEGO" is fine; keep it out of the + title (done — "Clutch Power"), use "LEGO bricks" in prose, vendored + abstract hero only, no sets/logos/minifigures. Do not title the post + "Legos for Data." +- **Metaphor fatigue.** The series already runs on extended metaphors + (looms, furnaces, soil). Guard: the metaphor must earn each appearance by + mapping to a mechanism (coupling→node fields, catalogue→SchemaIRI, + clutch→permissions, 1958-brick→lenses); cut any paragraph where it's + only decoration. +- **Overlap discipline.** #11 owns apps-as-views and the local-first canon; + #10 owns plugin scoping; #8 owns the hooks; #7 owns the log internals. + #15 links each once and never re-argues. The overlap-audit table above is + the contract. +- **Overclaim watch.** "Universal namespace" is true of the *protocol*; + network-scale claims (discovery, a public schema commons, cross-org + authority resolution beyond `xnet/1.0`'s rules) are roadmap. Keep verbs + honest: the coupling is shipped; the worldwide bin of bricks is the bet. +- **Performance receipts without self-sabotage.** Cite "our query + performance work" generically; don't quote raw cliff numbers from + exploration 0318 (internal measurements of unreleased paths). +- Open question for draft time: does the essay show one small end-to-end + "two apps, one datum, one permission grant" narrative vignette (a CRM + and a chat app sharing a Contact)? Likely yes — it dramatises question 1 + in 150 words — but cut if length exceeds ~15 min read. + +## Implementation Checklist + +- [x] Re-verify at draft time: 0307 remediation status (gates how the + hardening limit is phrased); JMAP still exploration-only; the ~60 + built-in schema-module count. +- [x] Write `site/src/pages/blog/clutch-power.astro` following series + conventions (Byline, SeriesNav, Mermaid, CodeFigure, `tok-*` + helpers, `prose` body, en-GB, nothing third-party). +- [x] Bespoke vendored hero under `site/src/components/blog/` — abstract + stud-grid motif, no LEGO trade dress. +- [x] Add the `posts[]` entry in `site/src/data/blog.ts` (slug + `clutch-power`, tags + `['essay','protocol','decentralization','philosophy']`, authors + `['crs48','claude']`, honest `readingMinutes`). +- [x] Body structure per Recommendation: cold open (1958 patent) → the bin + we never got → the coupling & who gets to play → six limits → the + weld and the grip. +- [x] Every mechanism claim carries its repo receipt (paths as listed in + Current State); external dates/quotes only from the verified set in + External Research; any new quote re-verified against the live source + (0247 discipline). +- [x] `CodeFigure` uses the real `extKey`/`sidecarId` APIs (no invented + fields); Mermaid diagrams adapted from this exploration. +- [x] Cross-link essays #7, #8, #10, #11 once each; link the protocol spec + (`docs/specs/protocol/`) as the "System of Play" receipt. +- [x] Changelog fragment via `scripts/changelog/new.mjs`; no changeset + (site is not a publishable package). +- [x] Conventional commits, header ≤72 chars; PR to `main`; let CI run + (no `--admin`); merge-commit per repo policy. + +## Validation Checklist + +- [x] Site build passes (verify via full build — astro dev has hung on + some pages before); post renders with hero, byline, diagrams, code + figure in light and dark. +- [x] Post appears on `/blog` index and in `rss.xml`; `seriesNeighbors` + links #14 ↔ #15 correctly. +- [x] Network tab clean — no third-party requests on the page. +- [x] Fact pass: every date (1958, 2015, 2023, 2013, 2004, 2019, 2024) + matches the sources in References; every repo path in the essay + exists on `main` at publish time. +- [x] Security pass: nothing in the limits section describes an unfixed + vulnerability or its mechanics (0307 check). +- [x] Trademark pass: no "Legos", no LEGO imagery, nominative references + only. +- [x] Overlap pass: a reader of #10/#11 finds a new argument in every + section (the coupling framing, the ATProto foil, the clutch-power + permissions half, the six limits). + +## References + +- LEGO stud-and-tube patent (28 Jan 1958) — · + +- Safety Dave, _LEGO as a Metaphor for Software Reuse_ (2021) — + +- Doug McIlroy / Unix pipes history — + +- Project Xanadu — +- Why OpenDoc failed — +- Berners-Lee, _Linked Data_ design note — +- Facebook Friends API shutdown (2015) — +- Twitter free-API shutdown (2023) — +- Reddit API pricing / Apollo (2023) — +- TechCrunch, _Social networks are getting stingy with their data_ (2024) — + +- RSS history — +- Solid → ODI stewardship (Oct 2024) — ; + Project Liberty talks — +- ATProto & Lexicon — ; + private-data gap — · + +- Ink & Switch, _Local-first software_ (2019) — +- UCAN — +- Google Zanzibar (USENIX ATC 2019) — +- Confused deputy — +- Plaid / screen scraping — +- GDPR Art. 20 portability in practice — +- "You're the product" origin (Lewis, 2010) — +- Fediverse moderation limits — · + +- Decentralized storage economics — +- Repo: [docs/specs/protocol/](../specs/protocol/) (L0–L3 + conformance), + [packages/data/src/schema/](../../packages/data/src/schema/) (node, registry, + extension, sidecar, lens-builders), + [packages/data/src/auth/](../../packages/data/src/auth/), + [packages/identity/src/](../../packages/identity/src/) (did, ucan, sharing), + [packages/crypto/src/envelope.ts](../../packages/crypto/src/envelope.ts), + [packages/core/src/lww.ts](../../packages/core/src/lww.ts), + [packages/sync/src/change.ts](../../packages/sync/src/change.ts), + [packages/hub/src/server.ts](../../packages/hub/src/server.ts), + [packages/plugins/src/connectors/define-connector.ts](../../packages/plugins/src/connectors/define-connector.ts), + [packages/cli/src/commands/mcp.ts](../../packages/cli/src/commands/mcp.ts); + explorations 0188, 0200, 0247, 0281 (essay #11), 0304, 0305, 0307 diff --git a/site/public/llms-full.txt b/site/public/llms-full.txt index 891fa4fe0..c8cc3e7b2 100644 --- a/site/public/llms-full.txt +++ b/site/public/llms-full.txt @@ -315,6 +315,29 @@ Without writing a single line of backend code, you got: - src/ - schema.ts defineSchema() definitions - App.tsx XNetProvider - TaskList.tsx useQuery + useMutate +## Go multiplayer in two commands + +Everything above is one keystroke away from being a shared app. Point the +provider at a sync hub and give everyone the same room string — whoever +shares the room sees the same data: + +```tsx + +``` + +To run your own hub locally (dev only — auth off accepts anyone): + +```bash +docker run --rm -p 4444:4444 -e HUB_AUTH=false ghcr.io/crs48/xnet-hub:latest +``` + +Open the app in two browser windows — changes appear in both. The room string +is the entire join flow: put it in a URL (`?room=standup`) and the URL becomes +an invitation. The smallest complete example of this is +[`examples/minimal-app`](https://github.com/crs48/xNet/tree/main/examples/minimal-app) +in the repo (~60 lines, copy-paste ready), and you can watch it run live on +the [demos page](/demos/). + ## Next steps @@ -7660,6 +7683,20 @@ reports upstream — the sender's DID is hashed (never sent raw) and document content is never included. Leave them unset (the default) and nothing is forwarded; `GET /diagnostics/health` simply reports `sharing: false`. +The upstream sink is xNet Cloud's first-party `POST /diagnostics` ingest +(exploration 0315): reports land in a quarantine and are drained into +`debug-report` nodes in the operator's own xNet workspace, where the workbench +_is_ the triage console — filterable tables, a `new → acked → fixed → released` +status field, and comments. **xNet does not use a third-party error service such +as Sentry.** The client keeps a dormant, vendor-neutral Sentry seam (no +`@sentry/*` SDK is installed and no DSN is minted), so if you self-host a +Sentry-compatible backend you can point that seam at it — [Bugsink][bugsink] +(single container, SQLite) or [GlitchTip][glitchtip] (MIT, Sentry-SDK +compatible) are the proven small-footprint options — but nothing ships enabled. + +[bugsink]: https://www.bugsink.com/ +[glitchtip]: https://glitchtip.com/ + ### CLI Flags | Flag | Description | diff --git a/site/src/components/blog/BrickArt.astro b/site/src/components/blog/BrickArt.astro new file mode 100644 index 000000000..3c0898f9a --- /dev/null +++ b/site/src/components/blog/BrickArt.astro @@ -0,0 +1,186 @@ +--- +// Decorative art for blog post #15 (exploration 0319), extracted so the same +// inline SVG backs both the post hero and the blog-index preview card (no +// external assets — Self-Audit parity). The scene draws the essay's argument: +// on the left, the silo era — two sealed boxes whose connectors don't match +// (a triangle socket, a round socket), each with a few dim points locked +// inside. On the right, one baseplate: a ground plane of studs on which +// bricks of different shapes all snap, because the coupling is shared. One +// brick hovers just above the plate, mid-lift — the grip lets go; that's the +// point. Another sits dashed with a keyhole: present, but it won't snap for +// you without the key. The cosmic-X hangs overhead as the reading lamp, as in +// the rest of the series. All geometry original; no LEGO trade dress. +interface Props { + /** Override the wrapper classes; defaults to full-bleed for hero use. */ + class?: string +} +const { class: className = 'pointer-events-none absolute inset-0 h-full w-full' } = + Astro.props + +// The baseplate stud row (x positions along the plate's top edge). +const studCols = Array.from({ length: 15 }, (_, i) => 448 + i * 34) + +// Studs on top of a brick: n studs across a brick starting at x with width w. +const brickStuds = (x: number, w: number, n: number) => + Array.from({ length: n }, (_, i) => x + (w / (n * 2)) * (2 * i + 1)) + +// The dotted footpath from the silos out to the baseplate. +const path = [ + [300, 300], + [348, 294], + [396, 296], + [436, 306] +] + .map(([x, y]) => `${x},${y}`) + .join(' ') +--- + + diff --git a/site/src/components/blog/BrickHero.astro b/site/src/components/blog/BrickHero.astro new file mode 100644 index 000000000..a4afd4903 --- /dev/null +++ b/site/src/components/blog/BrickHero.astro @@ -0,0 +1,38 @@ +--- +// Hero band for blog post #15 (exploration 0319). The decorative art lives in +// BrickArt.astro so the same inline SVG backs both this hero and the +// blog-index preview card; this component layers the post's title/deck over it. +import BrickArt from './BrickArt.astro' + +interface Props { + title: string + deck: string + date: string + readingMinutes: number + tags: string[] +} +const { title, deck, date, readingMinutes, tags } = Astro.props +--- + +
+ + +
+
+ + + {readingMinutes} min read + { + tags.map((tag) => ( + + {tag} + + )) + } +
+

+ {title} +

+

{deck}

+
+
diff --git a/site/src/components/blog/HonestBrick.astro b/site/src/components/blog/HonestBrick.astro new file mode 100644 index 000000000..f72da0564 --- /dev/null +++ b/site/src/components/blog/HonestBrick.astro @@ -0,0 +1,64 @@ +--- +// The honesty beat for post #15 (exploration 0319), modeled on HonestVault / +// HonestWorkshop. An essay that says "one coupling for all your data, and you +// decide who plays" owes the reader the six places where the metaphor stops +// working — starting with the one no architecture can fix: a grip is not a +// weld, and reading is copying. The rows concede the strongest standing +// objections rather than dodging them. +const rows = [ + { + isnt: 'We won’t pretend revocation can reach into the past.', + is: 'Once someone has read a piece of data, they have it — decryption is copying, and no protocol can un-show something. Revoking a grant stops every future change from reaching them; it cannot repossess what they already saw. Anything that promised more would be DRM wearing a nicer coat, and the grip is deliberately not a weld.' + }, + { + isnt: 'We won’t pretend a shared namespace makes people agree.', + is: 'Two apps sharing a Contact still have to agree on what a contact is, and that agreement is social, not technical — the Semantic Web spent a decade proving it. Lenses, overlays, and sidecars make disagreement cheap enough to live with; they don’t make coordination free. Anyone can mint a schema, which also means anyone can mint a duplicate.' + }, + { + isnt: 'We won’t pretend a frozen interface maintains itself.', + is: 'LEGO froze one moulding geometry and iterates everything else; a protocol pays for that promise continuously. When we hardened one detail of our merge rule, the change rippled through every conformance kernel and golden vector we keep. Backwards compatibility is a standing engineering bill, not a patent you file once.' + }, + { + isnt: 'We won’t pretend a general-purpose substrate is fast for free.', + is: 'A silo optimises for exactly one access pattern; a store that must answer any question about any shape pays a tax the silo never sees. Making the open substrate feel app-fast has taken months of unglamorous query and hydration work, and that ledger is still open.' + }, + { + isnt: 'We won’t pretend nobody has to run anything.', + is: 'Moxie Marlinspike is right that people do not want to run their own servers. Your replica is primary and local, and peers can sync directly — but an always-reachable relay is what makes sharing feel instant, and someone hosts and pays for it. Ours is optional and replaceable; it is not imaginary.' + }, + { + isnt: 'We won’t pretend permissions solve moderation or discovery.', + is: 'Access control decides who may read and write; it says nothing about what deserves an audience. Spaces give every community its own table and its own rules, which works at the scale of a table — network-scale discovery, spam, and abuse in a world with no central operator remain honestly unsolved, here and everywhere.' + } +] +--- + +
+
+

+ Where the metaphor stops +

+

+ Six things a universal coupling cannot do, conceded in plain sight — + because the essays that skip this section are the ones you were right + not to trust. +

+ +
    + { + rows.map((row) => ( +
  • +
    + +

    {row.isnt}

    +
    +
    + +

    {row.is}

    +
    +
  • + )) + } +
+
+
diff --git a/site/src/data/blog.ts b/site/src/data/blog.ts index 94a7151a1..2f67628a4 100644 --- a/site/src/data/blog.ts +++ b/site/src/data/blog.ts @@ -87,6 +87,24 @@ export interface BlogPost { } const posts: BlogPost[] = [ + { + slug: 'clutch-power', + title: 'Clutch Power', + description: + 'On 28 January 1958 the LEGO Group patented not a brick but a ' + + 'coupling — stud and tube, and with them clutch power: a grip firm ' + + 'enough to build with that still comes apart by hand. The web never ' + + 'got a coupling for data, so every app moulds pieces that fit only ' + + 'its own set, and the APIs that promised otherwise were drawbridges. ' + + 'On the four frozen interfaces xNet ships instead — one node shape, ' + + 'one namespace anyone can mint into, one merge rule, one permission ' + + 'algebra — and why the grip matters as much as the snap: nobody ' + + 'plays with your bricks unless you say so.', + pubDate: '2026-07-14T17:00:00Z', + authors: ['crs48', 'claude'], + tags: ['essay', 'protocol', 'decentralization', 'philosophy'], + readingMinutes: 14 + }, { slug: 'weights-you-can-hold', title: 'Weights You Can Hold', diff --git a/site/src/data/changelog/2026-07-14-new-essay-clutch-power.json b/site/src/data/changelog/2026-07-14-new-essay-clutch-power.json new file mode 100644 index 000000000..c44c5476a --- /dev/null +++ b/site/src/data/changelog/2026-07-14-new-essay-clutch-power.json @@ -0,0 +1,10 @@ +{ + "id": "2026-07-14-new-essay-clutch-power", + "date": "July 14, 2026", + "title": "New essay: Clutch Power", + "summary": "Blog post #15 frames xNet as LEGO for data on the web: one coupling — node shape, namespace, merge rule, permission algebra — and why the grip that lets go matters as much as the snap.", + "highlights": [], + "tags": [ + "platform" + ] +} diff --git a/site/src/pages/blog/clutch-power.astro b/site/src/pages/blog/clutch-power.astro new file mode 100644 index 000000000..bfd8e151e --- /dev/null +++ b/site/src/pages/blog/clutch-power.astro @@ -0,0 +1,518 @@ +--- +import Base from '../../layouts/Base.astro' +import Nav from '../../components/sections/Nav.astro' +import Footer from '../../components/sections/Footer.astro' +import SeriesNav from '../../components/blog/SeriesNav.astro' +import BrickHero from '../../components/blog/BrickHero.astro' +import Byline from '../../components/blog/Byline.astro' +import Mermaid from '../../components/blog/Mermaid.astro' +import CodeFigure from '../../components/blog/CodeFigure.astro' +import HonestBrick from '../../components/blog/HonestBrick.astro' +import { postBySlug, formatPostDate } from '../../data/blog' + +const post = postBySlug('clutch-power')! + +// --- syntax highlighting helpers (same tok-* idiom as the landing page's +// CodeBlock; coloured by the CSS variables in Base.astro). +const kw = (s: string) => `${s}` +const st = (s: string) => `${s}` +const cm = (s: string) => `${s}` + +// The essay's central exhibit: composing across an ownership boundary without +// forking and without asking. `extKey` and `sidecarId` are the real helpers +// from packages/data/src/schema/{extension,sidecar}.ts; `update`/`create` are +// the real mutate surface from the previous developer essay. +const composeCode = [ + `${cm('// Their brick: a Contact someone else created and governs.')}`, + `${cm('// Your stud: a field in your own namespace, riding on the')}`, + `${cm('// node itself — syncing and merging like any other property.')}`, + `${kw('await')} update(ContactSchema, contact.id, {`, + ` [extKey(${st("'acme.example'")}, ${st("'leadScore'")})]: 42`, + `})`, + ``, + `${cm('// Your private brick on their public one: a sidecar — a')}`, + `${cm('// separate node with its own permissions (they never see it),')}`, + `${cm('// addressed deterministically so every device finds the same one.')}`, + `${kw('await')} create(ContactNotes, {`, + ` target: contact.id, ${cm('// relation → any node, any schema')}`, + ` body: ${st("'Prefers the 1958 catalogue. Buys in bulk.'")}`, + `}, sidecarId(me.did, contact.id))` +].join('\n') + +// --- mermaid diagram sources (rendered client-side by ) --- +const coupling = `flowchart TB + subgraph couplingBlock["The coupling — frozen, specified, versioned"] + N["one node shape
id · schemaId · createdAt · createdBy"] + IRI["one namespace
xnet://authority/Name@version
(the authority can be you)"] + LWW["one merge rule
signed change log,
deterministic fold"] + AUTHZ["one permission algebra
roles · actions · grants,
enforced where data moves"] + end + subgraph bricks["The bricks — open-ended"] + T["a task"] + C["a contact"] + M["a message"] + X["your field on
someone else's node"] + S["your private notes
on their data"] + F["an imported silo
(CSV, Slack, feeds)"] + end + subgraph players["The players"] + APP["apps — views
(the previous essay)"] + AGT["agents — same table,
same rules"] + PPL["people — names you mint,
links you hand over"] + end + bricks -->|snap onto| couplingBlock + players -->|"play, where permitted"| couplingBlock` + +const gripNotWeld = `sequenceDiagram + participant O as Owner + participant R as Relay + participant G as Guest + O->>O: creates a node — encrypted,
its key wrapped per recipient + O->>R: publishes the signed change + Note over R: Guest holds no grant →
nothing is relayed.
No key → the brick doesn't snap. + O->>G: hands over a share link
(the secret rides in the URL fragment,
which no server ever receives) + G->>R: claims it — a delegation,
attenuated to read-only + R-->>G: changes for that one resource + G->>G: unwraps the key. The brick snaps. + O->>O: revokes the grant + Note over G: future changes stop arriving.
What was already read is already copied —
a grip, not a weld.` +--- + + +