@mstone6969/vault 0.2.0 → 0.5.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 (58) hide show
  1. package/README.md +198 -6
  2. package/dist/crypto.d.ts +99 -2
  3. package/dist/crypto.d.ts.map +1 -1
  4. package/dist/errors.d.ts +122 -4
  5. package/dist/errors.d.ts.map +1 -1
  6. package/dist/index.d.ts +2 -0
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/index.js +447 -33
  9. package/dist/index.js.map +9 -7
  10. package/dist/providers.d.ts +131 -0
  11. package/dist/providers.d.ts.map +1 -0
  12. package/dist/stores/file.d.ts +190 -0
  13. package/dist/stores/file.d.ts.map +1 -0
  14. package/dist/stores/file.js +1 -0
  15. package/dist/stores/memory.d.ts +98 -7
  16. package/dist/stores/memory.d.ts.map +1 -1
  17. package/dist/stores/sqlite.d.ts +140 -9
  18. package/dist/stores/sqlite.d.ts.map +1 -1
  19. package/dist/stores/sqlite.js +47 -12
  20. package/dist/stores/sqlite.js.map +3 -3
  21. package/dist/types.d.ts +408 -17
  22. package/dist/types.d.ts.map +1 -1
  23. package/dist/vault.d.ts +554 -19
  24. package/dist/vault.d.ts.map +1 -1
  25. package/docs/README.md +10 -0
  26. package/docs/index/README.md +48 -0
  27. package/docs/index/classes/FileStore.md +341 -0
  28. package/docs/index/classes/MemoryStore.md +240 -0
  29. package/docs/index/classes/Vault.md +805 -0
  30. package/docs/index/classes/VaultError.md +371 -0
  31. package/docs/index/classes/VaultKeyError.md +370 -0
  32. package/docs/index/functions/envKey.md +43 -0
  33. package/docs/index/functions/fileKey.md +46 -0
  34. package/docs/index/functions/generateKey.md +39 -0
  35. package/docs/index/functions/importKey.md +49 -0
  36. package/docs/index/functions/isKeyProvider.md +43 -0
  37. package/docs/index/functions/open.md +67 -0
  38. package/docs/index/functions/randomValue.md +53 -0
  39. package/docs/index/functions/seal.md +56 -0
  40. package/docs/index/functions/staticKey.md +39 -0
  41. package/docs/index/type-aliases/Generator.md +58 -0
  42. package/docs/index/type-aliases/HistoryEntry.md +65 -0
  43. package/docs/index/type-aliases/KeyProvider.md +74 -0
  44. package/docs/index/type-aliases/PutOptions.md +141 -0
  45. package/docs/index/type-aliases/RekeyReport.md +37 -0
  46. package/docs/index/type-aliases/RotationContext.md +49 -0
  47. package/docs/index/type-aliases/RotationPolicy.md +142 -0
  48. package/docs/index/type-aliases/SecretRecord.md +214 -0
  49. package/docs/index/type-aliases/SecretSummary.md +56 -0
  50. package/docs/index/type-aliases/VaultEvent.md +95 -0
  51. package/docs/index/type-aliases/VaultOptions.md +142 -0
  52. package/docs/index/type-aliases/VaultStore.md +156 -0
  53. package/docs/index/variables/DEFAULT_ALPHABET.md +29 -0
  54. package/docs/index/variables/DEFAULT_HISTORY_LIMIT.md +28 -0
  55. package/docs/index/variables/DEFAULT_PREFIX.md +23 -0
  56. package/docs/stores/sqlite/README.md +11 -0
  57. package/docs/stores/sqlite/classes/SqliteStore.md +307 -0
  58. package/package.json +15 -5
package/dist/types.d.ts CHANGED
@@ -1,36 +1,427 @@
1
- /** A stored secret, as the store keeps it. */
1
+ /**
2
+ * A value a rotatable entry used to hold.
3
+ *
4
+ * @remarks
5
+ * Kept sealed, exactly as the live value is, so history costs no more trust
6
+ * than the entry itself. A job that read the credential moments before a
7
+ * rotation can still finish on what it was given.
8
+ *
9
+ * @example
10
+ * ```ts
11
+ * await vault.rotate("alice", "db")
12
+ * // The value that was live until the rotation, opened:
13
+ * const [previous] = await vault.versions("alice", "db")
14
+ * ```
15
+ *
16
+ * @see {@link SecretRecord.history}
17
+ */
18
+ export type HistoryEntry = {
19
+ /** The value, sealed exactly as the live one is. */
20
+ sealed: string;
21
+ /**
22
+ * The data key that opens it, itself sealed under the master key.
23
+ *
24
+ * Null on values kept before envelope encryption, which are sealed under
25
+ * the master key directly. A `rekey` moves the non-null ones onto the new
26
+ * master key and leaves the rest alone.
27
+ */
28
+ sealedKey: string | null;
29
+ /** When this value was replaced. */
30
+ createdAt: Date;
31
+ };
32
+ /**
33
+ * How an entry's next value is produced.
34
+ *
35
+ * This is a recipe, not a value: it says *how* to make the next password, never
36
+ * what the current one is. Storing it means an entry can be rotated by anything
37
+ * holding the vault, without that thing being told the secret it is replacing.
38
+ *
39
+ * @example
40
+ * ```ts
41
+ * // The vault mints the next value itself.
42
+ * await vault.put("alice", "db", "current", {
43
+ * rotation: { kind: "random", length: 40, every: 60 * 60 * 24 * 30 },
44
+ * })
45
+ *
46
+ * // Or a function registered on the vault does, for a credential only the
47
+ * // far end can issue.
48
+ * await vault.put("alice", "aws", "current", {
49
+ * rotation: { kind: "generator", generator: "aws", arguments: { user: "ci" } },
50
+ * })
51
+ * await vault.rotate("alice", "aws")
52
+ * ```
53
+ *
54
+ * @see {@link PutOptions.rotation}
55
+ */
56
+ export type RotationPolicy = {
57
+ /**
58
+ * `random` has the vault generate one. `generator` calls a function you
59
+ * registered by name — for a credential only the far end can mint.
60
+ *
61
+ * @remarks
62
+ * `generator` names a function in the vault's `generators`; rotating with a
63
+ * name the vault does not have fails rather than inventing a value.
64
+ */
65
+ kind: "random" | "generator";
66
+ /**
67
+ * random: how many characters. Default 32.
68
+ *
69
+ * @defaultValue 32
70
+ */
71
+ length?: number;
72
+ /**
73
+ * random: which characters to draw from.
74
+ *
75
+ * @remarks
76
+ * Sampling is unbiased whatever the length, so an alphabet trimmed to what
77
+ * a system accepts costs nothing. Needs at least two characters.
78
+ *
79
+ * @defaultValue `DEFAULT_ALPHABET` — the 62 ASCII letters and digits
80
+ */
81
+ alphabet?: string;
82
+ /**
83
+ * generator: which registered generator to call.
84
+ *
85
+ * @remarks
86
+ * A name, not a function. What is written down is that an entry can be
87
+ * rotated, not how to impersonate the thing that rotates it — the function
88
+ * stays in the process that built the vault.
89
+ */
90
+ generator?: string;
91
+ /**
92
+ * generator: non-secret arguments, e.g. which account to rotate.
93
+ *
94
+ * @remarks
95
+ * Stored in the clear beside the policy, so it must hold nothing secret.
96
+ * Reaches the generator as the `arguments` of its context.
97
+ */
98
+ arguments?: Record<string, string>;
99
+ /**
100
+ * How often it wants rotating, in seconds. Nothing enforces it; `rotationDue` reports it.
101
+ *
102
+ * @remarks
103
+ * Measured from `rotatedAt`, or from `createdAt` for an entry never
104
+ * rotated. Left out, the entry is never reported as due.
105
+ *
106
+ * @example
107
+ * ```ts
108
+ * for (const secret of await vault.rotationDue()) {
109
+ * await vault.rotate(secret.owner, secret.name)
110
+ * }
111
+ * ```
112
+ */
113
+ every?: number;
114
+ };
115
+ /**
116
+ * A stored secret, as the store keeps it.
117
+ *
118
+ * @remarks
119
+ * The shape a {@link VaultStore} reads and writes, and the only place the
120
+ * sealed bytes appear. Callers of the vault get {@link SecretSummary} instead.
121
+ * A store persists these fields as given: none of them mean anything to it.
122
+ *
123
+ * @see {@link SecretSummary}
124
+ */
2
125
  export type SecretRecord = {
126
+ /** Whose it is. The vault never reaches across owners except to rekey. */
3
127
  owner: string;
128
+ /**
129
+ * What it is called, and how a reference finds it.
130
+ *
131
+ * @remarks
132
+ * Up to 64 characters of letters, numbers, dot, dash or underscore —
133
+ * checked by the vault before it reaches a store. Unique per owner.
134
+ */
4
135
  name: string;
5
- /** Sealed value, `iv:payload`. Never the plaintext. */
136
+ /**
137
+ * The value, sealed under this entry's data key — `iv:payload`, base64.
138
+ * Empty when the entry is not sealed.
139
+ */
6
140
  sealed: string;
7
141
  /**
8
- * Non-secret facts about the value, stored in the clear and returned by
9
- * `list`: what kind of credential it is, which username it belongs to, a
10
- * public key anything safe to show beside the name.
142
+ * This entry's data key, sealed under the master key.
143
+ *
144
+ * Every value gets its own key, and only these are re-sealed when the
145
+ * master key changes: rekeying costs one small operation per entry rather
146
+ * than re-encrypting every byte, and one leaked data key exposes one value.
147
+ *
148
+ * Null on entries written before envelope encryption, whose value is sealed
149
+ * under the master key directly.
150
+ */
151
+ sealedKey: string | null;
152
+ /**
153
+ * The value in the open. Only ever set when `isSealed` is false.
154
+ *
155
+ * @remarks
156
+ * This is the one field a store holds that is readable without a key, so an
157
+ * entry only lands here when `put` was told `open: true`.
158
+ */
159
+ plain: string | null;
160
+ /**
161
+ * False for entries stored in the open, which can be read back.
162
+ *
163
+ * @remarks
164
+ * Left out of a replacing `put`, an entry keeps whatever it already was:
165
+ * rotating a credential should not quietly unseal it.
166
+ *
167
+ * @defaultValue true for a new entry
168
+ */
169
+ isSealed: boolean;
170
+ /**
171
+ * Written once: a store must refuse to replace it.
172
+ *
173
+ * @remarks
174
+ * The refusing is the vault's — a store writes what it is given. `put` on a
175
+ * final entry throws and records a `denied` event with detail `"final"`.
176
+ * Removing it still works; finality is about change, not deletion.
177
+ */
178
+ isFinal: boolean;
179
+ /**
180
+ * When the entry stops resolving, or null if it does not.
181
+ *
182
+ * @remarks
183
+ * The entry stays in the store past this moment, but `open`, `read` and
184
+ * `resolve` refuse it. `purgeExpired` is what actually deletes it.
185
+ */
186
+ expiresAt: Date | null;
187
+ /**
188
+ * Previous values, newest first. Empty unless the entry keeps history.
189
+ *
190
+ * @remarks
191
+ * Filled by `rotate`, or by a `put` told `keepHistory: true`, and trimmed
192
+ * to the vault's `historyLimit`.
193
+ */
194
+ history: HistoryEntry[];
195
+ /** How to produce the next value, or null if nothing knows. */
196
+ rotation: RotationPolicy | null;
197
+ /**
198
+ * When it was last rotated, as opposed to merely replaced.
199
+ *
200
+ * @remarks
201
+ * Null until the first rotation, which is why `rotationDue` falls back to
202
+ * `createdAt` when deciding whether `every` has elapsed.
203
+ */
204
+ rotatedAt: Date | null;
205
+ /**
206
+ * Non-secret facts, stored in the clear and returned by `list`: what kind
207
+ * of credential it is, which username it belongs to, a public key.
11
208
  */
12
209
  metadata: Record<string, string>;
210
+ /** When the entry was first stored. Survives replacement. */
13
211
  createdAt: Date;
212
+ /** When it last changed. */
14
213
  updatedAt: Date;
15
214
  };
16
- /** A stored secret, as callers are allowed to see it: no value. */
17
- export type SecretSummary = Omit<SecretRecord, "sealed">;
18
215
  /**
19
- * Where sealed values live. Implement this to keep secrets in whatever database
20
- * you already run; `MemoryStore` and `SqliteStore` ship with the package.
216
+ * A stored secret, as callers are allowed to see it: no sealed value.
21
217
  *
22
- * Every method is scoped by `owner`, so one store serves many accounts.
218
+ * @remarks
219
+ * What `put`, `rotate`, `list` and `rotationDue` hand back. The sealed bytes,
220
+ * the data key and the kept history are dropped rather than hidden, so a
221
+ * summary can be logged or returned from an API without leaking anything the
222
+ * master key protects.
223
+ *
224
+ * @example
225
+ * ```ts
226
+ * for (const secret of await vault.list("alice")) {
227
+ * console.log(secret.name, secret.metadata.kind, secret.versions)
228
+ * }
229
+ * ```
230
+ *
231
+ * @see {@link SecretRecord}
232
+ */
233
+ export type SecretSummary = Omit<SecretRecord, "sealed" | "sealedKey" | "plain" | "history"> & {
234
+ /**
235
+ * Present only for entries stored in the open.
236
+ *
237
+ * @remarks
238
+ * A sealed entry leaves this undefined however it is summarised; its value
239
+ * only comes out of `open`.
240
+ */
241
+ value?: string;
242
+ /**
243
+ * How many previous values are kept.
244
+ *
245
+ * @remarks
246
+ * A count, not the values: `versions` on the vault opens those, one at a
247
+ * time and only for whoever holds the key.
248
+ */
249
+ versions: number;
250
+ };
251
+ /**
252
+ * What `put` is allowed to say about an entry beyond its value.
253
+ *
254
+ * @remarks
255
+ * Every field left out means "as it was" on a replacing `put`, so rotating a
256
+ * credential does not quietly forget what kind it is or when it expires. The
257
+ * exception is `final`, which must be asked for each time.
258
+ *
259
+ * @example
260
+ * ```ts
261
+ * await vault.put("alice", "db", "s3cret", {
262
+ * metadata: { kind: "postgres", user: "app" },
263
+ * rotation: { kind: "random", length: 40 },
264
+ * expiresAt: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000),
265
+ * })
266
+ * ```
267
+ */
268
+ export type PutOptions = {
269
+ /**
270
+ * Non-secret facts to keep beside the value, returned by `list`. Replaces
271
+ * whatever was there; leave it out to keep what the entry already has.
272
+ */
273
+ metadata?: Record<string, string>;
274
+ /**
275
+ * How to produce the next value when it is rotated.
276
+ *
277
+ * @remarks
278
+ * Pass null to drop a policy an entry already has; leaving it out keeps it.
279
+ *
280
+ * @see {@link RotationPolicy}
281
+ */
282
+ rotation?: RotationPolicy | null;
283
+ /**
284
+ * Store in the open, readable by `read`.
285
+ *
286
+ * @remarks
287
+ * For values that belong beside the secrets but are not secret — a host, an
288
+ * account id. Left out, the entry keeps how it was already stored.
289
+ *
290
+ * @defaultValue false
291
+ */
292
+ open?: boolean;
293
+ /**
294
+ * Refuse every future replacement.
295
+ *
296
+ * @remarks
297
+ * Not sticky: it is taken from this call alone, so it must be repeated by
298
+ * anything rewriting the entry — which nothing can, once it is set.
299
+ *
300
+ * @defaultValue false
301
+ */
302
+ final?: boolean;
303
+ /**
304
+ * When it should stop resolving.
305
+ *
306
+ * @remarks
307
+ * Pass null to make an expiring entry permanent again.
308
+ *
309
+ * @defaultValue null
310
+ */
311
+ expiresAt?: Date | null;
312
+ /**
313
+ * Keep the value being replaced, up to `historyLimit`.
314
+ *
315
+ * @remarks
316
+ * What `rotate` sets for you; set it by hand when replacing a value
317
+ * yourself and something may still be running on the old one.
318
+ *
319
+ * @defaultValue false
320
+ */
321
+ keepHistory?: boolean;
322
+ };
323
+ /**
324
+ * Where records live. Implement this to keep secrets in whatever database you
325
+ * already run; `MemoryStore`, `SqliteStore` and `FileStore` ship with the
326
+ * package.
327
+ *
328
+ * A store persists records as given and enforces nothing: the rules about
329
+ * finality, expiry and history are the vault's.
330
+ *
331
+ * @example
332
+ * ```ts
333
+ * import { Vault, MemoryStore } from "@mstone6969/vault"
334
+ *
335
+ * const vault = new Vault({ key, store: new MemoryStore() })
336
+ * ```
337
+ *
338
+ * @see {@link SecretRecord}
23
339
  */
24
340
  export type VaultStore = {
341
+ /**
342
+ * One record, or null when there is none under that name.
343
+ *
344
+ * @param owner Whose entry to look for.
345
+ * @param name The entry's name, already checked by the vault.
346
+ * @returns The record as it was written, or null.
347
+ */
25
348
  get(owner: string, name: string): Promise<SecretRecord | null>;
349
+ /**
350
+ * Every record one owner holds, in any order.
351
+ *
352
+ * @param owner Whose entries to return.
353
+ * @returns The owner's records; the vault sorts them by name itself.
354
+ */
26
355
  list(owner: string): Promise<SecretRecord[]>;
27
- /** Insert or replace, returning what was stored. */
28
- put(record: {
29
- owner: string;
30
- name: string;
31
- sealed: string;
32
- metadata: Record<string, string>;
33
- }): Promise<SecretRecord>;
356
+ /**
357
+ * Every record the store holds, whoever owns it. Only `rekey` and
358
+ * `purgeExpired` need this — nothing else reaches across owners.
359
+ *
360
+ * @returns Every record, in any order.
361
+ */
362
+ all(): Promise<SecretRecord[]>;
363
+ /**
364
+ * Writes a record, replacing any under the same owner and name.
365
+ *
366
+ * @param record The record to write. Store it as given: `isFinal` is the
367
+ * vault's rule to enforce, not the store's.
368
+ * @returns The record as stored, which is what the caller sees.
369
+ */
370
+ put(record: SecretRecord): Promise<SecretRecord>;
371
+ /**
372
+ * Deletes a record, returning false when there was nothing to delete.
373
+ *
374
+ * @param owner Whose entry to delete.
375
+ * @param name The entry to delete.
376
+ * @returns True when a record went, false when there was none.
377
+ */
34
378
  remove(owner: string, name: string): Promise<boolean>;
35
379
  };
380
+ /**
381
+ * Something a vault did, for whoever is keeping an audit trail.
382
+ *
383
+ * @remarks
384
+ * Handed to the vault's `onAccess`, which is never awaited and whose failures
385
+ * are ignored — logging must not break a vault. Events carry names, never
386
+ * values, so the trail is safe to keep wherever logs go.
387
+ *
388
+ * @example
389
+ * ```ts
390
+ * const vault = new Vault({
391
+ * key,
392
+ * store,
393
+ * onAccess: (event) => {
394
+ * if (event.action === "denied") {
395
+ * console.warn(`refused ${event.owner}/${event.name}: ${event.detail}`)
396
+ * }
397
+ * },
398
+ * })
399
+ * ```
400
+ */
401
+ export type VaultEvent = {
402
+ /**
403
+ * What was attempted. `denied` means the vault refused; see `detail`.
404
+ *
405
+ * @remarks
406
+ * `open` is a sealed value coming out, `read` an entry stored in the open.
407
+ * A `rotate` is also recorded as the `put` that carries it out.
408
+ */
409
+ action: "put" | "open" | "read" | "remove" | "rotate" | "rekey" | "denied";
410
+ /** Whose entry it was. Empty for vault-wide actions. */
411
+ owner: string;
412
+ /** The entry involved, or null for vault-wide actions like `rekey`. */
413
+ name: string | null;
414
+ /** When it happened. */
415
+ at: Date;
416
+ /**
417
+ * Why a `denied` happened, or what a vault-wide action touched.
418
+ *
419
+ * @remarks
420
+ * On a `denied`: `"final"` for a replacement of an entry written once,
421
+ * `"sealed"` for a `read` of a value only `open` returns, `"expired"` for
422
+ * an entry past `expiresAt`. On a `rekey`, how many entries moved and how
423
+ * many would not open.
424
+ */
425
+ detail?: string;
426
+ };
36
427
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,8CAA8C;AAC9C,MAAM,MAAM,YAAY,GAAG;IACvB,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,uDAAuD;IACvD,MAAM,EAAE,MAAM,CAAA;IACd;;;;OAIG;IACH,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAChC,SAAS,EAAE,IAAI,CAAA;IACf,SAAS,EAAE,IAAI,CAAA;CAClB,CAAA;AAED,mEAAmE;AACnE,MAAM,MAAM,aAAa,GAAG,IAAI,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAA;AAExD;;;;;GAKG;AACH,MAAM,MAAM,UAAU,GAAG;IACrB,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAAA;IAC9D,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAAA;IAC5C,oDAAoD;IACpD,GAAG,CAAC,MAAM,EAAE;QACR,KAAK,EAAE,MAAM,CAAA;QACb,IAAI,EAAE,MAAM,CAAA;QACZ,MAAM,EAAE,MAAM,CAAA;QACd,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KACnC,GAAG,OAAO,CAAC,YAAY,CAAC,CAAA;IACzB,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;CACxD,CAAA"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}