{"_id":"@bsv/color-permission-module","_rev":"7-10725e22bb421fe55a45027ebf38ee68","name":"@bsv/color-permission-module","dist-tags":{"latest":"0.2.0"},"versions":{"0.0.0-stage":{"name":"@bsv/color-permission-module","version":"0.0.0-stage","_id":"@bsv/color-permission-module@0.0.0-stage","stub":true,"maintainers":[{"name":"tyeverett","email":"p2ppsr@tyweb.us"}],"dist":{"shasum":"50eb9bca566bdbdd155bf1ab66dc0e9153c8e7d9","tarball":"https://registry.npmjs.org/@bsv/color-permission-module/-/color-permission-module-0.0.0-stage.tgz","fileCount":2,"integrity":"sha512-25o3oTWhPHopp6azLdcPQalmqjOvMEuYoI5lmtANPHx97EXp2H5odB/hBKVPapVT/YMlIWmnPY8pzxV11NQLEg==","signatures":[{"sig":"MEQCIDMfiJtorYCTnPQ6OHwCiDdah29IVhTbnNlCdDT1Y0K6AiAjv2IT4CXvCbHtkjr9mPEwkzFal/p8ibvB4c6cwDoKkA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":350},"_npmUser":{"name":"tyeverett","email":"p2ppsr@tyweb.us"},"description":"Temporary package placeholder for staged publishing","directories":{}},"0.1.0":{"name":"@bsv/color-permission-module","version":"0.1.0","keywords":["brc-207","brc-162","1color","tokens","permissions","wallet","BSV"],"author":{"name":"BSV Association"},"license":"SEE LICENSE IN LICENSE.txt","_id":"@bsv/color-permission-module@0.1.0","maintainers":[{"name":"johngalt5","email":"dylan@murraydt.com"},{"name":"loftsteinn","email":"oli@oskarsson.nl"},{"name":"dkellen","email":"darrkellen@gmail.com"},{"name":"braydude","email":"brayden167@gmail.com"},{"name":"tyeverett","email":"p2ppsr@tyweb.us"}],"homepage":"https://github.com/bsv-blockchain/ts-stack/tree/main/packages/wallet/color-permission-module#readme","bugs":{"url":"https://github.com/bsv-blockchain/ts-stack/issues"},"dist":{"shasum":"f44f493e973138745b0863cfe6968f415f786c33","tarball":"https://registry.npmjs.org/@bsv/color-permission-module/-/color-permission-module-0.1.0.tgz","fileCount":6,"integrity":"sha512-HoCVQt2IZctLcpApVsfTRcalLraEiR4jUN7wvan02tRRZOsHUbaPhjMvaquWg17AHCLabTi+Jly9i5tBVNGmpg==","signatures":[{"sig":"MEUCIQCnB2NSmpXuBheuc0z+vFvvQVQYWp0qlUQwL/kJxom1YQIgBygd3XjmcTs+XCLVQH+aSk3y34LdjoaAMJoR0Wq3zCk=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIQCx3hAABw66Vy/DFHG3FjPGPfbrU68GAPQ/lnZlRDWA0wIgHJgy2djFAeJASMO3X/9n8D226bcZzHM6D6rD4KhUTuo=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@bsv%2fcolor-permission-module@0.1.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":362134},"main":"./dist/index.mjs","type":"module","_from":"file:/home/runner/work/ts-stack/ts-stack/release-artifacts/packages/bsv-color-permission-module-0.1.0.tgz","types":"./dist/index.d.mts","module":"./dist/index.mjs","engines":{"node":">=22"},"exports":{".":{"import":{"types":"./dist/index.d.mts","default":"./dist/index.mjs"}}},"scripts":{"lint":"oxlint src --deny-warnings","test":"jest","build":"tsdown src/index.ts --format esm --dts --sourcemap --clean --out-dir dist --tsconfig tsconfig.build.json","clean":"rm -rf dist","typecheck":"tsc --project tsconfig.typecheck.json","pack:check":"node ../../../scripts/check-package-artifact.mjs . --modes esm --exports ColorPermissionModule,ColorPlan,createColorModule","format:check":"pnpm --workspace-root exec prettier --check \"packages/wallet/color-permission-module/src/**/*.ts\" \"packages/wallet/color-permission-module/README.md\" \"packages/wallet/color-permission-module/*.{cjs,json,ts}\"","test:browser":"pnpm build && node ../../../scripts/check-browser-package.mjs .","test:coverage":"jest --coverage","test:property":"jest --runInBand --runTestsByPath src/__tests__/ColorPlan.property.test.ts"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"12769d2a-d2fc-4154-8e2f-93380bdb9699"}},"_resolved":"/home/runner/work/ts-stack/ts-stack/release-artifacts/packages/bsv-color-permission-module-0.1.0.tgz","_integrity":"sha512-HoCVQt2IZctLcpApVsfTRcalLraEiR4jUN7wvan02tRRZOsHUbaPhjMvaquWg17AHCLabTi+Jly9i5tBVNGmpg==","repository":{"url":"git+https://github.com/bsv-blockchain/ts-stack.git","type":"git","directory":"packages/wallet/color-permission-module"},"_npmVersion":"11.19.1","description":"BRC-207 1Color wallet module for BRC-162 fungible tokens in BRC-100 wallets","directories":{},"sideEffects":false,"_nodeVersion":"24.22.1","dependencies":{"@bsv/templates":"^2.1.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^30.5.1","oxlint":"^1.83.0","tsdown":"0.23.0","ts-jest":"^29.4.12","@bsv/sdk":"^4.0.0","fast-check":"^4.9.0","typescript":"npm:@typescript/typescript6@6.0.2","@types/jest":"^30.0.0","@types/node":"^26.6.1","@jest/globals":"^30.5.1","@typescript/native":"npm:typescript@7.0.2","@bsv/wallet-toolbox-client":"^2.15.0"},"peerDependencies":{"@bsv/sdk":"^4.0.0","@bsv/wallet-toolbox-client":"^2.15.0"},"_npmOperationalInternal":{"tmp":"tmp/color-permission-module_0.1.0_1792787960036_0.755266863259503","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@bsv/color-permission-module","version":"0.1.1","keywords":["brc-207","brc-162","1color","tokens","permissions","wallet","BSV"],"author":{"name":"BSV Association"},"license":"SEE LICENSE IN LICENSE.txt","_id":"@bsv/color-permission-module@0.1.1","maintainers":[{"name":"johngalt5","email":"dylan@murraydt.com"},{"name":"loftsteinn","email":"oli@oskarsson.nl"},{"name":"dkellen","email":"darrkellen@gmail.com"},{"name":"braydude","email":"brayden167@gmail.com"},{"name":"tyeverett","email":"p2ppsr@tyweb.us"}],"homepage":"https://github.com/bsv-blockchain/ts-stack/tree/main/packages/wallet/color-permission-module#readme","bugs":{"url":"https://github.com/bsv-blockchain/ts-stack/issues"},"dist":{"shasum":"0f3e74e8e0c5af6f574d29e9eed2eab116c3bcde","tarball":"https://registry.npmjs.org/@bsv/color-permission-module/-/color-permission-module-0.1.1.tgz","fileCount":6,"integrity":"sha512-d/r6MbzHGOKkqDL6EzpUE4ZaTHnMxDuL14yTrV4cTojB2nr5H7GvfJFdf/f0Xx0Cu9kovlDqfFvNC/BjDUV3mg==","signatures":[{"sig":"MEUCIQDofVd0tfXIYvIFDYtumi7KYpnnfikAmk4m663Kyx4UygIgTtN917cwhFRLn/9h1ZGR1+XPu1JajO5MP1rTO2zWWk4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIQDp1dVN4VBo1CO4/vVGw4BCDXq73hvElDcSU0EZOgFqiwIgT0XQJim2/VLtFMnL9NJ4W2Tl3nxJXLyF3qoadX4pIPI=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@bsv%2fcolor-permission-module@0.1.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":362461},"main":"./dist/index.mjs","type":"module","_from":"file:/home/runner/work/ts-stack/ts-stack/release-artifacts/packages/bsv-color-permission-module-0.1.1.tgz","types":"./dist/index.d.mts","module":"./dist/index.mjs","engines":{"node":">=22"},"exports":{".":{"import":{"types":"./dist/index.d.mts","default":"./dist/index.mjs"}}},"scripts":{"lint":"oxlint src --deny-warnings","test":"jest","build":"tsdown src/index.ts --format esm --dts --sourcemap --clean --out-dir dist --tsconfig tsconfig.build.json","clean":"rm -rf dist","typecheck":"tsc --project tsconfig.typecheck.json","pack:check":"node ../../../scripts/check-package-artifact.mjs . --modes esm --exports ColorPermissionModule,ColorPlan,createColorModule","format:check":"pnpm --workspace-root exec prettier --check \"packages/wallet/color-permission-module/src/**/*.ts\" \"packages/wallet/color-permission-module/README.md\" \"packages/wallet/color-permission-module/*.{cjs,json,ts}\"","test:browser":"pnpm build && node ../../../scripts/check-browser-package.mjs .","test:coverage":"jest --coverage","test:property":"jest --runInBand --runTestsByPath src/__tests__/ColorPlan.property.test.ts"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"12769d2a-d2fc-4154-8e2f-93380bdb9699"}},"_resolved":"/home/runner/work/ts-stack/ts-stack/release-artifacts/packages/bsv-color-permission-module-0.1.1.tgz","_integrity":"sha512-d/r6MbzHGOKkqDL6EzpUE4ZaTHnMxDuL14yTrV4cTojB2nr5H7GvfJFdf/f0Xx0Cu9kovlDqfFvNC/BjDUV3mg==","repository":{"url":"git+https://github.com/bsv-blockchain/ts-stack.git","type":"git","directory":"packages/wallet/color-permission-module"},"_npmVersion":"11.19.1","description":"BRC-207 1Color wallet module for BRC-162 fungible tokens in BRC-100 wallets","directories":{},"sideEffects":false,"_nodeVersion":"24.22.1","dependencies":{"@bsv/templates":"^2.1.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^30.5.1","oxlint":"^1.83.0","tsdown":"0.23.0","ts-jest":"^29.4.12","@bsv/sdk":"^4.0.1","fast-check":"^4.9.0","typescript":"npm:@typescript/typescript6@6.0.2","@types/jest":"^30.0.0","@types/node":"^26.6.1","@jest/globals":"^30.5.1","@typescript/native":"npm:typescript@7.0.2","@bsv/wallet-toolbox-client":"^2.15.1"},"peerDependencies":{"@bsv/sdk":"^4.0.1","@bsv/wallet-toolbox-client":"^2.15.0"},"_npmOperationalInternal":{"tmp":"tmp/color-permission-module_0.1.1_1793150843665_0.8534169309154789","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"_id":"@bsv/color-permission-module@0.2.0","bugs":{"url":"https://github.com/bsv-blockchain/ts-stack/issues"},"dist":{"shasum":"73c6b6aab926062f83ebce2d0ae0039649ff2bb2","tarball":"https://registry.npmjs.org/@bsv/color-permission-module/-/color-permission-module-0.2.0.tgz","fileCount":6,"integrity":"sha512-ii6HON2MoAzIM+CNJYZjti/fjCuHkHP4GceaEap06OgRrJLHxZWSdvwe4bwtN7sZeZpUTNMlSn1wetTNu/2mDQ==","signatures":[{"sig":"MEYCIQDH3MWJoGC/8aMVbYOLQVZqSXgKoxQNxw50NssDRZ79VgIhALmKQSmBeDk1L2gUYQqn+PCrsNdBaMHxBYbqTBcpWP7b","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIFxclUxJ1EYNSM+ERYfwvSFW7J9nNwQud4oGyoSs2dofAiAzFhVQOXVCaFilnEzuZ44PnjrWxHjphNIpyXcMBXj3bA=="}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@bsv%2fcolor-permission-module@0.2.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":555024},"main":"./dist/index.mjs","name":"@bsv/color-permission-module","type":"module","_from":"file:/home/runner/work/ts-stack/ts-stack/release-artifacts/packages/bsv-color-permission-module-0.2.0.tgz","types":"./dist/index.d.mts","author":{"name":"BSV Association"},"module":"./dist/index.mjs","engines":{"node":">=22"},"exports":{".":{"import":{"types":"./dist/index.d.mts","default":"./dist/index.mjs"}}},"license":"SEE LICENSE IN LICENSE.txt","scripts":{"lint":"oxlint src --deny-warnings","test":"jest","build":"tsdown src/index.ts --format esm --dts --sourcemap --clean --out-dir dist --tsconfig tsconfig.build.json","clean":"rm -rf dist","typecheck":"tsc --project tsconfig.typecheck.json","pack:check":"node ../../../scripts/check-package-artifact.mjs . --modes esm --exports ColorPermissionModule,ColorPlan,createColorModule","format:check":"pnpm --workspace-root exec prettier --check \"packages/wallet/color-permission-module/src/**/*.ts\" \"packages/wallet/color-permission-module/README.md\" \"packages/wallet/color-permission-module/*.{cjs,json,ts}\"","test:browser":"pnpm build && node ../../../scripts/check-browser-package.mjs .","test:coverage":"jest --coverage","test:property":"jest --runInBand --runTestsByPath src/__tests__/ColorPlan.property.test.ts"},"version":"0.2.0","_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"12769d2a-d2fc-4154-8e2f-93380bdb9699"}},"homepage":"https://github.com/bsv-blockchain/ts-stack/tree/main/packages/wallet/color-permission-module#readme","keywords":["brc-207","brc-162","1color","tokens","permissions","wallet","BSV"],"_resolved":"/home/runner/work/ts-stack/ts-stack/release-artifacts/packages/bsv-color-permission-module-0.2.0.tgz","_integrity":"sha512-ii6HON2MoAzIM+CNJYZjti/fjCuHkHP4GceaEap06OgRrJLHxZWSdvwe4bwtN7sZeZpUTNMlSn1wetTNu/2mDQ==","repository":{"url":"git+https://github.com/bsv-blockchain/ts-stack.git","type":"git","directory":"packages/wallet/color-permission-module"},"_npmVersion":"11.19.1","description":"BRC-207 1Color wallet module for BRC-162 fungible tokens in BRC-100 wallets","directories":{},"maintainers":[{"name":"johngalt5","email":"dylan@murraydt.com"},{"name":"loftsteinn","email":"oli@oskarsson.nl"},{"name":"dkellen","email":"darrkellen@gmail.com"},{"name":"braydude","email":"brayden167@gmail.com"},{"name":"tyeverett","email":"p2ppsr@tyweb.us"}],"sideEffects":false,"_nodeVersion":"24.22.1","dependencies":{"@bsv/templates":"^2.2.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^30.5.1","oxlint":"^1.83.0","tsdown":"0.23.0","ts-jest":"^29.4.12","@bsv/sdk":"^4.0.1","fast-check":"^4.9.0","typescript":"npm:@typescript/typescript6@6.0.2","@types/jest":"^30.0.0","@types/node":"^26.6.1","@jest/globals":"^30.5.1","@typescript/native":"npm:typescript@7.0.2","@bsv/wallet-toolbox-client":"^2.15.1","@bsv/wallet-toolbox-mobile":"^2.15.1"},"peerDependencies":{"@bsv/sdk":"^4.0.1","@bsv/wallet-toolbox-client":"^2.15.0"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/color-permission-module_0.2.0_1793333840504_0.08542148945163186"}}},"time":{"created":"2026-10-23T20:35:21.549Z","modified":"2026-10-30T04:17:20.923Z","0.0.0-stage":"2026-10-23T20:35:21.549Z","0.1.0":"2026-10-23T20:39:20.117Z","0.1.1":"2026-10-28T01:27:23.755Z","0.2.0":"2026-10-30T04:17:20.603Z"},"bugs":{"url":"https://github.com/bsv-blockchain/ts-stack/issues"},"author":{"name":"BSV Association"},"license":"SEE LICENSE IN LICENSE.txt","homepage":"https://github.com/bsv-blockchain/ts-stack/tree/main/packages/wallet/color-permission-module#readme","keywords":["brc-207","brc-162","1color","tokens","permissions","wallet","BSV"],"repository":{"url":"git+https://github.com/bsv-blockchain/ts-stack.git","type":"git","directory":"packages/wallet/color-permission-module"},"description":"BRC-207 1Color wallet module for BRC-162 fungible tokens in BRC-100 wallets","maintainers":[{"name":"johngalt5","email":"dylan@murraydt.com"},{"name":"loftsteinn","email":"oli@oskarsson.nl"},{"name":"dkellen","email":"darrkellen@gmail.com"},{"name":"braydude","email":"brayden167@gmail.com"},{"name":"tyeverett","email":"p2ppsr@tyweb.us"}],"readme":"# Color Permission Module\n\n`@bsv/color-permission-module` implements the BRC-207 `color` wallet module for\nBRC-162 fungible tokens. It runs inside a `WalletPermissionsManager` and handles\nevery `p color` protocol, basket and action label.\n\n## Installation\n\nThe module needs the wallet that the permissions manager wraps, an overlay\nprovider and a prompt callback:\n\n```ts\nimport { createColorModule } from '@bsv/color-permission-module'\nimport { WalletPermissionsManager } from '@bsv/wallet-toolbox-client'\n\nconst color = createColorModule({\n  wallet: setup.wallet,\n  provider: colorOverlayProvider,\n  requestTokenAccess: async (originator, message) =>\n    await showTokenPrompt(originator, JSON.parse(message))\n})\n\nconst wallet = new WalletPermissionsManager(setup.wallet, adminOriginator, {\n  permissionModules: { color }\n})\n```\n\n`wallet` must be the underlying wallet, not the permissions manager. The module\nderives `p color` keys, signs token inputs and reads its baskets through it.\nInventory listing uses the wallet-toolbox `specOpBasketPrefixOutputs` storage\noperation.\n\n`provider` implements `ColorOverlayProvider`. The wallet implementer decides\nwhich overlays it trusts:\n\n| Method                             | BRC-207 query                                                                  |\n| ---------------------------------- | ------------------------------------------------------------------------------ |\n| `spendability(assetId, outpoints)` | `color-spendability`: outputs currently admitted and unspent                   |\n| `admission(assetId, outpoints)`    | `color-admission`: outputs ever admitted, used to read the asset's deploy      |\n| `submit(topics, beef, offChain?)`  | Submits to each topic: `tm_color_<assetId>` per asset, `tm_color` for a deploy |\n\n`submit` receives a third argument, the raw BRC-22 `offChainValues` bytes, only\nfor assets whose required profiles supply submission data; every other call\npasses two arguments, so a 0.1.0 provider keeps working unchanged. A submit\nreturns each topic's admittance.\n\n`requestTokenAccess` receives a JSON message whose `type` is `color_send`,\n`color_signature`, `color_access` (a read) or `color_relinquish`, and returns\ntrue to approve. Every message\ncarries `seekPermission` (false only when the caller passed\n`seekPermission: false`), and a `color_send` for a plain-noSend hand-over\ncarries `handoff: true`. A declined request throws `ColorConsentDeclinedError`.\nA `color_access` names the `basket` read (with `assetId` and `role` for a\nbalance or holdings basket) or the `p color` `labels` of a `listActions`. The\nmodule asks\non every operation and keeps no grants; the host decides whether an existing\ngrant covers a request and when to prompt the user.\n\nCall `color.dispose()` when the host tears down the wallet. Registered on a\n`WalletPermissionsManager`, the module advertises `brc207-color=4` (BRC-205) in\nthe manager's `getVersion` string.\n\n## Application calls\n\n- **Send**: `createAction` with the recipient's BRC-162 output, a plan in\n  `p color plan` labels, built with `ColorPlan.toLabels`, and\n  `options.randomizeOutputs: false` (every plan requires it: the plan's output\n  indices and the approved facts name the requested outputs). The module selects\n  admitted token inputs and adds token change in `createAction`, and supplies\n  the source transactions of the inputs it selects in `inputBEEF`, merged with\n  any `inputBEEF` the caller gave. Every output the module files (token\n  change, owned outputs, receipts, deploys and handoff splits) carries the tag\n  `p color <hex>`: the lowercase hex of the SHA-256 of the UTF-8 bytes of its\n  custody's derivation suffix. The tag is 72 characters\n  whatever the suffix, and storage keeps nothing of the suffix itself. The module reads the\n  transactions of the inputs it selects by their tags (`tagQueryMode: 'any'`),\n  normally with one `listOutputs` per asset basket and `limit` the number of\n  selected inputs, capped at 10,000 per page. Different payments may share a\n  suffix. When more matching rows exist, the module pages within the initial\n  nonnegative safe-integer `totalOutputs` count and stops once every selected source\n  is found; a changed count, duplicate row,\n  oversized page, stalled traversal or missing selected output fails the call.\n  Only selected transactions and their proofs or unproven ancestors are retained;\n  other same-tag outputs are neither spent nor credited. An output without its suffix tag is not selected, and an app-named\n  input without it is refused, so outputs filed without the tag are not spent\n  through the module. Suffix tags are\n  left out of the `p color assets` view and of the balance views' tag filters. A selected output whose transaction\n  the wallet does not return in full fails the call, naming the outpoint. The\n  module stages its record of each input it signs for (outpoint, script,\n  satoshis, asset and decrypted custody) when `createAction` funds the action,\n  and when the wallet's `createAction` comes back it binds the records of the\n  inputs of the returned unsigned transaction to that action's reference.\n  `signAction` signs only the inputs bound to its reference, without listing\n  the wallet's outputs; a wallet may hide an action's reserved inputs from its\n  listings (wallet-toolbox's `auto` action-batch mode does). Which outputs are\n  available is storage's to decide; the module also skips outputs staged or\n  being selected by its own calls. A reference's records are dropped when\n  `signAction` signs or refuses, and on `dispose()`. Two cases leave records\n  until `dispose()`: an action aborted before `signAction` leaves its bound\n  records unused, and a wallet `createAction` that fails after the module\n  funded it leaves its inputs staged, so the module does not select them again\n  until `dispose()`. In\n  `signAction` it checks the funded transaction against the plan, asks the user\n  to approve it (`color_send`: every asset leg, satoshi totals and fee, the\n  signatures it releases), signs the token inputs with any `sighashTypes`\n  override and submits the processed transaction to each asset topic, trying up\n  to three times. As in BTMS, an accepted submission completes the action, and\n  a held output the overlay does not report is resubmitted from the wallet's\n  copy of its transaction when it is next selected.\n- **Mint, burn and authority operations**: the plan declares exactly the\n  operations BRC-207 derives from the transaction (`mint`, `burn`,\n  `authority-split`, `-combine`, `-transfer`, `-end`). Authority inputs are\n  selected from the authority basket when the caller supplies none; mints and\n  burns use only the caller's value inputs and get no change.\n- **Deploy**: a BRC-162 deploy at output 0 with `ISSUE` in `plan.assets` and\n  its remittance in `plan.ownedOutputs`.\n  Once signed, an owned deploy is filed in its asset's value or authority\n  basket (keeping its `ISSUE` key) through the wallet's `internalizeAction`,\n  then submitted to `tm_color`; `tm_color_<assetId>` must admit it before it\n  can be spent. A deploy cannot be a `noSend` action.\n- **Handoff**: the same call with a BRC-177 `p nosend expiry` label and\n  `noSend`. For assets without a `plain-nosend` profile this is the only\n  `noSend` token action, since a plain `noSend` sent later with `sendWith`\n  would never reach the token overlay (see [Required profiles](#required-profiles)\n  for plain-noSend hand-overs). When the inputs exceed the amount, the module\n  first broadcasts a split to the exact amount. The split pays the wallet\n  itself and, like BRC-177's revocation anchor, gets no separate consent.\n- **Receive**: `internalizeAction` with `basket insertion` into the asset's\n  value or authority basket and the BRC-207 receipt instructions. For assets\n  without required profiles, the caller must already have submitted the\n  transaction; the received output must be admitted and unspent, and every\n  input must unlock its source. The module relies on that admission for the\n  transaction's token amounts rather than re-evaluating them. A receipt carries\n  BRC-207 custody instructions only (`version`, `assetId`, `derivationPrefix`,\n  `derivationSuffix`, `senderIdentityKey`, at most 1000 bytes). For an asset\n  whose required profile defines `admitReceipt`, that hook decides admission\n  instead (see [Required profiles](#required-profiles)).\n- **App-built transactions**: `createSignature` with a `p color` protocol ID\n  and a BRC-207 signature envelope in `data`. The whole transaction is\n  evaluated as a send is: every input needs its source, every token input must\n  be admitted and unspent in its overlay, every source and output of a profile\n  asset must conform to its deploy (`req` and each profile's own `ext`), and the\n  user approves the same facts\n  (`color_signature`: every asset leg, destinations, satoshi totals and fee,\n  the signature released) before the module signs.\n- **Reads**: `listOutputs` with `p color assets`, `p color balance <assetTag>`\n  or `p color balance <assetTag> authority`. A balance is summed exactly and\n  answered as a number in `totalOutputs`: exact to 2^53, rounded above.\n  As in BTMS, reads report wallet state alone and never query the overlay: the\n  inventory tags each output `color_state_available` or `color_state_reserved`\n  (an input of a pending action). Overlay spendability is checked only when\n  spending.\n\n## Required profiles\n\nA deploy may require BRC-207 processing profiles in its `req` map. Without\nregistered handlers the module refuses every such asset, exactly as 0.1.0 did,\nand never touches a store. A host that supports profiles registers one handler\nper profile id and injects a durable store:\n\n```ts\nimport { createColorModule } from '@bsv/color-permission-module'\n\nconst color = createColorModule({\n  wallet: underlyingWallet,\n  provider: defaultProvider,\n  requestTokenAccess,\n  store, // ColorModuleStore: durable get/set/delete/keys\n  profiles: {\n    [issuerProfile.id]: issuerProfile // every profile the host's assets require\n  }\n})\n```\n\nEach `profiles` key must equal its handler's `id`, and `store` is required when\n`profiles` is non-empty; the constructor throws a `TypeError` otherwise. Every\nstore key the module writes starts with `color.v1.`: the deploy cache and the\nsettled records `markSettled` writes. The layout under that prefix is internal\nto the module, and hosts never read or write it.\n\nThe registry fails closed: an asset is supported only when every profile in its\ndeploy's `req` is registered with a matching version (`versions`), otherwise\n`UnsupportedProfileError`, checked for every entry before any handler code runs.\nHandlers only restrict what the module would otherwise do. The deploy is\nresolved, each source checked against its transaction id, from the `color.v1.`\ncache, then the default provider, then each handler's `deployProviders()` in\nregistration order. A `RequiredProfileHandler` (`ProfileDescriptor`,\n`ProfileAssetContext`, `ProfileTxView`, `ProfileReceipt` and `ReceiptAdmission`\nare exported types) defines:\n\n| Member            | When it runs and what it decides                                                                                                                                                                                                                                                                                                     |\n| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |\n| `id`, `versions`  | The profile URI and the exact versions it supports                                                                                                                                                                                                                                                                                   |\n| `checkDescriptor` | Synchronously, at asset resolution: validates its `req` entry against the whole `req`; throws `ProfileParamsError`                                                                                                                                                                                                                   |\n| `checkExt`        | At asset resolution and for every token of the asset: validates the profile's own `ext` entry; without it that entry must be absent                                                                                                                                                                                                  |\n| `provider`        | Routes every spendability, admission and submit call for the asset; two handlers of one asset returning different providers fail with `ProfileParamsError`                                                                                                                                                                           |\n| `deployProviders` | Asked in order for an unknown asset's deploy after the default provider                                                                                                                                                                                                                                                              |\n| `sendPolicy`      | `'plain-nosend'`: every token `createAction` moving the asset must be `noSend` without a BRC-177 expiry label; token change stays in the transaction, tagged `color_offline`, and the module never submits the action. `signAction` refuses `options.noSend: false` or a `sendWith` batch and returns `noSend: true`, `sendWith: []` |\n| `operations`      | The operations a holder may declare for the asset; absent means all                                                                                                                                                                                                                                                                  |\n| `checkPlanData`   | In `createAction` and again in `signAction`: checks the plan's `profileData` leaf for the asset (undefined when absent); throws `ProfileDataError`. A profile without it accepts no plan leaf                                                                                                                                        |\n| `submissionData`  | In `signAction` of an action the module submits, before signing: the non-empty `offChainValues` bytes submitted to `tm_color_<assetId>`; at most one handler per asset. Not called for a plain-noSend hand-over                                                                                                                      |\n| `admitReceipt`    | For every receipt of the asset, after the custody, basket, ownership and deploy-conformance checks, in place of the overlay spendability check: `{ credit: 'settled' }` credits it, `{ credit: 'pending' }` credits it tagged `color_offline`, a throw credits nothing; at most one handler per asset                                |\n\nPlan `profileData` may name only profiles in the asset's `req` and assets in\n`plan.assets` (`ProfileDataError` otherwise). A receipt never carries\n`profileData`: any non-empty receipt `profileData` fails with the 0.1.0 error,\nand the wallet always receives the 5-member custody JSON.\n\nEvery token of a profile asset the module reads, as a source or an output, in\n`createAction` (requested outputs and explicit inputs), `signAction` (the final\ntransaction), `createSignature` and receipts, must conform to the deploy: a\nrepeated `req` must be byte-identical to the deploy's, and each required\nprofile's `checkExt` must accept its own `ext` entry. A BRC-161 JSON leg\nsupplies no `ext` state, so `checkExt` sees an absent entry and may reject it.\n\n### Receipts admitted by a profile\n\n`admitReceipt(ctx, receipt)` receives the asset's `ProfileAssetContext` (the\nunderlying wallet, this wallet's identity key, the authenticated deploy and the\nprofile's descriptor) and `{ assetId, txid, outputIndex, tx, beef }`, where `tx`\nis the received `Transaction` and `beef` the caller's `internalizeAction` bytes.\nIt runs once per receipt output, in order, independent of any other profile.\nThe module never parses, stores or submits evidence for it: a token issuer's\nown library, running in the host, verifies whatever the parties exchanged and\nrecords its decision where an app cannot write, and the hook reads that record\nor asks the issuer's overlay itself.\n\n### Pending outputs and `markSettled`\n\nA receipt admitted as `pending`, and the token change of a plain-noSend\nhand-over, carry the stored tag `color_offline`. Views (`p color assets`,\nbalances and tag filters) show it, so `p color balance <assetTag>` with\n`tags: ['color_offline']` is the pending balance. A `color_offline` output is\nspendable only once its overlay lists it: the module never resubmits it, and\nnever resubmits any output of an asset whose profiles declare a `sendPolicy` or\n`submissionData`, since the wallet's copy carries no off-chain values.\n\nThe host submits plain-noSend hand-overs and pending receipts, then calls\n`color.markSettled(txid)` once the overlay admitted the transaction.\n`markSettled` is an in-process method of the module object, not a BRC-100 call,\nso no app can reach it. It writes `color.v1.settled.<txid>` once (a second call\nwrites nothing), and views then hide `color_offline` for that transaction's\noutputs. A lost store shows them as pending again. Without profiles it does\nnothing; a txid that is not lowercase hex throws a `TypeError`.\nCaller-supplied `color_*` tags are stripped whenever profiles are registered.\n\n### Errors\n\n`ProfileParamsError`, `ProfileDataError` and `ColorConsentDeclinedError` are\nexported runtime values. Each sets `name` to its class name and starts its\nmessage with `[ClassName] `. Hosts and bridges match on `name`, then on that\nprefix, never on `instanceof`, since the module can be loaded more than once.\n`UnsupportedProfileError` keeps its 0.1.0 messages.\n\n## Limits of this version\n\nThe module fails explicitly, rather than falling back, on:\n\n- holding, creating or filing BRC-161 JSON outputs, and the BRC-161 `burn`\n  operation. BRC-161 JSON `transfer`, `mint` and `deploy+mint` outputs are read\n  as value and `auth` and `deploy+auth` as authority, as inputs and as outputs\n  to other parties, with the same overlay checks as any foreign token input; the\n  envelope may sit anywhere in the script (BRC-160). Only value inputs can fund\n  JSON transfer outputs; a JSON mint needs an authority input. Assets first\n  deployed as BRC-161, at any output index, are supported in BRC-162 form;\n- assets whose deploy declares required processing profiles that no\n  registered handler supports, among them BRC-209;\n- `profileData` in receipts, and plan `profileData` for profiles the asset does\n  not require;\n- receipt `customInstructions` above 1000 bytes;\n- building a deploy that declares a non-empty `req`, and `ISSUE` leaves in plan\n  `profileData`: such deploys are built outside the module;\n- `createSignature` for assets whose profiles define `sendPolicy`,\n  `submissionData` or `checkPlanData`, since a released signature cannot carry\n  submission data, stay off the wire or pass through a plan whose transition a\n  profile checks;\n- satoshi change positions (`changePositions` with a null `assetId`): wallet-toolbox\n  adds satoshi change while funding and does not position it.\n\nA plain-noSend hand-over still needs its asset overlay reachable at\n`createAction` and `signAction`: every input, including a `color_offline` one,\nmust be listed as admitted and unspent. The module carries no token history and\nvalidates none; a profile whose tokens move through chains of unsettled\nhand-overs relies on its own library for that.\n\nExplicit inputs are supported: this wallet's `p color` outputs are signed by the\nmodule, and foreign token inputs count only once their asset's overlay admits\nthem. The module supplies `inputBEEF` for the inputs it selects; the source\ntransactions of an input the app names are the app's to supply in `inputBEEF`,\nas wallet-toolbox requires for explicit inputs. `inputPositions` and token `changePositions` are honored; change\npositions follow the requested outputs.\n\nThe module does not validate BRC-176 lineage: proof transport is not part of\nBRC-207, and a separate module will feed lineage packets to a wallet-local\noverlay before this one runs. It relies on overlay admission and spendability.\nPlans, signature envelopes and receipt instructions have no `tokenProofs`\nmember, and a `p color` label other than a plan label is rejected.\n\nSignatures released through `createSignature` are not yet recorded as BRC-207\nexposure. BRC-207's non-final transaction rules are not implemented; such\ntransactions follow the wallet's existing behavior.\n\n## Extending the module\n\nA wallet with its own token policy can subclass `ColorPermissionModule`: its\nmembers are `protected`, so a derivative can override, for example, `approve`\n(the consent prompt), `assertSupportedAsset` (which assets it handles),\n`selectInputs` (coin selection) or `spendable` (the overlay query). The helpers\nthe module evaluates transactions with are exported too: the token readers\n(`readTokenOutput`, `tryReadTokenOutput`, `readSentToken`), `transactionTokens`,\n`requiredOperations`, `supplyChange`, and the consent builders `actionConsent`\nand `transactionConsent`. Their 0.1.0 positional calls are unchanged; the hand-over flag and\nthe token reader go in a trailing options object (`ActionConsentOptions`, or\n`TransactionConsentOptions` in place of the `deployOwned` boolean).\n\n## Verification\n\n```bash\npnpm --filter @bsv/sdk build\npnpm --filter @bsv/wallet-toolbox-client build\npnpm --filter @bsv/color-permission-module typecheck\npnpm --filter @bsv/color-permission-module lint\npnpm --filter @bsv/color-permission-module test:coverage\n```\n\n## License\n\nOpen BSV License version 6. See `LICENSE.txt`.\n","readmeFilename":"README.md"}