@noy-db/hub 0.1.0-pre.9 → 0.2.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/dist/aggregate/index.cjs +100 -36
- package/dist/aggregate/index.cjs.map +1 -1
- package/dist/aggregate/index.d.cts +2 -2
- package/dist/aggregate/index.d.ts +2 -2
- package/dist/aggregate/index.js +16 -9
- package/dist/aggregate/index.js.map +1 -1
- package/dist/attestation/index.cjs +305 -0
- package/dist/attestation/index.cjs.map +1 -0
- package/dist/attestation/index.d.cts +52 -0
- package/dist/attestation/index.d.ts +52 -0
- package/dist/attestation/index.js +36 -0
- package/dist/attestation/index.js.map +1 -0
- package/dist/blobs/index.cjs.map +1 -1
- package/dist/blobs/index.d.cts +7 -6
- package/dist/blobs/index.d.ts +7 -6
- package/dist/blobs/index.js +10 -8
- package/dist/blobs/index.js.map +1 -1
- package/dist/bundle/index.cjs +19121 -60
- package/dist/bundle/index.cjs.map +1 -1
- package/dist/bundle/index.d.cts +175 -6
- package/dist/bundle/index.d.ts +175 -6
- package/dist/bundle/index.js +543 -4
- package/dist/bundle/index.js.map +1 -1
- package/dist/chunk-26NK23DZ.js +296 -0
- package/dist/chunk-26NK23DZ.js.map +1 -0
- package/dist/{chunk-TDR6T5CJ.js → chunk-2LPPNWF6.js} +91 -132
- package/dist/chunk-2LPPNWF6.js.map +1 -0
- package/dist/{chunk-PTVMYYON.js → chunk-2N62W5YP.js} +3 -3
- package/dist/{chunk-QGZRWRSL.js → chunk-3LPV6BXR.js} +4 -4
- package/dist/{chunk-QAVUREFT.js → chunk-4CLICFEY.js} +12 -6
- package/dist/chunk-4CLICFEY.js.map +1 -0
- package/dist/chunk-4USCAEDT.js +10529 -0
- package/dist/chunk-4USCAEDT.js.map +1 -0
- package/dist/chunk-5IXJGFF2.js +83 -0
- package/dist/chunk-5IXJGFF2.js.map +1 -0
- package/dist/chunk-5OEJ6GOT.js +124 -0
- package/dist/chunk-5OEJ6GOT.js.map +1 -0
- package/dist/{chunk-4PWAI7Q4.js → chunk-5OX6XVNS.js} +5 -5
- package/dist/{chunk-2CSJGFCB.js → chunk-6EOXTJS2.js} +6 -229
- package/dist/chunk-6EOXTJS2.js.map +1 -0
- package/dist/chunk-6T2UDBKG.js +53 -0
- package/dist/chunk-6T2UDBKG.js.map +1 -0
- package/dist/{chunk-GOUT6DND.js → chunk-6YLPHBKR.js} +382 -95
- package/dist/chunk-6YLPHBKR.js.map +1 -0
- package/dist/chunk-7CEGU63S.js +179 -0
- package/dist/chunk-7CEGU63S.js.map +1 -0
- package/dist/chunk-A3JMGXPG.js +125 -0
- package/dist/chunk-A3JMGXPG.js.map +1 -0
- package/dist/chunk-BB27JMWB.js +795 -0
- package/dist/chunk-BB27JMWB.js.map +1 -0
- package/dist/{chunk-SCZXXXU4.js → chunk-BDV7INMP.js} +7 -32
- package/dist/chunk-BDV7INMP.js.map +1 -0
- package/dist/chunk-C3WE6UJY.js +19 -0
- package/dist/chunk-C3WE6UJY.js.map +1 -0
- package/dist/chunk-CH22FZHT.js +96 -0
- package/dist/chunk-CH22FZHT.js.map +1 -0
- package/dist/chunk-CXFOITNS.js +34 -0
- package/dist/chunk-CXFOITNS.js.map +1 -0
- package/dist/chunk-CXJG63MA.js +109 -0
- package/dist/chunk-CXJG63MA.js.map +1 -0
- package/dist/chunk-DAP2XL7Q.js +51 -0
- package/dist/chunk-DAP2XL7Q.js.map +1 -0
- package/dist/{chunk-AVVPZ4BC.js → chunk-DJRWA3Q5.js} +4 -4
- package/dist/chunk-DRXIZOFV.js +233 -0
- package/dist/chunk-DRXIZOFV.js.map +1 -0
- package/dist/chunk-FO3UEG4S.js +313 -0
- package/dist/chunk-FO3UEG4S.js.map +1 -0
- package/dist/chunk-GAUEWM7D.js +147 -0
- package/dist/chunk-GAUEWM7D.js.map +1 -0
- package/dist/{chunk-MDDTIZUO.js → chunk-GNHAC43Q.js} +218 -119
- package/dist/chunk-GNHAC43Q.js.map +1 -0
- package/dist/chunk-HHOO7HGH.js +57 -0
- package/dist/chunk-HHOO7HGH.js.map +1 -0
- package/dist/{chunk-WDM5XGGS.js → chunk-HQSQC2XL.js} +182 -12
- package/dist/chunk-HQSQC2XL.js.map +1 -0
- package/dist/chunk-IMYKDWB4.js +139 -0
- package/dist/chunk-IMYKDWB4.js.map +1 -0
- package/dist/{chunk-M62XNWRA.js → chunk-LSTBFLL2.js} +2 -2
- package/dist/{chunk-ACLDOTNQ.js → chunk-O6EJ6WTI.js} +436 -3
- package/dist/chunk-O6EJ6WTI.js.map +1 -0
- package/dist/chunk-PC6ZEDRL.js +71 -0
- package/dist/chunk-PC6ZEDRL.js.map +1 -0
- package/dist/chunk-PM3QYWUU.js +251 -0
- package/dist/chunk-PM3QYWUU.js.map +1 -0
- package/dist/chunk-PVUUIWHY.js +73 -0
- package/dist/chunk-PVUUIWHY.js.map +1 -0
- package/dist/chunk-PXTQPZO4.js +830 -0
- package/dist/chunk-PXTQPZO4.js.map +1 -0
- package/dist/{chunk-ZFKD4QMV.js → chunk-QSOYKKMD.js} +4 -4
- package/dist/chunk-QSOYKKMD.js.map +1 -0
- package/dist/{chunk-MR4424N3.js → chunk-R233SLY3.js} +2 -2
- package/dist/chunk-RC6SU5NO.js +36 -0
- package/dist/chunk-RC6SU5NO.js.map +1 -0
- package/dist/{chunk-USKYUS74.js → chunk-RRNA5GKT.js} +2 -2
- package/dist/{chunk-R36SIKES.js → chunk-RYIL3PI2.js} +2 -2
- package/dist/chunk-STNPB3UM.js +9 -0
- package/dist/chunk-STNPB3UM.js.map +1 -0
- package/dist/{chunk-M5INGEFC.js → chunk-TV3YZ35S.js} +7 -1
- package/dist/chunk-TV3YZ35S.js.map +1 -0
- package/dist/chunk-TY32C732.js +59 -0
- package/dist/chunk-TY32C732.js.map +1 -0
- package/dist/chunk-UMLVJTYV.js +20 -0
- package/dist/chunk-UMLVJTYV.js.map +1 -0
- package/dist/{chunk-NPC4LFV5.js → chunk-WIBHRONM.js} +2 -2
- package/dist/chunk-WIBHRONM.js.map +1 -0
- package/dist/{chunk-RKJ6OL7K.js → chunk-WIRRPTFH.js} +1 -1
- package/dist/chunk-WIRRPTFH.js.map +1 -0
- package/dist/{chunk-VQBTTTUN.js → chunk-Y26YV5R3.js} +4 -4
- package/dist/{chunk-VQBTTTUN.js.map → chunk-Y26YV5R3.js.map} +1 -1
- package/dist/{chunk-NXFEYLVG.js → chunk-YM7LFCG7.js} +5 -4
- package/dist/{chunk-NXFEYLVG.js.map → chunk-YM7LFCG7.js.map} +1 -1
- package/dist/{chunk-CIMZBAZB.js → chunk-Z6FNBOTC.js} +1 -1
- package/dist/chunk-Z6FNBOTC.js.map +1 -0
- package/dist/chunk-ZROPXHJY.js +82 -0
- package/dist/chunk-ZROPXHJY.js.map +1 -0
- package/dist/consent/index.cjs.map +1 -1
- package/dist/consent/index.d.cts +7 -6
- package/dist/consent/index.d.ts +7 -6
- package/dist/consent/index.js +3 -3
- package/dist/{crypto-IVKU7YTT.js → crypto-2CRLG4F4.js} +3 -3
- package/dist/{delegation-2DBS2EOH.js → delegation-ZTRT2PRV.js} +5 -4
- package/dist/derivations/index.cjs +368 -0
- package/dist/derivations/index.cjs.map +1 -0
- package/dist/derivations/index.d.cts +72 -0
- package/dist/derivations/index.d.ts +72 -0
- package/dist/derivations/index.js +27 -0
- package/dist/{dev-unlock-Da1B0TIK.d.cts → dev-unlock-AglVnkPY.d.cts} +1 -1
- package/dist/{dev-unlock-BdPp68qn.d.ts → dev-unlock-BOEYl1xl.d.ts} +1 -1
- package/dist/discriminant-BN9REW3o.d.cts +60 -0
- package/dist/discriminant-BN9REW3o.d.ts +60 -0
- package/dist/executor-S76VN45G.js +8 -0
- package/dist/executor-UCXLIGLW.js +11 -0
- package/dist/executor-UCXLIGLW.js.map +1 -0
- package/dist/executor-ZCNZJMGR.js +8 -0
- package/dist/executor-ZCNZJMGR.js.map +1 -0
- package/dist/fanout-sidecar-OKPMMPLG.js +51 -0
- package/dist/fanout-sidecar-OKPMMPLG.js.map +1 -0
- package/dist/guards/index.cjs +322 -0
- package/dist/guards/index.cjs.map +1 -0
- package/dist/guards/index.d.cts +31 -0
- package/dist/guards/index.d.ts +31 -0
- package/dist/guards/index.js +29 -0
- package/dist/guards/index.js.map +1 -0
- package/dist/{hash-lsoL3eEW.d.ts → hash-B9m3_fhj.d.ts} +1 -1
- package/dist/{hash-BEfzPKwo.d.cts → hash-RVqz2zi8.d.cts} +1 -1
- package/dist/history/index.cjs +9 -2
- package/dist/history/index.cjs.map +1 -1
- package/dist/history/index.d.cts +8 -7
- package/dist/history/index.d.ts +8 -7
- package/dist/history/index.js +6 -6
- package/dist/i18n/index.cjs +368 -27
- package/dist/i18n/index.cjs.map +1 -1
- package/dist/i18n/index.d.cts +7 -6
- package/dist/i18n/index.d.ts +7 -6
- package/dist/i18n/index.js +34 -6
- package/dist/i18n/index.js.map +1 -1
- package/dist/{index-DJTf9yxn.d.ts → index-B8bjExET.d.cts} +508 -14
- package/dist/{index-6xNpPsxR.d.cts → index-DfUbNad8.d.ts} +508 -14
- package/dist/index.cjs +8779 -1260
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +231 -19
- package/dist/index.d.ts +231 -19
- package/dist/index.js +311 -7370
- package/dist/index.js.map +1 -1
- package/dist/indexing/index.cjs +7 -1
- package/dist/indexing/index.cjs.map +1 -1
- package/dist/indexing/index.d.cts +3 -3
- package/dist/indexing/index.d.ts +3 -3
- package/dist/indexing/index.js +4 -4
- package/dist/issue-3W6IVLKH.js +12 -0
- package/dist/issue-3W6IVLKH.js.map +1 -0
- package/dist/{lazy-builder-BwEoBQZ9.d.ts → lazy-builder-Ci5_YG73.d.cts} +2 -2
- package/dist/{lazy-builder-CZVLKh0Z.d.cts → lazy-builder-D5GU14TS.d.ts} +2 -2
- package/dist/{ledger-QZTTHQAQ.js → ledger-O7FXOG3D.js} +6 -6
- package/dist/ledger-O7FXOG3D.js.map +1 -0
- package/dist/materialized-views/index.cjs +856 -0
- package/dist/materialized-views/index.cjs.map +1 -0
- package/dist/materialized-views/index.d.cts +186 -0
- package/dist/materialized-views/index.d.ts +186 -0
- package/dist/materialized-views/index.js +45 -0
- package/dist/materialized-views/index.js.map +1 -0
- package/dist/noydb-YAZNH5TI.js +34 -0
- package/dist/noydb-YAZNH5TI.js.map +1 -0
- package/dist/overlay-views/index.cjs +369 -0
- package/dist/overlay-views/index.cjs.map +1 -0
- package/dist/overlay-views/index.d.cts +82 -0
- package/dist/overlay-views/index.d.ts +82 -0
- package/dist/overlay-views/index.js +25 -0
- package/dist/overlay-views/index.js.map +1 -0
- package/dist/periods/index.cjs +7 -1
- package/dist/periods/index.cjs.map +1 -1
- package/dist/periods/index.d.cts +7 -6
- package/dist/periods/index.d.ts +7 -6
- package/dist/periods/index.js +6 -6
- package/dist/{predicate-SBHmi6D0.d.cts → predicate-Bt5ft-9c.d.cts} +51 -2
- package/dist/{predicate-SBHmi6D0.d.ts → predicate-Bt5ft-9c.d.ts} +51 -2
- package/dist/{public-envelope-6JTACYJV.js → public-envelope-HMYHZIRH.js} +4 -4
- package/dist/public-envelope-HMYHZIRH.js.map +1 -0
- package/dist/query/index.cjs +555 -128
- package/dist/query/index.cjs.map +1 -1
- package/dist/query/index.d.cts +3 -3
- package/dist/query/index.d.ts +3 -3
- package/dist/query/index.js +32 -11
- package/dist/read-only-facade-ITU6L7BL.js +7 -0
- package/dist/read-only-facade-ITU6L7BL.js.map +1 -0
- package/dist/registry-DKEXOJVO.js +7 -0
- package/dist/registry-DKEXOJVO.js.map +1 -0
- package/dist/registry-ST2VNFZC.js +10 -0
- package/dist/registry-ST2VNFZC.js.map +1 -0
- package/dist/registry-UFIK7CSR.js +8 -0
- package/dist/registry-UFIK7CSR.js.map +1 -0
- package/dist/registry-ZGYYSM5I.js +8 -0
- package/dist/registry-ZGYYSM5I.js.map +1 -0
- package/dist/revoke-S6JMSLUN.js +17 -0
- package/dist/revoke-S6JMSLUN.js.map +1 -0
- package/dist/session/index.cjs +7 -1
- package/dist/session/index.cjs.map +1 -1
- package/dist/session/index.d.cts +8 -7
- package/dist/session/index.d.ts +8 -7
- package/dist/session/index.js +10 -3
- package/dist/session/index.js.map +1 -1
- package/dist/shadow/index.cjs.map +1 -1
- package/dist/shadow/index.d.cts +7 -6
- package/dist/shadow/index.d.ts +7 -6
- package/dist/shadow/index.js +2 -2
- package/dist/signer-7NPTB3SQ.js +18 -0
- package/dist/signer-7NPTB3SQ.js.map +1 -0
- package/dist/snapshots/index.cjs +937 -0
- package/dist/snapshots/index.cjs.map +1 -0
- package/dist/snapshots/index.d.cts +28 -0
- package/dist/snapshots/index.d.ts +28 -0
- package/dist/snapshots/index.js +152 -0
- package/dist/snapshots/index.js.map +1 -0
- package/dist/stale-VKXSXJF4.js +13 -0
- package/dist/stale-VKXSXJF4.js.map +1 -0
- package/dist/store/index.cjs +14 -0
- package/dist/store/index.cjs.map +1 -1
- package/dist/store/index.d.cts +7 -6
- package/dist/store/index.d.ts +7 -6
- package/dist/store/index.js +5 -2
- package/dist/{strategy-D-SrOLCl.d.ts → strategy-CT2LCKAX.d.cts} +84 -19
- package/dist/{strategy-D-SrOLCl.d.cts → strategy-CT2LCKAX.d.ts} +84 -19
- package/dist/sync/index.cjs.map +1 -1
- package/dist/sync/index.d.cts +6 -5
- package/dist/sync/index.d.ts +6 -5
- package/dist/sync/index.js +4 -4
- package/dist/team/index.cjs +1554 -2
- package/dist/team/index.cjs.map +1 -1
- package/dist/team/index.d.cts +7 -6
- package/dist/team/index.d.ts +7 -6
- package/dist/team/index.js +77 -8
- package/dist/tx/index.cjs +375 -43
- package/dist/tx/index.cjs.map +1 -1
- package/dist/tx/index.d.cts +8 -7
- package/dist/tx/index.d.ts +8 -7
- package/dist/tx/index.js +56 -3
- package/dist/tx/index.js.map +1 -1
- package/dist/{types-Bo7NSXJr.d.ts → types-CaNQm4i8.d.ts} +3902 -614
- package/dist/{types-Bnb82f5R.d.cts → types-n2_IfwlQ.d.cts} +3902 -614
- package/dist/{index-CywCC1qZ.d.cts → ulid-B9SMWj5i.d.ts} +216 -27
- package/dist/{index-8QDuznDr.d.ts → ulid-CLMjmyhG.d.cts} +216 -27
- package/dist/util/index.cjs +7 -0
- package/dist/util/index.cjs.map +1 -1
- package/dist/util/index.d.cts +2 -0
- package/dist/util/index.d.ts +2 -0
- package/dist/util/index.js +5 -1
- package/dist/util/index.js.map +1 -1
- package/dist/with-derivation-CVIOPTUf.d.ts +13 -0
- package/dist/with-derivation-aKrtS7Jj.d.cts +13 -0
- package/dist/with-guard-DZQbPzoP.d.cts +18 -0
- package/dist/with-guard-DseETUrF.d.ts +18 -0
- package/dist/with-materialized-view-C1eA1_T_.d.cts +27 -0
- package/dist/with-materialized-view-DaYaE8-Q.d.ts +27 -0
- package/dist/with-overlayed-view-DQsh2p8H.d.ts +13 -0
- package/dist/with-overlayed-view-DleJfKcV.d.cts +13 -0
- package/package.json +77 -3
- package/dist/chunk-2CSJGFCB.js.map +0 -1
- package/dist/chunk-ACLDOTNQ.js.map +0 -1
- package/dist/chunk-BTDCBVJW.js +0 -160
- package/dist/chunk-BTDCBVJW.js.map +0 -1
- package/dist/chunk-CIMZBAZB.js.map +0 -1
- package/dist/chunk-EXHNQEV4.js +0 -392
- package/dist/chunk-EXHNQEV4.js.map +0 -1
- package/dist/chunk-GOUT6DND.js.map +0 -1
- package/dist/chunk-M5INGEFC.js.map +0 -1
- package/dist/chunk-MDDTIZUO.js.map +0 -1
- package/dist/chunk-NPC4LFV5.js.map +0 -1
- package/dist/chunk-QAVUREFT.js.map +0 -1
- package/dist/chunk-RKJ6OL7K.js.map +0 -1
- package/dist/chunk-SCZXXXU4.js.map +0 -1
- package/dist/chunk-TDR6T5CJ.js.map +0 -1
- package/dist/chunk-WDM5XGGS.js.map +0 -1
- package/dist/chunk-ZFKD4QMV.js.map +0 -1
- /package/dist/{chunk-PTVMYYON.js.map → chunk-2N62W5YP.js.map} +0 -0
- /package/dist/{chunk-QGZRWRSL.js.map → chunk-3LPV6BXR.js.map} +0 -0
- /package/dist/{chunk-4PWAI7Q4.js.map → chunk-5OX6XVNS.js.map} +0 -0
- /package/dist/{chunk-AVVPZ4BC.js.map → chunk-DJRWA3Q5.js.map} +0 -0
- /package/dist/{chunk-M62XNWRA.js.map → chunk-LSTBFLL2.js.map} +0 -0
- /package/dist/{chunk-MR4424N3.js.map → chunk-R233SLY3.js.map} +0 -0
- /package/dist/{chunk-USKYUS74.js.map → chunk-RRNA5GKT.js.map} +0 -0
- /package/dist/{chunk-R36SIKES.js.map → chunk-RYIL3PI2.js.map} +0 -0
- /package/dist/{crypto-IVKU7YTT.js.map → crypto-2CRLG4F4.js.map} +0 -0
- /package/dist/{delegation-2DBS2EOH.js.map → delegation-ZTRT2PRV.js.map} +0 -0
- /package/dist/{ledger-QZTTHQAQ.js.map → derivations/index.js.map} +0 -0
- /package/dist/{public-envelope-6JTACYJV.js.map → executor-S76VN45G.js.map} +0 -0
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ATTESTATIONS_COLLECTION,
|
|
3
|
+
REVOKED_RECORD_ID,
|
|
4
|
+
loadOrCreateSigner
|
|
5
|
+
} from "./chunk-HHOO7HGH.js";
|
|
6
|
+
import {
|
|
7
|
+
NOYDB_FORMAT_VERSION
|
|
8
|
+
} from "./chunk-WIRRPTFH.js";
|
|
9
|
+
import {
|
|
10
|
+
decrypt,
|
|
11
|
+
encrypt
|
|
12
|
+
} from "./chunk-R233SLY3.js";
|
|
13
|
+
import {
|
|
14
|
+
AttestationError,
|
|
15
|
+
ConflictError
|
|
16
|
+
} from "./chunk-O6EJ6WTI.js";
|
|
17
|
+
|
|
18
|
+
// src/attestation/revoke.ts
|
|
19
|
+
import { signRevocationList } from "@noy-db/attestation";
|
|
20
|
+
function requireOwner(ctx, op) {
|
|
21
|
+
if (ctx.role !== "owner") {
|
|
22
|
+
throw new AttestationError(`${op} requires the 'owner' role; caller is '${ctx.role}'. Revocation is the firm's identity operation.`);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
async function readSet(store, vault, dek) {
|
|
26
|
+
const env = await store.get(vault, ATTESTATIONS_COLLECTION, REVOKED_RECORD_ID);
|
|
27
|
+
if (!env) return { docIds: /* @__PURE__ */ new Set(), version: void 0 };
|
|
28
|
+
const set = JSON.parse(await decrypt(env._iv, env._data, dek));
|
|
29
|
+
return { docIds: new Set(set.docIds), version: env._v };
|
|
30
|
+
}
|
|
31
|
+
async function mutateSet(ctx, mutate) {
|
|
32
|
+
const dek = await ctx.getDEK();
|
|
33
|
+
for (let attempt = 0; attempt < 2; attempt++) {
|
|
34
|
+
const { docIds, version } = await readSet(ctx.store, ctx.vault, dek);
|
|
35
|
+
mutate(docIds);
|
|
36
|
+
const payload = { docIds: [...docIds].sort(), updatedAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
37
|
+
const { iv, data } = await encrypt(JSON.stringify(payload), dek);
|
|
38
|
+
const expectedVersion = version ?? 0;
|
|
39
|
+
const env = {
|
|
40
|
+
_noydb: NOYDB_FORMAT_VERSION,
|
|
41
|
+
_v: expectedVersion + 1,
|
|
42
|
+
_ts: payload.updatedAt,
|
|
43
|
+
_iv: iv,
|
|
44
|
+
_data: data
|
|
45
|
+
};
|
|
46
|
+
try {
|
|
47
|
+
await ctx.store.put(ctx.vault, ATTESTATIONS_COLLECTION, REVOKED_RECORD_ID, env, expectedVersion);
|
|
48
|
+
return;
|
|
49
|
+
} catch (e) {
|
|
50
|
+
if (e instanceof ConflictError && attempt === 0) continue;
|
|
51
|
+
throw e;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
async function revokeDocCore(ctx, docId) {
|
|
56
|
+
requireOwner(ctx, "revokeAttestation");
|
|
57
|
+
const issued = await ctx.store.get(ctx.vault, ATTESTATIONS_COLLECTION, docId);
|
|
58
|
+
if (!issued) throw new AttestationError(`revokeAttestation: attestation '${docId}' not found (was it issued by this vault?).`);
|
|
59
|
+
await mutateSet(ctx, (ids) => ids.add(docId));
|
|
60
|
+
}
|
|
61
|
+
async function unrevokeDocCore(ctx, docId) {
|
|
62
|
+
requireOwner(ctx, "unrevokeAttestation");
|
|
63
|
+
await mutateSet(ctx, (ids) => ids.delete(docId));
|
|
64
|
+
}
|
|
65
|
+
async function getRevokedDocIdsCore(ctx) {
|
|
66
|
+
const dek = await ctx.getDEK();
|
|
67
|
+
const { docIds } = await readSet(ctx.store, ctx.vault, dek);
|
|
68
|
+
return [...docIds].sort();
|
|
69
|
+
}
|
|
70
|
+
async function publishRevocationListCore(ctx) {
|
|
71
|
+
requireOwner(ctx, "publishRevocationList");
|
|
72
|
+
const docIds = await getRevokedDocIdsCore(ctx);
|
|
73
|
+
const signer = await loadOrCreateSigner(ctx.store, ctx.vault, () => ctx.getDEK());
|
|
74
|
+
return signRevocationList(docIds, (/* @__PURE__ */ new Date()).toISOString(), signer.keyId, signer.privateKeyPkcs8B64);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export {
|
|
78
|
+
revokeDocCore,
|
|
79
|
+
unrevokeDocCore,
|
|
80
|
+
getRevokedDocIdsCore,
|
|
81
|
+
publishRevocationListCore
|
|
82
|
+
};
|
|
83
|
+
//# sourceMappingURL=chunk-5IXJGFF2.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/attestation/revoke.ts"],"sourcesContent":["import type { NoydbStore, EncryptedEnvelope } from '../types.js'\nimport { NOYDB_FORMAT_VERSION } from '../types.js'\nimport { encrypt, decrypt } from '../crypto.js'\nimport { AttestationError, ConflictError } from '../errors.js'\nimport { loadOrCreateSigner, ATTESTATIONS_COLLECTION, REVOKED_RECORD_ID } from './signer.js'\nimport { signRevocationList, type RevocationList } from '@noy-db/attestation'\n\n/** Everything the revoke core needs from the Vault, injected for testability. */\nexport interface RevokeContext {\n readonly store: NoydbStore\n readonly vault: string\n readonly role: string\n /** The _attestations collection DEK. */\n getDEK(): Promise<CryptoKey>\n}\n\ninterface RevokedSet {\n docIds: string[]\n updatedAt: string\n}\n\nfunction requireOwner(ctx: RevokeContext, op: string): void {\n if (ctx.role !== 'owner') {\n throw new AttestationError(`${op} requires the 'owner' role; caller is '${ctx.role}'. Revocation is the firm's identity operation.`)\n }\n}\n\nasync function readSet(store: NoydbStore, vault: string, dek: CryptoKey): Promise<{ docIds: Set<string>; version: number | undefined }> {\n const env = await store.get(vault, ATTESTATIONS_COLLECTION, REVOKED_RECORD_ID)\n if (!env) return { docIds: new Set<string>(), version: undefined }\n const set = JSON.parse(await decrypt(env._iv, env._data, dek)) as RevokedSet\n return { docIds: new Set(set.docIds), version: env._v }\n}\n\n/** Read-modify-write the _revoked set with optimistic concurrency + one retry. */\nasync function mutateSet(ctx: RevokeContext, mutate: (ids: Set<string>) => void): Promise<void> {\n const dek = await ctx.getDEK()\n for (let attempt = 0; attempt < 2; attempt++) {\n const { docIds, version } = await readSet(ctx.store, ctx.vault, dek)\n mutate(docIds)\n const payload: RevokedSet = { docIds: [...docIds].sort(), updatedAt: new Date().toISOString() }\n const { iv, data } = await encrypt(JSON.stringify(payload), dek)\n const expectedVersion = version ?? 0\n const env: EncryptedEnvelope = {\n _noydb: NOYDB_FORMAT_VERSION, _v: expectedVersion + 1, _ts: payload.updatedAt, _iv: iv, _data: data,\n }\n try {\n await ctx.store.put(ctx.vault, ATTESTATIONS_COLLECTION, REVOKED_RECORD_ID, env, expectedVersion)\n return\n } catch (e) {\n if (e instanceof ConflictError && attempt === 0) continue\n throw e\n }\n }\n}\n\nexport async function revokeDocCore(ctx: RevokeContext, docId: string): Promise<void> {\n requireOwner(ctx, 'revokeAttestation')\n const issued = await ctx.store.get(ctx.vault, ATTESTATIONS_COLLECTION, docId)\n if (!issued) throw new AttestationError(`revokeAttestation: attestation '${docId}' not found (was it issued by this vault?).`)\n await mutateSet(ctx, (ids) => ids.add(docId))\n}\n\nexport async function unrevokeDocCore(ctx: RevokeContext, docId: string): Promise<void> {\n requireOwner(ctx, 'unrevokeAttestation')\n await mutateSet(ctx, (ids) => ids.delete(docId))\n}\n\nexport async function getRevokedDocIdsCore(ctx: RevokeContext): Promise<string[]> {\n const dek = await ctx.getDEK()\n const { docIds } = await readSet(ctx.store, ctx.vault, dek)\n return [...docIds].sort()\n}\n\nexport async function publishRevocationListCore(ctx: RevokeContext): Promise<RevocationList> {\n requireOwner(ctx, 'publishRevocationList')\n const docIds = await getRevokedDocIdsCore(ctx)\n const signer = await loadOrCreateSigner(ctx.store, ctx.vault, () => ctx.getDEK())\n return signRevocationList(docIds, new Date().toISOString(), signer.keyId, signer.privateKeyPkcs8B64)\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAKA,SAAS,0BAA+C;AAgBxD,SAAS,aAAa,KAAoB,IAAkB;AAC1D,MAAI,IAAI,SAAS,SAAS;AACxB,UAAM,IAAI,iBAAiB,GAAG,EAAE,0CAA0C,IAAI,IAAI,iDAAiD;AAAA,EACrI;AACF;AAEA,eAAe,QAAQ,OAAmB,OAAe,KAA+E;AACtI,QAAM,MAAM,MAAM,MAAM,IAAI,OAAO,yBAAyB,iBAAiB;AAC7E,MAAI,CAAC,IAAK,QAAO,EAAE,QAAQ,oBAAI,IAAY,GAAG,SAAS,OAAU;AACjE,QAAM,MAAM,KAAK,MAAM,MAAM,QAAQ,IAAI,KAAK,IAAI,OAAO,GAAG,CAAC;AAC7D,SAAO,EAAE,QAAQ,IAAI,IAAI,IAAI,MAAM,GAAG,SAAS,IAAI,GAAG;AACxD;AAGA,eAAe,UAAU,KAAoB,QAAmD;AAC9F,QAAM,MAAM,MAAM,IAAI,OAAO;AAC7B,WAAS,UAAU,GAAG,UAAU,GAAG,WAAW;AAC5C,UAAM,EAAE,QAAQ,QAAQ,IAAI,MAAM,QAAQ,IAAI,OAAO,IAAI,OAAO,GAAG;AACnE,WAAO,MAAM;AACb,UAAM,UAAsB,EAAE,QAAQ,CAAC,GAAG,MAAM,EAAE,KAAK,GAAG,YAAW,oBAAI,KAAK,GAAE,YAAY,EAAE;AAC9F,UAAM,EAAE,IAAI,KAAK,IAAI,MAAM,QAAQ,KAAK,UAAU,OAAO,GAAG,GAAG;AAC/D,UAAM,kBAAkB,WAAW;AACnC,UAAM,MAAyB;AAAA,MAC7B,QAAQ;AAAA,MAAsB,IAAI,kBAAkB;AAAA,MAAG,KAAK,QAAQ;AAAA,MAAW,KAAK;AAAA,MAAI,OAAO;AAAA,IACjG;AACA,QAAI;AACF,YAAM,IAAI,MAAM,IAAI,IAAI,OAAO,yBAAyB,mBAAmB,KAAK,eAAe;AAC/F;AAAA,IACF,SAAS,GAAG;AACV,UAAI,aAAa,iBAAiB,YAAY,EAAG;AACjD,YAAM;AAAA,IACR;AAAA,EACF;AACF;AAEA,eAAsB,cAAc,KAAoB,OAA8B;AACpF,eAAa,KAAK,mBAAmB;AACrC,QAAM,SAAS,MAAM,IAAI,MAAM,IAAI,IAAI,OAAO,yBAAyB,KAAK;AAC5E,MAAI,CAAC,OAAQ,OAAM,IAAI,iBAAiB,mCAAmC,KAAK,6CAA6C;AAC7H,QAAM,UAAU,KAAK,CAAC,QAAQ,IAAI,IAAI,KAAK,CAAC;AAC9C;AAEA,eAAsB,gBAAgB,KAAoB,OAA8B;AACtF,eAAa,KAAK,qBAAqB;AACvC,QAAM,UAAU,KAAK,CAAC,QAAQ,IAAI,OAAO,KAAK,CAAC;AACjD;AAEA,eAAsB,qBAAqB,KAAuC;AAChF,QAAM,MAAM,MAAM,IAAI,OAAO;AAC7B,QAAM,EAAE,OAAO,IAAI,MAAM,QAAQ,IAAI,OAAO,IAAI,OAAO,GAAG;AAC1D,SAAO,CAAC,GAAG,MAAM,EAAE,KAAK;AAC1B;AAEA,eAAsB,0BAA0B,KAA6C;AAC3F,eAAa,KAAK,uBAAuB;AACzC,QAAM,SAAS,MAAM,qBAAqB,GAAG;AAC7C,QAAM,SAAS,MAAM,mBAAmB,IAAI,OAAO,IAAI,OAAO,MAAM,IAAI,OAAO,CAAC;AAChF,SAAO,mBAAmB,SAAQ,oBAAI,KAAK,GAAE,YAAY,GAAG,OAAO,OAAO,OAAO,kBAAkB;AACrG;","names":[]}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DerivationCapExceededError,
|
|
3
|
+
DerivationOutputShapeError
|
|
4
|
+
} from "./chunk-O6EJ6WTI.js";
|
|
5
|
+
|
|
6
|
+
// src/derivations/executor.ts
|
|
7
|
+
var DerivationExecutor = {
|
|
8
|
+
/**
|
|
9
|
+
* Run `derive` once, validate output shape against the spec, stamp
|
|
10
|
+
* `_derivedFrom` onto every output. Returns per-output success or
|
|
11
|
+
* failure; throws only for shape mismatches (a contract violation).
|
|
12
|
+
*/
|
|
13
|
+
async run(strategy, source, sourceVersion, strategyHash, ctx) {
|
|
14
|
+
const outputs = {};
|
|
15
|
+
let derived;
|
|
16
|
+
try {
|
|
17
|
+
derived = await Promise.resolve(strategy.derive(source, ctx));
|
|
18
|
+
} catch (err) {
|
|
19
|
+
for (const key of Object.keys(strategy.outputs)) {
|
|
20
|
+
outputs[key] = {
|
|
21
|
+
kind: "failed",
|
|
22
|
+
value: {},
|
|
23
|
+
ok: false,
|
|
24
|
+
error: err instanceof Error ? err : new Error(String(err))
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
return { outputs, failed: true };
|
|
28
|
+
}
|
|
29
|
+
const meta = {
|
|
30
|
+
source: strategy.source,
|
|
31
|
+
sourceId: source.id,
|
|
32
|
+
sourceVersion,
|
|
33
|
+
derivedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
34
|
+
strategyHash
|
|
35
|
+
};
|
|
36
|
+
for (const key of Object.keys(strategy.outputs)) {
|
|
37
|
+
const outSpec = strategy.outputs[key];
|
|
38
|
+
if (!outSpec) continue;
|
|
39
|
+
const value = derived[key];
|
|
40
|
+
if (outSpec.shape === "array") {
|
|
41
|
+
if (value === void 0 || value === null) {
|
|
42
|
+
outputs[key] = { kind: "array", ok: true, entries: [] };
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
if (!Array.isArray(value)) {
|
|
46
|
+
throw new DerivationOutputShapeError(
|
|
47
|
+
key,
|
|
48
|
+
`shape 'array' expects an array, got ${typeof value}`
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
const maxFanout = outSpec.maxFanout ?? 64;
|
|
52
|
+
if (value.length > maxFanout) {
|
|
53
|
+
throw new DerivationCapExceededError(key, value.length, maxFanout);
|
|
54
|
+
}
|
|
55
|
+
const entries = [];
|
|
56
|
+
const seenKeys = /* @__PURE__ */ new Set();
|
|
57
|
+
for (let i = 0; i < value.length; i++) {
|
|
58
|
+
const row = value[i];
|
|
59
|
+
if (row === null || typeof row !== "object") {
|
|
60
|
+
throw new DerivationOutputShapeError(
|
|
61
|
+
key,
|
|
62
|
+
`array member at index ${i} must be a non-null object (got ${row === null ? "null" : typeof row})`
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
let derivedKey;
|
|
66
|
+
try {
|
|
67
|
+
derivedKey = outSpec.key(row);
|
|
68
|
+
} catch (err) {
|
|
69
|
+
throw new DerivationOutputShapeError(
|
|
70
|
+
key,
|
|
71
|
+
`key extractor threw on array member at index ${i}: ` + (err instanceof Error ? err.message : String(err))
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
if (typeof derivedKey !== "string" || derivedKey.length === 0) {
|
|
75
|
+
throw new DerivationOutputShapeError(
|
|
76
|
+
key,
|
|
77
|
+
`key extractor returned ${typeof derivedKey === "string" ? "empty string" : typeof derivedKey} at index ${i}; expected non-empty string`
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
if (seenKeys.has(derivedKey)) {
|
|
81
|
+
throw new DerivationOutputShapeError(
|
|
82
|
+
key,
|
|
83
|
+
`duplicate key "${derivedKey}" in array output (index ${i}); each derived row must have a unique key within a single derive() invocation`
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
seenKeys.add(derivedKey);
|
|
87
|
+
entries.push({
|
|
88
|
+
key: derivedKey,
|
|
89
|
+
value: { ...row, _derivedFrom: meta }
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
outputs[key] = { kind: "array", ok: true, entries };
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
if (value === void 0 || value === null) {
|
|
96
|
+
if (outSpec.optional === true) {
|
|
97
|
+
outputs[key] = { kind: "record", value: {}, ok: true, skipped: true };
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
throw new DerivationOutputShapeError(
|
|
101
|
+
key,
|
|
102
|
+
`expected object, got ${value === void 0 ? "undefined" : "null"}`
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
if (typeof value !== "object") {
|
|
106
|
+
throw new DerivationOutputShapeError(
|
|
107
|
+
key,
|
|
108
|
+
`expected object, got ${typeof value}`
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
outputs[key] = {
|
|
112
|
+
kind: "record",
|
|
113
|
+
value: { ...value, _derivedFrom: meta },
|
|
114
|
+
ok: true
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
return { outputs, failed: false };
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
export {
|
|
122
|
+
DerivationExecutor
|
|
123
|
+
};
|
|
124
|
+
//# sourceMappingURL=chunk-5OEJ6GOT.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/derivations/executor.ts"],"sourcesContent":["import { DerivationCapExceededError, DerivationOutputShapeError } from '../errors.js'\nimport type { DerivationContext, DerivationStrategy, DerivedFromMeta } from './types.js'\n\nexport interface RunResult {\n outputs: Record<string, OutputResult>\n failed: boolean\n}\n\n/**\n * Per-output result of a strategy invocation. Discriminated by\n * `kind`:\n *\n * - `record` — the existing v1 shape: one value (or a \"skipped\"\n * marker if the output was optional and `derive` returned null).\n * - `array` — a list of `(key, value)` entries.\n * The caller diffs these against the previously-emitted key set\n * (loaded from the fanout sidecar) to compute deletes + upserts.\n */\nexport type OutputResult =\n | RecordOutputResult\n | ArrayOutputResult\n | FailedOutputResult\n\nexport interface RecordOutputResult {\n kind: 'record'\n value: Record<string, unknown>\n ok: true\n /**\n * `true` when an optional output returned `null` /\n * `undefined`. The caller deletes any previously-emitted output at\n * the same id (mirrors \"tombstone for derived data\"); a never-emitted\n * output is a silent no-op. `ok: true` because skipping is a\n * successful outcome, not a failure.\n */\n skipped?: boolean\n}\n\nexport interface ArrayOutputResult {\n kind: 'array'\n ok: true\n /** One `(key, value)` per derived row. Empty array means \"all prior outputs for this source go.\" */\n entries: ReadonlyArray<{ readonly key: string; readonly value: Record<string, unknown> }>\n}\n\nexport interface FailedOutputResult {\n kind: 'failed'\n ok: false\n error: Error\n /** Always empty on failure; present so consumers don't have to narrow. */\n value: Record<string, unknown>\n}\n\n/**\n * Stateless functions that execute a derivation strategy. Persistence\n * (encrypt + store.put) is the caller's job — typically\n * `DerivationRegistry.onSourceWrite` which iterates run() results and\n * writes each output via `Collection.put`.\n */\nexport const DerivationExecutor = {\n /**\n * Run `derive` once, validate output shape against the spec, stamp\n * `_derivedFrom` onto every output. Returns per-output success or\n * failure; throws only for shape mismatches (a contract violation).\n */\n async run<\n TSource extends Record<string, unknown>,\n TOutputs extends Record<string, Record<string, unknown>>,\n >(\n strategy: DerivationStrategy<TSource, TOutputs>,\n source: TSource & { id: string },\n sourceVersion: number,\n strategyHash: string,\n ctx: DerivationContext,\n ): Promise<RunResult> {\n const outputs: Record<string, OutputResult> = {}\n let derived: Partial<TOutputs>\n\n try {\n derived = await Promise.resolve(strategy.derive(source as TSource, ctx))\n } catch (err) {\n for (const key of Object.keys(strategy.outputs)) {\n outputs[key] = {\n kind: 'failed',\n value: {},\n ok: false,\n error: err instanceof Error ? err : new Error(String(err)),\n }\n }\n return { outputs, failed: true }\n }\n\n const meta: DerivedFromMeta = {\n source: strategy.source,\n sourceId: source.id,\n sourceVersion,\n derivedAt: new Date().toISOString(),\n strategyHash,\n }\n\n for (const key of Object.keys(strategy.outputs)) {\n const outSpec = strategy.outputs[key]\n if (!outSpec) continue\n const value = (derived as Record<string, unknown>)[key]\n\n // ── Array-shape branch ─────────────────────────────────────\n if (outSpec.shape === 'array') {\n if (value === undefined || value === null) {\n // Treat null/undefined as \"empty array\" — clears all prior\n // outputs for this (source, output) pair. The caller's\n // diff turns that into deletes.\n outputs[key] = { kind: 'array', ok: true, entries: [] }\n continue\n }\n if (!Array.isArray(value)) {\n throw new DerivationOutputShapeError(\n key,\n `shape 'array' expects an array, got ${typeof value}`,\n )\n }\n const maxFanout = outSpec.maxFanout ?? 64\n if (value.length > maxFanout) {\n throw new DerivationCapExceededError(key, value.length, maxFanout)\n }\n const entries: Array<{ key: string; value: Record<string, unknown> }> = []\n const seenKeys = new Set<string>()\n for (let i = 0; i < value.length; i++) {\n const row = value[i] as unknown\n if (row === null || typeof row !== 'object') {\n throw new DerivationOutputShapeError(\n key,\n `array member at index ${i} must be a non-null object (got ${row === null ? 'null' : typeof row})`,\n )\n }\n let derivedKey: string\n try {\n derivedKey = outSpec.key(row as Record<string, unknown>)\n } catch (err) {\n throw new DerivationOutputShapeError(\n key,\n `key extractor threw on array member at index ${i}: `\n + (err instanceof Error ? err.message : String(err)),\n )\n }\n if (typeof derivedKey !== 'string' || derivedKey.length === 0) {\n throw new DerivationOutputShapeError(\n key,\n `key extractor returned ${typeof derivedKey === 'string' ? 'empty string' : typeof derivedKey} at index ${i}; expected non-empty string`,\n )\n }\n if (seenKeys.has(derivedKey)) {\n throw new DerivationOutputShapeError(\n key,\n `duplicate key \"${derivedKey}\" in array output (index ${i}); each derived row must have a unique key within a single derive() invocation`,\n )\n }\n seenKeys.add(derivedKey)\n entries.push({\n key: derivedKey,\n value: { ...(row as Record<string, unknown>), _derivedFrom: meta },\n })\n }\n outputs[key] = { kind: 'array', ok: true, entries }\n continue\n }\n\n // ── Record-shape branch (existing v1 behavior) ─────────────\n if (value === undefined || value === null) {\n if (outSpec.optional === true) {\n // Optional output explicitly skipped. Mark for caller\n // so any prior-emitted output at this id can be deleted.\n outputs[key] = { kind: 'record', value: {}, ok: true, skipped: true }\n continue\n }\n throw new DerivationOutputShapeError(\n key,\n `expected object, got ${value === undefined ? 'undefined' : 'null'}`,\n )\n }\n if (typeof value !== 'object') {\n throw new DerivationOutputShapeError(\n key,\n `expected object, got ${typeof value}`,\n )\n }\n outputs[key] = {\n kind: 'record',\n value: { ...(value as Record<string, unknown>), _derivedFrom: meta },\n ok: true,\n }\n }\n return { outputs, failed: false }\n },\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ensureCollectionDEK
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-HQSQC2XL.js";
|
|
4
4
|
import {
|
|
5
5
|
NOYDB_FORMAT_VERSION
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-WIRRPTFH.js";
|
|
7
7
|
import {
|
|
8
8
|
decrypt,
|
|
9
9
|
encrypt
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-R233SLY3.js";
|
|
11
11
|
import {
|
|
12
12
|
PermissionDeniedError
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-O6EJ6WTI.js";
|
|
14
14
|
|
|
15
15
|
// src/team/sync-credentials.ts
|
|
16
16
|
var SYNC_CREDENTIALS_COLLECTION = "_sync_credentials";
|
|
@@ -76,4 +76,4 @@ export {
|
|
|
76
76
|
listCredentials,
|
|
77
77
|
credentialStatus
|
|
78
78
|
};
|
|
79
|
-
//# sourceMappingURL=chunk-
|
|
79
|
+
//# sourceMappingURL=chunk-5OX6XVNS.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
NOYDB_FORMAT_VERSION
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-WIRRPTFH.js";
|
|
4
4
|
import {
|
|
5
5
|
base64ToBuffer,
|
|
6
6
|
bufferToBase64,
|
|
@@ -10,11 +10,11 @@ import {
|
|
|
10
10
|
encryptBytesWithAAD,
|
|
11
11
|
hmacSha256Hex,
|
|
12
12
|
sha256Hex
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-R233SLY3.js";
|
|
14
14
|
import {
|
|
15
15
|
ConflictError,
|
|
16
16
|
NotFoundError
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-O6EJ6WTI.js";
|
|
18
18
|
|
|
19
19
|
// src/blobs/mime-magic.ts
|
|
20
20
|
function hex(s) {
|
|
@@ -820,7 +820,7 @@ var BlobSet = class {
|
|
|
820
820
|
return this.buildResponse(slot, result.blob, { inline: true });
|
|
821
821
|
}
|
|
822
822
|
const aad = chunkAAD(slot.eTag, 0, result.blob.chunkCount);
|
|
823
|
-
const { decryptBytesWithAAD: decryptAAD } = await import("./crypto-
|
|
823
|
+
const { decryptBytesWithAAD: decryptAAD } = await import("./crypto-2CRLG4F4.js");
|
|
824
824
|
const decrypted = await decryptAAD(envelope._iv, envelope._data, blobDEK, aad);
|
|
825
825
|
const plaintext = result.blob.compression === "gzip" ? await decompressBytes(decrypted) : decrypted;
|
|
826
826
|
const body = new ReadableStream({
|
|
@@ -871,224 +871,6 @@ async function plainSha256Hex(data) {
|
|
|
871
871
|
return sha256Hex(data);
|
|
872
872
|
}
|
|
873
873
|
|
|
874
|
-
// src/blobs/export-blobs.ts
|
|
875
|
-
var ExportBlobsAbortedError = class extends Error {
|
|
876
|
-
constructor(reason) {
|
|
877
|
-
super(`exportBlobs aborted: ${reason}`);
|
|
878
|
-
this.name = "ExportBlobsAbortedError";
|
|
879
|
-
}
|
|
880
|
-
};
|
|
881
|
-
var EXPORT_AUDIT_COLLECTION = "_export_audit";
|
|
882
|
-
function createExportBlobsHandle(actor, listAccessibleCollections, getCollection, writeAudit, options) {
|
|
883
|
-
let aborted = false;
|
|
884
|
-
const abort = () => {
|
|
885
|
-
aborted = true;
|
|
886
|
-
};
|
|
887
|
-
if (options.signal) {
|
|
888
|
-
if (options.signal.aborted) aborted = true;
|
|
889
|
-
options.signal.addEventListener("abort", () => {
|
|
890
|
-
aborted = true;
|
|
891
|
-
});
|
|
892
|
-
}
|
|
893
|
-
function assertLive() {
|
|
894
|
-
if (aborted) throw new ExportBlobsAbortedError("aborted by caller");
|
|
895
|
-
}
|
|
896
|
-
const allowlist = options.collections ? new Set(options.collections) : null;
|
|
897
|
-
let auditPromise = null;
|
|
898
|
-
function writeAuditOnce() {
|
|
899
|
-
if (!auditPromise) {
|
|
900
|
-
auditPromise = writeAudit({
|
|
901
|
-
id: generateBatchId(),
|
|
902
|
-
mechanism: "exportBlobs",
|
|
903
|
-
actor,
|
|
904
|
-
startedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
905
|
-
collections: options.collections ?? null,
|
|
906
|
-
predicate: Boolean(options.where),
|
|
907
|
-
afterBlobId: options.afterBlobId ?? null
|
|
908
|
-
});
|
|
909
|
-
}
|
|
910
|
-
return auditPromise;
|
|
911
|
-
}
|
|
912
|
-
async function* generate() {
|
|
913
|
-
await writeAuditOnce();
|
|
914
|
-
assertLive();
|
|
915
|
-
const allCollections = await listAccessibleCollections();
|
|
916
|
-
const targets = allCollections.filter((name) => {
|
|
917
|
-
if (name.startsWith("_")) return false;
|
|
918
|
-
if (allowlist && !allowlist.has(name)) return false;
|
|
919
|
-
return true;
|
|
920
|
-
});
|
|
921
|
-
let resumeCursorHit = options.afterBlobId === void 0;
|
|
922
|
-
for (const collectionName of targets) {
|
|
923
|
-
if (aborted) return;
|
|
924
|
-
const coll = getCollection(collectionName);
|
|
925
|
-
const records = await coll.list().catch(() => []);
|
|
926
|
-
for (const record of records) {
|
|
927
|
-
if (aborted) return;
|
|
928
|
-
assertLive();
|
|
929
|
-
const idField = record.id;
|
|
930
|
-
if (typeof idField !== "string") continue;
|
|
931
|
-
if (options.where && !options.where(record, { collection: collectionName, id: idField })) continue;
|
|
932
|
-
const blobSet = coll.blob(idField);
|
|
933
|
-
const slots = await blobSet.list().catch(() => []);
|
|
934
|
-
for (const slot of slots) {
|
|
935
|
-
if (aborted) return;
|
|
936
|
-
if (!resumeCursorHit) {
|
|
937
|
-
if (slot.eTag === options.afterBlobId) {
|
|
938
|
-
resumeCursorHit = true;
|
|
939
|
-
}
|
|
940
|
-
continue;
|
|
941
|
-
}
|
|
942
|
-
const bytes = await blobSet.get(slot.name);
|
|
943
|
-
if (!bytes) continue;
|
|
944
|
-
const item = {
|
|
945
|
-
blobId: slot.eTag,
|
|
946
|
-
recordRef: { collection: collectionName, id: idField, slot: slot.name },
|
|
947
|
-
bytes,
|
|
948
|
-
meta: {
|
|
949
|
-
size: slot.size,
|
|
950
|
-
filename: slot.filename,
|
|
951
|
-
...slot.mimeType !== void 0 && { mimeType: slot.mimeType },
|
|
952
|
-
...slot.uploadedAt !== void 0 && { createdAt: slot.uploadedAt }
|
|
953
|
-
}
|
|
954
|
-
};
|
|
955
|
-
yield item;
|
|
956
|
-
}
|
|
957
|
-
}
|
|
958
|
-
}
|
|
959
|
-
}
|
|
960
|
-
const handle = {
|
|
961
|
-
abort,
|
|
962
|
-
get aborted() {
|
|
963
|
-
return aborted;
|
|
964
|
-
},
|
|
965
|
-
[Symbol.asyncIterator]: () => generate()
|
|
966
|
-
};
|
|
967
|
-
return handle;
|
|
968
|
-
}
|
|
969
|
-
function generateBatchId() {
|
|
970
|
-
const raw = globalThis.crypto.getRandomValues(new Uint8Array(16));
|
|
971
|
-
let s = "";
|
|
972
|
-
for (const b of raw) s += b.toString(16).padStart(2, "0");
|
|
973
|
-
return `batch-${Date.now().toString(36)}-${s.slice(0, 12)}`;
|
|
974
|
-
}
|
|
975
|
-
|
|
976
|
-
// src/blobs/blob-compaction.ts
|
|
977
|
-
var BLOB_EVICTION_AUDIT_COLLECTION = "_blob_eviction_audit";
|
|
978
|
-
async function runCompaction(ctx, options = {}) {
|
|
979
|
-
const now = options.now ?? /* @__PURE__ */ new Date();
|
|
980
|
-
const maxEvictions = options.maxEvictions ?? Infinity;
|
|
981
|
-
const dryRun = options.dryRun === true;
|
|
982
|
-
const allCollections = await ctx.listCollections();
|
|
983
|
-
const byCollection = {};
|
|
984
|
-
let evicted = 0;
|
|
985
|
-
let records = 0;
|
|
986
|
-
let auditEntries = 0;
|
|
987
|
-
let collectionsWithPolicy = 0;
|
|
988
|
-
outer: for (const collectionName of allCollections) {
|
|
989
|
-
if (collectionName.startsWith("_")) continue;
|
|
990
|
-
const config = ctx.getBlobFields(collectionName);
|
|
991
|
-
if (!config) continue;
|
|
992
|
-
const configuredSlots = Object.keys(config);
|
|
993
|
-
if (configuredSlots.length === 0) continue;
|
|
994
|
-
collectionsWithPolicy += 1;
|
|
995
|
-
byCollection[collectionName] = { records: 0, evicted: 0 };
|
|
996
|
-
const ids = await ctx.listRecords(collectionName);
|
|
997
|
-
for (const recordId of ids) {
|
|
998
|
-
if (evicted >= maxEvictions) break outer;
|
|
999
|
-
const record = await ctx.getRecord(collectionName, recordId).catch(() => null);
|
|
1000
|
-
if (record === null) continue;
|
|
1001
|
-
records += 1;
|
|
1002
|
-
byCollection[collectionName].records += 1;
|
|
1003
|
-
const slots = await ctx.listSlots(collectionName, recordId).catch(() => []);
|
|
1004
|
-
for (const slot of slots) {
|
|
1005
|
-
if (evicted >= maxEvictions) break outer;
|
|
1006
|
-
const policy = config[slot.name];
|
|
1007
|
-
if (!policy) continue;
|
|
1008
|
-
const reason = evaluatePolicy(policy, record, slot, now);
|
|
1009
|
-
if (!reason) continue;
|
|
1010
|
-
if (!dryRun) {
|
|
1011
|
-
await ctx.deleteSlot(collectionName, recordId, slot.name);
|
|
1012
|
-
await writeAuditEntry(ctx, {
|
|
1013
|
-
id: generateEvictionId(collectionName, recordId, slot.name),
|
|
1014
|
-
collection: collectionName,
|
|
1015
|
-
recordId,
|
|
1016
|
-
slotName: slot.name,
|
|
1017
|
-
blobHash: slot.eTag,
|
|
1018
|
-
reason,
|
|
1019
|
-
evictedAt: now.toISOString(),
|
|
1020
|
-
actor: ctx.actor
|
|
1021
|
-
});
|
|
1022
|
-
auditEntries += 1;
|
|
1023
|
-
}
|
|
1024
|
-
evicted += 1;
|
|
1025
|
-
byCollection[collectionName].evicted += 1;
|
|
1026
|
-
}
|
|
1027
|
-
}
|
|
1028
|
-
}
|
|
1029
|
-
return {
|
|
1030
|
-
evicted,
|
|
1031
|
-
records,
|
|
1032
|
-
collections: collectionsWithPolicy,
|
|
1033
|
-
auditEntries,
|
|
1034
|
-
byCollection
|
|
1035
|
-
};
|
|
1036
|
-
}
|
|
1037
|
-
function evaluatePolicy(policy, record, slot, now) {
|
|
1038
|
-
let ttlTriggered = false;
|
|
1039
|
-
let predicateTriggered = false;
|
|
1040
|
-
if (policy.retainDays !== void 0 && policy.retainDays > 0) {
|
|
1041
|
-
const uploadedAt = Date.parse(slot.uploadedAt);
|
|
1042
|
-
if (Number.isFinite(uploadedAt)) {
|
|
1043
|
-
const ageMs = now.getTime() - uploadedAt;
|
|
1044
|
-
const limitMs = policy.retainDays * 864e5;
|
|
1045
|
-
if (ageMs > limitMs) ttlTriggered = true;
|
|
1046
|
-
}
|
|
1047
|
-
}
|
|
1048
|
-
if (policy.evictWhen) {
|
|
1049
|
-
try {
|
|
1050
|
-
if (policy.evictWhen(record)) predicateTriggered = true;
|
|
1051
|
-
} catch {
|
|
1052
|
-
}
|
|
1053
|
-
}
|
|
1054
|
-
if (ttlTriggered && predicateTriggered) return "both";
|
|
1055
|
-
if (ttlTriggered) return "ttl";
|
|
1056
|
-
if (predicateTriggered) return "predicate";
|
|
1057
|
-
return null;
|
|
1058
|
-
}
|
|
1059
|
-
function generateEvictionId(collection, recordId, slotName) {
|
|
1060
|
-
const rand = globalThis.crypto.getRandomValues(new Uint8Array(8));
|
|
1061
|
-
let suffix = "";
|
|
1062
|
-
for (const b of rand) suffix += b.toString(16).padStart(2, "0");
|
|
1063
|
-
return `${collection}__${recordId}__${slotName}__${suffix}`;
|
|
1064
|
-
}
|
|
1065
|
-
async function writeAuditEntry(ctx, entry) {
|
|
1066
|
-
const json = JSON.stringify(entry);
|
|
1067
|
-
let envelope;
|
|
1068
|
-
if (ctx.encrypted) {
|
|
1069
|
-
const dek = await ctx.getDEK(BLOB_EVICTION_AUDIT_COLLECTION);
|
|
1070
|
-
const { iv, data } = await encrypt(json, dek);
|
|
1071
|
-
envelope = {
|
|
1072
|
-
_noydb: NOYDB_FORMAT_VERSION,
|
|
1073
|
-
_v: 1,
|
|
1074
|
-
_ts: entry.evictedAt,
|
|
1075
|
-
_iv: iv,
|
|
1076
|
-
_data: data,
|
|
1077
|
-
_by: entry.actor
|
|
1078
|
-
};
|
|
1079
|
-
} else {
|
|
1080
|
-
envelope = {
|
|
1081
|
-
_noydb: NOYDB_FORMAT_VERSION,
|
|
1082
|
-
_v: 1,
|
|
1083
|
-
_ts: entry.evictedAt,
|
|
1084
|
-
_iv: "",
|
|
1085
|
-
_data: json,
|
|
1086
|
-
_by: entry.actor
|
|
1087
|
-
};
|
|
1088
|
-
}
|
|
1089
|
-
await ctx.adapter.put(ctx.vault, BLOB_EVICTION_AUDIT_COLLECTION, entry.id, envelope);
|
|
1090
|
-
}
|
|
1091
|
-
|
|
1092
874
|
export {
|
|
1093
875
|
detectMimeType,
|
|
1094
876
|
detectMagic,
|
|
@@ -1099,11 +881,6 @@ export {
|
|
|
1099
881
|
BLOB_SLOTS_PREFIX,
|
|
1100
882
|
BLOB_VERSIONS_PREFIX,
|
|
1101
883
|
DEFAULT_CHUNK_SIZE,
|
|
1102
|
-
BlobSet
|
|
1103
|
-
ExportBlobsAbortedError,
|
|
1104
|
-
EXPORT_AUDIT_COLLECTION,
|
|
1105
|
-
createExportBlobsHandle,
|
|
1106
|
-
BLOB_EVICTION_AUDIT_COLLECTION,
|
|
1107
|
-
runCompaction
|
|
884
|
+
BlobSet
|
|
1108
885
|
};
|
|
1109
|
-
//# sourceMappingURL=chunk-
|
|
886
|
+
//# sourceMappingURL=chunk-6EOXTJS2.js.map
|