diff --git a/skills/software-development/atproto-identity-deep/SKILL.md b/skills/software-development/atproto-identity-deep/SKILL.md new file mode 100644 index 0000000..d120774 --- /dev/null +++ b/skills/software-development/atproto-identity-deep/SKILL.md @@ -0,0 +1,128 @@ +--- +name: atproto-identity-deep +description: "Use for deep ATProto identity: did:web via goat, PLC ops." +version: 1.0.0 +author: Hermes Agent +license: MIT +platforms: [linux, macos, windows] +metadata: + hermes: + tags: [ATProto, Identity, DID, PLC, did:web, Goat, Passkeys] +--- + +# ATProto Identity — Deep Dive + +Advanced identity work on AT Protocol: creating did:web accounts with goat, +operating against PLC (directory, mirrors, ops, audit), and passkeys as PLC +rotation keys. Distilled from the AT://links and DEEP AT://magic Semble collections +(2026-08-17). For basic DID:WEB serving patterns see `atproto-development`. + +## When to Use + +- You are creating a did:web ATProto account (self-hosted, non-Bluesky path). +- You need to inspect, submit, or reason about PLC operations (rotation keys, + audit logs, mirrors). +- You want passkey-based PLC key custody instead of raw hex keys. + +## Core concepts + +- **did:plc** = Bluesky-default identity; keys and PDS endpoint live in the PLC + directory; user-friendly, hands-off. +- **did:web** = identity hosted at `https:///.well-known/did.json`; + you control resolution; no PLC involvement; **no recovery window** — lose the + key or the domain and the identity is unrecoverable. +- **PLC operation** = a signed mutation of the DID document (rotationKeys, + alsoKnownAs, verificationMethods, services). Rotation keys EARLIER in the list + can rewrite/nullify a pending op within 72 hours. +- **Passkeys (WebAuthn)** can serve as PLC rotation keys: the key material is + derived from the passkey and signs PLC ops directly, keeping secrets local. + +## Creating a did:web account (goat — bnewbold's guide, whtwnd.com) + +Requirements: a domain + web server you control (for did.json), a handle domain +you control, an invite code to an atproto PDS, and `goat` (v0.2.2+ — earlier +versions had a deactivated-accounts bug). + +1. Prepare identity: decide did:web domain and handle; you'll update the DID + document several times, so keep a terminal open. +2. Host `did.json` at `https:///.well-known/did.json` with your + signing key's `publicKeyMultibase` (Multikey) and the `#atproto_pds` service + pointing at your target PDS. +3. Use goat to walk the account creation flow against the PDS (service-auth JWT + signed by your key). +4. Verify: `goat` resolves your handle/DID; `curl https:///.well-known/ + did.json` returns the doc; handle DNS/well-known points to the DID. + +Alternative client-side tooling: **atproto-did-web.lukeacl.com** — a wizard that +generates keys + did.json, validates hosting, and creates/activates the account on +a self-hosted PDS (all client-side; useful for manual setups). See also +`atproto-development` for key generation (secp256k1/p256) and custody rules. + +## PLC directory: canonical + mirrors + +| Service | Purpose | +|---|---| +| plc.directory | Canonical DID:PLC registry (DID -> document; ops; audit log) | +| didplc.directory | Community read replica (fast lookups, last-op, audit) | +| web.plc.directory | API docs (redoc) | +| eu.plc.wtf / experimental.us-west.plc.wtf | PLC mirrors running **Allegedly** (open-source PLC-log CLI suite, microcosm.blue) in wrap mode: `GET /{did}` resolves; `POST /:did` forwards ops upstream (experimental op forwarding at experimental.plc.wtf) | + +- `GET https://plc.directory/{did}` resolves a DID document. +- `GET https://plc.directory/{did}/log/audit` returns the full operation log. +- Mirrors exist for redundancy/speed; treat plc.directory as the source of truth + and mirrors as read caches (they can lag). + +## Passkeys as PLC rotation keys (plc-passkey.wisp.place) + +- Add a passkey as a rotation key: resolve handle, authenticate with an existing + passkey rotation key, sign and submit the PLC update directly to plc.directory. +- Retrieve/derive rotation key material from an existing passkey (recovery path). +- Properties: WebAuthn-based, keys stay local, direct PLC signing — no raw key + handling in most flows. Good custody story vs. hex keys (which must be backed up + in a password manager + sealed copy). + +## Related identity tooling (from the digest) + +- **keytrace.dev** — signed cross-account proofs: link your handle to GitHub/DNS/ + npm/Mastodon/PGP via tokens; writes `dev.keytrace.claim` to your PDS. +- **internethandle.org** — the "domains as handles" pitch (context for did:web + handles). +- **atp.pics** — avatar fetch/transform/cache by handle or DID (`GET /{handle}` + -> 302 to cached image; params w/h/q/f). +- **atpassport.net** — handle registry for a community (context: handle + squatting/redistribution on non-bsky services). +- **at-me.zzstoatzz.io** — NSID adoption stats (which identities/lexicons have + traction). + +## Pitfalls + +- **did:web has no recovery.** No PLC to rewrite you out of a bad op; custody = + key + domain, both must survive. +- **goat versions matter** — use current main / v0.2.2+ for deactivated-account + fixes. +- **PLC mirrors can lag or reject POSTs** — experimental op forwarding is + explicitly experimental; submit ops to the canonical directory. +- **Rotation-key ordering** — inserting a key at index 0 makes it able to override + pending ops for 72h; removing all original keys can orphan the identity. + Passkey rotation adds a recovery path but only if the passkey survives (sync it + properly). +- Did:web account creation on a PDS requires an **invite code** on most managed + PDSes — have one ready. +- Never store raw rotation keys in repos or logs (standing security rule; see + `atproto-development` key custody). + +## Verify + +- `curl -s https://plc.directory/did:plc:...` returns a valid DID document. +- `curl -s https://plc.directory//log/audit` returns the op history. +- `curl -s https://didplc.directory` — read replica up; resolves the same DID. +- After did:web setup: `curl -s https:///.well-known/did.json` matches + the expected doc, and `goat` resolves the handle. + +## Related skills + +- `atproto-ecosystem-map` — identity services in the provider registry. +- `atproto-development` — DID:WEB serving, key generation (secp256k1/p256), + custody rules, resolution chain. +- `atproto-pds-ops` — migration interplay (PLC keys + adversarial moves). +- `atproto-lexicon-registry` — dev.keytrace.claim / claim lexicons. diff --git a/skills/software-development/atproto-lexicon-registry/SKILL.md b/skills/software-development/atproto-lexicon-registry/SKILL.md new file mode 100644 index 0000000..2812957 --- /dev/null +++ b/skills/software-development/atproto-lexicon-registry/SKILL.md @@ -0,0 +1,106 @@ +--- +name: atproto-lexicon-registry +description: "Use for ATProto lexicon schemas: browse, author, publish." +version: 1.0.0 +author: Hermes Agent +license: MIT +platforms: [linux, macos, windows] +metadata: + hermes: + tags: [ATProto, Lexicon, Schemas, NSID, Registries] +--- + +# ATProto Lexicon Registry + +How to discover, understand, author, and publish ATProto lexicon schemas, and where +the ecosystem's registries live. Distilled from the AT://links and DEEP AT://magic +Semble collections (2026-08-17). + +## When to Use + +- You need to find an existing lexicon before inventing a record type. +- You are authoring/publishing a new schema (NSID, fields, validation) and want to + know the conventions and where it will be visible. +- You want to know which apps interoperate on shared data types. + +## Core concepts + +- **Lexicon** = JSON schema for records + XRPC endpoints. Records live in + collections identified by NSID (e.g. `app.bsky.feed.post`, + `network.cosmik.collection`). Core atproto.com + bsky.app lexicons are the + baseline; anything else is a community lexicon. +- **NSID = authority you control** (reverse domain). `app.bsky.*` belongs to + Bluesky; `org.atgeo.*`, `in.atmob.paste.*`, `community.lexicon.*`, `dev.keytrace.*` + belong to their authors. Your domain, your namespace. +- **Interop comes from shared lexicons.** at-store groups apps by the data types + they share (e.g. 47 apps on `app.bsky.feed.post`); community lexicons like + `community.lexicon.location.geo` are reused across projects (ATGeo embeds them). +- Publishing a schema = hosting the lexicon JSON (and often registering it in the + registries below), then writing records against it. + +## Registries & tools (status as of 2026-08) + +### Discovery / browsing +- **lexicon.garden** — the main discovery platform: browse, search, validate + schemas, API access, MCP integration for agents, "adding lexicons" + "documenting + lexicons" guides, trending lists (e.g. app.bsky.feed.like, app.bsky.feed.post, + app.bsky.feed.repost). +- **lexicon.store** — schema registry (browse NSIDs). +- **lexicons.bio** — biodiversity schemas aligned with DwC-DP: occurrence / + identification / media records, cross-record links via `com.atproto.repo.strongRef` + (a clean example of a small well-documented lexicon family). +- **rite.mino.mobi/lexicon** — word-level analysis of a Bluesky archive (CAR fetch + from the user's PDS or uploaded text): NRC emotion, Brysbaert concreteness, + AFINN sentiment, SUBTLEX frequency. Deterministic, client-side. +- **at-me.zzstoatzz.io** (@me) — NSID adoption stats across the network + (app.bsky ~66.4M users, chat.bsky ~1.7M, net.anisota, blue.flashes, sh.tangled, + site.standard, place.stream, community.lexicon ...) — useful to gauge whether a + lexicon has traction before adopting it. + +### Authoring examples worth copying +- **atgeo.org/place** — `org.atgeo.place` record with reusable + `community.lexicon.location.geo` / `community.lexicon.location.address` subtypes; + per-source collections (`org.atgeo.places.foursquare`). +- **atmobin.lol / atmob.in** — paste as a record in YOUR repo + (`in.atmob.paste.document`); the app writes the record and proxies it back at + `atmobin.lol/@you/in.atmob.paste.document/...` — no server-side copies. +- **keytrace.dev** — `dev.keytrace.claim` records on the user's PDS for signed + cross-account proofs (GitHub/DNS/npm/Mastodon/PGP). +- **atstore.fyi/apps/lexicons** — lexicon-set groups showing interop clusters; + also documents postgate/threadgate rkey-matching rules (rkey must equal the + post's rkey). + +### Interop context +- **Bridgy Fed** (bridgy-fed.readthedocs.io) — the reference for translating + between IndieWeb / ActivityPub / AT Protocol; its design doc explains how to + abstract across protocols when your lexicon feeds a federation bridge. + +## Pitfalls + +- **Namespace squatting**: pick an NSID under a domain you control; don't mint + records under others' authorities. +- **Validation matters**: lexicon.garden validates schemas — a malformed lexicon + breaks every consumer; test with the SDK's model generation before publishing + (see atproto-python / atproto-development). +- **Shared-data etiquette**: if a community lexicon already covers your need + (locations, pastes, bookmarks, verification), reuse it instead of forking — + interop is the point (see at-store clusters). +- **Rkey coupling rules** (postgate/threadgate) — some records require the rkey to + match another record's rkey; check the lexicon's docs. +- Registries are community-run and lag: a lexicon may be live on the network before + it appears in lexicon.garden. + +## Verify + +- `curl -s https://lexicon.garden` — registry loads; search a known NSID. +- Browse `https://atstore.fyi/apps/lexicons` — see interop clusters for a record + type you care about. +- Fetch a record via atpi (prefix `atpi.` to an at:// URL) to confirm a schema is + actually in use: `curl https://atpi.at:///`. + +## Related skills + +- `atproto-ecosystem-map` — network roles; lexicon registries in the registry table. +- `atproto-python` / `atproto-development` — SDK model generation from lexicons, + creating records. +- `atproto-tools-catalog` (planned) — clients/viewers grouped by shared lexicons.