@noy-db/hub 0.4.0-pre.1 → 0.4.0-pre.10
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/README.md +3 -4
- package/dist/api-ZDKTWNBB.js +20 -0
- package/dist/attestation/index.js +18 -18
- package/dist/{backup-LU2DTZTI.js → backup-2UX7PRM5.js} +13 -13
- package/dist/blobs/index.js +30 -15
- package/dist/blobs/index.js.map +1 -1
- package/dist/broker/index.js +12 -12
- package/dist/broker/index.js.map +1 -1
- package/dist/cargo/index.js +53 -43
- package/dist/{chunk-IY23KFNZ.js → chunk-35NMVJ7I.js} +3 -3
- package/dist/{chunk-S3BFKGET.js → chunk-3HUYRN24.js} +4 -4
- package/dist/chunk-3HUYRN24.js.map +1 -0
- package/dist/{walk-XS3PKM6I.js → chunk-3V3XR4S4.js} +4 -13
- package/dist/{walk-XS3PKM6I.js.map → chunk-3V3XR4S4.js.map} +1 -1
- package/dist/{chunk-RTEK4C4I.js → chunk-4JQK3L4V.js} +2 -2
- package/dist/{chunk-3ELCWU56.js → chunk-4ZKNC6A6.js} +2 -2
- package/dist/{chunk-VQNJ7UZL.js → chunk-55LKVALY.js} +106 -10
- package/dist/chunk-55LKVALY.js.map +1 -0
- package/dist/{chunk-VAIS3SOM.js → chunk-55LX6FSX.js} +2 -2
- package/dist/chunk-5D2ALSM5.js +19 -0
- package/dist/chunk-5D2ALSM5.js.map +1 -0
- package/dist/{chunk-6HPG2YNX.js → chunk-5DRROK5W.js} +2 -2
- package/dist/{chunk-S6Q37VGE.js → chunk-5GQEU4DN.js} +2 -2
- package/dist/chunk-5JOFWL4G.js +25 -0
- package/dist/chunk-5JOFWL4G.js.map +1 -0
- package/dist/{chunk-TOPYT5U5.js → chunk-63FE525P.js} +6 -6
- package/dist/chunk-6LJY7X5A.js +18 -0
- package/dist/chunk-6LJY7X5A.js.map +1 -0
- package/dist/{chunk-JVBO4SZL.js → chunk-6UBZ6I5Z.js} +2 -2
- package/dist/{chunk-BOKIKJJB.js → chunk-6ZNSB3H6.js} +5 -17
- package/dist/chunk-6ZNSB3H6.js.map +1 -0
- package/dist/{chunk-BMQWTQZ4.js → chunk-7YVBQJ7K.js} +13 -355
- package/dist/chunk-7YVBQJ7K.js.map +1 -0
- package/dist/{chunk-UFEVO57O.js → chunk-ABS7FMMD.js} +6 -6
- package/dist/chunk-AFHQATY4.js +47 -0
- package/dist/chunk-AFHQATY4.js.map +1 -0
- package/dist/{chunk-HOONYZY2.js → chunk-AKKRXT23.js} +7 -7
- package/dist/chunk-AKKRXT23.js.map +1 -0
- package/dist/{chunk-DDHM2TLX.js → chunk-AT2JJEKJ.js} +4 -4
- package/dist/chunk-AT2JJEKJ.js.map +1 -0
- package/dist/{chunk-M75ZZHSR.js → chunk-BLBAQRBM.js} +2 -2
- package/dist/{chunk-3SV2EPMN.js → chunk-BLCWSJLN.js} +88 -81
- package/dist/chunk-BLCWSJLN.js.map +1 -0
- package/dist/chunk-CADUYBQD.js +151 -0
- package/dist/chunk-CADUYBQD.js.map +1 -0
- package/dist/{chunk-G6EQYAL6.js → chunk-CI32CAFS.js} +5 -5
- package/dist/{chunk-FH52K7EG.js → chunk-CUZLNGD5.js} +2 -6
- package/dist/{chunk-FH52K7EG.js.map → chunk-CUZLNGD5.js.map} +1 -1
- package/dist/{chunk-2P7EGNKF.js → chunk-CXQW2NWO.js} +145 -3
- package/dist/chunk-CXQW2NWO.js.map +1 -0
- package/dist/{chunk-6B4DYGWO.js → chunk-DABACXEF.js} +3 -3
- package/dist/{chunk-F6T6L2UK.js → chunk-DMH3VZU5.js} +4 -4
- package/dist/chunk-DSDXAKIP.js +50 -0
- package/dist/chunk-DSDXAKIP.js.map +1 -0
- package/dist/{chunk-MQ6WOPSY.js → chunk-DZ2JXHWK.js} +5 -5
- package/dist/chunk-DZFQVICS.js +23 -0
- package/dist/chunk-DZFQVICS.js.map +1 -0
- package/dist/chunk-E23UGFVC.js +63 -0
- package/dist/chunk-E23UGFVC.js.map +1 -0
- package/dist/{chunk-UBNCR3YK.js → chunk-EE7UHLKH.js} +4 -4
- package/dist/chunk-EIPVYUEP.js +654 -0
- package/dist/chunk-EIPVYUEP.js.map +1 -0
- package/dist/{chunk-EGCRBCNA.js → chunk-EKRSCRNM.js} +3 -3
- package/dist/{chunk-YMUGBZN2.js → chunk-FQ5CHJR7.js} +1 -1
- package/dist/chunk-FQ5CHJR7.js.map +1 -0
- package/dist/{chunk-LB6OH6K2.js → chunk-FQZ6XTQ7.js} +17 -20
- package/dist/chunk-FQZ6XTQ7.js.map +1 -0
- package/dist/{chunk-IRQY7IR5.js → chunk-FRMPM7WG.js} +4 -4
- package/dist/{chunk-DVUZMT2W.js → chunk-G2JUIDFA.js} +9 -9
- package/dist/{chunk-DVUZMT2W.js.map → chunk-G2JUIDFA.js.map} +1 -1
- package/dist/{chunk-RND5ZPNP.js → chunk-G6WWZNJP.js} +13 -13
- package/dist/chunk-G6WWZNJP.js.map +1 -0
- package/dist/chunk-GJW4HX2O.js +1 -0
- package/dist/{chunk-T6GU5PPZ.js → chunk-GU3IP74F.js} +6 -6
- package/dist/{chunk-5OI6BR4H.js → chunk-GWWOGNBK.js} +308 -18
- package/dist/chunk-GWWOGNBK.js.map +1 -0
- package/dist/{chunk-UNCOC7QH.js → chunk-H2GPHUZD.js} +12 -13
- package/dist/chunk-H2GPHUZD.js.map +1 -0
- package/dist/{chunk-7CI6CP7Z.js → chunk-HMU5P6RL.js} +5 -5
- package/dist/chunk-HMU5P6RL.js.map +1 -0
- package/dist/{chunk-YJV2UZ7H.js → chunk-I5GEJX3R.js} +5 -5
- package/dist/chunk-I5GEJX3R.js.map +1 -0
- package/dist/{chunk-GWKAVKHI.js → chunk-IG6KUWBX.js} +2 -2
- package/dist/chunk-IG6KUWBX.js.map +1 -0
- package/dist/{chunk-MTQPRQHB.js → chunk-IPUG56GJ.js} +15 -5
- package/dist/{chunk-MTQPRQHB.js.map → chunk-IPUG56GJ.js.map} +1 -1
- package/dist/{chunk-SMIRGMS7.js → chunk-IXNCZTWA.js} +2 -2
- package/dist/{chunk-RM2XV574.js → chunk-IXTSNGYY.js} +3 -3
- package/dist/{chunk-KUPKLSX5.js → chunk-IYZISPGD.js} +7 -5
- package/dist/chunk-IYZISPGD.js.map +1 -0
- package/dist/{chunk-SMGEYW6G.js → chunk-JDOMW53O.js} +26 -16
- package/dist/chunk-JDOMW53O.js.map +1 -0
- package/dist/{chunk-PK6QCH2C.js → chunk-JJZGIE4U.js} +6 -5
- package/dist/{chunk-DRWBEDYO.js → chunk-JYJFGD2H.js} +2 -2
- package/dist/{chunk-TAGR72IR.js → chunk-KRCBZYTZ.js} +26 -177
- package/dist/chunk-KRCBZYTZ.js.map +1 -0
- package/dist/{chunk-HPUWOVR7.js → chunk-L2DGWBCT.js} +14 -14
- package/dist/chunk-L2DGWBCT.js.map +1 -0
- package/dist/{chunk-VEALDPHW.js → chunk-L3YYLT4E.js} +15 -2
- package/dist/chunk-L3YYLT4E.js.map +1 -0
- package/dist/{chunk-A7JJLVGH.js → chunk-LNPUSMZL.js} +29 -31
- package/dist/chunk-LNPUSMZL.js.map +1 -0
- package/dist/{chunk-KUIB4B5Q.js → chunk-LNZKOUJR.js} +2 -2
- package/dist/{chunk-IM3QVF53.js → chunk-MBKVNOJS.js} +6 -6
- package/dist/chunk-MCHBCNCE.js +367 -0
- package/dist/chunk-MCHBCNCE.js.map +1 -0
- package/dist/{chunk-VCBHAE4R.js → chunk-MHMLXJ3I.js} +2 -2
- package/dist/chunk-MHMLXJ3I.js.map +1 -0
- package/dist/{chunk-WNGGJWF7.js → chunk-MSMJJB4J.js} +2 -2
- package/dist/chunk-MSMJJB4J.js.map +1 -0
- package/dist/{chunk-T36RFODW.js → chunk-MXUT7FTE.js} +2 -2
- package/dist/chunk-MXUT7FTE.js.map +1 -0
- package/dist/{chunk-BGK233EA.js → chunk-N4BBNYIB.js} +11 -9
- package/dist/chunk-N4BBNYIB.js.map +1 -0
- package/dist/{chunk-3PF6CRDT.js → chunk-NFIBXF4V.js} +1082 -1583
- package/dist/chunk-NFIBXF4V.js.map +1 -0
- package/dist/{chunk-LOF2W3JU.js → chunk-NFNJLRY7.js} +368 -52
- package/dist/chunk-NFNJLRY7.js.map +1 -0
- package/dist/{chunk-N6WF5PKC.js → chunk-NFZGZ4AK.js} +2 -2
- package/dist/{chunk-JRBNCUNT.js → chunk-NGSJZFGL.js} +21 -4
- package/dist/chunk-NGSJZFGL.js.map +1 -0
- package/dist/chunk-NJ4DYYO5.js +81 -0
- package/dist/chunk-NJ4DYYO5.js.map +1 -0
- package/dist/{chunk-2IALOXZS.js → chunk-NM5UYF6Q.js} +2 -2
- package/dist/chunk-NM5UYF6Q.js.map +1 -0
- package/dist/{chunk-JBBSYJHP.js → chunk-NYEFP7DY.js} +4 -4
- package/dist/chunk-NYEFP7DY.js.map +1 -0
- package/dist/{chunk-CCOP5XDW.js → chunk-NZ24MX4J.js} +8 -46
- package/dist/chunk-NZ24MX4J.js.map +1 -0
- package/dist/{chunk-KWVJAOIN.js → chunk-OLEPKFTW.js} +4 -4
- package/dist/chunk-OLEPKFTW.js.map +1 -0
- package/dist/{chunk-OF75ACKS.js → chunk-PEATRIYJ.js} +9 -9
- package/dist/chunk-PEOZ34EM.js +13 -0
- package/dist/chunk-PEOZ34EM.js.map +1 -0
- package/dist/{chunk-UC2ETWF3.js → chunk-PTHKZWEH.js} +2 -14
- package/dist/{chunk-UC2ETWF3.js.map → chunk-PTHKZWEH.js.map} +1 -1
- package/dist/chunk-PVEWA2DU.js +23 -0
- package/dist/chunk-PVEWA2DU.js.map +1 -0
- package/dist/{chunk-LSASLXGC.js → chunk-QBAC3GXA.js} +1 -1
- package/dist/chunk-QBAC3GXA.js.map +1 -0
- package/dist/{chunk-RDXW3OBQ.js → chunk-QD46HPZG.js} +2 -2
- package/dist/chunk-QD46HPZG.js.map +1 -0
- package/dist/{chunk-N55W7KUL.js → chunk-QDIH2744.js} +2 -2
- package/dist/{chunk-6HY2X62D.js → chunk-QJNCB5SK.js} +2 -2
- package/dist/{chunk-4BRCIYFG.js → chunk-QX76XVQH.js} +6 -6
- package/dist/chunk-QX76XVQH.js.map +1 -0
- package/dist/{chunk-W2OG6JOL.js → chunk-QZWTRENR.js} +24 -7
- package/dist/chunk-QZWTRENR.js.map +1 -0
- package/dist/{chunk-6NQMXTYC.js → chunk-RO5NM6UI.js} +2 -2
- package/dist/chunk-RO5NM6UI.js.map +1 -0
- package/dist/chunk-SGDPRCC4.js +1075 -0
- package/dist/chunk-SGDPRCC4.js.map +1 -0
- package/dist/{chunk-2PCAVW2I.js → chunk-SHEEBRZ4.js} +2 -2
- package/dist/chunk-SMY5X46Z.js +14 -0
- package/dist/chunk-SMY5X46Z.js.map +1 -0
- package/dist/{chunk-ISMV2QVG.js → chunk-TG634KCO.js} +11 -2
- package/dist/chunk-TG634KCO.js.map +1 -0
- package/dist/{chunk-J6Q7UVQE.js → chunk-TUXQSFHZ.js} +4 -16
- package/dist/{chunk-J6Q7UVQE.js.map → chunk-TUXQSFHZ.js.map} +1 -1
- package/dist/{chunk-GULTLPFB.js → chunk-UADPR6F4.js} +3 -3
- package/dist/{chunk-GULTLPFB.js.map → chunk-UADPR6F4.js.map} +1 -1
- package/dist/{chunk-ZEQWCBCM.js → chunk-UDHBXYGG.js} +27 -5
- package/dist/chunk-UDHBXYGG.js.map +1 -0
- package/dist/{chunk-RA5VTXXG.js → chunk-V6UQZA2H.js} +2 -2
- package/dist/chunk-VG2ZSFYD.js +32 -0
- package/dist/chunk-VG2ZSFYD.js.map +1 -0
- package/dist/chunk-VKQCVU2Z.js +21 -0
- package/dist/chunk-VKQCVU2Z.js.map +1 -0
- package/dist/{chunk-QDPZWTN2.js → chunk-W3G5REIU.js} +2 -2
- package/dist/{chunk-WEYZTLXN.js → chunk-W3L64Y3J.js} +2 -2
- package/dist/{chunk-ONTBCHCP.js → chunk-W66AM5IB.js} +2 -2
- package/dist/chunk-W66AM5IB.js.map +1 -0
- package/dist/{chunk-A5BDDEXK.js → chunk-WBKZUO5V.js} +26 -43
- package/dist/chunk-WBKZUO5V.js.map +1 -0
- package/dist/{chunk-CBSY2N76.js → chunk-WLXMTYGO.js} +2 -2
- package/dist/{chunk-3U3FBR7O.js → chunk-X3F5YJG2.js} +2 -2
- package/dist/{chunk-GQNGCEP5.js → chunk-X45JYIAY.js} +3 -3
- package/dist/chunk-X45JYIAY.js.map +1 -0
- package/dist/{chunk-6XE5TMPR.js → chunk-X4MVWPHV.js} +3 -3
- package/dist/chunk-X4MVWPHV.js.map +1 -0
- package/dist/chunk-XZHEOSQ2.js +16 -0
- package/dist/chunk-XZHEOSQ2.js.map +1 -0
- package/dist/chunk-Y2NBBT6K.js +18 -0
- package/dist/chunk-Y2NBBT6K.js.map +1 -0
- package/dist/{chunk-DDATL6PU.js → chunk-Y2NJBNX3.js} +8 -8
- package/dist/{chunk-DDATL6PU.js.map → chunk-Y2NJBNX3.js.map} +1 -1
- package/dist/{chunk-YTGDPCPW.js → chunk-Y6B6HVKC.js} +2 -2
- package/dist/chunk-YMUFFJCO.js +23 -0
- package/dist/chunk-YMUFFJCO.js.map +1 -0
- package/dist/{chunk-O7WJ47EF.js → chunk-YWWQM7KP.js} +5 -14
- package/dist/chunk-YWWQM7KP.js.map +1 -0
- package/dist/{chunk-7O3AYBC7.js → chunk-YZJSJOUI.js} +235 -65
- package/dist/chunk-YZJSJOUI.js.map +1 -0
- package/dist/{chunk-5WZXVULX.js → chunk-ZTLOXFPB.js} +2 -2
- package/dist/chunk-ZTLOXFPB.js.map +1 -0
- package/dist/classified/index.js +5 -5
- package/dist/{classified-marker-WQVIJAW2.js → classified-marker-7PKJBFCG.js} +3 -3
- package/dist/collection-facade-6I5K5IOD.js +45 -0
- package/dist/{computed-DSMPXG2Y.js → computed-AB45PS4V.js} +3 -3
- package/dist/consent/index.js +13 -9
- package/dist/consent/index.js.map +1 -1
- package/dist/cover/index.js +37 -0
- package/dist/crdt/index.js +4 -0
- package/dist/crdt/index.js.map +1 -1
- package/dist/custody/index.js +26 -0
- package/dist/{dead-filter-2A7IAJ3D.js → dead-filter-FL3WIUZS.js} +2 -2
- package/dist/{chunk-GYYCX5K6.js → delegation-QXZ4MPPH.js} +12 -6
- package/dist/{chunk-GYYCX5K6.js.map → delegation-QXZ4MPPH.js.map} +1 -1
- package/dist/derivations/index.js +12 -12
- package/dist/derive-VGS7FKE3.js +22 -0
- package/dist/directory/index.js +46 -0
- package/dist/dispatch-EGGC7UD7.js +72 -0
- package/dist/dispatch-EGGC7UD7.js.map +1 -0
- package/dist/dispatch-GDSTUTVP.js +194 -0
- package/dist/dispatch-GDSTUTVP.js.map +1 -0
- package/dist/{enclave-7MW6ZGXW.js → enclave-SPEEDYZ4.js} +11 -11
- package/dist/executor-IEBLTBCW.js +9 -0
- package/dist/executor-OTF556PL.js +28 -0
- package/dist/executor-RM7XWQDU.js +9 -0
- package/dist/export-accessible-P42BQ4PB.js +23 -0
- package/dist/extract-partition-TCYXRWBN.js +38 -0
- package/dist/{fanout-sidecar-WDYQ77VB.js → fanout-sidecar-SSMRSC2L.js} +9 -9
- package/dist/find-OZMTRIK3.js +11 -0
- package/dist/forget/index.js +11 -11
- package/dist/forget/index.js.map +1 -1
- package/dist/guards/index.js +6 -6
- package/dist/history/index.js +16 -12
- package/dist/history/index.js.map +1 -1
- package/dist/i18n/index.js +16 -14
- package/dist/i18n/index.js.map +1 -1
- package/dist/index.d.ts +42 -42
- package/dist/index.js +330 -2106
- package/dist/index.js.map +1 -1
- package/dist/indexing/index.js +4 -2
- package/dist/indexing/index.js.map +1 -1
- package/dist/introspection/index.js +28 -0
- package/dist/issue-FCKN5O6C.js +19 -0
- package/dist/kernel/best-effort-revert.d.ts +9 -1
- package/dist/kernel/collection-config.d.ts +12 -70
- package/dist/kernel/collection.d.ts +11 -23
- package/dist/kernel/enclave/crypto.d.ts +8 -8
- package/dist/kernel/enclave/index.d.ts +3 -3
- package/dist/kernel/errors.d.ts +41 -22
- package/dist/kernel/lazy.d.ts +30 -0
- package/dist/kernel/noydb.d.ts +81 -124
- package/dist/kernel/query/builder.d.ts +10 -10
- package/dist/kernel/query/index.d.ts +0 -6
- package/dist/kernel/query/scan-builder.d.ts +4 -4
- package/dist/kernel/sync-policy.d.ts +76 -4
- package/dist/kernel/types.d.ts +146 -86
- package/dist/kernel/validation.d.ts +33 -33
- package/dist/kernel/vault.d.ts +41 -229
- package/dist/kernel/via/dispatch.d.ts +7 -0
- package/dist/{ledger-33BC4TR7.js → ledger-6XBEVWYP.js} +11 -11
- package/dist/liberate-CYUOS4NC.js +24 -0
- package/dist/{link-set-QK22TDEX.js → link-set-NK6L2A5S.js} +11 -11
- package/dist/materialized-views/index.js +22 -19
- package/dist/money/index.js +31 -0
- package/dist/noydb-FZZIMLCI.js +81 -0
- package/dist/overlay-views/index.js +4 -4
- package/dist/periods/index.js +15 -13
- package/dist/pod/index.js +26 -12
- package/dist/{policy-NAHB2TUT.js → policy/index.js} +6 -6
- package/dist/port/with/archive-strategy.d.ts +31 -0
- package/dist/port/with/blob-strategy.d.ts +15 -5
- package/dist/port/with/collection-options.d.ts +171 -0
- package/dist/port/with/collection-registries.d.ts +62 -0
- package/dist/port/with/strategies.d.ts +134 -0
- package/dist/port/with/team-strategy.d.ts +3 -2
- package/dist/portability/index.js +8 -8
- package/dist/{post-register-JVTMJ6OW.js → post-register-VFIYISUK.js} +6 -6
- package/dist/query/index.js +6 -46
- package/dist/{aggregate → reduce}/index.js +24 -17
- package/dist/reduce/index.js.map +1 -0
- package/dist/register-UKU2J6MN.js +25 -0
- package/dist/registry-2VCWVHZS.js +19 -0
- package/dist/registry-7Y5WF7GS.js +9 -0
- package/dist/{registry-VW6P6A3J.js → registry-BWD2ED52.js} +2 -2
- package/dist/registry-DTWRJLSF.js +18 -0
- package/dist/request-withdrawal-JYDZ5XY2.js +31 -0
- package/dist/{reveal-LGBOM2BO.js → reveal-CL2BCW6A.js} +6 -6
- package/dist/revoke-2TSAD2T4.js +24 -0
- package/dist/satellites/index.js +1 -1
- package/dist/schema-update/index.js +26 -0
- package/dist/sealed-record/index.js +12 -12
- package/dist/search/index.js +36 -0
- package/dist/{seed-PWK45HDF.js → seed-NUVJEL7T.js} +12 -12
- package/dist/seed-NUVJEL7T.js.map +1 -0
- package/dist/sequence/index.js +30 -0
- package/dist/session/index.js +13 -9
- package/dist/session/index.js.map +1 -1
- package/dist/shadow/index.js +6 -2
- package/dist/shadow/index.js.map +1 -1
- package/dist/signer-K7Z2EOMG.js +25 -0
- package/dist/snapshots/index.js +14 -10
- package/dist/snapshots/index.js.map +1 -1
- package/dist/{stale-FJED42DM.js → stale-A4J26OIC.js} +11 -10
- package/dist/storage-YVHZUISN.js +23 -0
- package/dist/store/index.js +22 -0
- package/dist/{store-coordination-provider-APODTV4W.js → store-coordination-provider-EWRZL7XF.js} +3 -3
- package/dist/sync/index.js +15 -12
- package/dist/sync/index.js.map +1 -1
- package/dist/team/index.js +33 -48
- package/dist/tiers/index.js +10 -10
- package/dist/to/index.js +1 -1
- package/dist/{tx → transactions}/index.js +7 -3
- package/dist/transactions/index.js.map +1 -0
- package/dist/util/index.js +1 -1
- package/dist/{verify-26Y5GNMK.js → verify-7XWHJWUN.js} +5 -5
- package/dist/via/blob/active.d.ts +23 -7
- package/dist/via/blob/binding.d.ts +1 -1
- package/dist/via/blob/index.d.ts +7 -1
- package/dist/via/i18n/core.d.ts +1 -1
- package/dist/via/i18n/index.d.ts +2 -0
- package/dist/via/money/money-reducer.d.ts +2 -2
- package/dist/walk-P5D6CF4V.js +21 -0
- package/dist/with-audit/consent/index.d.ts +2 -0
- package/dist/with-audit/forget/active.d.ts +3 -3
- package/dist/with-audit/forget/index.d.ts +6 -5
- package/dist/with-audit/forget/strategy.d.ts +3 -3
- package/dist/with-audit/guards/executor.d.ts +4 -4
- package/dist/with-audit/guards/immutable-guard.d.ts +3 -3
- package/dist/with-audit/guards/index.d.ts +1 -1
- package/dist/with-audit/guards/registry.d.ts +3 -3
- package/dist/with-audit/guards/transition-guard.d.ts +3 -3
- package/dist/with-audit/guards/types.d.ts +10 -10
- package/dist/with-audit/guards/with-guard.d.ts +2 -2
- package/dist/with-audit/periods/index.d.ts +2 -0
- package/dist/with-audit/periods/vault-facade.d.ts +6 -0
- package/dist/with-audit/portability/export-accessible.d.ts +4 -4
- package/dist/with-audit/portability/request-withdrawal.d.ts +3 -3
- package/dist/with-audit/portability/withdraw-accessible.d.ts +2 -2
- package/dist/with-audit/sealed-record/strategy.d.ts +1 -1
- package/dist/with-audit/tiers/index.d.ts +1 -0
- package/dist/with-cargo/adopt-partition.d.ts +7 -7
- package/dist/{legacy/kernel.d.ts → with-cargo/floor.d.ts} +4 -4
- package/dist/with-cargo/index.d.ts +9 -2
- package/dist/with-commit/crdt/index.d.ts +2 -0
- package/dist/with-commit/history/index.d.ts +2 -0
- package/dist/with-commit/history/time-machine.d.ts +2 -2
- package/dist/with-commit/numbering/descriptor.d.ts +16 -6
- package/dist/with-commit/tx/active.d.ts +5 -5
- package/dist/with-commit/tx/index.d.ts +2 -2
- package/dist/with-commit/tx/invariants.d.ts +1 -1
- package/dist/with-commit/tx/strategy.d.ts +3 -3
- package/dist/with-fork/shadow/index.d.ts +2 -0
- package/dist/with-fork/snapshots/active.d.ts +2 -2
- package/dist/with-fork/snapshots/index.d.ts +3 -1
- package/dist/with-fork/snapshots/noydb-facade.d.ts +3 -3
- package/dist/with-fork/snapshots/strategy.d.ts +2 -2
- package/dist/with-formula/derivations/dispatch.d.ts +98 -0
- package/dist/with-formula/derivations/executor.d.ts +2 -2
- package/dist/with-formula/derivations/index.d.ts +4 -1
- package/dist/with-formula/derivations/registry.d.ts +3 -3
- package/dist/with-formula/derivations/stale.d.ts +2 -2
- package/dist/with-formula/derivations/types.d.ts +3 -3
- package/dist/with-formula/derivations/with-derivation.d.ts +2 -2
- package/dist/with-formula/derivations/with-rollup.d.ts +15 -8
- package/dist/with-formula/materialized-views/dependency-analyzer.d.ts +3 -3
- package/dist/with-formula/materialized-views/dispatch.d.ts +75 -0
- package/dist/with-formula/materialized-views/index.d.ts +2 -1
- package/dist/with-formula/materialized-views/registry.d.ts +4 -4
- package/dist/with-formula/materialized-views/types.d.ts +11 -11
- package/dist/with-formula/materialized-views/with-materialized-view.d.ts +2 -2
- package/dist/with-formula/overlay-views/index.d.ts +1 -1
- package/dist/with-formula/overlay-views/registry.d.ts +4 -4
- package/dist/with-formula/overlay-views/types.d.ts +3 -3
- package/dist/with-formula/overlay-views/virtual-collection.d.ts +2 -2
- package/dist/with-formula/overlay-views/with-overlayed-view.d.ts +2 -2
- package/dist/with-lookup/indexing/active.d.ts +5 -5
- package/dist/with-lookup/indexing/index.d.ts +3 -1
- package/dist/with-lookup/indexing/strategy.d.ts +3 -3
- package/dist/with-lookup/{aggregate → reduce}/active.d.ts +8 -8
- package/dist/with-lookup/{aggregate → reduce}/groupby.d.ts +21 -21
- package/dist/with-lookup/reduce/index.d.ts +34 -0
- package/dist/with-lookup/{aggregate → reduce}/reducers.d.ts +11 -12
- package/dist/with-lookup/{aggregate/aggregation.d.ts → reduce/reduction.d.ts} +21 -21
- package/dist/with-lookup/{aggregate → reduce}/strategy.d.ts +15 -15
- package/dist/with-lookup/search/build-docs.d.ts +7 -2
- package/dist/with-lookup/search/index.d.ts +1 -1
- package/dist/with-party/broker/index.d.ts +1 -0
- package/dist/with-party/broker/seed.d.ts +1 -1
- package/dist/with-party/custody/liberate.d.ts +3 -3
- package/dist/with-party/directory/cover/index.d.ts +1 -5
- package/dist/with-party/directory/cover/schema.d.ts +0 -6
- package/dist/with-party/directory/cover/storage.d.ts +0 -8
- package/dist/with-party/directory/cover/types.d.ts +0 -21
- package/dist/with-party/directory/index.d.ts +2 -0
- package/dist/with-party/session/dev-unlock.d.ts +2 -2
- package/dist/with-party/session/index.d.ts +2 -0
- package/dist/with-party/session/session.d.ts +2 -2
- package/dist/with-party/team/deed.d.ts +8 -8
- package/dist/with-party/team/index.d.ts +4 -7
- package/dist/with-party/team/keyring.d.ts +83 -35
- package/dist/with-party/team/{managed-passphrase.d.ts → managed-secret.d.ts} +27 -27
- package/dist/with-party/team/noydb-facade.d.ts +43 -42
- package/dist/with-party/team/peer-recover.d.ts +13 -13
- package/dist/with-party/team/recovery.d.ts +5 -5
- package/dist/with-party/team/rotate-recover.d.ts +30 -30
- package/dist/with-pod/bundle.d.ts +30 -32
- package/dist/with-pod/format.d.ts +2 -2
- package/dist/with-pod/index.d.ts +2 -1
- package/dist/with-shape/blobs/blob-compaction.d.ts +43 -3
- package/dist/with-shape/blobs/blob-pinning.d.ts +112 -0
- package/dist/with-shape/blobs/blob-set.d.ts +86 -2
- package/dist/with-shape/introspection/index.d.ts +6 -0
- package/dist/with-shape/schema-update/index.d.ts +1 -0
- package/dist/with-store/index.d.ts +3 -2
- package/dist/with-store/route-store.d.ts +1 -1
- package/dist/{with-party/team/sync-active.d.ts → with-sync/active.d.ts} +1 -1
- package/dist/{with-party/team/sync-credentials.d.ts → with-sync/credentials.d.ts} +3 -3
- package/dist/{with-party/team/sync.d.ts → with-sync/engine.d.ts} +5 -5
- package/dist/{with-party/sync → with-sync}/index.d.ts +4 -2
- package/dist/{with-party/team/sync-period-scope.d.ts → with-sync/period-scope.d.ts} +2 -2
- package/dist/{with-party/team → with-sync}/presence.d.ts +2 -2
- package/dist/{with-party/team/sync-strategy.d.ts → with-sync/strategy.d.ts} +6 -6
- package/dist/{with-party/team/sync-transaction.d.ts → with-sync/transaction.d.ts} +3 -3
- package/dist/withdraw-accessible-A2PWF5MZ.js +28 -0
- package/package.json +45 -36
- package/dist/aggregate/index.js.map +0 -1
- package/dist/api-IQFZJSQO.js +0 -20
- package/dist/as/index.js +0 -30
- package/dist/at/index.js +0 -1
- package/dist/bundle/index.js +0 -105
- package/dist/by/index.js +0 -11
- package/dist/chunk-2IALOXZS.js.map +0 -1
- package/dist/chunk-2MUZ3LY6.js +0 -205
- package/dist/chunk-2MUZ3LY6.js.map +0 -1
- package/dist/chunk-2P7EGNKF.js.map +0 -1
- package/dist/chunk-3PF6CRDT.js.map +0 -1
- package/dist/chunk-3SV2EPMN.js.map +0 -1
- package/dist/chunk-4BRCIYFG.js.map +0 -1
- package/dist/chunk-5OI6BR4H.js.map +0 -1
- package/dist/chunk-5WZXVULX.js.map +0 -1
- package/dist/chunk-6NQMXTYC.js.map +0 -1
- package/dist/chunk-6XE5TMPR.js.map +0 -1
- package/dist/chunk-7CI6CP7Z.js.map +0 -1
- package/dist/chunk-7O3AYBC7.js.map +0 -1
- package/dist/chunk-A5BDDEXK.js.map +0 -1
- package/dist/chunk-A7JJLVGH.js.map +0 -1
- package/dist/chunk-BGK233EA.js.map +0 -1
- package/dist/chunk-BMQWTQZ4.js.map +0 -1
- package/dist/chunk-BOKIKJJB.js.map +0 -1
- package/dist/chunk-CCOP5XDW.js.map +0 -1
- package/dist/chunk-CHFZDSE4.js +0 -1
- package/dist/chunk-DDHM2TLX.js.map +0 -1
- package/dist/chunk-GQNGCEP5.js.map +0 -1
- package/dist/chunk-GVZQ4NAM.js +0 -14
- package/dist/chunk-GVZQ4NAM.js.map +0 -1
- package/dist/chunk-GWKAVKHI.js.map +0 -1
- package/dist/chunk-HOONYZY2.js.map +0 -1
- package/dist/chunk-HPUWOVR7.js.map +0 -1
- package/dist/chunk-ISMV2QVG.js.map +0 -1
- package/dist/chunk-JBBSYJHP.js.map +0 -1
- package/dist/chunk-JRBNCUNT.js.map +0 -1
- package/dist/chunk-JZWWLLVY.js +0 -99
- package/dist/chunk-JZWWLLVY.js.map +0 -1
- package/dist/chunk-KUPKLSX5.js.map +0 -1
- package/dist/chunk-KWVJAOIN.js.map +0 -1
- package/dist/chunk-LB6OH6K2.js.map +0 -1
- package/dist/chunk-LB7FD65R.js +0 -163
- package/dist/chunk-LB7FD65R.js.map +0 -1
- package/dist/chunk-LOF2W3JU.js.map +0 -1
- package/dist/chunk-LSASLXGC.js.map +0 -1
- package/dist/chunk-O7WJ47EF.js.map +0 -1
- package/dist/chunk-ONTBCHCP.js.map +0 -1
- package/dist/chunk-PT37L5DV.js +0 -255
- package/dist/chunk-PT37L5DV.js.map +0 -1
- package/dist/chunk-RDXW3OBQ.js.map +0 -1
- package/dist/chunk-RND5ZPNP.js.map +0 -1
- package/dist/chunk-S3BFKGET.js.map +0 -1
- package/dist/chunk-SMGEYW6G.js.map +0 -1
- package/dist/chunk-T36RFODW.js.map +0 -1
- package/dist/chunk-TAGR72IR.js.map +0 -1
- package/dist/chunk-UNCOC7QH.js.map +0 -1
- package/dist/chunk-VCBHAE4R.js.map +0 -1
- package/dist/chunk-VEALDPHW.js.map +0 -1
- package/dist/chunk-VQNJ7UZL.js.map +0 -1
- package/dist/chunk-W2OG6JOL.js.map +0 -1
- package/dist/chunk-WNGGJWF7.js.map +0 -1
- package/dist/chunk-YJV2UZ7H.js.map +0 -1
- package/dist/chunk-YMUGBZN2.js.map +0 -1
- package/dist/chunk-ZEQWCBCM.js.map +0 -1
- package/dist/collection-facade-MJXSC3Q6.js +0 -44
- package/dist/cover-B5SJDHR3.js +0 -52
- package/dist/delegation-A5A75KQO.js +0 -25
- package/dist/derive-HJSMH7RA.js +0 -21
- package/dist/executor-AXE4XMLT.js +0 -26
- package/dist/executor-KGNLJD6M.js +0 -9
- package/dist/executor-XGIS6CR7.js +0 -9
- package/dist/export-accessible-VVBJM3MM.js +0 -23
- package/dist/extract-partition-LGGBTQET.js +0 -38
- package/dist/find-YS6XWB46.js +0 -11
- package/dist/in/index.js +0 -1
- package/dist/issue-LSR5PS6H.js +0 -19
- package/dist/legacy/bundle.d.ts +0 -30
- package/dist/liberate-GBSAYLPJ.js +0 -24
- package/dist/noydb-MTUBMWFE.js +0 -70
- package/dist/on/index.js +0 -17
- package/dist/port/as/index.d.ts +0 -26
- package/dist/port/at/index.d.ts +0 -18
- package/dist/port/in/index.d.ts +0 -21
- package/dist/port/on/index.d.ts +0 -27
- package/dist/port/ui/index.d.ts +0 -21
- package/dist/port/with/index.d.ts +0 -18
- package/dist/register-X462DNDM.js +0 -23
- package/dist/registry-3XMCT7MQ.js +0 -18
- package/dist/registry-KHD2I3M2.js +0 -19
- package/dist/registry-NPOWJHC4.js +0 -9
- package/dist/request-withdrawal-U7K3JTMY.js +0 -31
- package/dist/revoke-OCWDSWRQ.js +0 -24
- package/dist/seed-PWK45HDF.js.map +0 -1
- package/dist/signer-3YFBLZRN.js +0 -25
- package/dist/storage-W3GURVFU.js +0 -23
- package/dist/tx/index.js.map +0 -1
- package/dist/ui/index.js +0 -1
- package/dist/with/index.js +0 -31
- package/dist/with-lookup/aggregate/index.d.ts +0 -23
- package/dist/withdraw-accessible-Y3B2535F.js +0 -28
- /package/dist/{api-IQFZJSQO.js.map → api-ZDKTWNBB.js.map} +0 -0
- /package/dist/{backup-LU2DTZTI.js.map → backup-2UX7PRM5.js.map} +0 -0
- /package/dist/{chunk-IY23KFNZ.js.map → chunk-35NMVJ7I.js.map} +0 -0
- /package/dist/{chunk-RTEK4C4I.js.map → chunk-4JQK3L4V.js.map} +0 -0
- /package/dist/{chunk-3ELCWU56.js.map → chunk-4ZKNC6A6.js.map} +0 -0
- /package/dist/{chunk-VAIS3SOM.js.map → chunk-55LX6FSX.js.map} +0 -0
- /package/dist/{chunk-6HPG2YNX.js.map → chunk-5DRROK5W.js.map} +0 -0
- /package/dist/{chunk-S6Q37VGE.js.map → chunk-5GQEU4DN.js.map} +0 -0
- /package/dist/{chunk-TOPYT5U5.js.map → chunk-63FE525P.js.map} +0 -0
- /package/dist/{chunk-JVBO4SZL.js.map → chunk-6UBZ6I5Z.js.map} +0 -0
- /package/dist/{chunk-UFEVO57O.js.map → chunk-ABS7FMMD.js.map} +0 -0
- /package/dist/{chunk-M75ZZHSR.js.map → chunk-BLBAQRBM.js.map} +0 -0
- /package/dist/{chunk-G6EQYAL6.js.map → chunk-CI32CAFS.js.map} +0 -0
- /package/dist/{chunk-6B4DYGWO.js.map → chunk-DABACXEF.js.map} +0 -0
- /package/dist/{chunk-F6T6L2UK.js.map → chunk-DMH3VZU5.js.map} +0 -0
- /package/dist/{chunk-MQ6WOPSY.js.map → chunk-DZ2JXHWK.js.map} +0 -0
- /package/dist/{chunk-UBNCR3YK.js.map → chunk-EE7UHLKH.js.map} +0 -0
- /package/dist/{chunk-EGCRBCNA.js.map → chunk-EKRSCRNM.js.map} +0 -0
- /package/dist/{chunk-IRQY7IR5.js.map → chunk-FRMPM7WG.js.map} +0 -0
- /package/dist/{as/index.js.map → chunk-GJW4HX2O.js.map} +0 -0
- /package/dist/{chunk-T6GU5PPZ.js.map → chunk-GU3IP74F.js.map} +0 -0
- /package/dist/{chunk-SMIRGMS7.js.map → chunk-IXNCZTWA.js.map} +0 -0
- /package/dist/{chunk-RM2XV574.js.map → chunk-IXTSNGYY.js.map} +0 -0
- /package/dist/{chunk-PK6QCH2C.js.map → chunk-JJZGIE4U.js.map} +0 -0
- /package/dist/{chunk-DRWBEDYO.js.map → chunk-JYJFGD2H.js.map} +0 -0
- /package/dist/{chunk-KUIB4B5Q.js.map → chunk-LNZKOUJR.js.map} +0 -0
- /package/dist/{chunk-IM3QVF53.js.map → chunk-MBKVNOJS.js.map} +0 -0
- /package/dist/{chunk-N6WF5PKC.js.map → chunk-NFZGZ4AK.js.map} +0 -0
- /package/dist/{chunk-OF75ACKS.js.map → chunk-PEATRIYJ.js.map} +0 -0
- /package/dist/{chunk-N55W7KUL.js.map → chunk-QDIH2744.js.map} +0 -0
- /package/dist/{chunk-6HY2X62D.js.map → chunk-QJNCB5SK.js.map} +0 -0
- /package/dist/{chunk-2PCAVW2I.js.map → chunk-SHEEBRZ4.js.map} +0 -0
- /package/dist/{chunk-RA5VTXXG.js.map → chunk-V6UQZA2H.js.map} +0 -0
- /package/dist/{chunk-QDPZWTN2.js.map → chunk-W3G5REIU.js.map} +0 -0
- /package/dist/{chunk-WEYZTLXN.js.map → chunk-W3L64Y3J.js.map} +0 -0
- /package/dist/{chunk-CBSY2N76.js.map → chunk-WLXMTYGO.js.map} +0 -0
- /package/dist/{chunk-3U3FBR7O.js.map → chunk-X3F5YJG2.js.map} +0 -0
- /package/dist/{chunk-YTGDPCPW.js.map → chunk-Y6B6HVKC.js.map} +0 -0
- /package/dist/{classified-marker-WQVIJAW2.js.map → classified-marker-7PKJBFCG.js.map} +0 -0
- /package/dist/{at/index.js.map → collection-facade-6I5K5IOD.js.map} +0 -0
- /package/dist/{bundle/index.js.map → computed-AB45PS4V.js.map} +0 -0
- /package/dist/{by → cover}/index.js.map +0 -0
- /package/dist/{in → custody}/index.js.map +0 -0
- /package/dist/{dead-filter-2A7IAJ3D.js.map → dead-filter-FL3WIUZS.js.map} +0 -0
- /package/dist/{chunk-CHFZDSE4.js.map → derive-VGS7FKE3.js.map} +0 -0
- /package/dist/{on → directory}/index.js.map +0 -0
- /package/dist/{collection-facade-MJXSC3Q6.js.map → enclave-SPEEDYZ4.js.map} +0 -0
- /package/dist/{computed-DSMPXG2Y.js.map → executor-IEBLTBCW.js.map} +0 -0
- /package/dist/{cover-B5SJDHR3.js.map → executor-OTF556PL.js.map} +0 -0
- /package/dist/{delegation-A5A75KQO.js.map → executor-RM7XWQDU.js.map} +0 -0
- /package/dist/{derive-HJSMH7RA.js.map → export-accessible-P42BQ4PB.js.map} +0 -0
- /package/dist/{enclave-7MW6ZGXW.js.map → extract-partition-TCYXRWBN.js.map} +0 -0
- /package/dist/{fanout-sidecar-WDYQ77VB.js.map → fanout-sidecar-SSMRSC2L.js.map} +0 -0
- /package/dist/{executor-AXE4XMLT.js.map → find-OZMTRIK3.js.map} +0 -0
- /package/dist/{ui → introspection}/index.js.map +0 -0
- /package/dist/{executor-KGNLJD6M.js.map → issue-FCKN5O6C.js.map} +0 -0
- /package/dist/{executor-XGIS6CR7.js.map → ledger-6XBEVWYP.js.map} +0 -0
- /package/dist/{export-accessible-VVBJM3MM.js.map → liberate-CYUOS4NC.js.map} +0 -0
- /package/dist/{extract-partition-LGGBTQET.js.map → link-set-NK6L2A5S.js.map} +0 -0
- /package/dist/{with → money}/index.js.map +0 -0
- /package/dist/{find-YS6XWB46.js.map → noydb-FZZIMLCI.js.map} +0 -0
- /package/dist/{issue-LSR5PS6H.js.map → policy/index.js.map} +0 -0
- /package/dist/{post-register-JVTMJ6OW.js.map → post-register-VFIYISUK.js.map} +0 -0
- /package/dist/{ledger-33BC4TR7.js.map → register-UKU2J6MN.js.map} +0 -0
- /package/dist/{liberate-GBSAYLPJ.js.map → registry-2VCWVHZS.js.map} +0 -0
- /package/dist/{link-set-QK22TDEX.js.map → registry-7Y5WF7GS.js.map} +0 -0
- /package/dist/{noydb-MTUBMWFE.js.map → registry-BWD2ED52.js.map} +0 -0
- /package/dist/{policy-NAHB2TUT.js.map → registry-DTWRJLSF.js.map} +0 -0
- /package/dist/{register-X462DNDM.js.map → request-withdrawal-JYDZ5XY2.js.map} +0 -0
- /package/dist/{reveal-LGBOM2BO.js.map → reveal-CL2BCW6A.js.map} +0 -0
- /package/dist/{registry-3XMCT7MQ.js.map → revoke-2TSAD2T4.js.map} +0 -0
- /package/dist/{registry-KHD2I3M2.js.map → schema-update/index.js.map} +0 -0
- /package/dist/{registry-NPOWJHC4.js.map → search/index.js.map} +0 -0
- /package/dist/{registry-VW6P6A3J.js.map → sequence/index.js.map} +0 -0
- /package/dist/{request-withdrawal-U7K3JTMY.js.map → signer-K7Z2EOMG.js.map} +0 -0
- /package/dist/{revoke-OCWDSWRQ.js.map → stale-A4J26OIC.js.map} +0 -0
- /package/dist/{signer-3YFBLZRN.js.map → storage-YVHZUISN.js.map} +0 -0
- /package/dist/{stale-FJED42DM.js.map → store/index.js.map} +0 -0
- /package/dist/{store-coordination-provider-APODTV4W.js.map → store-coordination-provider-EWRZL7XF.js.map} +0 -0
- /package/dist/{verify-26Y5GNMK.js.map → verify-7XWHJWUN.js.map} +0 -0
- /package/dist/{storage-W3GURVFU.js.map → walk-P5D6CF4V.js.map} +0 -0
- /package/dist/with-lookup/{aggregate → reduce}/canonical-key.d.ts +0 -0
- /package/dist/{with-party → with-sync}/tab-coordination.d.ts +0 -0
- /package/dist/{with-party → with-sync}/tab-write-relay.d.ts +0 -0
- /package/dist/{withdraw-accessible-Y3B2535F.js.map → withdraw-accessible-A2PWF5MZ.js.map} +0 -0
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
import {
|
|
2
2
|
loadVaultPolicy,
|
|
3
3
|
saveVaultPolicy
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-WLXMTYGO.js";
|
|
5
5
|
import {
|
|
6
6
|
PolicyDeniedError,
|
|
7
7
|
ValidationError
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-QZWTRENR.js";
|
|
9
9
|
|
|
10
10
|
// src/with-party/policy/presets.ts
|
|
11
11
|
var PERSONAL_POLICY = Object.freeze({
|
|
12
|
-
|
|
12
|
+
secret: {
|
|
13
13
|
minWords: 6,
|
|
14
14
|
minWordLength: 3,
|
|
15
15
|
rejectRepeatedAdjacent: true
|
|
16
16
|
},
|
|
17
17
|
gates: {
|
|
18
|
-
"rotate-
|
|
18
|
+
"rotate-secret": {
|
|
19
19
|
minTier: 1,
|
|
20
20
|
// Any second factor satisfies the gate — off-device kinds (TOTP,
|
|
21
21
|
// email-OTP, paper recovery, roaming WebAuthn) are the strongest;
|
|
@@ -35,13 +35,13 @@ var PERSONAL_POLICY = Object.freeze({
|
|
|
35
35
|
]
|
|
36
36
|
}]
|
|
37
37
|
},
|
|
38
|
-
"recover-
|
|
38
|
+
"recover-secret": {
|
|
39
39
|
minTier: 1,
|
|
40
40
|
enabled: true
|
|
41
41
|
},
|
|
42
42
|
// rotate-recovery: deliberate paper-sheet regeneration
|
|
43
|
-
// when the user remembers their
|
|
44
|
-
// knowing the
|
|
43
|
+
// when the user remembers their secret. PERSONAL allows tier-1 —
|
|
44
|
+
// knowing the secret is enough.
|
|
45
45
|
"rotate-recovery": { minTier: 1 },
|
|
46
46
|
"enroll-authenticator": { minTier: 1 },
|
|
47
47
|
"remove-authenticator": { minTier: 1 },
|
|
@@ -99,17 +99,17 @@ var PERSONAL_POLICY = Object.freeze({
|
|
|
99
99
|
}
|
|
100
100
|
});
|
|
101
101
|
var STRICT_POLICY = Object.freeze({
|
|
102
|
-
|
|
102
|
+
secret: {
|
|
103
103
|
minWords: 8,
|
|
104
104
|
minWordLength: 3,
|
|
105
105
|
rejectRepeatedAdjacent: true
|
|
106
106
|
},
|
|
107
107
|
gates: {
|
|
108
|
-
"rotate-
|
|
108
|
+
"rotate-secret": {
|
|
109
109
|
minTier: 1,
|
|
110
110
|
factors: [{ anyOf: ["totp", "email-otp", "recovery"], count: 2 }]
|
|
111
111
|
},
|
|
112
|
-
"recover-
|
|
112
|
+
"recover-secret": {
|
|
113
113
|
minTier: 1,
|
|
114
114
|
enabled: true
|
|
115
115
|
},
|
|
@@ -216,9 +216,9 @@ var STRICT_POLICY = Object.freeze({
|
|
|
216
216
|
});
|
|
217
217
|
function mergePolicy(base, override) {
|
|
218
218
|
if (!override) return base;
|
|
219
|
-
const
|
|
219
|
+
const secret = override.secret ?? base.secret;
|
|
220
220
|
return {
|
|
221
|
-
...
|
|
221
|
+
...secret !== void 0 ? { secret } : {},
|
|
222
222
|
gates: {
|
|
223
223
|
...base.gates,
|
|
224
224
|
...override.gates ?? {}
|
|
@@ -364,4 +364,4 @@ export {
|
|
|
364
364
|
describeGate,
|
|
365
365
|
createNoydbPolicy
|
|
366
366
|
};
|
|
367
|
-
//# sourceMappingURL=chunk-
|
|
367
|
+
//# sourceMappingURL=chunk-G6WWZNJP.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/with-party/policy/presets.ts","../src/with-party/policy/engine.ts","../src/with-party/policy/noydb-facade.ts"],"sourcesContent":["import type { VaultPolicy } from '../../kernel/types.js'\n\n/**\n * Default policy for personal vaults and SMB deployments — the gates\n * that need an off-device factor get one (TOTP / email-OTP / paper\n * recovery), the rest take a tier-1 unlock alone. Tier-3 (PIN) is the\n * floor only for `rotate-unlock` because that's the\n * \"change my PIN\" flow.\n *\n * The unspecified gates (e.g. `view-user-auth`) inherit the engine\n * default of `{ enabled: false, minTier: 1 }` — they fail closed.\n *\n * @see https://github.com/vLannaAi/noy-db-docs/blob/main/content/docs/services/session-tiers.md → Built-in gates\n */\nexport const PERSONAL_POLICY: VaultPolicy = Object.freeze({\n secret: {\n minWords: 6,\n minWordLength: 3,\n rejectRepeatedAdjacent: true,\n },\n gates: {\n 'rotate-secret': {\n minTier: 1,\n // Any second factor satisfies the gate — off-device kinds (TOTP,\n // email-OTP, paper recovery, roaming WebAuthn) are the strongest;\n // platform-bound kinds (platform WebAuthn, password, PIN) are\n // accepted because requiring \"something off-device\" is overkill\n // for personal/SMB threat models. Consumers needing the off-device\n // guarantee should use STRICT_POLICY or override this gate.\n factors: [{\n anyOf: [\n 'totp', 'email-otp', 'recovery',\n 'webauthn-roaming', 'webauthn-platform',\n 'password', 'pin',\n ],\n }],\n },\n 'recover-secret': {\n minTier: 1,\n enabled: true,\n },\n // rotate-recovery: deliberate paper-sheet regeneration\n // when the user remembers their secret. PERSONAL allows tier-1 —\n // knowing the secret is enough.\n 'rotate-recovery': { minTier: 1 },\n 'enroll-authenticator': { minTier: 1 },\n 'remove-authenticator': { minTier: 1 },\n // update-authenticator: meta-only mutation (slot rename, label\n // changes). Symmetric with enroll/remove under PERSONAL — tier-1\n // unlock alone. The structural anti-slot-swap guard inside the\n // implementation enforces wrap-material/id/method immutability\n // regardless of this gate's settings.\n 'update-authenticator': { minTier: 1 },\n 'rotate-unlock': { minTier: 2 },\n 'enroll-user': { minTier: 1 },\n 'revoke-user': { minTier: 1 },\n // Peer-recovery is a high-trust intentional op — co-owners\n // recovering each other should not need an off-device factor in\n // the personal/SMB threat model (the partner is already vetted by\n // virtue of being a co-owner). Tier-1 unlock is the floor; the\n // STRICT preset adds a recovery/email-OTP requirement.\n 'peer-recover-user': { minTier: 1 },\n // update-user: post-grant identity mutation (role/displayName/\n // permissions). PERSONAL_POLICY treats this on par with enroll-user\n // / revoke-user — tier-1 unlock alone. The role-elevation guard\n // inside the implementation is the structural backstop that this\n // gate's settings cannot weaken.\n 'update-user': { minTier: 1 },\n 'export-bundle': { minTier: 1 },\n 'export-plaintext': {\n minTier: 1,\n factors: [{ anyOf: ['totp', 'email-otp'] }],\n },\n 'view-user-auth': {\n minTier: 1,\n enabled: false,\n },\n // ─── User envelope gates ──────────────────────────────────────────\n // edit-own-profile: tier 3 floor — any active session can edit their\n // own profile/preferences. Tightening to require a TOTP for\n // profile changes is a one-line override.\n // view-team-profiles: tier 2 floor — an authenticated session can\n // read teammates' profiles (display names, avatars, locales).\n // Setting `enabled: false` makes vault.user.list() return only\n // self (privacy-strict opt-out).\n 'edit-own-profile': { minTier: 3 },\n 'view-team-profiles': { minTier: 2 },\n // client-unilateral-withdraw: a non-owner's self-service DESTRUCTIVE\n // withdrawal (export-and-delete/freeze). Fail-closed by default —\n // the firm opts in per jurisdiction/contract (e.g. GDPR Art. 17).\n // Listed explicitly (not just relying on the built-in default) so it is\n // discoverable in describeGate / policy dumps.\n 'client-unilateral-withdraw': { minTier: 1, enabled: false },\n // Two-party withdrawal: filing a request is non-destructive\n // (tier-1, enabled so a read-only client can ask); deciding it is the\n // destructive step (tier-2 floor + owner/admin role, enforced in code).\n 'user-request-withdrawal': { minTier: 1 },\n 'approve-user-withdrawal': { minTier: 2 },\n },\n}) as VaultPolicy\n\n/**\n * Strict policy for regulated deployments and shared workstations —\n * raises the phrase floor to 8 words, demands two distinct factors for\n * exports, and blocks export-on-shared-device. Use as a base for\n * `policy: { ...STRICT_POLICY, gates: { ...STRICT_POLICY.gates, ... } }`\n * tweaks.\n */\nexport const STRICT_POLICY: VaultPolicy = Object.freeze({\n secret: {\n minWords: 8,\n minWordLength: 3,\n rejectRepeatedAdjacent: true,\n },\n gates: {\n 'rotate-secret': {\n minTier: 1,\n factors: [{ anyOf: ['totp', 'email-otp', 'recovery'], count: 2 }],\n },\n 'recover-secret': {\n minTier: 1,\n enabled: true,\n },\n // rotate-recovery: STRICT requires an off-device factor —\n // rotating recovery is an off-site-trust event; a stolen unlocked\n // laptop must not be able to silently mint a new sheet for the\n // attacker. Matches the `peer-recover-user` STRICT default.\n 'rotate-recovery': {\n minTier: 1,\n factors: [{ anyOf: ['totp', 'email-otp', 'webauthn-roaming'] }],\n },\n 'enroll-authenticator': {\n minTier: 1,\n factors: [{ anyOf: ['totp', 'email-otp'] }],\n },\n 'remove-authenticator': {\n minTier: 1,\n factors: [{ anyOf: ['totp', 'email-otp'] }],\n },\n // STRICT update-authenticator: same factor floor as enroll/remove.\n // Even though meta changes don't touch wrap material, a malicious\n // rename could mislead the user about which device a slot\n // corresponds to (\"MacBook Touch ID\" → \"iPhone Touch ID\" on a\n // shared workstation). STRICT requires a fresh factor proof.\n 'update-authenticator': {\n minTier: 1,\n factors: [{ anyOf: ['totp', 'email-otp'] }],\n },\n 'rotate-unlock': { minTier: 1 },\n 'enroll-user': {\n minTier: 1,\n factors: [{ anyOf: ['totp', 'email-otp'] }],\n },\n 'revoke-user': {\n minTier: 1,\n factors: [{ anyOf: ['totp', 'email-otp'] }],\n },\n // STRICT peer-recovery: the issuer must present a recovery code\n // OR a fresh off-device second factor at the moment of recovery.\n // This binds the high-trust operation to a verifiable proof\n // (recovery sheet photographed by an attacker won't suffice —\n // they'd also need tier-1 unlock first; this gate is the freshness\n // binding on top). Roaming WebAuthn (YubiKey-class hardware key)\n // accepted; platform-bound kinds (Touch ID, password, PIN)\n // intentionally excluded under STRICT because they don't survive\n // device theft — the off-device requirement is the whole point.\n 'peer-recover-user': {\n minTier: 1,\n factors: [{ anyOf: ['recovery', 'totp', 'email-otp', 'webauthn-roaming'] }],\n },\n // STRICT update-user: matches the enroll-user / revoke-user shape\n // (off-device factor required). Update-user is admin-shaped — it\n // mutates someone else's role/permissions; STRICT requires a fresh\n // off-device factor proof so the operator affirmatively re-asserts\n // identity at the moment of mutation. Platform-bound factors\n // (Touch ID / password / PIN) intentionally excluded: same logic as\n // peer-recover-user — the off-device requirement is the whole\n // point under STRICT.\n 'update-user': {\n minTier: 1,\n factors: [{ anyOf: ['totp', 'email-otp'] }],\n },\n 'export-bundle': {\n minTier: 1,\n factors: [{ anyOf: ['totp', 'email-otp'] }],\n warn: { sharedDevice: 'block' },\n },\n 'export-plaintext': {\n minTier: 1,\n factors: [{ anyOf: ['totp', 'email-otp'], count: 2 }],\n warn: { sharedDevice: 'block' },\n },\n 'view-user-auth': {\n minTier: 1,\n enabled: false,\n },\n // ─── User envelope gates ──────────────────────────────────────────\n // STRICT: profile edits require a TOTP/email-OTP factor (typical\n // shared-workstation hardening — your name/avatar shouldn't change\n // without a fresh second-factor proof).\n 'edit-own-profile': {\n minTier: 2,\n factors: [{ anyOf: ['totp', 'email-otp'] }],\n },\n 'view-team-profiles': { minTier: 2 },\n // STRICT: still fail-closed, but if a regulated firm flips enabled:true\n // they inherit a two-factor proof + shared-device block for the\n // destructive withdrawal (mirrors export-plaintext's hardening).\n 'client-unilateral-withdraw': {\n minTier: 1,\n enabled: false,\n factors: [{ anyOf: ['totp', 'email-otp'], count: 2 }],\n warn: { sharedDevice: 'block' },\n },\n // STRICT: filing stays tier-1; the destructive APPROVE demands an\n // off-device factor + shared-device block (mirrors export-bundle).\n 'user-request-withdrawal': { minTier: 1 },\n 'approve-user-withdrawal': {\n minTier: 2,\n factors: [{ anyOf: ['totp', 'email-otp'] }],\n warn: { sharedDevice: 'block' },\n },\n },\n}) as VaultPolicy\n\n/**\n * Merge a developer override onto a preset. Unspecified gates inherit;\n * specified gates fully replace the preset's entry for that gate.\n *\n * Example:\n *\n * ```ts\n * mergePolicy(PERSONAL_POLICY, {\n * gates: {\n * 'app:approve-large-payment': { minTier: 2, factors: [{ anyOf: ['totp'] }] },\n * },\n * })\n * // → PERSONAL_POLICY plus the new app gate; existing gates intact.\n * ```\n */\nexport function mergePolicy(\n base: VaultPolicy,\n override?: Partial<VaultPolicy>,\n): VaultPolicy {\n if (!override) return base\n const secret = override.secret ?? base.secret\n return {\n ...(secret !== undefined ? { secret } : {}),\n gates: {\n ...base.gates,\n ...(override.gates ?? {}),\n },\n }\n}\n","/**\n * Policy gate engine — the {@link checkGate} entry point.\n *\n * Given a configured {@link VaultPolicy}, an active session tier, and\n * the factor proofs an actor is presenting, decide whether the gate\n * permits the action. On denial, throws {@link PolicyDeniedError} with\n * a stable {@link PolicyDenyReason} so consumers can branch in error\n * UIs.\n *\n * @see https://github.com/vLannaAi/noy-db-docs/blob/main/content/docs/services/session-tiers.md → checkGate() API\n *\n * @module\n */\nimport { PolicyDeniedError, type PolicyDenyReason } from '../../kernel/errors.js'\nimport type {\n ActiveTier,\n FactorProof,\n GateName,\n GatePolicy,\n VaultPolicy,\n FactorRequirement,\n} from '../../kernel/types.js'\n\n/** Default freshness window — 5 minutes. */\nexport const DEFAULT_FRESHNESS_MS = 5 * 60 * 1000\n\n/** Caller-supplied context for one `checkGate` invocation. */\nexport interface CheckGateContext {\n /** Tier the active session currently holds. */\n readonly activeTier: ActiveTier\n /** Proofs the actor is presenting for this gate. */\n readonly factors?: ReadonlyArray<FactorProof>\n /**\n * If the host knows the actor is on a shared device, set this to\n * `true` so the engine can apply `warn.sharedDevice` rules. Defaults\n * to `false`.\n */\n readonly sharedDevice?: boolean\n /**\n * Override `now()` for tests. Defaults to `Date.now()`.\n * @internal\n */\n readonly now?: number\n}\n\n/**\n * Decide whether `gate` permits the action under `context`. Throws\n * {@link PolicyDeniedError} on denial; resolves with `void` on success.\n *\n * Lookup rules:\n * - **Built-in gates** without a configured policy fail closed\n * (`enabled: false`).\n * - **App-defined gates** (`app:*`) without a configured policy are\n * treated as no-op (allow). The developer registered the policy if\n * they wanted enforcement; absence means the gate is informational.\n */\nexport async function checkGate(\n policy: VaultPolicy,\n gate: GateName,\n context: CheckGateContext,\n): Promise<void> {\n const configured = policy.gates[gate]\n if (!configured) {\n if (gate.startsWith('app:')) {\n // Custom app gate without a policy — the developer hasn't\n // registered one; engine treats it as an unenforced label.\n return\n }\n // Built-in gate without a policy — fail closed.\n throw deny(gate, 'disabled', { minTier: 1, enabled: false })\n }\n\n if (configured.enabled === false) {\n throw deny(gate, 'disabled', configured)\n }\n\n // Tier check first — cheap and a hard prerequisite.\n if (context.activeTier > configured.minTier) {\n // Higher number is a LOWER tier in this model (1 is most privileged).\n throw deny(gate, 'insufficient-tier', configured)\n }\n\n // Factor checks — every requirement entry must be satisfied.\n if (configured.factors && configured.factors.length > 0) {\n const presented = context.factors ?? []\n const now = context.now ?? Date.now()\n for (const requirement of configured.factors) {\n const matches = countMatchingFactors(presented, requirement, now)\n const need = requirement.count ?? 1\n if (matches.fresh < need) {\n if (matches.totalKindMatches < need) {\n throw deny(gate, 'missing-factor', configured)\n }\n // Some matched the kind list but not the freshness window.\n throw deny(gate, 'stale-proof', configured)\n }\n }\n }\n\n // Soft signals — only `'block'` raises here.\n if (configured.warn?.sharedDevice === 'block' && context.sharedDevice === true) {\n throw deny(gate, 'shared-device-blocked', configured)\n }\n}\n\n/**\n * Same as {@link checkGate} but returns a structured verdict instead\n * of throwing. Useful when an error UI wants to show the user\n * \"you'll need TOTP plus a recovery code to do that\" without first\n * triggering the action.\n */\nexport async function describeGate(\n policy: VaultPolicy,\n gate: GateName,\n context: CheckGateContext,\n): Promise<{ ok: true } | { ok: false; reason: PolicyDenyReason; required: GatePolicy }> {\n try {\n await checkGate(policy, gate, context)\n return { ok: true }\n } catch (err) {\n if (err instanceof PolicyDeniedError) {\n return { ok: false, reason: err.reason, required: err.required }\n }\n throw err\n }\n}\n\nfunction countMatchingFactors(\n presented: ReadonlyArray<FactorProof>,\n requirement: FactorRequirement,\n now: number,\n): { totalKindMatches: number; fresh: number } {\n const freshnessMs = requirement.freshnessMs ?? DEFAULT_FRESHNESS_MS\n let totalKindMatches = 0\n let fresh = 0\n for (const proof of presented) {\n if (!requirement.anyOf.includes(proof.kind)) continue\n totalKindMatches += 1\n const minted = proof.mintedAt ? Date.parse(proof.mintedAt) : now\n if (Number.isFinite(minted) && now - minted <= freshnessMs) {\n fresh += 1\n }\n }\n return { totalKindMatches, fresh }\n}\n\nfunction deny(gate: GateName, reason: PolicyDenyReason, required: GatePolicy): PolicyDeniedError {\n return new PolicyDeniedError(gate, reason, required)\n}\n","/**\n * Noydb-side policy / session-policy facade.\n *\n * Holds the vault-policy read/update/bootstrap logic (`getPolicy`,\n * `updatePolicy`, `bootstrapPolicy`) and the per-vault session-policy\n * enforcer wiring (`touchPolicy`, `checkPolicyOperation`). The session\n * *timer* and the managed-recovery enrolment check stay kernel-resident on\n * `Noydb` (interleaved with the instance lifecycle) and arrive here as the\n * `resetSessionTimer` / `assertRecoveryEnrolled` callbacks. The policy cache\n * and the enforcer map stay `Noydb`-resident too (touched by\n * `openVault`/`close`) and arrive by reference; behaviour is byte-identical\n * to the inline `Noydb` methods it replaced — every other dependency the\n * moving code touched on `this.*` arrives via {@link NoydbPolicyDeps}.\n *\n * Internal service — reached through `noydb.getPolicy(...)` etc. Public\n * contract ({@link NoydbPolicyApi} / {@link NoydbPolicyDeps} /\n * {@link NoydbPolicyFactory}) lives in the kernel spine; `createNoydb()`\n * wires this file's {@link createNoydbPolicy} in via a pre-resolved dynamic\n * import (the S4 gate recipe).\n */\nimport { ValidationError } from '../../kernel/errors.js'\nimport { PERSONAL_POLICY, mergePolicy } from './presets.js'\nimport { loadVaultPolicy, saveVaultPolicy } from './storage.js'\nimport type { VaultPolicy, ReAuthOperation, NoydbPolicyApi, NoydbPolicyDeps, NoydbPolicyFactory } from '../../kernel/types.js'\n\nexport class NoydbPolicy implements NoydbPolicyApi {\n constructor(private readonly deps: NoydbPolicyDeps) {}\n\n /**\n * Touch the policy enforcer for a vault (records activity, resets\n * idle timer). Also touches the legacy session timer. No-op if no enforcer.\n */\n touchPolicy(vault?: string): void {\n this.deps.resetSessionTimer()\n if (vault) {\n this.deps.policyEnforcers.get(vault)?.touch()\n }\n }\n\n /**\n * Check that a policy-guarded operation is permitted.\n * Throws `SessionPolicyError` if re-auth is required.\n */\n checkPolicyOperation(vault: string, op: ReAuthOperation): void {\n this.deps.policyEnforcers.get(vault)?.checkOperation(op)\n }\n\n /**\n * Read the active policy for a vault. Loads from `_meta/policy` on\n * first call; subsequent calls hit the in-memory cache. Throws\n * `ValidationError` if the vault has not been opened.\n */\n async getPolicy(vault: string): Promise<VaultPolicy> {\n if (this.deps.isClosed()) throw new ValidationError('Instance is closed')\n const cached = this.deps.policyCache.get(vault)\n if (cached) return cached\n await this.bootstrapPolicy(vault)\n return this.deps.policyCache.get(vault) ?? PERSONAL_POLICY\n }\n\n /**\n * Replace the policy document at `_meta/policy` and update the\n * in-memory cache. Gated by the `enroll-user` policy (a policy\n * change is fundamentally a privilege-management action).\n */\n async updatePolicy(vault: string, override: Partial<VaultPolicy>): Promise<VaultPolicy> {\n if (this.deps.isClosed()) throw new ValidationError('Instance is closed')\n const current = await this.getPolicy(vault)\n const merged = mergePolicy(current, override)\n if (this.deps.encrypted) {\n await saveVaultPolicy(this.deps.store, vault, merged)\n }\n this.deps.policyCache.set(vault, merged)\n return merged\n }\n\n /** Read or persist the vault policy at `_meta/policy` on first open. */\n async bootstrapPolicy(\n vault: string,\n opts?: { skipManagedCheck?: boolean },\n ): Promise<void> {\n const onDisk = await loadVaultPolicy(this.deps.store, vault)\n if (onDisk) {\n // Honour the on-disk document; developer overrides cannot\n // weaken what the vault committed to at creation time.\n this.deps.policyCache.set(vault, onDisk)\n await this.deps.assertRecoveryEnrolled(vault, onDisk, opts)\n return\n }\n // First time — persist the developer's policy (or default preset).\n const initial = this.deps.policyOption\n ? mergePolicy(PERSONAL_POLICY, this.deps.policyOption)\n : PERSONAL_POLICY\n await saveVaultPolicy(this.deps.store, vault, initial)\n this.deps.policyCache.set(vault, initial)\n await this.deps.assertRecoveryEnrolled(vault, initial, opts)\n }\n}\n\n/**\n * Factory that builds the `NoydbPolicy` service. `createNoydb()`\n * pre-resolves this via a dynamic import (mirrors\n * `with-party/directory/user-envelope/api.js#createUserApi`) and threads\n * it through `NoydbOptions.policyFactory` so `Noydb`'s constructor can\n * build `this.policyManager` synchronously.\n */\nexport const createNoydbPolicy: NoydbPolicyFactory = (deps) => new NoydbPolicy(deps)\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
//# sourceMappingURL=chunk-GJW4HX2O.js.map
|
|
@@ -201,7 +201,7 @@ var engineCtx = (ctx) => ({
|
|
|
201
201
|
function withClassified() {
|
|
202
202
|
return {
|
|
203
203
|
async reveal(ctx, id, field) {
|
|
204
|
-
const { revealSealedField } = await import("./reveal-
|
|
204
|
+
const { revealSealedField } = await import("./reveal-CL2BCW6A.js");
|
|
205
205
|
const value = await revealSealedField({
|
|
206
206
|
collection: ctx.collection,
|
|
207
207
|
encrypted: ctx.encrypted,
|
|
@@ -213,26 +213,26 @@ function withClassified() {
|
|
|
213
213
|
return value;
|
|
214
214
|
},
|
|
215
215
|
async verify(ctx, id, field, candidate) {
|
|
216
|
-
const { verifyDigestField } = await import("./verify-
|
|
216
|
+
const { verifyDigestField } = await import("./verify-7XWHJWUN.js");
|
|
217
217
|
const verdict = await verifyDigestField(engineCtx(ctx), id, field, candidate, policyOf(ctx.spec));
|
|
218
218
|
await ctx.onAccess?.("verify", id);
|
|
219
219
|
return verdict;
|
|
220
220
|
},
|
|
221
221
|
async verifyText(ctx, id, field, candidate) {
|
|
222
|
-
const { verifyTextField } = await import("./verify-
|
|
222
|
+
const { verifyTextField } = await import("./verify-7XWHJWUN.js");
|
|
223
223
|
const verdict = await verifyTextField(engineCtx(ctx), id, field, candidate, ctx.spec.verifyNormalize ?? "password");
|
|
224
224
|
await ctx.onAccess?.("verify", id);
|
|
225
225
|
return verdict;
|
|
226
226
|
},
|
|
227
227
|
async matchGroup(ctx, id, answers, opts) {
|
|
228
|
-
const { matchGroupFields } = await import("./verify-
|
|
228
|
+
const { matchGroupFields } = await import("./verify-7XWHJWUN.js");
|
|
229
229
|
const members = (ctx.groupMembers ?? []).map((m) => ({ field: m.field, policy: policyOf(m.spec) }));
|
|
230
230
|
const result = await matchGroupFields(engineCtx(ctx), id, answers, members, opts);
|
|
231
231
|
await ctx.onAccess?.("verify", id);
|
|
232
232
|
return result;
|
|
233
233
|
},
|
|
234
234
|
async computeTarget(ctx, field, candidate, costByte) {
|
|
235
|
-
const { computeBidxTarget } = await import("./find-
|
|
235
|
+
const { computeBidxTarget } = await import("./find-OZMTRIK3.js");
|
|
236
236
|
const dek = await ctx.getDEK();
|
|
237
237
|
return computeBidxTarget(candidate, policyOf(ctx.spec).normalize, dek, ctx.collection, field, costByte);
|
|
238
238
|
}
|
|
@@ -244,4 +244,4 @@ export {
|
|
|
244
244
|
classified,
|
|
245
245
|
withClassified
|
|
246
246
|
};
|
|
247
|
-
//# sourceMappingURL=chunk-
|
|
247
|
+
//# sourceMappingURL=chunk-GU3IP74F.js.map
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
2
|
assertTierAccess,
|
|
3
3
|
dekKey
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-PTHKZWEH.js";
|
|
5
5
|
import {
|
|
6
6
|
liveRecordIsElevated,
|
|
7
7
|
liveRecordTier
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-JYJFGD2H.js";
|
|
9
9
|
import {
|
|
10
10
|
openEnvelopeJson,
|
|
11
11
|
writeEnvelopeBody
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-G2JUIDFA.js";
|
|
13
13
|
import {
|
|
14
14
|
base64ToBuffer,
|
|
15
15
|
bufferToBase64,
|
|
@@ -21,19 +21,53 @@ import {
|
|
|
21
21
|
sha256Hex,
|
|
22
22
|
unwrapCek,
|
|
23
23
|
wrapCek
|
|
24
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-AKKRXT23.js";
|
|
25
25
|
import {
|
|
26
26
|
NOYDB_FORMAT_VERSION
|
|
27
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-QBAC3GXA.js";
|
|
28
28
|
import {
|
|
29
29
|
BlobIntentPendingError,
|
|
30
|
+
BlobOfflineError,
|
|
30
31
|
ConflictError,
|
|
31
32
|
NotFoundError,
|
|
32
33
|
TamperedError,
|
|
33
34
|
TierNotGrantedError,
|
|
34
35
|
UnsupportedTierCompositionError,
|
|
35
36
|
ValidationError
|
|
36
|
-
} from "./chunk-
|
|
37
|
+
} from "./chunk-QZWTRENR.js";
|
|
38
|
+
|
|
39
|
+
// src/with-shape/blobs/blob-pinning.ts
|
|
40
|
+
function memoryBlobPinStore() {
|
|
41
|
+
const rows = /* @__PURE__ */ new Map();
|
|
42
|
+
return {
|
|
43
|
+
async get(key) {
|
|
44
|
+
return rows.get(key) ?? null;
|
|
45
|
+
},
|
|
46
|
+
async set(key, entry) {
|
|
47
|
+
rows.set(key, entry);
|
|
48
|
+
},
|
|
49
|
+
async delete(key) {
|
|
50
|
+
rows.delete(key);
|
|
51
|
+
},
|
|
52
|
+
async entries(prefix) {
|
|
53
|
+
const out = [];
|
|
54
|
+
for (const [key, entry] of rows) {
|
|
55
|
+
if (key.startsWith(prefix)) out.push({ key, entry });
|
|
56
|
+
}
|
|
57
|
+
return out;
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
function createBlobPinCache(store) {
|
|
62
|
+
return {
|
|
63
|
+
store: store ?? memoryBlobPinStore(),
|
|
64
|
+
stats: { hits: 0, misses: 0, bytesDownloaded: 0 }
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
function blobPinKey(vault, collection, recordId, slotName) {
|
|
68
|
+
const prefix = `${vault}::${collection}::${recordId}::`;
|
|
69
|
+
return slotName === void 0 ? prefix : prefix + slotName;
|
|
70
|
+
}
|
|
37
71
|
|
|
38
72
|
// src/with-shape/blobs/mime-magic.ts
|
|
39
73
|
function hex(s) {
|
|
@@ -403,6 +437,12 @@ var BlobSet = class _BlobSet {
|
|
|
403
437
|
objectStore;
|
|
404
438
|
blobFields;
|
|
405
439
|
keyring;
|
|
440
|
+
/**
|
|
441
|
+
* Device-local pin registry + external side-cache + KPI counters (#808).
|
|
442
|
+
* Injected by `withBlobs()` (one shared instance per strategy — per
|
|
443
|
+
* "device"); absent on a direct construction that never threads one.
|
|
444
|
+
*/
|
|
445
|
+
pinCache;
|
|
406
446
|
/**
|
|
407
447
|
* Set only on the cleared clone `atTier()` returns (#749) — never by
|
|
408
448
|
* `openSlot`/`Collection.blob()`. Its presence is what makes a `BlobSet`
|
|
@@ -425,6 +465,7 @@ var BlobSet = class _BlobSet {
|
|
|
425
465
|
this.blobFields = opts.blobFields;
|
|
426
466
|
this.keyring = opts.keyring;
|
|
427
467
|
this.clearedTier = opts.clearedTier;
|
|
468
|
+
this.pinCache = opts.pinCache;
|
|
428
469
|
}
|
|
429
470
|
/**
|
|
430
471
|
* #724 I1 completion: a legacy (non-`perRecordKeys`) blob has no per-blob
|
|
@@ -435,7 +476,7 @@ var BlobSet = class _BlobSet {
|
|
|
435
476
|
* DECLARED; a collection with an undeclared field (or no `blobFields` at
|
|
436
477
|
* all) constructs fine and reaches this write path unguarded. Refuse the
|
|
437
478
|
* write itself instead of broadening the construction mandate, which
|
|
438
|
-
* would over-refuse blobless tiered collections (`
|
|
479
|
+
* would over-refuse blobless tiered collections (`blobsStrategy` is
|
|
439
480
|
* vault-wide, not per-collection). Called from every content-write entry
|
|
440
481
|
* (`put()`, `publish()`) — never from a read path, so a pre-existing
|
|
441
482
|
* legacy blob stays readable (back-compat).
|
|
@@ -582,7 +623,8 @@ var BlobSet = class _BlobSet {
|
|
|
582
623
|
...this.userId !== void 0 ? { userId: this.userId } : {},
|
|
583
624
|
...this.maxBlobBytes !== void 0 ? { maxBlobBytes: this.maxBlobBytes } : {},
|
|
584
625
|
...this.objectStore !== void 0 ? { objectStore: this.objectStore } : {},
|
|
585
|
-
...this.blobFields !== void 0 ? { blobFields: this.blobFields } : {}
|
|
626
|
+
...this.blobFields !== void 0 ? { blobFields: this.blobFields } : {},
|
|
627
|
+
...this.pinCache !== void 0 ? { pinCache: this.pinCache } : {}
|
|
586
628
|
});
|
|
587
629
|
}
|
|
588
630
|
/** The internal collection that holds slot metadata for this collection's blobs. */
|
|
@@ -1115,6 +1157,13 @@ var BlobSet = class _BlobSet {
|
|
|
1115
1157
|
* which are fixed for the operation's lifetime in the marker (C1/C2).
|
|
1116
1158
|
*/
|
|
1117
1159
|
async shredAllForRecord(ownerTier) {
|
|
1160
|
+
if (this.pinCache) {
|
|
1161
|
+
try {
|
|
1162
|
+
const rows = await this.pinCache.store.entries(blobPinKey(this.vault, this.collection, this.recordId));
|
|
1163
|
+
for (const { key } of rows) await this.pinCache.store.delete(key);
|
|
1164
|
+
} catch {
|
|
1165
|
+
}
|
|
1166
|
+
}
|
|
1118
1167
|
const tierArg = ownerTier ?? 0;
|
|
1119
1168
|
const intent = await this.resolveShredIntent(tierArg);
|
|
1120
1169
|
if (!intent) return this.unmarkedShred(tierArg);
|
|
@@ -1988,8 +2037,11 @@ var BlobSet = class _BlobSet {
|
|
|
1988
2037
|
for (let i = 0; i < blob.chunkCount; i++) {
|
|
1989
2038
|
const chunk = await this.readChunk(blob.eTag, i, blob.chunkCount, chunkKey);
|
|
1990
2039
|
if (!chunk) {
|
|
1991
|
-
throw new
|
|
1992
|
-
|
|
2040
|
+
throw new BlobOfflineError(
|
|
2041
|
+
this.collection,
|
|
2042
|
+
this.recordId,
|
|
2043
|
+
void 0,
|
|
2044
|
+
`chunk ${i}/${blob.chunkCount} for eTag "${blob.eTag}" is absent from the local store \u2014 content not yet synced to this device, or evicted (#808)`
|
|
1993
2045
|
);
|
|
1994
2046
|
}
|
|
1995
2047
|
chunks.push(chunk);
|
|
@@ -2310,7 +2362,11 @@ var BlobSet = class _BlobSet {
|
|
|
2310
2362
|
/**
|
|
2311
2363
|
* Fetch all bytes for the named slot.
|
|
2312
2364
|
* Returns `null` if the slot does not exist.
|
|
2313
|
-
* Throws `
|
|
2365
|
+
* Throws `BlobOfflineError` if the content is not available locally (#808):
|
|
2366
|
+
* an internal blob whose chunk envelopes are absent from the local store, or
|
|
2367
|
+
* an external slot with no local cached copy while the object store is
|
|
2368
|
+
* unreachable. External reads populate the device-local encrypted
|
|
2369
|
+
* side-cache, so a repeat read is served locally (see `pin()`).
|
|
2314
2370
|
*/
|
|
2315
2371
|
async get(slotName) {
|
|
2316
2372
|
if (await this.ownerRecordElevated()) return null;
|
|
@@ -2318,15 +2374,14 @@ var BlobSet = class _BlobSet {
|
|
|
2318
2374
|
const slot = slots[slotName];
|
|
2319
2375
|
if (!slot) return null;
|
|
2320
2376
|
if (slot.external) {
|
|
2321
|
-
|
|
2322
|
-
throw new NotFoundError(`Blob slot "${slotName}" is external but no objectStore is configured`);
|
|
2323
|
-
}
|
|
2324
|
-
return this.objectStore.getObject(slot.external.key);
|
|
2377
|
+
return this.readExternal(slotName, slot);
|
|
2325
2378
|
}
|
|
2326
2379
|
const result = await this.loadBlobObject(slot.eTag);
|
|
2327
2380
|
if (!result) return null;
|
|
2328
2381
|
const blobDEK = this.encrypted ? await this.getDEK(dekKey(BLOB_COLLECTION, result.atTier)) : void 0;
|
|
2329
|
-
|
|
2382
|
+
const bytes = await this.fetchAllChunks(result.blob, blobDEK, this.flatFallbackVerifyETag(slot.eTag, result.atTier));
|
|
2383
|
+
await this.recordLocalHit(slotName);
|
|
2384
|
+
return bytes;
|
|
2330
2385
|
}
|
|
2331
2386
|
/**
|
|
2332
2387
|
* A URL to fetch an `external` slot's object directly — presigned
|
|
@@ -2437,15 +2492,35 @@ var BlobSet = class _BlobSet {
|
|
|
2437
2492
|
/**
|
|
2438
2493
|
* List all slot entries for this record.
|
|
2439
2494
|
* Returns metadata only — no chunk data is loaded.
|
|
2495
|
+
*
|
|
2496
|
+
* #808: when a pin registry is present (`withBlobs()`), each entry is
|
|
2497
|
+
* annotated with this DEVICE's view — `pinned` / `lastAccessAt` /
|
|
2498
|
+
* `cachedBytes` (see their `SlotInfo` doc comments). The annotations come
|
|
2499
|
+
* from the device-local registry, never the vault store, and are what
|
|
2500
|
+
* `vault.compact()`'s pin exemption + cache-budget LRU pass key off.
|
|
2440
2501
|
*/
|
|
2441
2502
|
async list() {
|
|
2442
2503
|
if (await this.ownerRecordElevated()) return [];
|
|
2443
2504
|
const { slots } = await this.loadSlots();
|
|
2444
|
-
|
|
2505
|
+
const infos = Object.entries(slots).map(([name, slot]) => {
|
|
2445
2506
|
const pub = { ...slot };
|
|
2446
2507
|
delete pub.pendingRelease;
|
|
2447
2508
|
return { name, ...pub };
|
|
2448
2509
|
});
|
|
2510
|
+
if (!this.pinCache) return infos;
|
|
2511
|
+
const prefix = blobPinKey(this.vault, this.collection, this.recordId);
|
|
2512
|
+
const rows = await this.pinCache.store.entries(prefix);
|
|
2513
|
+
const byName = new Map(rows.map(({ key, entry }) => [key.slice(prefix.length), entry]));
|
|
2514
|
+
return infos.map((info) => {
|
|
2515
|
+
const entry = byName.get(info.name);
|
|
2516
|
+
if (!entry) return info;
|
|
2517
|
+
return {
|
|
2518
|
+
...info,
|
|
2519
|
+
...entry.pinned ? { pinned: true } : {},
|
|
2520
|
+
...entry.lastAccessAt !== void 0 ? { lastAccessAt: entry.lastAccessAt } : {},
|
|
2521
|
+
...entry.cachedBytes !== void 0 ? { cachedBytes: entry.cachedBytes } : {}
|
|
2522
|
+
};
|
|
2523
|
+
});
|
|
2449
2524
|
}
|
|
2450
2525
|
/**
|
|
2451
2526
|
* Delete the named slot from this record.
|
|
@@ -2471,6 +2546,218 @@ var BlobSet = class _BlobSet {
|
|
|
2471
2546
|
await this.releaseRef(eTagToRelease, 1, false).catch(() => {
|
|
2472
2547
|
});
|
|
2473
2548
|
}
|
|
2549
|
+
if (this.pinCache) {
|
|
2550
|
+
await this.pinCache.store.delete(this.pinKeyFor(slotName)).catch(() => {
|
|
2551
|
+
});
|
|
2552
|
+
}
|
|
2553
|
+
}
|
|
2554
|
+
// ─── Public API: Offline pinning + device-local cache (#808) ──────
|
|
2555
|
+
/**
|
|
2556
|
+
* Pin the named slot for offline availability ON THIS DEVICE.
|
|
2557
|
+
*
|
|
2558
|
+
* - Downloads eagerly (call while online): an internal blob's chunks are
|
|
2559
|
+
* fetched once to prove they are locally readable; an `external` slot's
|
|
2560
|
+
* bytes are fetched from the object store and kept in the device-local
|
|
2561
|
+
* side-cache, **encrypted** under the vault's `_blob` DEK via the same
|
|
2562
|
+
* enclave path as chunk encryption (the object-store copy sits outside
|
|
2563
|
+
* the ZK envelope by design; the local copy does not).
|
|
2564
|
+
* - A pinned slot is EXEMPT from `vault.compact()` eviction — both the
|
|
2565
|
+
* `blobFields` policy pass and the `cacheBudget` LRU pass.
|
|
2566
|
+
* - Pin state is device-local (never synced): it lives in the `withBlobs()`
|
|
2567
|
+
* pin registry, not in the vault store. Each device pins for itself.
|
|
2568
|
+
*
|
|
2569
|
+
* Throws `NotFoundError` for a missing slot and `BlobOfflineError` when the
|
|
2570
|
+
* eager download cannot complete (offline).
|
|
2571
|
+
*/
|
|
2572
|
+
async pin(slotName) {
|
|
2573
|
+
this.assertKeyPartSafe(this.recordId, "record id");
|
|
2574
|
+
this.assertKeyPartSafe(slotName, "slot name");
|
|
2575
|
+
const pc = this.requirePinCache("pin");
|
|
2576
|
+
if (await this.ownerRecordElevated()) {
|
|
2577
|
+
throw new NotFoundError(`Slot "${slotName}" not found on record "${this.recordId}"`);
|
|
2578
|
+
}
|
|
2579
|
+
const { slots } = await this.loadSlots();
|
|
2580
|
+
const slot = slots[slotName];
|
|
2581
|
+
if (!slot) throw new NotFoundError(`Slot "${slotName}" not found on record "${this.recordId}"`);
|
|
2582
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
2583
|
+
if (slot.external) {
|
|
2584
|
+
const bytes = await this.readExternal(slotName, slot);
|
|
2585
|
+
if (bytes === null) {
|
|
2586
|
+
throw new NotFoundError(`External object for blob slot "${slotName}" is missing from the object store`);
|
|
2587
|
+
}
|
|
2588
|
+
const key2 = this.pinKeyFor(slotName);
|
|
2589
|
+
const entry = await pc.store.get(key2);
|
|
2590
|
+
if (entry?.cipher) {
|
|
2591
|
+
await pc.store.set(key2, { ...entry, pinned: true, pinnedAt: entry.pinnedAt ?? now });
|
|
2592
|
+
} else {
|
|
2593
|
+
await this.cacheExternalCopy(slotName, bytes, { pin: true });
|
|
2594
|
+
}
|
|
2595
|
+
return;
|
|
2596
|
+
}
|
|
2597
|
+
const result = await this.loadBlobObject(slot.eTag);
|
|
2598
|
+
if (!result) throw new NotFoundError(`BlobObject ${slot.eTag} not found`);
|
|
2599
|
+
const blobDEK = this.encrypted ? await this.getDEK(dekKey(BLOB_COLLECTION, result.atTier)) : void 0;
|
|
2600
|
+
await this.fetchAllChunks(result.blob, blobDEK, this.flatFallbackVerifyETag(slot.eTag, result.atTier));
|
|
2601
|
+
const key = this.pinKeyFor(slotName);
|
|
2602
|
+
const prev = await pc.store.get(key);
|
|
2603
|
+
await pc.store.set(key, { ...prev ?? {}, pinned: true, pinnedAt: now, lastAccessAt: now });
|
|
2604
|
+
}
|
|
2605
|
+
/**
|
|
2606
|
+
* Unpin the named slot on this device — it returns to the normal lifecycle:
|
|
2607
|
+
* `blobFields` policy eviction applies again, and any local cached copy
|
|
2608
|
+
* (external slots) stays but becomes budget-managed (`cacheBudget` LRU).
|
|
2609
|
+
* A no-op when the slot is not pinned here.
|
|
2610
|
+
*/
|
|
2611
|
+
async unpin(slotName) {
|
|
2612
|
+
this.assertKeyPartSafe(slotName, "slot name");
|
|
2613
|
+
const pc = this.requirePinCache("unpin");
|
|
2614
|
+
const key = this.pinKeyFor(slotName);
|
|
2615
|
+
const entry = await pc.store.get(key);
|
|
2616
|
+
if (!entry?.pinned) return;
|
|
2617
|
+
const rest = { ...entry, pinned: false };
|
|
2618
|
+
delete rest.pinnedAt;
|
|
2619
|
+
await pc.store.set(key, rest);
|
|
2620
|
+
}
|
|
2621
|
+
/** Whether the named slot is pinned for offline ON THIS DEVICE (#808). */
|
|
2622
|
+
async isPinned(slotName) {
|
|
2623
|
+
const pc = this.requirePinCache("isPinned");
|
|
2624
|
+
const entry = await pc.store.get(this.pinKeyFor(slotName));
|
|
2625
|
+
return entry?.pinned === true;
|
|
2626
|
+
}
|
|
2627
|
+
/**
|
|
2628
|
+
* Drop this slot's device-local cached copy (the encrypted external
|
|
2629
|
+
* side-cache) WITHOUT touching the slot, the vault store, or the object
|
|
2630
|
+
* store. Returns the plaintext bytes freed (0 when nothing was cached, the
|
|
2631
|
+
* slot is pinned — pinned copies are exempt — or no registry is present).
|
|
2632
|
+
* The cache-budget pass inside `vault.compact()` is the expected caller;
|
|
2633
|
+
* the LRU access row itself is kept.
|
|
2634
|
+
*/
|
|
2635
|
+
async dropLocalCache(slotName) {
|
|
2636
|
+
const pc = this.pinCache;
|
|
2637
|
+
if (!pc) return 0;
|
|
2638
|
+
const key = this.pinKeyFor(slotName);
|
|
2639
|
+
const entry = await pc.store.get(key);
|
|
2640
|
+
if (!entry || entry.pinned || !entry.cipher) return 0;
|
|
2641
|
+
const freed = entry.cachedBytes ?? 0;
|
|
2642
|
+
const rest = { ...entry };
|
|
2643
|
+
delete rest.cipher;
|
|
2644
|
+
delete rest.cachedBytes;
|
|
2645
|
+
await pc.store.set(key, rest);
|
|
2646
|
+
return freed;
|
|
2647
|
+
}
|
|
2648
|
+
// ─── Internal: device-local pin registry plumbing (#808) ──────────
|
|
2649
|
+
/** This slot's registry key — see {@link blobPinKey}. */
|
|
2650
|
+
pinKeyFor(slotName) {
|
|
2651
|
+
return blobPinKey(this.vault, this.collection, this.recordId, slotName);
|
|
2652
|
+
}
|
|
2653
|
+
/** AAD binding for a cached external copy: the row's own registry key. */
|
|
2654
|
+
pinCopyAAD(slotName) {
|
|
2655
|
+
return new TextEncoder().encode(`pin:${this.pinKeyFor(slotName)}`);
|
|
2656
|
+
}
|
|
2657
|
+
requirePinCache(op) {
|
|
2658
|
+
if (!this.pinCache) {
|
|
2659
|
+
throw new ValidationError(
|
|
2660
|
+
`BlobSet.${op}() requires the withBlobs() pin registry \u2014 this handle was constructed without one (#808)`
|
|
2661
|
+
);
|
|
2662
|
+
}
|
|
2663
|
+
return this.pinCache;
|
|
2664
|
+
}
|
|
2665
|
+
/** KPI hit + LRU access stamp for a successful LOCAL read. No-op without a registry. */
|
|
2666
|
+
async recordLocalHit(slotName, prev) {
|
|
2667
|
+
const pc = this.pinCache;
|
|
2668
|
+
if (!pc) return;
|
|
2669
|
+
pc.stats.hits += 1;
|
|
2670
|
+
const key = this.pinKeyFor(slotName);
|
|
2671
|
+
const entry = prev ?? await pc.store.get(key);
|
|
2672
|
+
await pc.store.set(key, { ...entry ?? { pinned: false }, lastAccessAt: (/* @__PURE__ */ new Date()).toISOString() });
|
|
2673
|
+
}
|
|
2674
|
+
/**
|
|
2675
|
+
* Read an `external` slot (#808 taxonomy): local encrypted side-cache first
|
|
2676
|
+
* (hit); else the object store (miss + `bytesDownloaded`), auto-caching the
|
|
2677
|
+
* fetched bytes so the NEXT read — and any later offline read — is local.
|
|
2678
|
+
* A network failure with no local copy is the typed `BlobOfflineError`;
|
|
2679
|
+
* a genuinely absent object (fetch succeeded, nothing there) stays `null`.
|
|
2680
|
+
*/
|
|
2681
|
+
async readExternal(slotName, slot) {
|
|
2682
|
+
const pc = this.pinCache;
|
|
2683
|
+
if (pc) {
|
|
2684
|
+
const key = this.pinKeyFor(slotName);
|
|
2685
|
+
const entry = await pc.store.get(key);
|
|
2686
|
+
const cached = entry?.cipher ? await this.decryptCachedCopy(slotName, entry.cipher) : null;
|
|
2687
|
+
if (cached) {
|
|
2688
|
+
await this.recordLocalHit(slotName, entry);
|
|
2689
|
+
return cached;
|
|
2690
|
+
}
|
|
2691
|
+
}
|
|
2692
|
+
if (!this.objectStore) {
|
|
2693
|
+
throw new NotFoundError(`Blob slot "${slotName}" is external but no objectStore is configured`);
|
|
2694
|
+
}
|
|
2695
|
+
let bytes;
|
|
2696
|
+
try {
|
|
2697
|
+
bytes = await this.objectStore.getObject(slot.external.key);
|
|
2698
|
+
} catch (err) {
|
|
2699
|
+
throw new BlobOfflineError(
|
|
2700
|
+
this.collection,
|
|
2701
|
+
this.recordId,
|
|
2702
|
+
slotName,
|
|
2703
|
+
"no local cached copy and the object store is unreachable \u2014 pin() the slot while online to keep it readable offline (#808)",
|
|
2704
|
+
err
|
|
2705
|
+
);
|
|
2706
|
+
}
|
|
2707
|
+
if (bytes === null) return null;
|
|
2708
|
+
if (pc) {
|
|
2709
|
+
pc.stats.misses += 1;
|
|
2710
|
+
pc.stats.bytesDownloaded += bytes.byteLength;
|
|
2711
|
+
await this.cacheExternalCopy(slotName, bytes).catch(() => {
|
|
2712
|
+
});
|
|
2713
|
+
}
|
|
2714
|
+
return bytes;
|
|
2715
|
+
}
|
|
2716
|
+
/**
|
|
2717
|
+
* Decrypt a cached external copy. `null` (treated as a cache miss → network
|
|
2718
|
+
* refresh) when the vault keys can no longer open it — e.g. the copy was
|
|
2719
|
+
* cached before the owning record moved tiers, so it is sealed under a DEK
|
|
2720
|
+
* this handle no longer resolves. Genuine non-crypto failures propagate.
|
|
2721
|
+
*/
|
|
2722
|
+
async decryptCachedCopy(slotName, cipher) {
|
|
2723
|
+
if (!this.encrypted) return base64ToBuffer(cipher.data);
|
|
2724
|
+
const dek = await this.getDEK(dekKey(BLOB_COLLECTION, await this.ownerTier()));
|
|
2725
|
+
try {
|
|
2726
|
+
return await decryptBytesWithAAD(cipher.iv, cipher.data, dek, this.pinCopyAAD(slotName));
|
|
2727
|
+
} catch (err) {
|
|
2728
|
+
if (err instanceof TamperedError) return null;
|
|
2729
|
+
throw err;
|
|
2730
|
+
}
|
|
2731
|
+
}
|
|
2732
|
+
/**
|
|
2733
|
+
* Write an external slot's bytes into the device-local side-cache —
|
|
2734
|
+
* ENCRYPTED under the vault's `_blob` DEK (owner tier) via the enclave's
|
|
2735
|
+
* AAD-bound path, mirroring chunk encryption; base64 plaintext with
|
|
2736
|
+
* `iv: ''` only on an unencrypted vault (the envelope convention). A
|
|
2737
|
+
* pre-existing pin flag survives the rewrite.
|
|
2738
|
+
*/
|
|
2739
|
+
async cacheExternalCopy(slotName, bytes, opts) {
|
|
2740
|
+
const pc = this.pinCache;
|
|
2741
|
+
if (!pc) return;
|
|
2742
|
+
let cipher;
|
|
2743
|
+
if (this.encrypted) {
|
|
2744
|
+
const dek = await this.getDEK(dekKey(BLOB_COLLECTION, await this.ownerTier()));
|
|
2745
|
+
const enc = await encryptBytesWithAAD(bytes, dek, this.pinCopyAAD(slotName));
|
|
2746
|
+
cipher = { iv: enc.iv, data: enc.data };
|
|
2747
|
+
} else {
|
|
2748
|
+
cipher = { iv: "", data: bufferToBase64(bytes) };
|
|
2749
|
+
}
|
|
2750
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
2751
|
+
const key = this.pinKeyFor(slotName);
|
|
2752
|
+
const prev = await pc.store.get(key);
|
|
2753
|
+
const pinned = opts?.pin === true || prev?.pinned === true;
|
|
2754
|
+
await pc.store.set(key, {
|
|
2755
|
+
pinned,
|
|
2756
|
+
...pinned ? { pinnedAt: (opts?.pin === true ? now : prev?.pinnedAt) ?? now } : {},
|
|
2757
|
+
lastAccessAt: now,
|
|
2758
|
+
cachedBytes: bytes.byteLength,
|
|
2759
|
+
cipher
|
|
2760
|
+
});
|
|
2474
2761
|
}
|
|
2475
2762
|
/**
|
|
2476
2763
|
* Return a native `Response` whose body streams the decrypted,
|
|
@@ -2763,6 +3050,9 @@ async function plainSha256Hex(data) {
|
|
|
2763
3050
|
}
|
|
2764
3051
|
|
|
2765
3052
|
export {
|
|
3053
|
+
memoryBlobPinStore,
|
|
3054
|
+
createBlobPinCache,
|
|
3055
|
+
blobPinKey,
|
|
2766
3056
|
detectMimeType,
|
|
2767
3057
|
detectMagic,
|
|
2768
3058
|
isPreCompressed,
|
|
@@ -2779,4 +3069,4 @@ export {
|
|
|
2779
3069
|
DEFAULT_CHUNK_SIZE,
|
|
2780
3070
|
BlobSet
|
|
2781
3071
|
};
|
|
2782
|
-
//# sourceMappingURL=chunk-
|
|
3072
|
+
//# sourceMappingURL=chunk-GWWOGNBK.js.map
|