@ducat-unit/wallet-snap 0.1.2 → 0.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/AUDIT_SCOPE.md CHANGED
@@ -1,11 +1,11 @@
1
1
  # Ducat Snap Audit Scope
2
2
 
3
- This file defines the minimum security review scope before publishing `@ducat-unit/wallet-snap` or submitting it for MetaMask allowlisting.
3
+ This file defines the minimum security review scope before MetaMask allowlisting for `@ducat-unit/wallet-snap@0.1.5`.
4
4
 
5
5
  ## In Scope
6
6
 
7
7
  - `snap.manifest.json` permissions and allowed origins.
8
- - BIP32 entropy use for `m/84'/1'` and `m/86'/1'`.
8
+ - BIP32 entropy use for `m/84'/0'`, `m/86'/0'`, `m/84'/1'`, and `m/86'/1'`.
9
9
  - Local BIP32 child derivation in `src/bip32.ts`.
10
10
  - Account derivation in `src/accounts.ts`.
11
11
  - BIP322-style message signing in `src/message.ts`.
@@ -17,7 +17,7 @@ This file defines the minimum security review scope before publishing `@ducat-un
17
17
  - User confirmation content in `src/confirmations.ts`.
18
18
  - State storage in `src/state.ts`.
19
19
  - Home page network fetches in `src/home.ts`.
20
- - Build artifacts produced by `npm run verify`.
20
+ - Build artifacts produced by `npm run verify:release`.
21
21
 
22
22
  ## Required Findings To Rule Out
23
23
 
@@ -25,7 +25,7 @@ This file defines the minimum security review scope before publishing `@ducat-un
25
25
  - Any signing path that signs an input not explicitly listed in `signInputs`.
26
26
  - Any signing path that signs inputs for addresses not derived by the Snap.
27
27
  - Any irreversible operation that can proceed without a MetaMask confirmation.
28
- - Any mainnet key path, address, broadcast endpoint, or signing support in V1.
28
+ - Any mainnet request that uses a testnet key path, testnet address, or testnet broadcast endpoint, and any testnet request that uses a mainnet key path, mainnet address, or mainnet broadcast endpoint.
29
29
  - Any unauthorized origin able to invoke Snap RPC methods.
30
30
  - Any malformed PSBT, wrong-network PSBT, unknown address, or unknown input index that is accepted.
31
31
  - Any package dependency that violates MetaMask Snap SES constraints or creates avoidable key-management risk.
@@ -40,7 +40,7 @@ The final audit package should include:
40
40
  - Fixed commit hash, if fixes are required.
41
41
  - `npm pack --dry-run` output.
42
42
  - `npm audit --omit=dev` output.
43
- - `npm run verify` output.
43
+ - `npm run verify:release` output.
44
44
  - Snapper/security scan output.
45
45
  - Final `snap.manifest.json` shasum.
46
46
  - Demo video URL following `DEMO_SCRIPT.md`.
package/DEMO_SCRIPT.md CHANGED
@@ -6,8 +6,8 @@ Use this script for the MetaMask allowlist/directory submission video. Record ag
6
6
 
7
7
  1. Build and serve the Snap with `npm run verify` and `npm run serve`.
8
8
  2. Configure the Ducat frontend with `NEXT_PUBLIC_DUCAT_SNAP_ID` pointing at the local Snap during pre-submission testing, or `npm:@ducat-unit/wallet-snap` for the npm build.
9
- 3. Use signet or mutinynet only.
10
- 4. Fund the Snap-derived sats account with test BTC.
9
+ 3. Use the audited network being demonstrated. For mainnet demos, use small controlled amounts and the audited production validator/frontend configuration.
10
+ 4. Fund the Snap-derived sats account with BTC for the selected network.
11
11
 
12
12
  ## Recording Steps
13
13
 
@@ -31,5 +31,5 @@ Use this script for the MetaMask allowlist/directory submission video. Record ag
31
31
  - Every irreversible signing action shows a MetaMask confirmation.
32
32
  - Confirmations include origin, network, signed input indexes, output summary, and fee when calculable.
33
33
  - Private keys are never exported or shown.
34
- - Mainnet is not available in the V1 manifest or UI.
34
+ - Mainnet, signet, and mutinynet all use the expected network-specific addresses, validator endpoints, and broadcast endpoints.
35
35
  - Xverse and UniSat remain available in the wallet list.
package/LISTING.md CHANGED
@@ -6,16 +6,16 @@ Ducat Bitcoin accounts and Ducat-aware transaction signing in MetaMask.
6
6
 
7
7
  ## Long Description
8
8
 
9
- Ducat is a MetaMask Snap for using Ducat with Bitcoin signet and mutinynet accounts derived inside MetaMask. The Snap derives deterministic testnet Bitcoin accounts from the user's MetaMask Secret Recovery Phrase, keeps private keys inside MetaMask, and signs only explicit PSBT inputs requested by the Ducat web app.
9
+ Ducat is a MetaMask Snap for using Ducat with Bitcoin mainnet, signet, and mutinynet accounts derived inside MetaMask. The Snap derives deterministic Bitcoin accounts from the user's MetaMask Secret Recovery Phrase, keeps private keys inside MetaMask, and signs only explicit PSBT inputs requested by the Ducat web app.
10
10
 
11
11
  The Ducat web app remains the action surface for create, deposit, borrow, repay, withdraw, swap, liquidation, and repossess flows. The Snap provides account discovery, BIP322-style message signing, PSBT signing, batch PSBT signing, a simple transfer path, Ducat-aware MetaMask confirmations, pending/completed/failed action notifications, recent action history, and a Snap home page with copyable account addresses, BTC/UNIT balance, vault summary lookups, recent activity, and Ducat app routes.
12
12
 
13
- Mainnet is intentionally not enabled in this release.
13
+ Mainnet is enabled in this audit candidate and must be covered by the third-party review before production distribution.
14
14
 
15
15
  ## Permissions Rationale
16
16
 
17
17
  - `endowment:rpc`: Allows only approved Ducat frontend origins to invoke the Snap.
18
- - `snap_getBip32Entropy`: Derives Bitcoin testnet account keys for `m/84'/1'` and `m/86'/1'`.
18
+ - `snap_getBip32Entropy`: Derives Bitcoin account keys for `m/84'/0'`, `m/86'/0'`, `m/84'/1'`, and `m/86'/1'`.
19
19
  - `snap_dialog`: Shows mandatory confirmations before message signing, PSBT signing, batch signing, or transfers.
20
20
  - `snap_manageState`: Stores recent Ducat action metadata for Snap home.
21
21
  - `snap_notify`: Shows informational MetaMask notifications for pending approvals, completed actions, and failed non-rejection actions.
@@ -28,7 +28,7 @@ Mainnet is intentionally not enabled in this release.
28
28
  - Install approval screen for the Ducat Snap.
29
29
  - Ducat app wallet modal showing MetaMask as a connector.
30
30
  - Connected Ducat account addresses.
31
- - PSBT confirmation for create or deposit showing an action title, origin, testnet network, compact summary rows, signed input details, output details, fees, warnings, and Ducat app metadata.
31
+ - PSBT confirmation for create or deposit showing an action title, origin, network, compact summary rows, signed input details, output details, fees, warnings, and Ducat app metadata.
32
32
  - Batch confirmation for liquidation or repossess showing all-or-nothing signing, per-transaction rows, total fee, and warnings.
33
33
  - Message signing confirmation showing origin, network, signing account, BIP322 signature type, message fingerprint, message length, and copyable message body.
34
34
  - Transfer confirmation showing amount, fee, the `You pay` amount, change, sender, recipient, selected UTXOs, and broadcast endpoint.
package/README.md CHANGED
@@ -1,242 +1,164 @@
1
1
  # Ducat MetaMask Snap
2
2
 
3
- `@ducat-unit/wallet-snap` is the Ducat Bitcoin account and signing Snap for MetaMask.
3
+ `@ducat-unit/wallet-snap` is the Ducat Bitcoin account and signing Snap for MetaMask. It derives deterministic mainnet, signet, and mutinynet Bitcoin accounts from the user's MetaMask Secret Recovery Phrase, keeps private keys inside MetaMask, and exposes a narrow Ducat JSON-RPC API to approved Ducat frontend origins.
4
4
 
5
- The Snap derives deterministic Bitcoin testnet accounts from the user's MetaMask Secret Recovery Phrase and exposes a small Ducat JSON-RPC API to the Ducat frontend. The Ducat web app remains the action surface. Users create, deposit, borrow, repay, withdraw, swap, and liquidate in the web app; the Snap handles account derivation, MetaMask confirmations, PSBT/message signing, transfer signing, recent action state, action notifications, and a Snap home page.
5
+ The Ducat web app remains the user action surface. Users create, deposit, borrow, repay, withdraw, swap, liquidate, and repossess in the web app; the Snap handles account discovery, MetaMask confirmations, message signing, PSBT signing, batch signing, transfer signing, recent action state, notifications, and Snap Home.
6
6
 
7
- ## Launch Scope
7
+ ## Release Candidate Status
8
8
 
9
+ - Package candidate: `@ducat-unit/wallet-snap@0.1.5`
10
+ - Snap ID: `npm:@ducat-unit/wallet-snap`
9
11
  - Proposed Snap name: `Ducat`
10
- - npm package: `@ducat-unit/wallet-snap`
11
- - Snap ID after publish: `npm:@ducat-unit/wallet-snap`
12
- - Local development Snap ID: `local:http://localhost:8080`
13
- - V1 networks: `signet` and `mutinynet`
14
- - Mainnet: intentionally disabled until audit, soak testing, and allowlist approval
15
- - Derivation paths:
16
- - sats: `m/84'/1'/0'/0/0`, P2WPKH `tb1q...`, compressed 33-byte public key
17
- - runes: `m/86'/1'/0'/0/0`, P2TR `tb1p...`, x-only 32-byte internal public key
18
- - vault: `m/86'/1'/0'/0/1`, P2TR `tb1p...`, x-only 32-byte internal public key
12
+ - Audit candidate tag: `audit-candidate-0.1.5-20260615-audit-confirmation-hardening`
13
+ - Audit candidate commit: tag target for `audit-candidate-0.1.5-20260615-audit-confirmation-hardening`
14
+ - GitHub verification: `Verify Ducat Snap`
15
+ - Manifest source shasum: `RE0s+LP6Soq0Xn0R8P+DA2ChhPOB2pasPp9BsJng5/Y=`
16
+ - Package candidate digest evidence: `RELEASE_EVIDENCE.md`
19
17
 
20
- ## Requirements
18
+ Launch scope:
21
19
 
22
- - Node.js and npm. The repo is currently verified with the bundled Codex Node runtime, Node `24.14.0`.
23
- - MetaMask with Snaps support.
24
- - For `local:http://localhost:8080`, MetaMask must allow local Snap fetching. If MetaMask shows `Fetching local snaps is disabled`, enable local Snap development in MetaMask/Flask developer settings, then retry the install/update.
25
- - A Ducat frontend checkout configured to use this Snap. The current integration branch uses `/Users/lucasrodriguez/Desktop/Ducat/frontend-metamask-snap`.
20
+ - Networks: `mainnet`, `signet`, and `mutinynet`
21
+ - Mainnet: enabled in this audit candidate
22
+ - Derivation paths:
23
+ - sats mainnet: `m/84'/0'/0'/0/0`, P2WPKH `bc1q...`, compressed 33-byte public key
24
+ - runes mainnet: `m/86'/0'/0'/0/0`, P2TR `bc1p...`, x-only 32-byte internal public key
25
+ - vault mainnet: `m/86'/0'/0'/0/1`, P2TR `bc1p...`, x-only 32-byte internal public key
26
+ - sats testnet: `m/84'/1'/0'/0/0`, P2WPKH `tb1q...`, compressed 33-byte public key
27
+ - runes testnet: `m/86'/1'/0'/0/0`, P2TR `tb1p...`, x-only 32-byte internal public key
28
+ - vault testnet: `m/86'/1'/0'/0/1`, P2TR `tb1p...`, x-only 32-byte internal public key
26
29
 
27
30
  ## Install
28
31
 
29
32
  ```bash
30
- cd /Users/lucasrodriguez/Desktop/Ducat/SNAP
31
33
  npm ci
32
34
  ```
33
35
 
34
- ## Verify
35
-
36
- Use the normal development gate while editing:
36
+ Recommended local edit gate:
37
37
 
38
38
  ```bash
39
39
  npm run type-check
40
- npm test
40
+ npm test -- --runInBand
41
41
  npm run build
42
42
  npm run manifest
43
- ```
44
-
45
- Or run the combined gate:
46
-
47
- ```bash
48
- npm run verify
49
- ```
50
-
51
- After `npm run verify`, smoke-test the built Snap in MetaMask's simulation runtime:
52
-
53
- ```bash
54
43
  npm run harness:accounts
44
+ npm run harness:smoke-signing
55
45
  ```
56
46
 
57
- The harness serves the local Snap, installs it with a deterministic test Secret Recovery Phrase, and invokes `ducat_getAccounts`.
58
-
59
- The stricter release gate also runs the MetaMask simulation harness smoke test, production dependency audit, Snapper, and an npm package dry-run:
47
+ Full release gate:
60
48
 
61
49
  ```bash
62
50
  npm run verify:release
63
51
  ```
64
52
 
53
+ `verify:release` runs type checking, Jest, build, manifest regeneration, MetaMask simulation harness checks, production dependency audit, Snapper, release metadata verification, release manifest verification, and `npm pack --dry-run`.
54
+
65
55
  ## Run Locally
66
56
 
67
- Serve the Snap manifest and bundle:
57
+ Serve the local Snap:
68
58
 
69
59
  ```bash
70
- cd /Users/lucasrodriguez/Desktop/Ducat/SNAP
71
60
  npm run serve
72
61
  ```
73
62
 
74
- The Snap is served from:
63
+ The local Snap is served at:
75
64
 
76
65
  ```text
77
66
  http://localhost:8080
78
67
  ```
79
68
 
80
- Every source, dependency, or icon change can change `snap.manifest.json`'s `source.shasum`. After changing the Snap, run:
81
-
82
- ```bash
83
- npm run build
84
- npm run manifest
85
- ```
86
-
87
- Then restart `npm run serve` if the server is already running.
88
-
89
- ## Frontend Setup
90
-
91
- In the Ducat frontend `.env.local`, point the MetaMask connector at the local Snap:
69
+ For local frontend testing:
92
70
 
93
71
  ```bash
94
72
  NEXT_PUBLIC_DUCAT_SNAP_ID="local:http://localhost:8080"
95
73
  NEXT_PUBLIC_DUCAT_SNAP_VERSION=""
96
74
  ```
97
75
 
98
- For the published Snap, use:
76
+ For the published Snap:
99
77
 
100
78
  ```bash
101
79
  NEXT_PUBLIC_DUCAT_SNAP_ID="npm:@ducat-unit/wallet-snap"
102
- NEXT_PUBLIC_DUCAT_SNAP_VERSION="^0.1.2"
80
+ NEXT_PUBLIC_DUCAT_SNAP_VERSION="^0.1.5"
103
81
  ```
104
82
 
105
- Run the frontend on an origin allowed by `snap.manifest.json`, for example:
83
+ Allowed HTTPS Ducat origins in the published mainnet manifest:
106
84
 
107
- ```bash
108
- cd /Users/lucasrodriguez/Desktop/Ducat/frontend-metamask-snap
109
- npm run dev -- -p 3002
110
- ```
111
-
112
- Allowed local origins are:
113
-
114
- - `http://localhost:3000`
115
- - `http://localhost:3001`
116
- - `http://localhost:3002`
117
- - `http://localhost:3003`
118
-
119
- Allowed HTTPS QA origins are:
120
-
121
- - `https://dev-git-feat-metamask-snap-connector-ducat.vercel.app`
122
-
123
- These localhost origins are intentionally present for local development and Snap QA only. Do not remove them from the development manifest during local testing.
124
-
125
- ### Known Deferred Issue: Localhost Manifest Origins
126
-
127
- `snap.manifest.json` currently includes localhost origins. That is intentional for local Snap development and QA, but the current development manifest is not directory-ready. Do not remove the localhost origins in this iteration; handle this as a dedicated release-manifest task before MetaMask submission.
128
-
129
- Release update plan:
130
-
131
- 1. Keep the current development manifest available for local Snap testing.
132
- 2. Add a release manifest path or manifest-generation mode that removes every localhost origin.
133
- 3. Keep only approved HTTPS Ducat frontend origins in `endowment:rpc.allowedOrigins`.
134
- 4. Rebuild from the audited commit and regenerate the Snap manifest source shasum.
135
- 5. Update all release artifacts from that exact build: `RELEASE_EVIDENCE.md`, `AUDITOR_HANDOFF.md`, `submission/metamask-directory.json`, `submission/ALLOWLIST_SUBMISSION.md`, package shasum/integrity, screenshots, demo notes, and frontend production Snap env values.
136
- 6. Run `npm run build`, `npm run manifest`, `npm run verify:release-manifest`, `npm run verify:release`, and `npm run verify:submission-ready`.
137
- 7. Retag the final audit or submission candidate only after the release manifest, package evidence, and submission metadata are synced.
138
-
139
- ## MetaMask Local Update Flow
85
+ - `https://app.ducatprotocol.com`
86
+ - `https://dev.app.ducatprotocol.com`
87
+ - `https://staging.app.ducatprotocol.com`
140
88
 
141
- 1. Run `npm run serve` in this repo.
142
- 2. Run the frontend with `NEXT_PUBLIC_DUCAT_SNAP_ID="local:http://localhost:8080"`.
143
- 3. Connect MetaMask from the Ducat wallet picker.
144
- 4. If the Snap was already installed and the local shasum changed, use the frontend `Update Snap` button in the wallet picker or connected wallet dropdown.
145
- 5. Approve the MetaMask update prompt.
146
- 6. Retry the Ducat action.
147
-
148
- The connector intentionally does not call `wallet_requestSnaps` before every signature. Signing methods use `wallet_invokeSnap` against the installed Snap, so a stale local build must be updated explicitly.
89
+ The published manifest authorizes only stable, org-controlled HTTPS Ducat origins. Local development (`http://localhost`) and ephemeral, re-registerable preview deployments (`*.vercel.app`) are deliberately excluded so a local process or a taken-over preview subdomain can never drive mainnet signing; use a separate, unpublished dev manifest for local Snap QA. The release verifier rejects localhost, non-HTTPS, wildcard, duplicate, or unknown origins in the shipped manifest.
149
90
 
150
91
  ## JSON-RPC API
151
92
 
152
93
  - `ducat_getAccounts({ network })`
153
- - `ducat_clearRecentActions()`
154
94
  - `ducat_getCapabilities()`
155
95
  - `ducat_signMessage({ network, address, message })`
156
96
  - `ducat_signPsbt({ network, psbt, signInputs, context })`
157
97
  - `ducat_signBatch({ network, entries, context })`
158
98
  - `ducat_sendTransfer({ network, address, amountSats, feeRate })`
159
99
  - `ducat_getHomeState({ network })`
100
+ - `ducat_clearRecentActions()`
160
101
 
161
- ## What Users See
102
+ ## User Confirmation Surface
162
103
 
163
- MetaMask confirmations are intentionally action-specific and use structured sections and rows:
104
+ MetaMask confirmations are action-specific and structured:
164
105
 
165
- - Message signing shows the Ducat action label, origin, testnet network, signing account, BIP322 signature type, message length, message fingerprint, and copyable message body.
166
- - PSBT signing shows the Ducat action label, origin, testnet network, compact summary rows, signed input details, output details, fee, warnings, and Ducat app metadata.
106
+ - Message signing shows the Ducat action label, origin, network, account, BIP322 signature type, message length, message fingerprint, and copyable message body.
107
+ - PSBT signing shows the Ducat action label, origin, network, summary rows, signed input details, output details, fee, warnings, and Ducat app metadata.
167
108
  - Batch signing shows transaction count, all-or-nothing semantics, total fee, per-transaction summaries, and warning count.
168
- - Simple BTC transfer shows amount, estimated fee, the `You pay` amount, change, sender, recipient, selected UTXO count/value, and broadcast endpoint.
169
- - Snap Home shows structured cards for the last connected network, copyable BTC/UNIT/vault addresses, BTC and UNIT balances when services are available, vault status, recent action status, clickable links for HTTPS Ducat app origins, and copyable local routes during development. Approved Ducat origins can request a confirmed recent-action history clear.
170
- - MetaMask notifications announce pending approvals, completed signing/broadcast actions, and non-rejection failures. Notifications are informational only and never gate signing behavior.
171
-
172
- Errors returned to the frontend are friendly by default and include a stable `code` plus diagnostic `details` for developers. The frontend should display the `message` and keep details available for expanded debugging.
173
-
174
- ## Troubleshooting
109
+ - Simple BTC transfer shows amount, estimated fee, `You pay`, change, sender, recipient, selected UTXOs, and broadcast endpoint.
110
+ - Snap Home shows last connected network, copyable BTC/UNIT/vault addresses, public balance and vault lookups when available, recent action state, approved HTTPS Ducat app links, and local development routes.
175
111
 
176
- | Symptom | Likely Cause | Fix |
177
- | --- | --- | --- |
178
- | `Fetching local snaps is disabled` | MetaMask local Snap development is disabled. | Enable local Snap fetching in MetaMask/Flask developer settings, then retry install/update. |
179
- | MetaMask asks to reinstall before signing | The served local Snap shasum changed. | Run `npm run build && npm run manifest`, restart `npm run serve`, then use the frontend `Update Snap` button. |
180
- | `This site is not authorized to use the Ducat Snap` | The frontend origin is not in `snap.manifest.json`. | Use one of the allowed local origins or add the origin intentionally and regenerate the manifest. |
181
- | `This transaction is trying to spend an input from a different Ducat Snap account` | The PSBT input does not match the derived Snap account requested in `signInputs`. | Refresh the frontend wallet account state and rebuild the Ducat transaction. Use diagnostic details to compare expected and actual input addresses. |
182
- | Balance or vault status is unavailable on Snap Home | Public indexer or Ducat validator lookup timed out or failed. | Retry later. Signing still uses PSBT data supplied by the Ducat app. |
112
+ Errors returned to the frontend include a stable `code`, user-facing `message`, and diagnostic `details` for expanded debugging.
183
113
 
184
114
  ## Security Model
185
115
 
186
- - Private keys never leave the Snap.
187
- - The Snap only requests testnet BIP32 entropy paths in v1.
188
- - Mainnet requests are rejected.
116
+ - Private keys, child private keys, WIFs, and raw entropy never leave the Snap.
117
+ - The Snap requests Bitcoin mainnet and testnet BIP32 entropy paths: `m/84'/0'`, `m/86'/0'`, `m/84'/1'`, and `m/86'/1'`.
118
+ - Mainnet requests use Bitcoin mainnet addresses, transaction parsing, and broadcast endpoints; signet and mutinynet requests use Bitcoin testnet parameters.
119
+ - Unauthorized origins cannot invoke the Snap RPC API.
189
120
  - Only explicit `signInputs` indexes are signed.
190
121
  - Signing is restricted to derived Ducat Snap accounts.
191
- - Every message, PSBT, batch, and transfer signing path requires MetaMask confirmation.
192
- - Friendly frontend action context is display metadata only. Parsed PSBT data is the trusted signing summary.
193
- - Unauthorized origins cannot invoke the Snap RPC API.
194
-
195
- ### Taproot Script-Path Policy
122
+ - Message, PSBT, batch, and transfer signing require MetaMask confirmation.
123
+ - Frontend context is treated as untrusted display metadata. Parsed PSBT data is the signing source of truth.
124
+ - Snap state stores recent Ducat action metadata only.
196
125
 
197
- Vault PSBTs that spend Taproot script-path inputs must include a Ducat cosign tapleaf and control-block data that recomputes to the prevout P2TR output key. The tapleaf must place the derived Ducat vault key in the client slot, and the client and guard pubkeys must be distinct. The Snap rejects uncommitted script-path inputs, client/guard key collapse, and generic leaves even if the leaf contains the derived Ducat vault key.
126
+ Taproot script-path inputs must include a Ducat cosign tapleaf and control-block data that recomputes to the prevout P2TR output key. The tapleaf must place the derived Ducat vault key in the client slot, and the client and guard pubkeys must be distinct. The Snap rejects uncommitted script-path inputs, client/guard key collapse, and generic leaves even when a leaf contains the derived vault key.
198
127
 
199
- Mainnet support still requires a separate audit pass, but the signet/mutinynet Snap no longer contains the earlier alpha fallback that accepted uncommitted tapleaf data.
128
+ ## Audit And Submission Packet
200
129
 
201
- ## Audit Readiness Plan
130
+ Primary audit documents:
202
131
 
203
- Use this plan to move the current audit candidate from "ready to review" to "ready to submit". Do not change `snap.manifest.json` localhost origins as part of this note; handle that as a dedicated release-manifest task before external submission.
132
+ - `AUDITOR_HANDOFF.md`
133
+ - `AUDIT_SCOPE.md`
134
+ - `RELEASE_EVIDENCE.md`
135
+ - `INTERNAL_SECURITY_REVIEW.md`
136
+ - `DEPENDENCY_AUDIT.md`
137
+ - `SNAPPER_REVIEW.md`
204
138
 
205
- Current candidate progress: duplicate previous-output rejection, missing previous-output data rejection, oversized signing request rejection, PSBT input/output size guard coverage, suspicious data-output warnings, malformed transfer broadcast txid rejection, bounded primitive app-context metadata validation, hostile app-context containment for decoded vault data, create/borrow/repay/withdraw/repo/liquidate vault action decode coverage, malformed Snap Home balance and vault-data rejection, public-account fixture replay for captured PSBT confirmation text, a HTTPS-only release-manifest verifier, and a final submission-readiness gate for fixtures, E2E evidence, screenshots, audit/demo URLs, and npm metadata are implemented. Remaining external evidence work is real transaction fixture capture, full E2E recording, final support/privacy/escalation details, npm publish evidence, and the third-party audit report.
139
+ Submission documents:
206
140
 
207
- 1. Expand the Ducat transaction fixture corpus. Capture real client-sdk/validator PSBT fixtures for create, deposit, borrow, repay, withdraw, swap, liquidation, and repossess flows on mutinynet/signet. Include the exact Snap `WalletAccountRecord` and expected confirmation text so `npm run verify:fixtures` can replay OP_RETURN decoding, action labels, vault state summaries, data-output labels, warning behavior, and confirmation rendering without private keys.
208
- 2. Harden PSBT policy tests. Add adversarial cases for wrong network, unknown sign indexes, duplicate inputs, mixed account ownership, malicious frontend context, malformed data outputs, uncommitted Taproot script-path inputs, missing previous-output data, and suspicious zero-value outputs.
209
- 3. Split development and release configuration. Keep localhost origins and `local:http://localhost:8080` for development, but create a release manifest path that allows only approved HTTPS Ducat origins. Update CI to verify the release manifest, package shasum, and submission metadata together.
210
- 4. Complete E2E evidence. Record install, update, connect, reload reconnect, create, deposit, borrow, repay, withdraw, swap, liquidation, repossess, rejection, and disabled/re-enabled Snap flows using the same candidate bundle submitted to audit.
211
- 5. Lock the external submission packet. Finalize privacy/support/escalation contacts, screenshots, demo video, npm publish evidence, audited commit, fixed commit if needed, and the audit report. Update `submission/ALLOWLIST_SUBMISSION.md`, `submission/metamask-directory.json`, and `RELEASE_EVIDENCE.md` from that final candidate.
141
+ - `submission/README.md`
142
+ - `submission/ALLOWLIST_SUBMISSION.md`
143
+ - `submission/EXTERNAL_GATES.md`
144
+ - `submission/metamask-directory.json`
145
+ - `submission/fixtures/README.md`
146
+ - `submission/e2e/README.md`
147
+ - `submission/screenshots/README.md`
212
148
 
213
- ## Release Path
214
-
215
- 1. Confirm `npm run verify:release` passes from a clean checkout.
216
- 2. Update `RELEASE_EVIDENCE.md` for the audited candidate.
217
- 3. Tag the audit candidate.
218
- 4. Complete the third-party audit required for `snap_getBip32Entropy`.
219
- 5. Merge any audit fixes and tag the fixed candidate.
220
- 6. Publish `@ducat-unit/wallet-snap@0.1.2` to npm.
221
- 7. Replace pending external fields in `submission/metamask-directory.json` and `submission/ALLOWLIST_SUBMISSION.md`.
222
- 8. Capture real PSBT fixtures into `submission/fixtures/`.
223
- 9. Capture final E2E evidence into `submission/e2e/evidence.json`.
224
- 10. Capture final screenshots into `submission/screenshots/`.
225
- 11. Record the demo video using `DEMO_SCRIPT.md`.
226
- 12. Run `npm run verify:submission-ready`.
227
- 13. Submit the MetaMask allowlist/directory request with audit report, npm URL, public repo URL, demo video, support details, and listing assets.
149
+ The source, package, metadata, and local verification evidence are ready for external audit handoff. MetaMask directory submission still requires the third-party audit report, final screenshots, demo video, real transaction fixtures, final E2E evidence, and project-owned support/escalation details listed in `submission/EXTERNAL_GATES.md`.
228
150
 
229
151
  ## Useful Commands
230
152
 
231
153
  ```bash
232
154
  npm run type-check
233
- npm test
155
+ npm test -- --runInBand
234
156
  npm run build
235
157
  npm run manifest
236
- npm run serve
237
- npm run verify
158
+ npm run verify:harness
238
159
  npm run verify:release
239
160
  npm run verify:metadata
161
+ npm run verify:release-manifest
240
162
  npm run verify:submission-ready
241
163
  npm run audit:prod
242
164
  npm run pack:dry-run
@@ -1,51 +1,55 @@
1
1
  # Ducat Snap Release Checklist
2
2
 
3
- ## Pre-Submission
3
+ ## Completed For `0.1.5`
4
4
 
5
- - [x] Public repository contains the current audit-candidate source commit.
6
- - [x] `.github/workflows/verify.yml` succeeds on the current audit candidate.
5
+ - [x] Public repository contains the audit-candidate source tag.
6
+ - [x] Audit candidate tag exists after the final handoff commit: `audit-candidate-0.1.5-20260615-audit-confirmation-hardening`.
7
+ - [ ] `.github/workflows/verify.yml` succeeds on the current audit candidate.
7
8
  - [x] `npm run verify:release` succeeds locally.
8
- - [ ] `submission/metamask-directory.json` pending external fields are replaced.
9
- - [ ] `npm run verify:submission-ready` succeeds after external evidence is complete.
10
9
  - [x] `npm run pack:dry-run` output reviewed.
11
10
  - [x] `npm run audit:prod` output reviewed.
12
11
  - [x] Dependency audit reviewed.
13
12
  - [x] Snapper/security scan reviewed.
14
13
  - [x] Console logs, unused permissions, accidental placeholders, and dead RPC methods removed or documented as external gates.
15
- - [x] Alpha Taproot script-path compatibility fallback in `src/psbt.ts` was removed and replaced with committed tapleaf verification.
16
- - [ ] Real create/deposit/borrow/repay/withdraw/swap/liquidation/repossess PSBT fixtures captured in `submission/fixtures/`.
17
- - [ ] Final signet/mutinynet E2E evidence captured in `submission/e2e/evidence.json`.
14
+ - [x] Legacy Taproot script-path compatibility behavior removed and replaced with committed tapleaf verification.
15
+ - [x] Deterministic MetaMask simulation harness covers account derivation and owned P2WPKH PSBT signing.
16
+ - [x] Mainnet derivation, network parsing, endpoint selection, and release metadata added to the audit candidate.
17
+ - [x] `@ducat-unit/wallet-snap@0.1.5` release metadata prepared for audit handoff.
18
+ - [ ] Frontend PR #675 default Snap version range updated to `^0.1.5`.
19
+
20
+ ## Required Before MetaMask Submission
21
+
18
22
  - [ ] Third-party audit completed because the Snap uses `snap_getBip32Entropy`.
19
- - [ ] Audit fixes merged and tagged.
23
+ - [ ] Audit fixes merged and tagged, if the audit requires fixes.
24
+ - [ ] `submission/metamask-directory.json` pending external fields are replaced.
25
+ - [ ] `submission/ALLOWLIST_SUBMISSION.md` pending external fields are replaced.
26
+ - [ ] Real create/deposit/borrow/repay/withdraw/swap/liquidation/repossess PSBT fixtures captured in `submission/fixtures/`.
27
+ - [ ] Final mainnet/signet/mutinynet E2E evidence captured in `submission/e2e/evidence.json`.
28
+ - [ ] Final screenshots captured in `submission/screenshots/`.
29
+ - [ ] Demo video recorded with `DEMO_SCRIPT.md`.
30
+ - [ ] Production support, escalation, and response-time details finalized.
31
+ - [ ] `npm run verify:submission-ready` succeeds after external evidence is complete.
20
32
 
21
33
  ## Listing Assets
22
34
 
23
- - [x] Icon.
24
- - [ ] `submission/screenshots/` contains final screenshots.
25
- - [ ] Screenshots captured from the audited build using `LISTING.md`.
35
+ - [x] Icon: `images/icon.svg`.
26
36
  - [x] Short description from `LISTING.md`.
27
37
  - [x] Long description from `LISTING.md`.
28
- - [x] Privacy policy.
29
- - [ ] Support and escalation contact.
30
- - [ ] Demo video recorded with `DEMO_SCRIPT.md`, showing install, connect, create/deposit/borrow/repay/withdraw/swap/liquidation signing, and Snap home.
31
-
32
- ## Publish
33
-
34
- - [ ] Publish `@ducat-unit/wallet-snap` to npm.
35
- - [ ] Submit MetaMask allowlist/directory request with:
36
- - [ ] audited commit
37
- - [ ] fixed commit
38
- - [ ] audit report
39
- - [ ] npm URL
40
- - [ ] public repo URL
41
- - [ ] demo video
42
- - [ ] support details
43
- - [ ] listing assets
38
+ - [x] Privacy policy source: `PRIVACY.md`.
39
+ - [x] Security disclosure source: `SECURITY.md`.
40
+ - [x] Support source: `SUPPORT.md`.
41
+ - [ ] Final PNG screenshots captured from the audited build.
42
+ - [ ] Demo video recorded from the audited build.
43
+ - [ ] Support and escalation contact copied into the submission form.
44
44
 
45
- ## Production Cutover
45
+ ## Submission
46
46
 
47
+ - [ ] Submit MetaMask allowlist/directory request with the audited commit, fixed commit if any, audit report, npm URL, public repository URL, demo video, support details, and listing assets.
47
48
  - [ ] MetaMask allowlist approval received.
49
+
50
+ ## Production Cutover
51
+
48
52
  - [ ] Frontend production config uses `NEXT_PUBLIC_DUCAT_SNAP_ID=npm:@ducat-unit/wallet-snap`.
49
53
  - [ ] Frontend production config uses the approved release range in `NEXT_PUBLIC_DUCAT_SNAP_VERSION`.
50
54
  - [ ] Existing Xverse and UniSat regression flows pass.
51
- - [ ] Signet/mutinynet install, connect, create, deposit, borrow, repay, withdraw, swap, and liquidation/repossess E2E scenarios pass.
55
+ - [ ] Mainnet/signet/mutinynet install, connect, create, deposit, borrow, repay, withdraw, swap, liquidation, and repossess E2E scenarios pass.
package/SECURITY.md CHANGED
@@ -2,12 +2,11 @@
2
2
 
3
3
  Report security issues privately to the Ducat maintainers before public disclosure.
4
4
 
5
- Production release requirements:
5
+ Release requirements:
6
6
 
7
7
  - Third-party audit for key-management usage of `snap_getBip32Entropy`.
8
- - MetaMask allowlist/directory review.
9
- - Dependency audit and Snapper/security scan.
10
- - No mainnet permissions until the mainnet release audit delta is complete.
11
-
12
- V1 signs only explicit PSBT input indexes that match the Snap-derived signet/mutinynet addresses.
8
+ - MetaMask allowlist/directory review before production distribution.
9
+ - Production dependency audit and Snapper/security scan for every release candidate.
10
+ - Mainnet key derivation, signing, and broadcast support must be covered by the third-party audit before production distribution.
13
11
 
12
+ `@ducat-unit/wallet-snap@0.1.5` supports mainnet, signet, and mutinynet. It signs only explicit PSBT input indexes that match Snap-derived addresses and requires MetaMask confirmation before message, PSBT, batch, or transfer signing.
package/SNAPPER_REVIEW.md CHANGED
@@ -6,7 +6,9 @@ Last local command:
6
6
  npx --yes @sayfer_io/snapper --path . --output snapper-report.json
7
7
  ```
8
8
 
9
- Local result: 206 findings, all risk 1 and all under the `ESLinting` category.
9
+ Local result: 221 findings across the `ESLinting`, `ExcessiveComments`, and `HardcodedSecrets` categories.
10
+
11
+ The three `HardcodedSecrets` findings are the Ducat guardian x-only **public** key (`ef8e6d84…ca2e`) hardcoded per network in `src/networks.ts`. It is a public key that is intended to be embedded so the Snap can pin the vault cosigner identity; it is not a secret. The remaining findings are style/comment-density scanner policy, not signing, key-export, origin-authorization, confirmation-bypass, or network-scope findings.
10
12
 
11
13
  ## Addressed Findings
12
14
 
package/SUPPORT.md CHANGED
@@ -6,4 +6,4 @@ https://github.com/DUCAT-UNIT/ducat-snap/issues
6
6
 
7
7
  Security issues should not be filed as public issues. Follow `SECURITY.md` for private disclosure.
8
8
 
9
- For MetaMask directory submission, the public support URL, escalation contact, and response-time expectations must also be copied into `submission/ALLOWLIST_SUBMISSION.md`.
9
+ Before MetaMask directory submission, copy the final public support URL, private escalation contact, and response-time expectation into `submission/ALLOWLIST_SUBMISSION.md`.