P1Sat Permission Scheme for Basket `1sat`
Apps that manage digital collectables inside a wallet need to show a user's items and occasionally spend one of them, but a wallet basket only offers all-or-nothing access: either an app sees everything in a person's collection or nothing at all. That is either too invasive for an app that only cares about one collection, or too weak to let an app safely ask to move a single specific item without also getting blanket spending rights over the whole stash.
Reference for an AI
Everything an assistant needs to answer questions about BRC-165 accurately, including what it depends on.
Summary
- Why
- Wallet apps need a way to see and spend only specific collectable items without either exposing a user's whole inventory or granting blanket spending rights over items they should not touch.
- What
- BRC-165 is a wallet permission scheme, identified as `1sat`, that lets apps request scoped viewing of collectable items and per-action approval to spend a specific held item, while storage stays in the plain `1sat` basket.
- How
- An app requests view access with a basket named `p 1sat <scope>` (all, collection, app, creator, or id) plus a matching tag, and requests spend approval by labeling `createAction` with `p 1sat input id <key>`, letting a wallet's scheme module apply grants and prompts before touching the underlying `1sat` storage…
What this lets you do
- Probe wallet support for the 1sat scheme before showing item-related UI
- Request scoped item view by collection, app, creator, or single id
- Ask users to approve spending a specific held item per action
- Filter listed items with tags without leaking outside the granted scope
- Keep collectable storage in the plain 1sat basket while permissions stay separate
Written by claude-sonnet-5 from the specification text. Where the two differ, the original is correct.
The specification
Abstract
This BRC defines the P1Sat basket permission scheme for BRC-100 wallets: scheme id 1sat under BRC-99 / BRC-116.
Storage of collectables remains the plain basket 1sat (BRC-147). Applications request view access with a BRC-99 basket p 1sat <scope> (scope names the permission axis; filter values ride ordinary tags). Applications request spend authorization by labeling createAction with p 1sat input id <key>, where <key> is the bare BRC-164 list key for the held row. Conforming wallets route those requests to a scheme module, normalize storage to 1sat where needed, apply view grants and per-action spend approval as specified below, and MUST NOT treat payment / auto-pay grants as item access.
This document does not redefine 1Sat chain theory, inscriptions, collections, or provenance proofs. It does not replace BRC-147 or retarget BRC-150.
Motivation
Plain BRC-46 baskets only support coarse grant/deny. Collectables need finer app access — one collection, one app, one creator, or the full inventory — without inventing a storage basket per filter and without forcing inventory to live under a p … name.
BRC-99 reserves p <scheme> … for richer permission modules. This BRC defines scheme id 1sat and separates storage from permission routing:
| Layer | Law |
|---|---|
| Storage basket | 1sat (BRC-147) |
| View (list) | basket p 1sat <scope> (Scopes); axis values in tags; other tags only narrow further |
| Spend | createAction labels p 1sat input id <key> (BRC-164) |
| Provenance | BRC-150 on storage 1sat |
Basket Namespace
- Scheme ID:
1sat(no spaces; BRC-99) - Basket name format:
p 1sat <scope>where<scope>is a fixed axis token from Scopes (required). Basket names use only[a-z0-9 ]per BRC-100. Filter values are not part of the basket name. - Wallet capability: Must implement storage basket
1satper BRC-147; must routep 1sat …basket operations andp 1sat input id …labels to this scheme’s module; must enforce view grants on list and per-action spend approval on labeled spends - Permission semantics: See View and Spend
Module presence detection uses the BRC-98 protocol p 1sat probe (security level 0); see Module detection. Wallets route by scheme id 1sat (BRC-116). That probe is not the default key-derivation protocol for new inventory tips. New tip key derivation SHOULD follow BRC-147 / wallet policy (e.g. plain protocol names such as onesat).
BRC-123 registry listing for this scheme is deferred (current §3.1 letter-first scheme ids do not admit 1sat).
Specification
Scheme identifier
- Scheme id:
1sat(no spaces; BRC-99) - BRC-98 probe protocol:
[0, "p 1sat probe"](level 0; see Module detection) - BRC-99 basket form (view):
p 1sat <scope>(scope required; see Scopes) - BRC-111 label form (spend):
p 1sat input id <key>(<key>= bare BRC-164 list key)
Wallets that do not implement this scheme MUST reject operations under these identifiers per BRC-99 / BRC-98.
Module detection
Applications MAY detect whether scheme 1sat is available by probing a BRC-98 protocol under this scheme. Per BRC-98, protocol names are p <scheme-id> <rest>; the rest token for this probe is probe.
Probe (application behavior): call BRC-100 getPublicKey with:
{
"protocolID": [0, "p 1sat probe"],
"keyID": "1sat-module-probe",
"counterparty": "self",
"seekPermission": false
}
Notes:
- Protocol claim: security level 0, protocol name
p 1sat probe. Level 0 keeps the probe outside ordinary Level 1/2 protocol-permission UX when the wallet routes it to this scheme’s module (BRC-43, BRC-116). - Wallet behavior for supported vs unsupported
p …protocols and baskets is already defined by BRC-98, BRC-99, and BRC-116 (route to a registered module by scheme id1sat, or reject if the scheme is not supported). This BRC does not alter those rules. - Conforming module: when the wallet routes this
getPublicKeyto the1satmodule, the module SHOULD pass the request through (return a public key) so the probe succeeds without a user prompt. keyID:1sat-module-probeis RECOMMENDED for interoperability among probers; it is not a special wallet-reserved id beyond ordinary BRC-43 key-id rules.seekPermission: false: RECOMMENDED so capability detection does not open a permission UI.- Interpretation: applications treat probe success (on a wallet that uses P-module routing) as evidence that scheme
1satis registered, and a BRC-98/99 unsupported-scheme rejection as evidence it is not. Bare wallets without a permissions manager may not give a reliable signal; applications SHOULD only enable module-mediated labels/baskets when they expect P-module routing.
This probe does not grant view or spend rights. It does not change BRC-111 label rules; spend labels under this scheme still follow BRC-111’s p <scheme> <payload> form as specified in Spend.
Storage vs permissions
- Conforming wallets MUST file collectables in storage basket
1sat(BRC-147). - Permission basket ids are
p 1sat <scope>only (scope required). They are routing names only; held tips remain in1sat. - When a request uses a basket beginning with
p 1sat(after BRC-46 trim/lowercase), the wallet MUST:- treat the request as scheme
1sat; - parse scope from the basket name (reject if missing or unknown; values are not in the basket name);
- require axis tag value(s) on the request when the scope is not
all; - normalize the storage target to basket
1sat; - apply view permission for that scope and value(s) (prompt or prior grant) before returning outputs;
- enforce axis tags as a mandatory filter; other caller tags only narrow further.
- treat the request as scheme
View (listOutputs)
Scopes
After the scheme prefix p 1sat, a scope is required. The scope names a permission axis only. Filter values are not part of the basket name; they use ordinary output tags. The full basket name MUST stay within BRC-100 [a-z0-9 ].
| Basket form | Scope | Meaning |
|---|---|---|
p 1sat all | all | Entire storage 1sat |
p 1sat collection | collection | Collection-scoped view; values from collection:… tags |
p 1sat app | app | App-scoped view; values from app:… tags |
p 1sat creator | creator | Creator-scoped view; values from creator:… tags |
p 1sat id | id | Single-row lookup; values from id:… tags (BRC-164) |
Rules:
- Bare
p 1sat(no scope token) MUST be rejected. Full inventory usesp 1sat allonly. - Scope is exactly one token after
p 1sat(all,collection,app,creator, orid). Extra tokens in the basket name MUST be rejected. - Unknown scope tokens MUST be rejected with a clear error (fail closed). Future axes are added by revising this table.
- For scopes collection, app, creator, and id, the request MUST include at least one tag with the matching prefix (
collection:,app:,creator:,id:). The tag value (after the prefix) is the filter id. For collection, the value is a collection id per BRC-147. - For scope all, no axis tag is required. Caller tags are optional further filters only.
- Matching tags follow BRC-147 / BRC-164. Exact tag equality after normal wallet tag normalization.
- Scope id is a targeted lookup, not full-inventory access. It MUST NOT require grant all. Conforming wallets MUST allow
p 1sat id+id:<key>through the module without a prior collection/app/creator/all grant (auto-allow this narrow query, or an equivalent one-shot / id-scoped grant). Results MUST still be limited to the requestedid:…value(s). Spend targeting remains Spend (p 1sat input id <key>), not this scope alone.
Request shape
{
"basket": "p 1sat collection",
"tags": [
"collection:a1b2c3d4e5f6070890abcdef1234567890abcdef1234567890abcdef12345678_0",
"type:image/png"
],
"tagQueryMode": "all",
"includeTags": true,
"includeCustomInstructions": true
}
basket:p 1sat <scope>as in Scopes (axis only; scope required).tags: for non-allscopes, MUST include the axis tag(s) carrying the filter value(s). Additional tags (e.g.type:) only narrow further.tagQueryMode: applies to the caller’s tag set as constrained by Scope ceiling.- Apps MAY still call
listOutputswith plain basket1sat. That path is ordinary basket access (BRC-46 / BRC-116), not this scheme, unless the wallet elects to route plain1satthrough the same module as local policy.
Normalization
On listOutputs with basket p 1sat <scope>, conforming wallets MUST:
- Parse the scope (Scopes); reject bare
p 1sat, unknown scopes, and basket names that embed values after the scope token. - For non-
allscopes, require at least one matching axis tag on the request; reject if missing. - Require a view grant covering that scope and the requested axis value(s) (or prompt to create one) — see View grants.
- Rewrite the storage query basket to
1sat. - Enforce the granted axis tag value(s) as a mandatory filter on results (
tagQueryMode: "any"MUST NOT drop them). - Apply any additional non-axis caller tags only inside that ceiling.
- Return only outputs that satisfy the grant and the effective tag query.
How the wallet enforces (4)–(6) (query rewrite, post-filter, or equivalent) is an implementation choice.
Denial SHOULD use a distinct error so apps can distinguish “user denied item view” from generic basket denial.
View grants
Item view is not covered by ordinary payment / auto-pay grants.
Each list request has one scope. The scope maps to a tag prefix (or to no prefix for all):
| Scope | Required tag(s) on the request |
|---|---|
all | none |
collection | one or more collection:… |
app | one or more app:… |
creator | one or more creator:… |
id | one or more id:… |
The wallet queries storage basket 1sat with those tags (plus any optional extra tags the caller adds). Grant check is on this request’s scope and tag values, not a multi-axis matrix.
p 1sat all— requires a standing grant for full inventory (or a prompt that creates one).p 1sat collection/app/creator— requires a standing grant that covers the requested tag value(s) for that scope (or a prompt). Grant all also covers these.p 1sat id— no standing inventory grant; knowingid:<key>is enough to look up that row (see Scopes).
When the user approves a collection/app/creator/all request, the wallet SHOULD persist a grant for that scope and those tag values (or upgrade to all). Storage layout is local.
A later request MAY skip a new prompt when its scope and tag values are already covered by a stored grant (including grant all covering narrower scopes). Otherwise prompt or deny.
Scope ceiling and tag query
The scope’s required tags are mandatory on the result set. Optional extra tags (e.g. type:image/png) only narrow further. tagQueryMode: "any" MUST NOT drop the scope’s required tags.
Spend (createAction)
Spend targeting under this scheme is built on BRC-164 output identity tags. The held row MUST carry an id:<key> tag stamped by the holding wallet. The spend label names that key explicitly; the module resolves it back to the row with tag id:<key> under storage basket 1sat.
Label form
Held row (normative):
p 1sat input id <key>
Rules:
- BRC-111-style P-label: scheme id
1sat, payloadinput id <key>. <key>is the BRC-164 list key — the substring afterid:on the held output’s tags. Non-empty, no spaces, noid:prefix in the label.- Storage basket is implied by the scheme:
1sat.
Example (row tagged id:a1b2c3d4e5f60708):
p 1sat input id a1b2c3d4e5f60708
Multiple such labels MAY appear when the action spends multiple tracked rows. Rows without a BRC-164 id: tag cannot use this form.
Other input payloads. A label p 1sat input <outpoint> whose single payload outpoint is not the keyword id is outside this scheme’s permission model (e.g. naming a beefed external input). It is not a BRC-164 list key and is not further specified here. The normative spend path for wallet-held tips remains p 1sat input id <key>.
Module behavior
When createAction carries one or more p 1sat input id <key> labels, conforming wallets MUST:
- Route the call to the
1satpermission module (BRC-116). - Resolve each
<key>to a held output in storage basket1satvia BRC-164 (id:<key>). - Obtain user approval for this action’s spend before spending those outputs. Payment / auto-pay MUST NOT satisfy this. Send approval is per action (inline prompt); this BRC does not define a standing/persisted “can send items” grant.
- On approval, authorize only the spend set the user approved. A later
createSignature(or equivalent) MUST NOT expand that set without a new approval.
Once an action is classified as a held-tip spend under this scheme (via input id <key> and successful resolution), payment auto-approve MUST NOT apply.
Outpoint spend without labels
Apps MAY still spend by outpoint without a p 1sat input label. That path does not enter this scheme via labels. Wallets SHOULD still refuse to spend storage 1sat outputs under ordinary payment grants (BRC-147 payment separation). Interoperable module-mediated spend targeting uses the input label form above.
Capabilities (summary)
| Capability | Wire | Covers |
|---|---|---|
| View | listOutputs basket p 1sat <scope> | Listing storage 1sat under the module |
| Send | createAction labels p 1sat input id … | Per-action approval to spend labeled held rows (not a standing grant) |
Receive / internalizeAction insertion into 1sat remains ordinary basket insertion under BRC-147 and wallet basket-access policy. Fine-grained receive grants are out of scope for this BRC.
Relationship to plain basket 1sat
| Operation | Plain 1sat | p 1sat … / input labels |
|---|---|---|
| Storage of tips | Yes (normative) | Never |
listOutputs | Ordinary basket access | Module view + scope grants |
| Spend targeting | Outpoint / local policy | p 1sat input id <key> (BRC-164) |
Out of scope
- Origin / sat-ordering / transfer consensus rules
- Inscription envelope bytes
- Collection membership proofs
- BSV-21 fungible storage and permissions
- Marketplace lock templates
- Labels other than
p 1sat input …under scheme1sat - Fine-grained receive /
internalizeActiongrants
Security considerations
- Tag / grant spoofing — View matching on tags is only as trustworthy as the holding wallet’s own stamps. Tags are claims; tip→origin proof is BRC-150.
- Scheme bypass — Filing collectables only in a non-
1satbasket loses this profile’s storage contract. - Payment separation — Pay / auto-pay MUST NOT cover view under
p 1sat …or spends authorized viap 1sat input id …. - Scope ceiling — Extra caller tags MUST NOT widen past the granted axis values.
- Approval binding — After a spend is approved, signatures MUST NOT authorize a different spend set without a new approval.
Implementations
- 1sat-sdk — scheme module, input labels, scoped view
- HandCash Desktop / Mobile — prior art for item view/send separation (storage
1sat)
References
- BRC-99: P Baskets
- BRC-98: P Protocols
- BRC-100: Wallet Interface
- BRC-111: Transaction Labels
- BRC-116: Wallet Permissions and Counterparty Trust
- BRC-147: 1Sat Ordinals Basket Profile
- BRC-150: 1Sat Provenance Remittance
- BRC-164: Output Identity Tags
- BRC-123: Basket Permission Scheme Registry (registry listing deferred; see Basket Namespace)