@noy-db/hub 0.2.0-pre.30 → 0.2.0-pre.31

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (143) hide show
  1. package/dist/adapter/index.d.ts +9 -0
  2. package/dist/adapter/index.js +14 -0
  3. package/dist/attestation/index.d.ts +1 -1
  4. package/dist/attestation/index.js +3 -3
  5. package/dist/blobs/index.d.ts +3 -3
  6. package/dist/bundle/index.d.ts +3 -3
  7. package/dist/bundle/index.js +1 -1
  8. package/dist/{chunk-Y6YUWZTS.js → chunk-L5HHBOMS.js} +2 -2
  9. package/dist/{chunk-BVKLJBJJ.js → chunk-W5NVNJDX.js} +2 -1
  10. package/dist/{chunk-BVKLJBJJ.js.map → chunk-W5NVNJDX.js.map} +1 -1
  11. package/dist/consent/index.d.ts +2 -2
  12. package/dist/{decrypt-partition-Mhjh6nnG.d.ts → decrypt-partition-CXS5KopB.d.ts} +1 -1
  13. package/dist/derivations/index.d.ts +3 -3
  14. package/dist/{dev-unlock-DJ3IhgY9.d.ts → dev-unlock-CnHTTVea.d.ts} +1 -1
  15. package/dist/guards/index.d.ts +3 -3
  16. package/dist/{hash-DLwkYf1d.d.ts → hash-oc5paYl0.d.ts} +1 -1
  17. package/dist/history/index.d.ts +3 -3
  18. package/dist/i18n/index.d.ts +2 -2
  19. package/dist/{index-CMRIx_zx.d.ts → index-BmhGztUi.d.ts} +1 -1
  20. package/dist/index.d.ts +11 -11
  21. package/dist/index.js +2 -2
  22. package/dist/kernel/index.d.ts +2 -2
  23. package/dist/materialized-views/index.d.ts +3 -3
  24. package/dist/{mime-magic-CacDBwYp.d.ts → mime-magic-JeLKHRng.d.ts} +1 -1
  25. package/dist/{noydb-5MIBD77B.js → noydb-NAU2DTFP.js} +2 -2
  26. package/dist/noydb-NAU2DTFP.js.map +1 -0
  27. package/dist/overlay-views/index.d.ts +3 -3
  28. package/dist/periods/index.d.ts +2 -2
  29. package/dist/session/index.d.ts +3 -3
  30. package/dist/shadow/index.d.ts +2 -2
  31. package/dist/snapshots/index.d.ts +2 -2
  32. package/dist/store/index.d.ts +2 -2
  33. package/dist/sync/index.d.ts +1 -1
  34. package/dist/team/index.d.ts +2 -2
  35. package/dist/{transition-guard-J04-jime.d.ts → transition-guard-Dy3NioQr.d.ts} +1 -1
  36. package/dist/tx/index.d.ts +2 -2
  37. package/dist/{with-materialized-view-DNfzC5lH.d.ts → with-materialized-view-DIVeez0W.d.ts} +1 -1
  38. package/dist/{with-overlayed-view-qk3lbhOd.d.ts → with-overlayed-view-DVZrc5Hb.d.ts} +1 -1
  39. package/dist/{with-rollup-Dd3_ZG4b.d.ts → with-rollup-CbU-O4wP.d.ts} +1 -1
  40. package/package.json +62 -221
  41. package/dist/aggregate/index.cjs +0 -1144
  42. package/dist/aggregate/index.cjs.map +0 -1
  43. package/dist/aggregate/index.d.cts +0 -39
  44. package/dist/attestation/index.cjs +0 -305
  45. package/dist/attestation/index.cjs.map +0 -1
  46. package/dist/attestation/index.d.cts +0 -54
  47. package/dist/blobs/index.cjs +0 -1967
  48. package/dist/blobs/index.cjs.map +0 -1
  49. package/dist/blobs/index.d.cts +0 -48
  50. package/dist/bundle/index.cjs +0 -41045
  51. package/dist/bundle/index.cjs.map +0 -1
  52. package/dist/bundle/index.d.cts +0 -187
  53. package/dist/consent/index.cjs +0 -204
  54. package/dist/consent/index.cjs.map +0 -1
  55. package/dist/consent/index.d.cts +0 -27
  56. package/dist/crdt/index.cjs +0 -152
  57. package/dist/crdt/index.cjs.map +0 -1
  58. package/dist/crdt/index.d.cts +0 -30
  59. package/dist/decrypt-partition-C0iDpbSd.d.cts +0 -558
  60. package/dist/derivations/index.cjs +0 -469
  61. package/dist/derivations/index.cjs.map +0 -1
  62. package/dist/derivations/index.d.cts +0 -74
  63. package/dist/dev-unlock-0Z6yxfS7.d.cts +0 -263
  64. package/dist/discriminant-BN9REW3o.d.cts +0 -60
  65. package/dist/errors-BAWO5Z5a.d.cts +0 -1500
  66. package/dist/forget/index.cjs +0 -43
  67. package/dist/forget/index.cjs.map +0 -1
  68. package/dist/forget/index.d.cts +0 -1
  69. package/dist/guards/index.cjs +0 -455
  70. package/dist/guards/index.cjs.map +0 -1
  71. package/dist/guards/index.d.cts +0 -39
  72. package/dist/hash-Db8ncXGr.d.cts +0 -63
  73. package/dist/history/index.cjs +0 -1245
  74. package/dist/history/index.cjs.map +0 -1
  75. package/dist/history/index.d.cts +0 -65
  76. package/dist/i18n/index.cjs +0 -1280
  77. package/dist/i18n/index.cjs.map +0 -1
  78. package/dist/i18n/index.d.cts +0 -41
  79. package/dist/index-BMmajblo.d.cts +0 -362
  80. package/dist/index-C1SC1EPe.d.cts +0 -1325
  81. package/dist/index-xJEPkvMb.d.cts +0 -93
  82. package/dist/index.cjs +0 -48100
  83. package/dist/index.cjs.map +0 -1
  84. package/dist/index.d.cts +0 -1050
  85. package/dist/indexing/index.cjs +0 -803
  86. package/dist/indexing/index.cjs.map +0 -1
  87. package/dist/indexing/index.d.cts +0 -36
  88. package/dist/kernel/index.cjs +0 -751
  89. package/dist/kernel/index.cjs.map +0 -1
  90. package/dist/kernel/index.d.cts +0 -11
  91. package/dist/lazy-builder-eYZzLEL1.d.cts +0 -304
  92. package/dist/materialized-views/index.cjs +0 -1518
  93. package/dist/materialized-views/index.cjs.map +0 -1
  94. package/dist/materialized-views/index.d.cts +0 -187
  95. package/dist/mime-magic-sdMzsfVK.d.cts +0 -103
  96. package/dist/overlay-views/index.cjs +0 -399
  97. package/dist/overlay-views/index.cjs.map +0 -1
  98. package/dist/overlay-views/index.d.cts +0 -102
  99. package/dist/periods/index.cjs +0 -1041
  100. package/dist/periods/index.cjs.map +0 -1
  101. package/dist/periods/index.d.cts +0 -24
  102. package/dist/predicate-BmhBSPCH.d.cts +0 -267
  103. package/dist/query/index.cjs +0 -3480
  104. package/dist/query/index.cjs.map +0 -1
  105. package/dist/query/index.d.cts +0 -4
  106. package/dist/sealed-record/index.cjs +0 -139
  107. package/dist/sealed-record/index.cjs.map +0 -1
  108. package/dist/sealed-record/index.d.cts +0 -123
  109. package/dist/session/index.cjs +0 -495
  110. package/dist/session/index.cjs.map +0 -1
  111. package/dist/session/index.d.cts +0 -48
  112. package/dist/shadow/index.cjs +0 -133
  113. package/dist/shadow/index.cjs.map +0 -1
  114. package/dist/shadow/index.d.cts +0 -19
  115. package/dist/snapshots/index.cjs +0 -937
  116. package/dist/snapshots/index.cjs.map +0 -1
  117. package/dist/snapshots/index.d.cts +0 -30
  118. package/dist/store/index.cjs +0 -1091
  119. package/dist/store/index.cjs.map +0 -1
  120. package/dist/store/index.d.cts +0 -501
  121. package/dist/strategy-BSxFXGzb.d.cts +0 -110
  122. package/dist/strategy-mJExw4LQ.d.cts +0 -1069
  123. package/dist/sync/index.cjs +0 -1062
  124. package/dist/sync/index.cjs.map +0 -1
  125. package/dist/sync/index.d.cts +0 -45
  126. package/dist/team/index.cjs +0 -2805
  127. package/dist/team/index.cjs.map +0 -1
  128. package/dist/team/index.d.cts +0 -120
  129. package/dist/transition-guard-tWZIsaXe.d.cts +0 -165
  130. package/dist/tx/index.cjs +0 -614
  131. package/dist/tx/index.cjs.map +0 -1
  132. package/dist/tx/index.d.cts +0 -39
  133. package/dist/types-CdVfiQgt.d.cts +0 -15275
  134. package/dist/ulid-DRH25k3y.d.cts +0 -66
  135. package/dist/util/index.cjs +0 -237
  136. package/dist/util/index.cjs.map +0 -1
  137. package/dist/util/index.d.cts +0 -79
  138. package/dist/with-materialized-view-DfgPcvi9.d.cts +0 -27
  139. package/dist/with-overlayed-view-Cvfkx1lg.d.cts +0 -13
  140. package/dist/with-rollup-nIxo7h9z.d.cts +0 -47
  141. /package/dist/{noydb-5MIBD77B.js.map → adapter/index.js.map} +0 -0
  142. /package/dist/{chunk-Y6YUWZTS.js.map → chunk-L5HHBOMS.js.map} +0 -0
  143. /package/dist/{types-DHn9lEP0.d.ts → index-DHn9lEP0.d.ts} +0 -0
@@ -1,495 +0,0 @@
1
- "use strict";
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __export = (target, all) => {
7
- for (var name in all)
8
- __defProp(target, name, { get: all[name], enumerable: true });
9
- };
10
- var __copyProps = (to, from, except, desc) => {
11
- if (from && typeof from === "object" || typeof from === "function") {
12
- for (let key of __getOwnPropNames(from))
13
- if (!__hasOwnProp.call(to, key) && key !== except)
14
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
- }
16
- return to;
17
- };
18
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
-
20
- // src/session/index.ts
21
- var session_exports = {};
22
- __export(session_exports, {
23
- PolicyEnforcer: () => PolicyEnforcer,
24
- SessionExpiredError: () => SessionExpiredError,
25
- SessionNotFoundError: () => SessionNotFoundError,
26
- SessionPolicyError: () => SessionPolicyError,
27
- activeSessionCount: () => activeSessionCount,
28
- clearDevUnlock: () => clearDevUnlock,
29
- createEnforcer: () => createEnforcer,
30
- createSession: () => createSession,
31
- enableDevUnlock: () => enableDevUnlock,
32
- isDevUnlockActive: () => isDevUnlockActive,
33
- isSessionAlive: () => isSessionAlive,
34
- loadDevUnlock: () => loadDevUnlock,
35
- resolveSession: () => resolveSession,
36
- revokeAllSessions: () => revokeAllSessions,
37
- revokeSession: () => revokeSession,
38
- validateSessionPolicy: () => validateSessionPolicy,
39
- withSession: () => withSession
40
- });
41
- module.exports = __toCommonJS(session_exports);
42
-
43
- // src/errors.ts
44
- var NoydbError = class extends Error {
45
- /** Machine-readable error code. Stable across library versions. */
46
- code;
47
- constructor(code, message) {
48
- super(message);
49
- this.name = "NoydbError";
50
- this.code = code;
51
- }
52
- };
53
- var ValidationError = class extends NoydbError {
54
- constructor(message = "Validation error") {
55
- super("VALIDATION_ERROR", message);
56
- this.name = "ValidationError";
57
- }
58
- };
59
- var SessionExpiredError = class extends NoydbError {
60
- sessionId;
61
- constructor(sessionId) {
62
- super("SESSION_EXPIRED", `Session "${sessionId}" has expired. Re-unlock to continue.`);
63
- this.name = "SessionExpiredError";
64
- this.sessionId = sessionId;
65
- }
66
- };
67
- var SessionNotFoundError = class extends NoydbError {
68
- sessionId;
69
- constructor(sessionId) {
70
- super("SESSION_NOT_FOUND", `Session key for "${sessionId}" not found. The session may have been revoked or the page reloaded.`);
71
- this.name = "SessionNotFoundError";
72
- this.sessionId = sessionId;
73
- }
74
- };
75
- var SessionPolicyError = class extends NoydbError {
76
- operation;
77
- constructor(operation, message) {
78
- super(
79
- "SESSION_POLICY",
80
- message ?? `Operation "${operation}" requires re-authentication per the active session policy.`
81
- );
82
- this.name = "SessionPolicyError";
83
- this.operation = operation;
84
- }
85
- };
86
-
87
- // src/crypto.ts
88
- var subtle = globalThis.crypto.subtle;
89
- function bufferToBase64(buffer) {
90
- const bytes = buffer instanceof Uint8Array ? buffer : new Uint8Array(buffer);
91
- let binary = "";
92
- for (let i = 0; i < bytes.length; i++) {
93
- binary += String.fromCharCode(bytes[i]);
94
- }
95
- return btoa(binary);
96
- }
97
- function base64ToBuffer(base64) {
98
- const binary = atob(base64);
99
- const bytes = new Uint8Array(binary.length);
100
- for (let i = 0; i < binary.length; i++) {
101
- bytes[i] = binary.charCodeAt(i);
102
- }
103
- return bytes;
104
- }
105
-
106
- // src/bundle/ulid.ts
107
- var CROCKFORD_ALPHABET = "0123456789ABCDEFGHJKMNPQRSTVWXYZ";
108
- function encodeBase32(value, length) {
109
- let out = "";
110
- let v = value;
111
- for (let i = 0; i < length; i++) {
112
- out = CROCKFORD_ALPHABET[v % 32] + out;
113
- v = Math.floor(v / 32);
114
- }
115
- return out;
116
- }
117
- function generateULID() {
118
- const now = Date.now();
119
- const timestampHigh = Math.floor(now / 16777216);
120
- const timestampLow = now & 16777215;
121
- const tsPart = encodeBase32(timestampHigh, 5) + encodeBase32(timestampLow, 5);
122
- const randBytes = new Uint8Array(10);
123
- crypto.getRandomValues(randBytes);
124
- const rand1 = randBytes[0] * 2 ** 32 + (randBytes[1] << 24 >>> 0) + (randBytes[2] << 16) + (randBytes[3] << 8) + randBytes[4];
125
- const rand2 = randBytes[5] * 2 ** 32 + (randBytes[6] << 24 >>> 0) + (randBytes[7] << 16) + (randBytes[8] << 8) + randBytes[9];
126
- const randPart = encodeBase32(rand1, 8) + encodeBase32(rand2, 8);
127
- return tsPart + randPart;
128
- }
129
-
130
- // src/session/session.ts
131
- var subtle2 = globalThis.crypto.subtle;
132
- var DEFAULT_TTL_MS = 60 * 60 * 1e3;
133
- var sessionKeyStore = /* @__PURE__ */ new Map();
134
- async function createSession(keyring, vault, options = {}) {
135
- const ttlMs = options.ttlMs ?? DEFAULT_TTL_MS;
136
- const sessionId = generateULID();
137
- const expiresAt = new Date(Date.now() + ttlMs).toISOString();
138
- const sessionKey = await subtle2.generateKey(
139
- { name: "AES-GCM", length: 256 },
140
- false,
141
- // non-extractable — this is the tab-scope security invariant
142
- ["encrypt", "decrypt"]
143
- );
144
- const dekMap = {};
145
- for (const [collName, dek] of keyring.deks) {
146
- const raw = await subtle2.exportKey("raw", dek);
147
- dekMap[collName] = bufferToBase64(raw);
148
- }
149
- const payload = JSON.stringify({
150
- userId: keyring.userId,
151
- displayName: keyring.displayName,
152
- role: keyring.role,
153
- permissions: keyring.permissions,
154
- deks: dekMap,
155
- salt: bufferToBase64(keyring.salt)
156
- });
157
- const iv = globalThis.crypto.getRandomValues(new Uint8Array(12));
158
- const encrypted = await subtle2.encrypt(
159
- { name: "AES-GCM", iv },
160
- sessionKey,
161
- new TextEncoder().encode(payload)
162
- );
163
- const token = {
164
- _noydb_session: 1,
165
- sessionId,
166
- userId: keyring.userId,
167
- vault,
168
- role: keyring.role,
169
- expiresAt,
170
- wrappedKek: bufferToBase64(encrypted),
171
- kekIv: bufferToBase64(iv)
172
- };
173
- sessionKeyStore.set(sessionId, sessionKey);
174
- return { token, sessionId };
175
- }
176
- async function resolveSession(token) {
177
- if (Date.now() > new Date(token.expiresAt).getTime()) {
178
- sessionKeyStore.delete(token.sessionId);
179
- throw new SessionExpiredError(token.sessionId);
180
- }
181
- const sessionKey = sessionKeyStore.get(token.sessionId);
182
- if (!sessionKey) {
183
- throw new SessionNotFoundError(token.sessionId);
184
- }
185
- const iv = base64ToBuffer(token.kekIv);
186
- const ciphertext = base64ToBuffer(token.wrappedKek);
187
- let plaintext;
188
- try {
189
- plaintext = await subtle2.decrypt(
190
- { name: "AES-GCM", iv },
191
- sessionKey,
192
- ciphertext
193
- );
194
- } catch {
195
- throw new SessionNotFoundError(token.sessionId);
196
- }
197
- const payload = JSON.parse(new TextDecoder().decode(plaintext));
198
- const deks = /* @__PURE__ */ new Map();
199
- for (const [collName, rawBase64] of Object.entries(payload.deks)) {
200
- const dek = await subtle2.importKey(
201
- "raw",
202
- base64ToBuffer(rawBase64),
203
- { name: "AES-GCM", length: 256 },
204
- true,
205
- ["encrypt", "decrypt"]
206
- );
207
- deks.set(collName, dek);
208
- }
209
- return {
210
- userId: payload.userId,
211
- displayName: payload.displayName,
212
- role: payload.role,
213
- permissions: payload.permissions,
214
- deks,
215
- kek: null,
216
- // KEK not available in session context
217
- salt: base64ToBuffer(payload.salt),
218
- authenticators: []
219
- };
220
- }
221
- function revokeSession(sessionId) {
222
- sessionKeyStore.delete(sessionId);
223
- }
224
- function isSessionAlive(token) {
225
- if (Date.now() > new Date(token.expiresAt).getTime()) return false;
226
- return sessionKeyStore.has(token.sessionId);
227
- }
228
- function revokeAllSessions() {
229
- sessionKeyStore.clear();
230
- }
231
- function activeSessionCount() {
232
- return sessionKeyStore.size;
233
- }
234
-
235
- // src/session/session-policy.ts
236
- var PolicyEnforcer = class {
237
- policy;
238
- sessionId;
239
- onRevoke;
240
- createdAt;
241
- lastActivityAt;
242
- idleTimer = null;
243
- absoluteTimer = null;
244
- visibilityHandler = null;
245
- constructor(opts) {
246
- this.policy = opts.policy;
247
- this.sessionId = opts.sessionId;
248
- this.onRevoke = opts.onRevoke;
249
- this.createdAt = Date.now();
250
- this.lastActivityAt = Date.now();
251
- this.scheduleIdleTimer();
252
- this.scheduleAbsoluteTimer();
253
- this.registerBackgroundLock();
254
- }
255
- /**
256
- * Record an activity timestamp and reset the idle timer.
257
- * Call this at the top of every Noydb public method.
258
- */
259
- touch() {
260
- this.lastActivityAt = Date.now();
261
- this.scheduleIdleTimer();
262
- }
263
- /**
264
- * Check whether the given operation is allowed under the active policy.
265
- * Throws `SessionPolicyError` if the operation requires re-authentication.
266
- * Throws `SessionExpiredError` if the absolute timeout has been exceeded
267
- * (defensive check in case the timer fired before the call arrived).
268
- *
269
- * This is a synchronous check — callers don't await it.
270
- */
271
- checkOperation(op) {
272
- const { absoluteTimeoutMs } = this.policy;
273
- if (absoluteTimeoutMs !== void 0 && Date.now() - this.createdAt >= absoluteTimeoutMs) {
274
- this.expire("absolute");
275
- throw new SessionExpiredError(this.sessionId);
276
- }
277
- const required = this.policy.requireReAuthFor ?? [];
278
- if (required.includes(op)) {
279
- throw new SessionPolicyError(op);
280
- }
281
- }
282
- /**
283
- * Tear down timers and background-lock listener. Call from `Noydb.close()`
284
- * and whenever the session is revoked externally.
285
- */
286
- destroy() {
287
- if (this.idleTimer) {
288
- clearTimeout(this.idleTimer);
289
- this.idleTimer = null;
290
- }
291
- if (this.absoluteTimer) {
292
- clearTimeout(this.absoluteTimer);
293
- this.absoluteTimer = null;
294
- }
295
- if (this.visibilityHandler && typeof document !== "undefined") {
296
- document.removeEventListener("visibilitychange", this.visibilityHandler);
297
- this.visibilityHandler = null;
298
- }
299
- }
300
- /** How long since the last activity, in ms. */
301
- get idleMs() {
302
- return Date.now() - this.lastActivityAt;
303
- }
304
- /** How long since session creation, in ms. */
305
- get ageMs() {
306
- return Date.now() - this.createdAt;
307
- }
308
- // ── Private ──────────────────────────────────────────────────────────
309
- scheduleIdleTimer() {
310
- const { idleTimeoutMs } = this.policy;
311
- if (!idleTimeoutMs) return;
312
- if (this.idleTimer) clearTimeout(this.idleTimer);
313
- this.idleTimer = setTimeout(() => {
314
- this.expire("idle");
315
- }, idleTimeoutMs);
316
- }
317
- scheduleAbsoluteTimer() {
318
- const { absoluteTimeoutMs } = this.policy;
319
- if (!absoluteTimeoutMs) return;
320
- if (this.absoluteTimer) clearTimeout(this.absoluteTimer);
321
- this.absoluteTimer = setTimeout(() => {
322
- this.expire("absolute");
323
- }, absoluteTimeoutMs);
324
- }
325
- registerBackgroundLock() {
326
- if (!this.policy.lockOnBackground) return;
327
- if (typeof document === "undefined") return;
328
- this.visibilityHandler = () => {
329
- if (document.hidden) {
330
- this.expire("background");
331
- }
332
- };
333
- document.addEventListener("visibilitychange", this.visibilityHandler);
334
- }
335
- expire(reason) {
336
- this.destroy();
337
- revokeSession(this.sessionId);
338
- this.onRevoke(reason);
339
- }
340
- };
341
- function createEnforcer(opts) {
342
- return new PolicyEnforcer(opts);
343
- }
344
- function validateSessionPolicy(policy) {
345
- const { idleTimeoutMs, absoluteTimeoutMs } = policy;
346
- if (idleTimeoutMs !== void 0 && (typeof idleTimeoutMs !== "number" || idleTimeoutMs <= 0)) {
347
- throw new Error(`SessionPolicy.idleTimeoutMs must be a positive number, got ${idleTimeoutMs}`);
348
- }
349
- if (absoluteTimeoutMs !== void 0 && (typeof absoluteTimeoutMs !== "number" || absoluteTimeoutMs <= 0)) {
350
- throw new Error(`SessionPolicy.absoluteTimeoutMs must be a positive number, got ${absoluteTimeoutMs}`);
351
- }
352
- if (idleTimeoutMs !== void 0 && absoluteTimeoutMs !== void 0 && idleTimeoutMs >= absoluteTimeoutMs) {
353
- throw new Error(
354
- `SessionPolicy.idleTimeoutMs (${idleTimeoutMs}ms) must be less than absoluteTimeoutMs (${absoluteTimeoutMs}ms)`
355
- );
356
- }
357
- }
358
-
359
- // src/session/dev-unlock.ts
360
- var REQUIRED_ACKNOWLEDGE = "I-UNDERSTAND-THIS-DISABLES-UNLOCK-SECURITY";
361
- var STORAGE_PREFIX = "noydb:dev-unlock:";
362
- function assertDevEnvironment() {
363
- if (typeof process !== "undefined" && process.env.NODE_ENV === "production") {
364
- throw new ValidationError(
365
- 'devUnlock is not available in production builds. process.env.NODE_ENV is "production".'
366
- );
367
- }
368
- if (typeof globalThis !== "undefined" && globalThis.__vite_is_production__ === true) {
369
- throw new ValidationError("devUnlock is not available in production builds.");
370
- }
371
- if (typeof window !== "undefined" && typeof window.location !== "undefined") {
372
- const host = window.location.hostname;
373
- if (host !== "localhost" && host !== "127.0.0.1" && host !== "::1" && !host.endsWith(".local")) {
374
- throw new ValidationError(
375
- `devUnlock is only available on localhost. Current hostname: "${host}". Set NODE_ENV=development and run on localhost to use dev unlock.`
376
- );
377
- }
378
- }
379
- }
380
- function storageKey(vault, userId) {
381
- return `${STORAGE_PREFIX}${vault}:${userId}`;
382
- }
383
- function resolveStorage(persistAcrossTabs) {
384
- if (typeof window === "undefined") {
385
- throw new ValidationError("devUnlock requires a browser environment (window.sessionStorage / window.localStorage).");
386
- }
387
- return persistAcrossTabs ? window.localStorage : window.sessionStorage;
388
- }
389
- async function enableDevUnlock(vault, userId, keyring, options) {
390
- if (options.acknowledge !== REQUIRED_ACKNOWLEDGE) {
391
- throw new ValidationError(
392
- `devUnlock requires acknowledge: '${REQUIRED_ACKNOWLEDGE}'. Got: '${options.acknowledge}'. This is intentional \u2014 the full string must appear in your source.`
393
- );
394
- }
395
- assertDevEnvironment();
396
- const storage = resolveStorage(options.persistAcrossTabs);
397
- const dekMap = {};
398
- for (const [collName, dek] of keyring.deks) {
399
- const raw = await globalThis.crypto.subtle.exportKey("raw", dek);
400
- dekMap[collName] = bufferToBase64(raw);
401
- }
402
- const payload = JSON.stringify({
403
- _noydb_dev_unlock: 1,
404
- userId: keyring.userId,
405
- displayName: keyring.displayName,
406
- role: keyring.role,
407
- permissions: keyring.permissions,
408
- deks: dekMap,
409
- salt: bufferToBase64(keyring.salt)
410
- });
411
- storage.setItem(storageKey(vault, userId), payload);
412
- console.warn(
413
- "%c\u26A0\uFE0F NOYDB DEV UNLOCK ACTIVE \u26A0\uFE0F",
414
- "color: red; font-size: 16px; font-weight: bold",
415
- `
416
-
417
- Vault "${vault}" user "${userId}" is stored in ${options.persistAcrossTabs ? "localStorage" : "sessionStorage"} in PLAINTEXT DEKs.
418
- This is ONLY safe for local development. Never use in production.
419
- Call clearDevUnlock() to remove.`
420
- );
421
- }
422
- async function loadDevUnlock(vault, userId, options = {}) {
423
- if (typeof window === "undefined") return null;
424
- const storage = resolveStorage(options.persistAcrossTabs);
425
- const raw = storage.getItem(storageKey(vault, userId));
426
- if (!raw) return null;
427
- let parsed;
428
- try {
429
- parsed = JSON.parse(raw);
430
- } catch {
431
- return null;
432
- }
433
- if (parsed._noydb_dev_unlock !== 1) return null;
434
- const deks = /* @__PURE__ */ new Map();
435
- for (const [collName, rawBase64] of Object.entries(parsed.deks)) {
436
- const dek = await globalThis.crypto.subtle.importKey(
437
- "raw",
438
- base64ToBuffer(rawBase64),
439
- { name: "AES-GCM", length: 256 },
440
- true,
441
- ["encrypt", "decrypt"]
442
- );
443
- deks.set(collName, dek);
444
- }
445
- return {
446
- userId: parsed.userId,
447
- displayName: parsed.displayName,
448
- role: parsed.role,
449
- permissions: parsed.permissions,
450
- deks,
451
- kek: null,
452
- salt: base64ToBuffer(parsed.salt),
453
- authenticators: []
454
- };
455
- }
456
- function clearDevUnlock(vault, userId, options = {}) {
457
- if (typeof window === "undefined") return;
458
- const storage = resolveStorage(options.persistAcrossTabs);
459
- storage.removeItem(storageKey(vault, userId));
460
- }
461
- function isDevUnlockActive(vault, userId, options = {}) {
462
- if (typeof window === "undefined") return false;
463
- const storage = resolveStorage(options.persistAcrossTabs);
464
- return storage.getItem(storageKey(vault, userId)) !== null;
465
- }
466
-
467
- // src/session/active.ts
468
- function withSession() {
469
- return {
470
- validateSessionPolicy,
471
- createEnforcer,
472
- revokeAllSessions
473
- };
474
- }
475
- // Annotate the CommonJS export names for ESM import in node:
476
- 0 && (module.exports = {
477
- PolicyEnforcer,
478
- SessionExpiredError,
479
- SessionNotFoundError,
480
- SessionPolicyError,
481
- activeSessionCount,
482
- clearDevUnlock,
483
- createEnforcer,
484
- createSession,
485
- enableDevUnlock,
486
- isDevUnlockActive,
487
- isSessionAlive,
488
- loadDevUnlock,
489
- resolveSession,
490
- revokeAllSessions,
491
- revokeSession,
492
- validateSessionPolicy,
493
- withSession
494
- });
495
- //# sourceMappingURL=index.cjs.map