Repository navigation
Show BRC-169 handles for commit authors - #1
Merged
Merged
Conversation
The handle is whatever sits in the git commit's author/committer email slot, as git shows it: `[email protected]` (paymail form) or `@[email protected]`, normalised to lowercase `@handle@domain`. Anything else stays plain text. Nothing is added to the head token and nothing is required of users; resolution is best effort and never breaks a page. Discovery follows BRC-169 sections 5.1-5.4: fetch the domain's manifest.json, require metanet.handles with major version 1, use its resolve URL (well-known default when absent), and treat a domain without metanet.handles as unresolvable without probing. GET resolve?handle= with the tag stripped; only a 200 with a well-formed identityKey and a certificate counts. Manifests and bindings are cached in memory server-side (ttl clamped to 60 s..24 h, failures 5 min, 3 s timeouts, in-flight lookups shared). A handle is verified for a head only when the resolved identityKey is the identity that signed that head. The same commit on another publisher's head shows the author as plain text there. No cross-head lookups, no overlay index. Verified handles render as `@[email protected]` with a verified mark, linking to the identity page, on head lists (explore, user, commits, commit DAG, my repos via /api/handles) and on the commit page's author and committer rows. The repo header labels the owner and duplicate branch entries with the handle from that identity's own verified head on the origin; the pubkey display stays. Also silences a pre-existing Biome control-character finding in branch-button.tsx so `bun run lint` passes. Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_01EM5trZ4BfZpW7pBjq2onqX
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
The workflow pinned bun 1.3.14 while bun.lock has been lockfileVersion 2 since the initial commit, so `bun install --frozen-lockfile` has never passed. Pin the version the project actually builds with. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_01EM5trZ4BfZpW7pBjq2onqX
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Shows commit authors as verified BRC-169 handles, modelled on git: the handle is whatever is in the commit's author/committer email slot. Nothing changes in the head token; nothing is required of users; resolution is best effort and never breaks a page.
Rules
lib/handles.tsparseHandle): acceptshandle@domain(paymail form, BRC-169 2.1.7) and@handle@domain, with an optional+tag, and normalises to lowercase@handle@domain. Plain names, dotless ecosystems (aliases), and grammar violations are left as plain text and never touch the network.https://<domain>/manifest.jsonmust carrymetanet.handleswith major version 1; itsresolveURL is used (default/.well-known/metanet-handles/resolvewhen absent). Nometanet.handlesmeans unresolvable, and the well-known path is not probed.GET <resolve>?handle=<handle>with the tag stripped. Only a 200 with a well-formedidentityKeyand acertificateobject counts (subject/handle/domain echoes are checked when present;revoked: truerejects). 404/410/other/timeouts are unresolved. Manifests and bindings are cached in memory server-side: ttl clamped to 60 s..24 h, failures 5 min, 3 s timeouts, in-flight lookups shared.identityKeyequals theidentitythat signed the head being viewed. The same commit on someone else's head shows the author as plain text there. No cross-head lookups, no overlay index.components/handle-link.tsx): verified handles render as@[email protected]with a verified mark, linking to the identity page. A host-supplieddisplayNameis only surfaced in the tooltip, labelled unattested (2.4.8). Unverified authors render exactly as before. The repo header labels the owner and duplicate branch-picker entries with the handle from that identity's own verified current head on the origin; the pubkey display stays.lib/handles-server.tsholds the shared resolver; server pages callauthorHandles/commitHandles. The client-only "My repos" page goes throughGET /api/handlesand applies the samematchAuthorHandlesrule locally.Not implemented on purpose: search, reverse, aliases, messaging, payments, delegation, certificate signature/revocation checks.
Verification
lib/handles.test.ts(23 tests, mocked fetch): grammar and normalisation (valid, paymail, tagged, invalid, alias), manifest handling (resolve URL, default path, missingmetanet.handles→ no probing, bad major/non-https), ttl clamping, resolve-response validation, the verification rule (matching vs non-matching signer), and the resolver's caching (ttl expiry, negative and positive manifest ttl, shared in-flight lookups, error statuses).bun run lint,bun run typecheck,bun test(37 pass), andbun run buildall pass. Lint needed a one-linebiome-ignorefor a pre-existing control-character regex finding inbranch-button.tsx.🤖 Generated with Claude Code
https://claude.ai/code/session_01EM5trZ4BfZpW7pBjq2onqX