Beersy
BRC-165

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 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.

David Case, Brandon Cryderman / HandCashchanged 28 Aug 202611 min read

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 `` 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.

list requestscope + tag grfiltered items

The specification

Abstract

This BRC defines the P1Sat 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 . This BRC defines scheme id 1sat and separates storage from permission routing:

LayerLaw
Storage basket1sat (BRC-147)
View (list)basket p 1sat <scope> (Scopes); axis values in tags; other tags only narrow further
SpendcreateAction p 1sat input id <key> (BRC-164)
ProvenanceBRC-150 on storage 1sat

Basket Namespace

  1. Scheme ID: 1sat (no spaces; BRC-99)
  2. 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.
  3. Wallet capability: Must implement storage basket 1sat per BRC-147; must route p 1sat … basket operations and p 1sat input id … labels to this scheme’s module; must enforce view grants on list and per-action spend approval on labeled spends
  4. Permission semantics: See View and Spend

Module presence detection uses the BRC-98 protocol p 1sat probe ( 0); see Module detection. Wallets route by scheme id 1sat (BRC-116). That probe is not the default key-derivation protocol for new inventory . 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
}

:

  • 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 id 1sat, or reject if the scheme is not supported). This BRC does not alter those rules.
  • Conforming module: when the wallet routes this getPublicKey to the 1sat module, the module SHOULD pass the request through (return a public key) so the probe succeeds without a user prompt.
  • keyID: 1sat-module-probe is 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 1sat is 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

  1. Conforming wallets MUST file collectables in storage basket 1sat (BRC-147).
  2. Permission basket ids are p 1sat <scope> only (scope required). They are routing names only; held tips remain in 1sat.
  3. 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.

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 formScopeMeaning
p 1sat allallEntire storage 1sat
p 1sat collectioncollectionCollection-scoped view; values from collection:… tags
p 1sat appappApp-scoped view; values from app:… tags
p 1sat creatorcreatorCreator-scoped view; values from creator:… tags
p 1sat ididSingle-row lookup; values from id:… tags (BRC-164)

Rules:

  1. Bare p 1sat (no scope token) MUST be rejected. Full inventory uses p 1sat all only.
  2. Scope is exactly one token after p 1sat (all, collection, app, creator, or id). Extra tokens in the basket name MUST be rejected.
  3. Unknown scope tokens MUST be rejected with a clear error (fail closed). Future axes are added by revising this table.
  4. 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.
  5. For scope all, no axis tag is required. Caller tags are optional further filters only.
  6. Matching tags follow BRC-147 / BRC-164. Exact tag equality after normal wallet tag normalization.
  7. 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 requested id:… 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-all scopes, 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 listOutputs with plain basket 1sat. That path is ordinary basket access (BRC-46 / BRC-116), not this scheme, unless the wallet elects to route plain 1sat through the same module as local policy.

Normalization

On listOutputs with basket p 1sat <scope>, conforming wallets MUST:

  1. Parse the scope (Scopes); reject bare p 1sat, unknown scopes, and basket names that embed values after the scope token.
  2. For non-all scopes, require at least one matching axis tag on the request; reject if missing.
  3. Require a view grant covering that scope and the requested axis value(s) (or prompt to create one) — see View grants.
  4. Rewrite the storage query basket to 1sat.
  5. Enforce the granted axis tag value(s) as a mandatory filter on results (tagQueryMode: "any" MUST NOT drop them).
  6. Apply any additional non-axis caller tags only inside that ceiling.
  7. 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):

ScopeRequired tag(s) on the request
allnone
collectionone or more collection:…
appone or more app:…
creatorone or more creator:…
idone 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; knowing id:<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:

  1. BRC-111-style P-label: scheme id 1sat, payload input id <key>.
  2. <key> is the BRC-164 list key — the substring after id: on the held output’s tags. Non-empty, no spaces, no id: prefix in the label.
  3. 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 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:

  1. Route the call to the 1sat permission module (BRC-116).
  2. Resolve each <key> to a held output in storage basket 1sat via BRC-164 (id:<key>).
  3. 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.
  4. 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)

CapabilityWireCovers
ViewlistOutputs basket p 1sat <scope>Listing storage 1sat under the module
SendcreateAction 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

OperationPlain 1satp 1sat … / input labels
Storage of tipsYes (normative)Never
listOutputsOrdinary basket accessModule view + scope grants
Spend targetingOutpoint / local policyp 1sat input id <key> (BRC-164)

Out of scope

  • / 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 scheme 1sat
  • Fine-grained receive / internalizeAction grants

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-1sat basket loses this profile’s storage contract.
  • Payment separation — Pay / auto-pay MUST NOT cover view under p 1sat … or spends authorized via p 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

  1. BRC-99: P Baskets
  2. BRC-98: P Protocols
  3. BRC-100: Wallet Interface
  4. BRC-111: Transaction Labels
  5. BRC-116: Wallet Permissions and Counterparty Trust
  6. BRC-147: 1Sat Ordinals Basket Profile
  7. BRC-150: 1Sat Provenance Remittance
  8. BRC-164: Output Identity Tags
  9. BRC-123: Basket Permission Scheme Registry (registry listing deferred; see Basket Namespace)
Was this helpful?

Search Beersy

Search standards by number, title, author or topic