@noy-db/hub 0.4.0 → 0.6.0-pre.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api-67SBPMMH.js +20 -0
- package/dist/attestation/index.js +18 -18
- package/dist/{backup-X7F3TCFV.js → backup-GAYWQAFN.js} +16 -11
- package/dist/backup-GAYWQAFN.js.map +1 -0
- package/dist/blobs/index.js +20 -20
- package/dist/broker/index.js +12 -12
- package/dist/bundle-handle-5OUAI7CV.js +36 -0
- package/dist/bundle-handle-5OUAI7CV.js.map +1 -0
- package/dist/cargo/index.js +36 -36
- package/dist/{chunk-DQZXPGGZ.js → chunk-24UICKTB.js} +3 -3
- package/dist/{chunk-77AEMXFA.js → chunk-24ZLWWEO.js} +1 -1
- package/dist/chunk-24ZLWWEO.js.map +1 -0
- package/dist/{chunk-2BET5QTS.js → chunk-27TCYH6G.js} +5 -5
- package/dist/{chunk-MSMJJB4J.js → chunk-2KIV7BEK.js} +2 -2
- package/dist/{chunk-6ZNSB3H6.js → chunk-2LGDCNFJ.js} +2 -2
- package/dist/{chunk-GTYFIVIZ.js → chunk-35EBKWQU.js} +5 -5
- package/dist/chunk-35EBKWQU.js.map +1 -0
- package/dist/{chunk-WBKZUO5V.js → chunk-3737A6EA.js} +3 -3
- package/dist/{chunk-ZBYFMI6D.js → chunk-3CLZY46Y.js} +638 -300
- package/dist/chunk-3CLZY46Y.js.map +1 -0
- package/dist/{chunk-HLKXPJ4V.js → chunk-3EO7RZLJ.js} +6 -6
- package/dist/{chunk-JYJFGD2H.js → chunk-3FSX6LDG.js} +2 -2
- package/dist/{chunk-MXUT7FTE.js → chunk-3HYWYLXL.js} +2 -2
- package/dist/{chunk-IVYQAVWO.js → chunk-3IIPWA75.js} +11 -11
- package/dist/{chunk-7H3WWH6J.js → chunk-3UK6STWO.js} +3 -3
- package/dist/chunk-46V67XP5.js +117 -0
- package/dist/chunk-46V67XP5.js.map +1 -0
- package/dist/{chunk-NJ4DYYO5.js → chunk-4HDYQL3J.js} +2 -2
- package/dist/{chunk-P4JO3H6R.js → chunk-4MQDV3HZ.js} +2 -2
- package/dist/{chunk-X4MVWPHV.js → chunk-4UVDI4XE.js} +3 -3
- package/dist/{chunk-LXRTP3AQ.js → chunk-4VCWI42L.js} +2 -2
- package/dist/{chunk-QJNCB5SK.js → chunk-747LRSOO.js} +2 -2
- package/dist/{chunk-3HUYRN24.js → chunk-7F4DBNSP.js} +3 -3
- package/dist/{chunk-UADPR6F4.js → chunk-7G6VDWXB.js} +3 -3
- package/dist/{chunk-PTHKZWEH.js → chunk-AHLJSVRL.js} +2 -2
- package/dist/{chunk-NFZGZ4AK.js → chunk-AR2JDFAE.js} +2 -2
- package/dist/{chunk-3ECU57YH.js → chunk-BPTZ4K5L.js} +11 -11
- package/dist/{chunk-KRCBZYTZ.js → chunk-CCZJJ4I2.js} +4 -4
- package/dist/{chunk-NYEFP7DY.js → chunk-CJ73OLMW.js} +2 -2
- package/dist/{chunk-Q36YXK77.js → chunk-CYQOUTMY.js} +3 -3
- package/dist/{chunk-RBTVFPHF.js → chunk-DCMQR46R.js} +5 -5
- package/dist/{chunk-TG634KCO.js → chunk-DG27IUVI.js} +2 -2
- package/dist/{chunk-E23UGFVC.js → chunk-DMQCLZ4Z.js} +8 -6
- package/dist/chunk-DMQCLZ4Z.js.map +1 -0
- package/dist/{chunk-ZNWSG7XC.js → chunk-DPJTDNUF.js} +68 -34
- package/dist/chunk-DPJTDNUF.js.map +1 -0
- package/dist/{chunk-V6UQZA2H.js → chunk-E6427JU2.js} +2 -2
- package/dist/{chunk-JEI6JJNI.js → chunk-EK7DT5BT.js} +220 -13
- package/dist/chunk-EK7DT5BT.js.map +1 -0
- package/dist/chunk-EPFF7LOX.js +14 -0
- package/dist/chunk-EPFF7LOX.js.map +1 -0
- package/dist/{chunk-TWPK7KUJ.js → chunk-F3GVO44K.js} +6 -6
- package/dist/{chunk-QD46HPZG.js → chunk-FAXZQ5UF.js} +2 -2
- package/dist/{chunk-IG6KUWBX.js → chunk-FNSMZQS4.js} +2 -2
- package/dist/{chunk-BLBAQRBM.js → chunk-FUHKW252.js} +2 -2
- package/dist/{chunk-SU6SGWXM.js → chunk-FY343IZR.js} +8 -8
- package/dist/{chunk-KPZS5QAQ.js → chunk-GQ3BX5EA.js} +9 -1
- package/dist/chunk-GQ3BX5EA.js.map +1 -0
- package/dist/{chunk-DAFBJS4Y.js → chunk-GS5RT2KK.js} +4 -4
- package/dist/{chunk-5UQ7Y6SQ.js → chunk-HFKGIBMD.js} +3 -3
- package/dist/{chunk-QZWTRENR.js → chunk-HNGSV2YC.js} +133 -1
- package/dist/chunk-HNGSV2YC.js.map +1 -0
- package/dist/chunk-HNHCQ556.js +63 -0
- package/dist/chunk-HNHCQ556.js.map +1 -0
- package/dist/chunk-HS7HNYBD.js +91 -0
- package/dist/chunk-HS7HNYBD.js.map +1 -0
- package/dist/{chunk-SHEEBRZ4.js → chunk-HVQGCKY4.js} +2 -2
- package/dist/{chunk-35NMVJ7I.js → chunk-HXGUIPQB.js} +3 -3
- package/dist/{chunk-ERGECZEI.js → chunk-JEM2IGS3.js} +9 -9
- package/dist/chunk-JH3OHQM4.js +260 -0
- package/dist/chunk-JH3OHQM4.js.map +1 -0
- package/dist/{chunk-L3YYLT4E.js → chunk-JIUVJ4M7.js} +2 -2
- package/dist/{chunk-55LX6FSX.js → chunk-JRCYZEHU.js} +2 -2
- package/dist/{chunk-SFBYQMZM.js → chunk-JSRU5W2M.js} +5 -5
- package/dist/{chunk-NM5UYF6Q.js → chunk-JXIDGFKS.js} +2 -2
- package/dist/{chunk-VYYM3MEN.js → chunk-KHKKD62N.js} +16 -2
- package/dist/chunk-KHKKD62N.js.map +1 -0
- package/dist/{chunk-FQ5CHJR7.js → chunk-KUDZVJKQ.js} +21 -2
- package/dist/chunk-KUDZVJKQ.js.map +1 -0
- package/dist/{chunk-RO5NM6UI.js → chunk-KZ3KMDN3.js} +2 -2
- package/dist/{chunk-HZZP2ZIG.js → chunk-LBGPO5RL.js} +6 -6
- package/dist/{chunk-ZFG5EBI3.js → chunk-LTU4FLHG.js} +57 -27
- package/dist/chunk-LTU4FLHG.js.map +1 -0
- package/dist/{chunk-CLE3TMIS.js → chunk-MC2LFTQM.js} +5 -2
- package/dist/{chunk-467SWYT5.js → chunk-MJWCLSQL.js} +17 -8
- package/dist/chunk-MJWCLSQL.js.map +1 -0
- package/dist/{chunk-W3G5REIU.js → chunk-MSWYQLMQ.js} +2 -2
- package/dist/{chunk-WK7ULBTP.js → chunk-MVOWXQHN.js} +5 -3
- package/dist/chunk-MVOWXQHN.js.map +1 -0
- package/dist/{chunk-2J6UEN2V.js → chunk-MXZ5TSTR.js} +118 -4
- package/dist/chunk-MXZ5TSTR.js.map +1 -0
- package/dist/{chunk-SGDPRCC4.js → chunk-MZ5ZFO2D.js} +3 -3
- package/dist/{chunk-NBXFCQX4.js → chunk-NQCNSVGI.js} +9 -9
- package/dist/chunk-NQCNSVGI.js.map +1 -0
- package/dist/{chunk-EFJAAFBW.js → chunk-NQRJ5AJO.js} +2 -2
- package/dist/{chunk-Q2SEJMP2.js → chunk-NVU7ZMPN.js} +2 -2
- package/dist/{chunk-ZTLOXFPB.js → chunk-OF3L2SD6.js} +2 -2
- package/dist/{chunk-LLYIMSQQ.js → chunk-OMSAULZM.js} +11 -11
- package/dist/{chunk-SF2ZIRD6.js → chunk-OSFPNKY4.js} +3 -3
- package/dist/{chunk-WUHEP3HH.js → chunk-P7NGLLUF.js} +5 -5
- package/dist/{chunk-RQ4ZI4ZI.js → chunk-PGAPBZEK.js} +7 -7
- package/dist/{chunk-T2MOJF76.js → chunk-PP5CO2PR.js} +6 -6
- package/dist/{chunk-Q5YJCVJY.js → chunk-RLWY6Z44.js} +227 -41
- package/dist/chunk-RLWY6Z44.js.map +1 -0
- package/dist/{chunk-QGIBI6GL.js → chunk-ROWL352P.js} +5 -5
- package/dist/{chunk-ZHDSUZQU.js → chunk-RPXL6KSX.js} +4 -4
- package/dist/{chunk-DTFA5DO4.js → chunk-SKONR2OL.js} +3 -3
- package/dist/{chunk-AT2JJEKJ.js → chunk-SRGJET2F.js} +16 -5
- package/dist/chunk-SRGJET2F.js.map +1 -0
- package/dist/{chunk-4ZKNC6A6.js → chunk-T4GPR2IR.js} +2 -2
- package/dist/{chunk-NLYALJMY.js → chunk-TFZ7LLOQ.js} +113 -36
- package/dist/chunk-TFZ7LLOQ.js.map +1 -0
- package/dist/{chunk-TS5XLBZR.js → chunk-TLNNHG3A.js} +4 -4
- package/dist/{chunk-6UBZ6I5Z.js → chunk-UHXCLPGC.js} +2 -2
- package/dist/{chunk-KD4HGBJV.js → chunk-V5C5NNBR.js} +4 -4
- package/dist/{chunk-WYUAEZSC.js → chunk-VBY6ZLJT.js} +15 -14
- package/dist/chunk-VBY6ZLJT.js.map +1 -0
- package/dist/{chunk-AKKRXT23.js → chunk-VCETL77O.js} +34 -16
- package/dist/chunk-VCETL77O.js.map +1 -0
- package/dist/{chunk-5GQEU4DN.js → chunk-VJFMXYKP.js} +2 -2
- package/dist/{chunk-5DRROK5W.js → chunk-VMCCGUQB.js} +2 -2
- package/dist/{chunk-IXNCZTWA.js → chunk-W3TVWF6N.js} +2 -2
- package/dist/{chunk-W66AM5IB.js → chunk-WLYIROCJ.js} +2 -2
- package/dist/{chunk-OWHP3H5C.js → chunk-XB7LUDKM.js} +4 -4
- package/dist/{chunk-KYRDJI5O.js → chunk-XBLKM73C.js} +10 -10
- package/dist/{chunk-MHMLXJ3I.js → chunk-YAWK6AWF.js} +2 -2
- package/dist/{chunk-PWPYO73B.js → chunk-ZGGVOADG.js} +5 -5
- package/dist/{chunk-YGK2HMLR.js → chunk-ZK4CO2KZ.js} +9 -9
- package/dist/chunk-ZK4CO2KZ.js.map +1 -0
- package/dist/{chunk-DSDXAKIP.js → chunk-ZVF37PKE.js} +34 -5
- package/dist/chunk-ZVF37PKE.js.map +1 -0
- package/dist/{chunk-IFOH7RBI.js → chunk-ZWMO5GL5.js} +5 -5
- package/dist/{chunk-LRRX57UA.js → chunk-ZXJXDHNK.js} +4 -4
- package/dist/classified/index.js +5 -5
- package/dist/{classified-marker-LE54HWSX.js → classified-marker-MH3ON5OL.js} +3 -3
- package/dist/collection-facade-AHT7FATG.js +45 -0
- package/dist/{computed-AB45PS4V.js → computed-6G5M3UPH.js} +3 -3
- package/dist/consent/index.js +9 -9
- package/dist/cover/index.js +3 -3
- package/dist/custody/index.js +11 -11
- package/dist/{dead-filter-V3LVWYEJ.js → dead-filter-U575NGSH.js} +2 -2
- package/dist/debug/index.js +1 -1
- package/dist/{delegation-JDUMAF6L.js → delegation-PDYL6RWT.js} +10 -10
- package/dist/derivations/index.js +12 -12
- package/dist/derive-AKT4KU36.js +22 -0
- package/dist/directory/index.js +10 -10
- package/dist/{dispatch-6TV3DGO6.js → dispatch-4XIJSFTT.js} +5 -5
- package/dist/{dispatch-W7NWQ637.js → dispatch-N5HGVUGU.js} +18 -18
- package/dist/{enclave-YFCLPIDR.js → enclave-OPK24QDR.js} +13 -9
- package/dist/executor-3JZ4POTW.js +28 -0
- package/dist/executor-CYJQLKKI.js +9 -0
- package/dist/executor-S4QIKEHW.js +9 -0
- package/dist/export-accessible-CPTP5STN.js +23 -0
- package/dist/extract-partition-TWXPHVU7.js +38 -0
- package/dist/{fanout-sidecar-273RDMYS.js → fanout-sidecar-T2ZGLQFE.js} +9 -9
- package/dist/find-RBBYKXI7.js +11 -0
- package/dist/forget/index.js +9 -9
- package/dist/guards/index.js +6 -6
- package/dist/history/index.js +15 -15
- package/dist/i18n/index.js +14 -14
- package/dist/index.d.ts +35 -7
- package/dist/index.js +279 -202
- package/dist/index.js.map +1 -1
- package/dist/indexing/index.js +3 -3
- package/dist/introspection/index.js +12 -12
- package/dist/issue-N74C55X6.js +19 -0
- package/dist/kernel/collection-config.d.ts +4 -0
- package/dist/kernel/collection.d.ts +34 -8
- package/dist/kernel/cutover-transform.d.ts +64 -0
- package/dist/kernel/enclave/crypto.d.ts +24 -0
- package/dist/kernel/enclave/index.d.ts +2 -1
- package/dist/kernel/errors.d.ts +138 -0
- package/dist/kernel/noydb.d.ts +10 -1
- package/dist/kernel/put-many-atomic.d.ts +45 -0
- package/dist/kernel/secret-mode.d.ts +59 -0
- package/dist/kernel/types.d.ts +98 -7
- package/dist/kernel/validation.d.ts +33 -0
- package/dist/kernel/vault.d.ts +32 -6
- package/dist/{ledger-XE7JF2I2.js → ledger-DONWFC5M.js} +11 -11
- package/dist/liberate-KICI7AJN.js +24 -0
- package/dist/{link-set-CGYC3OH5.js → link-set-2TTP4VLO.js} +11 -11
- package/dist/managed-secret-EAOYWRYF.js +27 -0
- package/dist/materialized-views/index.js +19 -19
- package/dist/money/index.js +3 -3
- package/dist/noydb-6W2XGQCS.js +83 -0
- package/dist/overlay-views/index.js +6 -6
- package/dist/periods/index.js +16 -16
- package/dist/pod/index.js +121 -12
- package/dist/policy/index.js +4 -4
- package/dist/port/to/index.d.ts +3 -1
- package/dist/port/to/locator.d.ts +84 -0
- package/dist/port/with/device-seal-strategy.d.ts +16 -0
- package/dist/port/with/strategies.d.ts +2 -0
- package/dist/port/with/write-hooks.d.ts +6 -0
- package/dist/portability/index.js +8 -8
- package/dist/{post-register-LY35EDTJ.js → post-register-ORQOQJCS.js} +6 -6
- package/dist/query/index.js +4 -4
- package/dist/reduce/index.js +4 -4
- package/dist/register-LHETZRJM.js +32 -0
- package/dist/registry-AMAZ6QRZ.js +19 -0
- package/dist/registry-CZVINVQH.js +9 -0
- package/dist/registry-IKUR2MXD.js +9 -0
- package/dist/registry-JRIN447B.js +18 -0
- package/dist/request-withdrawal-2DN2RGCO.js +31 -0
- package/dist/{reveal-T34ADTPY.js → reveal-AG4SCHUQ.js} +6 -6
- package/dist/revoke-ZX4NM2CJ.js +24 -0
- package/dist/satellites/index.js +1 -1
- package/dist/schema-update/index.js +6 -6
- package/dist/sealed-record/index.js +12 -12
- package/dist/search/index.js +4 -4
- package/dist/{seed-JOV54PB3.js → seed-IRCDGIRK.js} +15 -15
- package/dist/seed-IRCDGIRK.js.map +1 -0
- package/dist/sequence/index.js +9 -9
- package/dist/session/index.js +9 -9
- package/dist/shadow/index.js +2 -2
- package/dist/signer-7KHD4OL2.js +25 -0
- package/dist/snapshots/index.js +10 -10
- package/dist/{stale-T3V7XEOB.js → stale-K734VACF.js} +10 -10
- package/dist/storage-4H2GF6RQ.js +23 -0
- package/dist/{store-coordination-provider-AHGFEMFA.js → store-coordination-provider-4SKLSFUG.js} +3 -3
- package/dist/sync/index.js +10 -10
- package/dist/team/index.js +27 -15
- package/dist/tiers/index.js +10 -10
- package/dist/to/index.js +28 -3
- package/dist/to/index.js.map +1 -1
- package/dist/transactions/index.js +3 -3
- package/dist/util/index.js +1 -1
- package/dist/{verify-7XWHJWUN.js → verify-RO5RTZOJ.js} +5 -5
- package/dist/walk-MQHYNDLZ.js +21 -0
- package/dist/with-audit/guards/registry.d.ts +8 -1
- package/dist/with-audit/guards/types.d.ts +5 -0
- package/dist/with-audit/periods/index.d.ts +1 -1
- package/dist/with-audit/periods/periods.d.ts +7 -0
- package/dist/with-commit/tx/atomic-eligibility.d.ts +13 -11
- package/dist/with-formula/derivations/registry.d.ts +6 -0
- package/dist/with-formula/derivations/types.d.ts +5 -0
- package/dist/with-lookup/indexing/eager-indexes.d.ts +10 -0
- package/dist/with-party/team/device-seal.d.ts +25 -0
- package/dist/with-party/team/echo-ceremony.d.ts +74 -0
- package/dist/with-party/team/echo-secret.d.ts +56 -0
- package/dist/with-party/team/index.d.ts +8 -0
- package/dist/with-party/team/keyring.d.ts +71 -9
- package/dist/with-party/team/rotate-recover.d.ts +99 -5
- package/dist/with-pod/bundle-handle.d.ts +9 -0
- package/dist/with-pod/bundle.d.ts +100 -2
- package/dist/with-pod/format.d.ts +92 -1
- package/dist/with-pod/index.d.ts +22 -1
- package/dist/with-pod/open.d.ts +117 -0
- package/dist/with-pod/redirect.d.ts +78 -0
- package/dist/with-pod/signature.d.ts +13 -0
- package/dist/with-shape/introspection/behaviors.d.ts +100 -0
- package/dist/with-shape/introspection/derivation-key.d.ts +17 -0
- package/dist/with-shape/introspection/describe.d.ts +36 -0
- package/dist/with-shape/introspection/index.d.ts +1 -0
- package/dist/with-shape/introspection/subsystem-matrix.d.ts +22 -0
- package/dist/with-shape/introspection/types.d.ts +2 -1
- package/dist/with-shape/links/names.d.ts +14 -0
- package/dist/with-shape/manifest/derive.d.ts +86 -0
- package/dist/with-shape/manifest/reserved-collections.d.ts +27 -0
- package/dist/with-shape/manifest/storage.d.ts +62 -0
- package/dist/with-shape/manifest/sync.d.ts +135 -0
- package/dist/with-shape/manifest/types.d.ts +49 -0
- package/dist/with-shape/manifest/writer.d.ts +32 -0
- package/dist/with-shape/persisted-schemas/field-ids.d.ts +29 -0
- package/dist/with-shape/persisted-schemas/register.d.ts +3 -0
- package/dist/with-shape/persisted-schemas/types.d.ts +17 -0
- package/dist/with-shape/schema-update/fence-controller.d.ts +34 -0
- package/dist/with-shape/schema-update/fence.d.ts +9 -0
- package/dist/with-shape/schema-update/strategies.d.ts +18 -2
- package/dist/with-shape/schema-update/types.d.ts +11 -0
- package/dist/with-sync/engine.d.ts +17 -0
- package/dist/with-sync/presence.d.ts +31 -1
- package/dist/withdraw-accessible-JSDQHXHE.js +28 -0
- package/dist/withdraw-accessible-JSDQHXHE.js.map +1 -0
- package/package.json +3 -3
- package/dist/api-SI2IVBQO.js +0 -20
- package/dist/backup-X7F3TCFV.js.map +0 -1
- package/dist/chunk-2J6UEN2V.js.map +0 -1
- package/dist/chunk-467SWYT5.js.map +0 -1
- package/dist/chunk-4JQK3L4V.js +0 -41
- package/dist/chunk-4JQK3L4V.js.map +0 -1
- package/dist/chunk-77AEMXFA.js.map +0 -1
- package/dist/chunk-AKKRXT23.js.map +0 -1
- package/dist/chunk-AT2JJEKJ.js.map +0 -1
- package/dist/chunk-DSDXAKIP.js.map +0 -1
- package/dist/chunk-E23UGFVC.js.map +0 -1
- package/dist/chunk-FQ5CHJR7.js.map +0 -1
- package/dist/chunk-GTYFIVIZ.js.map +0 -1
- package/dist/chunk-JEI6JJNI.js.map +0 -1
- package/dist/chunk-JQ2AX4T5.js +0 -23
- package/dist/chunk-JQ2AX4T5.js.map +0 -1
- package/dist/chunk-KPZS5QAQ.js.map +0 -1
- package/dist/chunk-NBXFCQX4.js.map +0 -1
- package/dist/chunk-NLYALJMY.js.map +0 -1
- package/dist/chunk-Q5YJCVJY.js.map +0 -1
- package/dist/chunk-QZWTRENR.js.map +0 -1
- package/dist/chunk-S7GIXBXV.js +0 -129
- package/dist/chunk-S7GIXBXV.js.map +0 -1
- package/dist/chunk-SBHN6QUT.js +0 -25
- package/dist/chunk-SBHN6QUT.js.map +0 -1
- package/dist/chunk-VYYM3MEN.js.map +0 -1
- package/dist/chunk-WK7ULBTP.js.map +0 -1
- package/dist/chunk-WYUAEZSC.js.map +0 -1
- package/dist/chunk-YGK2HMLR.js.map +0 -1
- package/dist/chunk-ZBYFMI6D.js.map +0 -1
- package/dist/chunk-ZFG5EBI3.js.map +0 -1
- package/dist/chunk-ZNWSG7XC.js.map +0 -1
- package/dist/collection-facade-DO2AABZT.js +0 -45
- package/dist/derive-ZPGVLE2Q.js +0 -22
- package/dist/executor-FPHKWDWT.js +0 -28
- package/dist/executor-IEBLTBCW.js +0 -9
- package/dist/executor-RM7XWQDU.js +0 -9
- package/dist/export-accessible-EKM3HGB2.js +0 -23
- package/dist/extract-partition-LS4ET5A6.js +0 -38
- package/dist/find-OZMTRIK3.js +0 -11
- package/dist/issue-LIA7FXBJ.js +0 -19
- package/dist/liberate-WZ3RHVKW.js +0 -24
- package/dist/noydb-ZLPVCDES.js +0 -81
- package/dist/register-6RIBIT3I.js +0 -25
- package/dist/registry-7Y5WF7GS.js +0 -9
- package/dist/registry-BWD2ED52.js +0 -8
- package/dist/registry-MUSL4AW6.js +0 -19
- package/dist/registry-RON4WHAP.js +0 -18
- package/dist/request-withdrawal-FT3ORAWN.js +0 -31
- package/dist/revoke-HC7WG3HE.js +0 -24
- package/dist/seed-JOV54PB3.js.map +0 -1
- package/dist/signer-CTWOH6KT.js +0 -25
- package/dist/storage-LLNLPWWB.js +0 -23
- package/dist/walk-G3NFEP5L.js +0 -21
- package/dist/withdraw-accessible-ANSVG6XG.js +0 -28
- /package/dist/{api-SI2IVBQO.js.map → api-67SBPMMH.js.map} +0 -0
- /package/dist/{chunk-DQZXPGGZ.js.map → chunk-24UICKTB.js.map} +0 -0
- /package/dist/{chunk-2BET5QTS.js.map → chunk-27TCYH6G.js.map} +0 -0
- /package/dist/{chunk-MSMJJB4J.js.map → chunk-2KIV7BEK.js.map} +0 -0
- /package/dist/{chunk-6ZNSB3H6.js.map → chunk-2LGDCNFJ.js.map} +0 -0
- /package/dist/{chunk-WBKZUO5V.js.map → chunk-3737A6EA.js.map} +0 -0
- /package/dist/{chunk-HLKXPJ4V.js.map → chunk-3EO7RZLJ.js.map} +0 -0
- /package/dist/{chunk-JYJFGD2H.js.map → chunk-3FSX6LDG.js.map} +0 -0
- /package/dist/{chunk-MXUT7FTE.js.map → chunk-3HYWYLXL.js.map} +0 -0
- /package/dist/{chunk-IVYQAVWO.js.map → chunk-3IIPWA75.js.map} +0 -0
- /package/dist/{chunk-7H3WWH6J.js.map → chunk-3UK6STWO.js.map} +0 -0
- /package/dist/{chunk-NJ4DYYO5.js.map → chunk-4HDYQL3J.js.map} +0 -0
- /package/dist/{chunk-P4JO3H6R.js.map → chunk-4MQDV3HZ.js.map} +0 -0
- /package/dist/{chunk-X4MVWPHV.js.map → chunk-4UVDI4XE.js.map} +0 -0
- /package/dist/{chunk-LXRTP3AQ.js.map → chunk-4VCWI42L.js.map} +0 -0
- /package/dist/{chunk-QJNCB5SK.js.map → chunk-747LRSOO.js.map} +0 -0
- /package/dist/{chunk-3HUYRN24.js.map → chunk-7F4DBNSP.js.map} +0 -0
- /package/dist/{chunk-UADPR6F4.js.map → chunk-7G6VDWXB.js.map} +0 -0
- /package/dist/{chunk-PTHKZWEH.js.map → chunk-AHLJSVRL.js.map} +0 -0
- /package/dist/{chunk-NFZGZ4AK.js.map → chunk-AR2JDFAE.js.map} +0 -0
- /package/dist/{chunk-3ECU57YH.js.map → chunk-BPTZ4K5L.js.map} +0 -0
- /package/dist/{chunk-KRCBZYTZ.js.map → chunk-CCZJJ4I2.js.map} +0 -0
- /package/dist/{chunk-NYEFP7DY.js.map → chunk-CJ73OLMW.js.map} +0 -0
- /package/dist/{chunk-Q36YXK77.js.map → chunk-CYQOUTMY.js.map} +0 -0
- /package/dist/{chunk-RBTVFPHF.js.map → chunk-DCMQR46R.js.map} +0 -0
- /package/dist/{chunk-TG634KCO.js.map → chunk-DG27IUVI.js.map} +0 -0
- /package/dist/{chunk-V6UQZA2H.js.map → chunk-E6427JU2.js.map} +0 -0
- /package/dist/{chunk-TWPK7KUJ.js.map → chunk-F3GVO44K.js.map} +0 -0
- /package/dist/{chunk-QD46HPZG.js.map → chunk-FAXZQ5UF.js.map} +0 -0
- /package/dist/{chunk-IG6KUWBX.js.map → chunk-FNSMZQS4.js.map} +0 -0
- /package/dist/{chunk-BLBAQRBM.js.map → chunk-FUHKW252.js.map} +0 -0
- /package/dist/{chunk-SU6SGWXM.js.map → chunk-FY343IZR.js.map} +0 -0
- /package/dist/{chunk-DAFBJS4Y.js.map → chunk-GS5RT2KK.js.map} +0 -0
- /package/dist/{chunk-5UQ7Y6SQ.js.map → chunk-HFKGIBMD.js.map} +0 -0
- /package/dist/{chunk-SHEEBRZ4.js.map → chunk-HVQGCKY4.js.map} +0 -0
- /package/dist/{chunk-35NMVJ7I.js.map → chunk-HXGUIPQB.js.map} +0 -0
- /package/dist/{chunk-ERGECZEI.js.map → chunk-JEM2IGS3.js.map} +0 -0
- /package/dist/{chunk-L3YYLT4E.js.map → chunk-JIUVJ4M7.js.map} +0 -0
- /package/dist/{chunk-55LX6FSX.js.map → chunk-JRCYZEHU.js.map} +0 -0
- /package/dist/{chunk-SFBYQMZM.js.map → chunk-JSRU5W2M.js.map} +0 -0
- /package/dist/{chunk-NM5UYF6Q.js.map → chunk-JXIDGFKS.js.map} +0 -0
- /package/dist/{chunk-RO5NM6UI.js.map → chunk-KZ3KMDN3.js.map} +0 -0
- /package/dist/{chunk-HZZP2ZIG.js.map → chunk-LBGPO5RL.js.map} +0 -0
- /package/dist/{chunk-CLE3TMIS.js.map → chunk-MC2LFTQM.js.map} +0 -0
- /package/dist/{chunk-W3G5REIU.js.map → chunk-MSWYQLMQ.js.map} +0 -0
- /package/dist/{chunk-SGDPRCC4.js.map → chunk-MZ5ZFO2D.js.map} +0 -0
- /package/dist/{chunk-EFJAAFBW.js.map → chunk-NQRJ5AJO.js.map} +0 -0
- /package/dist/{chunk-Q2SEJMP2.js.map → chunk-NVU7ZMPN.js.map} +0 -0
- /package/dist/{chunk-ZTLOXFPB.js.map → chunk-OF3L2SD6.js.map} +0 -0
- /package/dist/{chunk-LLYIMSQQ.js.map → chunk-OMSAULZM.js.map} +0 -0
- /package/dist/{chunk-SF2ZIRD6.js.map → chunk-OSFPNKY4.js.map} +0 -0
- /package/dist/{chunk-WUHEP3HH.js.map → chunk-P7NGLLUF.js.map} +0 -0
- /package/dist/{chunk-RQ4ZI4ZI.js.map → chunk-PGAPBZEK.js.map} +0 -0
- /package/dist/{chunk-T2MOJF76.js.map → chunk-PP5CO2PR.js.map} +0 -0
- /package/dist/{chunk-QGIBI6GL.js.map → chunk-ROWL352P.js.map} +0 -0
- /package/dist/{chunk-ZHDSUZQU.js.map → chunk-RPXL6KSX.js.map} +0 -0
- /package/dist/{chunk-DTFA5DO4.js.map → chunk-SKONR2OL.js.map} +0 -0
- /package/dist/{chunk-4ZKNC6A6.js.map → chunk-T4GPR2IR.js.map} +0 -0
- /package/dist/{chunk-TS5XLBZR.js.map → chunk-TLNNHG3A.js.map} +0 -0
- /package/dist/{chunk-6UBZ6I5Z.js.map → chunk-UHXCLPGC.js.map} +0 -0
- /package/dist/{chunk-KD4HGBJV.js.map → chunk-V5C5NNBR.js.map} +0 -0
- /package/dist/{chunk-5GQEU4DN.js.map → chunk-VJFMXYKP.js.map} +0 -0
- /package/dist/{chunk-5DRROK5W.js.map → chunk-VMCCGUQB.js.map} +0 -0
- /package/dist/{chunk-IXNCZTWA.js.map → chunk-W3TVWF6N.js.map} +0 -0
- /package/dist/{chunk-W66AM5IB.js.map → chunk-WLYIROCJ.js.map} +0 -0
- /package/dist/{chunk-OWHP3H5C.js.map → chunk-XB7LUDKM.js.map} +0 -0
- /package/dist/{chunk-KYRDJI5O.js.map → chunk-XBLKM73C.js.map} +0 -0
- /package/dist/{chunk-MHMLXJ3I.js.map → chunk-YAWK6AWF.js.map} +0 -0
- /package/dist/{chunk-PWPYO73B.js.map → chunk-ZGGVOADG.js.map} +0 -0
- /package/dist/{chunk-IFOH7RBI.js.map → chunk-ZWMO5GL5.js.map} +0 -0
- /package/dist/{chunk-LRRX57UA.js.map → chunk-ZXJXDHNK.js.map} +0 -0
- /package/dist/{classified-marker-LE54HWSX.js.map → classified-marker-MH3ON5OL.js.map} +0 -0
- /package/dist/{collection-facade-DO2AABZT.js.map → collection-facade-AHT7FATG.js.map} +0 -0
- /package/dist/{computed-AB45PS4V.js.map → computed-6G5M3UPH.js.map} +0 -0
- /package/dist/{dead-filter-V3LVWYEJ.js.map → dead-filter-U575NGSH.js.map} +0 -0
- /package/dist/{delegation-JDUMAF6L.js.map → delegation-PDYL6RWT.js.map} +0 -0
- /package/dist/{derive-ZPGVLE2Q.js.map → derive-AKT4KU36.js.map} +0 -0
- /package/dist/{dispatch-6TV3DGO6.js.map → dispatch-4XIJSFTT.js.map} +0 -0
- /package/dist/{dispatch-W7NWQ637.js.map → dispatch-N5HGVUGU.js.map} +0 -0
- /package/dist/{enclave-YFCLPIDR.js.map → enclave-OPK24QDR.js.map} +0 -0
- /package/dist/{executor-FPHKWDWT.js.map → executor-3JZ4POTW.js.map} +0 -0
- /package/dist/{executor-IEBLTBCW.js.map → executor-CYJQLKKI.js.map} +0 -0
- /package/dist/{executor-RM7XWQDU.js.map → executor-S4QIKEHW.js.map} +0 -0
- /package/dist/{export-accessible-EKM3HGB2.js.map → export-accessible-CPTP5STN.js.map} +0 -0
- /package/dist/{extract-partition-LS4ET5A6.js.map → extract-partition-TWXPHVU7.js.map} +0 -0
- /package/dist/{fanout-sidecar-273RDMYS.js.map → fanout-sidecar-T2ZGLQFE.js.map} +0 -0
- /package/dist/{find-OZMTRIK3.js.map → find-RBBYKXI7.js.map} +0 -0
- /package/dist/{issue-LIA7FXBJ.js.map → issue-N74C55X6.js.map} +0 -0
- /package/dist/{ledger-XE7JF2I2.js.map → ledger-DONWFC5M.js.map} +0 -0
- /package/dist/{liberate-WZ3RHVKW.js.map → liberate-KICI7AJN.js.map} +0 -0
- /package/dist/{link-set-CGYC3OH5.js.map → link-set-2TTP4VLO.js.map} +0 -0
- /package/dist/{noydb-ZLPVCDES.js.map → managed-secret-EAOYWRYF.js.map} +0 -0
- /package/dist/{register-6RIBIT3I.js.map → noydb-6W2XGQCS.js.map} +0 -0
- /package/dist/{post-register-LY35EDTJ.js.map → post-register-ORQOQJCS.js.map} +0 -0
- /package/dist/{registry-7Y5WF7GS.js.map → register-LHETZRJM.js.map} +0 -0
- /package/dist/{registry-BWD2ED52.js.map → registry-AMAZ6QRZ.js.map} +0 -0
- /package/dist/{registry-MUSL4AW6.js.map → registry-CZVINVQH.js.map} +0 -0
- /package/dist/{registry-RON4WHAP.js.map → registry-IKUR2MXD.js.map} +0 -0
- /package/dist/{request-withdrawal-FT3ORAWN.js.map → registry-JRIN447B.js.map} +0 -0
- /package/dist/{revoke-HC7WG3HE.js.map → request-withdrawal-2DN2RGCO.js.map} +0 -0
- /package/dist/{reveal-T34ADTPY.js.map → reveal-AG4SCHUQ.js.map} +0 -0
- /package/dist/{signer-CTWOH6KT.js.map → revoke-ZX4NM2CJ.js.map} +0 -0
- /package/dist/{stale-T3V7XEOB.js.map → signer-7KHD4OL2.js.map} +0 -0
- /package/dist/{storage-LLNLPWWB.js.map → stale-K734VACF.js.map} +0 -0
- /package/dist/{walk-G3NFEP5L.js.map → storage-4H2GF6RQ.js.map} +0 -0
- /package/dist/{store-coordination-provider-AHGFEMFA.js.map → store-coordination-provider-4SKLSFUG.js.map} +0 -0
- /package/dist/{verify-7XWHJWUN.js.map → verify-RO5RTZOJ.js.map} +0 -0
- /package/dist/{withdraw-accessible-ANSVG6XG.js.map → walk-MQHYNDLZ.js.map} +0 -0
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `beginEchoUnlock` — the interactive ceremony API (spec
|
|
3
|
+
* docs/superpowers/specs/2026-08-02-echo-secret-design.md, #940, Task 6).
|
|
4
|
+
*
|
|
5
|
+
* Split out of `echo-secret.ts` (which owns only the block builders +
|
|
6
|
+
* verifiers) because this module orchestrates BOTH `echo-secret.ts`
|
|
7
|
+
* (`verifyPrompt`/`resolveEchoReveal`/`verifyTypedEcho`) AND `keyring.ts`
|
|
8
|
+
* (`loadKeyring`) — and `keyring.ts` itself imports `buildEchoBlock` from
|
|
9
|
+
* `echo-secret.ts`. Keeping the ceremony here instead of inside
|
|
10
|
+
* `echo-secret.ts` yields a clean DAG (`echo-ceremony.ts` → {`echo-secret.ts`,
|
|
11
|
+
* `keyring.ts`}; `keyring.ts` → `echo-secret.ts`) instead of a two-file
|
|
12
|
+
* cycle, and restores `echo-secret.ts`'s documented charter (builders +
|
|
13
|
+
* verifiers only).
|
|
14
|
+
*
|
|
15
|
+
* @module
|
|
16
|
+
*/
|
|
17
|
+
import type { NoydbStore } from '../../kernel/types.js';
|
|
18
|
+
import type { DeviceSealProvider } from './device-seal.js';
|
|
19
|
+
import { type UnlockedKeyring } from './keyring.js';
|
|
20
|
+
/** Options for {@link beginEchoUnlock}. */
|
|
21
|
+
export interface BeginEchoUnlockOptions {
|
|
22
|
+
readonly userId: string;
|
|
23
|
+
readonly prompt: string;
|
|
24
|
+
readonly deviceSeal?: DeviceSealProvider;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* A prompt-verified, in-progress echo unlock. Stateless w.r.t. attempts —
|
|
28
|
+
* `complete()` may be called more than once (e.g. retry after a wrong key).
|
|
29
|
+
*/
|
|
30
|
+
export interface EchoCeremony {
|
|
31
|
+
/**
|
|
32
|
+
* Echo to display for owner recognition; null ⇒ degraded: ask the owner to
|
|
33
|
+
* TYPE it.
|
|
34
|
+
*
|
|
35
|
+
* Conforming-player contract (spec
|
|
36
|
+
* docs/superpowers/specs/2026-08-02-echo-secret-design.md, "Ceremony"):
|
|
37
|
+
* when the owner does NOT recognize the revealed echo, the player MUST show
|
|
38
|
+
* a hard phishing warning — do not continue, open the official app, rotate
|
|
39
|
+
* the secret immediately — MUST NOT offer any skip or
|
|
40
|
+
* "verification unavailable" fallback, and MUST simply abandon the ceremony
|
|
41
|
+
* by never calling {@link EchoCeremony.complete}. The kernel cannot enforce
|
|
42
|
+
* this terminal state; it is the player's obligation.
|
|
43
|
+
*/
|
|
44
|
+
readonly reveal: string | null;
|
|
45
|
+
readonly maskHint: string | undefined;
|
|
46
|
+
/** Complete the ceremony. `echo` is REQUIRED when `reveal` is null. */
|
|
47
|
+
complete(input: {
|
|
48
|
+
readonly echo?: string;
|
|
49
|
+
readonly key: string;
|
|
50
|
+
}): Promise<UnlockedKeyring>;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Begin the interactive anti-phishing unlock ceremony (spec decision 4):
|
|
54
|
+
* prompt → echo reveal → key. Fetches and parses the `_keyring/{userId}`
|
|
55
|
+
* row (same store path as `loadKeyring`), verifies the prompt, and resolves
|
|
56
|
+
* the echo for display (or degrades to the typed-echo path when the reveal
|
|
57
|
+
* cannot be resolved — sealed reveal under a foreign device).
|
|
58
|
+
*
|
|
59
|
+
* Conforming-player contract (spec
|
|
60
|
+
* docs/superpowers/specs/2026-08-02-echo-secret-design.md): an owner who does
|
|
61
|
+
* not recognize `ceremony.reveal` is looking at a phish. The player MUST then
|
|
62
|
+
* show a hard warning (stop, open the official app, rotate the secret now),
|
|
63
|
+
* MUST NOT offer a skip / "verification unavailable" fallback or any
|
|
64
|
+
* single-field secret entry, and MUST abandon the ceremony without calling
|
|
65
|
+
* `complete()`.
|
|
66
|
+
*
|
|
67
|
+
* @throws NoAccessError when no keyring exists for `userId` (mirrors
|
|
68
|
+
* `loadKeyring`'s missing-row error).
|
|
69
|
+
* @throws KeyringExpiredError when the slot is past its `expires_at` —
|
|
70
|
+
* checked before the prompt is verified, so an expired slot never reveals.
|
|
71
|
+
* @throws ValidationError when the keyring is not an echo keyring.
|
|
72
|
+
* @throws WrongPromptError when the prompt fails its verifier.
|
|
73
|
+
*/
|
|
74
|
+
export declare function beginEchoUnlock(store: NoydbStore, vault: string, opts: BeginEchoUnlockOptions): Promise<EchoCeremony>;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Echo-block builders + verifiers (spec
|
|
3
|
+
* docs/superpowers/specs/2026-08-02-echo-secret-design.md, #940).
|
|
4
|
+
*
|
|
5
|
+
* Builds and verifies the on-keyring {@link KeyringEchoBlock} declaration
|
|
6
|
+
* for the 3-part echo ceremony (prompt → echo → key). This module owns:
|
|
7
|
+
*
|
|
8
|
+
* - Minting the prompt/echo canary verifiers (the "canary trick": AES-KW
|
|
9
|
+
* wrap a constant 32-byte key under `deriveSecretKey(part, salt, …)`;
|
|
10
|
+
* verify = unwrap succeeds).
|
|
11
|
+
* - Building the reveal blob per the hybrid reveal policy (spec decision
|
|
12
|
+
* 4): `portable` (AES-GCM under the prompt, own salt), `sealed`
|
|
13
|
+
* (opaque to hub, unsealed only by the enrolling device's
|
|
14
|
+
* {@link DeviceSealProvider}), or `none`.
|
|
15
|
+
* - Resolving the echo for display (`resolveEchoReveal`, `null` ⇒
|
|
16
|
+
* degraded typed-echo path) and verifying a typed echo
|
|
17
|
+
* (`verifyTypedEcho`) for that degraded path.
|
|
18
|
+
*
|
|
19
|
+
* Deriving the actual KEK from all three parts together is
|
|
20
|
+
* `deriveEchoKey`/`encodeEchoParts` (`kernel/enclave/crypto.ts`) — a
|
|
21
|
+
* separate concern from this module's per-part verifiers.
|
|
22
|
+
*
|
|
23
|
+
* Known, accepted disclosure: `prompt_verifier` and `echo_verifier` are
|
|
24
|
+
* offline brute-force oracles for anyone holding the keyring file (600K
|
|
25
|
+
* PBKDF2 per guess), and the `sealed` reveal blob is unpadded so its length
|
|
26
|
+
* discloses the echo's UTF-8 byte length — see the threat model in
|
|
27
|
+
* `docs/superpowers/specs/2026-08-02-echo-secret-design.md`.
|
|
28
|
+
*
|
|
29
|
+
* @module
|
|
30
|
+
*/
|
|
31
|
+
import { type EchoSecretParts } from '../../kernel/enclave/index.js';
|
|
32
|
+
import type { KeyringEchoBlock } from '../../kernel/types.js';
|
|
33
|
+
import type { DeviceSealProvider } from './device-seal.js';
|
|
34
|
+
/** Same iteration floor as the KEK (spec resolved question 1). */
|
|
35
|
+
export declare const ECHO_KDF_ITERATIONS = 600000;
|
|
36
|
+
export type EchoRevealChoice = {
|
|
37
|
+
readonly kind: 'portable';
|
|
38
|
+
} | {
|
|
39
|
+
readonly kind: 'sealed';
|
|
40
|
+
readonly deviceSeal: DeviceSealProvider;
|
|
41
|
+
} | {
|
|
42
|
+
readonly kind: 'none';
|
|
43
|
+
};
|
|
44
|
+
/** Build the on-keyring echo declaration for a fresh enrollment. */
|
|
45
|
+
export declare function buildEchoBlock(parts: EchoSecretParts, reveal: EchoRevealChoice, maskHint?: string): Promise<KeyringEchoBlock>;
|
|
46
|
+
export declare function verifyPrompt(block: KeyringEchoBlock, prompt: string): Promise<boolean>;
|
|
47
|
+
/**
|
|
48
|
+
* Resolve the echo for display. `null` ⇒ degraded path: the player
|
|
49
|
+
* must ask the owner to TYPE the echo (verify via {@link verifyTypedEcho}).
|
|
50
|
+
* Callers MUST verify the prompt first — this assumes it.
|
|
51
|
+
*
|
|
52
|
+
* @throws WrongPromptError when the prompt cannot open the portable reveal
|
|
53
|
+
* (callers should verifyPrompt first for a boolean check).
|
|
54
|
+
*/
|
|
55
|
+
export declare function resolveEchoReveal(block: KeyringEchoBlock, prompt: string, deviceSeal?: DeviceSealProvider): Promise<string | null>;
|
|
56
|
+
export declare function verifyTypedEcho(block: KeyringEchoBlock, echo: string): Promise<boolean>;
|
|
@@ -32,4 +32,12 @@ export type { WrappedDeksBlob } from './wrapped-deks.js';
|
|
|
32
32
|
export { writeMagicLinkGrant, readMagicLinkGrantRecord, listMagicLinkGrants, unwrapMagicLinkGrant, revokeMagicLinkGrant, deriveMagicLinkContentKey, magicLinkGrantRecordId, isMagicLinkGrantExpired, } from './magic-link-grant.js';
|
|
33
33
|
export { hasExportCapability, evaluateExportCapability, } from './keyring.js';
|
|
34
34
|
export { hasImportCapability, evaluateImportCapability, } from './keyring.js';
|
|
35
|
+
export { buildEchoBlock, verifyPrompt, resolveEchoReveal, verifyTypedEcho, } from './echo-secret.js';
|
|
36
|
+
export type { EchoRevealChoice } from './echo-secret.js';
|
|
37
|
+
export { beginEchoUnlock } from './echo-ceremony.js';
|
|
38
|
+
export type { BeginEchoUnlockOptions, EchoCeremony } from './echo-ceremony.js';
|
|
39
|
+
export { MemoryDeviceSealProvider } from './device-seal.js';
|
|
40
|
+
export type { DeviceSealProvider } from './device-seal.js';
|
|
41
|
+
export type { EchoSecretParts } from '../../kernel/enclave/index.js';
|
|
42
|
+
export type { KeyringEchoBlock, NoydbStore } from '../../kernel/types.js';
|
|
35
43
|
export { describeAuthConfig, diagramAuthConfig, describeUserAuth, describeAllUsersAuth, } from '../auth-introspection/index.js';
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import type { NoydbStore, KeyringFile, KeyringAuthenticator, Role, Permissions, GrantOptions, RevokeOptions, UpdateUserOptions, UserInfo, ExportCapability, ExportFormat, ImportCapability, VaultPolicyOnDisk, UserEnvelope } from '../../kernel/types.js';
|
|
2
|
-
import { type EnclaveKey } from '../../kernel/enclave/index.js';
|
|
3
|
-
import { type SecretPolicy } from '../../kernel/validation.js';
|
|
1
|
+
import type { NoydbStore, KeyringFile, KeyringAuthenticator, Role, Permissions, GrantOptions, RevokeOptions, UpdateUserOptions, UserInfo, EncryptedEnvelope, ExportCapability, ExportFormat, ImportCapability, VaultPolicyOnDisk, UserEnvelope } from '../../kernel/types.js';
|
|
2
|
+
import { type EnclaveKey, type EchoSecretParts } from '../../kernel/enclave/index.js';
|
|
3
|
+
import { type SecretPolicy, type EchoSecretPolicy } from '../../kernel/validation.js';
|
|
4
|
+
import type { DeviceSealProvider } from './device-seal.js';
|
|
4
5
|
/** In-memory representation of an unlocked keyring. */
|
|
5
6
|
export interface UnlockedKeyring {
|
|
6
7
|
readonly userId: string;
|
|
@@ -75,9 +76,34 @@ export declare function mintKeyringCanary(kek: EnclaveKey): Promise<string>;
|
|
|
75
76
|
export interface LoadKeyringOptions {
|
|
76
77
|
/** The user whose keyring to unlock. */
|
|
77
78
|
readonly userId: string;
|
|
78
|
-
/**
|
|
79
|
-
|
|
79
|
+
/**
|
|
80
|
+
* That user's secret — a single string for a standard keyring, or the
|
|
81
|
+
* structured 3-part {@link EchoSecretParts} for an echo keyring (spec
|
|
82
|
+
* #940, AG-1: a single string can never unlock an echo keyring).
|
|
83
|
+
*/
|
|
84
|
+
readonly secret: string | EchoSecretParts;
|
|
80
85
|
}
|
|
86
|
+
/**
|
|
87
|
+
* KDF dispatch for tier-1 unlock (spec #940). An echo keyring accepts
|
|
88
|
+
* ONLY structured parts (AG-1 — no single string is key-equivalent);
|
|
89
|
+
* a standard keyring accepts only a string.
|
|
90
|
+
*/
|
|
91
|
+
export declare function deriveKekForKeyring(file: KeyringFile, secret: string | EchoSecretParts, salt: Uint8Array): Promise<EnclaveKey>;
|
|
92
|
+
/** Parse a raw keyring envelope. Single sanctioned reader of `_data` for keyring files. */
|
|
93
|
+
export declare function parseKeyringEnvelope(envelope: EncryptedEnvelope): KeyringFile;
|
|
94
|
+
/** Fetch + parse a user's keyring file; undefined when the row is missing. */
|
|
95
|
+
export declare function readKeyringFile(store: NoydbStore, vault: string, userId: string): Promise<{
|
|
96
|
+
readonly envelope: EncryptedEnvelope;
|
|
97
|
+
readonly file: KeyringFile;
|
|
98
|
+
} | undefined>;
|
|
99
|
+
/**
|
|
100
|
+
* Shared expiry gate — refuse to unwrap an expired slot. Call before any
|
|
101
|
+
* KEK derivation so an expired slot doesn't leak timing on the secret.
|
|
102
|
+
* Comparison uses Date.parse → ms-since-epoch; an unparseable expires_at is
|
|
103
|
+
* treated as "no expiry" so a malformed value can't silently lock users out
|
|
104
|
+
* (it'll surface in tests).
|
|
105
|
+
*/
|
|
106
|
+
export declare function assertKeyringNotExpired(file: KeyringFile): void;
|
|
81
107
|
/** Load and unlock a user's keyring for a vault. */
|
|
82
108
|
export declare function loadKeyring(store: NoydbStore, vault: string, opts: LoadKeyringOptions): Promise<UnlockedKeyring>;
|
|
83
109
|
/**
|
|
@@ -100,12 +126,34 @@ export declare function assertKeyringOpenAllowed(store: NoydbStore, vault: strin
|
|
|
100
126
|
export interface CreateOwnerKeyringOptions extends SecretPolicy {
|
|
101
127
|
/** The owner to create. */
|
|
102
128
|
readonly userId: string;
|
|
103
|
-
/**
|
|
104
|
-
|
|
129
|
+
/**
|
|
130
|
+
* The owner's secret — a plain string for a standard keyring, or the
|
|
131
|
+
* structured 3-part {@link EchoSecretParts} to enroll an echo keyring
|
|
132
|
+
* (spec #940). The shape alone selects the KDF and whether an `echo`
|
|
133
|
+
* block is written.
|
|
134
|
+
*/
|
|
135
|
+
readonly secret: string | EchoSecretParts;
|
|
105
136
|
/** Gate creation on the phrase-format strength rules. Default false. */
|
|
106
137
|
readonly validate?: boolean;
|
|
107
138
|
/** Escape hatch for fixtures and migrations — skips the strength gate. */
|
|
108
139
|
readonly allowWeakSecret?: boolean;
|
|
140
|
+
/**
|
|
141
|
+
* Echo enrollment only: device-local sealer for the reveal blob. Present
|
|
142
|
+
* ⇒ `reveal: 'sealed'` (attacker-B resistance); absent ⇒ `reveal:
|
|
143
|
+
* 'portable'` (spec resolved question 4). Ignored for a string secret.
|
|
144
|
+
*/
|
|
145
|
+
readonly deviceSeal?: DeviceSealProvider;
|
|
146
|
+
/** Echo enrollment only: optional display hint for the masked echo. */
|
|
147
|
+
readonly echoMaskHint?: string;
|
|
148
|
+
/**
|
|
149
|
+
* Echo enrollment only: strength-policy knobs for the 3-part secret's
|
|
150
|
+
* prompt / combined floors — the parts-path counterpart of the
|
|
151
|
+
* flattened `SecretPolicy` fields this options bag already extends
|
|
152
|
+
* (those apply to a STRING secret via `assertStrongSecret`; this
|
|
153
|
+
* applies to {@link EchoSecretParts} via `assertStrongEchoSecret`).
|
|
154
|
+
* Ignored for a string secret.
|
|
155
|
+
*/
|
|
156
|
+
readonly echoSecretPolicy?: EchoSecretPolicy;
|
|
109
157
|
}
|
|
110
158
|
/**
|
|
111
159
|
* Create the initial owner keyring for a new vault.
|
|
@@ -196,6 +244,15 @@ export interface ChangeSecretOptions extends SecretPolicy {
|
|
|
196
244
|
* the OLD secret is not retyped.
|
|
197
245
|
*/
|
|
198
246
|
export declare function changeSecret(store: NoydbStore, vault: string, keyring: UnlockedKeyring, opts: ChangeSecretOptions): Promise<UnlockedKeyring>;
|
|
247
|
+
/**
|
|
248
|
+
* Echo-mode recipient secret (spec #940). A pod slot may embed the reveal
|
|
249
|
+
* (`'portable'`, default) or omit it (`'none'`) — `'sealed'` is
|
|
250
|
+
* live-device-only and unavailable here: `writePod` has no device context
|
|
251
|
+
* to seal the reveal blob against.
|
|
252
|
+
*/
|
|
253
|
+
export interface EchoRecipientSecret extends EchoSecretParts {
|
|
254
|
+
readonly reveal?: 'portable' | 'none';
|
|
255
|
+
}
|
|
199
256
|
/**
|
|
200
257
|
* Recipient slot in a re-keyed `.noydb` bundle. Each slot becomes its
|
|
201
258
|
* own keyring file inside the bundle, sealed with its own secret.
|
|
@@ -209,8 +266,13 @@ export interface BundleRecipient {
|
|
|
209
266
|
readonly id: string;
|
|
210
267
|
/** Optional display name. Defaults to `id`. */
|
|
211
268
|
readonly displayName?: string;
|
|
212
|
-
/**
|
|
213
|
-
|
|
269
|
+
/**
|
|
270
|
+
* Secret the recipient will type to unlock — a plain string for a
|
|
271
|
+
* standard keyring, or the structured 3-part {@link EchoRecipientSecret}
|
|
272
|
+
* to embed an echo keyring so the anti-phishing ceremony travels with
|
|
273
|
+
* the pod (spec #940).
|
|
274
|
+
*/
|
|
275
|
+
readonly secret: string | EchoRecipientSecret;
|
|
214
276
|
/** Role on the destination vault. Defaults to `'viewer'`. */
|
|
215
277
|
readonly role?: Role;
|
|
216
278
|
/**
|
|
@@ -17,13 +17,31 @@
|
|
|
17
17
|
* @module
|
|
18
18
|
*/
|
|
19
19
|
import type { NoydbStore } from '../../kernel/types.js';
|
|
20
|
-
import { type EnclaveKey } from '../../kernel/enclave/index.js';
|
|
20
|
+
import { type EnclaveKey, type EchoSecretParts } from '../../kernel/enclave/index.js';
|
|
21
21
|
import { type PaperRecoveryEntry } from './recovery.js';
|
|
22
22
|
import type { ShamirRecoveryProvider } from './shamir-recovery-provider.js';
|
|
23
|
-
import { type SecretPolicy } from '../../kernel/validation.js';
|
|
23
|
+
import { type SecretPolicy, type EchoSecretPolicy } from '../../kernel/validation.js';
|
|
24
24
|
import type { UnlockedKeyring } from './keyring.js';
|
|
25
|
+
import type { DeviceSealProvider } from './device-seal.js';
|
|
25
26
|
import type { KeyringAuthenticator } from '../../kernel/types.js';
|
|
26
27
|
import type { EnrollAuthenticatorOptions } from './authenticators.js';
|
|
28
|
+
/**
|
|
29
|
+
* Echo-enrollment knobs for a rotation whose NEW secret is 3-part (spec #940).
|
|
30
|
+
*
|
|
31
|
+
* Deliberately NOT exported: it is reachable structurally through
|
|
32
|
+
* {@link RotateSecretInput.echoOptions}, and exporting it would mean adding it
|
|
33
|
+
* to the team + root barrels for a type consumers never need to name.
|
|
34
|
+
*/
|
|
35
|
+
interface RotateEchoOptions {
|
|
36
|
+
/**
|
|
37
|
+
* Device-local sealer for the reveal blob. Present ⇒ `reveal: 'sealed'`;
|
|
38
|
+
* absent ⇒ `reveal: 'portable'`. Mirrors
|
|
39
|
+
* {@link CreateOwnerKeyringOptions.deviceSeal}.
|
|
40
|
+
*/
|
|
41
|
+
readonly deviceSeal?: DeviceSealProvider;
|
|
42
|
+
/** Optional display hint for the masked echo. */
|
|
43
|
+
readonly maskHint?: string;
|
|
44
|
+
}
|
|
27
45
|
/**
|
|
28
46
|
* Context handed to a {@link SlotRewrapCeremony} when `rotateSecret`
|
|
29
47
|
* preserves a tier-2 slot. The ceremony's job is to re-derive its
|
|
@@ -65,10 +83,50 @@ export interface SlotRewrapContext {
|
|
|
65
83
|
export type SlotRewrapCeremony = (ctx: SlotRewrapContext) => Promise<EnrollAuthenticatorOptions>;
|
|
66
84
|
/** Caller payload for {@link rotateSecret}. */
|
|
67
85
|
export interface RotateSecretInput {
|
|
68
|
-
|
|
69
|
-
|
|
86
|
+
/**
|
|
87
|
+
* The secret currently opening the keyring — a string for a standard
|
|
88
|
+
* keyring, the 3-part {@link EchoSecretParts} for an echo one. The shape
|
|
89
|
+
* must MATCH the stored keyring: `deriveKekForKeyring` refuses a string on
|
|
90
|
+
* an echo keyring (`EchoCeremonyRequiredError`, AG-1) and parts on a
|
|
91
|
+
* standard one (`ValidationError`).
|
|
92
|
+
*/
|
|
93
|
+
readonly oldSecret: string | EchoSecretParts;
|
|
94
|
+
/**
|
|
95
|
+
* The secret to rotate TO. Its shape — independent of `oldSecret`'s —
|
|
96
|
+
* decides the keyring's mode after rotation: parts enroll an `echo` block
|
|
97
|
+
* (standard→echo upgrade, or a re-mint on echo→echo), a string removes any
|
|
98
|
+
* existing one (echo→standard downgrade).
|
|
99
|
+
*/
|
|
100
|
+
readonly newSecret: string | EchoSecretParts;
|
|
101
|
+
/**
|
|
102
|
+
* Strength-policy knobs applied when `newSecret` is a STRING. Ignored
|
|
103
|
+
* for 3-part {@link EchoSecretParts} — see `echoSecretPolicy` for the
|
|
104
|
+
* parts-path counterpart.
|
|
105
|
+
*/
|
|
70
106
|
readonly secretPolicy?: SecretPolicy;
|
|
107
|
+
/**
|
|
108
|
+
* Strength-policy knobs applied when `newSecret` is 3-part
|
|
109
|
+
* {@link EchoSecretParts} (prompt / combined floors). Ignored for a
|
|
110
|
+
* string `newSecret` — see `secretPolicy` for the string-path
|
|
111
|
+
* counterpart.
|
|
112
|
+
*/
|
|
113
|
+
readonly echoSecretPolicy?: EchoSecretPolicy;
|
|
71
114
|
readonly allowWeakSecret?: boolean;
|
|
115
|
+
/**
|
|
116
|
+
* Echo-enrollment knobs for the block minted when `newSecret` is 3-part.
|
|
117
|
+
* Ignored for a string `newSecret` (no block is written).
|
|
118
|
+
*/
|
|
119
|
+
readonly echoOptions?: RotateEchoOptions;
|
|
120
|
+
/**
|
|
121
|
+
* Explicit confirmation for an echo→standard rotation. When the stored
|
|
122
|
+
* keyring has an `echo` block AND `newSecret` is a plain string, the
|
|
123
|
+
* rotation is a security-posture downgrade — and that shape is decided
|
|
124
|
+
* purely by argument shape, so it must be opted into explicitly. Without
|
|
125
|
+
* this flag such a rotation throws `ValidationError` BEFORE any write
|
|
126
|
+
* (and before deriving the new KEK). Upgrades (string→parts) and
|
|
127
|
+
* same-mode rotations (string→string, parts→parts) never require it.
|
|
128
|
+
*/
|
|
129
|
+
readonly allowModeDowngrade?: boolean;
|
|
72
130
|
/**
|
|
73
131
|
* Map of slot id → re-enrolment ceremony. Slots whose id appears
|
|
74
132
|
* here are PRESERVED across rotation (the ceremony re-derives the
|
|
@@ -99,7 +157,13 @@ export interface RotateSecretInput {
|
|
|
99
157
|
* the rewrapped slots atomically with the rotation. Slots whose id
|
|
100
158
|
* isn't in the map are still dropped.
|
|
101
159
|
*
|
|
160
|
+
* Either secret may be a string or 3-part {@link EchoSecretParts}; the two
|
|
161
|
+
* shapes are independent, so a rotation doubles as the standard↔echo
|
|
162
|
+
* upgrade/downgrade ceremony (spec #940).
|
|
163
|
+
*
|
|
102
164
|
* @throws `InvalidKeyError` if `oldSecret` does not unwrap the keyring.
|
|
165
|
+
* @throws `EchoCeremonyRequiredError` if `oldSecret` is a string but the
|
|
166
|
+
* keyring is an echo keyring.
|
|
103
167
|
* @throws `WeakSecretError` if `newSecret` fails the strength rule.
|
|
104
168
|
* @throws `ValidationError` if a ceremony's result mismatches the
|
|
105
169
|
* slot's id or method (anti-slot-swap guard).
|
|
@@ -130,9 +194,38 @@ export type RecoveryProof = {
|
|
|
130
194
|
};
|
|
131
195
|
};
|
|
132
196
|
export interface RecoverSecretInput {
|
|
133
|
-
|
|
197
|
+
/**
|
|
198
|
+
* The secret to recover TO. As in {@link RotateSecretInput}, the shape
|
|
199
|
+
* decides the recovered keyring's mode: 3-part {@link EchoSecretParts}
|
|
200
|
+
* enroll a fresh (always PORTABLE) `echo` block, a string leaves the
|
|
201
|
+
* keyring standard and removes any block the old one carried.
|
|
202
|
+
*
|
|
203
|
+
* Recovery deliberately has no `echoOptions` counterpart — a device seal
|
|
204
|
+
* would bind the reveal blob to the device running the recovery, which is
|
|
205
|
+
* not necessarily the device the user will unlock from. Seal it afterwards
|
|
206
|
+
* with an explicit `rotateSecret`.
|
|
207
|
+
*
|
|
208
|
+
* A string `newSecret` on a previously-echo keyring performs the same
|
|
209
|
+
* echo→standard downgrade as `rotateSecret`, but WITHOUT an
|
|
210
|
+
* `allowModeDowngrade` gate — recovery is already a proof-gated reset
|
|
211
|
+
* ceremony (a valid recovery code/shares), so the shape-alone check
|
|
212
|
+
* `rotateSecret` needs is redundant here by design.
|
|
213
|
+
*/
|
|
214
|
+
readonly newSecret: string | EchoSecretParts;
|
|
134
215
|
readonly recoveryProof: RecoveryProof;
|
|
216
|
+
/**
|
|
217
|
+
* Strength-policy knobs applied when `newSecret` is a STRING. Ignored
|
|
218
|
+
* for 3-part {@link EchoSecretParts} — see `echoSecretPolicy` for the
|
|
219
|
+
* parts-path counterpart.
|
|
220
|
+
*/
|
|
135
221
|
readonly secretPolicy?: SecretPolicy;
|
|
222
|
+
/**
|
|
223
|
+
* Strength-policy knobs applied when `newSecret` is 3-part
|
|
224
|
+
* {@link EchoSecretParts} (prompt / combined floors). Ignored for a
|
|
225
|
+
* string `newSecret` — see `secretPolicy` for the string-path
|
|
226
|
+
* counterpart.
|
|
227
|
+
*/
|
|
228
|
+
readonly echoSecretPolicy?: EchoSecretPolicy;
|
|
136
229
|
readonly allowWeakSecret?: boolean;
|
|
137
230
|
/**
|
|
138
231
|
* After a successful paper-recovery, replace ALL remaining recovery
|
|
@@ -273,3 +366,4 @@ export type RecoveryEnrollmentInput = {
|
|
|
273
366
|
* stored set).
|
|
274
367
|
*/
|
|
275
368
|
export declare function recoverSecret(provider: ShamirRecoveryProvider | undefined, store: NoydbStore, vault: string, userId: string, input: RecoverSecretInput): Promise<UnlockedKeyring>;
|
|
369
|
+
export {};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { NoydbStore } from '../kernel/types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Return the stable opaque bundle handle for the given vault adapter,
|
|
4
|
+
* generating and persisting a fresh ULID on first call.
|
|
5
|
+
*
|
|
6
|
+
* See {@link import('../kernel/vault.js').Vault.getBundleHandle} for
|
|
7
|
+
* the full rationale and storage-path documentation.
|
|
8
|
+
*/
|
|
9
|
+
export declare function buildBundleHandle(adapter: NoydbStore, name: string): Promise<string>;
|
|
@@ -32,7 +32,9 @@
|
|
|
32
32
|
* call can also feed verification tools, format inspectors, or
|
|
33
33
|
* archive utilities that don't care about decryption.
|
|
34
34
|
*/
|
|
35
|
-
import { type NoydbPodHeader } from './format.js';
|
|
35
|
+
import { type NoydbPodHeader, type UnlockMethod } from './format.js';
|
|
36
|
+
import type { Redirect } from './redirect.js';
|
|
37
|
+
import type { DocSigner } from '../with-audit/attestation/signer.js';
|
|
36
38
|
import type { Vault } from '../kernel/vault.js';
|
|
37
39
|
import type { BundleRecipient } from '../with-party/team/keyring.js';
|
|
38
40
|
import type { Cover } from '../with-party/directory/cover/types.js';
|
|
@@ -230,6 +232,39 @@ export interface WritePodOptions {
|
|
|
230
232
|
readonly provider: SealingKeyProvider;
|
|
231
233
|
readonly perUser: Record<string, string>;
|
|
232
234
|
};
|
|
235
|
+
/**
|
|
236
|
+
* Pod-header signing control (#943).
|
|
237
|
+
*
|
|
238
|
+
* - omitted (default) — sign the header iff the source vault has a
|
|
239
|
+
* persisted document signer (`vault._loadPodSigner()` returns
|
|
240
|
+
* non-null). A vault that never minted a signer produces an
|
|
241
|
+
* unsigned `formatVersion: 1` header, exactly as before.
|
|
242
|
+
* - `false` — never sign, even if a signer is persisted.
|
|
243
|
+
* - an explicit {@link DocSigner} — sign with the supplied keypair
|
|
244
|
+
* without touching the vault's persisted signer (test / advanced
|
|
245
|
+
* injection). Does not mint or persist anything.
|
|
246
|
+
*
|
|
247
|
+
* Signing NEVER mints a signer as a side effect of export: an absent
|
|
248
|
+
* signer means an unsigned pod, not an on-the-fly key generation.
|
|
249
|
+
*/
|
|
250
|
+
readonly sign?: false | DocSigner;
|
|
251
|
+
/**
|
|
252
|
+
* Header L2 fields (#942) — pre-auth dispatch metadata written verbatim
|
|
253
|
+
* into the pod header. See `NoydbPodHeader` for the disclosure rationale
|
|
254
|
+
* of each. All optional; absence produces a legacy-shaped header exactly
|
|
255
|
+
* as before.
|
|
256
|
+
*/
|
|
257
|
+
readonly engineRange?: string;
|
|
258
|
+
readonly unlockMethods?: readonly UnlockMethod[];
|
|
259
|
+
readonly hasApp?: boolean;
|
|
260
|
+
readonly species?: 'full' | 'connection' | 'snapshot' | 'redirect' | 'group';
|
|
261
|
+
readonly pointerMode?: 'public' | 'private';
|
|
262
|
+
/**
|
|
263
|
+
* Signed "this moved, go there" pointer (#944), written verbatim into
|
|
264
|
+
* the plaintext header. Pass an already-signed {@link Redirect}
|
|
265
|
+
* (mint one via `signRedirect`) — `writePod` does not sign it for you.
|
|
266
|
+
*/
|
|
267
|
+
readonly redirect?: Redirect;
|
|
233
268
|
}
|
|
234
269
|
/** @deprecated Use `WritePodOptions`. */
|
|
235
270
|
export type WriteNoydbBundleOptions = WritePodOptions;
|
|
@@ -353,7 +388,14 @@ export declare function assembleBundleContainer(opts: {
|
|
|
353
388
|
bodyJsonStr: string;
|
|
354
389
|
compression: WritePodOptions['compression'];
|
|
355
390
|
/** Header fields beyond the always-present four. */
|
|
356
|
-
headerExtras?: Partial<Pick<NoydbPodHeader, 'publicEnvelope' | 'autoUnlock' | 'bundleKind' | 'transferSeal'>>;
|
|
391
|
+
headerExtras?: Partial<Pick<NoydbPodHeader, 'publicEnvelope' | 'autoUnlock' | 'bundleKind' | 'transferSeal' | 'engineRange' | 'unlockMethods' | 'hasApp' | 'species' | 'pointerMode' | 'redirect'>>;
|
|
392
|
+
/**
|
|
393
|
+
* When present, the assembled header is signed (#943): the header is
|
|
394
|
+
* bumped to `formatVersion: 2` and carries the sig/keyId/sigAlg tuple.
|
|
395
|
+
* Absent → an unsigned `formatVersion: 1` header (partitions, and pods
|
|
396
|
+
* from vaults without a signer, stay unsigned).
|
|
397
|
+
*/
|
|
398
|
+
signer?: DocSigner;
|
|
357
399
|
}): Promise<Uint8Array>;
|
|
358
400
|
export declare function writePod(vault: Vault, opts?: WritePodOptions): Promise<Uint8Array>;
|
|
359
401
|
/** @deprecated Use `writePod`. */
|
|
@@ -375,6 +417,50 @@ export declare const writeNoydbBundle: typeof writePod;
|
|
|
375
417
|
export declare function readPodHeader(bytes: Uint8Array): NoydbPodHeader;
|
|
376
418
|
/** @deprecated Use `readPodHeader`. */
|
|
377
419
|
export declare const readNoydbBundleHeader: typeof readPodHeader;
|
|
420
|
+
/**
|
|
421
|
+
* Outcome of {@link verifyPodHeader}.
|
|
422
|
+
*
|
|
423
|
+
* - `verified` — the header carried a sig-tuple, its `keyId` is in
|
|
424
|
+
* `trustedKeys`, and the signature checks out over the canonical
|
|
425
|
+
* header bytes.
|
|
426
|
+
* - `unsigned` — the header carried no signature (a legacy v1 pod, or a
|
|
427
|
+
* v2 pod written with `{ sign: false }`). Not an error; just unauthenticated.
|
|
428
|
+
* - `untrusted` — the header is signed but its `keyId` is not one the
|
|
429
|
+
* caller trusts. The signature was NOT checked.
|
|
430
|
+
* - `tampered` — the header is signed by a trusted key but the signature
|
|
431
|
+
* does not verify: the signed bytes were altered, or the mapped public
|
|
432
|
+
* key is not the one that actually signed.
|
|
433
|
+
*/
|
|
434
|
+
export interface PodVerifyResult {
|
|
435
|
+
readonly status: 'verified' | 'unsigned' | 'untrusted' | 'tampered';
|
|
436
|
+
/** The header's `keyId`, present whenever the header carried a sig-tuple. */
|
|
437
|
+
readonly keyId?: string;
|
|
438
|
+
}
|
|
439
|
+
/**
|
|
440
|
+
* Authenticate a pod header (#943) — a pure, dependency-free, WebCrypto-only
|
|
441
|
+
* verifier. Given only the raw pod bytes and a `trustedKeys` map
|
|
442
|
+
* (`keyId → publicKeyB64` the caller already trusts), it reports whether the
|
|
443
|
+
* header was signed by a trusted document signer.
|
|
444
|
+
*
|
|
445
|
+
* Pairs with the signing half in `assembleBundleContainer`/`writePod`: the
|
|
446
|
+
* signed payload is the final wire header with `sig` removed, so verification
|
|
447
|
+
* reconstructs it by stripping EXACTLY the `sig` field — `keyId`, `sigAlg`,
|
|
448
|
+
* and every other header field stay in the verified payload.
|
|
449
|
+
*
|
|
450
|
+
* No store, enclave, or vault dependency — reachable from a static page with
|
|
451
|
+
* only the pod bytes, the trusted-key map, and `globalThis.crypto`.
|
|
452
|
+
*
|
|
453
|
+
* SECURITY — authenticity is not integrity. A `verified` result proves the
|
|
454
|
+
* header (which includes the *claimed* `bodySha256`) is signed by a trusted
|
|
455
|
+
* key; it does NOT prove the body matches that hash. To trust the pod's
|
|
456
|
+
* BODY you MUST also confirm the body hashes to `header.bodySha256` — call
|
|
457
|
+
* `readPod`, which throws `BundleIntegrityError` on mismatch. A `verified`
|
|
458
|
+
* header paired with a swapped body is caught only by that integrity check.
|
|
459
|
+
* This function stays body-free by design so a static page can authenticate a
|
|
460
|
+
* header without decompressing the body; composing the two checks is the
|
|
461
|
+
* caller's responsibility. See `docs/subsystems/pod-signature.md`.
|
|
462
|
+
*/
|
|
463
|
+
export declare function verifyPodHeader(bytes: Uint8Array, trustedKeys: Readonly<Record<string, string>>): Promise<PodVerifyResult>;
|
|
378
464
|
/**
|
|
379
465
|
* Read just the bundle's cover (`https://github.com/vLannaAi/noy-db-docs/blob/main/content/docs/services/public-envelope.md`)
|
|
380
466
|
* — without verifying the body or even parsing the dump JSON. Pass
|
|
@@ -391,6 +477,18 @@ export declare const readNoydbBundleHeader: typeof readPodHeader;
|
|
|
391
477
|
export declare function readPodCover(bytes: Uint8Array, opts?: {
|
|
392
478
|
readonly locale?: string;
|
|
393
479
|
}): Cover | undefined;
|
|
480
|
+
/**
|
|
481
|
+
* Read just the bundle's Redirect record (#944) — without verifying the
|
|
482
|
+
* body or even parsing the dump JSON. Pass the raw bundle bytes; receive
|
|
483
|
+
* the header's `redirect` field or `undefined` if the bundle was written
|
|
484
|
+
* without one.
|
|
485
|
+
*
|
|
486
|
+
* The record is returned UNVERIFIED: `validateBundleHeader` only checks
|
|
487
|
+
* its shape at parse time (a parser has no `trustedKeys`). Callers that
|
|
488
|
+
* intend to follow the redirect MUST separately call `verifyRedirect`
|
|
489
|
+
* (`redirect.js`) before trusting `target`.
|
|
490
|
+
*/
|
|
491
|
+
export declare function readPodRedirect(bytes: Uint8Array): Redirect | undefined;
|
|
394
492
|
/**
|
|
395
493
|
* Read a full `.noydb` bundle: validate magic + header, verify
|
|
396
494
|
* integrity hash over the body bytes, decompress, and return the
|
|
@@ -46,12 +46,15 @@
|
|
|
46
46
|
* bundle and verify its integrity — nothing about the contents.
|
|
47
47
|
*/
|
|
48
48
|
import type { Cover } from '../with-party/directory/cover/types.js';
|
|
49
|
+
import type { Redirect } from './redirect.js';
|
|
49
50
|
/** Magic bytes 'NDB1' (ASCII), identifying a NOYDB bundle. */
|
|
50
51
|
export declare const NOYDB_BUNDLE_MAGIC: Uint8Array<ArrayBuffer>;
|
|
51
52
|
/** Total fixed prefix before the header JSON: 4+1+1+4 bytes. */
|
|
52
53
|
export declare const NOYDB_BUNDLE_PREFIX_BYTES = 10;
|
|
53
|
-
/** Current bundle format version. Bumped on layout changes. */
|
|
54
|
+
/** Current bundle format version. Bumped on layout changes. Default for unsigned pods. */
|
|
54
55
|
export declare const NOYDB_BUNDLE_FORMAT_VERSION = 1;
|
|
56
|
+
/** Format version for pods carrying a header signature (`sig`/`keyId`/`sigAlg`). */
|
|
57
|
+
export declare const NOYDB_BUNDLE_FORMAT_VERSION_SIGNED = 2;
|
|
55
58
|
/**
|
|
56
59
|
* Bitfield interpretation of the flags byte.
|
|
57
60
|
*
|
|
@@ -157,7 +160,95 @@ export interface NoydbPodHeader {
|
|
|
157
160
|
readonly alg: 'aes-256-gcm-pre-shared';
|
|
158
161
|
readonly sealId: string;
|
|
159
162
|
};
|
|
163
|
+
/**
|
|
164
|
+
* Non-secret 16-hex-char fingerprint identifying the signing key
|
|
165
|
+
* used for `sig`. A hash prefix, not the key itself — discloses no
|
|
166
|
+
* crypto config, safe under minimum-disclosure. Present iff `sig`
|
|
167
|
+
* and `sigAlg` are also present (all-or-nothing 3-tuple), and only
|
|
168
|
+
* on `formatVersion === 2` headers.
|
|
169
|
+
*/
|
|
170
|
+
readonly keyId?: string;
|
|
171
|
+
/**
|
|
172
|
+
* Signature authenticating the rest of the header (base64url,
|
|
173
|
+
* no padding). Verifies the header wasn't tampered with in
|
|
174
|
+
* transit/storage — see `with-pod/signature.ts`. Part of the
|
|
175
|
+
* sig/keyId/sigAlg 3-tuple.
|
|
176
|
+
*/
|
|
177
|
+
readonly sig?: string;
|
|
178
|
+
/**
|
|
179
|
+
* Signature algorithm for `sig`. Named `sigAlg` (not `alg`) to
|
|
180
|
+
* avoid confusion with `transferSeal.alg`. Part of the
|
|
181
|
+
* sig/keyId/sigAlg 3-tuple.
|
|
182
|
+
*/
|
|
183
|
+
readonly sigAlg?: 'ed25519';
|
|
184
|
+
/**
|
|
185
|
+
* Engine version range that wrote (and can read) this pod, e.g.
|
|
186
|
+
* `'^0.5.0'`. Discloses only a semver range — no timestamps, no
|
|
187
|
+
* identities — so a version-skew triage step (open a decade-old
|
|
188
|
+
* pod → route to a version-matched read-only player instead of a
|
|
189
|
+
* hard failure) or a landing page can branch before any library
|
|
190
|
+
* code runs. Safe under minimum-disclosure: a range says nothing
|
|
191
|
+
* about who wrote the pod or when.
|
|
192
|
+
*/
|
|
193
|
+
readonly engineRange?: string;
|
|
194
|
+
/**
|
|
195
|
+
* Declared unlock method(s), e.g. `['password', 'webauthn']`. Lets
|
|
196
|
+
* a landing/player present the right unlock UI pre-library, and is
|
|
197
|
+
* ALL a shared connection pod may disclose about its bootstrap
|
|
198
|
+
* (auth method + endpoint class). Safe under minimum-disclosure: it
|
|
199
|
+
* names a method family, not a credential, key, or identity.
|
|
200
|
+
*
|
|
201
|
+
* The member set mirrors the `@noy-db/on-*` package family
|
|
202
|
+
* (`on-password`, `on-webauthn`, `on-oidc`, `on-totp`,
|
|
203
|
+
* `on-email-otp`, `on-magic-link`, `on-pin`, `on-recovery`,
|
|
204
|
+
* `on-shamir`) — the top-level "which on-* package to load" method
|
|
205
|
+
* name, not the finer-grained `FactorKind` used by policy gates
|
|
206
|
+
* (which splits WebAuthn into `webauthn-roaming` /
|
|
207
|
+
* `webauthn-platform` for factor-proof freshness). `on-threat` is
|
|
208
|
+
* excluded — it's a lockout/duress helper, not an unlock method a
|
|
209
|
+
* landing page would present.
|
|
210
|
+
*/
|
|
211
|
+
readonly unlockMethods?: readonly UnlockMethod[];
|
|
212
|
+
/**
|
|
213
|
+
* App-manifest presence flag. Lets a landing fork between
|
|
214
|
+
* "orphan pod → read-only browse" and "linked app → launch flow"
|
|
215
|
+
* without reading the body. Safe under minimum-disclosure: a
|
|
216
|
+
* boolean, not the app's identity or contents.
|
|
217
|
+
*/
|
|
218
|
+
readonly hasApp?: boolean;
|
|
219
|
+
/**
|
|
220
|
+
* Artifact species hint for dispatcher branching, cloud tooling,
|
|
221
|
+
* and the share-flow guard that warns when a data-bearing pod is
|
|
222
|
+
* shared where a pointer was intended. An "orphan" pod is derived
|
|
223
|
+
* (`species: 'full'` + `hasApp: false`), not a separate species.
|
|
224
|
+
* Safe under minimum-disclosure: a coarse artifact-shape label, not
|
|
225
|
+
* contents or identity.
|
|
226
|
+
*/
|
|
227
|
+
readonly species?: 'full' | 'connection' | 'snapshot' | 'redirect' | 'group';
|
|
228
|
+
/**
|
|
229
|
+
* Whether the app pointer (if any) is disclosed pre-auth. Default
|
|
230
|
+
* is `'private'` by product decision (recorded in #942) — absence
|
|
231
|
+
* means private by convention; this field is never auto-injected,
|
|
232
|
+
* only an author's explicit opt-in writes `'public'`. Safe under
|
|
233
|
+
* minimum-disclosure: a disclosure-policy flag, not the pointer
|
|
234
|
+
* itself.
|
|
235
|
+
*/
|
|
236
|
+
readonly pointerMode?: 'public' | 'private';
|
|
237
|
+
/**
|
|
238
|
+
* Signed "this moved, go there" pointer (#944). Carried in the
|
|
239
|
+
* PLAINTEXT header (not the encrypted body) so a dispatcher can follow
|
|
240
|
+
* it pre-auth — no secret, no decompression. Structurally validated
|
|
241
|
+
* here (shape only); the record's OWN signature is a separate
|
|
242
|
+
* verification step (`verifyRedirect`) since a parser has no
|
|
243
|
+
* `trustedKeys`. `readPodRedirect` returns this field UNVERIFIED.
|
|
244
|
+
*/
|
|
245
|
+
readonly redirect?: Redirect;
|
|
160
246
|
}
|
|
247
|
+
/**
|
|
248
|
+
* Declared unlock method names — mirrors the `@noy-db/on-*` package
|
|
249
|
+
* family (see `unlockMethods` doc comment on `NoydbPodHeader`).
|
|
250
|
+
*/
|
|
251
|
+
export type UnlockMethod = 'password' | 'webauthn' | 'oidc' | 'totp' | 'email-otp' | 'magic-link' | 'pin' | 'recovery' | 'shamir';
|
|
161
252
|
/** @deprecated Use `NoydbPodHeader`. */
|
|
162
253
|
export type NoydbBundleHeader = NoydbPodHeader;
|
|
163
254
|
/**
|