@smonn/ids 0.4.0 → 0.6.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.
Files changed (51) hide show
  1. package/README.md +416 -14
  2. package/dist/bytes-lhzKVaBV.mjs +53 -0
  3. package/dist/bytes-lhzKVaBV.mjs.map +1 -0
  4. package/dist/cli.mjs +196 -17
  5. package/dist/cli.mjs.map +1 -1
  6. package/dist/{codec-shell-C0arqqX3.mjs → codec-shell-dWpxoFmy.mjs} +2 -23
  7. package/dist/codec-shell-dWpxoFmy.mjs.map +1 -0
  8. package/dist/drizzle-CeSni5PB.d.mts +44 -0
  9. package/dist/drizzle-CeSni5PB.d.mts.map +1 -0
  10. package/dist/drizzle.d.mts +2 -0
  11. package/dist/drizzle.mjs +42 -0
  12. package/dist/drizzle.mjs.map +1 -0
  13. package/dist/express.d.mts +92 -0
  14. package/dist/express.d.mts.map +1 -0
  15. package/dist/express.mjs +90 -0
  16. package/dist/express.mjs.map +1 -0
  17. package/dist/hono.d.mts +75 -0
  18. package/dist/hono.d.mts.map +1 -0
  19. package/dist/hono.mjs +63 -0
  20. package/dist/hono.mjs.map +1 -0
  21. package/dist/index.mjs +1 -1
  22. package/dist/kysely.d.mts +55 -0
  23. package/dist/kysely.d.mts.map +1 -0
  24. package/dist/kysely.mjs +42 -0
  25. package/dist/kysely.mjs.map +1 -0
  26. package/dist/{opaque-CX-Lc5B9.mjs → opaque-goLnFoo7.mjs} +32 -64
  27. package/dist/opaque-goLnFoo7.mjs.map +1 -0
  28. package/dist/opaque.d.mts +33 -9
  29. package/dist/opaque.d.mts.map +1 -1
  30. package/dist/opaque.mjs +1 -1
  31. package/dist/prisma.d.mts +84 -0
  32. package/dist/prisma.d.mts.map +1 -0
  33. package/dist/prisma.mjs +53 -0
  34. package/dist/prisma.mjs.map +1 -0
  35. package/dist/reverse--n4D2yxu.mjs +87 -0
  36. package/dist/reverse--n4D2yxu.mjs.map +1 -0
  37. package/dist/reverse.d.mts +76 -0
  38. package/dist/reverse.d.mts.map +1 -0
  39. package/dist/reverse.mjs +2 -0
  40. package/dist/{timestamp-BjdAetut.mjs → timestamp-Bgzxx8bE.mjs} +3 -2
  41. package/dist/{timestamp-BjdAetut.mjs.map → timestamp-Bgzxx8bE.mjs.map} +1 -1
  42. package/dist/timestamp-bytes-B57RM7Ho.mjs +26 -0
  43. package/dist/timestamp-bytes-B57RM7Ho.mjs.map +1 -0
  44. package/dist/wrapped-Dw5mHQhn.mjs +363 -0
  45. package/dist/wrapped-Dw5mHQhn.mjs.map +1 -0
  46. package/dist/wrapped.d.mts +133 -0
  47. package/dist/wrapped.d.mts.map +1 -0
  48. package/dist/wrapped.mjs +2 -0
  49. package/package.json +43 -7
  50. package/dist/codec-shell-C0arqqX3.mjs.map +0 -1
  51. package/dist/opaque-CX-Lc5B9.mjs.map +0 -1
@@ -0,0 +1,363 @@
1
+ import { a as toWireId, i as payloadBytesFromId, n as registerBrand, r as payloadBase32Length, s as validateBrand, t as wireMethods } from "./codec-shell-dWpxoFmy.mjs";
2
+ import { i as encodeHex, n as decodeHex, r as encodeBase64Url, t as decodeBase64Url } from "./bytes-lhzKVaBV.mjs";
3
+ //#region src/layouts/wrapped.ts
4
+ const zeroIv = new Uint8Array(16);
5
+ const pkcsPad = 16;
6
+ const laneByteLength = 8;
7
+ const tagByteLength = 8;
8
+ function writeU32Lane(value, lane) {
9
+ lane[0] = 0;
10
+ lane[1] = 0;
11
+ lane[2] = 0;
12
+ lane[3] = 0;
13
+ lane[4] = value >>> 24 & 255;
14
+ lane[5] = value >>> 16 & 255;
15
+ lane[6] = value >>> 8 & 255;
16
+ lane[7] = value & 255;
17
+ }
18
+ function readU32Lane(lane) {
19
+ for (let i = 0; i < 4; i++) if (lane[i] !== 0) return null;
20
+ return (lane[4] << 24 | lane[5] << 16 | lane[6] << 8 | lane[7]) >>> 0;
21
+ }
22
+ function writeI32Lane(value, lane) {
23
+ lane.fill(value < 0 ? 255 : 0, 0, 4);
24
+ new DataView(lane.buffer, lane.byteOffset, lane.byteLength).setInt32(4, value, false);
25
+ }
26
+ function readI32Lane(lane) {
27
+ const signExtension = (lane[4] & 128) === 0 ? 0 : 255;
28
+ for (let i = 0; i < 4; i++) if (lane[i] !== signExtension) return null;
29
+ return new DataView(lane.buffer, lane.byteOffset, lane.byteLength).getInt32(4, false);
30
+ }
31
+ function writeU64Lane(value, lane) {
32
+ new DataView(lane.buffer, lane.byteOffset, lane.byteLength).setBigUint64(0, value, false);
33
+ }
34
+ function readU64Lane(lane) {
35
+ return new DataView(lane.buffer, lane.byteOffset, lane.byteLength).getBigUint64(0, false);
36
+ }
37
+ function writeI64Lane(value, lane) {
38
+ new DataView(lane.buffer, lane.byteOffset, lane.byteLength).setBigInt64(0, value, false);
39
+ }
40
+ function readI64Lane(lane) {
41
+ return new DataView(lane.buffer, lane.byteOffset, lane.byteLength).getBigInt64(0, false);
42
+ }
43
+ function writeLane(kind, value, lane) {
44
+ if (kind === "i32") {
45
+ writeI32Lane(value, lane);
46
+ return;
47
+ }
48
+ if (kind === "u64") {
49
+ writeU64Lane(value, lane);
50
+ return;
51
+ }
52
+ if (kind === "i64") {
53
+ writeI64Lane(value, lane);
54
+ return;
55
+ }
56
+ writeU32Lane(value, lane);
57
+ }
58
+ function readLane(kind, lane) {
59
+ if (kind === "u64") return readU64Lane(lane);
60
+ if (kind === "i64") return readI64Lane(lane);
61
+ return kind === "i32" ? readI32Lane(lane) : readU32Lane(lane);
62
+ }
63
+ function hmacMessage(brand, kind, lane) {
64
+ const prefix = new TextEncoder().encode(`${brand}:${kind}:`);
65
+ const message = new Uint8Array(prefix.length + lane.length);
66
+ message.set(prefix, 0);
67
+ message.set(lane, prefix.length);
68
+ return message;
69
+ }
70
+ async function computeTag(key, brand, kind, lane) {
71
+ return new Uint8Array(await crypto.subtle.sign("HMAC", key.hmacKey, hmacMessage(brand, kind, lane))).subarray(0, tagByteLength);
72
+ }
73
+ function tagsEqual(a, b) {
74
+ let diff = 0;
75
+ for (let i = 0; i < a.length; i++) diff |= a[i] ^ b[i];
76
+ return diff === 0;
77
+ }
78
+ async function encryptPayload(key, plaintext) {
79
+ return new Uint8Array(await crypto.subtle.encrypt({
80
+ name: "AES-CBC",
81
+ iv: zeroIv
82
+ }, key.aesKey, plaintext)).subarray(0, 16);
83
+ }
84
+ async function decryptPayload(key, c1) {
85
+ const c2Input = new Uint8Array(16);
86
+ for (let i = 0; i < 16; i++) c2Input[i] = pkcsPad ^ c1[i];
87
+ const c2Encrypted = new Uint8Array(await crypto.subtle.encrypt({
88
+ name: "AES-CBC",
89
+ iv: zeroIv
90
+ }, key.aesKey, c2Input));
91
+ const ciphertext = new Uint8Array(32);
92
+ ciphertext.set(c1, 0);
93
+ ciphertext.set(c2Encrypted.subarray(0, 16), 16);
94
+ return new Uint8Array(await crypto.subtle.decrypt({
95
+ name: "AES-CBC",
96
+ iv: zeroIv
97
+ }, key.aesKey, ciphertext));
98
+ }
99
+ function buildPlaintext(lane, tag) {
100
+ const plaintext = new Uint8Array(16);
101
+ plaintext.set(lane, 0);
102
+ plaintext.set(tag, laneByteLength);
103
+ return plaintext;
104
+ }
105
+ async function wrapLookupKey(prefix, brand, key, kind, lookupKey) {
106
+ const lane = new Uint8Array(laneByteLength);
107
+ writeLane(kind, lookupKey, lane);
108
+ return toWireId(prefix, await encryptPayload(key, buildPlaintext(lane, await computeTag(key, brand, kind, lane))));
109
+ }
110
+ async function tryUnwrapLookupKey(prefix, brand, key, kind, id) {
111
+ const plaintext = await decryptPayload(key, payloadBytesFromId(prefix, id));
112
+ const lane = plaintext.subarray(0, laneByteLength);
113
+ if (!tagsEqual(plaintext.subarray(laneByteLength, 16), await computeTag(key, brand, kind, lane))) return null;
114
+ return readLane(kind, lane);
115
+ }
116
+ function schemaExample(prefix) {
117
+ return prefix + "0".repeat(payloadBase32Length);
118
+ }
119
+ function createWrappedLayoutOps(prefix, brand, kind, keys) {
120
+ const wrapKey = keys[0];
121
+ return {
122
+ wrap: (lookupKey) => wrapLookupKey(prefix, brand, wrapKey, kind, lookupKey),
123
+ unwrap: async (id) => {
124
+ for (const key of keys) {
125
+ const lookupKey = await tryUnwrapLookupKey(prefix, brand, key, kind, id);
126
+ if (lookupKey !== null) return lookupKey;
127
+ }
128
+ throw new Error("verification failed");
129
+ },
130
+ tryUnwrap: async (id) => {
131
+ for (const key of keys) {
132
+ const lookupKey = await tryUnwrapLookupKey(prefix, brand, key, kind, id);
133
+ if (lookupKey !== null) return lookupKey;
134
+ }
135
+ return null;
136
+ },
137
+ exampleWireId: () => schemaExample(prefix)
138
+ };
139
+ }
140
+ //#endregion
141
+ //#region src/wrapping-key.ts
142
+ const validKeyByteLengths = new Set([
143
+ 16,
144
+ 24,
145
+ 32
146
+ ]);
147
+ const aesInfo = new TextEncoder().encode("@smonn/ids/wrapped/aes/v1");
148
+ const hmacInfo = new TextEncoder().encode("@smonn/ids/wrapped/hmac/v1");
149
+ const internals = /* @__PURE__ */ new WeakMap();
150
+ /**
151
+ * Import raw operator secret bytes into a {@link WrappingKey} handle.
152
+ *
153
+ * One raw secret derives into AES and HMAC subkeys held inside the returned
154
+ * handle. Accepts 16, 24, or 32 bytes (AES-128 / AES-192 / AES-256 strength).
155
+ * To store or transport key material, use {@link encodeWrappingKey} /
156
+ * {@link decodeWrappingKey} (`"hex"` or `"base64url"` — not Crockford base32).
157
+ *
158
+ * @param bytes - 16, 24, or 32 raw key bytes.
159
+ */
160
+ async function importWrappingKey(bytes) {
161
+ assertValidKeyByteLength(bytes.length);
162
+ const aesKey = await deriveAesKey(bytes);
163
+ const hmacKey = await deriveHmacKey(bytes);
164
+ const key = Object.freeze({});
165
+ internals.set(key, {
166
+ rawBytes: bytes.slice(),
167
+ aesKey,
168
+ hmacKey
169
+ });
170
+ return key;
171
+ }
172
+ /**
173
+ * Encode raw wrapping operator secret bytes for storage in env vars or secret managers.
174
+ *
175
+ * Supports `"hex"` (lowercase) and `"base64url"`. Output round-trips through
176
+ * {@link decodeWrappingKey} back to the original bytes.
177
+ */
178
+ function encodeWrappingKey(bytes, format) {
179
+ assertWrappingKeyFormat(format);
180
+ assertValidKeyByteLength(bytes.length);
181
+ if (format === "hex") return encodeHex(bytes);
182
+ return encodeBase64Url(bytes);
183
+ }
184
+ /**
185
+ * Decode key material emitted by {@link encodeWrappingKey} back to raw bytes.
186
+ *
187
+ * The result can be passed directly to {@link importWrappingKey}.
188
+ */
189
+ function decodeWrappingKey(encoded, format) {
190
+ assertWrappingKeyFormat(format);
191
+ let bytes;
192
+ if (format === "hex") {
193
+ if (encoded.length === 0 || encoded.length % 2 !== 0) throw new Error("invalid hex key: length must be a positive even number of characters");
194
+ if (!/^[0-9a-fA-F]+$/.test(encoded)) throw new Error("invalid hex key: expected [0-9a-fA-F] only");
195
+ bytes = decodeHex(encoded);
196
+ } else try {
197
+ bytes = decodeBase64Url(encoded);
198
+ } catch {
199
+ throw new Error("invalid base64url key");
200
+ }
201
+ assertValidKeyByteLength(bytes.length);
202
+ return bytes;
203
+ }
204
+ /** Returns true when two handles were imported from the same raw operator secret. */
205
+ function wrappingKeysEqual(a, b) {
206
+ const aInternals = getWrappingKeyInternals(a);
207
+ const bInternals = getWrappingKeyInternals(b);
208
+ if (aInternals.rawBytes.length !== bInternals.rawBytes.length) return false;
209
+ for (let i = 0; i < aInternals.rawBytes.length; i++) if (aInternals.rawBytes[i] !== bInternals.rawBytes[i]) return false;
210
+ return true;
211
+ }
212
+ function getWrappingKeyMaterial(key) {
213
+ const keyInternals = getWrappingKeyInternals(key);
214
+ return {
215
+ aesKey: keyInternals.aesKey,
216
+ hmacKey: keyInternals.hmacKey
217
+ };
218
+ }
219
+ function getWrappingKeyInternals(key) {
220
+ const keyInternals = internals.get(key);
221
+ if (keyInternals === void 0) throw new Error("invalid wrapping key");
222
+ return keyInternals;
223
+ }
224
+ async function deriveAesKey(bytes) {
225
+ const base = await crypto.subtle.importKey("raw", bytes, "HKDF", false, ["deriveKey"]);
226
+ return crypto.subtle.deriveKey({
227
+ name: "HKDF",
228
+ hash: "SHA-256",
229
+ salt: new Uint8Array(),
230
+ info: aesInfo
231
+ }, base, {
232
+ name: "AES-CBC",
233
+ length: 256
234
+ }, false, ["encrypt", "decrypt"]);
235
+ }
236
+ async function deriveHmacKey(bytes) {
237
+ const base = await crypto.subtle.importKey("raw", bytes, "HKDF", false, ["deriveKey"]);
238
+ return crypto.subtle.deriveKey({
239
+ name: "HKDF",
240
+ hash: "SHA-256",
241
+ salt: new Uint8Array(),
242
+ info: hmacInfo
243
+ }, base, {
244
+ name: "HMAC",
245
+ hash: "SHA-256",
246
+ length: 256
247
+ }, false, ["sign", "verify"]);
248
+ }
249
+ function assertValidKeyByteLength(byteLength) {
250
+ if (!validKeyByteLengths.has(byteLength)) throw new Error(`invalid wrapping key length: expected 16, 24, or 32 bytes, got ${byteLength}`);
251
+ }
252
+ function assertWrappingKeyFormat(format) {
253
+ if (format !== "hex" && format !== "base64url") throw new Error(`invalid wrapping key format: expected hex or base64url, got '${formatForError(format)}'`);
254
+ }
255
+ function formatForError(value) {
256
+ try {
257
+ return String(value);
258
+ } catch {
259
+ return "[unprintable]";
260
+ }
261
+ }
262
+ //#endregion
263
+ //#region src/wrapped.ts
264
+ const u32Max = 4294967295;
265
+ const i32Min = -2147483648;
266
+ const i32Max = 2147483647;
267
+ const u64Max = 18446744073709551615n;
268
+ const i64Min = -(1n << 63n);
269
+ const i64Max = (1n << 63n) - 1n;
270
+ function assertSupportedKind(kind) {
271
+ if (kind !== "u32" && kind !== "i32" && kind !== "u64" && kind !== "i64") throw new Error("invalid wrapped key kind: expected u32, i32, u64, or i64");
272
+ }
273
+ function assertNonEmptyKeyring(keys) {
274
+ if (keys.length === 0) throw new Error("wrapped keyring must contain at least one key");
275
+ }
276
+ function assertNonDuplicateKeys(keys) {
277
+ for (let i = 0; i < keys.length; i++) for (let j = i + 1; j < keys.length; j++) if (wrappingKeysEqual(keys[i], keys[j])) throw new Error("duplicate wrapping key in keyring");
278
+ }
279
+ function assertU32LookupKey(lookupKey) {
280
+ if (typeof lookupKey !== "number" || !Number.isInteger(lookupKey) || Object.is(lookupKey, -0) || lookupKey < 0 || lookupKey > u32Max) throw new Error(`invalid u32 lookup key: expected integer in [0, ${u32Max}], got ${lookupKey}`);
281
+ }
282
+ function assertI32LookupKey(lookupKey) {
283
+ if (typeof lookupKey !== "number" || !Number.isInteger(lookupKey) || Object.is(lookupKey, -0) || lookupKey < i32Min || lookupKey > i32Max) throw new Error(`invalid i32 lookup key: expected integer in [${i32Min}, ${i32Max}], got ${lookupKey}`);
284
+ }
285
+ function assertU64LookupKey(lookupKey) {
286
+ if (typeof lookupKey !== "bigint" || lookupKey < 0n || lookupKey > u64Max) throw new Error(`invalid u64 lookup key: expected bigint in [0, ${u64Max}], got ${lookupKey}`);
287
+ }
288
+ function assertI64LookupKey(lookupKey) {
289
+ if (typeof lookupKey !== "bigint" || lookupKey < i64Min || lookupKey > i64Max) throw new Error(`invalid i64 lookup key: expected bigint in [${i64Min}, ${i64Max}], got ${lookupKey}`);
290
+ }
291
+ function assertLookupKey(kind, lookupKey) {
292
+ if (kind === "i32") {
293
+ assertI32LookupKey(lookupKey);
294
+ return;
295
+ }
296
+ if (kind === "u64") {
297
+ assertU64LookupKey(lookupKey);
298
+ return;
299
+ }
300
+ if (kind === "i64") {
301
+ assertI64LookupKey(lookupKey);
302
+ return;
303
+ }
304
+ assertU32LookupKey(lookupKey);
305
+ }
306
+ /**
307
+ * Construct a {@link WrappedKeyCodec} for `brand` and the given `kind`.
308
+ *
309
+ * `opts.kind` fixes the integer type at construction time — one brand, one
310
+ * kind. `opts.keys` is a non-empty ordered wrapping keyring: the first entry
311
+ * is current (used by `wrap`); all entries are tried on `unwrap`; duplicate
312
+ * operator secrets are rejected at construction.
313
+ *
314
+ * @example
315
+ * ```ts
316
+ * const key = await importWrappingKey(new Uint8Array(32));
317
+ * const invoices = createWrappedKeyId("inv", { kind: "u32", keys: [key] });
318
+ *
319
+ * const id = await invoices.wrap(42); // Id<"inv">
320
+ * await invoices.unwrap(id); // 42
321
+ * ```
322
+ */
323
+ function createWrappedKeyId(brand, opts) {
324
+ validateBrand(brand);
325
+ registerBrand(brand, opts.allowDuplicateBrand);
326
+ assertSupportedKind(opts.kind);
327
+ assertNonEmptyKeyring(opts.keys);
328
+ const layoutKeys = opts.keys.map(getWrappingKeyMaterial);
329
+ assertNonDuplicateKeys(opts.keys);
330
+ const prefix = `${brand}_`;
331
+ const wire = wireMethods(prefix);
332
+ const layout = createWrappedLayoutOps(prefix, brand, opts.kind, layoutKeys);
333
+ return {
334
+ wrap: async (lookupKey) => {
335
+ assertLookupKey(opts.kind, lookupKey);
336
+ return layout.wrap(lookupKey);
337
+ },
338
+ unwrap: (id) => layout.unwrap(id),
339
+ safeUnwrap: async (input) => {
340
+ const parsed = wire.safeParse(input);
341
+ if (!parsed.ok) return parsed;
342
+ const lookupKey = await layout.tryUnwrap(parsed.id);
343
+ if (lookupKey === null) return {
344
+ ok: false,
345
+ error: "verification_failed"
346
+ };
347
+ return {
348
+ ok: true,
349
+ id: parsed.id,
350
+ lookupKey
351
+ };
352
+ },
353
+ is: wire.is,
354
+ parse: wire.parse,
355
+ safeParse: wire.safeParse,
356
+ toJsonSchema: () => wire.toJsonSchema(brand, layout.exampleWireId()),
357
+ "~standard": wire["~standard"]
358
+ };
359
+ }
360
+ //#endregion
361
+ export { importWrappingKey as i, decodeWrappingKey as n, encodeWrappingKey as r, createWrappedKeyId as t };
362
+
363
+ //# sourceMappingURL=wrapped-Dw5mHQhn.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wrapped-Dw5mHQhn.mjs","names":[],"sources":["../src/layouts/wrapped.ts","../src/wrapping-key.ts","../src/wrapped.ts"],"sourcesContent":["import type { Id, Prefix } from \"../types.js\";\nimport { payloadBytesFromId, toWireId } from \"../wire/envelope.js\";\nimport { payloadBase32Length, payloadByteLength } from \"../wire/invariants.js\";\n\nconst zeroIv = new Uint8Array(payloadByteLength);\nconst pkcsPad = 0x10;\nconst laneByteLength = 8;\nconst tagByteLength = 8;\n\ntype LayoutWrappingKey = {\n aesKey: CryptoKey;\n hmacKey: CryptoKey;\n};\n\ntype LayoutWrappedKind = \"u32\" | \"i32\" | \"u64\" | \"i64\";\ntype LayoutLookupKey<K extends LayoutWrappedKind> = K extends \"u32\" | \"i32\" ? number : bigint;\n\nfunction writeU32Lane(value: number, lane: Uint8Array): void {\n lane[0] = 0;\n lane[1] = 0;\n lane[2] = 0;\n lane[3] = 0;\n lane[4] = (value >>> 24) & 0xff;\n lane[5] = (value >>> 16) & 0xff;\n lane[6] = (value >>> 8) & 0xff;\n lane[7] = value & 0xff;\n}\n\nfunction readU32Lane(lane: Uint8Array): number | null {\n for (let i = 0; i < 4; i++) {\n if (lane[i] !== 0) return null;\n }\n return ((lane[4]! << 24) | (lane[5]! << 16) | (lane[6]! << 8) | lane[7]!) >>> 0;\n}\n\nfunction writeI32Lane(value: number, lane: Uint8Array): void {\n lane.fill(value < 0 ? 0xff : 0x00, 0, 4);\n new DataView(lane.buffer, lane.byteOffset, lane.byteLength).setInt32(4, value, false);\n}\n\nfunction readI32Lane(lane: Uint8Array): number | null {\n const signExtension = (lane[4]! & 0x80) === 0 ? 0x00 : 0xff;\n for (let i = 0; i < 4; i++) {\n if (lane[i] !== signExtension) return null;\n }\n return new DataView(lane.buffer, lane.byteOffset, lane.byteLength).getInt32(4, false);\n}\n\nfunction writeU64Lane(value: bigint, lane: Uint8Array): void {\n new DataView(lane.buffer, lane.byteOffset, lane.byteLength).setBigUint64(0, value, false);\n}\n\nfunction readU64Lane(lane: Uint8Array): bigint {\n return new DataView(lane.buffer, lane.byteOffset, lane.byteLength).getBigUint64(0, false);\n}\n\nfunction writeI64Lane(value: bigint, lane: Uint8Array): void {\n new DataView(lane.buffer, lane.byteOffset, lane.byteLength).setBigInt64(0, value, false);\n}\n\nfunction readI64Lane(lane: Uint8Array): bigint {\n return new DataView(lane.buffer, lane.byteOffset, lane.byteLength).getBigInt64(0, false);\n}\n\nfunction writeLane<K extends LayoutWrappedKind>(\n kind: K,\n value: LayoutLookupKey<K>,\n lane: Uint8Array,\n): void {\n if (kind === \"i32\") {\n writeI32Lane(value as number, lane);\n return;\n }\n if (kind === \"u64\") {\n writeU64Lane(value as bigint, lane);\n return;\n }\n if (kind === \"i64\") {\n writeI64Lane(value as bigint, lane);\n return;\n }\n writeU32Lane(value as number, lane);\n}\n\nfunction readLane<K extends LayoutWrappedKind>(\n kind: K,\n lane: Uint8Array,\n): LayoutLookupKey<K> | null {\n if (kind === \"u64\") return readU64Lane(lane) as LayoutLookupKey<K>;\n if (kind === \"i64\") return readI64Lane(lane) as LayoutLookupKey<K>;\n const value = kind === \"i32\" ? readI32Lane(lane) : readU32Lane(lane);\n return value as LayoutLookupKey<K> | null;\n}\n\nfunction hmacMessage(brand: string, kind: LayoutWrappedKind, lane: Uint8Array): Uint8Array {\n const prefix = new TextEncoder().encode(`${brand}:${kind}:`);\n const message = new Uint8Array(prefix.length + lane.length);\n message.set(prefix, 0);\n message.set(lane, prefix.length);\n return message;\n}\n\nasync function computeTag(\n key: LayoutWrappingKey,\n brand: string,\n kind: LayoutWrappedKind,\n lane: Uint8Array,\n): Promise<Uint8Array> {\n const signature = new Uint8Array(\n await crypto.subtle.sign(\n \"HMAC\",\n key.hmacKey,\n hmacMessage(brand, kind, lane) as Uint8Array<ArrayBuffer>,\n ),\n );\n return signature.subarray(0, tagByteLength);\n}\n\nfunction tagsEqual(a: Uint8Array, b: Uint8Array): boolean {\n let diff = 0;\n for (let i = 0; i < a.length; i++) diff |= a[i]! ^ b[i]!;\n return diff === 0;\n}\n\nasync function encryptPayload(key: LayoutWrappingKey, plaintext: Uint8Array): Promise<Uint8Array> {\n const encrypted = new Uint8Array(\n await crypto.subtle.encrypt(\n { name: \"AES-CBC\", iv: zeroIv },\n key.aesKey,\n plaintext as Uint8Array<ArrayBuffer>,\n ),\n );\n return encrypted.subarray(0, payloadByteLength);\n}\n\nasync function decryptPayload(key: LayoutWrappingKey, c1: Uint8Array): Promise<Uint8Array> {\n const c2Input = new Uint8Array(payloadByteLength);\n for (let i = 0; i < payloadByteLength; i++) c2Input[i] = pkcsPad ^ c1[i]!;\n const c2Encrypted = new Uint8Array(\n await crypto.subtle.encrypt(\n { name: \"AES-CBC\", iv: zeroIv },\n key.aesKey,\n c2Input as Uint8Array<ArrayBuffer>,\n ),\n );\n const ciphertext = new Uint8Array(payloadByteLength * 2);\n ciphertext.set(c1, 0);\n ciphertext.set(c2Encrypted.subarray(0, payloadByteLength), payloadByteLength);\n return new Uint8Array(\n await crypto.subtle.decrypt(\n { name: \"AES-CBC\", iv: zeroIv },\n key.aesKey,\n ciphertext as Uint8Array<ArrayBuffer>,\n ),\n );\n}\n\nfunction buildPlaintext(lane: Uint8Array, tag: Uint8Array): Uint8Array {\n const plaintext = new Uint8Array(payloadByteLength);\n plaintext.set(lane, 0);\n plaintext.set(tag, laneByteLength);\n return plaintext;\n}\n\nasync function wrapLookupKey<Brand extends string, Kind extends LayoutWrappedKind>(\n prefix: Prefix<Brand>,\n brand: string,\n key: LayoutWrappingKey,\n kind: Kind,\n lookupKey: LayoutLookupKey<Kind>,\n): Promise<Id<Brand>> {\n const lane = new Uint8Array(laneByteLength);\n writeLane(kind, lookupKey, lane);\n const tag = await computeTag(key, brand, kind, lane);\n const encrypted = await encryptPayload(key, buildPlaintext(lane, tag));\n return toWireId(prefix, encrypted);\n}\n\nasync function tryUnwrapLookupKey<Brand extends string, Kind extends LayoutWrappedKind>(\n prefix: Prefix<Brand>,\n brand: string,\n key: LayoutWrappingKey,\n kind: Kind,\n id: Id<Brand>,\n): Promise<LayoutLookupKey<Kind> | null> {\n const plaintext = await decryptPayload(key, payloadBytesFromId(prefix, id));\n const lane = plaintext.subarray(0, laneByteLength);\n const tag = plaintext.subarray(laneByteLength, payloadByteLength);\n const expected = await computeTag(key, brand, kind, lane);\n if (!tagsEqual(tag, expected)) return null;\n return readLane(kind, lane);\n}\n\nfunction schemaExample<Brand extends string>(prefix: Prefix<Brand>): string {\n return prefix + \"0\".repeat(payloadBase32Length);\n}\n\nexport function createWrappedLayoutOps<Brand extends string, Kind extends LayoutWrappedKind>(\n prefix: Prefix<Brand>,\n brand: Brand,\n kind: Kind,\n keys: readonly LayoutWrappingKey[],\n) {\n const wrapKey = keys[0]!;\n return {\n wrap: (lookupKey: LayoutLookupKey<Kind>): Promise<Id<Brand>> =>\n wrapLookupKey(prefix, brand, wrapKey, kind, lookupKey),\n unwrap: async (id: Id<Brand>): Promise<LayoutLookupKey<Kind>> => {\n for (const key of keys) {\n const lookupKey = await tryUnwrapLookupKey(prefix, brand, key, kind, id);\n if (lookupKey !== null) return lookupKey;\n }\n throw new Error(\"verification failed\");\n },\n tryUnwrap: async (id: Id<Brand>): Promise<LayoutLookupKey<Kind> | null> => {\n for (const key of keys) {\n const lookupKey = await tryUnwrapLookupKey(prefix, brand, key, kind, id);\n if (lookupKey !== null) return lookupKey;\n }\n return null;\n },\n exampleWireId: (): Id<Brand> => schemaExample(prefix) as Id<Brand>,\n };\n}\n","import { decodeBase64Url, decodeHex, encodeBase64Url, encodeHex } from \"./bytes.js\";\n\n/** Wire encoding for wrapping operator secret bytes (not Crockford base32). */\nexport type WrappingKeyFormat = \"hex\" | \"base64url\";\n\nconst validKeyByteLengths = new Set([16, 24, 32]);\n\nconst aesInfo = new TextEncoder().encode(\"@smonn/ids/wrapped/aes/v1\");\nconst hmacInfo = new TextEncoder().encode(\"@smonn/ids/wrapped/hmac/v1\");\n\ndeclare const wrappingKeyBrand: unique symbol;\n\n/**\n * Opaque imported handle for one operator wrapping secret.\n *\n * Holds derived AES and HMAC subkeys internally; callers never access subkeys\n * or raw `CryptoKey` values directly. Obtain handles via {@link importWrappingKey}\n * and pass them to `createWrappedKeyId` as the `keys` wrapping keyring.\n *\n * Distinct from the **Opaque key** used by `@smonn/ids/opaque` — one raw\n * secret must not silently serve both codecs without an explicit import.\n */\nexport type WrappingKey = {\n readonly [wrappingKeyBrand]: \"WrappingKey\";\n};\n\ntype WrappingKeyInternals = {\n rawBytes: Uint8Array;\n aesKey: CryptoKey;\n hmacKey: CryptoKey;\n};\n\nexport type WrappingKeyMaterial = {\n aesKey: CryptoKey;\n hmacKey: CryptoKey;\n};\n\nconst internals = new WeakMap<WrappingKey, WrappingKeyInternals>();\n\n/**\n * Import raw operator secret bytes into a {@link WrappingKey} handle.\n *\n * One raw secret derives into AES and HMAC subkeys held inside the returned\n * handle. Accepts 16, 24, or 32 bytes (AES-128 / AES-192 / AES-256 strength).\n * To store or transport key material, use {@link encodeWrappingKey} /\n * {@link decodeWrappingKey} (`\"hex\"` or `\"base64url\"` — not Crockford base32).\n *\n * @param bytes - 16, 24, or 32 raw key bytes.\n */\nexport async function importWrappingKey(bytes: Uint8Array): Promise<WrappingKey> {\n assertValidKeyByteLength(bytes.length);\n const aesKey = await deriveAesKey(bytes);\n const hmacKey = await deriveHmacKey(bytes);\n const key = Object.freeze({}) as WrappingKey;\n internals.set(key, {\n rawBytes: bytes.slice(),\n aesKey,\n hmacKey,\n });\n return key;\n}\n\n/**\n * Encode raw wrapping operator secret bytes for storage in env vars or secret managers.\n *\n * Supports `\"hex\"` (lowercase) and `\"base64url\"`. Output round-trips through\n * {@link decodeWrappingKey} back to the original bytes.\n */\nexport function encodeWrappingKey(bytes: Uint8Array, format: WrappingKeyFormat): string {\n assertWrappingKeyFormat(format);\n assertValidKeyByteLength(bytes.length);\n if (format === \"hex\") return encodeHex(bytes);\n return encodeBase64Url(bytes);\n}\n\n/**\n * Decode key material emitted by {@link encodeWrappingKey} back to raw bytes.\n *\n * The result can be passed directly to {@link importWrappingKey}.\n */\nexport function decodeWrappingKey(encoded: string, format: WrappingKeyFormat): Uint8Array {\n assertWrappingKeyFormat(format);\n let bytes: Uint8Array;\n if (format === \"hex\") {\n if (encoded.length === 0 || encoded.length % 2 !== 0) {\n throw new Error(\"invalid hex key: length must be a positive even number of characters\");\n }\n if (!/^[0-9a-fA-F]+$/.test(encoded)) {\n throw new Error(\"invalid hex key: expected [0-9a-fA-F] only\");\n }\n bytes = decodeHex(encoded);\n } else {\n try {\n bytes = decodeBase64Url(encoded);\n } catch {\n throw new Error(\"invalid base64url key\");\n }\n }\n assertValidKeyByteLength(bytes.length);\n return bytes;\n}\n\n/** Returns true when two handles were imported from the same raw operator secret. */\nexport function wrappingKeysEqual(a: WrappingKey, b: WrappingKey): boolean {\n const aInternals = getWrappingKeyInternals(a);\n const bInternals = getWrappingKeyInternals(b);\n if (aInternals.rawBytes.length !== bInternals.rawBytes.length) return false;\n for (let i = 0; i < aInternals.rawBytes.length; i++) {\n if (aInternals.rawBytes[i] !== bInternals.rawBytes[i]) return false;\n }\n return true;\n}\n\nexport function getWrappingKeyMaterial(key: WrappingKey): WrappingKeyMaterial {\n const keyInternals = getWrappingKeyInternals(key);\n return {\n aesKey: keyInternals.aesKey,\n hmacKey: keyInternals.hmacKey,\n };\n}\n\nfunction getWrappingKeyInternals(key: WrappingKey): WrappingKeyInternals {\n const keyInternals = internals.get(key);\n if (keyInternals === undefined) {\n throw new Error(\"invalid wrapping key\");\n }\n return keyInternals;\n}\n\nasync function deriveAesKey(bytes: Uint8Array): Promise<CryptoKey> {\n const base = await crypto.subtle.importKey(\n \"raw\",\n bytes as Uint8Array<ArrayBuffer>,\n \"HKDF\",\n false,\n [\"deriveKey\"],\n );\n return crypto.subtle.deriveKey(\n { name: \"HKDF\", hash: \"SHA-256\", salt: new Uint8Array(), info: aesInfo },\n base,\n { name: \"AES-CBC\", length: 256 },\n false,\n [\"encrypt\", \"decrypt\"],\n );\n}\n\nasync function deriveHmacKey(bytes: Uint8Array): Promise<CryptoKey> {\n const base = await crypto.subtle.importKey(\n \"raw\",\n bytes as Uint8Array<ArrayBuffer>,\n \"HKDF\",\n false,\n [\"deriveKey\"],\n );\n return crypto.subtle.deriveKey(\n { name: \"HKDF\", hash: \"SHA-256\", salt: new Uint8Array(), info: hmacInfo },\n base,\n { name: \"HMAC\", hash: \"SHA-256\", length: 256 },\n false,\n [\"sign\", \"verify\"],\n );\n}\n\nfunction assertValidKeyByteLength(byteLength: number): void {\n if (!validKeyByteLengths.has(byteLength)) {\n throw new Error(`invalid wrapping key length: expected 16, 24, or 32 bytes, got ${byteLength}`);\n }\n}\n\nfunction assertWrappingKeyFormat(format: unknown): asserts format is WrappingKeyFormat {\n if (format !== \"hex\" && format !== \"base64url\") {\n throw new Error(\n `invalid wrapping key format: expected hex or base64url, got '${formatForError(format)}'`,\n );\n }\n}\n\nfunction formatForError(value: unknown): string {\n try {\n return String(value);\n } catch {\n return \"[unprintable]\";\n }\n}\n","import { validateBrand } from \"./brand.js\";\nimport { createWrappedLayoutOps } from \"./layouts/wrapped.js\";\nimport { registerBrand } from \"./registry.js\";\nimport type {\n Id,\n JsonSchema,\n ParseError,\n ParseResult,\n Prefix,\n StandardSchemaProps,\n} from \"./types.js\";\nimport { wireMethods } from \"./wire/codec-shell.js\";\nimport {\n decodeWrappingKey,\n encodeWrappingKey,\n getWrappingKeyMaterial,\n importWrappingKey,\n type WrappingKey,\n type WrappingKeyFormat,\n wrappingKeysEqual,\n} from \"./wrapping-key.js\";\n\nexport {\n decodeWrappingKey,\n encodeWrappingKey,\n importWrappingKey,\n type WrappingKey,\n type WrappingKeyFormat,\n};\n\nexport type WrappedKind = \"u32\" | \"i32\" | \"u64\" | \"i64\";\n\ntype LookupKeyForKind<K extends WrappedKind> = K extends \"u32\" | \"i32\" ? number : bigint;\n\n/**\n * Result returned by {@link WrappedKeyCodec.safeUnwrap}.\n *\n * On success, `id` is the canonical {@link Id} and `lookupKey` is the recovered\n * integer (`number` for 32-bit kinds, `bigint` for 64-bit kinds).\n * On failure, `error` is a {@link ParseError} for structural problems or\n * `\"verification_failed\"` when the payload is structurally valid but the\n * verification tag does not match any entry in the wrapping keyring.\n */\nexport type UnwrapResult<Brand extends string, Kind extends WrappedKind> =\n | { ok: true; id: Id<Brand>; lookupKey: LookupKeyForKind<Kind> }\n | { ok: false; error: ParseError | \"verification_failed\" };\n\n/**\n * Codec returned by {@link createWrappedKeyId}.\n *\n * Wraps a caller-owned integer **lookup key** into a public {@link Id} and\n * recovers it on unwrap. The codec is deterministic under fixed key material:\n * the same lookup key always yields the same public ID (**equality leakage**).\n *\n * - `wrap` / `unwrap` / `safeUnwrap` are async (WebCrypto).\n * - `is`, `parse`, `safeParse`, and `toJsonSchema` are synchronous and require\n * no key material — they validate prefix and base32 shape only.\n * - The `Kind` type parameter drives value types at the TypeScript boundary:\n * `u32` / `i32` → `number`; `u64` / `i64` → `bigint`.\n */\nexport type WrappedKeyCodec<Brand extends string, Kind extends WrappedKind> = {\n /**\n * Wrap `lookupKey` into a public ID using the current (first) wrapping key.\n *\n * Throws if `lookupKey` is out of range or the wrong JS type for `Kind`.\n */\n wrap(lookupKey: LookupKeyForKind<Kind>): Promise<Id<Brand>>;\n /**\n * Verify the payload of a trusted `Id<Brand>` and return the lookup key.\n *\n * Throws `\"verification failed\"` if no entry in the wrapping keyring matches\n * the payload tag. Use {@link safeUnwrap} for untrusted input.\n */\n unwrap(id: Id<Brand>): Promise<LookupKeyForKind<Kind>>;\n /**\n * Non-throwing path for untrusted input.\n *\n * Structurally parses `input` first (same rules as {@link safeParse}), then\n * verifies the payload. Returns `{ ok: false, error }` on any failure —\n * `ParseError` for structural problems or `\"verification_failed\"` for tag\n * mismatch — without throwing. Tamper, wrong keyring, and revoked-key cases\n * all surface as `\"verification_failed\"`.\n */\n safeUnwrap(input: unknown): Promise<UnwrapResult<Brand, Kind>>;\n /** Strict type guard: `true` only for already-canonical `Id<Brand>` strings. */\n is(value: unknown): value is Id<Brand>;\n /** Normalise to canonical form, or throw on parse failure. */\n parse(value: unknown): Id<Brand>;\n /** Normalise to canonical form, or return `{ ok: false, error }`. */\n safeParse(value: unknown): ParseResult<Brand>;\n toJsonSchema(): JsonSchema;\n readonly \"~standard\": StandardSchemaProps<Brand>;\n};\n\nexport type WrappedKeyOptions<K extends WrappedKind> = {\n kind: K;\n keys: [WrappingKey, ...WrappingKey[]];\n allowDuplicateBrand?: boolean;\n};\n\nconst u32Max = 0xffff_ffff;\nconst i32Min = -0x8000_0000;\nconst i32Max = 0x7fff_ffff;\nconst u64Max = 0xffff_ffff_ffff_ffffn;\nconst i64Min = -(1n << 63n);\nconst i64Max = (1n << 63n) - 1n;\n\nfunction assertSupportedKind(kind: WrappedKind): asserts kind is WrappedKind {\n if (kind !== \"u32\" && kind !== \"i32\" && kind !== \"u64\" && kind !== \"i64\") {\n throw new Error(\"invalid wrapped key kind: expected u32, i32, u64, or i64\");\n }\n}\n\nfunction assertNonEmptyKeyring(keys: readonly WrappingKey[]): void {\n if (keys.length === 0) {\n throw new Error(\"wrapped keyring must contain at least one key\");\n }\n}\n\nfunction assertNonDuplicateKeys(keys: readonly WrappingKey[]): void {\n for (let i = 0; i < keys.length; i++) {\n for (let j = i + 1; j < keys.length; j++) {\n if (wrappingKeysEqual(keys[i]!, keys[j]!)) {\n throw new Error(\"duplicate wrapping key in keyring\");\n }\n }\n }\n}\n\nfunction assertU32LookupKey(lookupKey: unknown): asserts lookupKey is number {\n if (\n typeof lookupKey !== \"number\" ||\n !Number.isInteger(lookupKey) ||\n Object.is(lookupKey, -0) ||\n lookupKey < 0 ||\n lookupKey > u32Max\n ) {\n throw new Error(`invalid u32 lookup key: expected integer in [0, ${u32Max}], got ${lookupKey}`);\n }\n}\n\nfunction assertI32LookupKey(lookupKey: unknown): asserts lookupKey is number {\n if (\n typeof lookupKey !== \"number\" ||\n !Number.isInteger(lookupKey) ||\n Object.is(lookupKey, -0) ||\n lookupKey < i32Min ||\n lookupKey > i32Max\n ) {\n throw new Error(\n `invalid i32 lookup key: expected integer in [${i32Min}, ${i32Max}], got ${lookupKey}`,\n );\n }\n}\n\nfunction assertU64LookupKey(lookupKey: unknown): asserts lookupKey is bigint {\n if (typeof lookupKey !== \"bigint\" || lookupKey < 0n || lookupKey > u64Max) {\n throw new Error(`invalid u64 lookup key: expected bigint in [0, ${u64Max}], got ${lookupKey}`);\n }\n}\n\nfunction assertI64LookupKey(lookupKey: unknown): asserts lookupKey is bigint {\n if (typeof lookupKey !== \"bigint\" || lookupKey < i64Min || lookupKey > i64Max) {\n throw new Error(\n `invalid i64 lookup key: expected bigint in [${i64Min}, ${i64Max}], got ${lookupKey}`,\n );\n }\n}\n\nfunction assertLookupKey<Kind extends WrappedKind>(\n kind: Kind,\n lookupKey: unknown,\n): asserts lookupKey is LookupKeyForKind<Kind> {\n if (kind === \"i32\") {\n assertI32LookupKey(lookupKey);\n return;\n }\n if (kind === \"u64\") {\n assertU64LookupKey(lookupKey);\n return;\n }\n if (kind === \"i64\") {\n assertI64LookupKey(lookupKey);\n return;\n }\n assertU32LookupKey(lookupKey);\n}\n\n/**\n * Construct a {@link WrappedKeyCodec} for `brand` and the given `kind`.\n *\n * `opts.kind` fixes the integer type at construction time — one brand, one\n * kind. `opts.keys` is a non-empty ordered wrapping keyring: the first entry\n * is current (used by `wrap`); all entries are tried on `unwrap`; duplicate\n * operator secrets are rejected at construction.\n *\n * @example\n * ```ts\n * const key = await importWrappingKey(new Uint8Array(32));\n * const invoices = createWrappedKeyId(\"inv\", { kind: \"u32\", keys: [key] });\n *\n * const id = await invoices.wrap(42); // Id<\"inv\">\n * await invoices.unwrap(id); // 42\n * ```\n */\nexport function createWrappedKeyId<Brand extends string, Kind extends WrappedKind>(\n brand: Brand,\n opts: WrappedKeyOptions<Kind>,\n): WrappedKeyCodec<Brand, Kind> {\n validateBrand(brand);\n registerBrand(brand, opts.allowDuplicateBrand);\n assertSupportedKind(opts.kind);\n assertNonEmptyKeyring(opts.keys);\n const layoutKeys = opts.keys.map(getWrappingKeyMaterial);\n assertNonDuplicateKeys(opts.keys);\n\n const prefix: Prefix<Brand> = `${brand}_`;\n const wire = wireMethods(prefix);\n const layout = createWrappedLayoutOps(prefix, brand, opts.kind, layoutKeys);\n\n return {\n wrap: async (lookupKey) => {\n assertLookupKey(opts.kind, lookupKey);\n return layout.wrap(lookupKey);\n },\n unwrap: (id) => layout.unwrap(id),\n safeUnwrap: async (input) => {\n const parsed = wire.safeParse(input);\n if (!parsed.ok) return parsed;\n const lookupKey = await layout.tryUnwrap(parsed.id);\n if (lookupKey === null) return { ok: false, error: \"verification_failed\" };\n return { ok: true, id: parsed.id, lookupKey };\n },\n is: wire.is,\n parse: wire.parse,\n safeParse: wire.safeParse,\n toJsonSchema: () => wire.toJsonSchema(brand, layout.exampleWireId()),\n \"~standard\": wire[\"~standard\"],\n };\n}\n"],"mappings":"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"}
@@ -0,0 +1,133 @@
1
+ import { a as StandardSchemaProps, i as ParseResult, n as JsonSchema, r as ParseError, t as Id } from "./types-g7CiQDyE.mjs";
2
+
3
+ //#region src/wrapping-key.d.ts
4
+ /** Wire encoding for wrapping operator secret bytes (not Crockford base32). */
5
+ type WrappingKeyFormat = "hex" | "base64url";
6
+ declare const wrappingKeyBrand: unique symbol;
7
+ /**
8
+ * Opaque imported handle for one operator wrapping secret.
9
+ *
10
+ * Holds derived AES and HMAC subkeys internally; callers never access subkeys
11
+ * or raw `CryptoKey` values directly. Obtain handles via {@link importWrappingKey}
12
+ * and pass them to `createWrappedKeyId` as the `keys` wrapping keyring.
13
+ *
14
+ * Distinct from the **Opaque key** used by `@smonn/ids/opaque` — one raw
15
+ * secret must not silently serve both codecs without an explicit import.
16
+ */
17
+ type WrappingKey = {
18
+ readonly [wrappingKeyBrand]: "WrappingKey";
19
+ };
20
+ /**
21
+ * Import raw operator secret bytes into a {@link WrappingKey} handle.
22
+ *
23
+ * One raw secret derives into AES and HMAC subkeys held inside the returned
24
+ * handle. Accepts 16, 24, or 32 bytes (AES-128 / AES-192 / AES-256 strength).
25
+ * To store or transport key material, use {@link encodeWrappingKey} /
26
+ * {@link decodeWrappingKey} (`"hex"` or `"base64url"` — not Crockford base32).
27
+ *
28
+ * @param bytes - 16, 24, or 32 raw key bytes.
29
+ */
30
+ declare function importWrappingKey(bytes: Uint8Array): Promise<WrappingKey>;
31
+ /**
32
+ * Encode raw wrapping operator secret bytes for storage in env vars or secret managers.
33
+ *
34
+ * Supports `"hex"` (lowercase) and `"base64url"`. Output round-trips through
35
+ * {@link decodeWrappingKey} back to the original bytes.
36
+ */
37
+ declare function encodeWrappingKey(bytes: Uint8Array, format: WrappingKeyFormat): string;
38
+ /**
39
+ * Decode key material emitted by {@link encodeWrappingKey} back to raw bytes.
40
+ *
41
+ * The result can be passed directly to {@link importWrappingKey}.
42
+ */
43
+ declare function decodeWrappingKey(encoded: string, format: WrappingKeyFormat): Uint8Array;
44
+ //#endregion
45
+ //#region src/wrapped.d.ts
46
+ type WrappedKind = "u32" | "i32" | "u64" | "i64";
47
+ type LookupKeyForKind<K extends WrappedKind> = K extends "u32" | "i32" ? number : bigint;
48
+ /**
49
+ * Result returned by {@link WrappedKeyCodec.safeUnwrap}.
50
+ *
51
+ * On success, `id` is the canonical {@link Id} and `lookupKey` is the recovered
52
+ * integer (`number` for 32-bit kinds, `bigint` for 64-bit kinds).
53
+ * On failure, `error` is a {@link ParseError} for structural problems or
54
+ * `"verification_failed"` when the payload is structurally valid but the
55
+ * verification tag does not match any entry in the wrapping keyring.
56
+ */
57
+ type UnwrapResult<Brand extends string, Kind extends WrappedKind> = {
58
+ ok: true;
59
+ id: Id<Brand>;
60
+ lookupKey: LookupKeyForKind<Kind>;
61
+ } | {
62
+ ok: false;
63
+ error: ParseError | "verification_failed";
64
+ };
65
+ /**
66
+ * Codec returned by {@link createWrappedKeyId}.
67
+ *
68
+ * Wraps a caller-owned integer **lookup key** into a public {@link Id} and
69
+ * recovers it on unwrap. The codec is deterministic under fixed key material:
70
+ * the same lookup key always yields the same public ID (**equality leakage**).
71
+ *
72
+ * - `wrap` / `unwrap` / `safeUnwrap` are async (WebCrypto).
73
+ * - `is`, `parse`, `safeParse`, and `toJsonSchema` are synchronous and require
74
+ * no key material — they validate prefix and base32 shape only.
75
+ * - The `Kind` type parameter drives value types at the TypeScript boundary:
76
+ * `u32` / `i32` → `number`; `u64` / `i64` → `bigint`.
77
+ */
78
+ type WrappedKeyCodec<Brand extends string, Kind extends WrappedKind> = {
79
+ /**
80
+ * Wrap `lookupKey` into a public ID using the current (first) wrapping key.
81
+ *
82
+ * Throws if `lookupKey` is out of range or the wrong JS type for `Kind`.
83
+ */
84
+ wrap(lookupKey: LookupKeyForKind<Kind>): Promise<Id<Brand>>;
85
+ /**
86
+ * Verify the payload of a trusted `Id<Brand>` and return the lookup key.
87
+ *
88
+ * Throws `"verification failed"` if no entry in the wrapping keyring matches
89
+ * the payload tag. Use {@link safeUnwrap} for untrusted input.
90
+ */
91
+ unwrap(id: Id<Brand>): Promise<LookupKeyForKind<Kind>>;
92
+ /**
93
+ * Non-throwing path for untrusted input.
94
+ *
95
+ * Structurally parses `input` first (same rules as {@link safeParse}), then
96
+ * verifies the payload. Returns `{ ok: false, error }` on any failure —
97
+ * `ParseError` for structural problems or `"verification_failed"` for tag
98
+ * mismatch — without throwing. Tamper, wrong keyring, and revoked-key cases
99
+ * all surface as `"verification_failed"`.
100
+ */
101
+ safeUnwrap(input: unknown): Promise<UnwrapResult<Brand, Kind>>; /** Strict type guard: `true` only for already-canonical `Id<Brand>` strings. */
102
+ is(value: unknown): value is Id<Brand>; /** Normalise to canonical form, or throw on parse failure. */
103
+ parse(value: unknown): Id<Brand>; /** Normalise to canonical form, or return `{ ok: false, error }`. */
104
+ safeParse(value: unknown): ParseResult<Brand>;
105
+ toJsonSchema(): JsonSchema;
106
+ readonly "~standard": StandardSchemaProps<Brand>;
107
+ };
108
+ type WrappedKeyOptions<K extends WrappedKind> = {
109
+ kind: K;
110
+ keys: [WrappingKey, ...WrappingKey[]];
111
+ allowDuplicateBrand?: boolean;
112
+ };
113
+ /**
114
+ * Construct a {@link WrappedKeyCodec} for `brand` and the given `kind`.
115
+ *
116
+ * `opts.kind` fixes the integer type at construction time — one brand, one
117
+ * kind. `opts.keys` is a non-empty ordered wrapping keyring: the first entry
118
+ * is current (used by `wrap`); all entries are tried on `unwrap`; duplicate
119
+ * operator secrets are rejected at construction.
120
+ *
121
+ * @example
122
+ * ```ts
123
+ * const key = await importWrappingKey(new Uint8Array(32));
124
+ * const invoices = createWrappedKeyId("inv", { kind: "u32", keys: [key] });
125
+ *
126
+ * const id = await invoices.wrap(42); // Id<"inv">
127
+ * await invoices.unwrap(id); // 42
128
+ * ```
129
+ */
130
+ declare function createWrappedKeyId<Brand extends string, Kind extends WrappedKind>(brand: Brand, opts: WrappedKeyOptions<Kind>): WrappedKeyCodec<Brand, Kind>;
131
+ //#endregion
132
+ export { UnwrapResult, WrappedKeyCodec, WrappedKeyOptions, WrappedKind, type WrappingKey, type WrappingKeyFormat, createWrappedKeyId, decodeWrappingKey, encodeWrappingKey, importWrappingKey };
133
+ //# sourceMappingURL=wrapped.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wrapped.d.mts","names":[],"sources":["../src/wrapping-key.ts","../src/wrapped.ts"],"mappings":";;;;KAGY,iBAAA;AAAA,cAOE,gBAAA;AAPd;;;;AAAY;AAA4B;;;;AAO1B;AAPd,KAmBY,WAAA;EAAA,UACA,gBAAA;AAAA;;;;;;;;;;;iBA0BU,iBAAA,CAAkB,KAAA,EAAO,UAAA,GAAa,OAAA,CAAQ,WAAA;AAAA;AAmBpE;;;;;AAnBoE,iBAmBpD,iBAAA,CAAkB,KAAA,EAAO,UAAA,EAAY,MAAA,EAAQ,iBAAA;;;;AAAA;AAY7D;iBAAgB,iBAAA,CAAkB,OAAA,UAAiB,MAAA,EAAQ,iBAAA,GAAoB,UAAA;;;KClDnE,WAAA;AAAA,KAEP,gBAAA,WAA2B,WAAA,IAAe,CAAA;;;AD7BnC;AAA4B;;;;AAO1B;AAYd;KCqBY,YAAA,oCAAgD,WAAA;EACtD,EAAA;EAAU,EAAA,EAAI,EAAA,CAAG,KAAA;EAAQ,SAAA,EAAW,gBAAA,CAAiB,IAAA;AAAA;EACrD,EAAA;EAAW,KAAA,EAAO,UAAA;AAAA;;;;;;;ADI4C;AAmBpE;;;;;;KCRY,eAAA,oCAAmD,WAAA;EDoB/D;;;;;ECdE,IAAA,CAAK,SAAA,EAAW,gBAAA,CAAiB,IAAA,IAAQ,OAAA,CAAQ,EAAA,CAAG,KAAA;;;;ADcyB;;;ECP7E,MAAA,CAAO,EAAA,EAAI,EAAA,CAAG,KAAA,IAAS,OAAA,CAAQ,gBAAA,CAAiB,IAAA;EA3ClD;;;;AAAY;AAAsC;;;;EAqDhD,UAAA,CAAW,KAAA,YAAiB,OAAA,CAAQ,YAAA,CAAa,KAAA,EAAO,IAAA;EAExD,EAAA,CAAG,KAAA,YAAiB,KAAA,IAAS,EAAA,CAAG,KAAA,GArDa;EAuD7C,KAAA,CAAM,KAAA,YAAiB,EAAA,CAAG,KAAA,GA5C5B;EA8CE,SAAA,CAAU,KAAA,YAAiB,WAAA,CAAY,KAAA;EACvC,YAAA,IAAgB,UAAA;EAAA,SACP,WAAA,EAAa,mBAAA,CAAoB,KAAA;AAAA;AAAA,KAGhC,iBAAA,WAA4B,WAAA;EACtC,IAAA,EAAM,CAAA;EACN,IAAA,GAAO,WAAA,KAAgB,WAAA;EACvB,mBAAA;AAAA;;;;;;;;;;;;;;;;AApDsB;AAexB;iBAiJgB,kBAAA,oCAAsD,WAAA,EACpE,KAAA,EAAO,KAAA,EACP,IAAA,EAAM,iBAAA,CAAkB,IAAA,IACvB,eAAA,CAAgB,KAAA,EAAO,IAAA"}
@@ -0,0 +1,2 @@
1
+ import { i as importWrappingKey, n as decodeWrappingKey, r as encodeWrappingKey, t as createWrappedKeyId } from "./wrapped-Dw5mHQhn.mjs";
2
+ export { createWrappedKeyId, decodeWrappingKey, encodeWrappingKey, importWrappingKey };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@smonn/ids",
3
- "version": "0.4.0",
3
+ "version": "0.6.0",
4
4
  "license": "MIT",
5
5
  "author": "Simon Ingeson (https://github.com/smonn)",
6
6
  "repository": {
@@ -17,21 +17,57 @@
17
17
  "exports": {
18
18
  ".": "./dist/index.mjs",
19
19
  "./opaque": "./dist/opaque.mjs",
20
+ "./reverse": "./dist/reverse.mjs",
21
+ "./wrapped": "./dist/wrapped.mjs",
22
+ "./drizzle": "./dist/drizzle.mjs",
23
+ "./hono": "./dist/hono.mjs",
24
+ "./kysely": "./dist/kysely.mjs",
25
+ "./prisma": "./dist/prisma.mjs",
26
+ "./express": "./dist/express.mjs",
20
27
  "./package.json": "./package.json"
21
28
  },
22
29
  "devDependencies": {
23
30
  "@changesets/cli": "2.31.0",
24
- "@types/node": "25.9.1",
31
+ "@types/express": "^5.0.6",
32
+ "@types/node": "25.9.3",
25
33
  "@vitest/coverage-v8": "4.1.8",
26
- "dependency-cruiser": "16.10.4",
27
- "knip": "6.15.0",
34
+ "dependency-cruiser": "17.4.3",
35
+ "drizzle-orm": "^0.45.2",
36
+ "express": "^5.2.1",
37
+ "hono": "^4.12.26",
38
+ "knip": "6.16.1",
39
+ "kysely": "^0.29.2",
28
40
  "mitata": "1.0.34",
29
- "oxfmt": "0.53.0",
30
- "oxlint": "1.68.0",
31
- "tsdown": "0.22.1",
41
+ "oxfmt": "0.55.0",
42
+ "oxlint": "1.69.0",
43
+ "tsdown": "0.22.2",
32
44
  "typescript": "6.0.3",
33
45
  "vitest": "4.1.8"
34
46
  },
47
+ "peerDependencies": {
48
+ "@prisma/client": ">=5.0.0",
49
+ "drizzle-orm": ">=0.30.0",
50
+ "express": ">=4.0.0",
51
+ "hono": ">=4.0.0",
52
+ "kysely": ">=0.27.0"
53
+ },
54
+ "peerDependenciesMeta": {
55
+ "drizzle-orm": {
56
+ "optional": true
57
+ },
58
+ "express": {
59
+ "optional": true
60
+ },
61
+ "hono": {
62
+ "optional": true
63
+ },
64
+ "kysely": {
65
+ "optional": true
66
+ },
67
+ "@prisma/client": {
68
+ "optional": true
69
+ }
70
+ },
35
71
  "engines": {
36
72
  "node": ">=24.0.0"
37
73
  },