@coffre/db 0.4.5 → 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 (44) hide show
  1. package/dist/connect.d.ts +1 -1
  2. package/dist/{database-edkMkG02.d.ts → database-C63WjCrC.d.ts} +1 -1
  3. package/dist/dialect.d.ts +7 -1
  4. package/dist/dialect.js +12 -1
  5. package/dist/grants.d.ts +105 -10
  6. package/dist/grants.js +207 -7
  7. package/dist/hyperdrive.d.ts +1 -1
  8. package/dist/index.d.ts +2 -2
  9. package/dist/log.d.ts +392 -2
  10. package/dist/log.js +53 -1
  11. package/dist/migrations/postgres/0002_instance_roles.sql +4 -0
  12. package/dist/migrations/postgres/0003_credential_scopes.sql +4 -0
  13. package/dist/migrations/postgres/meta/0002_snapshot.json +2860 -0
  14. package/dist/migrations/postgres/meta/0003_snapshot.json +2872 -0
  15. package/dist/migrations/postgres/meta/_journal.json +14 -0
  16. package/dist/migrations/sqlite/0002_instance_roles.sql +2 -0
  17. package/dist/migrations/sqlite/0003_credential_scopes.sql +2 -0
  18. package/dist/migrations/sqlite/meta/0002_snapshot.json +2594 -0
  19. package/dist/migrations/sqlite/meta/0003_snapshot.json +2608 -0
  20. package/dist/migrations/sqlite/meta/_journal.json +14 -0
  21. package/dist/portable.d.ts +2 -2
  22. package/dist/{schema-BqCB3XFm.d.ts → schema-a7PkFgea.d.ts} +68 -0
  23. package/dist/schema-sqlite.d.ts +76 -0
  24. package/dist/schema-sqlite.js +4 -0
  25. package/dist/schema-version.d.ts +1 -1
  26. package/dist/schema-version.js +60 -26
  27. package/dist/schema.d.ts +1 -1
  28. package/dist/schema.js +4 -0
  29. package/package.json +2 -2
  30. package/src/dialect.ts +14 -0
  31. package/src/grants.ts +272 -11
  32. package/src/log.ts +66 -2
  33. package/src/migrations/postgres/0002_instance_roles.sql +4 -0
  34. package/src/migrations/postgres/0003_credential_scopes.sql +4 -0
  35. package/src/migrations/postgres/meta/0002_snapshot.json +2860 -0
  36. package/src/migrations/postgres/meta/0003_snapshot.json +2872 -0
  37. package/src/migrations/postgres/meta/_journal.json +14 -0
  38. package/src/migrations/sqlite/0002_instance_roles.sql +2 -0
  39. package/src/migrations/sqlite/0003_credential_scopes.sql +2 -0
  40. package/src/migrations/sqlite/meta/0002_snapshot.json +2594 -0
  41. package/src/migrations/sqlite/meta/0003_snapshot.json +2608 -0
  42. package/src/migrations/sqlite/meta/_journal.json +14 -0
  43. package/src/schema.sqlite.ts +6 -0
  44. package/src/schema.ts +11 -1
package/dist/log.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { a as Transaction } from "./database-edkMkG02.js";
2
- import { LogKey } from "@coffre/core/audit";
1
+ import { a as Transaction, i as Queryable } from "./database-C63WjCrC.js";
2
+ import { LogKey, StoredEntry } from "@coffre/core/audit";
3
3
  //#region src/log.d.ts
4
4
  /**
5
5
  * Appending to the audit log, the one table both the app and the vault
@@ -75,4 +75,394 @@ export declare function lockLogHead(tx: Transaction): Promise<{
75
75
  * commits. It throws to refuse.
76
76
  */
77
77
  export declare function appendEntries(tx: Transaction, key: LogKey, entries: readonly NewEntry[], check?: (tx: Transaction) => Promise<void>): Promise<Appended>;
78
+ /** An entry's columns, as the chain's codec reads them (`StoredEntry`). */
79
+ export declare function entryColumns(db: Queryable): {
80
+ seq: import("drizzle-orm/pg-core").PgColumn<{
81
+ name: "seq";
82
+ tableName: "audit_log";
83
+ dataType: "bigint";
84
+ columnType: "PgBigInt64";
85
+ data: bigint;
86
+ driverParam: string;
87
+ notNull: true;
88
+ hasDefault: false;
89
+ isPrimaryKey: true;
90
+ isAutoincrement: false;
91
+ hasRuntimeDefault: false;
92
+ enumValues: undefined;
93
+ baseColumn: never;
94
+ identity: undefined;
95
+ generated: undefined;
96
+ }, {}, {}>;
97
+ author: import("drizzle-orm/pg-core").PgColumn<{
98
+ name: "author";
99
+ tableName: "audit_log";
100
+ dataType: "string";
101
+ columnType: "PgText";
102
+ data: string;
103
+ driverParam: string;
104
+ notNull: true;
105
+ hasDefault: false;
106
+ isPrimaryKey: false;
107
+ isAutoincrement: false;
108
+ hasRuntimeDefault: false;
109
+ enumValues: [string, ...string[]];
110
+ baseColumn: never;
111
+ identity: undefined;
112
+ generated: undefined;
113
+ }, {}, {}>;
114
+ keyId: import("drizzle-orm/pg-core").PgColumn<{
115
+ name: "key_id";
116
+ tableName: "audit_log";
117
+ dataType: "string";
118
+ columnType: "PgText";
119
+ data: string;
120
+ driverParam: string;
121
+ notNull: true;
122
+ hasDefault: false;
123
+ isPrimaryKey: false;
124
+ isAutoincrement: false;
125
+ hasRuntimeDefault: false;
126
+ enumValues: [string, ...string[]];
127
+ baseColumn: never;
128
+ identity: undefined;
129
+ generated: undefined;
130
+ }, {}, {}>;
131
+ occurredAt: import("drizzle-orm/pg-core").PgColumn<{
132
+ name: "occurred_at";
133
+ tableName: "audit_log";
134
+ dataType: "number";
135
+ columnType: "PgBigInt53";
136
+ data: number;
137
+ driverParam: string | number;
138
+ notNull: true;
139
+ hasDefault: false;
140
+ isPrimaryKey: false;
141
+ isAutoincrement: false;
142
+ hasRuntimeDefault: false;
143
+ enumValues: undefined;
144
+ baseColumn: never;
145
+ identity: undefined;
146
+ generated: undefined;
147
+ }, {}, {}>;
148
+ actor: import("drizzle-orm/pg-core").PgColumn<{
149
+ name: "actor";
150
+ tableName: "audit_log";
151
+ dataType: "string";
152
+ columnType: "PgText";
153
+ data: string;
154
+ driverParam: string;
155
+ notNull: true;
156
+ hasDefault: false;
157
+ isPrimaryKey: false;
158
+ isAutoincrement: false;
159
+ hasRuntimeDefault: false;
160
+ enumValues: [string, ...string[]];
161
+ baseColumn: never;
162
+ identity: undefined;
163
+ generated: undefined;
164
+ }, {}, {}>;
165
+ action: import("drizzle-orm/pg-core").PgColumn<{
166
+ name: "action";
167
+ tableName: "audit_log";
168
+ dataType: "string";
169
+ columnType: "PgText";
170
+ data: string;
171
+ driverParam: string;
172
+ notNull: true;
173
+ hasDefault: false;
174
+ isPrimaryKey: false;
175
+ isAutoincrement: false;
176
+ hasRuntimeDefault: false;
177
+ enumValues: [string, ...string[]];
178
+ baseColumn: never;
179
+ identity: undefined;
180
+ generated: undefined;
181
+ }, {}, {}>;
182
+ decision: import("drizzle-orm/pg-core").PgColumn<{
183
+ name: "decision";
184
+ tableName: "audit_log";
185
+ dataType: "string";
186
+ columnType: "PgText";
187
+ data: string;
188
+ driverParam: string;
189
+ notNull: true;
190
+ hasDefault: false;
191
+ isPrimaryKey: false;
192
+ isAutoincrement: false;
193
+ hasRuntimeDefault: false;
194
+ enumValues: [string, ...string[]];
195
+ baseColumn: never;
196
+ identity: undefined;
197
+ generated: undefined;
198
+ }, {}, {}>;
199
+ code: import("drizzle-orm/pg-core").PgColumn<{
200
+ name: "code";
201
+ tableName: "audit_log";
202
+ dataType: "string";
203
+ columnType: "PgText";
204
+ data: string;
205
+ driverParam: string;
206
+ notNull: false;
207
+ hasDefault: false;
208
+ isPrimaryKey: false;
209
+ isAutoincrement: false;
210
+ hasRuntimeDefault: false;
211
+ enumValues: [string, ...string[]];
212
+ baseColumn: never;
213
+ identity: undefined;
214
+ generated: undefined;
215
+ }, {}, {}>;
216
+ subjectPrincipal: import("drizzle-orm/pg-core").PgColumn<{
217
+ name: "subject_principal";
218
+ tableName: "audit_log";
219
+ dataType: "string";
220
+ columnType: "PgText";
221
+ data: string;
222
+ driverParam: string;
223
+ notNull: false;
224
+ hasDefault: false;
225
+ isPrimaryKey: false;
226
+ isAutoincrement: false;
227
+ hasRuntimeDefault: false;
228
+ enumValues: [string, ...string[]];
229
+ baseColumn: never;
230
+ identity: undefined;
231
+ generated: undefined;
232
+ }, {}, {}>;
233
+ projectId: import("drizzle-orm/pg-core").PgColumn<{
234
+ name: "project_id";
235
+ tableName: "audit_log";
236
+ dataType: "string";
237
+ columnType: "PgUUID";
238
+ data: string;
239
+ driverParam: string;
240
+ notNull: false;
241
+ hasDefault: false;
242
+ isPrimaryKey: false;
243
+ isAutoincrement: false;
244
+ hasRuntimeDefault: false;
245
+ enumValues: undefined;
246
+ baseColumn: never;
247
+ identity: undefined;
248
+ generated: undefined;
249
+ }, {}, {}>;
250
+ environmentId: import("drizzle-orm/pg-core").PgColumn<{
251
+ name: "environment_id";
252
+ tableName: "audit_log";
253
+ dataType: "string";
254
+ columnType: "PgUUID";
255
+ data: string;
256
+ driverParam: string;
257
+ notNull: false;
258
+ hasDefault: false;
259
+ isPrimaryKey: false;
260
+ isAutoincrement: false;
261
+ hasRuntimeDefault: false;
262
+ enumValues: undefined;
263
+ baseColumn: never;
264
+ identity: undefined;
265
+ generated: undefined;
266
+ }, {}, {}>;
267
+ secretId: import("drizzle-orm/pg-core").PgColumn<{
268
+ name: "secret_id";
269
+ tableName: "audit_log";
270
+ dataType: "string";
271
+ columnType: "PgUUID";
272
+ data: string;
273
+ driverParam: string;
274
+ notNull: false;
275
+ hasDefault: false;
276
+ isPrimaryKey: false;
277
+ isAutoincrement: false;
278
+ hasRuntimeDefault: false;
279
+ enumValues: undefined;
280
+ baseColumn: never;
281
+ identity: undefined;
282
+ generated: undefined;
283
+ }, {}, {}>;
284
+ secretVersionId: import("drizzle-orm/pg-core").PgColumn<{
285
+ name: "secret_version_id";
286
+ tableName: "audit_log";
287
+ dataType: "string";
288
+ columnType: "PgUUID";
289
+ data: string;
290
+ driverParam: string;
291
+ notNull: false;
292
+ hasDefault: false;
293
+ isPrimaryKey: false;
294
+ isAutoincrement: false;
295
+ hasRuntimeDefault: false;
296
+ enumValues: undefined;
297
+ baseColumn: never;
298
+ identity: undefined;
299
+ generated: undefined;
300
+ }, {}, {}>;
301
+ operationId: import("drizzle-orm/pg-core").PgColumn<{
302
+ name: "operation_id";
303
+ tableName: "audit_log";
304
+ dataType: "string";
305
+ columnType: "PgUUID";
306
+ data: string;
307
+ driverParam: string;
308
+ notNull: false;
309
+ hasDefault: false;
310
+ isPrimaryKey: false;
311
+ isAutoincrement: false;
312
+ hasRuntimeDefault: false;
313
+ enumValues: undefined;
314
+ baseColumn: never;
315
+ identity: undefined;
316
+ generated: undefined;
317
+ }, {}, {}>;
318
+ requestId: import("drizzle-orm/pg-core").PgColumn<{
319
+ name: "request_id";
320
+ tableName: "audit_log";
321
+ dataType: "string";
322
+ columnType: "PgText";
323
+ data: string;
324
+ driverParam: string;
325
+ notNull: false;
326
+ hasDefault: false;
327
+ isPrimaryKey: false;
328
+ isAutoincrement: false;
329
+ hasRuntimeDefault: false;
330
+ enumValues: [string, ...string[]];
331
+ baseColumn: never;
332
+ identity: undefined;
333
+ generated: undefined;
334
+ }, {}, {}>;
335
+ sourceIp: import("drizzle-orm/pg-core").PgColumn<{
336
+ name: "source_ip";
337
+ tableName: "audit_log";
338
+ dataType: "string";
339
+ columnType: "PgText";
340
+ data: string;
341
+ driverParam: string;
342
+ notNull: false;
343
+ hasDefault: false;
344
+ isPrimaryKey: false;
345
+ isAutoincrement: false;
346
+ hasRuntimeDefault: false;
347
+ enumValues: [string, ...string[]];
348
+ baseColumn: never;
349
+ identity: undefined;
350
+ generated: undefined;
351
+ }, {}, {}>;
352
+ relatedSeq: import("drizzle-orm/pg-core").PgColumn<{
353
+ name: "related_seq";
354
+ tableName: "audit_log";
355
+ dataType: "bigint";
356
+ columnType: "PgBigInt64";
357
+ data: bigint;
358
+ driverParam: string;
359
+ notNull: false;
360
+ hasDefault: false;
361
+ isPrimaryKey: false;
362
+ isAutoincrement: false;
363
+ hasRuntimeDefault: false;
364
+ enumValues: undefined;
365
+ baseColumn: never;
366
+ identity: undefined;
367
+ generated: undefined;
368
+ }, {}, {}>;
369
+ metadata: import("drizzle-orm/pg-core").PgColumn<{
370
+ name: "metadata";
371
+ tableName: "audit_log";
372
+ dataType: "string";
373
+ columnType: "PgText";
374
+ data: string;
375
+ driverParam: string;
376
+ notNull: true;
377
+ hasDefault: true;
378
+ isPrimaryKey: false;
379
+ isAutoincrement: false;
380
+ hasRuntimeDefault: false;
381
+ enumValues: [string, ...string[]];
382
+ baseColumn: never;
383
+ identity: undefined;
384
+ generated: undefined;
385
+ }, {}, {}>;
386
+ prevHash: import("drizzle-orm/pg-core").PgColumn<{
387
+ name: "prev_hash";
388
+ tableName: "audit_log";
389
+ dataType: "custom";
390
+ columnType: "PgCustomColumn";
391
+ data: Buffer<ArrayBufferLike>;
392
+ driverParam: unknown;
393
+ notNull: true;
394
+ hasDefault: false;
395
+ isPrimaryKey: false;
396
+ isAutoincrement: false;
397
+ hasRuntimeDefault: false;
398
+ enumValues: undefined;
399
+ baseColumn: never;
400
+ identity: undefined;
401
+ generated: undefined;
402
+ }, {}, {
403
+ pgColumnBuilderBrand: "PgCustomColumnBuilderBrand";
404
+ }>;
405
+ mac: import("drizzle-orm/pg-core").PgColumn<{
406
+ name: "mac";
407
+ tableName: "audit_log";
408
+ dataType: "custom";
409
+ columnType: "PgCustomColumn";
410
+ data: Buffer<ArrayBufferLike>;
411
+ driverParam: unknown;
412
+ notNull: true;
413
+ hasDefault: false;
414
+ isPrimaryKey: false;
415
+ isAutoincrement: false;
416
+ hasRuntimeDefault: false;
417
+ enumValues: undefined;
418
+ baseColumn: never;
419
+ identity: undefined;
420
+ generated: undefined;
421
+ }, {}, {
422
+ pgColumnBuilderBrand: "PgCustomColumnBuilderBrand";
423
+ }>;
424
+ hash: import("drizzle-orm/pg-core").PgColumn<{
425
+ name: "hash";
426
+ tableName: "audit_log";
427
+ dataType: "custom";
428
+ columnType: "PgCustomColumn";
429
+ data: Buffer<ArrayBufferLike>;
430
+ driverParam: unknown;
431
+ notNull: true;
432
+ hasDefault: false;
433
+ isPrimaryKey: false;
434
+ isAutoincrement: false;
435
+ hasRuntimeDefault: false;
436
+ enumValues: undefined;
437
+ baseColumn: never;
438
+ identity: undefined;
439
+ generated: undefined;
440
+ }, {}, {
441
+ pgColumnBuilderBrand: "PgCustomColumnBuilderBrand";
442
+ }>;
443
+ };
444
+ /**
445
+ * How a reader tells the vault's own entries from those forged in its name:
446
+ * by their MAC, which only the vault holds the key to check. Each it finds
447
+ * forged goes to `forged`.
448
+ */
449
+ export type Authenticity = {
450
+ authentic: (entry: StoredEntry) => boolean;
451
+ forged: (entry: StoredEntry) => void;
452
+ };
453
+ /** How many entries in its name the vault reads back, a page at a time, for its own newest of a kind (`newestAuthentic`). */
454
+ export declare const LOOK_BACK: {
455
+ page: number;
456
+ pages: number;
457
+ };
458
+ /** What `newestAuthentic` finds: the entry, or why there is none. */
459
+ export type Newest = StoredEntry | 'none' | 'forged' | 'unreached';
460
+ /**
461
+ * The newest of the entries `page` reads, newest first and before a seq,
462
+ * that `check` finds authentic, read back a page at a time: 'none' when
463
+ * there are none at all, 'forged' when every one is in the vault's name but
464
+ * not its own, and 'unreached' once it has read LOOK_BACK such entries
465
+ * (1024), whether or not more are left.
466
+ */
467
+ export declare function newestAuthentic(page: (before: bigint | undefined) => Promise<StoredEntry[]>, check: Authenticity): Promise<Newest>;
78
468
  //#endregion
package/dist/log.js CHANGED
@@ -136,5 +136,57 @@ async function appendEntries(tx, key, entries, check) {
136
136
  occurredAt: now
137
137
  };
138
138
  }
139
+ /** An entry's columns, as the chain's codec reads them (`StoredEntry`). */
140
+ function entryColumns(db) {
141
+ const { auditLog } = tablesOf(db);
142
+ return {
143
+ seq: auditLog.seq,
144
+ author: auditLog.author,
145
+ keyId: auditLog.keyId,
146
+ occurredAt: auditLog.occurredAt,
147
+ actor: auditLog.actor,
148
+ action: auditLog.action,
149
+ decision: auditLog.decision,
150
+ code: auditLog.code,
151
+ subjectPrincipal: auditLog.subjectPrincipal,
152
+ projectId: auditLog.projectId,
153
+ environmentId: auditLog.environmentId,
154
+ secretId: auditLog.secretId,
155
+ secretVersionId: auditLog.secretVersionId,
156
+ operationId: auditLog.operationId,
157
+ requestId: auditLog.requestId,
158
+ sourceIp: auditLog.sourceIp,
159
+ relatedSeq: auditLog.relatedSeq,
160
+ metadata: auditLog.metadata,
161
+ prevHash: auditLog.prevHash,
162
+ mac: auditLog.mac,
163
+ hash: auditLog.hash
164
+ };
165
+ }
166
+ /** How many entries in its name the vault reads back, a page at a time, for its own newest of a kind (`newestAuthentic`). */
167
+ const LOOK_BACK = {
168
+ page: 32,
169
+ pages: 32
170
+ };
171
+ /**
172
+ * The newest of the entries `page` reads, newest first and before a seq,
173
+ * that `check` finds authentic, read back a page at a time: 'none' when
174
+ * there are none at all, 'forged' when every one is in the vault's name but
175
+ * not its own, and 'unreached' once it has read LOOK_BACK such entries
176
+ * (1024), whether or not more are left.
177
+ */
178
+ async function newestAuthentic(page, check) {
179
+ let before;
180
+ for (let read = 0; read < LOOK_BACK.pages; read += 1) {
181
+ const entries = await page(before);
182
+ for (const entry of entries) {
183
+ if (check.authentic(entry)) return entry;
184
+ check.forged(entry);
185
+ }
186
+ if (entries.length < LOOK_BACK.page) return before === void 0 && entries.length === 0 ? "none" : "forged";
187
+ before = entries.at(-1).seq;
188
+ }
189
+ return "unreached";
190
+ }
139
191
  //#endregion
140
- export { LogHeadMismatch, LogRewound, appendEntries, forgetLogHeads, lockLogHead };
192
+ export { LOOK_BACK, LogHeadMismatch, LogRewound, appendEntries, entryColumns, forgetLogHeads, lockLogHead, newestAuthentic };
@@ -0,0 +1,4 @@
1
+ ALTER TABLE "vault_members" ADD COLUMN "role" text;--> statement-breakpoint
2
+ ALTER TABLE "vault_members" ADD COLUMN "scope" text;--> statement-breakpoint
3
+ -- The vault sets a person's instance role and its scope, as it sets the rest of their row.
4
+ GRANT UPDATE (role, scope) ON vault_members TO coffre_vault;
@@ -0,0 +1,4 @@
1
+ ALTER TABLE "credentials" ADD COLUMN "scope" text;--> statement-breakpoint
2
+ ALTER TABLE "service_bindings" ADD COLUMN "scope" text;--> statement-breakpoint
3
+ -- The app seals each token and binding of 0.4 with its account's grants, once, as it seals the rest of their rows.
4
+ GRANT UPDATE (scope) ON credentials, service_bindings TO coffre_app;