@bsv/wallet-toolbox 2.1.25 → 3.0.0-alpha.0

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.
Files changed (257) hide show
  1. package/docs/CREATEACTION_BLOCKERS.md +391 -0
  2. package/docs/CUTOVER_RUNBOOK.md +95 -0
  3. package/docs/REQUIREMENTS_COMPLIANCE.md +157 -0
  4. package/docs/ROLLOUT_PLAN.md +273 -0
  5. package/docs/SESSION_HANDOFF.md +298 -0
  6. package/docs/STORAGE_METHOD_WIRING.md +176 -0
  7. package/docs/client.md +3765 -1325
  8. package/docs/monitor.md +255 -33
  9. package/docs/services.md +304 -280
  10. package/docs/setup.md +24 -24
  11. package/docs/storage.md +2783 -251
  12. package/docs/v3-upgrade/index.html +911 -0
  13. package/docs/wallet.md +4956 -9455
  14. package/out/src/Wallet.d.ts.map +1 -1
  15. package/out/src/Wallet.js.map +1 -1
  16. package/out/src/WalletLogger.d.ts.map +1 -1
  17. package/out/src/WalletLogger.js.map +1 -1
  18. package/out/src/__tests/CWIStyleWalletManager.test.js.map +1 -1
  19. package/out/src/__tests/WalletPermissionsManager.fixtures.d.ts.map +1 -1
  20. package/out/src/__tests/WalletPermissionsManager.fixtures.js.map +1 -1
  21. package/out/src/entropy/EntropyCollector.d.ts.map +1 -1
  22. package/out/src/entropy/EntropyCollector.js.map +1 -1
  23. package/out/src/monitor/LeasedMonitorTask.d.ts +43 -0
  24. package/out/src/monitor/LeasedMonitorTask.d.ts.map +1 -0
  25. package/out/src/monitor/LeasedMonitorTask.js +89 -0
  26. package/out/src/monitor/LeasedMonitorTask.js.map +1 -0
  27. package/out/src/monitor/Monitor.d.ts +7 -0
  28. package/out/src/monitor/Monitor.d.ts.map +1 -1
  29. package/out/src/monitor/Monitor.js +7 -0
  30. package/out/src/monitor/Monitor.js.map +1 -1
  31. package/out/src/monitor/MonitorDaemon.d.ts.map +1 -1
  32. package/out/src/monitor/MonitorDaemon.js.map +1 -1
  33. package/out/src/monitor/V7LeasedTask.d.ts +43 -0
  34. package/out/src/monitor/V7LeasedTask.d.ts.map +1 -0
  35. package/out/src/monitor/V7LeasedTask.js +89 -0
  36. package/out/src/monitor/V7LeasedTask.js.map +1 -0
  37. package/out/src/monitor/index.all.d.ts +1 -0
  38. package/out/src/monitor/index.all.d.ts.map +1 -1
  39. package/out/src/monitor/index.all.js +1 -0
  40. package/out/src/monitor/index.all.js.map +1 -1
  41. package/out/src/monitor/tasks/TaskCheckForProofs.d.ts +2 -0
  42. package/out/src/monitor/tasks/TaskCheckForProofs.d.ts.map +1 -1
  43. package/out/src/monitor/tasks/TaskCheckForProofs.js +55 -0
  44. package/out/src/monitor/tasks/TaskCheckForProofs.js.map +1 -1
  45. package/out/src/monitor/tasks/TaskSendWaiting.d.ts.map +1 -1
  46. package/out/src/monitor/tasks/TaskSendWaiting.js.map +1 -1
  47. package/out/src/sdk/WalletStorage.interfaces.d.ts +59 -59
  48. package/out/src/sdk/WalletStorage.interfaces.d.ts.map +1 -1
  49. package/out/src/sdk/types.d.ts +32 -0
  50. package/out/src/sdk/types.d.ts.map +1 -1
  51. package/out/src/sdk/types.js +50 -1
  52. package/out/src/sdk/types.js.map +1 -1
  53. package/out/src/services/chaintracker/chaintracks/Ingest/LiveIngestorWhatsOnChainPoll.d.ts.map +1 -1
  54. package/out/src/services/chaintracker/chaintracks/Ingest/LiveIngestorWhatsOnChainPoll.js.map +1 -1
  55. package/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageBase.d.ts.map +1 -1
  56. package/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageBase.js.map +1 -1
  57. package/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageKnex.d.ts.map +1 -1
  58. package/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageKnex.js.map +1 -1
  59. package/out/src/services/chaintracker/chaintracks/createDefaultIdbChaintracksOptions.d.ts.map +1 -1
  60. package/out/src/services/chaintracker/chaintracks/createDefaultIdbChaintracksOptions.js.map +1 -1
  61. package/out/src/services/chaintracker/chaintracks/createDefaultKnexChaintracksOptions.d.ts.map +1 -1
  62. package/out/src/services/chaintracker/chaintracks/createDefaultKnexChaintracksOptions.js.map +1 -1
  63. package/out/src/services/chaintracker/chaintracks/createDefaultNoDbChaintracksOptions.d.ts.map +1 -1
  64. package/out/src/services/chaintracker/chaintracks/createDefaultNoDbChaintracksOptions.js.map +1 -1
  65. package/out/src/services/chaintracker/chaintracks/createIdbChaintracks.d.ts.map +1 -1
  66. package/out/src/services/chaintracker/chaintracks/createIdbChaintracks.js.map +1 -1
  67. package/out/src/services/chaintracker/chaintracks/createKnexChaintracks.d.ts.map +1 -1
  68. package/out/src/services/chaintracker/chaintracks/createKnexChaintracks.js.map +1 -1
  69. package/out/src/services/chaintracker/chaintracks/createNoDbChaintracks.d.ts.map +1 -1
  70. package/out/src/services/chaintracker/chaintracks/createNoDbChaintracks.js.map +1 -1
  71. package/out/src/services/chaintracker/chaintracks/util/BulkFilesReader.d.ts.map +1 -1
  72. package/out/src/services/chaintracker/chaintracks/util/BulkFilesReader.js.map +1 -1
  73. package/out/src/services/chaintracker/chaintracks/util/ChaintracksFs.d.ts.map +1 -1
  74. package/out/src/services/chaintracker/chaintracks/util/ChaintracksFs.js.map +1 -1
  75. package/out/src/services/chaintracker/chaintracks/util/SingleWriterMultiReaderLock.d.ts.map +1 -1
  76. package/out/src/services/chaintracker/chaintracks/util/SingleWriterMultiReaderLock.js.map +1 -1
  77. package/out/src/services/chaintracker/chaintracks/util/__tests/SingleWriterMultiReaderLock.test.js.map +1 -1
  78. package/out/src/storage/StorageIdb.d.ts.map +1 -1
  79. package/out/src/storage/StorageIdb.js +10 -5
  80. package/out/src/storage/StorageIdb.js.map +1 -1
  81. package/out/src/storage/StorageKnex.d.ts +133 -3
  82. package/out/src/storage/StorageKnex.d.ts.map +1 -1
  83. package/out/src/storage/StorageKnex.js +691 -94
  84. package/out/src/storage/StorageKnex.js.map +1 -1
  85. package/out/src/storage/StorageProvider.d.ts +114 -1
  86. package/out/src/storage/StorageProvider.d.ts.map +1 -1
  87. package/out/src/storage/StorageProvider.js +164 -4
  88. package/out/src/storage/StorageProvider.js.map +1 -1
  89. package/out/src/storage/WalletStorageManager.d.ts.map +1 -1
  90. package/out/src/storage/WalletStorageManager.js.map +1 -1
  91. package/out/src/storage/idbHelpers.d.ts +5 -0
  92. package/out/src/storage/idbHelpers.d.ts.map +1 -1
  93. package/out/src/storage/idbHelpers.js +42 -0
  94. package/out/src/storage/idbHelpers.js.map +1 -1
  95. package/out/src/storage/methods/attemptToPostReqsToNetwork.d.ts.map +1 -1
  96. package/out/src/storage/methods/attemptToPostReqsToNetwork.js +116 -4
  97. package/out/src/storage/methods/attemptToPostReqsToNetwork.js.map +1 -1
  98. package/out/src/storage/methods/createAction.d.ts.map +1 -1
  99. package/out/src/storage/methods/createAction.js +22 -5
  100. package/out/src/storage/methods/createAction.js.map +1 -1
  101. package/out/src/storage/methods/internalizeAction.d.ts.map +1 -1
  102. package/out/src/storage/methods/internalizeAction.js +172 -5
  103. package/out/src/storage/methods/internalizeAction.js.map +1 -1
  104. package/out/src/storage/methods/listActionsKnex.d.ts +49 -0
  105. package/out/src/storage/methods/listActionsKnex.d.ts.map +1 -1
  106. package/out/src/storage/methods/listActionsKnex.js +179 -69
  107. package/out/src/storage/methods/listActionsKnex.js.map +1 -1
  108. package/out/src/storage/methods/listOutputsKnex.d.ts.map +1 -1
  109. package/out/src/storage/methods/listOutputsKnex.js +51 -4
  110. package/out/src/storage/methods/listOutputsKnex.js.map +1 -1
  111. package/out/src/storage/methods/processAction.d.ts.map +1 -1
  112. package/out/src/storage/methods/processAction.js +82 -14
  113. package/out/src/storage/methods/processAction.js.map +1 -1
  114. package/out/src/storage/methods/purgeData.d.ts.map +1 -1
  115. package/out/src/storage/methods/purgeData.js +22 -14
  116. package/out/src/storage/methods/purgeData.js.map +1 -1
  117. package/out/src/storage/methods/reviewStatus.d.ts.map +1 -1
  118. package/out/src/storage/methods/reviewStatus.js +18 -9
  119. package/out/src/storage/methods/reviewStatus.js.map +1 -1
  120. package/out/src/storage/schema/KnexMigrations.d.ts.map +1 -1
  121. package/out/src/storage/schema/KnexMigrations.js +134 -0
  122. package/out/src/storage/schema/KnexMigrations.js.map +1 -1
  123. package/out/src/storage/schema/StorageIdbSchema.d.ts +43 -2
  124. package/out/src/storage/schema/StorageIdbSchema.d.ts.map +1 -1
  125. package/out/src/storage/schema/__tests/backfill.runner.test.d.ts +2 -0
  126. package/out/src/storage/schema/__tests/backfill.runner.test.d.ts.map +1 -0
  127. package/out/src/storage/schema/__tests/backfill.runner.test.js +148 -0
  128. package/out/src/storage/schema/__tests/backfill.runner.test.js.map +1 -0
  129. package/out/src/storage/schema/__tests/backfill.test.d.ts +2 -0
  130. package/out/src/storage/schema/__tests/backfill.test.d.ts.map +1 -0
  131. package/out/src/storage/schema/__tests/backfill.test.js +96 -0
  132. package/out/src/storage/schema/__tests/backfill.test.js.map +1 -0
  133. package/out/src/storage/schema/__tests/processingFsm.test.d.ts +2 -0
  134. package/out/src/storage/schema/__tests/processingFsm.test.d.ts.map +1 -0
  135. package/out/src/storage/schema/__tests/processingFsm.test.js +42 -0
  136. package/out/src/storage/schema/__tests/processingFsm.test.js.map +1 -0
  137. package/out/src/storage/schema/__tests/processingFsmLegacyMapping.test.d.ts +2 -0
  138. package/out/src/storage/schema/__tests/processingFsmLegacyMapping.test.d.ts.map +1 -0
  139. package/out/src/storage/schema/__tests/processingFsmLegacyMapping.test.js +82 -0
  140. package/out/src/storage/schema/__tests/processingFsmLegacyMapping.test.js.map +1 -0
  141. package/out/src/storage/schema/__tests/spendabilityRule.test.d.ts +2 -0
  142. package/out/src/storage/schema/__tests/spendabilityRule.test.d.ts.map +1 -0
  143. package/out/src/storage/schema/__tests/spendabilityRule.test.js +29 -0
  144. package/out/src/storage/schema/__tests/spendabilityRule.test.js.map +1 -0
  145. package/out/src/storage/schema/__tests/v7FsmLegacyMapping.test.d.ts +2 -0
  146. package/out/src/storage/schema/__tests/v7FsmLegacyMapping.test.d.ts.map +1 -0
  147. package/out/src/storage/schema/__tests/v7FsmLegacyMapping.test.js +77 -0
  148. package/out/src/storage/schema/__tests/v7FsmLegacyMapping.test.js.map +1 -0
  149. package/out/src/storage/schema/backfill.d.ts +35 -0
  150. package/out/src/storage/schema/backfill.d.ts.map +1 -0
  151. package/out/src/storage/schema/backfill.idb.d.ts +32 -0
  152. package/out/src/storage/schema/backfill.idb.d.ts.map +1 -0
  153. package/out/src/storage/schema/backfill.idb.js +95 -0
  154. package/out/src/storage/schema/backfill.idb.js.map +1 -0
  155. package/out/src/storage/schema/backfill.js +150 -0
  156. package/out/src/storage/schema/backfill.js.map +1 -0
  157. package/out/src/storage/schema/backfill.knex.d.ts +32 -0
  158. package/out/src/storage/schema/backfill.knex.d.ts.map +1 -0
  159. package/out/src/storage/schema/backfill.knex.js +240 -0
  160. package/out/src/storage/schema/backfill.knex.js.map +1 -0
  161. package/out/src/storage/schema/backfill.runner.d.ts +63 -0
  162. package/out/src/storage/schema/backfill.runner.d.ts.map +1 -0
  163. package/out/src/storage/schema/backfill.runner.js +64 -0
  164. package/out/src/storage/schema/backfill.runner.js.map +1 -0
  165. package/out/src/storage/schema/coinbaseMaturityBackfill.d.ts +25 -0
  166. package/out/src/storage/schema/coinbaseMaturityBackfill.d.ts.map +1 -0
  167. package/out/src/storage/schema/coinbaseMaturityBackfill.js +75 -0
  168. package/out/src/storage/schema/coinbaseMaturityBackfill.js.map +1 -0
  169. package/out/src/storage/schema/monitorLease.d.ts +57 -0
  170. package/out/src/storage/schema/monitorLease.d.ts.map +1 -0
  171. package/out/src/storage/schema/monitorLease.js +101 -0
  172. package/out/src/storage/schema/monitorLease.js.map +1 -0
  173. package/out/src/storage/schema/processingFsm.d.ts +27 -0
  174. package/out/src/storage/schema/processingFsm.d.ts.map +1 -0
  175. package/out/src/storage/schema/processingFsm.js +132 -0
  176. package/out/src/storage/schema/processingFsm.js.map +1 -0
  177. package/out/src/storage/schema/schemaCutover.d.ts +34 -0
  178. package/out/src/storage/schema/schemaCutover.d.ts.map +1 -0
  179. package/out/src/storage/schema/schemaCutover.js +230 -0
  180. package/out/src/storage/schema/schemaCutover.js.map +1 -0
  181. package/out/src/storage/schema/schemaCutoverIdb.d.ts +26 -0
  182. package/out/src/storage/schema/schemaCutoverIdb.d.ts.map +1 -0
  183. package/out/src/storage/schema/schemaCutoverIdb.js +90 -0
  184. package/out/src/storage/schema/schemaCutoverIdb.js.map +1 -0
  185. package/out/src/storage/schema/spendabilityRefresh.d.ts +49 -0
  186. package/out/src/storage/schema/spendabilityRefresh.d.ts.map +1 -0
  187. package/out/src/storage/schema/spendabilityRefresh.js +120 -0
  188. package/out/src/storage/schema/spendabilityRefresh.js.map +1 -0
  189. package/out/src/storage/schema/spendabilityRule.d.ts +45 -0
  190. package/out/src/storage/schema/spendabilityRule.d.ts.map +1 -0
  191. package/out/src/storage/schema/spendabilityRule.js +52 -0
  192. package/out/src/storage/schema/spendabilityRule.js.map +1 -0
  193. package/out/src/storage/schema/tables/TableAction.d.ts +3 -3
  194. package/out/src/storage/schema/tables/TableAction.d.ts.map +1 -1
  195. package/out/src/storage/schema/tables/TableChainTip.d.ts +1 -1
  196. package/out/src/storage/schema/tables/TableMonitorLease.d.ts +1 -1
  197. package/out/src/storage/schema/tables/TableOutput.d.ts +7 -0
  198. package/out/src/storage/schema/tables/TableOutput.d.ts.map +1 -1
  199. package/out/src/storage/schema/tables/TableOutput.js.map +1 -1
  200. package/out/src/storage/schema/tables/TableTransactionNew.d.ts +50 -0
  201. package/out/src/storage/schema/tables/TableTransactionNew.d.ts.map +1 -0
  202. package/out/src/storage/schema/tables/TableTransactionNew.js +3 -0
  203. package/out/src/storage/schema/tables/TableTransactionNew.js.map +1 -0
  204. package/out/src/storage/schema/tables/TableTxAudit.d.ts +1 -1
  205. package/out/src/storage/schema/tables/index.d.ts +5 -0
  206. package/out/src/storage/schema/tables/index.d.ts.map +1 -1
  207. package/out/src/storage/schema/tables/index.js +5 -0
  208. package/out/src/storage/schema/tables/index.js.map +1 -1
  209. package/out/src/storage/schema/transactionCrud.d.ts +41 -0
  210. package/out/src/storage/schema/transactionCrud.d.ts.map +1 -0
  211. package/out/src/storage/schema/transactionCrud.js +205 -0
  212. package/out/src/storage/schema/transactionCrud.js.map +1 -0
  213. package/out/src/storage/schema/transactionService.d.ts +315 -0
  214. package/out/src/storage/schema/transactionService.d.ts.map +1 -0
  215. package/out/src/storage/schema/transactionService.js +783 -0
  216. package/out/src/storage/schema/transactionService.js.map +1 -0
  217. package/out/src/storage/schema/txAudit.d.ts +33 -0
  218. package/out/src/storage/schema/txAudit.d.ts.map +1 -0
  219. package/out/src/storage/schema/txAudit.js +64 -0
  220. package/out/src/storage/schema/txAudit.js.map +1 -0
  221. package/out/src/storage/schema/v7Backfill.d.ts.map +1 -1
  222. package/out/src/storage/schema/v7Backfill.js +4 -1
  223. package/out/src/storage/schema/v7Backfill.js.map +1 -1
  224. package/out/src/storage/schema/v7Backfill.runner.d.ts.map +1 -1
  225. package/out/src/storage/schema/v7Backfill.runner.js +3 -1
  226. package/out/src/storage/schema/v7Backfill.runner.js.map +1 -1
  227. package/out/src/storage/schema/v7CoinbaseMaturityBackfill.d.ts +25 -0
  228. package/out/src/storage/schema/v7CoinbaseMaturityBackfill.d.ts.map +1 -0
  229. package/out/src/storage/schema/v7CoinbaseMaturityBackfill.js +75 -0
  230. package/out/src/storage/schema/v7CoinbaseMaturityBackfill.js.map +1 -0
  231. package/out/src/storage/schema/v7Crud.d.ts +5 -3
  232. package/out/src/storage/schema/v7Crud.d.ts.map +1 -1
  233. package/out/src/storage/schema/v7Crud.js +11 -9
  234. package/out/src/storage/schema/v7Crud.js.map +1 -1
  235. package/out/src/storage/schema/v7Cutover.d.ts +34 -0
  236. package/out/src/storage/schema/v7Cutover.d.ts.map +1 -0
  237. package/out/src/storage/schema/v7Cutover.js +223 -0
  238. package/out/src/storage/schema/v7Cutover.js.map +1 -0
  239. package/out/src/storage/schema/v7CutoverIdb.d.ts +26 -0
  240. package/out/src/storage/schema/v7CutoverIdb.d.ts.map +1 -0
  241. package/out/src/storage/schema/v7CutoverIdb.js +90 -0
  242. package/out/src/storage/schema/v7CutoverIdb.js.map +1 -0
  243. package/out/src/storage/schema/v7Fsm.d.ts.map +1 -1
  244. package/out/src/storage/schema/v7Fsm.js +22 -6
  245. package/out/src/storage/schema/v7Fsm.js.map +1 -1
  246. package/out/src/storage/schema/v7Service.d.ts +305 -0
  247. package/out/src/storage/schema/v7Service.d.ts.map +1 -0
  248. package/out/src/storage/schema/v7Service.js +757 -0
  249. package/out/src/storage/schema/v7Service.js.map +1 -0
  250. package/out/src/storage/schema/v7SpendabilityRefresh.d.ts +49 -0
  251. package/out/src/storage/schema/v7SpendabilityRefresh.d.ts.map +1 -0
  252. package/out/src/storage/schema/v7SpendabilityRefresh.js +111 -0
  253. package/out/src/storage/schema/v7SpendabilityRefresh.js.map +1 -0
  254. package/out/src/storage/storageProviderHelpers.js +1 -1
  255. package/out/src/storage/storageProviderHelpers.js.map +1 -1
  256. package/out/src/utility/Format.js.map +1 -1
  257. package/package.json +7 -4
@@ -0,0 +1,273 @@
1
+ # Schema Migration Rollout Plan
2
+
3
+ Multi-week phased production rollout of the new-schema migration (per the spec (`PROD_REQ_V7_TS.md`)). This is a **project plan**, not an operator runbook. For step-by-step cutover mechanics, see `docs/CUTOVER_RUNBOOK.md`.
4
+
5
+ **Owner:** Wallet Platform Lead
6
+ **Status:** Draft — pending sign-off
7
+ **Target start:** Week of 2026-05-18
8
+ **Target completion:** Week of 2026-06-15
9
+
10
+ ---
11
+
12
+ ## 1. Goal
13
+
14
+ Migrate every production wallet-toolbox database from the legacy `transactions` / `proven_tx_reqs` / `proven_txs` triad to the new canonical `transactions` + per-user `actions` model without losing a single UTXO, without exceeding 30 minutes of writer downtime in any deployment, and without regressing the hot spendable-outputs query latency. Success means: legacy tables dropped in week 4, conformance suite green in staging and production, zero P1/P2 incidents attributable to the migration, and a measurable reduction in `tx_audit.processing.rejected` once the granular FSM is live.
15
+
16
+ ---
17
+
18
+ ## 2. Risk Matrix
19
+
20
+ | Risk | Likelihood | Impact | Mitigation | Owner |
21
+ |---|---|---|---|---|
22
+ | **Cutover failure mid-rename** | Medium | High — torn FK state, writer pool stalled | `runSchemaCutover` is idempotent; `transactions_legacy` presence guard recovers from partial failure. Always run a staging dry-run on a production snapshot first. Maintenance-mode window 2× expected duration. | SRE on-call |
23
+ | **Partial backfill (rows skipped)** | Medium | High — silent UTXO loss | §3 smoke tests 3.1–3.5 enforce row-count parity and orphan-free FKs. Abort if any check fails. Pre-flight: snapshot legacy row counts to a separate file before cutover. | Wallet Platform Eng |
24
+ | **FK mismatch on `outputs` / `tx_labels_map`** | Medium | Critical — spendable query returns garbage | Cutover remaps FKs with offset arithmetic; smoke tests 3.4 + 3.5 must return 0 orphans. Block reopening writer pool until both return 0. | SRE on-call |
25
+ | **Downstream code drift (callers still hit `proven_tx_reqs`)** | High | High — instant 500s post-rename | Audit every dependent service (`monitor`, `services`, `wallet`, `client`) one week before staging cutover. Grep for legacy table names in production deploys. Block week-3 production cutover if any caller has been deployed in last 7 days without an audit. | Wallet Platform Eng |
26
+ | **Performance regression on hot spendable query** | Low | High — wallet UI latency | Verify single-table query plan (§4 of the spec) on staging with prod-scale data before week 2 cutover. Run k6 load test against `findSpendableOutputs` at 10× normal QPS. Compare p50/p95/p99 against pre-cutover baseline. Abort if p95 regresses >15%. | Performance Eng |
27
+ | **Coinbase maturity backfill miss** | Medium | Medium — coinbase outputs stuck unspendable | Runbook §6 known limitation: legacy coinbase outputs need one-off `matures_at_height` backfill. Add to pre-flight checklist; verify with sample query before opening writers. | Wallet Platform Eng |
28
+ | **Monitor race during cutover** | Low | High — chain tip writes mid-rename | Stop Monitor daemon before runSchemaCutover (runbook §2.2). Confirm `monitor_lease` is empty before proceeding. | SRE on-call |
29
+ | **Rollback window blown** | Low | Critical — no path back to legacy state | Rollback is best-effort and only valid if zero post-cutover writes have occurred. Keep `*_legacy` tables for full 30 days. Backup retained until week-4 drop signed off. | SRE on-call |
30
+ | **IDB client cutover lag** | Medium | Medium — mobile clients on stale schema | `runIdbSchemaCutover` runs on next app open. Add telemetry to count clients still on legacy schema; force-upgrade prompt at 14 days. | Mobile Eng |
31
+
32
+ ---
33
+
34
+ ## 3. Timeline
35
+
36
+ ### Week 1 (2026-05-18 — 2026-05-22): Deploy & shadow
37
+
38
+ **Theme:** Additive code lands. No cutover. Backfill rehearsed in staging.
39
+
40
+ | Day | Activity |
41
+ |---|---|
42
+ | Mon | Cut release branch. Deploy new-schema additive code (creates `transactions_new`, `actions`, `outputs` parallel structure) to staging. |
43
+ | Tue | Run the new-schema migration in additive mode on staging snapshot of production data. Capture row counts, durations, query plans. |
44
+ | Wed | Shadow-run TransactionService writes against staging — both schemas updated, reads still hit legacy. Verify divergence metric stays at 0. |
45
+ | Thu | Deploy new-schema additive code to production (no cutover). Verify zero impact on hot query latency. |
46
+ | Fri | Performance baseline: capture p50/p95/p99 of `findSpendableOutputs`, `refreshOutputsSpendable`, monitor tick duration. Document in dashboard. |
47
+
48
+ **Exit criteria:** Additive code deployed to prod; staging shadow shows 100% write parity for 48h; backfill duration measured against prod-scale staging data.
49
+
50
+ ### Week 2 (2026-05-25 — 2026-05-29): Stage cutover + soak
51
+
52
+ **Theme:** Real cutover on staging. 7-day soak. Full conformance suite.
53
+
54
+ | Day | Activity |
55
+ |---|---|
56
+ | Mon | Schedule staging maintenance window. Run full pre-flight checklist (§4). |
57
+ | Mon | Execute `runSchemaCutover` on staging. Execute `runIdbSchemaCutover` against staging IDB fixtures. Time the cutover; record duration. |
58
+ | Mon | Run runbook §3 smoke tests. Reopen staging writers only after all pass. |
59
+ | Tue–Sun | 7-day soak. Run §5 conformance suite end-to-end on day 1, day 3, day 7. Run k6 load test on day 2 and day 6. |
60
+ | Daily | Watch metrics from §6. Flag any anomaly to the rollout channel. |
61
+
62
+ **Exit criteria:** Conformance suite green on day 7; zero P1/P2 incidents; `tx_audit.processing.rejected` rate flat or declining; FK orphan checks return 0 every 12h.
63
+
64
+ ### Week 3 (2026-06-01 — 2026-06-05): Production cutover + monitor
65
+
66
+ **Theme:** Production cutover in scheduled window. 7-day monitored soak. Rollback armed.
67
+
68
+ | Day | Activity |
69
+ |---|---|
70
+ | Mon AM | Final go/no-go meeting. Verify go criteria (§5). |
71
+ | Mon (window) | Scheduled maintenance window — 02:00–04:00 UTC. Drain writers. Stop Monitor. Run `runSchemaCutover` on production. Run smoke tests. Reopen writers on green. |
72
+ | Mon PM | Rolling Monitor restart. Watch lease contention metric. |
73
+ | Tue–Sun | 7-day monitored soak. Daily metrics review at 09:00 UTC. Rollback playbook on hot standby — SRE on-call rehearses restore from backup once during the week. |
74
+ | Daily | IDB cutover telemetry — track client migration rate. |
75
+
76
+ **Exit criteria:** Conformance suite green on day 7; zero P1/P2 production incidents; orphan checks return 0; performance within 5% of week-1 baseline; >95% of mobile clients on new IDB schema.
77
+
78
+ ### Week 4 (2026-06-08 — 2026-06-12): Decommission
79
+
80
+ **Theme:** Drop legacy tables. Remove shadow paths. Close the book.
81
+
82
+ | Day | Activity |
83
+ |---|---|
84
+ | Mon | Final orphan + row-count audit on production. Confirm no code path references `*_legacy` tables. |
85
+ | Tue | Scheduled maintenance window. Drop `transactions_legacy`, `proven_tx_reqs_legacy`, `proven_txs_legacy`. Drop legacy indexes. |
86
+ | Wed | Remove shadow-write code paths from main. Tag release. |
87
+ | Thu | Archive pre-cutover backup to cold storage. Update runbook with lessons learned. |
88
+ | Fri | Project retro. Close epic. |
89
+
90
+ **Exit criteria:** Legacy tables dropped; shadow code removed; retro complete; epic closed.
91
+
92
+ ---
93
+
94
+ ## 4. Pre-flight Checklist
95
+
96
+ Operators must verify all ten items before kicking off the cutover step in week 2 or week 3.
97
+
98
+ 1. Full database backup taken in the last 4 hours and verified by test-restore on a scratch host.
99
+ 2. new-schema additive migration applied: `SELECT name FROM sqlite_master WHERE type='table' AND name='transactions_new'` returns one row.
100
+ 3. Deployed application code is on the new-schema storage path (`TransactionService` enabled, no callers reference `proven_txs` or `proven_tx_reqs`).
101
+ 4. Legacy coinbase outputs have had `matures_at_height` backfilled (runbook §6 known limitation).
102
+ 5. Writer pool drained or application in maintenance mode; zero in-flight wallet transactions confirmed.
103
+ 6. Monitor daemon stopped; `monitor_lease` table empty.
104
+ 7. Pre-cutover row-count snapshot captured to `cutover-snapshot-<env>-<timestamp>.json` (counts of `transactions`, `proven_tx_reqs`, `proven_txs`, `outputs`, `tx_labels_map`).
105
+ 8. Performance baseline from week 1 saved and accessible to the rollout channel.
106
+ 9. Rollback decision-maker identified and on-call; backup restore script tested in the last 7 days.
107
+ 10. Comms sent (§8): engineering team, on-call rotation, ops, leadership notified 24h ahead with start time and rollback contact.
108
+
109
+ ---
110
+
111
+ ## 5. Go / No-Go Criteria
112
+
113
+ Explicit conditions to abort each phase. If any condition trips, halt and run the abort procedure (rollback if cutover started; revert deploy if not).
114
+
115
+ ### Week 1 — Deploy additive code
116
+ - **GO:** Staging additive migration completes in <2× estimated duration; shadow-write divergence metric is 0; hot query p95 unchanged on staging.
117
+ - **NO-GO:** Migration fails or exceeds 2× estimate; shadow-write divergence >0; hot query p95 regresses >15% on staging.
118
+
119
+ ### Week 2 — Stage cutover
120
+ - **GO:** All ten pre-flight items checked; staging backup verified; conformance suite green from week 1 shadow run.
121
+ - **NO-GO:** Any pre-flight item unchecked; backfill rehearsal failed; downstream-code-drift audit found unmigrated callers.
122
+ - **ABORT during cutover:** Any §3 smoke test returns nonzero orphans or row-count mismatch; cutover exceeds 3× estimated duration.
123
+
124
+ ### Week 3 — Production cutover
125
+ - **GO:** All week-2 exit criteria met; zero open P1/P2 from staging soak; rollback playbook rehearsed in last 7 days; leadership sign-off recorded.
126
+ - **NO-GO:** Any staging soak incident unresolved; pre-flight checklist incomplete; any caller deployed in last 7 days without an audit.
127
+ - **ABORT during cutover:** Same as week 2 — orphan checks fail or duration exceeds 3× estimate. Trigger rollback per runbook §4.
128
+
129
+ ### Week 4 — Decommission
130
+ - **GO:** 7-day production soak clean; mobile IDB migration >95%; final orphan audit returns 0.
131
+ - **NO-GO:** Any open incident referencing new tables; IDB migration <95%; any caller still referencing `*_legacy`.
132
+
133
+ ---
134
+
135
+ ## 6. Observability
136
+
137
+ Metrics and dashboards required before week 2 cutover. All must be wired into the rollout dashboard with alert thresholds.
138
+
139
+ | Metric | Source | Threshold | Alert |
140
+ |---|---|---|---|
141
+ | `tx_audit.processing.rejected` rate | tx_audit table, rolled up 1m | <1/min sustained | Page on-call if >10/min for 5m |
142
+ | `refreshOutputsSpendable.flipped` count | refreshOutputsSpendable return value | Baseline ±20% | Slack on-call if 5× baseline |
143
+ | `monitor_lease` contention | monitor_lease attempts vs. claims | <5% retry rate | Page if >20% for 10m |
144
+ | Cutover duration histogram | runSchemaCutover step timings | <budget per runbook §1.5 | Real-time during cutover only |
145
+ | FK orphan check counts | Smoke test queries §3.4 + §3.5 | Always 0 | Page immediately on nonzero |
146
+ | Hot spendable query p50/p95/p99 | App-side timer around `findSpendableOutputs` | p95 <baseline+15% | Page if p95 >baseline+25% for 5m |
147
+ | IDB cutover progress | Client telemetry — schema version reported | Trending up | Slack daily summary |
148
+ | Shadow-write divergence (week 1) | App-side comparator: legacy vs. new-schema row state | Always 0 | Page on first nonzero |
149
+ | `transactions.processing` FSM distribution | Histogram by state, sampled every 5m | Stable mix | Slack if any state spikes 10× |
150
+ | Backup recency | Backup tooling — last successful timestamp | <4h | Block cutover if >4h |
151
+
152
+ **Dashboards required:**
153
+ - **Schema Migration Rollout** — all metrics above, single page, refresh 30s.
154
+ - **Schema Migration Performance** — hot query latencies vs. baseline, 1h/24h/7d.
155
+ - **Schema Migration Audit** — tx_audit event volume by type, FSM transition violations, orphan check history.
156
+
157
+ ---
158
+
159
+ ## 7. Linear Ticket Structure
160
+
161
+ Proposed structure — **do not auto-create**. Hand to the planner once leadership signs off on the timeline.
162
+
163
+ ### Parent epic
164
+
165
+ **OPL-XXX — Schema Migration Rollout to Production**
166
+
167
+ - Labels: `epic`, `cutover`, `migration`
168
+ - Cycle: spans 4 cycles (one per week)
169
+ - Description: Links this plan, the PRD, the runbook. Lists all child tickets. Owner: Wallet Platform Lead.
170
+ - Acceptance: All 12 child tickets closed; legacy tables dropped; retro filed; dashboard archived.
171
+
172
+ ### Child tickets
173
+
174
+ #### Week 1 — Deploy & shadow
175
+
176
+ **OPL-XXX-1 — Deploy new-schema additive code to staging**
177
+ - Labels: `staging`, `cutover`
178
+ - Acceptance: `transactions_new`, `actions`, `outputs` tables exist in staging; row counts match expectations; no impact on staging query latency for 24h.
179
+
180
+ **OPL-XXX-2 — Shadow-write parity in staging**
181
+ - Labels: `staging`, `observability`
182
+ - Acceptance: Shadow-write comparator runs against staging traffic; divergence metric stays at 0 for 48h; comparator code merged behind feature flag.
183
+
184
+ **OPL-XXX-3 — Deploy new-schema additive code to production**
185
+ - Labels: `cutover`
186
+ - Acceptance: Production has `transactions_new` + `actions` tables; zero impact on hot query latency for 24h post-deploy; rollback path validated.
187
+
188
+ **OPL-XXX-4 — Performance baseline capture**
189
+ - Labels: `observability`
190
+ - Acceptance: p50/p95/p99 of `findSpendableOutputs`, `refreshOutputsSpendable`, monitor tick duration documented in Schema Migration Performance dashboard. Numbers signed off by Performance Eng.
191
+
192
+ #### Week 2 — Staging cutover
193
+
194
+ **OPL-XXX-5 — Build Schema Migration Rollout dashboard**
195
+ - Labels: `observability`
196
+ - Acceptance: All 10 metrics in §6 of plan wired; alert thresholds configured; dashboard linked from epic.
197
+
198
+ **OPL-XXX-6 — Stage cutover dry-run on production snapshot**
199
+ - Labels: `staging`, `cutover`
200
+ - Acceptance: `runSchemaCutover` executed on staging restored from prod snapshot; duration measured; smoke tests pass; results documented.
201
+
202
+ **OPL-XXX-7 — Run §5 conformance suite against post-cutover staging**
203
+ - Labels: `staging`
204
+ - Acceptance: All conformance tests (existing + new conformance tests) green on day 1, day 3, day 7 of staging soak.
205
+
206
+ #### Week 3 — Production cutover
207
+
208
+ **OPL-XXX-8 — Downstream code audit**
209
+ - Labels: `cutover`
210
+ - Acceptance: Grep audit of every dependent service (monitor, services, wallet, client) — zero references to `proven_tx_reqs` or `proven_txs` in deployable code paths. Audit signed off by Wallet Platform Eng.
211
+
212
+ **OPL-XXX-9 — Rollback rehearsal**
213
+ - Labels: `rollback`, `cutover`
214
+ - Acceptance: SRE on-call restores from a recent prod backup on a scratch host; documents restore duration; confirms `rollbackSchemaCutover` works on the rehearsal data.
215
+
216
+ **OPL-XXX-10 — Production cutover execution**
217
+ - Labels: `cutover`
218
+ - Acceptance: Scheduled maintenance window completed; smoke tests pass; writers reopened; no P1/P2 in first 24h; cutover duration logged.
219
+
220
+ **OPL-XXX-11 — 7-day production soak observation**
221
+ - Labels: `observability`, `cutover`
222
+ - Acceptance: Daily metrics review for 7 days; all thresholds in §6 stayed within bounds; orphan checks 0; no migration-attributable incidents.
223
+
224
+ #### Week 4 — Decommission
225
+
226
+ **OPL-XXX-12 — Drop legacy tables & remove shadow paths**
227
+ - Labels: `cutover`
228
+ - Acceptance: `transactions_legacy`, `proven_tx_reqs_legacy`, `proven_txs_legacy` dropped in scheduled window; shadow-write code removed from main; release tagged; backup archived to cold storage.
229
+
230
+ ---
231
+
232
+ ## 8. Communication Plan
233
+
234
+ Who needs to know what, when. Slack channels named for the wallet-toolbox org conventions; substitute as needed.
235
+
236
+ | Phase boundary | Engineering team (#wallet-eng) | On-call (#oncall-wallet) | Ops (#ops) | Leadership (email + #leadership) |
237
+ |---|---|---|---|---|
238
+ | **T-7 days before Week 1** | Plan + timeline shared; ticket assignments | Awareness only | Awareness only | Plan + risk matrix, 1-pager |
239
+ | **Week 1 deploy day** | Deploy plan, on-call rotation | Active — handle any deploy fallout | Notified at start + end | Status update at EOD |
240
+ | **Week 1 EOW** | Performance baseline + shadow results | Status | Status | Weekly status: green/yellow/red |
241
+ | **T-24h before staging cutover** | Pre-flight checklist link, window time | Pre-flight checklist link, window time | Notified | Notified |
242
+ | **Staging cutover start** | Live thread in #wallet-eng | Active — primary responder | Notified at start | — |
243
+ | **Staging cutover end** | Smoke test results | Smoke test results | Notified | EOD update |
244
+ | **Daily during staging soak** | Metrics summary, dashboard link | Active for any alert | — | Weekly only |
245
+ | **T-48h before prod cutover** | Final go/no-go meeting invite | Final go/no-go meeting invite | Maintenance window booking | Go/no-go context briefing |
246
+ | **T-24h before prod cutover** | Comms blast: window, rollback contact, dashboard link | Same + on-call handoff | Same + customer comms draft | Same |
247
+ | **Prod cutover start** | Live thread in #wallet-eng | Active — primary responder, rollback armed | Updates every 15m | Watch only |
248
+ | **Prod cutover end (green)** | Smoke results, writer reopen confirmed | Stand down to monitoring | Customer comms sent | Status update with metrics |
249
+ | **Prod cutover end (rollback)** | Rollback initiated; timeline | Active — execute rollback per runbook §4 | Customer comms: extended window | Immediate phone call to lead + VP |
250
+ | **Daily during prod soak** | Metrics summary | Active for any alert | — | Weekly only |
251
+ | **Week 4 decommission** | Drop plan, window time | Awareness | Notified | Final status: project closed |
252
+ | **Post-retro** | Retro doc shared | Lessons learned for runbook | Process improvements | Outcome summary |
253
+
254
+ **Escalation path during any cutover window:**
255
+ 1. SRE on-call (primary)
256
+ 2. Wallet Platform Lead (secondary)
257
+ 3. VP Engineering (rollback authority for production)
258
+
259
+ **Customer comms ownership:** Ops drafts; Wallet Platform Lead approves; sent by Ops 24h ahead of any user-visible maintenance window.
260
+
261
+ ---
262
+
263
+ ## 9. Open Questions
264
+
265
+ Resolve before week 2 starts. Owner in parens.
266
+
267
+ - Mobile IDB force-upgrade threshold — 14 days as proposed, or shorter? (Mobile Eng)
268
+ - MySQL deployments — runbook §6 flags no automated integration tests. Do we hold MySQL cutover for an extra cycle? (Wallet Platform Lead)
269
+ - Backup retention beyond 30 days — cold storage cost vs. recovery confidence. (Ops)
270
+
271
+ ---
272
+
273
+ *End of ROLLOUT_PLAN.md**
@@ -0,0 +1,298 @@
1
+ # Wallet-Toolbox Refactor — Session Handoff
2
+
3
+ **Date:** 2026-05-12
4
+ **Branch:** `wallet-toolbox-v3`
5
+ **Spec source:** `PROD_REQ_V7_TS.md` + `bsv_wallet_transaction_requirements (1).md` v1.0
6
+
7
+ Use this doc to resume work in a fresh session. Read it top to bottom before dispatching new subagents.
8
+
9
+ ---
10
+
11
+ ## 0. Naming convention (renaming pass complete)
12
+
13
+ Prior drafts of this work used `V7`/`v7` as a working label throughout the codebase. That label was the 7th draft number of an internal requirements document and had no meaning outside this team. A bulk rename pass stripped every `V7`/`v7` reference from source, tests, docs, and most comments. Future readers should see the work as a wallet-toolbox refactor, not a versioned cut.
14
+
15
+ **Identifier renames applied:**
16
+
17
+ | From | To |
18
+ |---|---|
19
+ | `V7TransactionService` | `TransactionService` |
20
+ | `V7BackfillDriver` / `V7BackfillStats` | `BackfillDriver` / `BackfillStats` |
21
+ | `V7KnexBackfillDriver` / `V7IdbBackfillDriver` | `KnexBackfillDriver` / `IdbBackfillDriver` |
22
+ | `V7LeasedTask` | `LeasedMonitorTask` |
23
+ | `TableTransactionV7` | `TableTransactionNew` |
24
+ | `runV7Backfill` / `runV7KnexBackfill` / `runV7IdbBackfill` | `runBackfill` / `runKnexBackfill` / `runIdbBackfill` |
25
+ | `runV7Cutover` / `runV7IdbCutover` / `rollbackV7Cutover` | `runSchemaCutover` / `runIdbSchemaCutover` / `rollbackSchemaCutover` |
26
+ | `transactions_v7` (Knex table, IDB store, all string literals) | `transactions_new` |
27
+ | `transactionsV7` (IDB schema key) | `transactionsNew` |
28
+ | `upgradeTransactionsV7` | `upgradeTransactionsNew` |
29
+ | `getV7Service` | `getTransactionService` |
30
+
31
+ **File renames applied** (source + tests + docs):
32
+
33
+ ```
34
+ src/storage/schema/v7Backfill.ts → backfill.ts
35
+ src/storage/schema/v7Backfill.runner.ts → backfill.runner.ts
36
+ src/storage/schema/v7Backfill.knex.ts → backfill.knex.ts
37
+ src/storage/schema/v7Backfill.idb.ts → backfill.idb.ts
38
+ src/storage/schema/v7Crud.ts → transactionCrud.ts
39
+ src/storage/schema/v7Cutover.ts → schemaCutover.ts
40
+ src/storage/schema/v7CutoverIdb.ts → schemaCutoverIdb.ts
41
+ src/storage/schema/v7Fsm.ts → processingFsm.ts
42
+ src/storage/schema/v7Service.ts → transactionService.ts
43
+ src/storage/schema/v7Spendability.ts → spendabilityRule.ts
44
+ src/storage/schema/v7SpendabilityRefresh.ts → spendabilityRefresh.ts
45
+ src/storage/schema/v7MonitorLease.ts → monitorLease.ts
46
+ src/storage/schema/v7TxAudit.ts → txAudit.ts
47
+ src/storage/schema/v7CoinbaseMaturityBackfill.ts → coinbaseMaturityBackfill.ts
48
+ src/storage/schema/tables/TableTransactionV7.ts → TableTransactionNew.ts
49
+ src/monitor/V7LeasedTask.ts → LeasedMonitorTask.ts
50
+ test/storage/v7*.test.ts → matching descriptive names
51
+ docs/V7_*.md → prefix dropped
52
+ ```
53
+
54
+ **Migration string key:** `'2026-05-11-001 V7 additive schema (...)'` was renamed to `'2026-05-11-001 add refactor schema (...)'` because the migration was never released to production. Future migration keys should describe what they do without any version label.
55
+
56
+ **Comments cleaned:** every `V7 spec`, `per V7 §X`, `V7 canonical`, `V7 cutover`, etc. comment was rewritten contextually. File header doc blocks were rewritten to describe behavior without a version reference.
57
+
58
+ **Intentional carve-outs:**
59
+
60
+ - `PROD_REQ_V7_TS.md` — root spec doc, kept as the external source-of-record name.
61
+ - File-level citations like `* §5 conformance suite from PROD_REQ_V7_TS.md` — deliberate spec doc references.
62
+
63
+ **Verification:** `grep -rn 'V7\|v7' src test docs` returns zero hits outside the two intentional carve-outs above.
64
+
65
+ The renaming pass touched ~50 files. All renamed tests pass. Build clean.
66
+
67
+ ---
68
+
69
+ ## 1. Status at a glance
70
+
71
+ | Layer | Status |
72
+ |---|---|
73
+ | Schema (tables, FSM, migrations) | Complete |
74
+ | Backfill (pure helpers + Knex/IDB drivers) | Complete |
75
+ | TransactionService (CRUD + FSM + audit + lease + spendability) | Complete (15 net-new methods + 4 wave-1 methods) |
76
+ | Cutover (Knex + IDB destructive helpers) | Complete |
77
+ | Storage method wiring | Complete: listOutputsKnex, listActionsKnex, createAction, processAction, attemptToPostReqsToNetwork, internalizeAction |
78
+ | Monitor lease + recordProof integration | Partial: TaskCheckForProofs wired; other tasks deferred |
79
+ | Spec compliance (`bsv_wallet_transaction_requirements v1.0`) | §1-§6 fully satisfied; §7 testing 7/10 scenarios explicit; §8 3/4 satisfied |
80
+ | Tests | **15 refactor suites, 141 tests, 100% pass.** Combined storage+method suite 364 pass, 7 failures (pre-existing, see §4), 1 skipped |
81
+ | Naming | All `V7`/`v7` references stripped. See §0 above. |
82
+
83
+ Build: `npm run build` clean.
84
+
85
+ ---
86
+
87
+ ## 2. Files inventory
88
+
89
+ ### Source — schema & migrations
90
+
91
+ ```
92
+ src/sdk/types.ts ProcessingStatus FSM + legacy maps
93
+ src/storage/schema/KnexMigrations.ts Additive new-schema migration + maturity column
94
+ src/storage/schema/StorageIdbSchema.ts IDB types for new-schema stores
95
+ src/storage/idbHelpers.ts IDB upgradeV1 + new-schema stores
96
+ src/storage/schema/tables/TableAction.ts NEW per-user view type
97
+ src/storage/schema/tables/TableTransactionNew.ts NEW per-txid canonical type
98
+ src/storage/schema/tables/TableChainTip.ts NEW singleton chain tip
99
+ src/storage/schema/tables/TableTxAudit.ts NEW append-only audit
100
+ src/storage/schema/tables/TableMonitorLease.ts NEW per-task lease
101
+ src/storage/schema/tables/TableOutput.ts ADDED maturesAtHeight field
102
+ src/storage/schema/tables/index.ts exports
103
+ ```
104
+
105
+ ### Source — service primitives
106
+
107
+ ```
108
+ src/storage/schema/processingFsm.ts Transition table + validator
109
+ src/storage/schema/spendabilityRule.ts Pure §4 rule
110
+ src/storage/schema/spendabilityRefresh.ts Knex refresh, preserves reorging
111
+ src/storage/schema/monitorLease.ts tryClaim/renew/release
112
+ src/storage/schema/txAudit.ts appendTxAudit + auditProcessingTransition
113
+ src/storage/schema/transactionCrud.ts find/insert/transitionProcessing
114
+ src/storage/schema/transactionService.ts TransactionService — primary surface
115
+ ```
116
+
117
+ ### Source — backfill & cutover
118
+
119
+ ```
120
+ src/storage/schema/backfill.ts Pure transformation helpers
121
+ src/storage/schema/backfill.runner.ts Orchestrator (empty-txid map fix)
122
+ src/storage/schema/backfill.knex.ts Knex driver
123
+ src/storage/schema/backfill.idb.ts IDB driver
124
+ src/storage/schema/schemaCutover.ts Knex destructive cutover helper
125
+ src/storage/schema/schemaCutoverIdb.ts IDB cutover (store rename via copy)
126
+ src/storage/schema/coinbaseMaturityBackfill.ts One-off coinbase maturesAtHeight backfill
127
+ ```
128
+
129
+ ### Source — wired storage methods + monitor
130
+
131
+ ```
132
+ src/storage/StorageProvider.ts getTransactionService, insertLegacyTransaction, disable/enableForeignKeys
133
+ src/storage/StorageKnex.ts TransactionService override, provenTxs*TableName helpers
134
+ src/storage/methods/createAction.ts Routes inserts to transactions_legacy
135
+ src/storage/methods/processAction.ts Calls findOrCreateActionForTxid + repointLabelsToActionId + repointOutputsToNewTransactionId
136
+ src/storage/methods/listActionsKnex.ts JOIN actions ⨝ transactions, status filter mapping
137
+ src/storage/methods/listOutputsKnex.ts t.processing filter, label-join via actions hop
138
+ src/storage/methods/attemptToPostReqsToNetwork.ts 10 call sites (recordHistoryNote, recordBroadcastResult, incrementAttempts, mergeBeefForTxids)
139
+ src/storage/methods/internalizeAction.ts 5 call sites (findActionByUserTxid, findOrCreateForBroadcast, recordProof/createWithProof, updateActionSatoshisDelta)
140
+ src/storage/methods/reviewStatus.ts proven*TableName resolution
141
+ src/storage/methods/purgeData.ts proven*TableName resolution
142
+ src/monitor/Monitor.ts instanceId for lease ownership
143
+ src/monitor/LeasedMonitorTask.ts NEW helper wraps body in claim/renew/release
144
+ src/monitor/tasks/TaskCheckForProofs.ts Lease-gated proof loop + recordProof hook
145
+ src/monitor/index.all.ts Exports LeasedMonitorTask
146
+ ```
147
+
148
+ ### Tests
149
+
150
+ ```
151
+ src/storage/schema/__tests/backfill.test.ts Pure helpers
152
+ src/storage/schema/__tests/backfill.runner.test.ts Fake driver
153
+ src/storage/schema/__tests/processingFsm.test.ts Transition matrix
154
+ src/storage/schema/__tests/processingFsmLegacyMapping.test.ts Legacy→new-schema status mapping
155
+ src/storage/schema/__tests/spendabilityRule.test.ts §4 pure rule
156
+ test/storage/backfillKnex.test.ts Knex integration
157
+ test/storage/transactionCrudAndAudit.test.ts Insert/find/transition + audit
158
+ test/storage/monitorLease.test.ts Claim/renew/release/takeover
159
+ test/storage/schemaCutover.test.ts Full+empty+idempotent
160
+ test/storage/schemaCutoverIdb.test.ts IDB rename via fake-indexeddb
161
+ test/storage/schemaConformance.test.ts §5 + spec compliance (10 tests)
162
+ test/storage/coinbaseMaturityBackfill.test.ts Maturity height = height+100
163
+ test/storage/transactionServiceExpansion.test.ts 38 tests across 15 net-new methods
164
+ test/storage/methods/monitorLeaseIntegration.test.ts Two-instance lease race
165
+ test/storage/listActionsKnexRefactor.test.ts listActions post-cutover
166
+ test/storage/methods/listOutputsKnexRefactor.test.ts listOutputs post-cutover
167
+ test/storage/methods/createActionRefactor.test.ts createAction/processAction wiring
168
+ test/storage/methods/attemptToPostReqsToNetworkRefactor.test.ts All 4 broadcast outcomes
169
+ test/storage/methods/internalizeActionWiring.test.ts 5 branches
170
+ ```
171
+
172
+ ### Docs
173
+
174
+ ```
175
+ docs/CUTOVER_RUNBOOK.md Operator runbook (pre-flight, smoke tests, rollback)
176
+ docs/ROLLOUT_PLAN.md 4-week phased plan + Linear ticket structure
177
+ docs/STORAGE_METHOD_WIRING.md Gap analysis + 26-day effort estimate (now mostly done)
178
+ docs/CREATEACTION_BLOCKERS.md txid timing problem + chosen Option B
179
+ docs/REQUIREMENTS_COMPLIANCE.md Spec compliance audit
180
+ docs/SESSION_HANDOFF.md This file
181
+ ```
182
+
183
+ ---
184
+
185
+ ## 3. Spec compliance summary (v1.0)
186
+
187
+ Per `bsv_wallet_transaction_requirements (1).md`:
188
+
189
+ | Section | Status | Notes |
190
+ |---|---|---|
191
+ | §1 Core Principles | ✅ | Reorg gap fixed (FSM tightened, refresh preserves) |
192
+ | §2 Statuses | ✅ | 9-status spec mapped to 14 ProcessingStatus values |
193
+ | §3 Happy Path | ✅ | Self-created flow + fallback preserved in legacy |
194
+ | §4 Third-party | ✅ | Both confirmed + unconfirmed paths covered |
195
+ | §5 Failure scenarios | ✅ | All 7 scenarios handled |
196
+ | §6 DB sync rules | ✅ | Refresh skips reorging to preserve spendable |
197
+ | §7 Tests | 7/10 explicit | Tests A (tip/deep), B (broadcast-fail discard), E (mixed broadcast) deferred — legacy code covers semantics but no new-schema-specific test |
198
+ | §8 Non-functional | 3/4 | Atomicity gap acknowledged (eventual consistency via refresh) |
199
+
200
+ ---
201
+
202
+ ## 4. Known pre-existing failures (not migration-caused)
203
+
204
+ | Test | Cause | Fix path |
205
+ |---|---|---|
206
+ | `createActionToGenerateBeefs.man.test.ts` (6 tests) | Manual test, requires live funded wallet | None — operator-driven |
207
+ | `StorageMySQLDojoReader.man.test.ts` | Needs `TEST_DOJO_CONNECTION` env | None — operator-driven |
208
+ | `adminStats.man.test.ts` | Needs MySQL env | None — operator-driven |
209
+ | `abortAction.test.ts` (when run with other suites) | Knex connection pool exhaustion (resource leak in beforeAll) | Fix pool teardown in test fixtures; tests pass when run alone |
210
+ | `markStaleInputsAsSpent.test.ts` | FK violation pre-cutover (schema bug predating cutover) | Likely fixed by running cutover before test |
211
+ | `findLegacy.test.ts` test 8 | Queries `status` column on post-cutover `transactions` | Rewrite to use `processing` or query `transactions_legacy` |
212
+ | `update.test.ts 7a updateTransactionStatus` | Pre-existing | Same path as findLegacy test 8 |
213
+
214
+ ---
215
+
216
+ ## 5. Pickup list for next session
217
+
218
+ Prioritized by impact:
219
+
220
+ ### High value, small scope
221
+
222
+ 1. **§7 test coverage fills (3 tests).** Add to `test/storage/schemaConformance.test.ts`:
223
+ - Test A: third-party confirmed at chain tip → `unconfirmed` + spendable.
224
+ - Test B: third-party unconfirmed, broadcast fails → no DB row created.
225
+ - Test E: mixed broadcast results across services → positive accepted + `tx_audit` records discrepancy.
226
+ 2. **Fix `abortAction.test.ts` resource leak.** Likely a missing `knex.destroy()` in `beforeAll`/`afterAll`. Run individually first to confirm fix isolates.
227
+ 3. **Fix `findLegacy.test.ts` test 8 and `update.test.ts 7a`.** Either rewrite to use `transactions_legacy` or skip if test no longer applies post-cutover.
228
+
229
+ ### Medium value, medium scope
230
+
231
+ 4. **Monitor wiring expansion.** Currently only `TaskCheckForProofs` lease-gated and new-schema-aware. Other tasks (`TaskNewHeader`, `TaskPurge`, etc.) still bypass the new-schema service. Wrap each with `LeasedMonitorTask` and add `recordProof`/`transition` hooks where applicable.
232
+ 5. **Atomicity tightening (GAP 3 from compliance doc).** Wrap `transitionProcessing` + targeted `refreshOutputsSpendable(userId, txid)` in a Knex transaction at call sites where torn reads would matter (e.g. mid-processAction state change).
233
+ 6. **IDB-side new-schema service.** Currently `StorageIdb.getTransactionService()` returns `undefined`. Implement a parallel `TransactionServiceIdb` operating on the existing IDB stores so non-Knex deployments get full new-schema semantics.
234
+
235
+ ### Operator-driven, no code
236
+
237
+ 7. **Staging cutover dry-run.** Follow `docs/ROLLOUT_PLAN.md` week 2. Capture timing, verify smoke tests, document any rough edges.
238
+ 8. **Coinbase maturity backfill on legacy data.** Run `backfillCoinbaseMaturity` on staging to populate `matures_at_height` for legacy coinbase outputs. Tracks in `BackfillCoinbaseMaturityStats`.
239
+
240
+ ### Defer / out of scope
241
+
242
+ - **`StorageMySQLDojoReader.man.test.ts` + `adminStats.man.test.ts`** — manual tests requiring external infrastructure.
243
+ - **`createActionToGenerateBeefs.man.test.ts`** — needs live funded wallet.
244
+
245
+ ---
246
+
247
+ ## 6. Key commands
248
+
249
+ ```bash
250
+ cd /Users/personal/git/ts-stack/packages/wallet/wallet-toolbox
251
+
252
+ # Build
253
+ npm run build
254
+
255
+ # All new-schema + migrations (target green: 20 suites, 169 tests)
256
+ npx jest --testPathPatterns="schema|backfill|cutover|storage/KnexMigrations" --silent
257
+
258
+ # Specific schema conformance
259
+ npx jest --testPathPatterns="schemaConformance"
260
+
261
+ # Wired storage methods
262
+ npx jest --testPathPatterns="createAction|processAction|internalizeAction|attemptToPost|listActions|listOutputs" --silent
263
+
264
+ # Cutover dry-run on a populated test SQLite (see test/storage/schemaCutover.test.ts)
265
+ # Production: see docs/CUTOVER_RUNBOOK.md
266
+ ```
267
+
268
+ ---
269
+
270
+ ## 7. Architecture invariants to preserve
271
+
272
+ When making further changes:
273
+
274
+ - **The transaction service is the only sanctioned mutation path for `transactions`/`actions` post-cutover.** Direct `knex('transactions').insert(...)` writes break the FSM + audit contract. Use `TransactionService.create` / `transition` / `findOrCreate*`.
275
+ - **Every state change writes a `tx_audit` row** via `auditProcessingTransition` (called inside `transitionProcessing`). Don't bypass.
276
+ - **`runSchemaCutover` is one-way in production.** Keep `transactions_legacy` and friends for 30 days per runbook §5.
277
+ - **Reorg branch must never write `invalid` or `doubleSpend` directly.** FSM enforces this. Monitor's reorg handler should follow `confirmed → reorging → unconfirmed`, then handle invalidation via the standard path if independently detected.
278
+ - **`outputs.spendable` is a cached derivative.** Source of truth is the §4 rule. Always refresh after transition.
279
+ - **Coinbase outputs need both `is_coinbase = true` on the new-schema transaction AND `matures_at_height` populated on the output row.** Maturity maturity backfill is a one-off post-cutover operation.
280
+
281
+ ---
282
+
283
+ ## 8. Subagent prompt templates that worked
284
+
285
+ Use these as starting points for the pickup list:
286
+
287
+ - **Test gap fill** → `bopen-tools:tester` with: "Read `docs/REQUIREMENTS_COMPLIANCE.md` §7. Add Test [A/B/E] to `test/storage/schemaConformance.test.ts` using `setupCutDb` pattern. Assert spec-cited behavior. Run `npx jest --testPathPatterns="schemaConformance"`."
288
+ - **Storage wiring** → `bsv-blockchain-wallet-toolbox-expert` with method file path + service signatures + "Gate calls through `storage.getTransactionService()`. Pre-cutover/IDB returns `undefined`, fall back to legacy code. Add test in `test/storage/methods/<Method>Wiring.test.ts`."
289
+ - **Monitor task wiring** → `bsv-blockchain-wallet-toolbox-expert` with task file path + "Wrap body in `LeasedMonitorTask.run('<task-name>', this.instanceId, 60_000, async () => { /* body */ })`. Call appropriate transaction service method on state-change events."
290
+
291
+ Caveats from prior sessions:
292
+ - Don't dispatch two subagents that both touch `transactionService.ts` or `StorageKnex.ts` in parallel — merge conflicts. Serialize.
293
+ - The `bopen-tools:architecture-reviewer` agent refuses to write `.md` analysis files per its prompt; pass output back through main agent to persist.
294
+ - Test fixture changes ripple — `TestUtilsWalletStorage.ts:insertTestTransaction` is now new-schema-aware; preserve that path.
295
+
296
+ ---
297
+
298
+ **End of handoff document.** Resume work by reading §5 pickup list, then dispatch per §8 template.