@coffre/db 0.8.2 → 0.10.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.
- package/dist/connect.d.ts +1 -1
- package/dist/{database-BEnexh-3.d.ts → database-BFnO2b2P.d.ts} +1 -1
- package/dist/dialect.d.ts +1 -1
- package/dist/grants.d.ts +2 -2
- package/dist/hyperdrive.d.ts +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/log.d.ts +7 -1
- package/dist/log.js +11 -1
- package/dist/migrations/postgres/0010_handle_places.sql +2 -0
- package/dist/migrations/postgres/0011_plain_values.sql +19 -0
- package/dist/migrations/postgres/0012_sensitive_values.sql +18 -0
- package/dist/migrations/postgres/0013_contributor_role.sql +5 -0
- package/dist/migrations/postgres/0014_custom_roles.sql +4 -0
- package/dist/migrations/postgres/meta/0010_snapshot.json +2991 -0
- package/dist/migrations/postgres/meta/0011_snapshot.json +2997 -0
- package/dist/migrations/postgres/meta/0012_snapshot.json +3004 -0
- package/dist/migrations/postgres/meta/0013_snapshot.json +3004 -0
- package/dist/migrations/postgres/meta/0014_snapshot.json +3000 -0
- package/dist/migrations/postgres/meta/_journal.json +35 -0
- package/dist/migrations/sqlite/0010_handle_places.sql +2 -0
- package/dist/migrations/sqlite/0011_plain_values.sql +14 -0
- package/dist/migrations/sqlite/0012_sensitive_values.sql +15 -0
- package/dist/migrations/sqlite/0013_contributor_role.sql +28 -0
- package/dist/migrations/sqlite/0014_custom_roles.sql +27 -0
- package/dist/migrations/sqlite/meta/0010_snapshot.json +2711 -0
- package/dist/migrations/sqlite/meta/0011_snapshot.json +2718 -0
- package/dist/migrations/sqlite/meta/0012_snapshot.json +2726 -0
- package/dist/migrations/sqlite/meta/0013_snapshot.json +2726 -0
- package/dist/migrations/sqlite/meta/0014_snapshot.json +2722 -0
- package/dist/migrations/sqlite/meta/_journal.json +35 -0
- package/dist/portable.d.ts +2 -2
- package/dist/{schema-BZRkBJQZ.d.ts → schema-NBVA9q-s.d.ts} +51 -0
- package/dist/schema-sqlite.d.ts +55 -0
- package/dist/schema-sqlite.js +5 -6
- package/dist/schema-version.d.ts +1 -1
- package/dist/schema-version.js +70 -0
- package/dist/schema.d.ts +1 -1
- package/dist/schema.js +5 -7
- package/package.json +2 -2
- package/src/grants.ts +3 -2
- package/src/log.ts +16 -0
- package/src/migrations/postgres/0010_handle_places.sql +2 -0
- package/src/migrations/postgres/0011_plain_values.sql +19 -0
- package/src/migrations/postgres/0012_sensitive_values.sql +18 -0
- package/src/migrations/postgres/0013_contributor_role.sql +5 -0
- package/src/migrations/postgres/0014_custom_roles.sql +4 -0
- package/src/migrations/postgres/meta/0010_snapshot.json +2991 -0
- package/src/migrations/postgres/meta/0011_snapshot.json +2997 -0
- package/src/migrations/postgres/meta/0012_snapshot.json +3004 -0
- package/src/migrations/postgres/meta/0013_snapshot.json +3004 -0
- package/src/migrations/postgres/meta/0014_snapshot.json +3000 -0
- package/src/migrations/postgres/meta/_journal.json +35 -0
- package/src/migrations/sqlite/0010_handle_places.sql +2 -0
- package/src/migrations/sqlite/0011_plain_values.sql +14 -0
- package/src/migrations/sqlite/0012_sensitive_values.sql +15 -0
- package/src/migrations/sqlite/0013_contributor_role.sql +28 -0
- package/src/migrations/sqlite/0014_custom_roles.sql +27 -0
- package/src/migrations/sqlite/meta/0010_snapshot.json +2711 -0
- package/src/migrations/sqlite/meta/0011_snapshot.json +2718 -0
- package/src/migrations/sqlite/meta/0012_snapshot.json +2726 -0
- package/src/migrations/sqlite/meta/0013_snapshot.json +2726 -0
- package/src/migrations/sqlite/meta/0014_snapshot.json +2722 -0
- package/src/migrations/sqlite/meta/_journal.json +35 -0
- package/src/schema.sqlite.ts +15 -9
- package/src/schema.ts +15 -10
|
@@ -71,6 +71,41 @@
|
|
|
71
71
|
"when": 1792281880190,
|
|
72
72
|
"tag": "0009_handles",
|
|
73
73
|
"breakpoints": true
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
"idx": 10,
|
|
77
|
+
"version": "6",
|
|
78
|
+
"when": 1792315000277,
|
|
79
|
+
"tag": "0010_handle_places",
|
|
80
|
+
"breakpoints": true
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
"idx": 11,
|
|
84
|
+
"version": "6",
|
|
85
|
+
"when": 1792317461299,
|
|
86
|
+
"tag": "0011_plain_values",
|
|
87
|
+
"breakpoints": true
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
"idx": 12,
|
|
91
|
+
"version": "6",
|
|
92
|
+
"when": 1792340920098,
|
|
93
|
+
"tag": "0012_sensitive_values",
|
|
94
|
+
"breakpoints": true
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
"idx": 13,
|
|
98
|
+
"version": "6",
|
|
99
|
+
"when": 1792343374795,
|
|
100
|
+
"tag": "0013_contributor_role",
|
|
101
|
+
"breakpoints": true
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
"idx": 14,
|
|
105
|
+
"version": "6",
|
|
106
|
+
"when": 1792345777255,
|
|
107
|
+
"tag": "0014_custom_roles",
|
|
108
|
+
"breakpoints": true
|
|
74
109
|
}
|
|
75
110
|
]
|
|
76
111
|
}
|
package/dist/portable.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { m as schema_d_exports } from "./schema-
|
|
2
|
-
import { t as Database } from "./database-
|
|
1
|
+
import { m as schema_d_exports } from "./schema-NBVA9q-s.js";
|
|
2
|
+
import { t as Database } from "./database-BFnO2b2P.js";
|
|
3
3
|
import { t as schema_sqlite_d_exports } from "./schema-sqlite.js";
|
|
4
4
|
import { LibSQLDatabase } from "drizzle-orm/libsql";
|
|
5
5
|
//#region src/portable.d.ts
|
|
@@ -714,6 +714,40 @@ declare const secretVersions: import("drizzle-orm/pg-core").PgTableWithColumns<{
|
|
|
714
714
|
identity: undefined;
|
|
715
715
|
generated: undefined;
|
|
716
716
|
}, {}, {}>;
|
|
717
|
+
plaintext: import("drizzle-orm/pg-core").PgColumn<{
|
|
718
|
+
name: "plaintext";
|
|
719
|
+
tableName: "secret_versions";
|
|
720
|
+
dataType: "string";
|
|
721
|
+
columnType: "PgText";
|
|
722
|
+
data: string;
|
|
723
|
+
driverParam: string;
|
|
724
|
+
notNull: false;
|
|
725
|
+
hasDefault: false;
|
|
726
|
+
isPrimaryKey: false;
|
|
727
|
+
isAutoincrement: false;
|
|
728
|
+
hasRuntimeDefault: false;
|
|
729
|
+
enumValues: [string, ...string[]];
|
|
730
|
+
baseColumn: never;
|
|
731
|
+
identity: undefined;
|
|
732
|
+
generated: undefined;
|
|
733
|
+
}, {}, {}>;
|
|
734
|
+
sensitive: import("drizzle-orm/pg-core").PgColumn<{
|
|
735
|
+
name: "sensitive";
|
|
736
|
+
tableName: "secret_versions";
|
|
737
|
+
dataType: "boolean";
|
|
738
|
+
columnType: "PgBoolean";
|
|
739
|
+
data: boolean;
|
|
740
|
+
driverParam: boolean;
|
|
741
|
+
notNull: true;
|
|
742
|
+
hasDefault: true;
|
|
743
|
+
isPrimaryKey: false;
|
|
744
|
+
isAutoincrement: false;
|
|
745
|
+
hasRuntimeDefault: false;
|
|
746
|
+
enumValues: undefined;
|
|
747
|
+
baseColumn: never;
|
|
748
|
+
identity: undefined;
|
|
749
|
+
generated: undefined;
|
|
750
|
+
}, {}, {}>;
|
|
717
751
|
};
|
|
718
752
|
dialect: "pg";
|
|
719
753
|
}>;
|
|
@@ -3298,6 +3332,23 @@ declare const credentials: import("drizzle-orm/pg-core").PgTableWithColumns<{
|
|
|
3298
3332
|
identity: undefined;
|
|
3299
3333
|
generated: undefined;
|
|
3300
3334
|
}, {}, {}>;
|
|
3335
|
+
places: import("drizzle-orm/pg-core").PgColumn<{
|
|
3336
|
+
name: "places";
|
|
3337
|
+
tableName: "credentials";
|
|
3338
|
+
dataType: "string";
|
|
3339
|
+
columnType: "PgText";
|
|
3340
|
+
data: string;
|
|
3341
|
+
driverParam: string;
|
|
3342
|
+
notNull: false;
|
|
3343
|
+
hasDefault: false;
|
|
3344
|
+
isPrimaryKey: false;
|
|
3345
|
+
isAutoincrement: false;
|
|
3346
|
+
hasRuntimeDefault: false;
|
|
3347
|
+
enumValues: [string, ...string[]];
|
|
3348
|
+
baseColumn: never;
|
|
3349
|
+
identity: undefined;
|
|
3350
|
+
generated: undefined;
|
|
3351
|
+
}, {}, {}>;
|
|
3301
3352
|
label: import("drizzle-orm/pg-core").PgColumn<{
|
|
3302
3353
|
name: "label";
|
|
3303
3354
|
tableName: "credentials";
|
package/dist/schema-sqlite.d.ts
CHANGED
|
@@ -756,6 +756,42 @@ export declare const secretVersions: import("drizzle-orm/sqlite-core").SQLiteTab
|
|
|
756
756
|
}, {}, {
|
|
757
757
|
length: number | undefined;
|
|
758
758
|
}>;
|
|
759
|
+
plaintext: import("drizzle-orm/sqlite-core").SQLiteColumn<{
|
|
760
|
+
name: "plaintext";
|
|
761
|
+
tableName: "secret_versions";
|
|
762
|
+
dataType: "string";
|
|
763
|
+
columnType: "SQLiteText";
|
|
764
|
+
data: string;
|
|
765
|
+
driverParam: string;
|
|
766
|
+
notNull: false;
|
|
767
|
+
hasDefault: false;
|
|
768
|
+
isPrimaryKey: false;
|
|
769
|
+
isAutoincrement: false;
|
|
770
|
+
hasRuntimeDefault: false;
|
|
771
|
+
enumValues: [string, ...string[]];
|
|
772
|
+
baseColumn: never;
|
|
773
|
+
identity: undefined;
|
|
774
|
+
generated: undefined;
|
|
775
|
+
}, {}, {
|
|
776
|
+
length: undefined;
|
|
777
|
+
}>;
|
|
778
|
+
sensitive: import("drizzle-orm/sqlite-core").SQLiteColumn<{
|
|
779
|
+
name: string;
|
|
780
|
+
tableName: "secret_versions";
|
|
781
|
+
dataType: "boolean";
|
|
782
|
+
columnType: "SQLiteBoolean";
|
|
783
|
+
data: boolean;
|
|
784
|
+
driverParam: number;
|
|
785
|
+
notNull: true;
|
|
786
|
+
hasDefault: true;
|
|
787
|
+
isPrimaryKey: false;
|
|
788
|
+
isAutoincrement: false;
|
|
789
|
+
hasRuntimeDefault: false;
|
|
790
|
+
enumValues: undefined;
|
|
791
|
+
baseColumn: never;
|
|
792
|
+
identity: undefined;
|
|
793
|
+
generated: undefined;
|
|
794
|
+
}, {}, {}>;
|
|
759
795
|
};
|
|
760
796
|
dialect: "sqlite";
|
|
761
797
|
}>;
|
|
@@ -3427,6 +3463,25 @@ export declare const credentials: import("drizzle-orm/sqlite-core").SQLiteTableW
|
|
|
3427
3463
|
}, {}, {
|
|
3428
3464
|
length: undefined;
|
|
3429
3465
|
}>;
|
|
3466
|
+
places: import("drizzle-orm/sqlite-core").SQLiteColumn<{
|
|
3467
|
+
name: "places";
|
|
3468
|
+
tableName: "credentials";
|
|
3469
|
+
dataType: "string";
|
|
3470
|
+
columnType: "SQLiteText";
|
|
3471
|
+
data: string;
|
|
3472
|
+
driverParam: string;
|
|
3473
|
+
notNull: false;
|
|
3474
|
+
hasDefault: false;
|
|
3475
|
+
isPrimaryKey: false;
|
|
3476
|
+
isAutoincrement: false;
|
|
3477
|
+
hasRuntimeDefault: false;
|
|
3478
|
+
enumValues: [string, ...string[]];
|
|
3479
|
+
baseColumn: never;
|
|
3480
|
+
identity: undefined;
|
|
3481
|
+
generated: undefined;
|
|
3482
|
+
}, {}, {
|
|
3483
|
+
length: undefined;
|
|
3484
|
+
}>;
|
|
3430
3485
|
label: import("drizzle-orm/sqlite-core").SQLiteColumn<{
|
|
3431
3486
|
name: "label";
|
|
3432
3487
|
tableName: "credentials";
|
package/dist/schema-sqlite.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { n as relationsOf, t as ACTIVE_SUBJECT } from "./relations-BfR3JjT1.js";
|
|
2
2
|
import { asPostgres } from "./portable.js";
|
|
3
3
|
import { sql } from "drizzle-orm";
|
|
4
|
-
import { ROLE_NAMES, assignableToEnvironment } from "@coffre/core/access";
|
|
5
4
|
import { blob, check, customType, foreignKey, index, integer, primaryKey, sqliteTable, text, unique, uniqueIndex } from "drizzle-orm/sqlite-core";
|
|
6
5
|
//#region src/schema.sqlite.ts
|
|
7
6
|
/**
|
|
@@ -124,7 +123,9 @@ const secretVersions = sqliteTable("secret_versions", {
|
|
|
124
123
|
createdBy: text("created_by").notNull(),
|
|
125
124
|
recipe: text(),
|
|
126
125
|
pairId: text("pair_id"),
|
|
127
|
-
pairHalf: text("pair_half")
|
|
126
|
+
pairHalf: text("pair_half"),
|
|
127
|
+
plaintext: text(),
|
|
128
|
+
sensitive: flag("sensitive").notNull().default(false)
|
|
128
129
|
}, (table) => [
|
|
129
130
|
unique("secret_versions_secret_id_version_key").on(table.secretId, table.version),
|
|
130
131
|
check("secret_versions_version_check", sql`${table.version} > 0`),
|
|
@@ -156,8 +157,6 @@ const dismissedKeys = sqliteTable("dismissed_keys", {
|
|
|
156
157
|
foreignColumns: [environments.id]
|
|
157
158
|
}).onDelete("restrict")
|
|
158
159
|
]);
|
|
159
|
-
const ROLES = sql.raw(ROLE_NAMES.map((role) => `'${role}'`).join(", "));
|
|
160
|
-
const ENVIRONMENT_ROLES = sql.raw(ROLE_NAMES.filter(assignableToEnvironment).map((role) => `'${role}'`).join(", "));
|
|
161
160
|
const vaultMembers = sqliteTable("vault_members", {
|
|
162
161
|
principal: text().primaryKey(),
|
|
163
162
|
status: text().notNull(),
|
|
@@ -194,8 +193,7 @@ const vaultGrants = sqliteTable("vault_grants", {
|
|
|
194
193
|
}, (table) => [
|
|
195
194
|
check("vault_grants_one_place", sql`((${table.projectId} IS NULL) <> (${table.environmentId} IS NULL) AND ${table.environmentSlug} IS NULL) OR (${table.projectId} IS NULL AND ${table.environmentId} IS NULL)`),
|
|
196
195
|
check("vault_grants_environment_slug_check", sql`${table.environmentSlug} IS NULL OR (${isSlug(table.environmentSlug, 63)})`),
|
|
197
|
-
check("vault_grants_role_check", sql
|
|
198
|
-
check("vault_grants_environment_role_check", sql`(${table.environmentId} IS NULL AND ${table.environmentSlug} IS NULL) OR ${table.role} IN (${ENVIRONMENT_ROLES})`),
|
|
196
|
+
check("vault_grants_role_check", sql`length(${table.role}) BETWEEN 2 AND 32 AND ${table.role} GLOB '[a-z]*' AND ${table.role} NOT GLOB '*[^a-z0-9-]*'`),
|
|
199
197
|
unique("vault_grants_on_project").on(table.principal, table.projectId),
|
|
200
198
|
unique("vault_grants_on_environment").on(table.principal, table.environmentId),
|
|
201
199
|
unique("vault_grants_on_environment_slug").on(table.principal, table.environmentSlug),
|
|
@@ -487,6 +485,7 @@ const credentials = sqliteTable("credentials", {
|
|
|
487
485
|
principal: text().notNull(),
|
|
488
486
|
identityId: text("identity_id"),
|
|
489
487
|
scope: text(),
|
|
488
|
+
places: text(),
|
|
490
489
|
label: text(),
|
|
491
490
|
createdAt: createdAt(),
|
|
492
491
|
createdBy: text("created_by").notNull(),
|
package/dist/schema-version.d.ts
CHANGED
package/dist/schema-version.js
CHANGED
|
@@ -78,6 +78,41 @@ const KNOWN_MIGRATIONS = {
|
|
|
78
78
|
"when": 1792281879553,
|
|
79
79
|
"tag": "0009_handles",
|
|
80
80
|
"breakpoints": true
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
"idx": 10,
|
|
84
|
+
"version": "7",
|
|
85
|
+
"when": 1792314999425,
|
|
86
|
+
"tag": "0010_handle_places",
|
|
87
|
+
"breakpoints": true
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
"idx": 11,
|
|
91
|
+
"version": "7",
|
|
92
|
+
"when": 1792317460399,
|
|
93
|
+
"tag": "0011_plain_values",
|
|
94
|
+
"breakpoints": true
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
"idx": 12,
|
|
98
|
+
"version": "7",
|
|
99
|
+
"when": 1792340919452,
|
|
100
|
+
"tag": "0012_sensitive_values",
|
|
101
|
+
"breakpoints": true
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
"idx": 13,
|
|
105
|
+
"version": "7",
|
|
106
|
+
"when": 1792343374226,
|
|
107
|
+
"tag": "0013_contributor_role",
|
|
108
|
+
"breakpoints": true
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
"idx": 14,
|
|
112
|
+
"version": "7",
|
|
113
|
+
"when": 1792345776262,
|
|
114
|
+
"tag": "0014_custom_roles",
|
|
115
|
+
"breakpoints": true
|
|
81
116
|
}
|
|
82
117
|
].map((entry) => entry.tag),
|
|
83
118
|
sqlite: [
|
|
@@ -150,6 +185,41 @@ const KNOWN_MIGRATIONS = {
|
|
|
150
185
|
"when": 1792281880190,
|
|
151
186
|
"tag": "0009_handles",
|
|
152
187
|
"breakpoints": true
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
"idx": 10,
|
|
191
|
+
"version": "6",
|
|
192
|
+
"when": 1792315000277,
|
|
193
|
+
"tag": "0010_handle_places",
|
|
194
|
+
"breakpoints": true
|
|
195
|
+
},
|
|
196
|
+
{
|
|
197
|
+
"idx": 11,
|
|
198
|
+
"version": "6",
|
|
199
|
+
"when": 1792317461299,
|
|
200
|
+
"tag": "0011_plain_values",
|
|
201
|
+
"breakpoints": true
|
|
202
|
+
},
|
|
203
|
+
{
|
|
204
|
+
"idx": 12,
|
|
205
|
+
"version": "6",
|
|
206
|
+
"when": 1792340920098,
|
|
207
|
+
"tag": "0012_sensitive_values",
|
|
208
|
+
"breakpoints": true
|
|
209
|
+
},
|
|
210
|
+
{
|
|
211
|
+
"idx": 13,
|
|
212
|
+
"version": "6",
|
|
213
|
+
"when": 1792343374795,
|
|
214
|
+
"tag": "0013_contributor_role",
|
|
215
|
+
"breakpoints": true
|
|
216
|
+
},
|
|
217
|
+
{
|
|
218
|
+
"idx": 14,
|
|
219
|
+
"version": "6",
|
|
220
|
+
"when": 1792345777255,
|
|
221
|
+
"tag": "0014_custom_roles",
|
|
222
|
+
"breakpoints": true
|
|
153
223
|
}
|
|
154
224
|
].map((entry) => entry.tag)
|
|
155
225
|
};
|
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-
|
|
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
2
|
export { auditChainHead, auditLog, consumedTokens, credentials, deviceAuthorizations, dismissedKeys, environments, environmentsRelations, identities, mcpApprovals, mcpConnections, oauthClients, projects, secretReferences, secretVersions, secrets, secretsRelations, serviceBindings, vaultGrants, vaultMembers };
|
package/dist/schema.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
|
|
2
2
|
import { n as relationsOf, t as ACTIVE_SUBJECT } from "./relations-BfR3JjT1.js";
|
|
3
3
|
import { sql } from "drizzle-orm";
|
|
4
|
-
import { ROLE_NAMES, assignableToEnvironment } from "@coffre/core/access";
|
|
5
4
|
import { bigint, boolean, check, customType, foreignKey, index, integer, pgTable, primaryKey, text, timestamp, unique, uniqueIndex, uuid } from "drizzle-orm/pg-core";
|
|
6
5
|
//#region src/schema.ts
|
|
7
6
|
var schema_exports = /* @__PURE__ */ __exportAll({
|
|
@@ -129,7 +128,9 @@ const secretVersions = pgTable("secret_versions", {
|
|
|
129
128
|
createdBy: text("created_by").notNull(),
|
|
130
129
|
recipe: text(),
|
|
131
130
|
pairId: uuid("pair_id"),
|
|
132
|
-
pairHalf: text("pair_half")
|
|
131
|
+
pairHalf: text("pair_half"),
|
|
132
|
+
plaintext: text(),
|
|
133
|
+
sensitive: boolean().notNull().default(false)
|
|
133
134
|
}, (table) => [
|
|
134
135
|
unique("secret_versions_secret_id_version_key").on(table.secretId, table.version),
|
|
135
136
|
check("secret_versions_version_check", sql`${table.version} > 0`),
|
|
@@ -168,9 +169,6 @@ const dismissedKeys = pgTable("dismissed_keys", {
|
|
|
168
169
|
foreignColumns: [environments.id]
|
|
169
170
|
}).onDelete("restrict")
|
|
170
171
|
]);
|
|
171
|
-
/** The role catalogue, as SQL: every role, and those an environment may be granted. */
|
|
172
|
-
const ROLES = sql.raw(ROLE_NAMES.map((role) => `'${role}'`).join(", "));
|
|
173
|
-
const ENVIRONMENT_ROLES = sql.raw(ROLE_NAMES.filter(assignableToEnvironment).map((role) => `'${role}'`).join(", "));
|
|
174
172
|
/**
|
|
175
173
|
* The vault's member directory: everyone it has admitted, written by the
|
|
176
174
|
* vault alone, read by both. A principal with no row is no member.
|
|
@@ -219,8 +217,7 @@ const vaultGrants = pgTable("vault_grants", {
|
|
|
219
217
|
}, (table) => [
|
|
220
218
|
check("vault_grants_one_place", sql`((${table.projectId} IS NULL) <> (${table.environmentId} IS NULL) AND ${table.environmentSlug} IS NULL) OR (${table.projectId} IS NULL AND ${table.environmentId} IS NULL)`),
|
|
221
219
|
check("vault_grants_environment_slug_check", sql`${table.environmentSlug} IS NULL OR ${table.environmentSlug} ~ '^[a-z0-9][a-z0-9-]{0,62}$'`),
|
|
222
|
-
check("vault_grants_role_check", sql`${table.role}
|
|
223
|
-
check("vault_grants_environment_role_check", sql`(${table.environmentId} IS NULL AND ${table.environmentSlug} IS NULL) OR ${table.role} IN (${ENVIRONMENT_ROLES})`),
|
|
220
|
+
check("vault_grants_role_check", sql`${table.role} ~ '^[a-z][a-z0-9-]{1,31}$'`),
|
|
224
221
|
unique("vault_grants_on_project").on(table.principal, table.projectId),
|
|
225
222
|
unique("vault_grants_on_environment").on(table.principal, table.environmentId),
|
|
226
223
|
unique("vault_grants_on_environment_slug").on(table.principal, table.environmentSlug),
|
|
@@ -553,6 +550,7 @@ const credentials = pgTable("credentials", {
|
|
|
553
550
|
principal: text().notNull(),
|
|
554
551
|
identityId: uuid("identity_id"),
|
|
555
552
|
scope: text(),
|
|
553
|
+
places: text(),
|
|
556
554
|
label: text(),
|
|
557
555
|
createdAt: createdAt(),
|
|
558
556
|
createdBy: text("created_by").notNull(),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@coffre/db",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"description": "coffre's database: the schema, its migrations and the connections, on Postgres or SQLite.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -79,7 +79,7 @@
|
|
|
79
79
|
"drizzle-orm": "0.45.2",
|
|
80
80
|
"pg": "8.16.3",
|
|
81
81
|
"pg-connection-string": "2.14.0",
|
|
82
|
-
"@coffre/core": "0.
|
|
82
|
+
"@coffre/core": "0.10.0"
|
|
83
83
|
},
|
|
84
84
|
"devDependencies": {
|
|
85
85
|
"@types/node": "26.1.1",
|
package/src/grants.ts
CHANGED
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
type Conversion,
|
|
10
10
|
type ConversionInput,
|
|
11
11
|
type InstanceRole,
|
|
12
|
+
type BuiltinRole,
|
|
12
13
|
type Role,
|
|
13
14
|
type Scope,
|
|
14
15
|
} from '@coffre/core/access';
|
|
@@ -129,10 +130,10 @@ export function everyProjectConversion(
|
|
|
129
130
|
role: person ? role : 'member',
|
|
130
131
|
everyProject: live
|
|
131
132
|
.filter((grant) => grant.projectId === null && grant.environmentId === null)
|
|
132
|
-
.map((grant) => ({ environmentSlug: grant.environmentSlug, role: grant.role as
|
|
133
|
+
.map((grant) => ({ environmentSlug: grant.environmentSlug, role: grant.role as BuiltinRole, expiresAt: grant.expiresAt })),
|
|
133
134
|
grants: live
|
|
134
135
|
.filter((grant) => grant.projectId !== null)
|
|
135
|
-
.map((grant) => ({ projectId: grant.projectId, environmentId: grant.environmentId, role: grant.role as
|
|
136
|
+
.map((grant) => ({ projectId: grant.projectId, environmentId: grant.environmentId, role: grant.role as BuiltinRole, expiresAt: grant.expiresAt })),
|
|
136
137
|
projects,
|
|
137
138
|
});
|
|
138
139
|
}
|
package/src/log.ts
CHANGED
|
@@ -283,6 +283,22 @@ export async function newestVaultEntries(db: Queryable, action: string, limit: n
|
|
|
283
283
|
return rows as StoredEntry[];
|
|
284
284
|
}
|
|
285
285
|
|
|
286
|
+
/**
|
|
287
|
+
* The number of the newest entry in the vault's name, allowed, of one
|
|
288
|
+
* `action`, or null for none: whether one was appended since, and nothing
|
|
289
|
+
* of what it says, so its MAC is not checked. One indexed read.
|
|
290
|
+
*/
|
|
291
|
+
export async function newestVaultSeq(db: Queryable, action: string): Promise<bigint | null> {
|
|
292
|
+
const { auditLog } = tablesOf(db);
|
|
293
|
+
const [row] = await db
|
|
294
|
+
.select({ seq: auditLog.seq })
|
|
295
|
+
.from(auditLog)
|
|
296
|
+
.where(and(eq(auditLog.author, 'vault'), eq(auditLog.action, action), eq(auditLog.decision, 'allow')))
|
|
297
|
+
.orderBy(desc(auditLog.seq))
|
|
298
|
+
.limit(1);
|
|
299
|
+
return (row?.seq as bigint | undefined) ?? null;
|
|
300
|
+
}
|
|
301
|
+
|
|
286
302
|
/** How many entries in its name the vault reads back, a page at a time, for its own newest of a kind (`newestAuthentic`). */
|
|
287
303
|
export const LOOK_BACK = { page: 32, pages: 32 };
|
|
288
304
|
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
-- A handle's places (0.9): the environments it was made for, by id and whether as @me, which the proxy's stable URL resolves to. A nullable column the release before neither reads nor writes; the app sets it when it makes a handle, and never after (no UPDATE grant).
|
|
2
|
+
ALTER TABLE "credentials" ADD COLUMN "places" text;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
-- Plain values (0.9): a version of a key marked not secret holds its value in the clear too. Nullable, so the release before writes on as it did.
|
|
2
|
+
ALTER TABLE "secret_versions" ADD COLUMN "plaintext" text;--> statement-breakpoint
|
|
3
|
+
-- A version is still only ever erased, and an erased one holds no value, in the clear or not.
|
|
4
|
+
CREATE OR REPLACE FUNCTION secret_versions_erase_only() RETURNS trigger LANGUAGE plpgsql AS $$
|
|
5
|
+
BEGIN
|
|
6
|
+
IF octet_length(NEW.ciphertext) <> 0 OR octet_length(NEW.wrapped_dek) <> 0 OR NEW.plaintext IS NOT NULL
|
|
7
|
+
OR (NEW.id, NEW.secret_id, NEW.version, NEW.envelope_version, NEW.iv, NEW.auth_tag,
|
|
8
|
+
NEW.kek_provider, NEW.kek_id, NEW.kek_version, NEW.created_at, NEW.created_by,
|
|
9
|
+
NEW.recipe, NEW.pair_id, NEW.pair_half)
|
|
10
|
+
IS DISTINCT FROM
|
|
11
|
+
(OLD.id, OLD.secret_id, OLD.version, OLD.envelope_version, OLD.iv, OLD.auth_tag,
|
|
12
|
+
OLD.kek_provider, OLD.kek_id, OLD.kek_version, OLD.created_at, OLD.created_by,
|
|
13
|
+
OLD.recipe, OLD.pair_id, OLD.pair_half) THEN
|
|
14
|
+
RAISE EXCEPTION 'a secret version is only ever erased' USING ERRCODE = 'insufficient_privilege';
|
|
15
|
+
END IF;
|
|
16
|
+
RETURN NEW;
|
|
17
|
+
END
|
|
18
|
+
$$;--> statement-breakpoint
|
|
19
|
+
GRANT UPDATE (plaintext) ON secret_versions TO coffre_app;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
-- Sensitive values (0.10): a version never handed back to a person, which the vault's wrap of its data key binds. Defaults to false, so the release before writes on as it did.
|
|
2
|
+
ALTER TABLE "secret_versions" ADD COLUMN "sensitive" boolean DEFAULT false NOT NULL;--> statement-breakpoint
|
|
3
|
+
-- A version is still only ever erased: its sensitivity with the rest of it.
|
|
4
|
+
CREATE OR REPLACE FUNCTION secret_versions_erase_only() RETURNS trigger LANGUAGE plpgsql AS $$
|
|
5
|
+
BEGIN
|
|
6
|
+
IF octet_length(NEW.ciphertext) <> 0 OR octet_length(NEW.wrapped_dek) <> 0 OR NEW.plaintext IS NOT NULL
|
|
7
|
+
OR (NEW.id, NEW.secret_id, NEW.version, NEW.envelope_version, NEW.iv, NEW.auth_tag,
|
|
8
|
+
NEW.kek_provider, NEW.kek_id, NEW.kek_version, NEW.created_at, NEW.created_by,
|
|
9
|
+
NEW.recipe, NEW.pair_id, NEW.pair_half, NEW.sensitive)
|
|
10
|
+
IS DISTINCT FROM
|
|
11
|
+
(OLD.id, OLD.secret_id, OLD.version, OLD.envelope_version, OLD.iv, OLD.auth_tag,
|
|
12
|
+
OLD.kek_provider, OLD.kek_id, OLD.kek_version, OLD.created_at, OLD.created_by,
|
|
13
|
+
OLD.recipe, OLD.pair_id, OLD.pair_half, OLD.sensitive) THEN
|
|
14
|
+
RAISE EXCEPTION 'a secret version is only ever erased' USING ERRCODE = 'insufficient_privilege';
|
|
15
|
+
END IF;
|
|
16
|
+
RETURN NEW;
|
|
17
|
+
END
|
|
18
|
+
$$;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
-- The Contributor role (0.10): use and write, never read. The role checks widen to it, which the release before never grants.
|
|
2
|
+
ALTER TABLE "vault_grants" DROP CONSTRAINT "vault_grants_role_check";--> statement-breakpoint
|
|
3
|
+
ALTER TABLE "vault_grants" DROP CONSTRAINT "vault_grants_environment_role_check";--> statement-breakpoint
|
|
4
|
+
ALTER TABLE "vault_grants" ADD CONSTRAINT "vault_grants_role_check" CHECK ("vault_grants"."role" IN ('viewer', 'contributor', 'developer', 'maintainer', 'access-manager', 'auditor', 'owner'));--> statement-breakpoint
|
|
5
|
+
ALTER TABLE "vault_grants" ADD CONSTRAINT "vault_grants_environment_role_check" CHECK (("vault_grants"."environment_id" IS NULL AND "vault_grants"."environment_slug" IS NULL) OR "vault_grants"."role" IN ('viewer', 'contributor', 'developer', 'auditor'));
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
-- Roles an Owner makes (0.10): a grant names a role by its id, which the vault's policy defines; which of them an environment may be granted, the vault decides. The checks widen: the release before grants only the roles it ships.
|
|
2
|
+
ALTER TABLE "vault_grants" DROP CONSTRAINT "vault_grants_environment_role_check";--> statement-breakpoint
|
|
3
|
+
ALTER TABLE "vault_grants" DROP CONSTRAINT "vault_grants_role_check";--> statement-breakpoint
|
|
4
|
+
ALTER TABLE "vault_grants" ADD CONSTRAINT "vault_grants_role_check" CHECK ("vault_grants"."role" ~ '^[a-z][a-z0-9-]{1,31}$');
|