@noy-db/hub 0.3.0-pre.11 → 0.3.0-pre.13
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/dist/aggregate/index.js +4 -4
- package/dist/api-ZGS6LCOF.js +20 -0
- package/dist/as/index.js +11 -11
- package/dist/attestation/index.js +18 -18
- package/dist/{backup-XA5STIYQ.js → backup-BJ57IKAO.js} +28 -11
- package/dist/backup-BJ57IKAO.js.map +1 -0
- package/dist/blobs/index.js +12 -10
- package/dist/blobs/index.js.map +1 -1
- package/dist/broker/index.js +12 -12
- package/dist/bundle/index.js +25 -22
- package/dist/bundle/index.js.map +1 -1
- package/dist/by/index.js +2 -2
- package/dist/cargo/index.js +22 -22
- package/dist/{chunk-WGV4CUZT.js → chunk-2NVOWNI3.js} +4 -4
- package/dist/{chunk-WGV4CUZT.js.map → chunk-2NVOWNI3.js.map} +1 -1
- package/dist/{chunk-OFJ5GPNA.js → chunk-3B5VVCNY.js} +2 -2
- package/dist/{chunk-KPGX66PM.js → chunk-3LQ2YKO4.js} +2 -2
- package/dist/{chunk-D26JB3LZ.js → chunk-3QCRBHCY.js} +2 -2
- package/dist/{chunk-H6CZSDWK.js → chunk-454JXE57.js} +3 -3
- package/dist/{chunk-H6CZSDWK.js.map → chunk-454JXE57.js.map} +1 -1
- package/dist/{chunk-DGH65E7Q.js → chunk-4CTHCN4J.js} +24 -10
- package/dist/chunk-4CTHCN4J.js.map +1 -0
- package/dist/{chunk-4N5QFSNQ.js → chunk-4JBYV75E.js} +5 -5
- package/dist/{chunk-UTLEAJXC.js → chunk-4NXKCLLQ.js} +2 -2
- package/dist/{chunk-ARSAMO24.js → chunk-4VNQOLML.js} +2 -2
- package/dist/{chunk-X6CMGUAG.js → chunk-5M5DVGV7.js} +2 -2
- package/dist/{chunk-DJ3VKYFA.js → chunk-5O3XF4DV.js} +4 -4
- package/dist/chunk-5O3XF4DV.js.map +1 -0
- package/dist/{chunk-XHV25KBM.js → chunk-5YOLBEQ6.js} +2 -2
- package/dist/{chunk-CB25ONKC.js → chunk-6CRIV7DE.js} +2 -2
- package/dist/{chunk-BE7N3AXA.js → chunk-6JTIAGHD.js} +3 -3
- package/dist/{chunk-JOQ53DMI.js → chunk-6QTNZJBS.js} +3 -3
- package/dist/{chunk-BZO4WCJI.js → chunk-6T2SCQRU.js} +4 -4
- package/dist/{chunk-FQQF23MC.js → chunk-7DSTRQIJ.js} +2 -2
- package/dist/{chunk-IP2QBAGS.js → chunk-AUSTCW2X.js} +10 -10
- package/dist/{chunk-A2Y6YFVN.js → chunk-B3HJYUOF.js} +2 -2
- package/dist/{chunk-SRVQHVNX.js → chunk-BDVFPG6Y.js} +5 -5
- package/dist/{chunk-FH542DDY.js → chunk-BIOUI4HL.js} +50 -1
- package/dist/chunk-BIOUI4HL.js.map +1 -0
- package/dist/{chunk-YXOUQ2H7.js → chunk-CAF6WOK7.js} +2 -2
- package/dist/{chunk-H6HM6CVR.js → chunk-CDUQTA3Z.js} +114 -12
- package/dist/chunk-CDUQTA3Z.js.map +1 -0
- package/dist/{chunk-HUS3J5WM.js → chunk-CIE2BASH.js} +2 -2
- package/dist/{chunk-DIRRS7WP.js → chunk-CRI4OUV4.js} +2 -2
- package/dist/{chunk-FXK4X4BL.js → chunk-DLG74CNB.js} +4 -4
- package/dist/{chunk-WTUNZACT.js → chunk-E5ZQT5KX.js} +2 -2
- package/dist/{chunk-DMFNPHCX.js → chunk-EQO2UVP4.js} +6 -6
- package/dist/{chunk-MCEKIAO4.js → chunk-ERJ7FU55.js} +3 -3
- package/dist/{chunk-6QILBDZU.js → chunk-EVVGJDRQ.js} +3 -3
- package/dist/{chunk-7VSGW5KJ.js → chunk-EVX47VBM.js} +2 -2
- package/dist/{chunk-D3EFFFOL.js → chunk-EXK7QRWF.js} +5 -5
- package/dist/{chunk-5JB73NMC.js → chunk-EYZ6IQ6X.js} +5 -5
- package/dist/{chunk-BCYQA5BK.js → chunk-F64IRYG3.js} +2 -2
- package/dist/{chunk-K62IUKOD.js → chunk-FHS2HQSH.js} +5 -5
- package/dist/{chunk-2JMMY7HZ.js → chunk-FM3G3NOY.js} +27 -9
- package/dist/chunk-FM3G3NOY.js.map +1 -0
- package/dist/{chunk-67TNU77I.js → chunk-FUG4SFN3.js} +2 -2
- package/dist/{chunk-ZP5PL65C.js → chunk-GKEWXIV5.js} +2 -2
- package/dist/{chunk-RKRGDAS7.js → chunk-GTGPO5KW.js} +5 -5
- package/dist/{chunk-MSPNM2OM.js → chunk-HB3RFQSC.js} +3 -3
- package/dist/{chunk-W5D62AQD.js → chunk-HDMEGAQE.js} +20 -7
- package/dist/chunk-HDMEGAQE.js.map +1 -0
- package/dist/chunk-HDQIIUPH.js +135 -0
- package/dist/chunk-HDQIIUPH.js.map +1 -0
- package/dist/{chunk-7QIXUSDQ.js → chunk-HTJQYHZP.js} +15 -12
- package/dist/chunk-HTJQYHZP.js.map +1 -0
- package/dist/{chunk-OOLO4LQG.js → chunk-I6GALP6E.js} +6 -6
- package/dist/{chunk-57V5S7PW.js → chunk-IL6POWCW.js} +6 -6
- package/dist/{chunk-7NS43EXZ.js → chunk-IU6SNYX6.js} +5 -5
- package/dist/{chunk-5ZOSG3RJ.js → chunk-J2ZX2XUV.js} +5 -5
- package/dist/{chunk-L2SNBIV7.js → chunk-JIF24JPM.js} +57 -15
- package/dist/chunk-JIF24JPM.js.map +1 -0
- package/dist/{chunk-SYMS4546.js → chunk-JKJOGPZN.js} +2 -2
- package/dist/{chunk-CKZW6P5V.js → chunk-JNAI2HN2.js} +1 -1
- package/dist/chunk-JNAI2HN2.js.map +1 -0
- package/dist/{chunk-AWB5JZW6.js → chunk-JZUV47FZ.js} +2 -2
- package/dist/{chunk-ODJWBC5I.js → chunk-K5IMOGHB.js} +2 -2
- package/dist/{chunk-3G4KMVUN.js → chunk-KSKBRKGJ.js} +3 -3
- package/dist/{chunk-HFJIGWJC.js → chunk-LASZKVMO.js} +3 -3
- package/dist/{chunk-IGJHJYM6.js → chunk-LXEXBTKL.js} +4 -4
- package/dist/{chunk-3CNQ7FQ3.js → chunk-M4CV6BRT.js} +119 -25
- package/dist/chunk-M4CV6BRT.js.map +1 -0
- package/dist/{chunk-H44ZE4IE.js → chunk-MEFJPTZ4.js} +33 -17
- package/dist/chunk-MEFJPTZ4.js.map +1 -0
- package/dist/{chunk-PR5LC5YX.js → chunk-MV43JSJF.js} +4 -4
- package/dist/{chunk-ELNBMFOS.js → chunk-NJ4EOKMB.js} +4 -4
- package/dist/{chunk-PXWVF7MC.js → chunk-NR5LT5RY.js} +7 -7
- package/dist/{chunk-QYPKGVT4.js → chunk-NWSGI5C7.js} +3 -3
- package/dist/{chunk-P5RY4ZWD.js → chunk-OSDB5WW3.js} +92 -15
- package/dist/chunk-OSDB5WW3.js.map +1 -0
- package/dist/chunk-PN2XMATY.js +37 -0
- package/dist/chunk-PN2XMATY.js.map +1 -0
- package/dist/{chunk-25NDNMQ7.js → chunk-Q5VNKNE5.js} +3 -3
- package/dist/{chunk-CIKY6I4W.js → chunk-QLWMEXCT.js} +2 -2
- package/dist/{chunk-VA4ZWLFY.js → chunk-QRB7NAOJ.js} +2 -2
- package/dist/{chunk-3MSQLQNZ.js → chunk-R4ROFEYC.js} +2 -2
- package/dist/{chunk-BEIRE5K4.js → chunk-RCVJZMFE.js} +4 -4
- package/dist/{chunk-VR24ILCR.js → chunk-RIX4V2TB.js} +3 -3
- package/dist/{chunk-Q3XSMOZM.js → chunk-RYCTDFUX.js} +2 -2
- package/dist/{chunk-7E67FJ33.js → chunk-RZ5SVOYR.js} +2 -2
- package/dist/{chunk-IDIV5NVH.js → chunk-SLFHQTTW.js} +5 -5
- package/dist/chunk-SNZ6URZZ.js +2782 -0
- package/dist/chunk-SNZ6URZZ.js.map +1 -0
- package/dist/{chunk-C3YH34IL.js → chunk-T2FFWNPK.js} +3 -3
- package/dist/{chunk-O2DYPAZY.js → chunk-UNFPPVNI.js} +2 -2
- package/dist/{chunk-MELR46EF.js → chunk-VFUPHI2Z.js} +63 -10
- package/dist/chunk-VFUPHI2Z.js.map +1 -0
- package/dist/{chunk-GA2QHD6P.js → chunk-VLFCJYTL.js} +9 -9
- package/dist/{chunk-YSXEFGND.js → chunk-VN3DBQAU.js} +2 -2
- package/dist/{chunk-C7NTK5I3.js → chunk-VZRODIM3.js} +4 -4
- package/dist/{chunk-QLLKLFE2.js → chunk-W22IKJE2.js} +2 -2
- package/dist/{chunk-5XIPOCQC.js → chunk-X3YYQWOQ.js} +3 -3
- package/dist/{chunk-A2QF4JUE.js → chunk-X7QBD67R.js} +625 -293
- package/dist/chunk-X7QBD67R.js.map +1 -0
- package/dist/{chunk-QQJXBZCO.js → chunk-XDYREZWE.js} +82 -10
- package/dist/chunk-XDYREZWE.js.map +1 -0
- package/dist/{chunk-OEAATWH5.js → chunk-XWZVFISC.js} +40 -6
- package/dist/{chunk-OEAATWH5.js.map → chunk-XWZVFISC.js.map} +1 -1
- package/dist/{chunk-XFXUTFWQ.js → chunk-YFXZEAYK.js} +6 -6
- package/dist/{chunk-7ITPJFGC.js → chunk-ZAJAVEXY.js} +2 -2
- package/dist/{chunk-4R4Q64W5.js → chunk-ZICD77GM.js} +2 -2
- package/dist/{chunk-45ZZLTFH.js → chunk-ZJ2AK4V7.js} +2 -2
- package/dist/{chunk-UFILRICG.js → chunk-ZUODRVHY.js} +2 -2
- package/dist/classified/index.js +5 -5
- package/dist/{classified-marker-LQWWQNIJ.js → classified-marker-CZKA6ITE.js} +8 -4
- package/dist/classified-marker-CZKA6ITE.js.map +1 -0
- package/dist/collection-facade-TLWIPI76.js +44 -0
- package/dist/{computed-W6MVAMWZ.js → computed-ZIQTYTDI.js} +3 -3
- package/dist/consent/index.js +9 -9
- package/dist/{dead-filter-4KXZEB3X.js → dead-filter-ESOBZZP5.js} +2 -2
- package/dist/delegation-W7ZV2322.js +25 -0
- package/dist/derivations/index.js +12 -12
- package/dist/derive-H2BJTLUI.js +21 -0
- package/dist/{enclave-VXAQD4XJ.js → enclave-AP3I5W7O.js} +15 -9
- package/dist/executor-KGWTNEQD.js +9 -0
- package/dist/executor-OVEXR6RT.js +9 -0
- package/dist/executor-UNEH5ZYH.js +25 -0
- package/dist/export-accessible-PCMXSUZS.js +23 -0
- package/dist/extract-partition-SWHFSYJO.js +38 -0
- package/dist/{fanout-sidecar-CKYFH33E.js → fanout-sidecar-A765THMX.js} +9 -9
- package/dist/find-N6345CNT.js +11 -0
- package/dist/forget/index.js +9 -9
- package/dist/guards/index.js +3 -3
- package/dist/history/index.js +14 -11
- package/dist/history/index.js.map +1 -1
- package/dist/i18n/index.js +14 -14
- package/dist/index.d.ts +5 -1
- package/dist/index.js +108 -89
- package/dist/index.js.map +1 -1
- package/dist/indexing/index.js +5 -5
- package/dist/indexing/index.js.map +1 -1
- package/dist/issue-5OKB6I2R.js +19 -0
- package/dist/kernel/best-effort-revert.d.ts +52 -0
- package/dist/kernel/collection-config.d.ts +28 -0
- package/dist/kernel/collection.d.ts +49 -32
- package/dist/kernel/enclave/classify/verify.d.ts +3 -0
- package/dist/kernel/enclave/index.d.ts +2 -1
- package/dist/kernel/enclave/record-keys/deterministic.d.ts +1 -0
- package/dist/kernel/enclave/record-keys/lifecycle.d.ts +50 -0
- package/dist/kernel/enclave/record-keys/record-codec.d.ts +27 -0
- package/dist/kernel/errors.d.ts +75 -1
- package/dist/kernel/lazy-count.d.ts +13 -0
- package/dist/kernel/noydb.d.ts +8 -0
- package/dist/kernel/tier-visibility.d.ts +54 -0
- package/dist/kernel/types.d.ts +92 -0
- package/dist/kernel/vault.d.ts +23 -6
- package/dist/kernel/via/dispatch.d.ts +10 -0
- package/dist/kernel/via/graph.d.ts +2 -1
- package/dist/{ledger-FU6GH5EH.js → ledger-GFBKVPV4.js} +11 -11
- package/dist/legacy/bundle.d.ts +1 -1
- package/dist/liberate-3VDOT4KO.js +24 -0
- package/dist/{link-set-MNADSH5M.js → link-set-Z7Q2ASFX.js} +11 -11
- package/dist/materialized-views/index.js +18 -18
- package/dist/noydb-ZCJOYBDI.js +68 -0
- package/dist/on/index.js +9 -9
- package/dist/overlay-views/index.js +4 -4
- package/dist/periods/index.js +12 -12
- package/dist/pod/index.js +11 -11
- package/dist/{policy-JTFOPPUU.js → policy-Z3RUAIY2.js} +5 -5
- package/dist/port/with/blob-strategy.d.ts +17 -0
- package/dist/port/with/lookup-strategy.d.ts +2 -1
- package/dist/portability/index.js +8 -8
- package/dist/{post-register-HAWO3O7O.js → post-register-JTH76BLY.js} +12 -7
- package/dist/post-register-JTH76BLY.js.map +1 -0
- package/dist/{public-envelope-NJVB7LPA.js → public-envelope-B4KNWVUA.js} +4 -4
- package/dist/query/index.js +5 -5
- package/dist/register-VAHONCID.js +23 -0
- package/dist/registry-7MLVD3VO.js +19 -0
- package/dist/registry-EPKPD5SM.js +18 -0
- package/dist/registry-P5T7PS2U.js +9 -0
- package/dist/request-withdrawal-TI3A5WPS.js +31 -0
- package/dist/{reveal-BOY7XYFH.js → reveal-DIBHLUZX.js} +7 -7
- package/dist/reveal-DIBHLUZX.js.map +1 -0
- package/dist/revoke-FDRD6GRW.js +24 -0
- package/dist/satellites/index.js +1 -1
- package/dist/sealed-record/index.js +12 -12
- package/dist/{seed-4RRXT42N.js → seed-Q6M2IZFL.js} +11 -11
- package/dist/session/index.js +9 -9
- package/dist/shadow/index.js +2 -2
- package/dist/signer-MUWEIUI6.js +25 -0
- package/dist/snapshots/index.js +10 -10
- package/dist/stale-OSQ7J3AA.js +29 -0
- package/dist/storage-MVFCGEQE.js +23 -0
- package/dist/{store-coordination-provider-HPYVFJCV.js → store-coordination-provider-64OEZFGS.js} +3 -3
- package/dist/sync/index.js +9 -9
- package/dist/team/index.js +15 -15
- package/dist/tiers/index.js +14 -10
- package/dist/to/index.js +1 -1
- package/dist/tx/index.js +3 -3
- package/dist/util/index.js +1 -1
- package/dist/{verify-66RHOW7N.js → verify-ZASTRNPR.js} +9 -8
- package/dist/verify-ZASTRNPR.js.map +1 -0
- package/dist/via/lookup/registry.d.ts +9 -0
- package/dist/via/money/where.d.ts +27 -6
- package/dist/{walk-2RWEOCAS.js → walk-SVNDIZ62.js} +11 -11
- package/dist/with/index.js +11 -11
- package/dist/with-audit/forget/strategy.d.ts +22 -0
- package/dist/with-audit/tiers/index.d.ts +275 -3
- package/dist/with-audit/tiers/strategy.d.ts +5 -4
- package/dist/with-cargo/describe-extraction.d.ts +9 -1
- package/dist/with-cargo/extract-partition.d.ts +9 -1
- package/dist/with-cargo/walk-closure.d.ts +32 -3
- package/dist/with-commit/history/history.d.ts +46 -0
- package/dist/with-commit/history/ledger/store.d.ts +21 -0
- package/dist/with-commit/history/strategy.d.ts +10 -0
- package/dist/with-commit/history/time-machine.d.ts +23 -0
- package/dist/with-commit/tx/elevated-handle.d.ts +2 -1
- package/dist/with-commit/tx/transaction.d.ts +5 -0
- package/dist/with-formula/materialized-views/executor.d.ts +9 -0
- package/dist/with-formula/materialized-views/stale.d.ts +52 -1
- package/dist/with-lookup/embeddings/index.d.ts +1 -0
- package/dist/with-lookup/embeddings/vec-id.d.ts +47 -0
- package/dist/with-lookup/indexing/collection-facade.d.ts +38 -1
- package/dist/with-lookup/indexing/lazy-builder.d.ts +35 -2
- package/dist/with-lookup/indexing/persisted-indexes.d.ts +44 -1
- package/dist/with-lookup/search/collection-facade.d.ts +40 -0
- package/dist/with-lookup/search/persisted-index-store.d.ts +82 -2
- package/dist/with-lookup/search/strategy.d.ts +4 -0
- package/dist/with-party/team/sync.d.ts +9 -0
- package/dist/with-shape/blobs/blob-intent.d.ts +153 -0
- package/dist/with-shape/blobs/blob-set.d.ts +949 -5
- package/dist/with-shape/satellites/fanout.d.ts +5 -4
- package/dist/with-shape/satellites/migrate-cek.d.ts +26 -0
- package/dist/with-shape/satellites/types.d.ts +11 -0
- package/dist/withdraw-accessible-WZIEVWSR.js +28 -0
- package/package.json +3 -3
- package/dist/api-YGMINAET.js +0 -20
- package/dist/backup-XA5STIYQ.js.map +0 -1
- package/dist/chunk-2JMMY7HZ.js.map +0 -1
- package/dist/chunk-3CNQ7FQ3.js.map +0 -1
- package/dist/chunk-7QIXUSDQ.js.map +0 -1
- package/dist/chunk-A2QF4JUE.js.map +0 -1
- package/dist/chunk-AOVDSIL3.js +0 -1221
- package/dist/chunk-AOVDSIL3.js.map +0 -1
- package/dist/chunk-CKZW6P5V.js.map +0 -1
- package/dist/chunk-DGH65E7Q.js.map +0 -1
- package/dist/chunk-DJ3VKYFA.js.map +0 -1
- package/dist/chunk-FH542DDY.js.map +0 -1
- package/dist/chunk-H44ZE4IE.js.map +0 -1
- package/dist/chunk-H6HM6CVR.js.map +0 -1
- package/dist/chunk-L2SNBIV7.js.map +0 -1
- package/dist/chunk-MELR46EF.js.map +0 -1
- package/dist/chunk-P5RY4ZWD.js.map +0 -1
- package/dist/chunk-QQJXBZCO.js.map +0 -1
- package/dist/chunk-TPH5EO6L.js +0 -54
- package/dist/chunk-TPH5EO6L.js.map +0 -1
- package/dist/chunk-W5D62AQD.js.map +0 -1
- package/dist/classified-marker-LQWWQNIJ.js.map +0 -1
- package/dist/collection-facade-YE2O4J4O.js +0 -39
- package/dist/delegation-OPUU3R2E.js +0 -25
- package/dist/derive-BGUHU663.js +0 -21
- package/dist/executor-GTVSUUBX.js +0 -25
- package/dist/executor-GZWMTOXB.js +0 -9
- package/dist/executor-XXGS4S3K.js +0 -9
- package/dist/export-accessible-BMULIOYB.js +0 -23
- package/dist/extract-partition-JUQTWDXR.js +0 -36
- package/dist/find-XRGCNGNN.js +0 -11
- package/dist/issue-UB6AA5M6.js +0 -19
- package/dist/liberate-YUN7W5QG.js +0 -24
- package/dist/noydb-6JLBZU4U.js +0 -67
- package/dist/post-register-HAWO3O7O.js.map +0 -1
- package/dist/register-VCKOBWKT.js +0 -23
- package/dist/registry-72UKJ2L4.js +0 -9
- package/dist/registry-BZFLJNEH.js +0 -18
- package/dist/registry-YJEYSYI5.js +0 -19
- package/dist/request-withdrawal-6MJRMFHF.js +0 -31
- package/dist/reveal-BOY7XYFH.js.map +0 -1
- package/dist/revoke-4KUNSVJC.js +0 -24
- package/dist/signer-DDDXP5JD.js +0 -25
- package/dist/stale-NXPT56JA.js +0 -14
- package/dist/storage-IR6EEAV2.js +0 -23
- package/dist/verify-66RHOW7N.js.map +0 -1
- package/dist/withdraw-accessible-CLMZEHQT.js +0 -28
- /package/dist/{api-YGMINAET.js.map → api-ZGS6LCOF.js.map} +0 -0
- /package/dist/{chunk-OFJ5GPNA.js.map → chunk-3B5VVCNY.js.map} +0 -0
- /package/dist/{chunk-KPGX66PM.js.map → chunk-3LQ2YKO4.js.map} +0 -0
- /package/dist/{chunk-D26JB3LZ.js.map → chunk-3QCRBHCY.js.map} +0 -0
- /package/dist/{chunk-4N5QFSNQ.js.map → chunk-4JBYV75E.js.map} +0 -0
- /package/dist/{chunk-UTLEAJXC.js.map → chunk-4NXKCLLQ.js.map} +0 -0
- /package/dist/{chunk-ARSAMO24.js.map → chunk-4VNQOLML.js.map} +0 -0
- /package/dist/{chunk-X6CMGUAG.js.map → chunk-5M5DVGV7.js.map} +0 -0
- /package/dist/{chunk-XHV25KBM.js.map → chunk-5YOLBEQ6.js.map} +0 -0
- /package/dist/{chunk-CB25ONKC.js.map → chunk-6CRIV7DE.js.map} +0 -0
- /package/dist/{chunk-BE7N3AXA.js.map → chunk-6JTIAGHD.js.map} +0 -0
- /package/dist/{chunk-JOQ53DMI.js.map → chunk-6QTNZJBS.js.map} +0 -0
- /package/dist/{chunk-BZO4WCJI.js.map → chunk-6T2SCQRU.js.map} +0 -0
- /package/dist/{chunk-FQQF23MC.js.map → chunk-7DSTRQIJ.js.map} +0 -0
- /package/dist/{chunk-IP2QBAGS.js.map → chunk-AUSTCW2X.js.map} +0 -0
- /package/dist/{chunk-A2Y6YFVN.js.map → chunk-B3HJYUOF.js.map} +0 -0
- /package/dist/{chunk-SRVQHVNX.js.map → chunk-BDVFPG6Y.js.map} +0 -0
- /package/dist/{chunk-YXOUQ2H7.js.map → chunk-CAF6WOK7.js.map} +0 -0
- /package/dist/{chunk-HUS3J5WM.js.map → chunk-CIE2BASH.js.map} +0 -0
- /package/dist/{chunk-DIRRS7WP.js.map → chunk-CRI4OUV4.js.map} +0 -0
- /package/dist/{chunk-FXK4X4BL.js.map → chunk-DLG74CNB.js.map} +0 -0
- /package/dist/{chunk-WTUNZACT.js.map → chunk-E5ZQT5KX.js.map} +0 -0
- /package/dist/{chunk-DMFNPHCX.js.map → chunk-EQO2UVP4.js.map} +0 -0
- /package/dist/{chunk-MCEKIAO4.js.map → chunk-ERJ7FU55.js.map} +0 -0
- /package/dist/{chunk-6QILBDZU.js.map → chunk-EVVGJDRQ.js.map} +0 -0
- /package/dist/{chunk-7VSGW5KJ.js.map → chunk-EVX47VBM.js.map} +0 -0
- /package/dist/{chunk-D3EFFFOL.js.map → chunk-EXK7QRWF.js.map} +0 -0
- /package/dist/{chunk-5JB73NMC.js.map → chunk-EYZ6IQ6X.js.map} +0 -0
- /package/dist/{chunk-BCYQA5BK.js.map → chunk-F64IRYG3.js.map} +0 -0
- /package/dist/{chunk-K62IUKOD.js.map → chunk-FHS2HQSH.js.map} +0 -0
- /package/dist/{chunk-67TNU77I.js.map → chunk-FUG4SFN3.js.map} +0 -0
- /package/dist/{chunk-ZP5PL65C.js.map → chunk-GKEWXIV5.js.map} +0 -0
- /package/dist/{chunk-RKRGDAS7.js.map → chunk-GTGPO5KW.js.map} +0 -0
- /package/dist/{chunk-MSPNM2OM.js.map → chunk-HB3RFQSC.js.map} +0 -0
- /package/dist/{chunk-OOLO4LQG.js.map → chunk-I6GALP6E.js.map} +0 -0
- /package/dist/{chunk-57V5S7PW.js.map → chunk-IL6POWCW.js.map} +0 -0
- /package/dist/{chunk-7NS43EXZ.js.map → chunk-IU6SNYX6.js.map} +0 -0
- /package/dist/{chunk-5ZOSG3RJ.js.map → chunk-J2ZX2XUV.js.map} +0 -0
- /package/dist/{chunk-SYMS4546.js.map → chunk-JKJOGPZN.js.map} +0 -0
- /package/dist/{chunk-AWB5JZW6.js.map → chunk-JZUV47FZ.js.map} +0 -0
- /package/dist/{chunk-ODJWBC5I.js.map → chunk-K5IMOGHB.js.map} +0 -0
- /package/dist/{chunk-3G4KMVUN.js.map → chunk-KSKBRKGJ.js.map} +0 -0
- /package/dist/{chunk-HFJIGWJC.js.map → chunk-LASZKVMO.js.map} +0 -0
- /package/dist/{chunk-IGJHJYM6.js.map → chunk-LXEXBTKL.js.map} +0 -0
- /package/dist/{chunk-PR5LC5YX.js.map → chunk-MV43JSJF.js.map} +0 -0
- /package/dist/{chunk-ELNBMFOS.js.map → chunk-NJ4EOKMB.js.map} +0 -0
- /package/dist/{chunk-PXWVF7MC.js.map → chunk-NR5LT5RY.js.map} +0 -0
- /package/dist/{chunk-QYPKGVT4.js.map → chunk-NWSGI5C7.js.map} +0 -0
- /package/dist/{chunk-25NDNMQ7.js.map → chunk-Q5VNKNE5.js.map} +0 -0
- /package/dist/{chunk-CIKY6I4W.js.map → chunk-QLWMEXCT.js.map} +0 -0
- /package/dist/{chunk-VA4ZWLFY.js.map → chunk-QRB7NAOJ.js.map} +0 -0
- /package/dist/{chunk-3MSQLQNZ.js.map → chunk-R4ROFEYC.js.map} +0 -0
- /package/dist/{chunk-BEIRE5K4.js.map → chunk-RCVJZMFE.js.map} +0 -0
- /package/dist/{chunk-VR24ILCR.js.map → chunk-RIX4V2TB.js.map} +0 -0
- /package/dist/{chunk-Q3XSMOZM.js.map → chunk-RYCTDFUX.js.map} +0 -0
- /package/dist/{chunk-7E67FJ33.js.map → chunk-RZ5SVOYR.js.map} +0 -0
- /package/dist/{chunk-IDIV5NVH.js.map → chunk-SLFHQTTW.js.map} +0 -0
- /package/dist/{chunk-C3YH34IL.js.map → chunk-T2FFWNPK.js.map} +0 -0
- /package/dist/{chunk-O2DYPAZY.js.map → chunk-UNFPPVNI.js.map} +0 -0
- /package/dist/{chunk-GA2QHD6P.js.map → chunk-VLFCJYTL.js.map} +0 -0
- /package/dist/{chunk-YSXEFGND.js.map → chunk-VN3DBQAU.js.map} +0 -0
- /package/dist/{chunk-C7NTK5I3.js.map → chunk-VZRODIM3.js.map} +0 -0
- /package/dist/{chunk-QLLKLFE2.js.map → chunk-W22IKJE2.js.map} +0 -0
- /package/dist/{chunk-5XIPOCQC.js.map → chunk-X3YYQWOQ.js.map} +0 -0
- /package/dist/{chunk-XFXUTFWQ.js.map → chunk-YFXZEAYK.js.map} +0 -0
- /package/dist/{chunk-7ITPJFGC.js.map → chunk-ZAJAVEXY.js.map} +0 -0
- /package/dist/{chunk-4R4Q64W5.js.map → chunk-ZICD77GM.js.map} +0 -0
- /package/dist/{chunk-45ZZLTFH.js.map → chunk-ZJ2AK4V7.js.map} +0 -0
- /package/dist/{chunk-UFILRICG.js.map → chunk-ZUODRVHY.js.map} +0 -0
- /package/dist/{collection-facade-YE2O4J4O.js.map → collection-facade-TLWIPI76.js.map} +0 -0
- /package/dist/{computed-W6MVAMWZ.js.map → computed-ZIQTYTDI.js.map} +0 -0
- /package/dist/{dead-filter-4KXZEB3X.js.map → dead-filter-ESOBZZP5.js.map} +0 -0
- /package/dist/{delegation-OPUU3R2E.js.map → delegation-W7ZV2322.js.map} +0 -0
- /package/dist/{derive-BGUHU663.js.map → derive-H2BJTLUI.js.map} +0 -0
- /package/dist/{enclave-VXAQD4XJ.js.map → enclave-AP3I5W7O.js.map} +0 -0
- /package/dist/{executor-GTVSUUBX.js.map → executor-KGWTNEQD.js.map} +0 -0
- /package/dist/{executor-GZWMTOXB.js.map → executor-OVEXR6RT.js.map} +0 -0
- /package/dist/{executor-XXGS4S3K.js.map → executor-UNEH5ZYH.js.map} +0 -0
- /package/dist/{export-accessible-BMULIOYB.js.map → export-accessible-PCMXSUZS.js.map} +0 -0
- /package/dist/{extract-partition-JUQTWDXR.js.map → extract-partition-SWHFSYJO.js.map} +0 -0
- /package/dist/{fanout-sidecar-CKYFH33E.js.map → fanout-sidecar-A765THMX.js.map} +0 -0
- /package/dist/{find-XRGCNGNN.js.map → find-N6345CNT.js.map} +0 -0
- /package/dist/{issue-UB6AA5M6.js.map → issue-5OKB6I2R.js.map} +0 -0
- /package/dist/{ledger-FU6GH5EH.js.map → ledger-GFBKVPV4.js.map} +0 -0
- /package/dist/{liberate-YUN7W5QG.js.map → liberate-3VDOT4KO.js.map} +0 -0
- /package/dist/{link-set-MNADSH5M.js.map → link-set-Z7Q2ASFX.js.map} +0 -0
- /package/dist/{noydb-6JLBZU4U.js.map → noydb-ZCJOYBDI.js.map} +0 -0
- /package/dist/{policy-JTFOPPUU.js.map → policy-Z3RUAIY2.js.map} +0 -0
- /package/dist/{public-envelope-NJVB7LPA.js.map → public-envelope-B4KNWVUA.js.map} +0 -0
- /package/dist/{register-VCKOBWKT.js.map → register-VAHONCID.js.map} +0 -0
- /package/dist/{registry-72UKJ2L4.js.map → registry-7MLVD3VO.js.map} +0 -0
- /package/dist/{registry-BZFLJNEH.js.map → registry-EPKPD5SM.js.map} +0 -0
- /package/dist/{registry-YJEYSYI5.js.map → registry-P5T7PS2U.js.map} +0 -0
- /package/dist/{request-withdrawal-6MJRMFHF.js.map → request-withdrawal-TI3A5WPS.js.map} +0 -0
- /package/dist/{revoke-4KUNSVJC.js.map → revoke-FDRD6GRW.js.map} +0 -0
- /package/dist/{seed-4RRXT42N.js.map → seed-Q6M2IZFL.js.map} +0 -0
- /package/dist/{signer-DDDXP5JD.js.map → signer-MUWEIUI6.js.map} +0 -0
- /package/dist/{stale-NXPT56JA.js.map → stale-OSQ7J3AA.js.map} +0 -0
- /package/dist/{storage-IR6EEAV2.js.map → storage-MVFCGEQE.js.map} +0 -0
- /package/dist/{store-coordination-provider-HPYVFJCV.js.map → store-coordination-provider-64OEZFGS.js.map} +0 -0
- /package/dist/{walk-2RWEOCAS.js.map → walk-SVNDIZ62.js.map} +0 -0
- /package/dist/{withdraw-accessible-CLMZEHQT.js.map → withdraw-accessible-WZIEVWSR.js.map} +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/with-cargo/walk-closure.ts","../src/with-cargo/extract-partition.ts"],"sourcesContent":["/**\n * Transitive-closure FK walker. Computes the set of\n * (collection, id) tuples reachable from seed predicates, so a\n * partition extraction ships a referentially-complete subset.\n *\n * Two-phase, plaintext, read-only (runs inside the unlocked vault\n * session — see foundation §13.4 / spec invariant 7):\n * 1. INBOUND expansion: from selected records, pull every record\n * that references them (children travel with parents), to a\n * fixed point.\n * 2. OUTBOUND completion: pull every parent the selected set\n * references (no dangling FKs), transitively, WITHOUT\n * re-expanding inbound from those parents (bounds the closure).\n *\n * The FK graph is auto-derived from the vault's existing RefRegistry\n * (the `ref('target')` declarations on collections) — no hand-written\n * edge list.\n *\n * @module\n */\nimport type { Vault } from '../kernel/vault.js'\nimport { PartitionExtractionError } from '../kernel/errors.js'\n\n/** Seed predicate per collection. Records that return true become roots. */\nexport interface WalkClosureOptions {\n readonly seeds: Record<\n string,\n (record: Record<string, unknown>) => boolean | Promise<boolean>\n >\n /** Max fixed-point iterations before throwing. Default 16. */\n readonly maxDepth?: number\n}\n\nexport interface ClosureResult {\n /** collection → set of record ids that travel together. */\n readonly closure: Map<string, Set<string>>\n readonly graph: {\n /** Fixed-point iterations the walk needed to converge. */\n readonly depth: number\n /** True if an edge pointed back to an already-selected node. */\n readonly cyclesDetected: boolean\n }\n}\n\nexport async function walkClosure(\n vault: Vault,\n opts: WalkClosureOptions,\n): Promise<ClosureResult> {\n const closure = new Map<string, Set<string>>()\n\n // Records carry a string `id` by construction (Collection.put(id: string)).\n // A non-string id during the walk means a malformed record — fail loud\n // rather than silently dropping it from the closure (which would leave a\n // dangling FK or a missing child in the extracted bundle).\n const requireStringId = (collection: string, record: Record<string, unknown>): string => {\n const id = record['id']\n if (typeof id !== 'string') {\n throw new PartitionExtractionError(\n `walkClosure: record in collection \"${collection}\" has a non-string ` +\n `id (${typeof id}); cannot include it in the partition closure.`,\n )\n }\n return id\n }\n\n const add = (collection: string, id: string): boolean => {\n let set = closure.get(collection)\n if (!set) {\n set = new Set<string>()\n closure.set(collection, set)\n }\n if (set.has(id)) return false\n set.add(id)\n return true\n }\n\n // Phase 0: evaluate seed predicates.\n for (const [collectionName, predicate] of Object.entries(opts.seeds)) {\n const coll = vault.collection<Record<string, unknown>>(collectionName)\n const records = await coll.list()\n for (const record of records) {\n if (await predicate(record)) {\n add(collectionName, requireStringId(collectionName, record))\n }\n }\n }\n\n const { refRegistry } = vault._introspectState()\n const maxDepth = opts.maxDepth ?? 16\n let cyclesDetected = false\n\n // `depth` counts PRODUCTIVE expansion generations (rounds that added at\n // least one new record), taken as the max over the two phases — i.e. the\n // FK hop-distance the closure needed, not the raw loop-iteration count.\n // The terminal draining pass that adds nothing does not count.\n let inboundDepth = 0\n let outboundDepth = 0\n\n // Phase 1 — INBOUND expansion. Worklist of newly-added (collection,id)\n // whose children we still need to pull.\n let frontier: Array<[string, string]> = []\n for (const [c, ids] of closure) for (const id of ids) frontier.push([c, id])\n\n while (frontier.length > 0) {\n const next: Array<[string, string]> = []\n for (const [collectionName, id] of frontier) {\n // Which collections reference THIS collection, and via which field?\n for (const inbound of refRegistry.getInbound(collectionName)) {\n const childColl = vault.collection<Record<string, unknown>>(inbound.collection)\n // TODO(perf): re-scans the full inbound collection on every frontier\n // element. O(frontier · inboundCollections · records) per depth. Fine\n // at consumer-firm scale (foundation §13.4); revisit with an index or\n // pagination if extraction over very large vaults gets slow.\n const childRecords = await childColl.list()\n for (const child of childRecords) {\n const fk = child[inbound.field]\n // Only scalar FK values can match an id; skip null/objects\n // (mirrors checkIntegrity's scalar guard, vault.ts).\n if (typeof fk !== 'string' && typeof fk !== 'number') continue\n if (String(fk) !== id) continue\n const childId = requireStringId(inbound.collection, child)\n if (add(inbound.collection, childId)) {\n next.push([inbound.collection, childId])\n } else {\n cyclesDetected = true\n }\n }\n }\n }\n if (next.length > 0 && ++inboundDepth > maxDepth) {\n throw new PartitionExtractionError(\n `walkClosure exceeded maxDepth=${maxDepth}; the FK graph may be ` +\n `unexpectedly deep or cyclic. Raise maxDepth or narrow the seeds.`,\n )\n }\n frontier = next\n }\n\n // Phase 2 — OUTBOUND completion. Pull referenced parents so no FK\n // dangles. Transitive over outbound edges only; parents are NOT\n // inbound-expanded (that would drag in unrelated siblings).\n let outboundFrontier: Array<[string, string]> = []\n for (const [c, ids] of closure) for (const id of ids) outboundFrontier.push([c, id])\n\n while (outboundFrontier.length > 0) {\n const next: Array<[string, string]> = []\n for (const [collectionName, id] of outboundFrontier) {\n const outbound = refRegistry.getOutbound(collectionName)\n if (Object.keys(outbound).length === 0) continue\n const coll = vault.collection<Record<string, unknown>>(collectionName)\n const record = await coll.get(id)\n if (!record) continue\n for (const [field, descriptor] of Object.entries(outbound)) {\n const rawId = record[field]\n // Only scalar FK values reference a parent id; skip null/objects.\n if (typeof rawId !== 'string' && typeof rawId !== 'number') continue\n const parentId = String(rawId)\n // Reaching an already-selected parent here is normal DAG\n // convergence (a child referencing its in-scope parent), not a\n // cycle — so do NOT flag cyclesDetected in the outbound phase.\n if (add(descriptor.target, parentId)) {\n next.push([descriptor.target, parentId])\n }\n }\n }\n if (next.length > 0 && ++outboundDepth > maxDepth) {\n throw new PartitionExtractionError(\n `walkClosure exceeded maxDepth=${maxDepth} during outbound completion.`,\n )\n }\n outboundFrontier = next\n }\n\n const depth = Math.max(inboundDepth, outboundDepth)\n\n return { closure, graph: { depth, cyclesDetected } }\n}\n","/**\n * Partition extraction. Walks the FK closure, re-encrypts\n * the selected records under fresh per-collection DEKs, seals those DEKs\n * under a one-time transfer key, and serializes an unowned\n * `extracted-partition` bundle.\n *\n * @module\n */\nimport type { Vault } from '../kernel/vault.js'\nimport type { EncryptedEnvelope, BlobObject, SlotRecord, VersionRecord } from '../kernel/types.js'\nimport { NOYDB_BACKUP_VERSION } from '../kernel/types.js'\nimport {\n decrypt,\n encrypt,\n openEnvelopeJson,\n generateDEK,\n bufferToBase64,\n encryptBytesWithAAD,\n decryptBytesWithAAD,\n unwrapCek,\n wrapCek,\n type EnclaveKey,\n} from '../kernel/enclave/index.js'\nimport {\n BLOB_COLLECTION,\n BLOB_INDEX_COLLECTION,\n BLOB_CHUNKS_COLLECTION,\n BLOB_SLOTS_PREFIX,\n BLOB_VERSIONS_PREFIX,\n} from '../with-shape/blobs/blob-set.js'\nimport { PartitionExtractionError } from '../kernel/errors.js'\nimport { walkClosure, type WalkClosureOptions } from './walk-closure.js'\nimport { generateULID } from '../with-pod/ulid.js'\nimport { SCHEMAS_COLLECTION } from '../with-shape/persisted-schemas/storage.js'\nimport { NOYDB_FORMAT_VERSION } from '../kernel/types.js'\nimport { LEDGER_COLLECTION } from '../with-commit/history/ledger/constants.js'\nimport { canonicalJson, hashEntry } from '../with-commit/history/ledger/entry.js'\nimport type { LedgerEntry } from '../with-commit/history/ledger/entry.js'\nimport { envelopePayloadHash } from '../with-commit/history/ledger/hash.js'\nimport {\n assembleBundleContainer,\n buildExtractedPartitionWrapper,\n type TransferSealPayload,\n} from '../with-pod/bundle.js'\n\n/** Re-keyed collections snapshot + the fresh DEKs used. */\nexport interface ReKeyResult {\n readonly collections: Record<string, Record<string, EncryptedEnvelope>>\n readonly deks: Map<string, EnclaveKey>\n}\n\n/**\n * Re-encrypt every record in `closure` under a fresh per-collection DEK.\n * Reads raw source envelopes, decrypts under the source DEK, re-encrypts\n * under the new DEK. Plaintext-pipeline: requires an unlocked vault.\n */\nexport async function reKeyClosure(\n vault: Vault,\n closure: Map<string, Set<string>>,\n fieldProjection?: Record<string, readonly string[]>,\n): Promise<ReKeyResult> {\n const { name: vaultName, adapter, getDEK } = vault._introspectState()\n const collections: Record<string, Record<string, EncryptedEnvelope>> = {}\n const deks = new Map<string, EnclaveKey>()\n\n for (const [collectionName, ids] of closure) {\n const srcDek = await getDEK(collectionName)\n const destDek = await generateDEK()\n deks.set(collectionName, destDek)\n const out: Record<string, EncryptedEnvelope> = {}\n // FR-7 structural field projection: when this collection has a projection,\n // narrow the plaintext body to `id` (always) + the listed fields BEFORE\n // re-encryption, so excluded fields never travel in the bundle. Applied\n // identically in both re-key branches; only the body changes — the `_cek`\n // re-wrap order is untouched. Absent/empty projection → byte-identical to\n // the un-projected path (`proj` is undefined and `project` is a no-op).\n const projList = fieldProjection?.[collectionName]\n const proj = projList ? new Set(projList) : undefined\n const project = (plaintext: string): string => {\n if (!proj) return plaintext\n const rec = JSON.parse(plaintext) as Record<string, unknown>\n const kept: Record<string, unknown> = {}\n if ('id' in rec) kept['id'] = rec['id'] // id ALWAYS preserved\n for (const f of proj) if (f in rec) kept[f] = rec[f]\n return JSON.stringify(kept)\n }\n\n for (const id of ids) {\n const env = await adapter.get(vaultName, collectionName, id)\n if (!env) continue\n if (env._cek !== undefined) {\n // Per-record CEK: a naive `{ ...env }` spread would carry a\n // SOURCE-DEK-wrapped CEK into a bundle re-keyed under a different\n // destination DEK — silently undecryptable for the recipient.\n // Re-wrap: unwrap the CEK under the source DEK, re-encrypt the body\n // under the SAME CEK (decision 2 — CEK reused on re-key, preserving\n // the history-chain identity), then wrap the CEK under the fresh\n // destination DEK. The recipient gains access transitively once they\n // re-wrap the collection DEK under their KEK on adopt.\n const cek = await unwrapCek(env._cek, srcDek)\n const plaintext = await decrypt(env._iv, env._data, cek)\n const { iv, data } = await encrypt(project(plaintext), cek)\n const wrapped = await wrapCek(cek, destDek)\n out[id] = { ...env, _iv: iv, _data: data, _cek: wrapped }\n continue\n }\n const plaintext = await openEnvelopeJson(env, srcDek)\n const { iv, data } = await encrypt(project(plaintext), destDek)\n out[id] = { ...env, _iv: iv, _data: data }\n }\n collections[collectionName] = out\n }\n\n return { collections, deks }\n}\n\n/**\n * Re-key the persisted JSON Schemas (`_schemas/<collection>`) for the\n * closure collections under the destination DEKs. Returns a\n * `{ collection: envelope }` map for the carried collections that actually\n * have a schema; collections without one are omitted.\n */\nexport async function reKeySchemas(\n vault: Vault,\n closure: Map<string, Set<string>>,\n destDeks: Map<string, EnclaveKey>,\n fieldProjection?: Record<string, readonly string[]>,\n): Promise<Record<string, EncryptedEnvelope>> {\n const { name: vaultName, adapter, getDEK } = vault._introspectState()\n const out: Record<string, EncryptedEnvelope> = {}\n\n for (const collectionName of closure.keys()) {\n // FR-7: skip a projected collection's schema — the narrowed shape no\n // longer matches the stored JSON Schema, so carrying it would assert a\n // contract the projected records violate (missing required fields).\n if (fieldProjection?.[collectionName]) continue\n const env = await adapter.get(vaultName, SCHEMAS_COLLECTION, collectionName)\n if (!env) continue // collection has no persisted schema — skip\n const destDek = destDeks.get(collectionName)\n if (!destDek) continue\n const srcDek = await getDEK(collectionName)\n const plaintext = await openEnvelopeJson(env, srcDek)\n const { iv, data } = await encrypt(plaintext, destDek)\n out[collectionName] = { ...env, _iv: iv, _data: data }\n }\n return out\n}\n\nconst paddedIndex = (n: number): string => String(n).padStart(10, '0')\n\nexport interface ReKeyLedgerResult {\n /** { paddedIndex: re-encrypted entry envelope } for backup._internal._ledger. */\n readonly entries: Record<string, EncryptedEnvelope>\n /** Recomputed ledgerHead for the carried chain (index -1 when empty). */\n readonly head: { hash: string; index: number; ts: string }\n}\n\n/**\n * Build the carried `_ledger` chain for an extracted partition.\n * Filters source entries to the closure, RE-CHAINS them (fresh index + prevHash),\n * and re-encrypts under `ledgerDek`. The `payloadHash` is recomputed against the\n * re-keyed envelope ONLY for the latest `put` per (collection,id) — the entry\n * `verifyBackupIntegrity` cross-checks; earlier puts + deletes keep their source\n * `payloadHash` verbatim (recomputing an intermediate put would assert a false\n * hash for an older version). Amendments + out-of-closure entries are dropped;\n * `_ledger_deltas`/`_history` are deferred to slice 2.\n */\nexport async function reKeyLedger(\n vault: Vault,\n closure: Map<string, Set<string>>,\n reKeyedCollections: Record<string, Record<string, EncryptedEnvelope>>,\n ledgerDek: EnclaveKey,\n): Promise<ReKeyLedgerResult> {\n const { name: vaultName, adapter, getDEK } = vault._introspectState()\n const srcLedgerDek = await getDEK(LEDGER_COLLECTION)\n\n // 1. Load + decrypt source entries in index order.\n const ids = (await adapter.list(vaultName, LEDGER_COLLECTION)).sort()\n const srcEntries: LedgerEntry[] = []\n for (const id of ids) {\n const env = await adapter.get(vaultName, LEDGER_COLLECTION, id)\n if (!env) continue\n srcEntries.push(JSON.parse(await openEnvelopeJson(env, srcLedgerDek)) as LedgerEntry)\n }\n\n // 2. Keep closure put/delete entries (drop amendments + out-of-closure).\n const kept = srcEntries.filter(\n (e) => (e.op === 'put' || e.op === 'delete') && (closure.get(e.collection)?.has(e.id) ?? false),\n )\n\n // 3a. Reverse pass: index of the LATEST put per (collection,id).\n const latestPutIndex = new Map<string, number>()\n for (let i = kept.length - 1; i >= 0; i--) {\n const e = kept[i]!\n if (e.op !== 'put') continue\n const key = `${e.collection}/${e.id}`\n if (!latestPutIndex.has(key)) latestPutIndex.set(key, i)\n }\n\n // 3b. Forward re-chain + re-encrypt.\n const entries: Record<string, EncryptedEnvelope> = {}\n let prevHash = ''\n let last: LedgerEntry | undefined\n for (let i = 0; i < kept.length; i++) {\n const src = kept[i]!\n const key = `${src.collection}/${src.id}`\n const isLatestPut = src.op === 'put' && latestPutIndex.get(key) === i\n const reKeyedEnv = reKeyedCollections[src.collection]?.[src.id]\n const payloadHash = isLatestPut && reKeyedEnv\n ? await envelopePayloadHash(reKeyedEnv)\n : src.payloadHash\n const entry: LedgerEntry = {\n index: i,\n prevHash,\n op: src.op,\n collection: src.collection,\n id: src.id,\n version: src.version,\n ts: src.ts,\n actor: src.actor,\n payloadHash,\n ...(src.reason !== undefined ? { reason: src.reason } : {}),\n }\n const { iv, data } = await encrypt(canonicalJson(entry), ledgerDek)\n entries[paddedIndex(i)] = {\n _noydb: NOYDB_FORMAT_VERSION, _v: i + 1, _ts: entry.ts, _iv: iv, _data: data, _by: entry.actor,\n }\n prevHash = await hashEntry(entry)\n last = entry\n }\n\n return {\n entries,\n head: last ? { hash: prevHash, index: last.index, ts: last.ts } : { hash: '', index: -1, ts: '' },\n }\n}\n\n/** Build the AAD binding for chunk integrity: \"{eTag}:{chunkIndex}:{chunkCount}\".\n * Mirrors `chunkAAD` in blob-set.ts — the eTag is preserved verbatim across\n * the transfer (see `reKeyBlobs`), so the same AAD that bound a chunk in the\n * source keeps binding it in the bundle. */\nfunction chunkAAD(eTag: string, chunkIndex: number, chunkCount: number): Uint8Array {\n return new TextEncoder().encode(`${eTag}:${chunkIndex}:${chunkCount}`)\n}\n\n/** Carried blob internals + the fresh transfer `_blob` DEK (present only when\n * the closure references at least one chunk-based blob). */\nexport interface ReKeyBlobsResult {\n /** `_blob_slots_<C>` / `_blob_versions_<C>` / `_blob_index` / `_blob_chunks`\n * envelopes for the bundle's `_internal` map. */\n readonly internal: Record<string, Record<string, EncryptedEnvelope>>\n /** Fresh transfer `_blob` DEK — seal it so owner-creation wraps it under the\n * recipient KEK. Undefined when no blob travels (source keyring untouched). */\n readonly blobDek?: EnclaveKey\n}\n\n/**\n * Carry the FK-closed slice's blobs — HARDENED key handling (no master-key leak).\n *\n * The source vault's shared `_blob` DEK decrypts (or unwraps the content CEK of)\n * EVERY blob in the source. Sealing it into the transfer would hand the recipient\n * a key to blobs far outside their slice. Instead we mint a **fresh transfer\n * `_blob` DEK** and arrange every carried blob into per-blob-CEK mode under it:\n *\n * - **erasable blob** (`_cek` present): unwrap the per-blob content CEK under the\n * SOURCE `_blob` DEK, re-wrap it under the FRESH transfer DEK. Chunks travel\n * **verbatim** (still ciphertext under that same content CEK — passthrough).\n * - **legacy blob** (no `_cek`, chunks under the shared `_blob` DEK): promote it\n * IN-BUNDLE — mint a fresh content CEK, decrypt each chunk under the source\n * `_blob` DEK and re-encrypt under the content CEK (same AAD, so the eTag-bound\n * integrity holds), then wrap the content CEK under the transfer DEK. The\n * SOURCE is never mutated (non-destructive), and the bundle never holds\n * plaintext blob bytes (zero-knowledge preserved).\n *\n * **eTag identity is preserved** (not re-HMAC'd). eTags are HMAC-keyed off the\n * `_blob` DEK, but they are stored as OPAQUE keys (`_blob_index/<eTag>`,\n * `_blob_chunks/<eTag>_<i>`) and never recomputed on read — only on a `put()`\n * for dedup. Keeping them verbatim keeps every slot/version/index/chunk key and\n * the chunk AAD coherent with zero chunk-key churn. The only consequence: a\n * future `put()` of identical bytes in the adopted vault computes a different\n * eTag (HMAC under the fresh DEK) and will NOT dedup against the carried blob —\n * an accepted, documented trade for hardened key isolation.\n *\n * Slots/versions are re-keyed under their parent collection's destination DEK\n * (honoring `fieldProjection` — projected-out blob fields' slots never travel);\n * `BlobObject.refCount` is recomputed from carried references only.\n *\n * `external` slots reference an unencrypted shared-bucket object that is not in\n * the bundle — their slot metadata travels (so the catalog entry survives) but\n * the bytes do not (a documented v1 limitation; their eTag is `''`).\n */\nexport async function reKeyBlobs(\n vault: Vault,\n closure: Map<string, Set<string>>,\n destDeks: Map<string, EnclaveKey>,\n fieldProjection?: Record<string, readonly string[]>,\n): Promise<ReKeyBlobsResult> {\n const { name: vaultName, adapter, getDEK } = vault._introspectState()\n const internal: Record<string, Record<string, EncryptedEnvelope>> = {}\n\n // travel set: eTag → number of carried references (slots + versions) within\n // the closure. Recomputed refCount, NOT the source's (which may count\n // out-of-slice referrers, leaving the adopted blob un-GC-able).\n const carriedRefs = new Map<string, number>()\n const addRef = (eTag: string): void => {\n if (!eTag) return // external slot — no chunk-based blob to carry\n carriedRefs.set(eTag, (carriedRefs.get(eTag) ?? 0) + 1)\n }\n\n const place = (collection: string, id: string, env: EncryptedEnvelope): void => {\n let bucket = internal[collection]\n if (!bucket) { bucket = {}; internal[collection] = bucket }\n bucket[id] = env\n }\n\n // ── Slots + versions (parent-collection-DEK keyed) ─────────────────\n for (const [collectionName, ids] of closure) {\n const destDek = destDeks.get(collectionName)\n if (!destDek) continue\n const srcDek = await getDEK(collectionName)\n const projList = fieldProjection?.[collectionName]\n const proj = projList ? new Set(projList) : undefined\n\n // Slots: one envelope per record, a `{ slotName: SlotRecord }` map.\n const slotsCollection = `${BLOB_SLOTS_PREFIX}${collectionName}`\n for (const id of ids) {\n const env = await adapter.get(vaultName, slotsCollection, id)\n if (!env) continue\n const slots = JSON.parse(await openEnvelopeJson(env, srcDek)) as Record<string, SlotRecord>\n // FR-7: drop projected-out blob fields' slots (slot names are blob field\n // names) — their eTags then never enter the travel set.\n const kept: Record<string, SlotRecord> = {}\n for (const [slotName, slot] of Object.entries(slots)) {\n if (proj && !proj.has(slotName)) continue\n kept[slotName] = slot\n addRef(slot.eTag)\n }\n if (Object.keys(kept).length === 0) continue\n const { iv, data } = await encrypt(JSON.stringify(kept), destDek)\n place(slotsCollection, id, { ...env, _iv: iv, _data: data })\n }\n\n // Versions: key = `${recordId}::${slotName}::${label}`; each an independent\n // refCount hold on its eTag.\n const versionsCollection = `${BLOB_VERSIONS_PREFIX}${collectionName}`\n const versionKeys = await adapter.list(vaultName, versionsCollection)\n for (const key of versionKeys) {\n const [recordId, slotName] = key.split('::')\n if (recordId === undefined || !ids.has(recordId)) continue\n if (proj && slotName !== undefined && !proj.has(slotName)) continue\n const env = await adapter.get(vaultName, versionsCollection, key)\n if (!env) continue\n const record = JSON.parse(await openEnvelopeJson(env, srcDek)) as VersionRecord\n addRef(record.eTag)\n const { iv, data } = await encrypt(JSON.stringify(record), destDek)\n place(versionsCollection, key, { ...env, _iv: iv, _data: data })\n }\n }\n\n // No chunk-based blob in the closure → carry nothing, mint nothing. Guarded\n // so `getDEK('_blob')` does not auto-mint + persist a phantom DEK on the\n // source keyring (mirrors the carryLedger non-destructive guard).\n if (carriedRefs.size === 0) return { internal }\n\n // ── Index + chunks (re-keyed under a FRESH transfer `_blob` DEK) ────\n const srcBlobDek = await getDEK(BLOB_COLLECTION)\n const transferBlobDek = await generateDEK()\n\n for (const [eTag, refCount] of carriedRefs) {\n const idxEnv = await adapter.get(vaultName, BLOB_INDEX_COLLECTION, eTag)\n if (!idxEnv) continue // dangling slot reference — nothing to carry\n const blob = JSON.parse(await openEnvelopeJson(idxEnv, srcBlobDek)) as BlobObject\n\n // Resolve the per-blob content CEK; passthrough vs. in-bundle promotion.\n let contentCek: EnclaveKey\n let chunksPassthrough: boolean\n if (blob._cek !== undefined) {\n contentCek = await unwrapCek(blob._cek, srcBlobDek)\n chunksPassthrough = true\n } else {\n // Legacy: promote to per-blob-CEK for the bundle (source untouched).\n contentCek = await generateDEK()\n chunksPassthrough = false\n }\n\n // Chunks: verbatim for an already-erasable blob; decrypt-then-re-encrypt\n // under the fresh content CEK for a legacy blob (same eTag-bound AAD).\n for (let i = 0; i < blob.chunkCount; i++) {\n const chunkId = `${eTag}_${i}`\n const chunkEnv = await adapter.get(vaultName, BLOB_CHUNKS_COLLECTION, chunkId)\n if (!chunkEnv) {\n throw new PartitionExtractionError(\n `reKeyBlobs: blob chunk ${i}/${blob.chunkCount} missing for eTag \"${eTag}\"; `\n + `cannot carry an incomplete blob into the partition.`,\n )\n }\n if (chunksPassthrough) {\n place(BLOB_CHUNKS_COLLECTION, chunkId, chunkEnv)\n } else {\n const aad = chunkAAD(eTag, i, blob.chunkCount)\n const plain = await decryptBytesWithAAD(chunkEnv._iv, chunkEnv._data, srcBlobDek, aad)\n const { iv, data } = await encryptBytesWithAAD(plain, contentCek, aad)\n place(BLOB_CHUNKS_COLLECTION, chunkId, { ...chunkEnv, _iv: iv, _data: data })\n }\n }\n\n // Index: per-blob-CEK mode under the transfer DEK, refCount corrected.\n // Drop any transient `_cekPending` (never set on a settled blob — possible\n // only if the source is mid-migration; we set a fresh settled `_cek`).\n const { _cekPending, ...rest } = blob\n void _cekPending\n const carried: BlobObject = { ...rest, refCount, _cek: await wrapCek(contentCek, transferBlobDek) }\n const { iv, data } = await encrypt(JSON.stringify(carried), transferBlobDek)\n place(BLOB_INDEX_COLLECTION, eTag, { ...idxEnv, _iv: iv, _data: data })\n }\n\n return { internal, blobDek: transferBlobDek }\n}\n\n/** A minted transfer key (raw 32 bytes) + the seal carrying the DEK set. */\nexport interface SealResult {\n readonly seal: TransferSealPayload\n readonly transferKey: Uint8Array\n}\n\n/**\n * Mint a random 32-byte transfer key, export each DEK to raw bytes, and\n * AES-256-GCM-seal the `{ collection: base64(rawDEK) }` map under the\n * transfer key. The transfer key is returned to the caller out-of-band;\n * only the sealed bytes travel in the bundle. Layout: iv(12) ‖ ct ‖ tag.\n */\nexport async function sealDeks(deks: Map<string, EnclaveKey>): Promise<SealResult> {\n const dekMap: Record<string, string> = {}\n for (const [collection, dek] of deks) {\n const raw = await crypto.subtle.exportKey('raw', dek)\n dekMap[collection] = bufferToBase64(raw)\n }\n\n const transferKey = crypto.getRandomValues(new Uint8Array(32))\n const key = await crypto.subtle.importKey('raw', transferKey, 'AES-GCM', false, ['encrypt'])\n const iv = crypto.getRandomValues(new Uint8Array(12))\n const plaintext = new TextEncoder().encode(JSON.stringify(dekMap))\n const ct = await crypto.subtle.encrypt({ name: 'AES-GCM', iv }, key, plaintext)\n\n const combined = new Uint8Array(iv.byteLength + ct.byteLength)\n combined.set(iv, 0)\n combined.set(new Uint8Array(ct), iv.byteLength)\n\n const sealId = bufferToBase64(crypto.getRandomValues(new Uint8Array(12)))\n return {\n seal: { v: 1, alg: 'aes-256-gcm-pre-shared', sealId, payload: bufferToBase64(combined) },\n transferKey,\n }\n}\n\nexport interface ExtractPartitionResult {\n readonly bundleBytes: Uint8Array\n /** Raw 32-byte transfer key — deliver out-of-band; required to adopt. */\n readonly transferKey: Uint8Array\n readonly sealId: string\n}\n\n/**\n * Extract a re-keyed, transfer-sealed partition. Owner-only\n * (invariant 5): producing a standalone re-keyed vault is an\n * ownership operation. Non-destructive on the source.\n */\nexport type ExtractPartitionOptions = WalkClosureOptions & {\n readonly compression?: 'auto' | 'brotli' | 'gzip' | 'none'\n readonly carrySchemas?: boolean\n readonly carryLedger?: boolean\n /**\n * FR-7 structural field projection: per-collection allow-list of fields\n * to keep. Non-listed fields are dropped from each record BEFORE\n * re-encryption (so they never travel in the bundle); `id` is always\n * preserved. A projected collection's persisted schema is NOT carried.\n * Absent/empty → un-projected behavior (byte-identical to today).\n */\n readonly fieldProjection?: Record<string, readonly string[]>\n}\n\n/**\n * Public extract-partition entry — gated behind `cargoStrategy: withCargo()`\n * (S4). Routes through the source vault's cargo strategy so an un-opted-in\n * caller hits `NO_CARGO`'s throw; `withCargo()` dynamically imports and runs\n * {@link extractPartitionCore} (the crypto engine, kept out of the floor).\n */\nexport async function extractPartition(\n vault: Vault,\n opts: ExtractPartitionOptions,\n): Promise<ExtractPartitionResult> {\n return vault.cargoStrategy.extractPartition(vault, opts)\n}\n\n/**\n * The extract-partition crypto engine — reached only when `withCargo()` is\n * opted in (via the lazy `with-cargo/active.ts` chunk). Body unchanged from the\n * hardened implementation; only the public gate wraps it.\n */\nexport async function extractPartitionCore(\n vault: Vault,\n opts: ExtractPartitionOptions,\n): Promise<ExtractPartitionResult> {\n // FR-6: extract-and-sever is the inalienability-floor half — owner-only. A\n // custodian operates fully but must NEVER produce a standalone re-keyed\n // partition (that would let it sever a copy out from under the sealed owner).\n // Explicit assertion so the security boundary is auditable at this site.\n if (vault.role === 'custodian') {\n throw new PartitionExtractionError(\n 'extractPartition is owner-only; a custodian cannot extract-and-sever '\n + '(FR-6: producing a re-keyed standalone partition is an ownership operation; use the Deed owner).',\n )\n }\n if (vault.role !== 'owner') {\n throw new PartitionExtractionError(\n `extractPartition requires the 'owner' role on the source vault; caller is '${vault.role}'. `\n + `Producing a re-keyed standalone partition is an ownership operation.`,\n )\n }\n\n // Persisted-schema writes (collection({ persistJsonSchema: true })) are fire-\n // and-forget queued onto vault._pendingSchemaWrites — a caller that does\n // `collection() → put() → extractPartition({ carrySchemas: true })` in quick\n // succession can hit a window where _schemas/<col> is not yet on disk and\n // reKeySchemas silently drops the row. Drain BEFORE reKeySchemas reads.\n if (opts.carrySchemas) await vault._drainPendingSchemaWrites()\n\n const { closure } = await walkClosure(vault, opts)\n const { collections, deks } = await reKeyClosure(vault, closure, opts.fieldProjection)\n\n // carryLedger: mint a fresh _ledger DEK, build the carried chain, and\n // SEAL the ledger DEK alongside the data DEKs so owner-creation wraps it into the\n // recipient keyring (lets them decrypt + verify the chain). Must run BEFORE\n // sealDeks.\n let ledgerHead: { hash: string; index: number; ts: string } | undefined\n let ledgerEntries: Record<string, EncryptedEnvelope> | undefined\n if (opts.carryLedger && vault._getLedgerOrNull() !== null) {\n // Skip when the source vault has no history strategy: reKeyLedger's first\n // `getDEK(LEDGER_COLLECTION)` would auto-mint and persist a phantom\n // _ledger DEK on the source keyring (contradicting \"non-destructive on\n // the source\"), and there's nothing to carry anyway. Mirrors the same\n // null-guard the source audit-append uses below.\n const ledgerDek = await generateDEK()\n const built = await reKeyLedger(vault, closure, collections, ledgerDek)\n if (built.head.index >= 0) {\n ledgerEntries = built.entries\n ledgerHead = built.head\n deks.set(LEDGER_COLLECTION, ledgerDek)\n }\n }\n\n // Carry the slice's blobs — re-keyed under a FRESH transfer `_blob` DEK\n // (HARDENED: never carries the source's shared blob DEK). Runs BEFORE\n // sealDeks so the fresh DEK is sealed alongside the data DEKs; non-destructive\n // on the source (mints + reads `_blob` only when the closure has blobs).\n const blobs = await reKeyBlobs(vault, closure, deks, opts.fieldProjection)\n if (blobs.blobDek) deks.set(BLOB_COLLECTION, blobs.blobDek)\n\n // Build _internal (schemas + ledger + blobs). reKeySchemas reads data-\n // collection DEKs only, so it is unaffected by the _ledger DEK added above.\n const internalSchemas = opts.carrySchemas ? await reKeySchemas(vault, closure, deks, opts.fieldProjection) : {}\n const internal: Record<string, Record<string, EncryptedEnvelope>> = {}\n if (Object.keys(internalSchemas).length > 0) internal[SCHEMAS_COLLECTION] = internalSchemas\n if (ledgerEntries) internal[LEDGER_COLLECTION] = ledgerEntries\n for (const [collection, records] of Object.entries(blobs.internal)) internal[collection] = records\n const hasInternal = Object.keys(internal).length > 0\n\n const { seal, transferKey } = await sealDeks(deks)\n\n // Source-side audit: record that a partition\n // was handed over. Non-destructive — an audit append, no record touched.\n // No-op when the source vault has no history strategy. append() fills\n // index/prevHash/ts and (since actor is '') the ledger's configured actor.\n await vault._getLedgerOrNull()?.append({\n op: 'lifecycle',\n collection: '',\n id: '',\n version: 0,\n actor: '',\n payloadHash: '',\n reason: `partition-handed-over:${seal.sealId}`,\n })\n\n // Build the dump JSON: unowned (empty keyrings), empty ledger (default),\n // re-keyed collections only.\n const { name: vaultName } = vault._introspectState()\n const backup = {\n _noydb_backup: NOYDB_BACKUP_VERSION,\n _compartment: vaultName,\n _exported_at: new Date().toISOString(),\n _exported_by: '', // unowned — no source user travels\n keyrings: {},\n collections,\n ...(hasInternal ? { _internal: internal } : {}),\n ...(ledgerHead ? { ledgerHead: { hash: ledgerHead.hash, index: ledgerHead.index, ts: ledgerHead.ts } } : {}),\n }\n const bodyJsonStr = JSON.stringify(buildExtractedPartitionWrapper(JSON.stringify(backup), seal))\n\n // An extracted partition is a NEW vault, not a re-export of the source —\n // mint a fresh handle rather than reusing the source's stable ULID\n // (which would collide if a recipient imports both source + partition).\n const handle = generateULID()\n const bundleBytes = await assembleBundleContainer({\n handle,\n bodyJsonStr,\n compression: opts.compression,\n headerExtras: {\n bundleKind: 'extracted-partition',\n transferSeal: { v: seal.v, alg: seal.alg, sealId: seal.sealId }, // indicator only\n },\n })\n\n return { bundleBytes, transferKey, sealId: seal.sealId }\n}\n"],"mappings":"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","names":["plaintext","iv","data"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/with-commit/history/history.ts","../src/with-commit/history/time-machine.ts"],"sourcesContent":["import type { NoydbStore, EncryptedEnvelope, HistoryOptions, PruneOptions } from '../../kernel/types.js'\nimport { NOYDB_FORMAT_VERSION } from '../../kernel/types.js'\nimport { isTombstone } from '../../kernel/enclave/index.js'\n\n/**\n * History storage convention:\n * Collection: `_history`\n * ID format: `{collection}:{recordId}:{paddedVersion}`\n * Version is zero-padded to 10 digits for lexicographic sorting.\n */\n\nconst HISTORY_COLLECTION = '_history'\nconst VERSION_PAD = 10\n\nfunction historyId(collection: string, recordId: string, version: number): string {\n return `${collection}:${recordId}:${String(version).padStart(VERSION_PAD, '0')}`\n}\n\n// Unused today, kept for future history-id parsing utilities.\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nfunction parseHistoryId(id: string): { collection: string; recordId: string; version: number } | null {\n const lastColon = id.lastIndexOf(':')\n if (lastColon < 0) return null\n const versionStr = id.slice(lastColon + 1)\n const rest = id.slice(0, lastColon)\n const firstColon = rest.indexOf(':')\n if (firstColon < 0) return null\n return {\n collection: rest.slice(0, firstColon),\n recordId: rest.slice(firstColon + 1),\n version: parseInt(versionStr, 10),\n }\n}\n\nfunction matchesPrefix(id: string, collection: string, recordId?: string): boolean {\n if (recordId) {\n return id.startsWith(`${collection}:${recordId}:`)\n }\n return id.startsWith(`${collection}:`)\n}\n\n/** Save a history entry (a complete encrypted envelope snapshot). */\nexport async function saveHistory(\n adapter: NoydbStore,\n vault: string,\n collection: string,\n recordId: string,\n envelope: EncryptedEnvelope,\n): Promise<void> {\n const id = historyId(collection, recordId, envelope._v)\n await adapter.put(vault, HISTORY_COLLECTION, id, envelope)\n}\n\n/** Get history entries for a record, sorted newest-first. */\nexport async function getHistory(\n adapter: NoydbStore,\n vault: string,\n collection: string,\n recordId: string,\n options?: HistoryOptions,\n): Promise<EncryptedEnvelope[]> {\n const allIds = await adapter.list(vault, HISTORY_COLLECTION)\n const matchingIds = allIds\n .filter(id => matchesPrefix(id, collection, recordId))\n .sort()\n .reverse() // newest first\n\n const entries: EncryptedEnvelope[] = []\n\n for (const id of matchingIds) {\n const envelope = await adapter.get(vault, HISTORY_COLLECTION, id)\n if (!envelope) continue\n\n // Apply time filters\n if (options?.from && envelope._ts < options.from) continue\n if (options?.to && envelope._ts > options.to) continue\n\n entries.push(envelope)\n\n if (options?.limit && entries.length >= options.limit) break\n }\n\n return entries\n}\n\n/** Get a specific version's envelope from history. */\nexport async function getVersionEnvelope(\n adapter: NoydbStore,\n vault: string,\n collection: string,\n recordId: string,\n version: number,\n): Promise<EncryptedEnvelope | null> {\n const id = historyId(collection, recordId, version)\n return adapter.get(vault, HISTORY_COLLECTION, id)\n}\n\n/** Prune history entries. Returns the number of entries deleted. */\nexport async function pruneHistory(\n adapter: NoydbStore,\n vault: string,\n collection: string,\n recordId: string | undefined,\n options: PruneOptions,\n): Promise<number> {\n const allIds = await adapter.list(vault, HISTORY_COLLECTION)\n const matchingIds = allIds\n .filter(id => recordId ? matchesPrefix(id, collection, recordId) : matchesPrefix(id, collection))\n .sort()\n\n let toDelete: string[] = []\n\n if (options.keepVersions !== undefined) {\n // Keep only the N most recent, delete the rest\n const keep = options.keepVersions\n if (matchingIds.length > keep) {\n toDelete = matchingIds.slice(0, matchingIds.length - keep)\n }\n }\n\n if (options.beforeDate) {\n // Delete entries older than the specified date\n for (const id of matchingIds) {\n if (toDelete.includes(id)) continue\n const envelope = await adapter.get(vault, HISTORY_COLLECTION, id)\n if (envelope && envelope._ts < options.beforeDate) {\n toDelete.push(id)\n }\n }\n }\n\n // Deduplicate\n const uniqueDeletes = [...new Set(toDelete)]\n\n for (const id of uniqueDeletes) {\n await adapter.delete(vault, HISTORY_COLLECTION, id)\n }\n\n return uniqueDeletes.length\n}\n\n/** Clear all history for a vault, optionally scoped to a collection or record. */\nexport async function clearHistory(\n adapter: NoydbStore,\n vault: string,\n collection?: string,\n recordId?: string,\n): Promise<number> {\n const allIds = await adapter.list(vault, HISTORY_COLLECTION)\n let toDelete: string[]\n\n if (collection && recordId) {\n toDelete = allIds.filter(id => matchesPrefix(id, collection, recordId))\n } else if (collection) {\n toDelete = allIds.filter(id => matchesPrefix(id, collection))\n } else {\n toDelete = allIds\n }\n\n for (const id of toDelete) {\n await adapter.delete(vault, HISTORY_COLLECTION, id)\n }\n\n return toDelete.length\n}\n\n/**\n * Crypto-shred every `_history` version of a record. Each non-tombstone\n * history envelope is OVERWRITTEN in place with a tombstone\n * `{ _noydb, _v, _ts: now, _by: actor, _iv: '', _data: '' }` — dropping\n * `_iv`/`_data`/`_cek`/`_det`, so the prior ciphertext (and the wrapped CEK\n * that could decrypt it) is gone everywhere this store reaches. The version\n * counter (`_v`) is preserved so the audit trail still shows \"N versions\n * existed and were erased.\"\n *\n * Overwrite — NOT delete — so the history key itself survives as proof the\n * version existed. Already-tombstoned versions (re-run / idempotent forget)\n * are left untouched and not counted.\n *\n * Returns the number of history versions newly tombstoned.\n */\nexport async function tombstoneHistory(\n adapter: NoydbStore,\n vault: string,\n collection: string,\n recordId: string,\n actor: string,\n encrypted: boolean,\n): Promise<number> {\n const allIds = await adapter.list(vault, HISTORY_COLLECTION)\n const matchingIds = allIds.filter(id => matchesPrefix(id, collection, recordId))\n\n const now = new Date().toISOString()\n let count = 0\n for (const id of matchingIds) {\n const env = await adapter.get(vault, HISTORY_COLLECTION, id)\n if (!env) continue\n // Already a tombstone (no body and no wrapped CEK)? Skip — idempotent.\n if (isTombstone(env, encrypted)) continue\n const tombstone: EncryptedEnvelope = {\n _noydb: NOYDB_FORMAT_VERSION,\n _v: env._v,\n _ts: now,\n _iv: '',\n _data: '',\n ...(actor ? { _by: actor } : {}),\n }\n await adapter.put(vault, HISTORY_COLLECTION, id, tombstone)\n count++\n }\n return count\n}\n","/**\n * Time-machine queries — point-in-time reads reconstructed from the\n * existing history + ledger infrastructure.\n *\n * ## Usage\n *\n * ```ts\n * const vault = await db.openVault('acme', { passphrase })\n * const q1End = vault.at('2026-03-31T23:59:59Z')\n * const invoice = await q1End.collection<Invoice>('invoices').get('inv-001')\n * // → the record as it stood at the close of Q1 2026\n * ```\n *\n * ## How it works\n *\n * Every write path already fans out into two persistence lanes:\n *\n * 1. `saveHistory(...)` persists a **full encrypted envelope snapshot**\n * per version under the `_history` collection (one envelope per\n * version, keyed by `{collection}:{id}:{paddedVersion}`). Each\n * envelope carries its own `_ts` (the write timestamp).\n * 2. `ledger.append(...)` appends a hash-chained audit entry that\n * records the `op` (put / delete), `version`, and `ts`.\n *\n * Reconstruction at a target timestamp T is therefore:\n *\n * - Find the newest history envelope for `(collection, id)` whose\n * `_ts ≤ T` — that's the state the record was in at T.\n * - Check the ledger for any `op: 'delete'` entry for the same\n * `(collection, id)` with `entry.ts` in `(latestEnvelope._ts, T]` —\n * if present, the record was deleted before T, so return `null`.\n * - Decrypt the surviving envelope with the current collection DEK\n * (DEKs are per-collection but stable across versions — the same\n * key encrypts v1 and v15 of a record).\n *\n * No delta replay. The existing `history.ts` module already stores\n * complete snapshots; we just pick the right one.\n *\n * ## Read-only contract\n *\n * Every write method on `CollectionInstant` throws\n * {@link ReadOnlyAtInstantError}. A historical view is a *read*\n * surface — mutating the past would require either a branch/shadow\n * mechanism (tracked under shadow vaults) or a rewrite of\n * history, which breaks the ledger's tamper-evidence guarantee.\n *\n * @module\n */\nimport type { EncryptedEnvelope, NoydbStore } from '../../kernel/types.js'\nimport type { LedgerStore } from './ledger/store.js'\nimport { getHistory } from './history.js'\nimport { decrypt, type EnclaveKey } from '../../kernel/enclave/index.js'\nimport { ReadOnlyAtInstantError } from '../../kernel/errors.js'\n\n/**\n * Narrow view of a {@link Vault}'s internals that\n * {@link VaultInstant} needs. Passed in by `Vault.at()` rather than\n * constructed here so all crypto + adapter access stays inside the\n * Vault class.\n *\n * Not exported from the public barrel — consumers should get a\n * `VaultInstant` via `vault.at(ts)`, never by constructing one\n * directly.\n */\nexport interface VaultEngine {\n readonly adapter: NoydbStore\n /** Vault name (the compartment). */\n readonly name: string\n /**\n * `true` when the vault was opened with a passphrase (the normal\n * case). `false` in plaintext-mode vaults (`encrypt: false`) — in\n * that case `envelope._data` is raw JSON and we skip the DEK lookup.\n */\n readonly encrypted: boolean\n /**\n * Resolves the DEK used to decrypt a given collection's envelopes.\n * Not called when `encrypted` is false.\n */\n getDEK(collection: string): Promise<EnclaveKey>\n /**\n * Lazily-initialised ledger. We consult it to detect deletes that\n * happened between the latest history snapshot and the target\n * timestamp. `null` when history is disabled for this vault — in\n * that case time-machine reads fall back to history-only\n * reconstruction (which may miss deletes).\n */\n getLedger(): LedgerStore | null\n}\n\n/**\n * A vault at a fixed instant. Produced by `vault.at(timestamp)`.\n * Carries no session state of its own — every read is a fresh\n * lookup through the vault's adapter.\n *\n * Cheap to construct; safe to throw away. Create one per query.\n */\nexport class VaultInstant {\n constructor(\n private readonly engine: VaultEngine,\n /** Fully-resolved target timestamp (ISO-8601 UTC). */\n public readonly timestamp: string,\n ) {}\n\n /** Get a point-in-time view of a collection. */\n collection<T = unknown>(name: string): CollectionInstant<T> {\n return new CollectionInstant<T>(this.engine, this.timestamp, name)\n }\n}\n\n/**\n * A read-only collection view anchored to a past instant.\n *\n * Every write method throws {@link ReadOnlyAtInstantError} — see the\n * module docstring for why. The read surface is intentionally smaller\n * than the live {@link Collection}: `get` and `list` cover the\n * \"what did the books look like on date X\" use case without pulling\n * in the full query DSL / joins / aggregates at this stage. Follow-up\n * work tracked under.\n */\nexport class CollectionInstant<T = unknown> {\n constructor(\n private readonly engine: VaultEngine,\n private readonly targetTs: string,\n public readonly name: string,\n ) {}\n\n /**\n * Return the record as it existed at the target timestamp, or\n * `null` if the record had not been created yet or had already been\n * deleted by then.\n */\n async get(id: string): Promise<T | null> {\n const envelope = await this.resolveEnvelope(id)\n if (!envelope) return null\n const plaintext = this.engine.encrypted\n ? await decrypt(envelope._iv, envelope._data, await this.engine.getDEK(this.name))\n : envelope._data\n return JSON.parse(plaintext) as T\n }\n\n /**\n * IDs of records that existed (had at least one `put` and were not\n * subsequently deleted) at the target timestamp.\n *\n * Implemented as a linear scan over history + ledger. Performance\n * is bounded by total history size (not live-vault size), so the\n * memory-first vault-scale cap (1K–50K records × average history\n * depth) still applies.\n */\n async list(): Promise<string[]> {\n const historyIds = await collectHistoryIds(this.engine.adapter, this.engine.name, this.name)\n const liveIds = await this.engine.adapter.list(this.engine.name, this.name)\n const candidateIds = new Set<string>([...historyIds, ...liveIds])\n const alive: string[] = []\n for (const id of candidateIds) {\n const env = await this.resolveEnvelope(id)\n if (env) alive.push(id)\n }\n return alive.sort()\n }\n\n // ── write guards ───────────────────────────────────────────────────\n\n async put(_id: string, _record: T): Promise<never> {\n throw new ReadOnlyAtInstantError('put', this.targetTs)\n }\n async delete(_id: string): Promise<never> {\n throw new ReadOnlyAtInstantError('delete', this.targetTs)\n }\n async update(_id: string, _patch: Partial<T>): Promise<never> {\n throw new ReadOnlyAtInstantError('update', this.targetTs)\n }\n\n // ── internals ─────────────────────────────────────────────────────\n\n /**\n * Return the envelope that represents the record's state at\n * `targetTs`, accounting for deletes. `null` if the record didn't\n * exist at that instant.\n *\n * ## Why we use the ledger as the authoritative timeline\n *\n * The per-version history snapshots saved by `saveHistory()` do\n * carry a `_ts` field, but that timestamp is the moment the\n * snapshot was *captured* (i.e. the instant right before the\n * subsequent overwrite), not the original write time. The ledger,\n * by contrast, records `ts` at the moment of each `put` / `delete`\n * — it's the only source that tracks the real timeline. So:\n *\n * 1. Walk the ledger; find the latest entry for `(collection, id)`\n * with `ts ≤ targetTs`.\n * 2. If that entry is a `delete`, the record was gone at the\n * target instant — return null.\n * 3. Otherwise it's a `put` with a specific `version`. Load the\n * envelope for that version from history, falling back to the\n * live collection for the most recent version.\n *\n * ## Fallback when the ledger is disabled\n *\n * If the vault has history disabled, `getLedger()` returns null and\n * we fall back to comparing envelope `_ts` fields. This is\n * approximate and gets the *last write* right but may confuse the\n * intermediate versions; adopters needing accurate time-machine\n * reads should leave history enabled.\n */\n private async resolveEnvelope(id: string): Promise<EncryptedEnvelope | null> {\n const ledger = this.engine.getLedger()\n if (ledger) {\n return this.resolveViaLedger(id, ledger)\n }\n return this.resolveViaEnvelopeTs(id)\n }\n\n private async resolveViaLedger(id: string, ledger: LedgerStore): Promise<EncryptedEnvelope | null> {\n const entries = await ledger.entries()\n // Entries are already ordered by index which is the mutation order.\n let latest: { op: 'put' | 'delete'; version: number } | null = null\n for (const e of entries) {\n if (e.collection !== this.name || e.id !== id) continue\n if (e.ts > this.targetTs) break // entries are time-ordered by index\n // `amendment` + `lifecycle` entries are audit-only summaries — they\n // carry no (collection, id) tuple of their own and would never match\n // the filter above. The narrow here is a type guard, not a runtime\n // skip.\n // `forget` is a subject-erasure summary with empty (collection, id) —\n // never matches the filter above; the narrow is a type guard.\n if (e.op === 'amendment' || e.op === 'lifecycle' || e.op === 'forget') continue\n // `migration` is a record rewrite (cutover) — resolve it like a put.\n latest = { op: e.op === 'migration' ? 'put' : e.op, version: e.version }\n }\n if (!latest) return null\n if (latest.op === 'delete') return null\n return this.loadVersion(id, latest.version)\n }\n\n private async resolveViaEnvelopeTs(id: string): Promise<EncryptedEnvelope | null> {\n const history = await getHistory(\n this.engine.adapter, this.engine.name, this.name, id,\n )\n const live = await this.engine.adapter.get(this.engine.name, this.name, id)\n const byVersion = new Map<number, EncryptedEnvelope>()\n for (const e of history) byVersion.set(e._v, e)\n if (live) byVersion.set(live._v, live)\n const sorted = [...byVersion.values()].sort((a, b) =>\n a._ts < b._ts ? 1 : a._ts > b._ts ? -1 : 0,\n )\n return sorted.find((e) => e._ts <= this.targetTs) ?? null\n }\n\n /**\n * Fetch the envelope for a specific version. The live record (most\n * recent put) lives in the main collection; prior versions live in\n * `_history`. We check live first because the common case after a\n * delete is that we're trying to load the last-live version from\n * history, and skipping live for the current-version case avoids a\n * redundant lookup.\n */\n private async loadVersion(id: string, version: number): Promise<EncryptedEnvelope | null> {\n const live = await this.engine.adapter.get(this.engine.name, this.name, id)\n if (live && live._v === version) return live\n\n // Direct lookup by (collection, id, version) — avoids scanning all history.\n const historyId = `${this.name}:${id}:${String(version).padStart(10, '0')}`\n return await this.engine.adapter.get(this.engine.name, '_history', historyId)\n }\n}\n\n/**\n * Scan the `_history` collection once and collect every distinct\n * `recordId` for the given collection. History keys follow the\n * shape `<collection>:<recordId>:<paddedVersion>`; we split on the\n * last two colons (delimiter-safe because `paddedVersion` is\n * exactly 10 digits).\n */\nasync function collectHistoryIds(\n adapter: NoydbStore,\n vault: string,\n collection: string,\n): Promise<string[]> {\n const all = await adapter.list(vault, '_history')\n const prefix = `${collection}:`\n const seen = new Set<string>()\n for (const key of all) {\n if (!key.startsWith(prefix)) continue\n const lastColon = key.lastIndexOf(':')\n if (lastColon <= prefix.length) continue\n const middle = key.slice(prefix.length, lastColon)\n seen.add(middle)\n }\n return [...seen]\n}\n"],"mappings":"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","names":["historyId"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/with-lookup/embeddings/cosine.ts","../src/with-lookup/embeddings/descriptor.ts","../src/with-lookup/embeddings/vector-set.ts","../src/with-lookup/search/tokenize.ts","../src/with-lookup/search/scan.ts","../src/with-lookup/search/segment.ts","../src/with-lookup/search/inverted-index.ts","../src/with-lookup/search/snippet.ts","../src/with-lookup/search/index-store.ts","../src/with-lookup/search/build-docs.ts","../src/with-lookup/search/active.ts","../src/with-lookup/search/strategy.ts","../src/with-lookup/search/collection-facade.ts"],"sourcesContent":["/** Cosine similarity in [-1,1]; 0 on zero-norm or length mismatch (no NaN). (L2) */\nexport function cosine(a: Float32Array | number[], b: Float32Array | number[]): number {\n if (a.length !== b.length) return 0\n let dot = 0, na = 0, nb = 0\n for (let i = 0; i < a.length; i++) {\n const x = a[i]!, y = b[i]!\n dot += x * y; na += x * x; nb += y * y\n }\n if (na === 0 || nb === 0) return 0\n return dot / (Math.sqrt(na) * Math.sqrt(nb))\n}\n","/** Per-collection embedding config (L2). The encode hook is host/remote — no bundled model. */\nimport { getAtPath } from '../../via/i18n/core.js'\n\nexport interface EmbeddingDescriptor {\n readonly source: string | readonly string[]\n readonly encode: (text: string) => Promise<Float32Array>\n readonly dim: number\n readonly model: string\n}\n\n/** Concatenate the record's source-field text (skips empties; supports nested/[]-wildcard paths). */\nexport function embeddingSourceText(record: Record<string, unknown>, source: string | readonly string[]): string {\n const fields = typeof source === 'string' ? [source] : source\n const parts: string[] = []\n for (const f of fields) {\n for (const leaf of getAtPath(record, f)) {\n if (typeof leaf === 'string' && leaf !== '') parts.push(leaf)\n }\n }\n return parts.join(' ')\n}\n","/** In-memory vector set for L2 semantic retrieval. Loaded once per session from\n * decrypted _vec sidecars (injected loader), brute-force cosine kNN, model-guarded. */\nimport { cosine } from './cosine.js'\nimport { EmbeddingModelMismatchError } from '../../kernel/errors.js'\n\nexport interface StoredVector { readonly id: string; readonly vec: Float32Array; readonly model: string }\nexport interface VectorHit { readonly id: string; readonly score: number }\n\nexport class VectorSet {\n private vectors: StoredVector[] | undefined\n get loaded(): boolean { return this.vectors !== undefined }\n\n async ensureLoaded(load: () => Promise<StoredVector[]>): Promise<void> {\n if (this.vectors === undefined) this.vectors = await load()\n }\n\n markDirty(): void { this.vectors = undefined }\n\n cosineTopK(query: Float32Array, k: number, opts: { minScore?: number; expectModel?: string } = {}): VectorHit[] {\n const all = this.vectors ?? []\n const minScore = opts.minScore ?? -Infinity\n const hits: VectorHit[] = []\n for (const v of all) {\n if (opts.expectModel !== undefined && v.model !== opts.expectModel) {\n throw new EmbeddingModelMismatchError(opts.expectModel, v.model)\n }\n const score = cosine(query, v.vec)\n if (score >= minScore) hits.push({ id: v.id, score })\n }\n hits.sort((a, b) => b.score - a.score)\n return hits.slice(0, k)\n }\n}\n","/**\n * Default text tokenizer for scan-mode search.\n *\n * NFKC-normalize → lowercase → split on Unicode letter/number runs. This is a\n * word-boundary tokenizer: it does **not** segment scripts written without\n * inter-word spaces (Thai, Lao, Khmer, CJK) — those collapse to one token per\n * run. For such data, a dictionary/ICU segmenter is the right `tokenizer`\n * (the engine takes one as a parameter); substring/`contains` matching is the\n * pragmatic fallback until then.\n */\nexport type Tokenizer = (text: string) => string[]\n\nconst WORD = /[\\p{L}\\p{N}]+/gu\n\nexport const tokenize: Tokenizer = (text: string): string[] => {\n if (!text) return []\n return text.normalize('NFKC').toLowerCase().match(WORD) ?? []\n}\n","/**\n * Scan-mode full-text search — ranks **already-decrypted** records by\n * BM25 against a tokenized query. Pure client-side: nothing is written to the\n * store, so this adds **zero** leakage (unlike a store-usable blind index,\n * which is a separate, gated opt-in).\n *\n * O(n) over the collection; intended for small/medium collections (the pilot's\n * scale) where moving the existing userland scan into the DB is the win.\n */\nimport { tokenize, type Tokenizer } from './tokenize.js'\n\nexport interface SearchOptions {\n /** Top-N by score (default: all matches). */\n readonly limit?: number\n /** `'any'` (default) = OR of query terms; `'all'` = every term must match. */\n readonly match?: 'any' | 'all'\n /** Treat the LAST query term as a prefix (typeahead). */\n readonly prefix?: boolean\n}\n\nexport interface SearchResult<T> {\n readonly id: string\n readonly score: number\n readonly record: T\n}\n\nexport interface SearchEntry<T> {\n readonly id: string\n readonly record: T\n}\n\nconst K1 = 1.2\nconst B = 0.75\n\n/** Coerce a field value to searchable text (numbers/booleans stringified). */\nfunction fieldText(record: unknown, field: string): string {\n const v = (record as Record<string, unknown>)[field]\n if (typeof v === 'string') return v\n if (v === null || v === undefined) return ''\n if (typeof v === 'number' || typeof v === 'boolean') return String(v)\n return ''\n}\n\nexport function searchScan<T>(\n entries: ReadonlyArray<SearchEntry<T>>,\n field: string,\n query: string,\n opts: SearchOptions = {},\n tokenizer: Tokenizer = tokenize,\n): SearchResult<T>[] {\n const queryTerms = tokenizer(query)\n if (queryTerms.length === 0) return []\n\n const match = opts.match ?? 'any'\n const usePrefix = opts.prefix ?? false\n const exactTerms = usePrefix ? queryTerms.slice(0, -1) : queryTerms\n const prefixTerm = usePrefix ? queryTerms[queryTerms.length - 1] : undefined\n\n // One tokenize pass per doc; collect corpus stats (df, avg length).\n const docs = entries.map((e) => ({ id: e.id, record: e.record, terms: tokenizer(fieldText(e.record, field)) }))\n const N = docs.length || 1\n const df = new Map<string, number>()\n let totalLen = 0\n for (const d of docs) {\n totalLen += d.terms.length\n for (const t of new Set(d.terms)) df.set(t, (df.get(t) ?? 0) + 1)\n }\n const avgdl = totalLen / N || 1\n\n // Document frequency for the prefix term: docs containing ANY term with it.\n let prefixDf = 0\n if (prefixTerm !== undefined) {\n for (const d of docs) {\n if (d.terms.some((t) => t.startsWith(prefixTerm))) prefixDf++\n }\n }\n\n const requiredCount = exactTerms.length + (prefixTerm !== undefined ? 1 : 0)\n const results: SearchResult<T>[] = []\n\n for (const d of docs) {\n const tf = new Map<string, number>()\n for (const t of d.terms) tf.set(t, (tf.get(t) ?? 0) + 1)\n\n const matched: { tf: number; df: number }[] = []\n for (const qt of exactTerms) {\n const c = tf.get(qt) ?? 0\n if (c > 0) matched.push({ tf: c, df: df.get(qt) ?? 0 })\n }\n if (prefixTerm !== undefined) {\n let ptf = 0\n for (const [t, c] of tf) if (t.startsWith(prefixTerm)) ptf += c\n if (ptf > 0) matched.push({ tf: ptf, df: prefixDf })\n }\n\n if (matched.length === 0) continue\n if (match === 'all' && matched.length < requiredCount) continue\n\n let score = 0\n for (const m of matched) {\n const idf = Math.log(1 + (N - m.df + 0.5) / (m.df + 0.5))\n const denom = m.tf + K1 * (1 - B + B * (d.terms.length / avgdl))\n score += idf * ((m.tf * (K1 + 1)) / (denom || 1))\n }\n results.push({ id: d.id, score, record: d.record })\n }\n\n results.sort((a, b) => b.score - a.score)\n return opts.limit !== undefined ? results.slice(0, opts.limit) : results\n}\n","/**\n * i18n word tokenizer for the L1 lexical index. Uses Intl.Segmenter\n * (standard ECMAScript — hub-portable) to dictionary-segment Thai/Lao/Khmer/CJK,\n * which the word-run `tokenize` cannot. Terms are matched in NFKC-lowercased form;\n * offsets index the ORIGINAL text so snippets slice the user's text.\n */\nimport type { Tokenizer } from './tokenize.js'\n\nconst SEGMENTER = new Intl.Segmenter(undefined, { granularity: 'word' })\n\nexport interface Token {\n readonly term: string\n readonly offset: number\n}\n\n/** Word-like tokens with NFKC-lowercased terms + original-text char offsets. */\nexport const segmentTokens = (text: string): Token[] => {\n const out: Token[] = []\n if (!text) return out\n for (const s of SEGMENTER.segment(text)) {\n if (s.isWordLike) out.push({ term: s.segment.normalize('NFKC').toLowerCase(), offset: s.index })\n }\n return out\n}\n\n/** Term-only tokenizer (the public `Tokenizer` shape) — for queries. */\nexport const segmentTokenizer: Tokenizer = (text: string): string[] =>\n segmentTokens(text).map((t) => t.term)\n","/**\n * In-memory inverted index for the L1 lexical retrieval layer. Built\n * client-side from already-decrypted records; nothing touches the store. BM25\n * mirrors src/search/scan.ts; multi-field with max-field combination so a record\n * ranks by its strongest field, which also supplies the snippet location.\n */\nimport { segmentTokens, segmentTokenizer } from './segment.js'\n\nconst K1 = 1.2\nconst B = 0.75\n\nexport interface IndexDoc {\n readonly id: string\n readonly fields: ReadonlyArray<{ readonly field: string; readonly locale?: string; readonly text: string }>\n}\n\nexport interface IndexHit {\n readonly id: string\n readonly score: number\n readonly field: string\n readonly locale?: string\n readonly text: string\n readonly offset: number\n}\n\nexport interface QueryOptions {\n readonly limit?: number\n readonly match?: 'any' | 'all'\n readonly prefix?: boolean\n readonly fields?: readonly string[]\n}\n\nexport interface IndexSnapshot {\n readonly v: 1\n readonly fieldStats: ReadonlyArray<[string, { df: [string, number][]; n: number; totalLen: number }]>\n readonly docs: ReadonlyArray<{\n id: string; field: string; locale?: string; text: string; len: number\n tf: [string, number][]; firstOffset: [string, number][]\n }>\n}\n\ninterface Doc {\n id: string\n field: string\n locale?: string\n text: string\n len: number\n tf: Map<string, number>\n firstOffset: Map<string, number>\n}\n\nexport class InvertedIndex {\n // per field: df (term -> #docs), N (#docs), totalLen\n private readonly fieldStats = new Map<string, { df: Map<string, number>; n: number; totalLen: number }>()\n private readonly docs: Doc[] = []\n\n static build(docs: ReadonlyArray<IndexDoc>): InvertedIndex {\n const idx = new InvertedIndex()\n for (const d of docs) {\n for (const f of d.fields) {\n const tokens = segmentTokens(f.text)\n const tf = new Map<string, number>()\n const firstOffset = new Map<string, number>()\n for (const t of tokens) {\n tf.set(t.term, (tf.get(t.term) ?? 0) + 1)\n if (!firstOffset.has(t.term)) firstOffset.set(t.term, t.offset)\n }\n const doc: Doc = { id: d.id, field: f.field, ...(f.locale !== undefined ? { locale: f.locale } : {}), text: f.text, len: tokens.length, tf, firstOffset }\n idx.docs.push(doc)\n let s = idx.fieldStats.get(f.field)\n if (!s) { s = { df: new Map(), n: 0, totalLen: 0 }; idx.fieldStats.set(f.field, s) }\n s.n += 1\n s.totalLen += doc.len\n for (const term of tf.keys()) s.df.set(term, (s.df.get(term) ?? 0) + 1)\n }\n }\n return idx\n }\n\n query(query: string, opts: QueryOptions = {}): IndexHit[] {\n const terms = segmentTokenizer(query)\n if (terms.length === 0) return []\n const usePrefix = opts.prefix ?? false\n const exact = usePrefix ? terms.slice(0, -1) : terms\n const prefix = usePrefix ? terms[terms.length - 1] : undefined\n const match = opts.match ?? 'any'\n const required = exact.length + (prefix !== undefined ? 1 : 0)\n\n // best (max-score) doc per record\n const best = new Map<string, IndexHit>()\n for (const doc of this.docs) {\n if (opts.fields !== undefined && !opts.fields.includes(doc.field)) continue\n const stats = this.fieldStats.get(doc.field)!\n const avgdl = stats.totalLen / stats.n || 1\n let score = 0\n let matchedCount = 0\n let snippetOffset = -1\n\n const scoreTerm = (tf: number, df: number, offset: number): void => {\n if (tf <= 0) return\n matchedCount += 1\n if (snippetOffset < 0 && offset >= 0) snippetOffset = offset\n const idf = Math.log(1 + (stats.n - df + 0.5) / (df + 0.5))\n const denom = tf + K1 * (1 - B + B * (doc.len / avgdl))\n score += idf * ((tf * (K1 + 1)) / (denom || 1))\n }\n\n for (const qt of exact) scoreTerm(doc.tf.get(qt) ?? 0, stats.df.get(qt) ?? 0, doc.firstOffset.get(qt) ?? -1)\n\n if (prefix !== undefined) {\n // Build a set of exact query terms so we don't double-count a term that\n // is both an exact match and starts with the prefix (defect 2 fix).\n const exactSet = new Set(exact)\n let ptf = 0\n let poff = -1\n for (const [term, c] of doc.tf) {\n if (term.startsWith(prefix) && !exactSet.has(term)) {\n ptf += c\n if (poff < 0) poff = doc.firstOffset.get(term) ?? -1\n }\n }\n if (ptf > 0) {\n // df for the prefix: count DISTINCT docs in this field that have any\n // prefix-matching term — mirrors scan.ts semantics (defect 1 fix).\n let pdf = 0\n for (const d of this.docs) {\n if (d.field === doc.field && [...d.tf.keys()].some((t) => t.startsWith(prefix))) pdf++\n }\n scoreTerm(ptf, pdf || 1, poff)\n }\n }\n\n if (matchedCount === 0) continue\n if (match === 'all' && matchedCount < required) continue\n\n const hit: IndexHit = {\n id: doc.id, score, field: doc.field, text: doc.text,\n offset: snippetOffset < 0 ? 0 : snippetOffset,\n ...(doc.locale !== undefined ? { locale: doc.locale } : {}),\n }\n const prev = best.get(doc.id)\n if (!prev || hit.score > prev.score) best.set(doc.id, hit)\n }\n\n const results = [...best.values()].sort((a, b) => b.score - a.score)\n return opts.limit !== undefined ? results.slice(0, opts.limit) : results\n }\n\n toSnapshot(): IndexSnapshot {\n return {\n v: 1,\n fieldStats: [...this.fieldStats].map(([f, s]) => [f, { df: [...s.df], n: s.n, totalLen: s.totalLen }]),\n docs: this.docs.map((d) => ({\n id: d.id, field: d.field, text: d.text, len: d.len,\n tf: [...d.tf], firstOffset: [...d.firstOffset],\n ...(d.locale !== undefined ? { locale: d.locale } : {}),\n })),\n }\n }\n\n static fromSnapshot(s: IndexSnapshot): InvertedIndex {\n const idx = new InvertedIndex()\n for (const [f, st] of s.fieldStats) idx.fieldStats.set(f, { df: new Map(st.df), n: st.n, totalLen: st.totalLen })\n for (const d of s.docs) {\n idx.docs.push({\n id: d.id, field: d.field, text: d.text, len: d.len,\n tf: new Map(d.tf), firstOffset: new Map(d.firstOffset),\n ...(d.locale !== undefined ? { locale: d.locale } : {}),\n })\n }\n return idx\n }\n}\n","/**\n * Minimal-disclosure snippet: a char-window around a match offset (L1).\n * Unicode-safe (operates on code points). `…` marks each truncated end.\n */\nexport function extractSnippet(text: string, offset: number, window = 80): string {\n const chars = Array.from(text)\n if (chars.length <= window) return text\n // offset is a UTF-16 index into `text`; map to a code-point index.\n const cpOffset = Array.from(text.slice(0, Math.max(0, offset))).length\n const half = Math.floor(window / 2)\n let start = Math.max(0, cpOffset - half)\n const end = Math.min(chars.length, start + window)\n start = Math.max(0, end - window)\n const body = chars.slice(start, end).join('')\n return `${start > 0 ? '…' : ''}${body}${end < chars.length ? '…' : ''}`\n}\n","/**\n * The index persistence seam (L1.5). MemoryIndexStore is session-scoped and\n * lazy; an opaque-blob backend implements the same interface so the\n * collection call-site is unchanged.\n */\nimport { InvertedIndex, type IndexDoc } from './inverted-index.js'\n\nexport interface IndexStore {\n ensureBuilt(build: () => ReadonlyArray<IndexDoc>): Promise<InvertedIndex>\n markDirty(): void\n flush(): Promise<void>\n readonly built: boolean\n}\n\nexport class MemoryIndexStore implements IndexStore {\n private index: InvertedIndex | undefined\n\n get built(): boolean { return this.index !== undefined }\n\n async ensureBuilt(build: () => ReadonlyArray<IndexDoc>): Promise<InvertedIndex> {\n if (this.index === undefined) this.index = InvertedIndex.build(build())\n return this.index\n }\n\n markDirty(): void { this.index = undefined }\n\n async flush(): Promise<void> { /* in-memory: nothing to persist */ }\n}\n","/**\n * Map a decrypted record's configured text fields → IndexDoc field entries\n * (L1). String, i18nText, dictKey, and blob-filename expansion. Uses\n * getAtPath for nested/[]-wildcard paths. Blob filenames are NOT inline on the\n * record — the collection pre-resolves them (one listSlots() per record, the\n * heaviest source) and feeds them to {@link buildBlobFieldEntries}.\n */\nimport { getAtPath } from '../../via/i18n/core.js'\nimport type { I18nTextDescriptor } from '../../via/i18n/core.js'\nimport type { DictKeyDescriptor, StaticDictDescriptor } from '../../via/i18n/dictionary.js'\nimport type { IndexDoc } from './inverted-index.js'\n\ntype FieldEntry = IndexDoc['fields'][number]\n\nexport function buildStringFieldEntries(\n record: Record<string, unknown>,\n textIndexes: readonly string[],\n only?: readonly string[],\n): FieldEntry[] {\n const fields = only ? textIndexes.filter((f) => only.includes(f)) : textIndexes\n const out: FieldEntry[] = []\n for (const field of fields) {\n for (const leaf of getAtPath(record, field)) {\n if (typeof leaf === 'string' && leaf !== '') out.push({ field, text: leaf })\n }\n }\n return out\n}\n\nexport function buildI18nFieldEntries(\n record: Record<string, unknown>,\n i18nFields: Record<string, I18nTextDescriptor>,\n textIndexes: readonly string[],\n only?: readonly string[],\n): FieldEntry[] {\n const fields = (only ? textIndexes.filter((f) => only.includes(f)) : textIndexes).filter((f) => f in i18nFields)\n const out: FieldEntry[] = []\n for (const field of fields) {\n for (const leaf of getAtPath(record, field)) {\n if (!leaf || typeof leaf !== 'object' || Array.isArray(leaf)) continue\n for (const [locale, val] of Object.entries(leaf as Record<string, unknown>)) {\n if (typeof val === 'string' && val !== '') out.push({ field, locale, text: val })\n }\n }\n }\n return out\n}\n\n/** label map: field -> (key -> { locale -> label }). Precomputed in the collection (async for dynamic dicts). */\nexport function buildDictKeyFieldEntries(\n record: Record<string, unknown>,\n dictKeyFields: Record<string, DictKeyDescriptor | StaticDictDescriptor>,\n labelMaps: Map<string, Map<string, Record<string, string>>>,\n textIndexes: readonly string[],\n only?: readonly string[],\n): FieldEntry[] {\n const fields = (only ? textIndexes.filter((f) => only.includes(f)) : textIndexes).filter((f) => f in dictKeyFields)\n const out: FieldEntry[] = []\n for (const field of fields) {\n const map = labelMaps.get(field)\n if (!map) continue\n for (const leaf of getAtPath(record, field)) {\n const keys = typeof leaf === 'string' ? [leaf] : Array.isArray(leaf) ? leaf.filter((k): k is string => typeof k === 'string') : []\n for (const key of keys) {\n const labels = map.get(key)\n if (!labels) continue\n for (const [locale, label] of Object.entries(labels)) {\n if (label !== '') out.push({ field, locale, text: label })\n }\n }\n }\n }\n return out\n}\n\n/**\n * Blob filenames precomputed in the collection (`field -> filenames[]`, from one\n * async `listSlots()` per record — the heaviest source, see {@link buildBlobFieldEntries}'s\n * caller). Bytes are never tokenized; only the slot `filename` is indexed.\n */\nexport function buildBlobFieldEntries(filenamesByField: Map<string, string[]>): FieldEntry[] {\n const out: FieldEntry[] = []\n for (const [field, names] of filenamesByField) {\n for (const name of names) if (name !== '') out.push({ field, text: name })\n }\n return out\n}\n","/**\n * Enable the search / retrieval capability.\n * Pass to `createNoydb({ searchStrategy: withSearch() })` to make a collection's\n * `search` / `retrieve` / `similarTo` / `warmIndex` / `flushIndex` methods live,\n * and to enable the put()-time embedding-vector compute for collections that\n * declare an `embeddings` config. The search/retrieval engine is dynamically\n * imported here, so it stays out of the floor bundle until opted in.\n */\nimport type { SearchStrategy } from './strategy.js'\n\nexport function withSearch(): SearchStrategy {\n return {\n async search(ctx, field, query, opts) {\n const { search } = await import('./collection-facade.js')\n return search(ctx, field, query, opts)\n },\n async retrieve(ctx, query, opts) {\n const { retrieve } = await import('./collection-facade.js')\n return retrieve(ctx, query, opts)\n },\n async similarTo(ctx, vector, opts) {\n const { similarTo } = await import('./collection-facade.js')\n return similarTo(ctx, vector, opts)\n },\n async warmIndex(ctx) {\n const { warmIndex } = await import('./collection-facade.js')\n return warmIndex(ctx)\n },\n async flushIndex(ctx) {\n const { flushIndex } = await import('./collection-facade.js')\n return flushIndex(ctx)\n },\n async embedOnWrite(ctx, id, record, version) {\n const { embedOnWrite } = await import('./collection-facade.js')\n return embedOnWrite(ctx, id, record, version)\n },\n }\n}\n","/**\n * Search capability strategy — the on-demand collection-level retrieval\n * operations the `Collection` routes through: scan-mode full-text `search`,\n * unified `retrieve` (lexical | semantic | hybrid), raw-vector `similarTo`, and\n * the lexical-index lifecycle (`warmIndex` / `flushIndex`). The active engine\n * ({@link withSearch}) dynamically imports the search/retrieval facade (keeping\n * it out of the floor bundle); {@link NO_SEARCH} throws.\n *\n * The embedding write-hook (`embedOnWrite`) is paired here too: opting into\n * `withSearch()` enables both the query surface AND the put()-time vector\n * compute — a vector that no gated `similarTo` / semantic `retrieve` could read\n * is dead weight, so embedding compute is not separately gatable. `Collection`\n * always assembles the per-call {@link SearchContext} and delegates here, so an\n * un-opted-in caller hits `NO_SEARCH`'s throw.\n * @internal\n */\nimport type { SearchContext } from './collection-facade.js'\nimport type { SearchOptions, SearchResult } from './index.js'\nimport type { RetrieveOptions, RetrieveHit } from './retrieve-types.js'\nimport { SearchNotEnabledError } from '../../kernel/errors.js'\n\nexport interface SearchStrategy {\n search<T>(ctx: SearchContext<T>, field: string, query: string, opts?: SearchOptions): Promise<SearchResult<T>[]>\n retrieve<T>(ctx: SearchContext<T>, query: string, opts?: RetrieveOptions<T>): Promise<RetrieveHit<T>[]>\n similarTo<T>(ctx: SearchContext<T>, vector: Float32Array, opts?: { k?: number; minScore?: number; includeRecord?: boolean }): Promise<RetrieveHit<T>[]>\n warmIndex<T>(ctx: SearchContext<T>): Promise<void>\n flushIndex<T>(ctx: SearchContext<T>): Promise<void>\n embedOnWrite<T>(ctx: SearchContext<T>, id: string, record: T, version: number): Promise<void>\n}\n\n/**\n * No-op stub — the floor default. Every capability method (and the embedding\n * write-hook) throws {@link SearchNotEnabledError}; opt in with\n * `searchStrategy: withSearch()` in createNoydb. @internal\n */\nexport const NO_SEARCH: SearchStrategy = {\n async search() { throw new SearchNotEnabledError() },\n async retrieve() { throw new SearchNotEnabledError() },\n async similarTo() { throw new SearchNotEnabledError() },\n async warmIndex() { throw new SearchNotEnabledError() },\n async flushIndex() { throw new SearchNotEnabledError() },\n async embedOnWrite() { throw new SearchNotEnabledError() },\n}\n","/**\n * Collection-level search / retrieval (`search` / `retrieve` / `similarTo` +\n * the lexical-index build/flush/warm machinery).\n *\n * This is the retrieval surface: a pure client-side lexical scan\n * (`search`), the persisted-or-in-memory inverted-index lifecycle\n * (`flushIndex` / `warmIndex` / `buildRetrievalDocs` + the dict-label / blob-\n * filename resolvers that feed it), and the lexical / semantic / hybrid\n * `retrieve` fan-out plus raw-vector kNN (`similarTo`). None of it touches the\n * write path — it reads the live eager cache and the encrypted `_vec` / `_ftindex`\n * side-cars.\n *\n * Every function takes a small {@link SearchContext} instead of `this`,\n * mirroring the `record-keys/` siblings.\n *\n * The `cache` is the SAME `Map` reference `Collection` owns (passed by\n * reference, never copied) so the index always builds over the live working\n * set. {@link buildPersistedIndexCallbacks} is special: it is invoked from the\n * `Collection` constructor *before* `this.codec` exists, so it takes a context\n * THUNK and resolves the context lazily at each callback invocation.\n *\n * Internal service — not exported as a `@noy-db/hub/*` subpath.\n */\nimport type { NoydbStore } from '../../kernel/types.js'\nimport type { RecordCodec } from '../../kernel/enclave/index.js'\nimport { stripI18nFilled, type I18nTextDescriptor } from '../../via/i18n/core.js'\nimport { isStaticDictDescriptor, type DictKeyDescriptor, type StaticDictDescriptor, type DictionaryHandle } from '../../via/i18n/dictionary.js'\nimport type { BlobSet } from '../../with-shape/blobs/blob-set.js'\nimport type { BlobFieldsConfig } from '../../with-shape/blobs/blob-compaction.js'\nimport type { Query } from '../../kernel/query/index.js'\nimport { embeddingSourceText, type VectorSet, type EmbeddingDescriptor, type StoredVector } from '../embeddings/index.js'\nimport { EmbeddingDimMismatchError } from '../../kernel/errors.js'\nimport { searchScan, fuseRetrieval, type SearchOptions, type SearchResult } from './index.js'\nimport type { IndexStore } from './index-store.js'\nimport type { PersistedIndexCallbacks } from './persisted-index-store.js'\nimport { extractSnippet } from './snippet.js'\nimport { buildStringFieldEntries, buildI18nFieldEntries, buildDictKeyFieldEntries, buildBlobFieldEntries } from './build-docs.js'\nimport type { IndexDoc, IndexHit } from './inverted-index.js'\nimport type { RetrieveOptions, RetrieveHit } from './retrieve-types.js'\n\n/** Everything the moving search/retrieval methods touched on `this.*`. */\nexport interface SearchContext<T> {\n /** Collection name — error context + `_ftindex` row key. */\n readonly name: string\n /** Vault namespace the side-cars (`_vec`, `_ftindex`) live under. */\n readonly vault: string\n /** The ciphertext store. */\n readonly adapter: NoydbStore\n /** The record codec — decrypts the `_vec` / `_ftindex` side-car bodies. */\n readonly codec: RecordCodec<T>\n /** The eager working-set cache (SHARED `Map` reference, never copied). */\n readonly cache: Map<string, { record: T; version: number }>\n /** True in lazy mode — search/retrieve/warm require eager mode. */\n readonly lazy: boolean\n /** Declared text-index fields, or undefined. */\n readonly textIndexes: readonly string[] | undefined\n /** Declared i18n fields, or undefined. */\n readonly i18nFields: Record<string, I18nTextDescriptor> | undefined\n /** Declared dictionary-key fields, or undefined. */\n readonly dictKeyFields: Record<string, DictKeyDescriptor | StaticDictDescriptor> | undefined\n /** Declared blob fields, or undefined. */\n readonly blobFields: BlobFieldsConfig | undefined\n /** Dictionary handle resolver (dynamic dict-key labels), or undefined. */\n readonly getDictionary: ((name: string) => Promise<DictionaryHandle>) | undefined\n /** The lexical inverted-index store (in-memory or persisted), or undefined. */\n readonly searchIndexStore: IndexStore | undefined\n /** The vector set for semantic retrieval, or undefined. */\n readonly vectorSet: VectorSet | undefined\n /** The embeddings descriptor, or undefined. */\n readonly embeddings: EmbeddingDescriptor | undefined\n /** Hydrate the eager cache before reading it. */\n ensureHydrated(): Promise<void>\n /** Open the blob facade for a record (used to list indexed blob filenames). */\n blob(id: string): BlobSet\n}\n\n/**\n * Client-side lexical scan over the live eager cache. Eager mode only;\n * nothing searchable is written to the store.\n */\nexport async function search<T>(ctx: SearchContext<T>, field: string, query: string, opts: SearchOptions = {}): Promise<SearchResult<T>[]> {\n if (ctx.lazy) {\n throw new Error(\n `Collection \"${ctx.name}\": search() (scan mode) requires eager mode (prefetch: true). ` +\n `A store-usable blind index for lazy / at-scale search is a separate gated opt-in (#308).`,\n )\n }\n await ctx.ensureHydrated()\n const entries: { id: string; record: T }[] = []\n // Strip the internal densify marker from the user-facing records.\n // Non-mutating: never touches the cached record object. The search index\n // is built over the same (marker-free) record, which is fine — the marker\n // is never a searchable field.\n for (const [id, e] of ctx.cache) entries.push({ id, record: stripI18nFilled(e.record as Record<string, unknown>) as T })\n return searchScan(entries, field, query, opts)\n}\n\n/** L1 — build IndexDoc[] for the configured text fields over the live cache. */\nexport function buildRetrievalDocs<T>(\n ctx: SearchContext<T>,\n labelMaps: Map<string, Map<string, Record<string, string>>>,\n blobFilenames: Map<string, Map<string, string[]>>,\n only?: readonly string[],\n): IndexDoc[] {\n const docs: IndexDoc[] = []\n for (const [id, e] of ctx.cache) {\n const rec = stripI18nFilled(e.record as Record<string, unknown>)\n const fields = buildStringFieldEntries(rec, ctx.textIndexes ?? [], only)\n if (ctx.i18nFields) fields.push(...buildI18nFieldEntries(rec, ctx.i18nFields, ctx.textIndexes ?? [], only))\n if (ctx.dictKeyFields) fields.push(...buildDictKeyFieldEntries(rec, ctx.dictKeyFields, labelMaps, ctx.textIndexes ?? [], only))\n const blobNames = blobFilenames.get(id)\n if (blobNames) fields.push(...buildBlobFieldEntries(blobNames))\n if (fields.length > 0) docs.push({ id, fields })\n }\n return docs\n}\n\n/** L1 — true iff any configured text index is also a blob field (gates ALL slot I/O). */\nexport function hasIndexedBlobFields<T>(ctx: SearchContext<T>, only?: readonly string[]): boolean {\n if (!ctx.blobFields || !ctx.textIndexes) return false\n const fields = only ? ctx.textIndexes.filter((f) => only.includes(f)) : ctx.textIndexes\n return fields.some((f) => f in ctx.blobFields!)\n}\n\n/**\n * L1 — resolve `recordId -> (blobField -> filenames[])` by listing slots\n * for the configured blob fields of each cached record. Blob slot metadata is\n * NOT inline on the record: it lives in a separate `_blob_slots_*` collection,\n * so this costs ONE `blob(id).list()` (a `listSlots`) per record at build time\n * — the heaviest indexing source. Fully gated by {@link hasIndexedBlobFields};\n * non-blob (and blob-but-not-indexed) collections do ZERO slot I/O.\n */\nasync function resolveBlobFilenames<T>(ctx: SearchContext<T>, only?: readonly string[]): Promise<Map<string, Map<string, string[]>>> {\n const out = new Map<string, Map<string, string[]>>()\n if (!hasIndexedBlobFields(ctx, only)) return out\n const indexed = (only ? ctx.textIndexes!.filter((f) => only.includes(f)) : ctx.textIndexes!)\n .filter((f) => f in ctx.blobFields!)\n const indexedSet = new Set(indexed)\n for (const id of ctx.cache.keys()) {\n let slots\n try {\n slots = await ctx.blob(id).list()\n } catch {\n continue\n }\n let byField: Map<string, string[]> | undefined\n for (const slot of slots) {\n if (!indexedSet.has(slot.name) || !slot.filename) continue\n if (!byField) { byField = new Map(); out.set(id, byField) }\n const names = byField.get(slot.name)\n if (names) names.push(slot.filename)\n else byField.set(slot.name, [slot.filename])\n }\n }\n return out\n}\n\n/** L1 — field -> (key -> {locale->label}) for dictKey fields; static from table, dynamic via getDictionary().list(). */\nasync function resolveDictLabelMaps<T>(ctx: SearchContext<T>): Promise<Map<string, Map<string, Record<string, string>>>> {\n const maps = new Map<string, Map<string, Record<string, string>>>()\n if (!ctx.dictKeyFields || !ctx.textIndexes) return maps\n for (const field of ctx.textIndexes) {\n const desc = ctx.dictKeyFields[field]\n if (!desc) continue\n const m = new Map<string, Record<string, string>>()\n if (isStaticDictDescriptor(desc)) {\n for (const [key, labels] of Object.entries(desc.table)) m.set(key, labels as Record<string, string>)\n } else {\n if (ctx.getDictionary) {\n const handle = await ctx.getDictionary(desc.name)\n for (const e of await handle.list()) m.set(e.key, e.labels)\n }\n }\n maps.set(field, m)\n }\n return maps\n}\n\n/** L1.5 — force-persist the lexical index now (e.g. on save/idle). Persists only when textIndexPersist is enabled; a no-op otherwise. */\nexport async function flushIndex<T>(ctx: SearchContext<T>): Promise<void> {\n if (!ctx.searchIndexStore) return\n await ctx.ensureHydrated()\n const labelMaps = await resolveDictLabelMaps(ctx)\n const blobFilenames = await resolveBlobFilenames(ctx)\n await ctx.searchIndexStore.ensureBuilt(() => buildRetrievalDocs(ctx, labelMaps, blobFilenames))\n await ctx.searchIndexStore.flush?.()\n}\n\n/** L2 — load + decrypt all _vec sidecars into StoredVector[] for the VectorSet. */\nfunction buildVectorLoad<T>(ctx: SearchContext<T>): () => Promise<StoredVector[]> {\n return async () => {\n const ids = await ctx.adapter.list(ctx.vault, '_vec')\n const out: StoredVector[] = []\n for (const id of ids) {\n const env = await ctx.adapter.get(ctx.vault, '_vec', id)\n if (!env) continue\n const body = await ctx.codec.decryptJsonString(env)\n if (body === null) continue\n const parsed = JSON.parse(body) as { vec: number[]; model: string }\n out.push({ id, vec: new Float32Array(parsed.vec), model: parsed.model })\n }\n return out\n }\n}\n\n/**\n * L1.5 — build the PersistedIndexCallbacks bridge: crypto lives here\n * (collection has getDEK / encryptJsonString / decryptJsonString / adapter),\n * the index store itself is crypto-free.\n *\n * Fingerprint encoding: body-wrap approach — save(json, fp) stores\n * JSON.stringify({ fp, idx: json }) as the encrypted body so the standard\n * EncryptedEnvelope shape is never extended. load() decrypts and JSON.parses\n * the wrapper back out.\n *\n * Cache shape: ctx.cache stores { record, version } — currentFingerprint()\n * iterates over e.version.\n *\n * NOTE: this factory is invoked from the `Collection` constructor *before*\n * `this.codec` is assigned, so it takes a context THUNK and resolves the\n * context lazily inside each callback — by the time a callback actually runs,\n * the codec and cache are fully wired.\n */\nexport function buildPersistedIndexCallbacks<T>(provideCtx: () => SearchContext<T>): PersistedIndexCallbacks {\n const FT = '_ftindex'\n return {\n load: async () => {\n const ctx = provideCtx()\n const env = await ctx.adapter.get(ctx.vault, FT, ctx.name)\n if (!env) return null\n const body = await ctx.codec.decryptJsonString(env)\n if (body === null) return null\n try {\n const wrapped = JSON.parse(body) as { fp: { count: number; maxVersion: number }; idx: string }\n return { json: wrapped.idx, fingerprint: wrapped.fp }\n } catch {\n return null\n }\n },\n save: async (json, fp) => {\n const ctx = provideCtx()\n const body = JSON.stringify({ fp, idx: json })\n const env = await ctx.codec.encryptJsonString(body, fp.count)\n await ctx.adapter.put(ctx.vault, FT, ctx.name, env)\n },\n remove: async () => { const ctx = provideCtx(); await ctx.adapter.delete(ctx.vault, FT, ctx.name) },\n currentFingerprint: () => {\n const ctx = provideCtx()\n let maxVersion = 0\n for (const e of ctx.cache.values()) if (e.version > maxVersion) maxVersion = e.version\n return { count: ctx.cache.size, maxVersion }\n },\n }\n}\n\n/** L1 — pre-build the lexical index (e.g. on open) so the first retrieve() pays no build scan. */\nexport async function warmIndex<T>(ctx: SearchContext<T>): Promise<void> {\n if (!ctx.searchIndexStore) return\n if (ctx.lazy) {\n throw new Error(\n `Collection \"${ctx.name}\": warmIndex() requires eager mode (prefetch: true).`,\n )\n }\n await ctx.ensureHydrated()\n const built = ctx.searchIndexStore.built\n const labelMaps = built ? new Map() : await resolveDictLabelMaps(ctx)\n const blobFilenames = built ? new Map() : await resolveBlobFilenames(ctx)\n await ctx.searchIndexStore.ensureBuilt(() => buildRetrievalDocs(ctx, labelMaps, blobFilenames))\n}\n\n/** Retrieval. mode: 'lexical' (default) | 'semantic' (L2) | 'hybrid' (L3). */\nexport async function retrieve<T>(ctx: SearchContext<T>, query: string, opts: RetrieveOptions<T> = {}): Promise<RetrieveHit<T>[]> {\n const hits =\n opts.mode === 'semantic' ? await retrieveSemantic(ctx, query, opts)\n : opts.mode === 'hybrid' ? await retrieveHybrid(ctx, query, opts)\n : await retrieveLexical(ctx, query, opts)\n return opts.within ? applyWithin(hits, opts.within) : hits\n}\n\n/** L3 — keep only hits whose id matches the structured query, re-rank 1-based. */\nfunction applyWithin<T>(hits: RetrieveHit<T>[], within: Query<T>): RetrieveHit<T>[] {\n const ids = new Set(within._idArray())\n return hits.filter(h => ids.has(h.id)).map((h, i) => ({ ...h, rank: i + 1 }))\n}\n\n/** L1 — client-side lexical retrieval; ranked { id, score, field, snippet, locale? }. */\nasync function retrieveLexical<T>(ctx: SearchContext<T>, query: string, opts: RetrieveOptions<T>): Promise<RetrieveHit<T>[]> {\n if (!ctx.searchIndexStore) {\n throw new Error(`Collection \"${ctx.name}\": retrieve() requires a textIndexes config.`)\n }\n if (ctx.lazy) {\n throw new Error(\n `Collection \"${ctx.name}\": retrieve() requires eager mode (prefetch: true).`,\n )\n }\n await ctx.ensureHydrated()\n const built = ctx.searchIndexStore.built\n const labelMaps = built ? new Map() : await resolveDictLabelMaps(ctx)\n const blobFilenames = built ? new Map() : await resolveBlobFilenames(ctx)\n const index = await ctx.searchIndexStore.ensureBuilt(() => buildRetrievalDocs(ctx, labelMaps, blobFilenames))\n const hits = index.query(query, {\n ...(opts.limit !== undefined ? { limit: opts.limit } : {}),\n ...(opts.match ? { match: opts.match } : {}),\n ...(opts.prefix ? { prefix: opts.prefix } : {}),\n ...(opts.fields ? { fields: opts.fields } : {}),\n })\n const window = opts.snippetWindow ?? 80\n return hits.map((h: IndexHit, i: number) => {\n const base: RetrieveHit<T> = {\n id: h.id,\n score: h.score,\n rank: i + 1,\n field: h.field,\n snippet: extractSnippet(h.text, h.offset, window),\n ...(h.locale !== undefined ? { locale: h.locale } : {}),\n ...(opts.includeRecord\n ? (() => {\n const e = ctx.cache.get(h.id)\n return e ? { record: stripI18nFilled(e.record as Record<string, unknown>) as T } : {}\n })()\n : {}),\n }\n return base\n })\n}\n\n/** L3 — hybrid: fuse lexical (L1) + semantic (L2) by RRF. Requires embeddings. */\nasync function retrieveHybrid<T>(ctx: SearchContext<T>, query: string, opts: RetrieveOptions<T>): Promise<RetrieveHit<T>[]> {\n if (!ctx.embeddings) {\n throw new Error(`Collection \"${ctx.name}\": retrieve({mode:'hybrid'}) requires an embeddings config.`)\n }\n const [lex, sem] = await Promise.all([\n retrieveLexical(ctx, query, opts),\n retrieveSemantic(ctx, query, opts),\n ])\n return fuseRetrieval([lex, sem], opts.limit !== undefined ? { limit: opts.limit } : {})\n}\n\n/** L2 — semantic branch of retrieve(): encode query → similarTo(). */\nasync function retrieveSemantic<T>(ctx: SearchContext<T>, query: string, opts: RetrieveOptions<T>): Promise<RetrieveHit<T>[]> {\n if (!ctx.embeddings) throw new Error(`Collection \"${ctx.name}\": retrieve({mode:'semantic'}) requires an embeddings config.`)\n if (ctx.lazy) throw new Error(`Collection \"${ctx.name}\": retrieve() requires eager mode (prefetch: true).`)\n const qVec = await ctx.embeddings.encode(query)\n return similarTo(ctx, qVec, {\n ...(opts.limit !== undefined ? { k: opts.limit } : {}),\n ...(opts.minScore !== undefined ? { minScore: opts.minScore } : {}),\n ...(opts.includeRecord ? { includeRecord: true } : {}),\n })\n}\n\n/** L2 — raw-vector kNN over the encrypted vector set (decrypted in the trusted tier).\n * Snippet is '' for vector hits in v1 (semantic match isn't span-located). */\nexport async function similarTo<T>(ctx: SearchContext<T>, vector: Float32Array, opts: { k?: number; minScore?: number; includeRecord?: boolean } = {}): Promise<RetrieveHit<T>[]> {\n if (!ctx.embeddings || !ctx.vectorSet) throw new Error(`Collection \"${ctx.name}\": similarTo() requires an embeddings config.`)\n if (ctx.lazy) throw new Error(`Collection \"${ctx.name}\": similarTo() requires eager mode (prefetch: true).`)\n await ctx.ensureHydrated()\n await ctx.vectorSet.ensureLoaded(buildVectorLoad(ctx))\n const hits = ctx.vectorSet.cosineTopK(vector, opts.k ?? 10, {\n ...(opts.minScore !== undefined ? { minScore: opts.minScore } : {}),\n expectModel: ctx.embeddings.model,\n })\n return hits.map((h, i) => {\n const base: RetrieveHit<T> = { id: h.id, score: h.score, rank: i + 1, field: '(vector)', snippet: '' }\n if (opts.includeRecord) { const e = ctx.cache.get(h.id); if (e) (base as { record?: T }).record = stripI18nFilled(e.record as Record<string, unknown>) as T }\n return base\n })\n}\n\n/**\n * L2 — the embedding write-hook: derive a record's embedding vector at\n * write and persist it as the encrypted `_vec` side-car. Routed through the\n * search strategy so it runs only when `withSearch()` is opted in — computing\n * vectors that no gated `similarTo` / semantic `retrieve` could query would be\n * dead weight, so the compute is paired with the search capability. The caller\n * (`Collection.put`) only invokes this when `embeddings` is declared.\n */\nexport async function embedOnWrite<T>(ctx: SearchContext<T>, id: string, record: T, version: number): Promise<void> {\n if (!ctx.embeddings) return\n const text = embeddingSourceText(record as Record<string, unknown>, ctx.embeddings.source)\n const vec = await ctx.embeddings.encode(text)\n if (vec.length !== ctx.embeddings.dim) throw new EmbeddingDimMismatchError('embeddings', ctx.embeddings.dim, vec.length)\n const body = JSON.stringify({ vec: Array.from(vec), model: ctx.embeddings.model, dim: ctx.embeddings.dim })\n const vecEnv = await ctx.codec.encryptJsonString(body, version)\n await ctx.adapter.put(ctx.vault, '_vec', id, vecEnv)\n ctx.vectorSet?.markDirty()\n}\n"],"mappings":"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","names":["K1","B","search","retrieve","similarTo","warmIndex","flushIndex","embedOnWrite"]}
|