Agent guide, a gibhub skill, and a BRC-73 permission manifest - #2
Merged
Merged
Conversation
CLAUDE.md was 46 lines and out of date. Replace it with AGENTS.md, the arrangement the gib CLI uses, and make CLAUDE.md a symlink to it. Covers what the code actually does: every route and what it renders, the lib modules that matter, the head token's exact fields and vocabulary, the overlay and ORDFS routes the site calls and what each returns, and the conventions already in the code (server components by default, server-side handle resolution behind one shared cache, react-query keys, and the standing rule not to reimplement anything the @1sat SDK ships). Adds skills/gibhub/SKILL.md for agents working in this codebase, listed in a catalog table in AGENTS.md. This is not a monorepo, so skills/ at the root is the only copy; there is nothing to mirror it to. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_01EM5trZ4BfZpW7pBjq2onqX
The site made a wallet prompt for each permission as the user reached it: identity key on connect, then the protocol, then the label, then the basket, then spending. A manifest lets the wallet ask once. /manifest.json already existed for PWA metadata and the babbage.trust block, so the permissions go into that same route rather than a new public/manifest.json: the trust block is conditional on an environment variable, so the document has to be built per request. Shape and placement follow WalletPermissionsManager in @bsv/wallet-toolbox, which is what @1sat/connect bundles. It reads `manifest.metanet || manifest.babbage` then `.groupPermissions`, and validates nothing, so three things had to be got exactly right: - Action labels are not a category. GroupedPermissions has only description, spendingAuthorization, protocolPermissions, basketAccess and certificateAccess. A label is gated as the level-1 protocol `action label <name>`, so that is how `gib push` and `gib delete` are declared. - Level-1 entries carry no counterparty. The manager forces it to "" at level 1, and a literal "" is a reserved slot that drops the entry. - No extra keys: the grant path deep-equals granted entries against the requested ones, which are these literal objects. Declared: the identity key protocol, `gib branch`, the two action labels, basket `gib`, and a 10,000 sat monthly spending allowance. Spending is needed and not assumed: createAction computes a net spend for the 1-satoshi head plus fees and calls ensureSpendingAuthorization. Nothing else is declared; every one of those six is reached by code in lib/gib-wallet.ts or the @1sat/connect handshake. Also sets access-control-allow-origin on the response. A wallet running in a page fetches this cross-origin, and a failed fetch is cached as "no manifest" for five minutes. BSV Desktop's own manifest route does the same. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_01EM5trZ4BfZpW7pBjq2onqX
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
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.
Three things, each verified against the code rather than against memory.
1.
AGENTS.md, withCLAUDE.mdas a symlink to itCLAUDE.mdwas 46 lines and had drifted. It is replaced byAGENTS.md(git mode 120000 symlink at
CLAUDE.md), the arrangement the gib CLIuses.
It covers every route and what it renders, the lib modules that matter,
the head token's exact fields and vocabulary, the overlay and ORDFS
routes the site calls and what each returns, the fact that
lib/gib-head.tsdecodes heads locally so/meworks with no overlay,and the conventions already present in the code — server components by
default, server-side handle resolution behind one shared cache, the
react-query keys in use, and the standing rule not to reimplement
anything the
@1satSDK ships.The "things that will bite you" section is drawn from real facts: the
repository origin resolving to the genesis tree forever, handle
verification being per head rather than per commit, the hard-coded
gibbasket, and CI's bun pin.
2.
skills/gibhub/SKILL.mdA short skill for agents working in this codebase, listed in a catalog
table in
AGENTS.md. This is not a monorepo, soskills/at the rootis the only copy; there is nothing to mirror it to.
3. A BRC-73 grouped permission manifest
The site made the wallet prompt separately for each permission as the
user reached it.
/manifest.jsonnow carries ametanet.groupPermissionsblock so a BRC-100 wallet asks once.The permissions block went into the existing
app/manifest.json/route.tsrather than a new
public/manifest.json, because thebabbage.trustblock there is conditional on an environment variable and so the
document has to be built per request. Nothing was clobbered.
Declared, and nothing more:
[1, "identity key retrieval"]getPublicKey({ identityKey: true })on connect[1, "gib branch"]pushDropLock/unlockByScript[1, "action label gib push"]mintHead[1, "action label gib delete"]burnHeadgiblistOutputs({ basket: "gib" }), and where minted heads are filedspendingAuthorization, 10 000 sat/monthcreateAction's net spend for the 1-satoshi head plus feesSpending authorization is declared because the code needs one, not on
assumption:
createActioncomputesnetSpent > 0for the 1-satoshihead and calls
ensureSpendingAuthorization.Three details are not guessable from the spec name and are recorded in
AGENTS.md:GroupedPermissionshas onlydescription,spendingAuthorization,protocolPermissions,basketAccess,certificateAccess. A label is gated as the level-1protocol
action label <name>.""at level 1, and a literal""is a reserved slot that drops theentry — so no entry here declares one, even though
gib-wallet.tssigns with counterparty
anyone.the requested ones, which are these literal objects.
The response also sets
access-control-allow-origin: *, matching BSVDesktop's own manifest route: a wallet running in a page fetches this
cross-origin, and a failed fetch is cached as "no manifest" for five
minutes.
Verification
bun run lint,bun run typecheck,bun testandbun run buildallpass. The manifest was fetched from a running dev server and checked two
ways: that it parses and matches the
GroupedPermissionsshape with nodead (
level 0), dropped (counterparty: "", level 2 without acounterparty) or non-spec entries; and that the manager's
isRequestIncludedInGroupPermissionsmatcher, transcribed from source,covers all six requests this app actually makes and nothing else.
🤖 Generated with Claude Code
https://claude.ai/code/session_01EM5trZ4BfZpW7pBjq2onqX