{"blyg":"0.3","id":"7eeh3bfzfcnhh90d5pkvkc2r1n","kind":"thread","origin":"https://blyg.blygger.org/","page":"t/7eeh3bfzfcnhh90d5pkvkc2r1n/","author":{"name":"Venkatesh Rao","url":"https://blyg.blygger.org/"},"created":"2026-10-07T20:10:59Z","updated":"2026-10-07T20:11:31Z","version":1,"content_md":"\n# RFC-1 — Mentions across identifier schemes: petnames in the studio, full identifiers on the wire\n\n**Request for comments · non-normative · OPEN FOR COMMENT until 2026-11-04 on\n[blyg.blygger.org](https://blyg.blygger.org/t/7eeh3bfzfcnhh90d5pkvkc2r1n/) (#66); without a blyg,\ncomment on [blygger-spec#14](https://github.com/blygger/blygger-spec/issues/14) · session 40, 2026-10-07.** Drafted by Opus 5.5 at Venkat Rao's request; edited the same session by\nFable 5.1, whose rulings on the five open questions are section 10. An RFC is a\nrecommendation put up for comment *before* any client builds it, because the\nreference client shipping a convention reads as a blessing. Like a technical note,\nan RFC constrains nothing. After its comment period and the gate in section 10,\nruling 1, it becomes a technical note. It builds on locked decisions #11 (the opaque\n`author`), #35 (identity practice, proposed in\n`docs/proposals/identity-practice-proposal.md`, which becomes `tn-2`), #36 (groups,\n`tn-3`), #20 (studio grammar versus wire grammar) and #32 (`[[id]]` is silent).\nWritten against protocol 0.3 as published on 2026-10-07; no pre-1.0 version promises\nanything (#21).\n\n## 1. The question\n\nSeveral early users have asked for **multi-author blygs**, and with them comes a\nsecond request: **@-mentions** of the people who write there and of people\nelsewhere. The request (Venkat Rao, session 40) was for three things:\n\n1. a consistent recommendation for **user identifiers within a domain** that can\n   travel through the protocol;\n2. an evaluation of how markup in the item body could carry the major\n   identifier schemes — **W3C DIDs, Ethereum accounts, ActivityPub, ATProto and\n   h-card** — so that clients sharing a convention can resolve @-mentions;\n3. a convention in which **the client keeps an address book of contacts across\n   schemes**. The author types a short `@handle`, the client looks up the full\n   identifiers in that address book, and the full identifiers travel on the\n   wire, so that another client can resolve whichever scheme it speaks.\n\nThe third request is the design. Sections 2–4 clear the ground, section 5 is the\nconvention, and sections 6–9 cover reading, scheme details, the reference\nclient's default and what is rejected. Section 10 records the rulings.\n\nThe constraints are fixed. Authors are never addressable (§5.5, §16.8). The\nprotocol has no reply primitive and no fourth mention relation (§16.8). The\nprotocol has no normative write surface (#31), so nothing here comes from\nMicropub, in keeping with that decision while staying close to the IndieWeb in\nspirit. Whatever this RFC recommends has to be HTML and studio practice, not\nprotocol.\n\n## 2. Correcting a premise: the single `author` does not block multi-author blygs\n\nThe worry was that an item's author field holds only one name, so a multi-author\nblyg would have to sign everything as \"community\" unless the spec changed in\na way that breaks RSS. Two parts of that are true and one is not.\n\n- **A multi-author blyg does not need more than one name per item.** `author` is\n  **per-item** (§5.5). A masthead blyg with five writers publishes items whose\n  bylines differ item by item. That is shape B of `tn-3`, specified since #11, and\n  the feed rule is single-**publisher**, never single-author. \"Community\" is only\n  needed if you want it: the Protocol Institute node already uses the byline\n  \"Editor\".\n- **RSS is not the binding constraint.** In RSS 2.0, the core `<author>` element\n  is a single email address, and the protocol does not emit it. The feed carries\n  `<dc:creator>` (§7). Dublin Core lets that element repeat, and Atom allows\n  several `<author>` elements. Many feed readers show only the first creator,\n  which is a display limit, not a format limit.\n- **The real single-valued thing is the protocol's own §5.5.** `author` is one\n  JSON object. Only **co-authored items** need more than one person in it, and\n  §5.5's extension point already lets them carry more without a spec change\n  (section 4.1 below).\n\nSo multi-author blygs work today and need nothing from the protocol. What the\nreference client lacks is studio-side: one `author_name` setting stamps every\nitem (`protocol.ts` sets `author.url` to the origin). That is a client gap, and\nsection 8 addresses it.\n\n**The census, re-run 2026-10-07** against the 20 blygs listed at blygger.com (19\nreachable), the three newest items each: every item `author` is `{name, url}`,\n`{name}`, or absent. No client has invented an authorspace grammar, no item has\ntwo people in it, and no body contains an h-card or mention markup.\nManifest-level `author` has grown `bio`, `links` and `avatar` in several clients.\nThe per-item field is still empty, so this is still the cheapest time to\nrecommend something.\n\n## 3. Identifiers within a domain\n\nIn shape B (one origin, many bylines), what identifies a member? The answer\nfollows from #35's spine — **a person is a URL they control** — with one\nconcession for people who have no URL of their own:\n\n| Member has… | `author.url` | What it proves |\n|---|---|---|\n| their own site, profile or actor URL | that URL | portable. If the page links back (section 5.5), a reader can confirm the byline from the member's side. |\n| nothing of their own | a house-hosted member page, e.g. `https://house.example/people/alice/` | only that **the house** says so. That is honest: in shape B the house answers for everything (`tn-3` section 5). |\n\nThe member page is presentation. It is an HTML page like any `page`, not a\nprotocol construct, so it does not make authors addressable in §16.8's sense:\nnothing in the protocol references it. It has a second job, which section 5.5\ngives it: it is the origin-side end of the reciprocal proof for a member who\ndoes have their own URL. A member who later moves to their own origin (shape A)\ntakes their own URL with them. A house URL does not travel. That is the\npractical reason to prefer the member's own URL whenever they have one.\n\n**No `user@domain` grammar inside an origin.** `@alice` as typed in the studio is\na **petname**, a name that is meaningful only in this address book (section 5).\nIt never reaches the wire as an identifier. DNS remains the namespace (#11).\n\n## 4. The five schemes, evaluated\n\nEach scheme answers four questions:\n\n- What is its **stable** identifier, as opposed to its human-readable name?\n- Can a reader resolve it with an ordinary fetch?\n- How does a person prove control of it?\n- What does it reduce to under #35's two proofs: a reciprocal link, or a\n  signature?\n\n| Scheme | Human name (mutable) | Stable identifier to put on the wire | Resolution | Proof | Reduces to |\n|---|---|---|---|---|---|\n| **Web / h-card** | the URL itself | `https://alice.example/` | fetch, then parse the representative h-card | `rel=\"me\"` reciprocal links | link (it *is* #35) |\n| **ActivityPub** | `@alice@social.example` | `acct:alice@social.example` (RFC 7565), plus the actor's `https` URL | WebFinger (RFC 7033) maps `acct:` to the actor URL | Mastodon-family servers check `rel=\"me\"` on the links in a profile and serve `rel=\"me\"` on profiles themselves | link |\n| **ATProto** | handle `alice.example` or `alice.bsky.social` | the DID, usually `did:plc:…` | DNS TXT `_atproto.<handle>` or `https://<handle>/.well-known/atproto-did`, and the DID document's `alsoKnownAs` points back | two-way handle↔DID binding. A domain handle is DNS control. | link (a domain handle is a URL the person controls) |\n| **W3C DID** | none | `did:<method>:…` | method-specific. `did:web` is an HTTPS fetch. `did:plc` needs a directory. `did:key` and `did:pkh` resolve locally. | `did:web`: DNS. Others: a key in the document | `did:web` reduces to a link. The others reduce to a signature. |\n| **Ethereum** | ENS name `alice.eth` | the account as a DID, `did:pkh:eip155:1:0xAb…` (the CAIP-10 account `eip155:1:0xAb…` wrapped; see section 7) | ENS needs chain access (an RPC endpoint); the account needs nothing | EIP-191 signature (e.g. over `content_hash`, #35 §4.2); EIP-4361 for sign-in | signature |\n\nFour observations decide the design.\n\n1. **h-card is not a rival scheme. It is the envelope.** It is the IndieWeb's\n   format for \"here is a person and their identifiers\": `p-name`, `u-url`\n   (which may repeat), `u-uid`, and `u-key`. Every other row can be written\n   *inside* an h-card. That makes it the natural carrier for request 3, and it\n   is already how Mastodon marks up mentions in HTML (`<span class=\"h-card\"><a\n   class=\"u-url mention\" href=\"…\">@<span>alice</span></a></span>`).\n2. **Put the stable identifier on the wire, never the name.** ENS names expire\n   and transfer, ATProto handles change, and fediverse accounts migrate. The\n   address, the DID and the actor's `acct:` are what a distant reader can still\n   match a year later. The web is the exception, because the URL is both the\n   name and the identifier. That is exactly why #35 chose it.\n3. **Three of the five reduce to \"a URL the person controls\".** Those are the\n   web, ActivityPub, and ATProto with a domain handle. `did:web` joins them.\n   Only `did:plc`/`did:key` and Ethereum need a signature or a non-HTTP resolver.\n   The default can therefore stay boring (section 8) and lose almost nothing.\n4. **The schemes differ in cost to the reader, not just in reach.** Resolving\n   an ENS name needs chain access, and `did:plc` needs a third-party\n   directory. A static reader cannot do either. Any convention has to work for\n   a reader that resolves *nothing*, and that pushes the visible fallback onto\n   a plain `https` link.\n\nA fifth, smaller observation sets the wire vocabulary: with Ethereum accounts\nwritten as `did:pkh:`, **everything on the wire is an `https:`, `acct:` or\n`did:` URI**. Three schemes, three normalization rules (section 6), and a\nmatcher needs nothing else.\n\n### 4.1 What `author` can carry for co-authored items\n\nA co-authored item keeps one `author` object, as §5.5 requires. It can use the\nextension point §5.5 grants, so no spec change is needed:\n\n```json\n\"author\": {\n  \"name\": \"Alice Ng and Bob Ruiz\",\n  \"url\": \"https://house.example/\",\n  \"coauthors\": [\n    { \"name\": \"Alice Ng\", \"url\": \"https://alice.example/\", \"ids\": [\"did:plc:7iza6de2dwap2sbkpav7c6c6\"] },\n    { \"name\": \"Bob Ruiz\", \"url\": \"https://social.example/users/bob\", \"ids\": [\"acct:bob@social.example\"] }\n  ]\n}\n```\n\nA reader that knows only `name` shows \"Alice Ng and Bob Ruiz\", which is correct.\n`<dc:creator>` carries the same combined string. Emitting one `<dc:creator>` per\nperson is legal, but readers that show only the first would drop Bob. For a\nsingle author, `ids` sits directly in `author` beside `url`. `ids` is the same\narray as a mention's alternate identifiers (section 5), with the same emission\nrule, and is ruled in as a conventional member in section 10, ruling 5. It is\ndistinct from the manifest-level `links` that several clients already emit:\n`links` are labelled links for display, `ids` are identifiers for matching.\n\n## 5. The convention: an address book of petnames, full identifiers on the wire\n\nThis is the design the request asked for. It takes its shape from **petname\nsystems**, and in particular from Zooko's triangle. Zooko's observation was\nthat a name cannot be global, secure and memorable all at once. The standard\nresolution, used by Stiegler's petname designs and by every phone's\ncontact list, is to keep the memorable name local, to the person who chose it,\nand to send the global, secure identifier. `@kyle` is memorable only in\none studio. `did:plc:…` is global and verifiable but nobody can type it.\nSo the address book holds the mapping, and the wire carries only what other\nclients can check.\n\n### 5.1 The address book (studio-private)\n\nEach contact record holds:\n\n- `handle`: the petname the author types (`kyle`). It is unique within the\n  book. **It never leaves the studio.**\n- `name`: the display name used when the mention renders.\n- `url`: the primary `https` URL, used as the link target. It is optional only\n  for a contact who has no web presence at all, for example an Ethereum-only\n  contact.\n- `ids[]`: alternate identifiers in their stable form (section 4 observation 2).\n  Each carries **provenance**:\n\n    - `self` means the contact publishes it themselves, for example as a\n      `rel=\"me\"` link or an h-card `u-url` at their `url`, or as an\n      `alsoKnownAs` entry in their DID document;\n    - `bound` means the scheme's own two-way binding was checked. Examples are a\n      handle and DID that point at each other, or WebFinger agreeing with the\n      actor;\n    - `entered` means the author typed it in, and nothing has checked it.\n\n- `member: true` for people who publish at this origin. In shape B the\n  house's member roster is simply the book's member entries. The roster supplies\n  each member's byline, and the members sign in with #31's scoped tokens. The\n  roster changes nothing about accountability: the house still withdraws any\n  item and owns every pin (`tn-3` section 5).\n\n**How the book fills itself.** When the author adds a contact by any single\nidentifier, the studio resolves outward from it and gathers what it can:\n\n- from a URL, it fetches the page and reads the representative h-card and the\n  `rel=\"me\"` links, which reveal the person's fediverse, Bluesky and GitHub\n  profiles, all `self`;\n- from `@alice@social.example`, it runs WebFinger, reaches the actor, and reads\n  the actor's profile links;\n- from an ATProto handle, it resolves the DID and checks the DID document's\n  `alsoKnownAs`;\n- from `did:web`, it fetches the DID document.\n\nSubscriptions supply contacts for free: every subscribed blyg's `author` already\ncarries a `name` and `url`, and the studio can offer to add it.\n\n### 5.2 Writing: `@handle` is studio grammar and is consumed at publish\n\nThe editor offers autocomplete on `@`. The grammar is **studio-private** under\n#20's two-layer split, like TK. It is consumed at publish, and it never appears\nin `content_md`:\n\n- `@kyle` that matches a contact turns into a mention.\n- `@word` that matches nothing stays literal text, and the editor shows a soft\n  warning with an \"add contact\" action. It is never a publish error, because `@`\n  is common in prose, in code and in email addresses. Text in code spans and code\n  blocks is never touched, which is the same rule as #54.\n\n**Why it must be consumed rather than left in `content_md`:** forkers re-parse\n`content_md` (#63). If `@kyle` stayed in the text, it would travel to a forker\nwhose address book has no `kyle`, or a different one. That would make one\nperson's petname resolve to another person in someone else's fork. Under\n#43's boundary test, a grammar that a third party has to re-parse belongs to the\nprotocol. This one must not become protocol (§16.8), so it must not survive\npublish.\n\nThe same fact sets what a fork keeps. A forked thread descends from the pinned\ndocument (#57), so its baked `content_html` carries the h-cards. A forked\n*fragment* is re-rendered from `content_md` (#63), so it carries the plain\nlink and not the alternate identifiers, unless the forking client's own book\nknows the URL and re-wraps it. That is correct: the identifiers were the\noriginal publisher's statement about their contact, and a fork is the forker's\nspeech.\n\n### 5.3 What goes on the wire\n\n**In `content_md`:** a plain markdown link, which any markdown reader understands:\n\n```markdown\nThanks to [@Kyle Mathews](https://bricolage.io/) for the edge-cache work.\n```\n\n**In `content_html`:** the same link, wrapped as an h-card that carries the\ncontact's alternate identifiers:\n\n```html\n<span class=\"h-card\"><a class=\"u-url\" href=\"https://bricolage.io/\">@<span class=\"p-name\">Kyle Mathews</span></a><data class=\"u-url\" value=\"did:plc:7iza6de2dwap2sbkpav7c6c6\"></data><data class=\"u-url\" value=\"acct:kyle@social.example\"></data></span>\n```\n\nThe markup follows these rules:\n\n- **The visible anchor is the contact's `https` URL.** A reader that knows\n  nothing about h-card shows a link, and clicking it works. A contact without\n  a URL renders as `<span class=\"h-card\">@<span class=\"p-name\">Name</span>…</span>`,\n  which shows a name with no link. The `@` sits outside `p-name`, so a parser\n  gets the name and the page gets the sigil.\n- **Each alternate identifier is a `<data class=\"u-url\" value=\"…\">`.**\n  microformats2 parsers read `<data value>` for `u-*` properties, and `u-url`\n  is allowed to repeat. `<data>` renders nothing, so readers that ignore it lose\n  nothing. All these values are absolute URIs, so §5.2's rule that\n  `content_html` is self-contained holds.\n- **Only `self` and `bound` identifiers go on the wire by default.** The\n  `entered` identifiers stay in the book. Putting an unchecked DID beside\n  someone's URL tells every reader that the two are the same person, and the\n  author never verified that. The author MAY choose to publish `entered`\n  identifiers per contact, but the studio should not do it unasked.\n- **Order carries no meaning.** The anchor's `href` is the primary identifier;\n  everything else is unordered.\n- **Mentions are silent on the wire**, in exactly the sense in which `[[id]]` is\n  silent (§10.1, #32). They add no `transclusions[]` entry, no relation (§15.4)\n  and no new field, and they send nothing (section 10, ruling 2).\n\nWhy this is not a spec construct: the markup is ordinary HTML using a published\nW3C-community vocabulary, inside a field that already accepts any editorial\nHTML. No reader, receiver or publisher has to change for it to work, so it fails\nevery part of #43's test for protocol. It uses no `blyg-` class and no\n`data-blyg-*` attribute. Those prefixes are spec vocabulary (§10.2), and using\none would turn this into a spec construct by the back door.\n\n### 5.4 The byline uses the same record\n\nWhen a member publishes, the studio fills `author` from their contact record:\n`name`, `url`, and the same filtered `ids`. A permalink page renders the byline\nas an h-card (`p-author h-card`) inside the item's `h-entry`. A\nmicroformats-aware reader then gets the byline and the mentions from one parse,\nand the item becomes a valid IndieWeb post without any work on the reader's part.\n\n### 5.5 The proof on a shared origin\n\n#35's proof is a reciprocal `rel=\"me\"` link: `author.url` names a page that\nlinks back to the identity origin, and the sentence both links make is \"this\nis also me\". For a one-person blyg that sentence is true in both directions.\nOn a shared origin it is false in one: Alice is not the house.\n\nThe ruling (section 10, ruling 3) keeps the proof and moves its origin-side\nend. On a shared origin the reciprocal `rel=\"me\"` runs between `author.url`\nand the member's **page under the origin** (section 3), and both directions are\nnow true statements, because both pages are Alice:\n\n- `https://alice.example/` carries `<a rel=\"me\" href=\"https://house.example/people/alice/\">`;\n- `https://house.example/people/alice/` carries `<a rel=\"me\" href=\"https://alice.example/\">`.\n\nA reader verifying a byline fetches `author.url` and looks for a `rel=\"me\"`\nlink whose `href` is either the identity origin itself (#35 as written, the\none-person case) or a URL that has the identity origin as its prefix (the\nshared case). In the second case it fetches that page and requires a\n`rel=\"me\"` back to `author.url`. Two bounded fetches, cached per\n`(author.url, origin)` pair, and the result is shown with the same chrome as\nany other verified claim: there are two states, verified and claim, and this\nadds no third. The house can write whatever it likes on its side of the pair,\nbut the house is already the party asserting the byline; what it cannot forge\nis Alice's page, which is exactly the half #35 relies on. A member whose\n`author.url` *is* the house page has nothing on the far side to check, and the\nbyline stays a claim, as section 3 says.\n\nThis is also what makes `tn-3` section 5's portability concrete: when Alice\nleaves, the house removes its `rel=\"me\"`, Alice's page points at her new\norigin, and the same reader rule follows her there.\n\n### 5.6 Agent members\n\nAn AI that runs on the same client as the human publisher and publishes with a\nmember's rights needs almost nothing from this convention, because #38 already\nsettled the protocol side: an agent is a valid opaque `author`, at the studio it\nis a token with a member's scopes, and the protocol never asks who acted. Four\nclient-side accommodations remain, none of them on the wire.\n\n1. **The roster says what the client cannot tell.** A `member: true` record can\n   be a person or an agent, and nothing in a token reveals which. An agent\n   member's record carries `operator`, the URL of the human or organisation\n   that answers for it (`tn-2` section 7), and a declared `model`. Both flow\n   into what the studio stamps on the agent's items.\n2. **The token scope decides the byline.** #52 already requires publishing to be\n   a distinct verb from drafting, and that distinction is #38's\n   response-versus-pipe line made mechanical. A draft-only token means a human\n   approves and publishes: the human's byline, and one `generated[]` span\n   naming the model. A publish-scope token means the agent publishes on its own\n   initiative: the agent's byline with `operator`, and a whole-item\n   `generated[]` span. The byline says who, the provenance says how, and the\n   operator says who answers; none of the three is collapsed into another.\n3. **Provenance in the address book is set by the resolver, never by the\n   caller.** No API path may assert `self` or `bound`. Anything an agent adds\n   to the book is `entered` and stays off the wire until the studio resolves\n   it. Without this rule an agent holding a contacts scope becomes the identity\n   broker that rejected design 5 guards against. The publish API also returns\n   unresolved `@word` warnings in machine-readable form, since an agent never\n   sees the editor's soft warning.\n4. **No pin or withdraw scopes for agent tokens by default.** A pin is an\n   irrevocable hosting promise and withdrawal is the only exit; `tn-3`'s test\n   says the house answers for both. Scope names are the build's (#52), and the\n   default is conservative.\n\nTwo of the rulings in section 10 are what make agents safe here. Ruling 2,\nmentions are silent, matters most: an agent writing a hundred items with\n@-mentions produces no notifications, where an opt-in would have been the\nflood `tn-3` section 6.2 describes by another route. Ruling 3 covers the\nbyline: an agent with only a house member page stays a claim, which is honest,\nand `operator` is likewise a claim by the origin, the party already\naccountable under invariant 4, so there is nothing further to prove.\n\nOne question is left to the client: whether a house with several human members\nshares one address book or keeps one per member. Petnames are personal by\nconstruction, and a shared newsroom contact list is also ordinary practice.\nEither works with everything above.\n\n## 6. Reading: resolving a mention in the scheme you speak\n\nA receiving client finds `.h-card` elements in `content_html` and collects the\n`href` and the `<data class=\"u-url\">` values. It then does whatever its own\nschemes allow:\n\n- **Match against its own address book.** It normalises each identifier per\n  scheme, three rules for three schemes:\n\n    - `https` URLs: as §15.4 normalizes an origin — scheme and host\n      case-insensitive, default port dropped, trailing slash normalized;\n    - `acct:` identifiers: compare case-insensitively;\n    - DIDs: compare exactly, except that a `did:pkh:eip155:…` account is\n      compared case-insensitively on the address, and a bare CAIP-10\n      `eip155:…` met in the wild is read as the same account (section 7).\n\n  The client then looks for a contact holding any of the identifiers. On a\n  match it MAY show the mention as *the reader's own* contact, under the\n  reader's petname.\n- **Resolve schemes it speaks.** An ATProto-aware reader can link the DID to a\n  Bluesky profile, a wallet-aware reader can show the ENS reverse name, and a\n  fediverse-aware reader can offer to follow the actor.\n- **Do nothing.** The link still works, which is the floor.\n\nThree rules protect readers. They mirror #35's reader rules:\n\n1. **A relabel replaces the whole mention.** If the reader shows its own\n   contact's petname, it also uses its own contact's URL as the link.\n   Otherwise a publisher could pair the victim's DID with the attacker's\n   `href`, and a reader would print the victim's name over the attacker's\n   link. With this rule, a forged pairing makes the reader show its own,\n   correct contact, with no way to redirect the click.\n2. **A mention's identifiers are the publisher's claim and never prove anything.**\n   An h-card that lists a URL and a DID together does not tell the reader that\n   they belong to one person. A reader MUST NOT add a mention's identifiers to\n   its own contact record without checking them. This is #35's rule against\n   merging identities across origins without a verified claim, applied to\n   mentions. A match against the reader's book is a display decision, never a\n   merge (§13.1 rules 5 and 7).\n3. **No counts and no gating.** \"You were mentioned 40 times\" is a follower\n   metric by another name (#12, #13). A client may list mentions of a contact\n   for its own owner. It never publishes them as a number.\n\n**Quotations carry other people's mentions.** A baked transclusion copies the\nsource's `content_html`, h-cards included (§10.2, verbatim). Those mentions are\nthe *quoted* author's speech. The quoting client MUST NOT treat them as its own,\nwhether for notification, for its book, or for display as \"mentioned by me\".\n\n**The reference reader's sanitizer drops this markup today.**\n`blygger-studio/src/importer/sanitize.ts` keeps `class`, but `data` is not in\nits tag list, so the element is unwrapped and its `value` removed. It also\nstrips any `href` that is not `http(s)`/`mailto`/`tel`, which is right. The fix\nis small: allow the `<data>` element with `value` (inert text, never fetched).\nWithout it, the reference client would publish the full identifiers and then\nthrow them away on every read. Other clients' sanitizers will vary. Every\nreader keeps the visible link, so the design degrades to an ordinary link.\n\n## 7. Scheme notes\n\n- **ActivityPub.** On the wire, an `acct:` identifier plus the actor URL as\n  `href`. Actually *notifying* a fediverse account requires delivery to its\n  inbox as an ActivityPub actor. A blyg is not an actor and should not become\n  one in order to do this. Bridges such as Bridgy Fed, which turn Webmention-sending\n  web sites into fediverse presences, are the route for anyone who wants it,\n  outside the protocol.\n- **ATProto.** Emit the DID, not the handle. A handle that is the person's own\n  domain is the best case of all: their `url` is `https://alice.example/` and\n  their DID resolves back to that domain. One record then counts as `bound` in two\n  schemes.\n- **DIDs.** `did:web` is a URL with extra steps (#35). Other methods are stored and\n  emitted when `self` (listed in the person's h-card or `rel=\"me\"` links) and are\n  otherwise left to clients that resolve them.\n- **Ethereum.** Emit the account as `did:pkh:eip155:<chain>:<address>`, which is\n  the CAIP-10 account in DID clothing and the same bytes. Writing it as a DID\n  keeps the wire to three URI schemes and spares readers a fourth normalizer;\n  readers accept a bare `eip155:…` as the same account. ENS is an input\n  convenience, because a name that can expire must never be the wire\n  identifier. Proof of control is a signature, which is #35's second proof. A\n  signed byline (EIP-191 over `content_hash`) is that proposal's mechanism,\n  unchanged. Whatever the address book does, a wallet scheme is meaningful in\n  a mention only when the person themselves published the address at their URL.\n- **h-card.** It is the carrier format. The contact's own representative h-card\n  is also where the book learns their other identifiers. In practice, a person\n  who wants to be mentionable across schemes lists them on their home page.\n\n## 8. Recommendation for the reference client\n\nThe client should stay boring (the ruling that tabled blygger-studio#35: \"studio should be\nboring\"), so its default is narrow, and every wider scheme belongs in other\nclients or in extensions.\n\n1. **Per-item bylines from a member roster**, which closes the real multi-author\n   gap. A member's `author.url` is their own URL when they have one, otherwise a\n   house member page. Tie this in with #31 tokens so each member's scoped token\n   publishes under that member's byline.\n2. **An address book with `@handle` autocomplete**, consumed at publish into a\n   markdown link in `content_md` and an h-card in `content_html`, as in\n   section 5.\n3. **Schemes it resolves when a contact is added:** `https` (h-card and `rel=\"me\"`),\n   fediverse handles (WebFinger) and ATProto handles (DNS or well-known, giving\n   the DID), plus `did:web`. These all reduce to a URL or a DNS check, and none of\n   them needs a vendored dependency (the session-29 ruling).\n4. **Schemes it stores but does not resolve:** other DIDs and `did:pkh` accounts. It\n   accepts them as `entered`, and emits them only when the contact's own page\n   lists them. ENS lookups, wallet sign-in and signature checking belong in an\n   extension, not the base client.\n5. **Its sanitizer keeps `<data value>`**, so it reads the markup it writes.\n6. **No notification.** A mention is silent like `[[id]]`; the reference client\n   sends no Webmention for one, and offers no switch to (section 10, ruling 2).\n7. **Byline verification on a shared origin** follows section 5.5 when the\n   reader side of #35 is built: one rule, two fetches, two display states.\n8. **Agent members per section 5.6:** `operator` and `model` on the roster\n   record, the byline chosen by the token's scope, resolver-only provenance in\n   the book, publish warnings returned by the API, and no pin or withdraw\n   scopes on agent tokens by default.\n9. **Later: IndieAuth for member sign-in.** IndieAuth proves that a member\n   controls their URL at the moment the house mints their token, so the\n   roster's `url` becomes verified from the member's side without a second\n   fetch. It fits #52 (an OAuth-style minting flow) and is the one IndieWeb spec\n   besides Webmention and microformats that the studio has a use for.\n\n**Of the five schemes, the reference client should emit h-card markup and\nrecognise the web, ActivityPub, ATProto and `did:web` natively, and treat\nEthereum and other DID methods as data it carries but does not interpret.**\nThe full identifier list still goes on the wire for every scheme, which is what\nlets a wallet-aware or ATProto-native client resolve what the reference client\nonly carries.\n\n## 9. Rejected designs\n\nRecorded because each will be re-proposed.\n\n1. **An `@` construct in the spec** (a MAY directive in §10.1, a `mentions[]`\n   field in the item, a `blyg:mention` feed element). Rejected because it would\n   make authors addressable (§16.8). It would also add a reference kind that\n   receivers would be expected to act on, which is a reply primitive by another\n   route. Finally, it would freeze one identifier vocabulary into a permanent\n   surface while the schemes themselves keep moving.\n2. **Leaving `@handle` in `content_md` for each reader to resolve.** A\n   petname means something only in the book that defined it. Shipping one\n   gives every forker and reader a name that resolves to whoever *they* call\n   `kyle` (section 5.2).\n3. **One canonical scheme that everyone must use** (all DIDs, or all fediverse).\n   This picks a winner among live communities. It also adds a resolver as a\n   dependency for every reader. The census shows that the field already chose\n   the URL.\n4. **`user@domain` addressing inside a shared origin.** Closed at #11 and again\n   in `tn-3` section 8: the path or subdomain already serves as the namespace.\n5. **Putting `entered` identifiers on the wire by default.** That would make\n   every author an unwitting identity broker, publishing guesses about which\n   accounts belong together.\n6. **`data-blyg-ids`.** It would survive today's sanitizer because of the\n   `data-blyg-` prefix. Rejected because that prefix is spec vocabulary, and\n   using it here would add a construct silently. Fix the sanitizer instead.\n7. **Micropub** as the members' write path. No normative write surface (#31).\n   The studio's own API with scoped tokens already serves the purpose.\n8. **Salmention-style propagation of mentions upstream.** It pushes other\n   people's responses onto a target's page. §15.5 forbids that: nothing lets a\n   stubber put words on the target's page.\n9. **A Webmention for every mention, or an opt-in switch for one in the\n   reference client.** A mention is a link, and a link notifies nobody (#32).\n   The reasoning is section 10, ruling 2; what a client that does send must\n   respect is there too.\n10. **An \"acknowledged\" display class between verified and claim**, for a\n    member's link to a shared origin. Rejected because any link from Alice's\n    page to the house proves only that Alice linked to something there, and a\n    third chrome state is more display for less proof. Section 5.5 keeps the\n    reciprocal `rel=\"me\"` and two states.\n11. **Bare CAIP-10 as the wire form of an Ethereum account.** It is a fourth\n    URI scheme for the same bytes `did:pkh:` already carries (section 7).\n\n## 10. Rulings (Fable 5.1, session 40, 2026-10-07)\n\nThe draft closed with five questions. The rulings follow, each with the\nprinciple it rests on; where a ruling differs from the draft's own\nrecommendation, it says so.\n\n**1. Sequencing.** The route is confirmed, and where it runs was decided the same\nsession (decision #66): the project's own blyg at `blyg.blygger.org` carries RFCs,\nand comment periods run there. (a) This edited draft is published as a thread on\nthat blyg, with a stated close date in the text; the version under comment is\npinned, a revision during the period is a new version, pinned in turn when\ncomments should move to it. (b) Comments are the protocol's own responses: a\nstub of the RFC item, whose `stub_of.version` records which draft it answers; a\nquote is a partial transclusion; a counter-proposal is a fork from the pin.\nAnyone without a blyg can open an issue on `blygger-spec` instead, and the item\nsays so. There is no RFC section on blygger.org. (c) Nothing in section 8 is\nbuilt in the reference client until the period closes. (d) After that, the RFC\nbecomes a technical note of its own by the gate #35 uses for `tn-2`: one client\nemits mention h-cards and a second resolves them. It does **not** fold into\n`tn-2`. That note's subject is one person's URL and the two proofs of it; this\none's is a client convention for naming *other* people, and folding them would\nmake the identity note carry a studio design. Two rulings here are about\n`author` rather than about mentions, and `tn-2` absorbs them when it is\nwritten: the shared-origin proof (ruling 3) and `ids` (ruling 5). The git file\nstays the single source throughout; the blyg publishes versions of it, never\nhand-edited copies (#66).\n\n**2. A mention does not notify.** Mentions are silent, and the reference\nclient sends nothing for one and offers no switch to. This is #32's principle\ncarried over, not a new one: a link asserts nothing on the target's behalf, so\na receiver has nothing to verify, and a notification with no verifiable claim\nbehind it is the trackback class §15.6 holds down. The `@` form is a link with\na better name, and it inherits the link's silence; \"@ notifies\" is an\nexpectation from media with reply primitives, which this one refuses (§16.8).\nTwo further facts settle the edges. §16.8's bar on a fourth relation is not in\nplay either way, because a mention's target is a person's page and never an\nitem; §15 governs mentions between blyg items, and this was never a §15\nquestion. And where a person's URL happens to be a blyg page, a plain\nWebmention to it is refused outright (§15.3 step 1: the target must name a\npublished item) or marked *failed* (§15.4 step 4), so it could only ever cost\nthe receiver fetches. What remains is the open web: any client may send a W3C\nWebmention to a non-blyg page for a link it publishes, as IndieWeb sites do,\nand this RFC neither blesses nor forbids that. A client that does so should\nobserve three things: never to a target inside a blyg origin; never for an\nh-card inside a baked quote (§10.2 verbatim, the quoted author's speech);\nnever by default, only per mention at the author's choice. This differs from\nthe draft, which recommended a per-mention opt-in in the reference client.\nThe client stays boring (blygger-studio#35), and the one way to cite without\nnotifying stays wide.\n\n**3. Reciprocity on a shared origin.** Not an acknowledgement class. The\nproof is #35's reciprocal `rel=\"me\"`, unchanged; what moves is its origin-side\nend, from the origin to the member's page under it (section 5.5). Both links\nthen say \"this is also me\" truthfully, because both pages are the member. The\nreader rule is one rule with two acceptable far ends: the identity origin\nitself, or a page that has it as a prefix and links back. Two fetches, two\ndisplay states, no third chrome. The draft's alternative, any link from\n`author.url` to the origin shown as \"linked from\", was rejected because a link\nproves that the member linked to something at the house, not that they write\nthere, and because a third state is more display for less proof (section 9,\nitem 10). This is a ruling about identity semantics, so it is Fable's under\n#58, and `tn-2` carries it when written. `tn-3` section 5 already promised\nthat a verified byline survives a move from shape B to shape A; this is what\nmakes that true.\n\n**4. The spec says nothing.** Confirmed. A sentence about preserving\nmicroformats in `content_html` would be the spec's first word, however\nindirect, about identity markup, and #11's silence on identity is a principle\nrather than an omission. Under #43 it would in any case be a revision that\nreaders already handle, and a convention one client emits is not yet a reader\nquestion. The fix lives in the reference client's sanitizer (section 8, item 5).\nRevisit when a second client emits the markup *and* a sanitizing reader's\nloss of it has caused a failure someone can name; the candidate home would be\n§13.1, not §5.2.\n\n**5. `ids` in `author`.** Allowed as a conventional member, filtered as\nsection 5.3 filters mentions. #35 already places two conventional members in\n`author`, the signature and an agent's `operator`, so a third of the same\ncharacter adds no principle. The shape: an unordered array of absolute URIs\nin the three wire schemes, `https:`, `acct:` and `did:` (Ethereum as\n`did:pkh:`, section 7), each `self` or `bound` from the member's own\npublications. Because of that filter the house relays what the member\npublishes about themselves and asserts nothing new. §5.5's pass-through rule\nbinds `ids` as it binds every `author` member, and §13.1 rules 5 and 7 still\nhold: a reader matching `ids` against its book is making a display decision,\nnever a merge. The draft's reason stands as the practical one: a reader should\nnot need a fetch to match a byline against its address book.\n\n**What happens next.** Published for comment under ruling 1 on 2026-10-07; the\nperiod closes 2026-11-04 (four weeks, as recommended). Revisions during the\nperiod are made in this file and republished as new versions of the same item. The decision list carries one entry for the five rulings (#67), with\nthis section as its reasoning.\n\n\n\n*Source: [`docs/rfcs/rfc-1-mentions-and-identifier-schemes.md`](https://github.com/blygger/blygger-spec/blob/main/docs/rfcs/rfc-1-mentions-and-identifier-schemes.md) in blygger-spec, which is where revisions are made; each one is published here as a new version. To comment, respond to this item from your own blyg: a stub is a comment, a partial quote names the passage, and a fork of the pinned version is a counter-proposal.*\n\n","content_html":"<div class=\"blyg-tk-gen\"><h1>RFC-1 — Mentions across identifier schemes: petnames in the studio, full identifiers on the wire</h1>\n<p><strong>Request for comments · non-normative · OPEN FOR COMMENT until 2026-11-04 on\n<a href=\"https://blyg.blygger.org/t/7eeh3bfzfcnhh90d5pkvkc2r1n/\">blyg.blygger.org</a> (#66); without a blyg,\ncomment on <a href=\"https://github.com/blygger/blygger-spec/issues/14\">blygger-spec#14</a> · session 40, 2026-10-07.</strong> Drafted by Opus 5.5 at Venkat Rao's request; edited the same session by\nFable 5.1, whose rulings on the five open questions are section 10. An RFC is a\nrecommendation put up for comment <em>before</em> any client builds it, because the\nreference client shipping a convention reads as a blessing. Like a technical note,\nan RFC constrains nothing. After its comment period and the gate in section 10,\nruling 1, it becomes a technical note. It builds on locked decisions #11 (the opaque\n<code>author</code>), #35 (identity practice, proposed in\n<code>docs/proposals/identity-practice-proposal.md</code>, which becomes <code>tn-2</code>), #36 (groups,\n<code>tn-3</code>), #20 (studio grammar versus wire grammar) and #32 (<code>[[id]]</code> is silent).\nWritten against protocol 0.3 as published on 2026-10-07; no pre-1.0 version promises\nanything (#21).</p>\n<h2>1. The question</h2>\n<p>Several early users have asked for <strong>multi-author blygs</strong>, and with them comes a\nsecond request: <strong>@-mentions</strong> of the people who write there and of people\nelsewhere. The request (Venkat Rao, session 40) was for three things:</p>\n<ol>\n<li>a consistent recommendation for <strong>user identifiers within a domain</strong> that can\ntravel through the protocol;</li>\n<li>an evaluation of how markup in the item body could carry the major\nidentifier schemes — <strong>W3C DIDs, Ethereum accounts, ActivityPub, ATProto and\nh-card</strong> — so that clients sharing a convention can resolve @-mentions;</li>\n<li>a convention in which <strong>the client keeps an address book of contacts across\nschemes</strong>. The author types a short <code>@handle</code>, the client looks up the full\nidentifiers in that address book, and the full identifiers travel on the\nwire, so that another client can resolve whichever scheme it speaks.</li>\n</ol>\n<p>The third request is the design. Sections 2–4 clear the ground, section 5 is the\nconvention, and sections 6–9 cover reading, scheme details, the reference\nclient's default and what is rejected. Section 10 records the rulings.</p>\n<p>The constraints are fixed. Authors are never addressable (§5.5, §16.8). The\nprotocol has no reply primitive and no fourth mention relation (§16.8). The\nprotocol has no normative write surface (#31), so nothing here comes from\nMicropub, in keeping with that decision while staying close to the IndieWeb in\nspirit. Whatever this RFC recommends has to be HTML and studio practice, not\nprotocol.</p>\n<h2>2. Correcting a premise: the single <code>author</code> does not block multi-author blygs</h2>\n<p>The worry was that an item's author field holds only one name, so a multi-author\nblyg would have to sign everything as &quot;community&quot; unless the spec changed in\na way that breaks RSS. Two parts of that are true and one is not.</p>\n<ul>\n<li><strong>A multi-author blyg does not need more than one name per item.</strong> <code>author</code> is\n<strong>per-item</strong> (§5.5). A masthead blyg with five writers publishes items whose\nbylines differ item by item. That is shape B of <code>tn-3</code>, specified since #11, and\nthe feed rule is single-<strong>publisher</strong>, never single-author. &quot;Community&quot; is only\nneeded if you want it: the Protocol Institute node already uses the byline\n&quot;Editor&quot;.</li>\n<li><strong>RSS is not the binding constraint.</strong> In RSS 2.0, the core <code>&lt;author&gt;</code> element\nis a single email address, and the protocol does not emit it. The feed carries\n<code>&lt;dc:creator&gt;</code> (§7). Dublin Core lets that element repeat, and Atom allows\nseveral <code>&lt;author&gt;</code> elements. Many feed readers show only the first creator,\nwhich is a display limit, not a format limit.</li>\n<li><strong>The real single-valued thing is the protocol's own §5.5.</strong> <code>author</code> is one\nJSON object. Only <strong>co-authored items</strong> need more than one person in it, and\n§5.5's extension point already lets them carry more without a spec change\n(section 4.1 below).</li>\n</ul>\n<p>So multi-author blygs work today and need nothing from the protocol. What the\nreference client lacks is studio-side: one <code>author_name</code> setting stamps every\nitem (<code>protocol.ts</code> sets <code>author.url</code> to the origin). That is a client gap, and\nsection 8 addresses it.</p>\n<p><strong>The census, re-run 2026-10-07</strong> against the 20 blygs listed at <a href=\"http://blygger.com\">blygger.com</a> (19\nreachable), the three newest items each: every item <code>author</code> is <code>{name, url}</code>,\n<code>{name}</code>, or absent. No client has invented an authorspace grammar, no item has\ntwo people in it, and no body contains an h-card or mention markup.\nManifest-level <code>author</code> has grown <code>bio</code>, <code>links</code> and <code>avatar</code> in several clients.\nThe per-item field is still empty, so this is still the cheapest time to\nrecommend something.</p>\n<h2>3. Identifiers within a domain</h2>\n<p>In shape B (one origin, many bylines), what identifies a member? The answer\nfollows from #35's spine — <strong>a person is a URL they control</strong> — with one\nconcession for people who have no URL of their own:</p>\n<table>\n<thead>\n<tr>\n<th>Member has…</th>\n<th><code>author.url</code></th>\n<th>What it proves</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>their own site, profile or actor URL</td>\n<td>that URL</td>\n<td>portable. If the page links back (section 5.5), a reader can confirm the byline from the member's side.</td>\n</tr>\n<tr>\n<td>nothing of their own</td>\n<td>a house-hosted member page, e.g. <code>https://house.example/people/alice/</code></td>\n<td>only that <strong>the house</strong> says so. That is honest: in shape B the house answers for everything (<code>tn-3</code> section 5).</td>\n</tr>\n</tbody>\n</table>\n<p>The member page is presentation. It is an HTML page like any <code>page</code>, not a\nprotocol construct, so it does not make authors addressable in §16.8's sense:\nnothing in the protocol references it. It has a second job, which section 5.5\ngives it: it is the origin-side end of the reciprocal proof for a member who\ndoes have their own URL. A member who later moves to their own origin (shape A)\ntakes their own URL with them. A house URL does not travel. That is the\npractical reason to prefer the member's own URL whenever they have one.</p>\n<p><strong>No <code>user@domain</code> grammar inside an origin.</strong> <code>@alice</code> as typed in the studio is\na <strong>petname</strong>, a name that is meaningful only in this address book (section 5).\nIt never reaches the wire as an identifier. DNS remains the namespace (#11).</p>\n<h2>4. The five schemes, evaluated</h2>\n<p>Each scheme answers four questions:</p>\n<ul>\n<li>What is its <strong>stable</strong> identifier, as opposed to its human-readable name?</li>\n<li>Can a reader resolve it with an ordinary fetch?</li>\n<li>How does a person prove control of it?</li>\n<li>What does it reduce to under #35's two proofs: a reciprocal link, or a\nsignature?</li>\n</ul>\n<table>\n<thead>\n<tr>\n<th>Scheme</th>\n<th>Human name (mutable)</th>\n<th>Stable identifier to put on the wire</th>\n<th>Resolution</th>\n<th>Proof</th>\n<th>Reduces to</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><strong>Web / h-card</strong></td>\n<td>the URL itself</td>\n<td><code>https://alice.example/</code></td>\n<td>fetch, then parse the representative h-card</td>\n<td><code>rel=&quot;me&quot;</code> reciprocal links</td>\n<td>link (it <em>is</em> #35)</td>\n</tr>\n<tr>\n<td><strong>ActivityPub</strong></td>\n<td><code>@alice@social.example</code></td>\n<td><code>acct:alice@social.example</code> (RFC 7565), plus the actor's <code>https</code> URL</td>\n<td>WebFinger (RFC 7033) maps <code>acct:</code> to the actor URL</td>\n<td>Mastodon-family servers check <code>rel=&quot;me&quot;</code> on the links in a profile and serve <code>rel=&quot;me&quot;</code> on profiles themselves</td>\n<td>link</td>\n</tr>\n<tr>\n<td><strong>ATProto</strong></td>\n<td>handle <code>alice.example</code> or <code>alice.bsky.social</code></td>\n<td>the DID, usually <code>did:plc:…</code></td>\n<td>DNS TXT <code>_atproto.&lt;handle&gt;</code> or <code>https://&lt;handle&gt;/.well-known/atproto-did</code>, and the DID document's <code>alsoKnownAs</code> points back</td>\n<td>two-way handle↔DID binding. A domain handle is DNS control.</td>\n<td>link (a domain handle is a URL the person controls)</td>\n</tr>\n<tr>\n<td><strong>W3C DID</strong></td>\n<td>none</td>\n<td><code>did:&lt;method&gt;:…</code></td>\n<td>method-specific. <code>did:web</code> is an HTTPS fetch. <code>did:plc</code> needs a directory. <code>did:key</code> and <code>did:pkh</code> resolve locally.</td>\n<td><code>did:web</code>: DNS. Others: a key in the document</td>\n<td><code>did:web</code> reduces to a link. The others reduce to a signature.</td>\n</tr>\n<tr>\n<td><strong>Ethereum</strong></td>\n<td>ENS name <code>alice.eth</code></td>\n<td>the account as a DID, <code>did:pkh:eip155:1:0xAb…</code> (the CAIP-10 account <code>eip155:1:0xAb…</code> wrapped; see section 7)</td>\n<td>ENS needs chain access (an RPC endpoint); the account needs nothing</td>\n<td>EIP-191 signature (e.g. over <code>content_hash</code>, #35 §4.2); EIP-4361 for sign-in</td>\n<td>signature</td>\n</tr>\n</tbody>\n</table>\n<p>Four observations decide the design.</p>\n<ol>\n<li><strong>h-card is not a rival scheme. It is the envelope.</strong> It is the IndieWeb's\nformat for &quot;here is a person and their identifiers&quot;: <code>p-name</code>, <code>u-url</code>\n(which may repeat), <code>u-uid</code>, and <code>u-key</code>. Every other row can be written\n<em>inside</em> an h-card. That makes it the natural carrier for request 3, and it\nis already how Mastodon marks up mentions in HTML (<code>&lt;span class=&quot;h-card&quot;&gt;&lt;a class=&quot;u-url mention&quot; href=&quot;…&quot;&gt;@&lt;span&gt;alice&lt;/span&gt;&lt;/a&gt;&lt;/span&gt;</code>).</li>\n<li><strong>Put the stable identifier on the wire, never the name.</strong> ENS names expire\nand transfer, ATProto handles change, and fediverse accounts migrate. The\naddress, the DID and the actor's <code>acct:</code> are what a distant reader can still\nmatch a year later. The web is the exception, because the URL is both the\nname and the identifier. That is exactly why #35 chose it.</li>\n<li><strong>Three of the five reduce to &quot;a URL the person controls&quot;.</strong> Those are the\nweb, ActivityPub, and ATProto with a domain handle. <code>did:web</code> joins them.\nOnly <code>did:plc</code>/<code>did:key</code> and Ethereum need a signature or a non-HTTP resolver.\nThe default can therefore stay boring (section 8) and lose almost nothing.</li>\n<li><strong>The schemes differ in cost to the reader, not just in reach.</strong> Resolving\nan ENS name needs chain access, and <code>did:plc</code> needs a third-party\ndirectory. A static reader cannot do either. Any convention has to work for\na reader that resolves <em>nothing</em>, and that pushes the visible fallback onto\na plain <code>https</code> link.</li>\n</ol>\n<p>A fifth, smaller observation sets the wire vocabulary: with Ethereum accounts\nwritten as <code>did:pkh:</code>, <strong>everything on the wire is an <code>https:</code>, <code>acct:</code> or\n<code>did:</code> URI</strong>. Three schemes, three normalization rules (section 6), and a\nmatcher needs nothing else.</p>\n<h3>4.1 What <code>author</code> can carry for co-authored items</h3>\n<p>A co-authored item keeps one <code>author</code> object, as §5.5 requires. It can use the\nextension point §5.5 grants, so no spec change is needed:</p>\n<pre><code class=\"language-json\">&quot;author&quot;: {\n  &quot;name&quot;: &quot;Alice Ng and Bob Ruiz&quot;,\n  &quot;url&quot;: &quot;https://house.example/&quot;,\n  &quot;coauthors&quot;: [\n    { &quot;name&quot;: &quot;Alice Ng&quot;, &quot;url&quot;: &quot;https://alice.example/&quot;, &quot;ids&quot;: [&quot;did:plc:7iza6de2dwap2sbkpav7c6c6&quot;] },\n    { &quot;name&quot;: &quot;Bob Ruiz&quot;, &quot;url&quot;: &quot;https://social.example/users/bob&quot;, &quot;ids&quot;: [&quot;acct:bob@social.example&quot;] }\n  ]\n}\n</code></pre>\n<p>A reader that knows only <code>name</code> shows &quot;Alice Ng and Bob Ruiz&quot;, which is correct.\n<code>&lt;dc:creator&gt;</code> carries the same combined string. Emitting one <code>&lt;dc:creator&gt;</code> per\nperson is legal, but readers that show only the first would drop Bob. For a\nsingle author, <code>ids</code> sits directly in <code>author</code> beside <code>url</code>. <code>ids</code> is the same\narray as a mention's alternate identifiers (section 5), with the same emission\nrule, and is ruled in as a conventional member in section 10, ruling 5. It is\ndistinct from the manifest-level <code>links</code> that several clients already emit:\n<code>links</code> are labelled links for display, <code>ids</code> are identifiers for matching.</p>\n<h2>5. The convention: an address book of petnames, full identifiers on the wire</h2>\n<p>This is the design the request asked for. It takes its shape from <strong>petname\nsystems</strong>, and in particular from Zooko's triangle. Zooko's observation was\nthat a name cannot be global, secure and memorable all at once. The standard\nresolution, used by Stiegler's petname designs and by every phone's\ncontact list, is to keep the memorable name local, to the person who chose it,\nand to send the global, secure identifier. <code>@kyle</code> is memorable only in\none studio. <code>did:plc:…</code> is global and verifiable but nobody can type it.\nSo the address book holds the mapping, and the wire carries only what other\nclients can check.</p>\n<h3>5.1 The address book (studio-private)</h3>\n<p>Each contact record holds:</p>\n<ul>\n<li>\n<p><code>handle</code>: the petname the author types (<code>kyle</code>). It is unique within the\nbook. <strong>It never leaves the studio.</strong></p>\n</li>\n<li>\n<p><code>name</code>: the display name used when the mention renders.</p>\n</li>\n<li>\n<p><code>url</code>: the primary <code>https</code> URL, used as the link target. It is optional only\nfor a contact who has no web presence at all, for example an Ethereum-only\ncontact.</p>\n</li>\n<li>\n<p><code>ids[]</code>: alternate identifiers in their stable form (section 4 observation 2).\nEach carries <strong>provenance</strong>:</p>\n<ul>\n<li><code>self</code> means the contact publishes it themselves, for example as a\n<code>rel=&quot;me&quot;</code> link or an h-card <code>u-url</code> at their <code>url</code>, or as an\n<code>alsoKnownAs</code> entry in their DID document;</li>\n<li><code>bound</code> means the scheme's own two-way binding was checked. Examples are a\nhandle and DID that point at each other, or WebFinger agreeing with the\nactor;</li>\n<li><code>entered</code> means the author typed it in, and nothing has checked it.</li>\n</ul>\n</li>\n<li>\n<p><code>member: true</code> for people who publish at this origin. In shape B the\nhouse's member roster is simply the book's member entries. The roster supplies\neach member's byline, and the members sign in with #31's scoped tokens. The\nroster changes nothing about accountability: the house still withdraws any\nitem and owns every pin (<code>tn-3</code> section 5).</p>\n</li>\n</ul>\n<p><strong>How the book fills itself.</strong> When the author adds a contact by any single\nidentifier, the studio resolves outward from it and gathers what it can:</p>\n<ul>\n<li>from a URL, it fetches the page and reads the representative h-card and the\n<code>rel=&quot;me&quot;</code> links, which reveal the person's fediverse, Bluesky and GitHub\nprofiles, all <code>self</code>;</li>\n<li>from <code>@alice@social.example</code>, it runs WebFinger, reaches the actor, and reads\nthe actor's profile links;</li>\n<li>from an ATProto handle, it resolves the DID and checks the DID document's\n<code>alsoKnownAs</code>;</li>\n<li>from <code>did:web</code>, it fetches the DID document.</li>\n</ul>\n<p>Subscriptions supply contacts for free: every subscribed blyg's <code>author</code> already\ncarries a <code>name</code> and <code>url</code>, and the studio can offer to add it.</p>\n<h3>5.2 Writing: <code>@handle</code> is studio grammar and is consumed at publish</h3>\n<p>The editor offers autocomplete on <code>@</code>. The grammar is <strong>studio-private</strong> under\n#20's two-layer split, like TK. It is consumed at publish, and it never appears\nin <code>content_md</code>:</p>\n<ul>\n<li><code>@kyle</code> that matches a contact turns into a mention.</li>\n<li><code>@word</code> that matches nothing stays literal text, and the editor shows a soft\nwarning with an &quot;add contact&quot; action. It is never a publish error, because <code>@</code>\nis common in prose, in code and in email addresses. Text in code spans and code\nblocks is never touched, which is the same rule as #54.</li>\n</ul>\n<p><strong>Why it must be consumed rather than left in <code>content_md</code>:</strong> forkers re-parse\n<code>content_md</code> (#63). If <code>@kyle</code> stayed in the text, it would travel to a forker\nwhose address book has no <code>kyle</code>, or a different one. That would make one\nperson's petname resolve to another person in someone else's fork. Under\n#43's boundary test, a grammar that a third party has to re-parse belongs to the\nprotocol. This one must not become protocol (§16.8), so it must not survive\npublish.</p>\n<p>The same fact sets what a fork keeps. A forked thread descends from the pinned\ndocument (#57), so its baked <code>content_html</code> carries the h-cards. A forked\n<em>fragment</em> is re-rendered from <code>content_md</code> (#63), so it carries the plain\nlink and not the alternate identifiers, unless the forking client's own book\nknows the URL and re-wraps it. That is correct: the identifiers were the\noriginal publisher's statement about their contact, and a fork is the forker's\nspeech.</p>\n<h3>5.3 What goes on the wire</h3>\n<p><strong>In <code>content_md</code>:</strong> a plain markdown link, which any markdown reader understands:</p>\n<pre><code class=\"language-markdown\">Thanks to [@Kyle Mathews](https://bricolage.io/) for the edge-cache work.\n</code></pre>\n<p><strong>In <code>content_html</code>:</strong> the same link, wrapped as an h-card that carries the\ncontact's alternate identifiers:</p>\n<pre><code class=\"language-html\">&lt;span class=&quot;h-card&quot;&gt;&lt;a class=&quot;u-url&quot; href=&quot;https://bricolage.io/&quot;&gt;@&lt;span class=&quot;p-name&quot;&gt;Kyle Mathews&lt;/span&gt;&lt;/a&gt;&lt;data class=&quot;u-url&quot; value=&quot;did:plc:7iza6de2dwap2sbkpav7c6c6&quot;&gt;&lt;/data&gt;&lt;data class=&quot;u-url&quot; value=&quot;acct:kyle@social.example&quot;&gt;&lt;/data&gt;&lt;/span&gt;\n</code></pre>\n<p>The markup follows these rules:</p>\n<ul>\n<li><strong>The visible anchor is the contact's <code>https</code> URL.</strong> A reader that knows\nnothing about h-card shows a link, and clicking it works. A contact without\na URL renders as <code>&lt;span class=&quot;h-card&quot;&gt;@&lt;span class=&quot;p-name&quot;&gt;Name&lt;/span&gt;…&lt;/span&gt;</code>,\nwhich shows a name with no link. The <code>@</code> sits outside <code>p-name</code>, so a parser\ngets the name and the page gets the sigil.</li>\n<li><strong>Each alternate identifier is a <code>&lt;data class=&quot;u-url&quot; value=&quot;…&quot;&gt;</code>.</strong>\nmicroformats2 parsers read <code>&lt;data value&gt;</code> for <code>u-*</code> properties, and <code>u-url</code>\nis allowed to repeat. <code>&lt;data&gt;</code> renders nothing, so readers that ignore it lose\nnothing. All these values are absolute URIs, so §5.2's rule that\n<code>content_html</code> is self-contained holds.</li>\n<li><strong>Only <code>self</code> and <code>bound</code> identifiers go on the wire by default.</strong> The\n<code>entered</code> identifiers stay in the book. Putting an unchecked DID beside\nsomeone's URL tells every reader that the two are the same person, and the\nauthor never verified that. The author MAY choose to publish <code>entered</code>\nidentifiers per contact, but the studio should not do it unasked.</li>\n<li><strong>Order carries no meaning.</strong> The anchor's <code>href</code> is the primary identifier;\neverything else is unordered.</li>\n<li><strong>Mentions are silent on the wire</strong>, in exactly the sense in which <code>[[id]]</code> is\nsilent (§10.1, #32). They add no <code>transclusions[]</code> entry, no relation (§15.4)\nand no new field, and they send nothing (section 10, ruling 2).</li>\n</ul>\n<p>Why this is not a spec construct: the markup is ordinary HTML using a published\nW3C-community vocabulary, inside a field that already accepts any editorial\nHTML. No reader, receiver or publisher has to change for it to work, so it fails\nevery part of #43's test for protocol. It uses no <code>blyg-</code> class and no\n<code>data-blyg-*</code> attribute. Those prefixes are spec vocabulary (§10.2), and using\none would turn this into a spec construct by the back door.</p>\n<h3>5.4 The byline uses the same record</h3>\n<p>When a member publishes, the studio fills <code>author</code> from their contact record:\n<code>name</code>, <code>url</code>, and the same filtered <code>ids</code>. A permalink page renders the byline\nas an h-card (<code>p-author h-card</code>) inside the item's <code>h-entry</code>. A\nmicroformats-aware reader then gets the byline and the mentions from one parse,\nand the item becomes a valid IndieWeb post without any work on the reader's part.</p>\n<h3>5.5 The proof on a shared origin</h3>\n<p>#35's proof is a reciprocal <code>rel=&quot;me&quot;</code> link: <code>author.url</code> names a page that\nlinks back to the identity origin, and the sentence both links make is &quot;this\nis also me&quot;. For a one-person blyg that sentence is true in both directions.\nOn a shared origin it is false in one: Alice is not the house.</p>\n<p>The ruling (section 10, ruling 3) keeps the proof and moves its origin-side\nend. On a shared origin the reciprocal <code>rel=&quot;me&quot;</code> runs between <code>author.url</code>\nand the member's <strong>page under the origin</strong> (section 3), and both directions are\nnow true statements, because both pages are Alice:</p>\n<ul>\n<li><code>https://alice.example/</code> carries <code>&lt;a rel=&quot;me&quot; href=&quot;https://house.example/people/alice/&quot;&gt;</code>;</li>\n<li><code>https://house.example/people/alice/</code> carries <code>&lt;a rel=&quot;me&quot; href=&quot;https://alice.example/&quot;&gt;</code>.</li>\n</ul>\n<p>A reader verifying a byline fetches <code>author.url</code> and looks for a <code>rel=&quot;me&quot;</code>\nlink whose <code>href</code> is either the identity origin itself (#35 as written, the\none-person case) or a URL that has the identity origin as its prefix (the\nshared case). In the second case it fetches that page and requires a\n<code>rel=&quot;me&quot;</code> back to <code>author.url</code>. Two bounded fetches, cached per\n<code>(author.url, origin)</code> pair, and the result is shown with the same chrome as\nany other verified claim: there are two states, verified and claim, and this\nadds no third. The house can write whatever it likes on its side of the pair,\nbut the house is already the party asserting the byline; what it cannot forge\nis Alice's page, which is exactly the half #35 relies on. A member whose\n<code>author.url</code> <em>is</em> the house page has nothing on the far side to check, and the\nbyline stays a claim, as section 3 says.</p>\n<p>This is also what makes <code>tn-3</code> section 5's portability concrete: when Alice\nleaves, the house removes its <code>rel=&quot;me&quot;</code>, Alice's page points at her new\norigin, and the same reader rule follows her there.</p>\n<h3>5.6 Agent members</h3>\n<p>An AI that runs on the same client as the human publisher and publishes with a\nmember's rights needs almost nothing from this convention, because #38 already\nsettled the protocol side: an agent is a valid opaque <code>author</code>, at the studio it\nis a token with a member's scopes, and the protocol never asks who acted. Four\nclient-side accommodations remain, none of them on the wire.</p>\n<ol>\n<li><strong>The roster says what the client cannot tell.</strong> A <code>member: true</code> record can\nbe a person or an agent, and nothing in a token reveals which. An agent\nmember's record carries <code>operator</code>, the URL of the human or organisation\nthat answers for it (<code>tn-2</code> section 7), and a declared <code>model</code>. Both flow\ninto what the studio stamps on the agent's items.</li>\n<li><strong>The token scope decides the byline.</strong> #52 already requires publishing to be\na distinct verb from drafting, and that distinction is #38's\nresponse-versus-pipe line made mechanical. A draft-only token means a human\napproves and publishes: the human's byline, and one <code>generated[]</code> span\nnaming the model. A publish-scope token means the agent publishes on its own\ninitiative: the agent's byline with <code>operator</code>, and a whole-item\n<code>generated[]</code> span. The byline says who, the provenance says how, and the\noperator says who answers; none of the three is collapsed into another.</li>\n<li><strong>Provenance in the address book is set by the resolver, never by the\ncaller.</strong> No API path may assert <code>self</code> or <code>bound</code>. Anything an agent adds\nto the book is <code>entered</code> and stays off the wire until the studio resolves\nit. Without this rule an agent holding a contacts scope becomes the identity\nbroker that rejected design 5 guards against. The publish API also returns\nunresolved <code>@word</code> warnings in machine-readable form, since an agent never\nsees the editor's soft warning.</li>\n<li><strong>No pin or withdraw scopes for agent tokens by default.</strong> A pin is an\nirrevocable hosting promise and withdrawal is the only exit; <code>tn-3</code>'s test\nsays the house answers for both. Scope names are the build's (#52), and the\ndefault is conservative.</li>\n</ol>\n<p>Two of the rulings in section 10 are what make agents safe here. Ruling 2,\nmentions are silent, matters most: an agent writing a hundred items with\n@-mentions produces no notifications, where an opt-in would have been the\nflood <code>tn-3</code> section 6.2 describes by another route. Ruling 3 covers the\nbyline: an agent with only a house member page stays a claim, which is honest,\nand <code>operator</code> is likewise a claim by the origin, the party already\naccountable under invariant 4, so there is nothing further to prove.</p>\n<p>One question is left to the client: whether a house with several human members\nshares one address book or keeps one per member. Petnames are personal by\nconstruction, and a shared newsroom contact list is also ordinary practice.\nEither works with everything above.</p>\n<h2>6. Reading: resolving a mention in the scheme you speak</h2>\n<p>A receiving client finds <code>.h-card</code> elements in <code>content_html</code> and collects the\n<code>href</code> and the <code>&lt;data class=&quot;u-url&quot;&gt;</code> values. It then does whatever its own\nschemes allow:</p>\n<ul>\n<li>\n<p><strong>Match against its own address book.</strong> It normalises each identifier per\nscheme, three rules for three schemes:</p>\n<ul>\n<li><code>https</code> URLs: as §15.4 normalizes an origin — scheme and host\ncase-insensitive, default port dropped, trailing slash normalized;</li>\n<li><code>acct:</code> identifiers: compare case-insensitively;</li>\n<li>DIDs: compare exactly, except that a <code>did:pkh:eip155:…</code> account is\ncompared case-insensitively on the address, and a bare CAIP-10\n<code>eip155:…</code> met in the wild is read as the same account (section 7).</li>\n</ul>\n<p>The client then looks for a contact holding any of the identifiers. On a\nmatch it MAY show the mention as <em>the reader's own</em> contact, under the\nreader's petname.</p>\n</li>\n<li>\n<p><strong>Resolve schemes it speaks.</strong> An ATProto-aware reader can link the DID to a\nBluesky profile, a wallet-aware reader can show the ENS reverse name, and a\nfediverse-aware reader can offer to follow the actor.</p>\n</li>\n<li>\n<p><strong>Do nothing.</strong> The link still works, which is the floor.</p>\n</li>\n</ul>\n<p>Three rules protect readers. They mirror #35's reader rules:</p>\n<ol>\n<li><strong>A relabel replaces the whole mention.</strong> If the reader shows its own\ncontact's petname, it also uses its own contact's URL as the link.\nOtherwise a publisher could pair the victim's DID with the attacker's\n<code>href</code>, and a reader would print the victim's name over the attacker's\nlink. With this rule, a forged pairing makes the reader show its own,\ncorrect contact, with no way to redirect the click.</li>\n<li><strong>A mention's identifiers are the publisher's claim and never prove anything.</strong>\nAn h-card that lists a URL and a DID together does not tell the reader that\nthey belong to one person. A reader MUST NOT add a mention's identifiers to\nits own contact record without checking them. This is #35's rule against\nmerging identities across origins without a verified claim, applied to\nmentions. A match against the reader's book is a display decision, never a\nmerge (§13.1 rules 5 and 7).</li>\n<li><strong>No counts and no gating.</strong> &quot;You were mentioned 40 times&quot; is a follower\nmetric by another name (#12, #13). A client may list mentions of a contact\nfor its own owner. It never publishes them as a number.</li>\n</ol>\n<p><strong>Quotations carry other people's mentions.</strong> A baked transclusion copies the\nsource's <code>content_html</code>, h-cards included (§10.2, verbatim). Those mentions are\nthe <em>quoted</em> author's speech. The quoting client MUST NOT treat them as its own,\nwhether for notification, for its book, or for display as &quot;mentioned by me&quot;.</p>\n<p><strong>The reference reader's sanitizer drops this markup today.</strong>\n<code>blygger-studio/src/importer/sanitize.ts</code> keeps <code>class</code>, but <code>data</code> is not in\nits tag list, so the element is unwrapped and its <code>value</code> removed. It also\nstrips any <code>href</code> that is not <code>http(s)</code>/<code>mailto</code>/<code>tel</code>, which is right. The fix\nis small: allow the <code>&lt;data&gt;</code> element with <code>value</code> (inert text, never fetched).\nWithout it, the reference client would publish the full identifiers and then\nthrow them away on every read. Other clients' sanitizers will vary. Every\nreader keeps the visible link, so the design degrades to an ordinary link.</p>\n<h2>7. Scheme notes</h2>\n<ul>\n<li><strong>ActivityPub.</strong> On the wire, an <code>acct:</code> identifier plus the actor URL as\n<code>href</code>. Actually <em>notifying</em> a fediverse account requires delivery to its\ninbox as an ActivityPub actor. A blyg is not an actor and should not become\none in order to do this. Bridges such as Bridgy Fed, which turn Webmention-sending\nweb sites into fediverse presences, are the route for anyone who wants it,\noutside the protocol.</li>\n<li><strong>ATProto.</strong> Emit the DID, not the handle. A handle that is the person's own\ndomain is the best case of all: their <code>url</code> is <code>https://alice.example/</code> and\ntheir DID resolves back to that domain. One record then counts as <code>bound</code> in two\nschemes.</li>\n<li><strong>DIDs.</strong> <code>did:web</code> is a URL with extra steps (#35). Other methods are stored and\nemitted when <code>self</code> (listed in the person's h-card or <code>rel=&quot;me&quot;</code> links) and are\notherwise left to clients that resolve them.</li>\n<li><strong>Ethereum.</strong> Emit the account as <code>did:pkh:eip155:&lt;chain&gt;:&lt;address&gt;</code>, which is\nthe CAIP-10 account in DID clothing and the same bytes. Writing it as a DID\nkeeps the wire to three URI schemes and spares readers a fourth normalizer;\nreaders accept a bare <code>eip155:…</code> as the same account. ENS is an input\nconvenience, because a name that can expire must never be the wire\nidentifier. Proof of control is a signature, which is #35's second proof. A\nsigned byline (EIP-191 over <code>content_hash</code>) is that proposal's mechanism,\nunchanged. Whatever the address book does, a wallet scheme is meaningful in\na mention only when the person themselves published the address at their URL.</li>\n<li><strong>h-card.</strong> It is the carrier format. The contact's own representative h-card\nis also where the book learns their other identifiers. In practice, a person\nwho wants to be mentionable across schemes lists them on their home page.</li>\n</ul>\n<h2>8. Recommendation for the reference client</h2>\n<p>The client should stay boring (the ruling that tabled blygger-studio#35: &quot;studio should be\nboring&quot;), so its default is narrow, and every wider scheme belongs in other\nclients or in extensions.</p>\n<ol>\n<li><strong>Per-item bylines from a member roster</strong>, which closes the real multi-author\ngap. A member's <code>author.url</code> is their own URL when they have one, otherwise a\nhouse member page. Tie this in with #31 tokens so each member's scoped token\npublishes under that member's byline.</li>\n<li><strong>An address book with <code>@handle</code> autocomplete</strong>, consumed at publish into a\nmarkdown link in <code>content_md</code> and an h-card in <code>content_html</code>, as in\nsection 5.</li>\n<li><strong>Schemes it resolves when a contact is added:</strong> <code>https</code> (h-card and <code>rel=&quot;me&quot;</code>),\nfediverse handles (WebFinger) and ATProto handles (DNS or well-known, giving\nthe DID), plus <code>did:web</code>. These all reduce to a URL or a DNS check, and none of\nthem needs a vendored dependency (the session-29 ruling).</li>\n<li><strong>Schemes it stores but does not resolve:</strong> other DIDs and <code>did:pkh</code> accounts. It\naccepts them as <code>entered</code>, and emits them only when the contact's own page\nlists them. ENS lookups, wallet sign-in and signature checking belong in an\nextension, not the base client.</li>\n<li><strong>Its sanitizer keeps <code>&lt;data value&gt;</code></strong>, so it reads the markup it writes.</li>\n<li><strong>No notification.</strong> A mention is silent like <code>[[id]]</code>; the reference client\nsends no Webmention for one, and offers no switch to (section 10, ruling 2).</li>\n<li><strong>Byline verification on a shared origin</strong> follows section 5.5 when the\nreader side of #35 is built: one rule, two fetches, two display states.</li>\n<li><strong>Agent members per section 5.6:</strong> <code>operator</code> and <code>model</code> on the roster\nrecord, the byline chosen by the token's scope, resolver-only provenance in\nthe book, publish warnings returned by the API, and no pin or withdraw\nscopes on agent tokens by default.</li>\n<li><strong>Later: IndieAuth for member sign-in.</strong> IndieAuth proves that a member\ncontrols their URL at the moment the house mints their token, so the\nroster's <code>url</code> becomes verified from the member's side without a second\nfetch. It fits #52 (an OAuth-style minting flow) and is the one IndieWeb spec\nbesides Webmention and microformats that the studio has a use for.</li>\n</ol>\n<p><strong>Of the five schemes, the reference client should emit h-card markup and\nrecognise the web, ActivityPub, ATProto and <code>did:web</code> natively, and treat\nEthereum and other DID methods as data it carries but does not interpret.</strong>\nThe full identifier list still goes on the wire for every scheme, which is what\nlets a wallet-aware or ATProto-native client resolve what the reference client\nonly carries.</p>\n<h2>9. Rejected designs</h2>\n<p>Recorded because each will be re-proposed.</p>\n<ol>\n<li><strong>An <code>@</code> construct in the spec</strong> (a MAY directive in §10.1, a <code>mentions[]</code>\nfield in the item, a <code>blyg:mention</code> feed element). Rejected because it would\nmake authors addressable (§16.8). It would also add a reference kind that\nreceivers would be expected to act on, which is a reply primitive by another\nroute. Finally, it would freeze one identifier vocabulary into a permanent\nsurface while the schemes themselves keep moving.</li>\n<li><strong>Leaving <code>@handle</code> in <code>content_md</code> for each reader to resolve.</strong> A\npetname means something only in the book that defined it. Shipping one\ngives every forker and reader a name that resolves to whoever <em>they</em> call\n<code>kyle</code> (section 5.2).</li>\n<li><strong>One canonical scheme that everyone must use</strong> (all DIDs, or all fediverse).\nThis picks a winner among live communities. It also adds a resolver as a\ndependency for every reader. The census shows that the field already chose\nthe URL.</li>\n<li><strong><code>user@domain</code> addressing inside a shared origin.</strong> Closed at #11 and again\nin <code>tn-3</code> section 8: the path or subdomain already serves as the namespace.</li>\n<li><strong>Putting <code>entered</code> identifiers on the wire by default.</strong> That would make\nevery author an unwitting identity broker, publishing guesses about which\naccounts belong together.</li>\n<li><strong><code>data-blyg-ids</code>.</strong> It would survive today's sanitizer because of the\n<code>data-blyg-</code> prefix. Rejected because that prefix is spec vocabulary, and\nusing it here would add a construct silently. Fix the sanitizer instead.</li>\n<li><strong>Micropub</strong> as the members' write path. No normative write surface (#31).\nThe studio's own API with scoped tokens already serves the purpose.</li>\n<li><strong>Salmention-style propagation of mentions upstream.</strong> It pushes other\npeople's responses onto a target's page. §15.5 forbids that: nothing lets a\nstubber put words on the target's page.</li>\n<li><strong>A Webmention for every mention, or an opt-in switch for one in the\nreference client.</strong> A mention is a link, and a link notifies nobody (#32).\nThe reasoning is section 10, ruling 2; what a client that does send must\nrespect is there too.</li>\n<li><strong>An &quot;acknowledged&quot; display class between verified and claim</strong>, for a\nmember's link to a shared origin. Rejected because any link from Alice's\npage to the house proves only that Alice linked to something there, and a\nthird chrome state is more display for less proof. Section 5.5 keeps the\nreciprocal <code>rel=&quot;me&quot;</code> and two states.</li>\n<li><strong>Bare CAIP-10 as the wire form of an Ethereum account.</strong> It is a fourth\nURI scheme for the same bytes <code>did:pkh:</code> already carries (section 7).</li>\n</ol>\n<h2>10. Rulings (Fable 5.1, session 40, 2026-10-07)</h2>\n<p>The draft closed with five questions. The rulings follow, each with the\nprinciple it rests on; where a ruling differs from the draft's own\nrecommendation, it says so.</p>\n<p><strong>1. Sequencing.</strong> The route is confirmed, and where it runs was decided the same\nsession (decision #66): the project's own blyg at <code>blyg.blygger.org</code> carries RFCs,\nand comment periods run there. (a) This edited draft is published as a thread on\nthat blyg, with a stated close date in the text; the version under comment is\npinned, a revision during the period is a new version, pinned in turn when\ncomments should move to it. (b) Comments are the protocol's own responses: a\nstub of the RFC item, whose <code>stub_of.version</code> records which draft it answers; a\nquote is a partial transclusion; a counter-proposal is a fork from the pin.\nAnyone without a blyg can open an issue on <code>blygger-spec</code> instead, and the item\nsays so. There is no RFC section on <a href=\"http://blygger.org\">blygger.org</a>. (c) Nothing in section 8 is\nbuilt in the reference client until the period closes. (d) After that, the RFC\nbecomes a technical note of its own by the gate #35 uses for <code>tn-2</code>: one client\nemits mention h-cards and a second resolves them. It does <strong>not</strong> fold into\n<code>tn-2</code>. That note's subject is one person's URL and the two proofs of it; this\none's is a client convention for naming <em>other</em> people, and folding them would\nmake the identity note carry a studio design. Two rulings here are about\n<code>author</code> rather than about mentions, and <code>tn-2</code> absorbs them when it is\nwritten: the shared-origin proof (ruling 3) and <code>ids</code> (ruling 5). The git file\nstays the single source throughout; the blyg publishes versions of it, never\nhand-edited copies (#66).</p>\n<p><strong>2. A mention does not notify.</strong> Mentions are silent, and the reference\nclient sends nothing for one and offers no switch to. This is #32's principle\ncarried over, not a new one: a link asserts nothing on the target's behalf, so\na receiver has nothing to verify, and a notification with no verifiable claim\nbehind it is the trackback class §15.6 holds down. The <code>@</code> form is a link with\na better name, and it inherits the link's silence; &quot;@ notifies&quot; is an\nexpectation from media with reply primitives, which this one refuses (§16.8).\nTwo further facts settle the edges. §16.8's bar on a fourth relation is not in\nplay either way, because a mention's target is a person's page and never an\nitem; §15 governs mentions between blyg items, and this was never a §15\nquestion. And where a person's URL happens to be a blyg page, a plain\nWebmention to it is refused outright (§15.3 step 1: the target must name a\npublished item) or marked <em>failed</em> (§15.4 step 4), so it could only ever cost\nthe receiver fetches. What remains is the open web: any client may send a W3C\nWebmention to a non-blyg page for a link it publishes, as IndieWeb sites do,\nand this RFC neither blesses nor forbids that. A client that does so should\nobserve three things: never to a target inside a blyg origin; never for an\nh-card inside a baked quote (§10.2 verbatim, the quoted author's speech);\nnever by default, only per mention at the author's choice. This differs from\nthe draft, which recommended a per-mention opt-in in the reference client.\nThe client stays boring (blygger-studio#35), and the one way to cite without\nnotifying stays wide.</p>\n<p><strong>3. Reciprocity on a shared origin.</strong> Not an acknowledgement class. The\nproof is #35's reciprocal <code>rel=&quot;me&quot;</code>, unchanged; what moves is its origin-side\nend, from the origin to the member's page under it (section 5.5). Both links\nthen say &quot;this is also me&quot; truthfully, because both pages are the member. The\nreader rule is one rule with two acceptable far ends: the identity origin\nitself, or a page that has it as a prefix and links back. Two fetches, two\ndisplay states, no third chrome. The draft's alternative, any link from\n<code>author.url</code> to the origin shown as &quot;linked from&quot;, was rejected because a link\nproves that the member linked to something at the house, not that they write\nthere, and because a third state is more display for less proof (section 9,\nitem 10). This is a ruling about identity semantics, so it is Fable's under\n#58, and <code>tn-2</code> carries it when written. <code>tn-3</code> section 5 already promised\nthat a verified byline survives a move from shape B to shape A; this is what\nmakes that true.</p>\n<p><strong>4. The spec says nothing.</strong> Confirmed. A sentence about preserving\nmicroformats in <code>content_html</code> would be the spec's first word, however\nindirect, about identity markup, and #11's silence on identity is a principle\nrather than an omission. Under #43 it would in any case be a revision that\nreaders already handle, and a convention one client emits is not yet a reader\nquestion. The fix lives in the reference client's sanitizer (section 8, item 5).\nRevisit when a second client emits the markup <em>and</em> a sanitizing reader's\nloss of it has caused a failure someone can name; the candidate home would be\n§13.1, not §5.2.</p>\n<p><strong>5. <code>ids</code> in <code>author</code>.</strong> Allowed as a conventional member, filtered as\nsection 5.3 filters mentions. #35 already places two conventional members in\n<code>author</code>, the signature and an agent's <code>operator</code>, so a third of the same\ncharacter adds no principle. The shape: an unordered array of absolute URIs\nin the three wire schemes, <code>https:</code>, <code>acct:</code> and <code>did:</code> (Ethereum as\n<code>did:pkh:</code>, section 7), each <code>self</code> or <code>bound</code> from the member's own\npublications. Because of that filter the house relays what the member\npublishes about themselves and asserts nothing new. §5.5's pass-through rule\nbinds <code>ids</code> as it binds every <code>author</code> member, and §13.1 rules 5 and 7 still\nhold: a reader matching <code>ids</code> against its book is making a display decision,\nnever a merge. The draft's reason stands as the practical one: a reader should\nnot need a fetch to match a byline against its address book.</p>\n<p><strong>What happens next.</strong> Published for comment under ruling 1 on 2026-10-07; the\nperiod closes 2026-11-04 (four weeks, as recommended). Revisions during the\nperiod are made in this file and republished as new versions of the same item. The decision list carries one entry for the five rulings (#67), with\nthis section as its reasoning.</p>\n</div>\n<p><span class=\"blyg-tk-gen\">\n<em>Source: <a href=\"https://github.com/blygger/blygger-spec/blob/main/docs/rfcs/rfc-1-mentions-and-identifier-schemes.md\"><code>docs/rfcs/rfc-1-mentions-and-identifier-schemes.md</code></a> in blygger-spec, which is where revisions are made; each one is published here as a new version. To comment, respond to this item from your own blyg: a stub is a comment, a partial quote names the passage, and a fork of the pinned version is a counter-proposal.</em>\n</span></p>\n","content_hash":"sha256:00da2dff2ff8ebfd770583b3b67958b670cbdefa9f6906e4699136070741e3f5","media":[],"transclusions":[],"generated":[{"sources":[],"model":"claude-opus-5-5+claude-fable-5-1"},{"sources":[],"model":"claude-opus-5-5"}],"changelog":[{"version":1,"at":"2026-10-07T20:11:31Z","note":"RFC-1 open for comment until 2026-11-04.","pinned":true}]}