@coffre/db 0.10.2 → 0.12.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 (46) hide show
  1. package/dist/connect.d.ts +1 -1
  2. package/dist/{database-DBtn3jqp.d.ts → database-Ds1Y79h6.d.ts} +1 -1
  3. package/dist/dialect.d.ts +1 -1
  4. package/dist/grants.d.ts +12 -5
  5. package/dist/grants.js +13 -8
  6. package/dist/hyperdrive.d.ts +9 -2
  7. package/dist/hyperdrive.js +16 -2
  8. package/dist/index.d.ts +2 -2
  9. package/dist/log.d.ts +1 -1
  10. package/dist/migrations/postgres/0015_workload_access.sql +43 -0
  11. package/dist/migrations/postgres/0016_spent_tokens.sql +12 -0
  12. package/dist/migrations/postgres/0017_capped_alerts.sql +10 -0
  13. package/dist/migrations/postgres/meta/0015_snapshot.json +3256 -0
  14. package/dist/migrations/postgres/meta/0016_snapshot.json +3256 -0
  15. package/dist/migrations/postgres/meta/0017_snapshot.json +3295 -0
  16. package/dist/migrations/postgres/meta/_journal.json +21 -0
  17. package/dist/migrations/sqlite/0015_workload_access.sql +70 -0
  18. package/dist/migrations/sqlite/0016_capped_alerts.sql +7 -0
  19. package/dist/migrations/sqlite/meta/0015_snapshot.json +2959 -0
  20. package/dist/migrations/sqlite/meta/0016_snapshot.json +2998 -0
  21. package/dist/migrations/sqlite/meta/_journal.json +14 -0
  22. package/dist/portable.d.ts +2 -2
  23. package/dist/{schema-NBVA9q-s.d.ts → schema-DcVkJhCf.d.ts} +393 -2
  24. package/dist/schema-sqlite.d.ts +408 -1
  25. package/dist/schema-sqlite.js +61 -5
  26. package/dist/schema-version.d.ts +1 -1
  27. package/dist/schema-version.js +35 -0
  28. package/dist/schema.d.ts +2 -2
  29. package/dist/schema.js +71 -5
  30. package/package.json +2 -2
  31. package/src/grants.ts +18 -9
  32. package/src/hyperdrive.ts +16 -2
  33. package/src/migrations/postgres/0015_workload_access.sql +43 -0
  34. package/src/migrations/postgres/0016_spent_tokens.sql +12 -0
  35. package/src/migrations/postgres/0017_capped_alerts.sql +10 -0
  36. package/src/migrations/postgres/meta/0015_snapshot.json +3256 -0
  37. package/src/migrations/postgres/meta/0016_snapshot.json +3256 -0
  38. package/src/migrations/postgres/meta/0017_snapshot.json +3295 -0
  39. package/src/migrations/postgres/meta/_journal.json +21 -0
  40. package/src/migrations/sqlite/0015_workload_access.sql +70 -0
  41. package/src/migrations/sqlite/0016_capped_alerts.sql +7 -0
  42. package/src/migrations/sqlite/meta/0015_snapshot.json +2959 -0
  43. package/src/migrations/sqlite/meta/0016_snapshot.json +2998 -0
  44. package/src/migrations/sqlite/meta/_journal.json +14 -0
  45. package/src/schema.sqlite.ts +83 -2
  46. package/src/schema.ts +91 -2
@@ -1,5 +1,5 @@
1
1
  declare namespace schema_sqlite_d_exports {
2
- export { auditChainHead, auditLog, consumedTokens, credentials, deviceAuthorizations, dismissedKeys, environments, environmentsRelations, identities, mcpApprovals, mcpConnections, oauthClients, projects, secretReferences, secretVersions, secrets, secretsRelations, serviceBindings, vaultGrants, vaultMembers };
2
+ export { auditChainHead, auditLog, cappedAlerts, consumedTokens, credentials, deviceAuthorizations, dismissedKeys, enrollments, environments, environmentsRelations, identities, mcpApprovals, mcpConnections, oauthClients, projects, secretReferences, secretVersions, secrets, secretsRelations, serviceBindings, vaultGrants, vaultMembers };
3
3
  }
4
4
  export declare const projects: import("drizzle-orm/sqlite-core").SQLiteTableWithColumns<{
5
5
  name: "projects";
@@ -2400,6 +2400,25 @@ export declare const serviceBindings: import("drizzle-orm/sqlite-core").SQLiteTa
2400
2400
  }, {}, {
2401
2401
  length: undefined;
2402
2402
  }>;
2403
+ policy: import("drizzle-orm/sqlite-core").SQLiteColumn<{
2404
+ name: "policy";
2405
+ tableName: "service_bindings";
2406
+ dataType: "string";
2407
+ columnType: "SQLiteText";
2408
+ data: string;
2409
+ driverParam: string;
2410
+ notNull: false;
2411
+ hasDefault: false;
2412
+ isPrimaryKey: false;
2413
+ isAutoincrement: false;
2414
+ hasRuntimeDefault: false;
2415
+ enumValues: [string, ...string[]];
2416
+ baseColumn: never;
2417
+ identity: undefined;
2418
+ generated: undefined;
2419
+ }, {}, {
2420
+ length: undefined;
2421
+ }>;
2403
2422
  label: import("drizzle-orm/sqlite-core").SQLiteColumn<{
2404
2423
  name: "label";
2405
2424
  tableName: "service_bindings";
@@ -2552,6 +2571,68 @@ export declare const consumedTokens: import("drizzle-orm/sqlite-core").SQLiteTab
2552
2571
  };
2553
2572
  dialect: "sqlite";
2554
2573
  }>;
2574
+ export declare const cappedAlerts: import("drizzle-orm/sqlite-core").SQLiteTableWithColumns<{
2575
+ name: "capped_alerts";
2576
+ schema: undefined;
2577
+ columns: {
2578
+ service: import("drizzle-orm/sqlite-core").SQLiteColumn<{
2579
+ name: "service";
2580
+ tableName: "capped_alerts";
2581
+ dataType: "string";
2582
+ columnType: "SQLiteText";
2583
+ data: string;
2584
+ driverParam: string;
2585
+ notNull: true;
2586
+ hasDefault: false;
2587
+ isPrimaryKey: false;
2588
+ isAutoincrement: false;
2589
+ hasRuntimeDefault: false;
2590
+ enumValues: [string, ...string[]];
2591
+ baseColumn: never;
2592
+ identity: undefined;
2593
+ generated: undefined;
2594
+ }, {}, {
2595
+ length: undefined;
2596
+ }>;
2597
+ kind: import("drizzle-orm/sqlite-core").SQLiteColumn<{
2598
+ name: "kind";
2599
+ tableName: "capped_alerts";
2600
+ dataType: "string";
2601
+ columnType: "SQLiteText";
2602
+ data: string;
2603
+ driverParam: string;
2604
+ notNull: true;
2605
+ hasDefault: false;
2606
+ isPrimaryKey: false;
2607
+ isAutoincrement: false;
2608
+ hasRuntimeDefault: false;
2609
+ enumValues: [string, ...string[]];
2610
+ baseColumn: never;
2611
+ identity: undefined;
2612
+ generated: undefined;
2613
+ }, {}, {
2614
+ length: undefined;
2615
+ }>;
2616
+ raisedAt: import("drizzle-orm/sqlite-core").SQLiteColumn<{
2617
+ name: string;
2618
+ tableName: "capped_alerts";
2619
+ dataType: "date";
2620
+ columnType: "SQLiteTimestamp";
2621
+ data: Date;
2622
+ driverParam: number;
2623
+ notNull: true;
2624
+ hasDefault: false;
2625
+ isPrimaryKey: false;
2626
+ isAutoincrement: false;
2627
+ hasRuntimeDefault: false;
2628
+ enumValues: undefined;
2629
+ baseColumn: never;
2630
+ identity: undefined;
2631
+ generated: undefined;
2632
+ }, {}, {}>;
2633
+ };
2634
+ dialect: "sqlite";
2635
+ }>;
2555
2636
  /**
2556
2637
  * MCP clients that registered themselves (RFC 7591), the fallback to Client
2557
2638
  * ID Metadata Documents, which need no row. The ID is the client's
@@ -3294,6 +3375,203 @@ export declare const mcpApprovals: import("drizzle-orm/sqlite-core").SQLiteTable
3294
3375
  };
3295
3376
  dialect: "sqlite";
3296
3377
  }>;
3378
+ /**
3379
+ * Enrollment codes (docs/design/workload-access.md, section 4.4): what CI
3380
+ * mints for a platform that signs no identity, and the app exchanges for a
3381
+ * workload's session at `/api/auth/workload`. Never a credential itself, and
3382
+ * only ever added: the log says which code a promote superseded. Its scope,
3383
+ * fixed at minting, is the binding's within what the minter held; the MAC
3384
+ * covers everything but its hint and creation time (auth-rows.ts in the server).
3385
+ */
3386
+ export declare const enrollments: import("drizzle-orm/sqlite-core").SQLiteTableWithColumns<{
3387
+ name: "enrollments";
3388
+ schema: undefined;
3389
+ columns: {
3390
+ id: import("drizzle-orm/sqlite-core").SQLiteColumn<{
3391
+ name: "id";
3392
+ tableName: "enrollments";
3393
+ dataType: "string";
3394
+ columnType: "SQLiteText";
3395
+ data: string;
3396
+ driverParam: string;
3397
+ notNull: true;
3398
+ hasDefault: false;
3399
+ isPrimaryKey: true;
3400
+ isAutoincrement: false;
3401
+ hasRuntimeDefault: false;
3402
+ enumValues: [string, ...string[]];
3403
+ baseColumn: never;
3404
+ identity: undefined;
3405
+ generated: undefined;
3406
+ }, {}, {
3407
+ length: undefined;
3408
+ }>;
3409
+ authMac: import("drizzle-orm/sqlite-core").SQLiteColumn<{
3410
+ name: string;
3411
+ tableName: "enrollments";
3412
+ dataType: "buffer";
3413
+ columnType: "SQLiteBlobBuffer";
3414
+ data: Buffer<ArrayBufferLike>;
3415
+ driverParam: Buffer<ArrayBufferLike>;
3416
+ notNull: true;
3417
+ hasDefault: false;
3418
+ isPrimaryKey: false;
3419
+ isAutoincrement: false;
3420
+ hasRuntimeDefault: false;
3421
+ enumValues: undefined;
3422
+ baseColumn: never;
3423
+ identity: undefined;
3424
+ generated: undefined;
3425
+ }, {}, {}>;
3426
+ bindingId: import("drizzle-orm/sqlite-core").SQLiteColumn<{
3427
+ name: "binding_id";
3428
+ tableName: "enrollments";
3429
+ dataType: "string";
3430
+ columnType: "SQLiteText";
3431
+ data: string;
3432
+ driverParam: string;
3433
+ notNull: true;
3434
+ hasDefault: false;
3435
+ isPrimaryKey: false;
3436
+ isAutoincrement: false;
3437
+ hasRuntimeDefault: false;
3438
+ enumValues: [string, ...string[]];
3439
+ baseColumn: never;
3440
+ identity: undefined;
3441
+ generated: undefined;
3442
+ }, {}, {
3443
+ length: number | undefined;
3444
+ }>;
3445
+ codeHash: import("drizzle-orm/sqlite-core").SQLiteColumn<{
3446
+ name: string;
3447
+ tableName: "enrollments";
3448
+ dataType: "buffer";
3449
+ columnType: "SQLiteBlobBuffer";
3450
+ data: Buffer<ArrayBufferLike>;
3451
+ driverParam: Buffer<ArrayBufferLike>;
3452
+ notNull: true;
3453
+ hasDefault: false;
3454
+ isPrimaryKey: false;
3455
+ isAutoincrement: false;
3456
+ hasRuntimeDefault: false;
3457
+ enumValues: undefined;
3458
+ baseColumn: never;
3459
+ identity: undefined;
3460
+ generated: undefined;
3461
+ }, {}, {}>;
3462
+ codeHint: import("drizzle-orm/sqlite-core").SQLiteColumn<{
3463
+ name: "code_hint";
3464
+ tableName: "enrollments";
3465
+ dataType: "string";
3466
+ columnType: "SQLiteText";
3467
+ data: string;
3468
+ driverParam: string;
3469
+ notNull: true;
3470
+ hasDefault: false;
3471
+ isPrimaryKey: false;
3472
+ isAutoincrement: false;
3473
+ hasRuntimeDefault: false;
3474
+ enumValues: [string, ...string[]];
3475
+ baseColumn: never;
3476
+ identity: undefined;
3477
+ generated: undefined;
3478
+ }, {}, {
3479
+ length: number | undefined;
3480
+ }>;
3481
+ scope: import("drizzle-orm/sqlite-core").SQLiteColumn<{
3482
+ name: "scope";
3483
+ tableName: "enrollments";
3484
+ dataType: "string";
3485
+ columnType: "SQLiteText";
3486
+ data: string;
3487
+ driverParam: string;
3488
+ notNull: true;
3489
+ hasDefault: false;
3490
+ isPrimaryKey: false;
3491
+ isAutoincrement: false;
3492
+ hasRuntimeDefault: false;
3493
+ enumValues: [string, ...string[]];
3494
+ baseColumn: never;
3495
+ identity: undefined;
3496
+ generated: undefined;
3497
+ }, {}, {
3498
+ length: undefined;
3499
+ }>;
3500
+ createdAt: import("drizzle-orm/sqlite-core").SQLiteColumn<{
3501
+ name: string;
3502
+ tableName: "enrollments";
3503
+ dataType: "date";
3504
+ columnType: "SQLiteTimestamp";
3505
+ data: Date;
3506
+ driverParam: number;
3507
+ notNull: true;
3508
+ hasDefault: true;
3509
+ isPrimaryKey: false;
3510
+ isAutoincrement: false;
3511
+ hasRuntimeDefault: false;
3512
+ enumValues: undefined;
3513
+ baseColumn: never;
3514
+ identity: undefined;
3515
+ generated: undefined;
3516
+ }, {}, {}>;
3517
+ createdBy: import("drizzle-orm/sqlite-core").SQLiteColumn<{
3518
+ name: "created_by";
3519
+ tableName: "enrollments";
3520
+ dataType: "string";
3521
+ columnType: "SQLiteText";
3522
+ data: string;
3523
+ driverParam: string;
3524
+ notNull: true;
3525
+ hasDefault: false;
3526
+ isPrimaryKey: false;
3527
+ isAutoincrement: false;
3528
+ hasRuntimeDefault: false;
3529
+ enumValues: [string, ...string[]];
3530
+ baseColumn: never;
3531
+ identity: undefined;
3532
+ generated: undefined;
3533
+ }, {}, {
3534
+ length: number | undefined;
3535
+ }>;
3536
+ createdWith: import("drizzle-orm/sqlite-core").SQLiteColumn<{
3537
+ name: "created_with";
3538
+ tableName: "enrollments";
3539
+ dataType: "string";
3540
+ columnType: "SQLiteText";
3541
+ data: string;
3542
+ driverParam: string;
3543
+ notNull: false;
3544
+ hasDefault: false;
3545
+ isPrimaryKey: false;
3546
+ isAutoincrement: false;
3547
+ hasRuntimeDefault: false;
3548
+ enumValues: [string, ...string[]];
3549
+ baseColumn: never;
3550
+ identity: undefined;
3551
+ generated: undefined;
3552
+ }, {}, {
3553
+ length: number | undefined;
3554
+ }>;
3555
+ expiresAt: import("drizzle-orm/sqlite-core").SQLiteColumn<{
3556
+ name: string;
3557
+ tableName: "enrollments";
3558
+ dataType: "date";
3559
+ columnType: "SQLiteTimestamp";
3560
+ data: Date;
3561
+ driverParam: number;
3562
+ notNull: true;
3563
+ hasDefault: false;
3564
+ isPrimaryKey: false;
3565
+ isAutoincrement: false;
3566
+ hasRuntimeDefault: false;
3567
+ enumValues: undefined;
3568
+ baseColumn: never;
3569
+ identity: undefined;
3570
+ generated: undefined;
3571
+ }, {}, {}>;
3572
+ };
3573
+ dialect: "sqlite";
3574
+ }>;
3297
3575
  export declare const credentials: import("drizzle-orm/sqlite-core").SQLiteTableWithColumns<{
3298
3576
  name: "credentials";
3299
3577
  schema: undefined;
@@ -3626,6 +3904,135 @@ export declare const credentials: import("drizzle-orm/sqlite-core").SQLiteTableW
3626
3904
  }, {}, {
3627
3905
  length: number | undefined;
3628
3906
  }>;
3907
+ jkt: import("drizzle-orm/sqlite-core").SQLiteColumn<{
3908
+ name: "jkt";
3909
+ tableName: "credentials";
3910
+ dataType: "string";
3911
+ columnType: "SQLiteText";
3912
+ data: string;
3913
+ driverParam: string;
3914
+ notNull: false;
3915
+ hasDefault: false;
3916
+ isPrimaryKey: false;
3917
+ isAutoincrement: false;
3918
+ hasRuntimeDefault: false;
3919
+ enumValues: [string, ...string[]];
3920
+ baseColumn: never;
3921
+ identity: undefined;
3922
+ generated: undefined;
3923
+ }, {}, {
3924
+ length: undefined;
3925
+ }>;
3926
+ notAfter: import("drizzle-orm/sqlite-core").SQLiteColumn<{
3927
+ name: string;
3928
+ tableName: "credentials";
3929
+ dataType: "date";
3930
+ columnType: "SQLiteTimestamp";
3931
+ data: Date;
3932
+ driverParam: number;
3933
+ notNull: false;
3934
+ hasDefault: false;
3935
+ isPrimaryKey: false;
3936
+ isAutoincrement: false;
3937
+ hasRuntimeDefault: false;
3938
+ enumValues: undefined;
3939
+ baseColumn: never;
3940
+ identity: undefined;
3941
+ generated: undefined;
3942
+ }, {}, {}>;
3943
+ ancestors: import("drizzle-orm/sqlite-core").SQLiteColumn<{
3944
+ name: "ancestors";
3945
+ tableName: "credentials";
3946
+ dataType: "string";
3947
+ columnType: "SQLiteText";
3948
+ data: string;
3949
+ driverParam: string;
3950
+ notNull: false;
3951
+ hasDefault: false;
3952
+ isPrimaryKey: false;
3953
+ isAutoincrement: false;
3954
+ hasRuntimeDefault: false;
3955
+ enumValues: [string, ...string[]];
3956
+ baseColumn: never;
3957
+ identity: undefined;
3958
+ generated: undefined;
3959
+ }, {}, {
3960
+ length: undefined;
3961
+ }>;
3962
+ constraints: import("drizzle-orm/sqlite-core").SQLiteColumn<{
3963
+ name: "constraints";
3964
+ tableName: "credentials";
3965
+ dataType: "string";
3966
+ columnType: "SQLiteText";
3967
+ data: string;
3968
+ driverParam: string;
3969
+ notNull: false;
3970
+ hasDefault: false;
3971
+ isPrimaryKey: false;
3972
+ isAutoincrement: false;
3973
+ hasRuntimeDefault: false;
3974
+ enumValues: [string, ...string[]];
3975
+ baseColumn: never;
3976
+ identity: undefined;
3977
+ generated: undefined;
3978
+ }, {}, {
3979
+ length: undefined;
3980
+ }>;
3981
+ enrollmentId: import("drizzle-orm/sqlite-core").SQLiteColumn<{
3982
+ name: "enrollment_id";
3983
+ tableName: "credentials";
3984
+ dataType: "string";
3985
+ columnType: "SQLiteText";
3986
+ data: string;
3987
+ driverParam: string;
3988
+ notNull: false;
3989
+ hasDefault: false;
3990
+ isPrimaryKey: false;
3991
+ isAutoincrement: false;
3992
+ hasRuntimeDefault: false;
3993
+ enumValues: [string, ...string[]];
3994
+ baseColumn: never;
3995
+ identity: undefined;
3996
+ generated: undefined;
3997
+ }, {}, {
3998
+ length: number | undefined;
3999
+ }>;
4000
+ approvedAt: import("drizzle-orm/sqlite-core").SQLiteColumn<{
4001
+ name: string;
4002
+ tableName: "credentials";
4003
+ dataType: "date";
4004
+ columnType: "SQLiteTimestamp";
4005
+ data: Date;
4006
+ driverParam: number;
4007
+ notNull: false;
4008
+ hasDefault: false;
4009
+ isPrimaryKey: false;
4010
+ isAutoincrement: false;
4011
+ hasRuntimeDefault: false;
4012
+ enumValues: undefined;
4013
+ baseColumn: never;
4014
+ identity: undefined;
4015
+ generated: undefined;
4016
+ }, {}, {}>;
4017
+ approvedBy: import("drizzle-orm/sqlite-core").SQLiteColumn<{
4018
+ name: "approved_by";
4019
+ tableName: "credentials";
4020
+ dataType: "string";
4021
+ columnType: "SQLiteText";
4022
+ data: string;
4023
+ driverParam: string;
4024
+ notNull: false;
4025
+ hasDefault: false;
4026
+ isPrimaryKey: false;
4027
+ isAutoincrement: false;
4028
+ hasRuntimeDefault: false;
4029
+ enumValues: [string, ...string[]];
4030
+ baseColumn: never;
4031
+ identity: undefined;
4032
+ generated: undefined;
4033
+ }, {}, {
4034
+ length: number | undefined;
4035
+ }>;
3629
4036
  };
3630
4037
  dialect: "sqlite";
3631
4038
  }>;
@@ -278,6 +278,8 @@ const auditLog = sqliteTable("audit_log", {
278
278
  index("audit_log_releases_idx").on(table.author, table.actor, table.action, table.decision, table.occurredAt),
279
279
  index("audit_log_subject_idx").on(table.author, table.subjectPrincipal, table.seq),
280
280
  index("audit_log_unbind_idx").on(sql`json_extract(${table.metadata}, '$.bindingId')`).where(sql`${table.author} = 'app' AND ${table.action} = 'token.unbind' AND ${table.decision} = 'allow'`),
281
+ index("audit_log_freeze_idx").on(sql`json_extract(${table.metadata}, '$.target')`, table.seq).where(sql`${table.author} = 'app' AND ${table.action} IN ('workload.freeze', 'workload.unfreeze') AND ${table.decision} = 'allow'`),
282
+ index("audit_log_supersede_idx").on(sql`json_extract(${table.metadata}, '$.enrollmentId')`).where(sql`${table.author} = 'app' AND ${table.action} = 'enrollment.supersede' AND ${table.decision} = 'allow'`),
281
283
  index("audit_log_exchange_idx").on(sql`json_extract(${table.metadata}, '$.credentialId')`).where(sql`${table.author} = 'app' AND ${table.action} = 'token.exchange' AND ${table.decision} = 'allow'`),
282
284
  index("audit_log_token_create_idx").on(sql`json_extract(${table.metadata}, '$.targetCredentialId')`).where(sql`${table.author} = 'app' AND ${table.action} = 'token.create' AND ${table.decision} = 'allow'`),
283
285
  index("audit_log_reference_end_idx").on(table.relatedSeq).where(sql`${table.author} = 'vault' AND ${table.action} = 'reference.end' AND ${table.decision} = 'allow'`),
@@ -367,6 +369,7 @@ const serviceBindings = sqliteTable("service_bindings", {
367
369
  jwks: text(),
368
370
  claims: text().notNull(),
369
371
  scope: text(),
372
+ policy: text(),
370
373
  label: text(),
371
374
  createdAt: createdAt(),
372
375
  createdBy: text("created_by").notNull(),
@@ -389,6 +392,14 @@ const consumedTokens = sqliteTable("consumed_tokens", {
389
392
  hash: bytes("hash").primaryKey(),
390
393
  consumedAt: time("consumed_at").notNull().default(now)
391
394
  }, (table) => [check("consumed_tokens_hash_check", sql`octet_length(${table.hash}) = 32`)]);
395
+ const cappedAlerts = sqliteTable("capped_alerts", {
396
+ service: text().notNull(),
397
+ kind: text().notNull(),
398
+ raisedAt: time("raised_at").notNull()
399
+ }, (table) => [primaryKey({
400
+ name: "capped_alerts_pkey",
401
+ columns: [table.service, table.kind]
402
+ })]);
392
403
  /**
393
404
  * MCP clients that registered themselves (RFC 7591), the fallback to Client
394
405
  * ID Metadata Documents, which need no row. The ID is the client's
@@ -475,6 +486,37 @@ const mcpApprovals = sqliteTable("mcp_approvals", {
475
486
  }).onDelete("restrict"),
476
487
  index("mcp_approvals_open_idx").on(table.connectionId, table.digest).where(sql`${table.reportedAt} IS NULL`)
477
488
  ]);
489
+ /**
490
+ * Enrollment codes (docs/design/workload-access.md, section 4.4): what CI
491
+ * mints for a platform that signs no identity, and the app exchanges for a
492
+ * workload's session at `/api/auth/workload`. Never a credential itself, and
493
+ * only ever added: the log says which code a promote superseded. Its scope,
494
+ * fixed at minting, is the binding's within what the minter held; the MAC
495
+ * covers everything but its hint and creation time (auth-rows.ts in the server).
496
+ */
497
+ const enrollments = sqliteTable("enrollments", {
498
+ id: text().primaryKey(),
499
+ authMac: bytes("auth_mac").notNull(),
500
+ bindingId: text("binding_id").notNull(),
501
+ codeHash: bytes("code_hash").notNull(),
502
+ codeHint: text("code_hint").notNull(),
503
+ scope: text().notNull(),
504
+ createdAt: createdAt(),
505
+ createdBy: text("created_by").notNull(),
506
+ createdWith: text("created_with"),
507
+ expiresAt: time("expires_at").notNull()
508
+ }, (table) => [
509
+ unique("enrollments_code_hash_key").on(table.codeHash),
510
+ check("enrollments_auth_mac_check", sql`octet_length(${table.authMac}) = 32`),
511
+ check("enrollments_code_hash_check", sql`octet_length(${table.codeHash}) = 32`),
512
+ check("enrollments_scope_check", sql`json_valid(${table.scope})`),
513
+ foreignKey({
514
+ name: "enrollments_binding_id_fkey",
515
+ columns: [table.bindingId],
516
+ foreignColumns: [serviceBindings.id]
517
+ }).onDelete("restrict"),
518
+ index("enrollments_binding_idx").on(table.bindingId, table.createdAt)
519
+ ]);
478
520
  const credentials = sqliteTable("credentials", {
479
521
  id: text().primaryKey(),
480
522
  kind: text().notNull(),
@@ -493,12 +535,20 @@ const credentials = sqliteTable("credentials", {
493
535
  lastUsedAt: time("last_used_at"),
494
536
  lastUsedIp: text("last_used_ip"),
495
537
  revokedAt: time("revoked_at"),
496
- revokedBy: text("revoked_by")
538
+ revokedBy: text("revoked_by"),
539
+ jkt: text(),
540
+ notAfter: time("not_after"),
541
+ ancestors: text(),
542
+ constraints: text(),
543
+ enrollmentId: text("enrollment_id"),
544
+ approvedAt: time("approved_at"),
545
+ approvedBy: text("approved_by")
497
546
  }, (table) => [
498
547
  unique("credentials_token_hash_key").on(table.tokenHash),
499
- check("credentials_kind_check", sql`${table.kind} IN ('browser', 'cli', 'service', 'personal', 'handle')`),
548
+ check("credentials_kind_check", sql`${table.kind} IN ('browser', 'cli', 'service', 'personal', 'handle', 'workload')`),
500
549
  check("credentials_principal_check", sql`${table.principal} LIKE 'user:%' OR ${table.principal} LIKE 'token:%'`),
501
- check("credentials_kind_matches_principal", sql`(${table.kind} = 'service') = (${table.principal} LIKE 'token:%')`),
550
+ check("credentials_kind_matches_principal", sql`(${table.kind} IN ('service', 'workload')) = (${table.principal} LIKE 'token:%')`),
551
+ check("credentials_workload_jkt_check", sql`${table.kind} <> 'workload' OR ${table.jkt} IS NOT NULL`),
502
552
  check("credentials_token_hash_check", sql`octet_length(${table.tokenHash}) = 32`),
503
553
  check("credentials_auth_mac_check", sql`octet_length(${table.authMac}) = 32`),
504
554
  foreignKey({
@@ -521,7 +571,13 @@ const credentials = sqliteTable("credentials", {
521
571
  }).onDelete("restrict"),
522
572
  index("credentials_principal_idx").on(table.principal, table.generation),
523
573
  index("credentials_live_idx").on(table.principal, table.expiresAt).where(sql`${table.revokedAt} IS NULL`),
524
- index("credentials_issued_by_idx").on(table.principal, table.createdBy, table.createdAt)
574
+ index("credentials_issued_by_idx").on(table.principal, table.createdBy, table.createdAt),
575
+ foreignKey({
576
+ name: "credentials_enrollment_id_fkey",
577
+ columns: [table.enrollmentId],
578
+ foreignColumns: [enrollments.id]
579
+ }).onDelete("restrict"),
580
+ index("credentials_enrollment_roots_idx").on(table.enrollmentId, table.createdAt).where(sql`${table.kind} = 'workload' AND ${table.ancestors} IS NULL`)
525
581
  ]);
526
582
  const deviceAuthorizations = sqliteTable("device_authorizations", {
527
583
  id: text().primaryKey(),
@@ -560,4 +616,4 @@ const { environmentsRelations, secretsRelations } = relationsOf(asPostgres({
560
616
  secretVersions
561
617
  }));
562
618
  //#endregion
563
- export { auditChainHead, auditLog, consumedTokens, credentials, deviceAuthorizations, dismissedKeys, environments, environmentsRelations, identities, mcpApprovals, mcpConnections, oauthClients, projects, secretReferences, secretVersions, secrets, secretsRelations, serviceBindings, vaultGrants, vaultMembers };
619
+ export { auditChainHead, auditLog, cappedAlerts, consumedTokens, credentials, deviceAuthorizations, dismissedKeys, enrollments, environments, environmentsRelations, identities, mcpApprovals, mcpConnections, oauthClients, projects, secretReferences, secretVersions, secrets, secretsRelations, serviceBindings, vaultGrants, vaultMembers };
@@ -1,4 +1,4 @@
1
- import { i as Queryable } from "./database-DBtn3jqp.js";
1
+ import { i as Queryable } from "./database-Ds1Y79h6.js";
2
2
  import { Engine } from "./dialect.js";
3
3
  //#region src/schema-version.d.ts
4
4
  /**
@@ -113,6 +113,27 @@ const KNOWN_MIGRATIONS = {
113
113
  "when": 1792345776262,
114
114
  "tag": "0014_custom_roles",
115
115
  "breakpoints": true
116
+ },
117
+ {
118
+ "idx": 15,
119
+ "version": "7",
120
+ "when": 1792803757287,
121
+ "tag": "0015_workload_access",
122
+ "breakpoints": true
123
+ },
124
+ {
125
+ "idx": 16,
126
+ "version": "7",
127
+ "when": 1792814038307,
128
+ "tag": "0016_spent_tokens",
129
+ "breakpoints": true
130
+ },
131
+ {
132
+ "idx": 17,
133
+ "version": "7",
134
+ "when": 1792835445795,
135
+ "tag": "0017_capped_alerts",
136
+ "breakpoints": true
116
137
  }
117
138
  ].map((entry) => entry.tag),
118
139
  sqlite: [
@@ -220,6 +241,20 @@ const KNOWN_MIGRATIONS = {
220
241
  "when": 1792345777255,
221
242
  "tag": "0014_custom_roles",
222
243
  "breakpoints": true
244
+ },
245
+ {
246
+ "idx": 15,
247
+ "version": "6",
248
+ "when": 1792803757926,
249
+ "tag": "0015_workload_access",
250
+ "breakpoints": true
251
+ },
252
+ {
253
+ "idx": 16,
254
+ "version": "6",
255
+ "when": 1792835446455,
256
+ "tag": "0016_capped_alerts",
257
+ "breakpoints": true
223
258
  }
224
259
  ].map((entry) => entry.tag)
225
260
  };
package/dist/schema.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- import { _ as secrets, a as deviceAuthorizations, b as vaultGrants, c as environmentsRelations, d as mcpConnections, f as oauthClients, g as secretVersions, h as secretReferences, i as credentials, l as identities, n as auditLog, o as dismissedKeys, p as projects, r as consumedTokens, s as environments, t as auditChainHead, u as mcpApprovals, v as secretsRelations, x as vaultMembers, y as serviceBindings } from "./schema-NBVA9q-s.js";
2
- export { auditChainHead, auditLog, consumedTokens, credentials, deviceAuthorizations, dismissedKeys, environments, environmentsRelations, identities, mcpApprovals, mcpConnections, oauthClients, projects, secretReferences, secretVersions, secrets, secretsRelations, serviceBindings, vaultGrants, vaultMembers };
1
+ import { C as vaultMembers, S as vaultGrants, _ as secretReferences, a as credentials, b as secretsRelations, c as enrollments, d as identities, f as mcpApprovals, h as projects, i as consumedTokens, l as environments, m as oauthClients, n as auditLog, o as deviceAuthorizations, p as mcpConnections, r as cappedAlerts, s as dismissedKeys, t as auditChainHead, u as environmentsRelations, v as secretVersions, x as serviceBindings, y as secrets } from "./schema-DcVkJhCf.js";
2
+ export { auditChainHead, auditLog, cappedAlerts, consumedTokens, credentials, deviceAuthorizations, dismissedKeys, enrollments, environments, environmentsRelations, identities, mcpApprovals, mcpConnections, oauthClients, projects, secretReferences, secretVersions, secrets, secretsRelations, serviceBindings, vaultGrants, vaultMembers };