@coffre/db 0.0.0-stage → 0.1.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/LICENSE +21 -0
- package/README.md +14 -2
- package/dist/commits-BuW-NL3n.js +30 -0
- package/dist/connect.d.ts +21 -0
- package/dist/connect.js +155 -0
- package/dist/database-CWpo5aF0.d.ts +39 -0
- package/dist/dialect.d.ts +88 -0
- package/dist/dialect.js +128 -0
- package/dist/hyperdrive.d.ts +32 -0
- package/dist/hyperdrive.js +53 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +34 -0
- package/dist/log.d.ts +72 -0
- package/dist/log.js +133 -0
- package/dist/migrate.d.ts +10 -0
- package/dist/migrate.js +129 -0
- package/dist/migrations/postgres/0000_baseline.sql +502 -0
- package/dist/migrations/postgres/meta/0000_snapshot.json +1939 -0
- package/dist/migrations/postgres/meta/_journal.json +13 -0
- package/dist/migrations/sqlite/0000_baseline.sql +293 -0
- package/dist/migrations/sqlite/meta/0000_snapshot.json +1811 -0
- package/dist/migrations/sqlite/meta/_journal.json +13 -0
- package/dist/portable.d.ts +33 -0
- package/dist/portable.js +12 -0
- package/dist/relations-DqgxtlKu.js +58 -0
- package/dist/rolldown-runtime-D7D4PA-g.js +13 -0
- package/dist/schema-Cd4WOnB5.d.ts +2503 -0
- package/dist/schema-sqlite.d.ts +2587 -0
- package/dist/schema-sqlite.js +401 -0
- package/dist/schema-version.d.ts +11 -0
- package/dist/schema-version.js +16 -0
- package/dist/schema.d.ts +2 -0
- package/dist/schema.js +448 -0
- package/package.json +91 -3
- package/src/baseline/postgres.sql +238 -0
- package/src/baseline/sqlite.sql +27 -0
- package/src/baseline.ts +104 -0
- package/src/commits.ts +47 -0
- package/src/connect.ts +168 -0
- package/src/database.ts +63 -0
- package/src/dialect.ts +174 -0
- package/src/drizzle.postgres.config.ts +7 -0
- package/src/drizzle.sqlite.config.ts +7 -0
- package/src/hyperdrive.ts +62 -0
- package/src/log.ts +177 -0
- package/src/migrate-main.ts +8 -0
- package/src/migrate.ts +206 -0
- package/src/migrations/postgres/0000_baseline.sql +502 -0
- package/src/migrations/postgres/meta/0000_snapshot.json +1939 -0
- package/src/migrations/postgres/meta/_journal.json +13 -0
- package/src/migrations/sqlite/0000_baseline.sql +293 -0
- package/src/migrations/sqlite/meta/0000_snapshot.json +1811 -0
- package/src/migrations/sqlite/meta/_journal.json +13 -0
- package/src/portable.ts +54 -0
- package/src/relations.ts +53 -0
- package/src/schema-version.ts +13 -0
- package/src/schema.sqlite.ts +511 -0
- package/src/schema.ts +548 -0
- package/src/verify-runtime.ts +120 -0
|
@@ -0,0 +1,401 @@
|
|
|
1
|
+
import { n as relationsOf, t as ACTIVE_SUBJECT } from "./relations-DqgxtlKu.js";
|
|
2
|
+
import { asPostgres } from "./portable.js";
|
|
3
|
+
import { sql } from "drizzle-orm";
|
|
4
|
+
import { ROLE_NAMES, assignableToEnvironment } from "@coffre/core/access";
|
|
5
|
+
import { blob, check, customType, foreignKey, index, integer, primaryKey, sqliteTable, text, unique, uniqueIndex } from "drizzle-orm/sqlite-core";
|
|
6
|
+
//#region src/schema.sqlite.ts
|
|
7
|
+
/**
|
|
8
|
+
* The schema in schema.ts, for SQLite (through libsql). Same tables,
|
|
9
|
+
* columns, keys and row types (portable.ts checks); only the storage
|
|
10
|
+
* differs:
|
|
11
|
+
*
|
|
12
|
+
* - Ids and strings are `text`, with no default for ids: the application
|
|
13
|
+
* makes every id.
|
|
14
|
+
* - Bytes are `blob`.
|
|
15
|
+
* - Times are integer milliseconds since the epoch.
|
|
16
|
+
* - Patterns are checked with GLOB, which is case-sensitive and needs no
|
|
17
|
+
* extension, rather than a regular expression.
|
|
18
|
+
*/
|
|
19
|
+
const bytes = (name) => blob(name, { mode: "buffer" });
|
|
20
|
+
/** A 64-bit integer read as a bigint, like Postgres's bigint in 'bigint' mode. */
|
|
21
|
+
const int64 = customType({
|
|
22
|
+
dataType: () => "integer",
|
|
23
|
+
fromDriver: (value) => BigInt(value)
|
|
24
|
+
});
|
|
25
|
+
const time = (name) => integer(name, { mode: "timestamp_ms" });
|
|
26
|
+
const now = sql`(CAST(unixepoch('subsec') * 1000 AS INTEGER))`;
|
|
27
|
+
const createdAt = () => time("created_at").notNull().default(now);
|
|
28
|
+
const flag = (name) => integer(name, { mode: "boolean" });
|
|
29
|
+
/** `^[a-z0-9][a-z0-9-]{0,max-1}$`, in GLOB. */
|
|
30
|
+
const isSlug = (column, max) => sql`length(${column}) BETWEEN 1 AND ${sql.raw(String(max))} AND ${column} GLOB '[a-z0-9]*' AND ${column} NOT GLOB '*[^a-z0-9-]*'`;
|
|
31
|
+
const projects = sqliteTable("projects", {
|
|
32
|
+
id: text().primaryKey(),
|
|
33
|
+
slug: text().notNull(),
|
|
34
|
+
name: text().notNull(),
|
|
35
|
+
createdAt: createdAt(),
|
|
36
|
+
archivedAt: time("archived_at")
|
|
37
|
+
}, (table) => [unique("projects_slug_key").on(table.slug), check("projects_slug_check", isSlug(table.slug, 63))]);
|
|
38
|
+
const environments = sqliteTable("environments", {
|
|
39
|
+
id: text().primaryKey(),
|
|
40
|
+
projectId: text("project_id").notNull(),
|
|
41
|
+
slug: text().notNull(),
|
|
42
|
+
name: text().notNull(),
|
|
43
|
+
createdAt: createdAt(),
|
|
44
|
+
archivedAt: time("archived_at")
|
|
45
|
+
}, (table) => [
|
|
46
|
+
unique("environments_project_id_slug_key").on(table.projectId, table.slug),
|
|
47
|
+
unique("environments_project_scoped").on(table.id, table.projectId),
|
|
48
|
+
check("environments_slug_check", isSlug(table.slug, 63)),
|
|
49
|
+
foreignKey({
|
|
50
|
+
name: "environments_project_id_fkey",
|
|
51
|
+
columns: [table.projectId],
|
|
52
|
+
foreignColumns: [projects.id]
|
|
53
|
+
}).onDelete("restrict")
|
|
54
|
+
]);
|
|
55
|
+
const secrets = sqliteTable("secrets", {
|
|
56
|
+
id: text().primaryKey(),
|
|
57
|
+
projectId: text("project_id").notNull(),
|
|
58
|
+
environmentId: text("environment_id").notNull(),
|
|
59
|
+
key: text().notNull(),
|
|
60
|
+
createdAt: createdAt(),
|
|
61
|
+
updatedAt: time("updated_at").notNull().default(now),
|
|
62
|
+
currentVersionId: text("current_version_id").references(() => secretVersions.id, { onDelete: "no action" }),
|
|
63
|
+
currentVersion: integer("current_version").notNull().default(0),
|
|
64
|
+
archivedAt: time("archived_at")
|
|
65
|
+
}, (table) => [
|
|
66
|
+
unique("secrets_project_id_environment_id_key_key").on(table.projectId, table.environmentId, table.key),
|
|
67
|
+
check("secrets_key_check", sql`length(${table.key}) BETWEEN 1 AND 128 AND ${table.key} GLOB '[A-Za-z_]*' AND ${table.key} NOT GLOB '*[^A-Za-z0-9_]*'`),
|
|
68
|
+
foreignKey({
|
|
69
|
+
name: "secrets_project_id_fkey",
|
|
70
|
+
columns: [table.projectId],
|
|
71
|
+
foreignColumns: [projects.id]
|
|
72
|
+
}).onDelete("restrict"),
|
|
73
|
+
foreignKey({
|
|
74
|
+
name: "secrets_environment_id_fkey",
|
|
75
|
+
columns: [table.environmentId],
|
|
76
|
+
foreignColumns: [environments.id]
|
|
77
|
+
}).onDelete("restrict"),
|
|
78
|
+
foreignKey({
|
|
79
|
+
name: "secrets_environment_in_project",
|
|
80
|
+
columns: [table.environmentId, table.projectId],
|
|
81
|
+
foreignColumns: [environments.id, environments.projectId]
|
|
82
|
+
}),
|
|
83
|
+
index("secrets_lookup_idx").on(table.projectId, table.environmentId, table.key)
|
|
84
|
+
]);
|
|
85
|
+
const secretVersions = sqliteTable("secret_versions", {
|
|
86
|
+
id: text().primaryKey(),
|
|
87
|
+
secretId: text("secret_id").notNull(),
|
|
88
|
+
version: integer().notNull(),
|
|
89
|
+
envelopeVersion: integer("envelope_version").notNull(),
|
|
90
|
+
ciphertext: bytes("ciphertext").notNull(),
|
|
91
|
+
iv: bytes("iv").notNull(),
|
|
92
|
+
authTag: bytes("auth_tag").notNull(),
|
|
93
|
+
wrappedDek: bytes("wrapped_dek").notNull(),
|
|
94
|
+
kekProvider: text("kek_provider").notNull(),
|
|
95
|
+
kekId: text("kek_id").notNull(),
|
|
96
|
+
kekVersion: text("kek_version").notNull(),
|
|
97
|
+
createdAt: createdAt(),
|
|
98
|
+
createdBy: text("created_by").notNull()
|
|
99
|
+
}, (table) => [
|
|
100
|
+
unique("secret_versions_secret_id_version_key").on(table.secretId, table.version),
|
|
101
|
+
check("secret_versions_version_check", sql`${table.version} > 0`),
|
|
102
|
+
check("secret_versions_iv_check", sql`octet_length(${table.iv}) = 12`),
|
|
103
|
+
check("secret_versions_auth_tag_check", sql`octet_length(${table.authTag}) = 16`),
|
|
104
|
+
foreignKey({
|
|
105
|
+
name: "secret_versions_secret_id_fkey",
|
|
106
|
+
columns: [table.secretId],
|
|
107
|
+
foreignColumns: [secrets.id]
|
|
108
|
+
}).onDelete("restrict"),
|
|
109
|
+
index("secret_versions_secret_idx").on(table.secretId, table.version)
|
|
110
|
+
]);
|
|
111
|
+
const ROLES = sql.raw(ROLE_NAMES.map((role) => `'${role}'`).join(", "));
|
|
112
|
+
const ENVIRONMENT_ROLES = sql.raw(ROLE_NAMES.filter(assignableToEnvironment).map((role) => `'${role}'`).join(", "));
|
|
113
|
+
const vaultMembers = sqliteTable("vault_members", {
|
|
114
|
+
principal: text().primaryKey(),
|
|
115
|
+
status: text().notNull(),
|
|
116
|
+
owner: flag("owner").notNull().default(false),
|
|
117
|
+
generation: integer().notNull().default(0),
|
|
118
|
+
createdAt: integer("created_at", { mode: "number" }).notNull(),
|
|
119
|
+
createdBy: text("created_by").notNull(),
|
|
120
|
+
statusChangedAt: integer("status_changed_at", { mode: "number" }).notNull(),
|
|
121
|
+
statusChangedBy: text("status_changed_by").notNull(),
|
|
122
|
+
accessSeq: int64("access_seq").notNull(),
|
|
123
|
+
mac: bytes("mac").notNull()
|
|
124
|
+
}, (table) => [
|
|
125
|
+
check("vault_members_mac_check", sql`octet_length(${table.mac}) = 32`),
|
|
126
|
+
check("vault_members_principal_check", sql`(${table.principal} GLOB 'user:?*' OR ${table.principal} GLOB 'token:?*' OR ${table.principal} GLOB 'sync:?*')
|
|
127
|
+
AND substr(${table.principal}, instr(${table.principal}, ':') + 1, 1) <> ':'
|
|
128
|
+
AND instr(${table.principal}, ' ') = 0 AND instr(${table.principal}, char(9)) = 0
|
|
129
|
+
AND instr(${table.principal}, char(10)) = 0 AND instr(${table.principal}, char(13)) = 0`),
|
|
130
|
+
check("vault_members_user_lowercase", sql`${table.principal} NOT LIKE 'user:%' OR ${table.principal} = lower(${table.principal})`),
|
|
131
|
+
check("vault_members_status_check", sql`${table.status} IN ('active', 'removed')`),
|
|
132
|
+
check("vault_members_owner_check", sql`NOT ${table.owner} OR (${table.status} = 'active' AND ${table.principal} LIKE 'user:%')`),
|
|
133
|
+
check("vault_members_generation_check", sql`${table.generation} >= 0`)
|
|
134
|
+
]);
|
|
135
|
+
const vaultGrants = sqliteTable("vault_grants", {
|
|
136
|
+
principal: text().notNull(),
|
|
137
|
+
projectId: text("project_id"),
|
|
138
|
+
environmentId: text("environment_id"),
|
|
139
|
+
role: text().notNull(),
|
|
140
|
+
expiresAt: integer("expires_at", { mode: "number" }),
|
|
141
|
+
grantedAt: integer("granted_at", { mode: "number" }).notNull(),
|
|
142
|
+
grantedBy: text("granted_by").notNull()
|
|
143
|
+
}, (table) => [
|
|
144
|
+
check("vault_grants_one_place", sql`(${table.projectId} IS NULL) <> (${table.environmentId} IS NULL)`),
|
|
145
|
+
check("vault_grants_role_check", sql`${table.role} IN (${ROLES})`),
|
|
146
|
+
check("vault_grants_environment_role_check", sql`${table.environmentId} IS NULL OR ${table.role} IN (${ENVIRONMENT_ROLES})`),
|
|
147
|
+
unique("vault_grants_on_project").on(table.principal, table.projectId),
|
|
148
|
+
unique("vault_grants_on_environment").on(table.principal, table.environmentId),
|
|
149
|
+
foreignKey({
|
|
150
|
+
name: "vault_grants_principal_fkey",
|
|
151
|
+
columns: [table.principal],
|
|
152
|
+
foreignColumns: [vaultMembers.principal]
|
|
153
|
+
}).onDelete("restrict"),
|
|
154
|
+
foreignKey({
|
|
155
|
+
name: "vault_grants_project_id_fkey",
|
|
156
|
+
columns: [table.projectId],
|
|
157
|
+
foreignColumns: [projects.id]
|
|
158
|
+
}).onDelete("restrict"),
|
|
159
|
+
foreignKey({
|
|
160
|
+
name: "vault_grants_environment_id_fkey",
|
|
161
|
+
columns: [table.environmentId],
|
|
162
|
+
foreignColumns: [environments.id]
|
|
163
|
+
}).onDelete("restrict")
|
|
164
|
+
]);
|
|
165
|
+
const auditLog = sqliteTable("audit_log", {
|
|
166
|
+
seq: int64("seq").primaryKey(),
|
|
167
|
+
author: text().notNull(),
|
|
168
|
+
keyId: text("key_id").notNull(),
|
|
169
|
+
occurredAt: integer("occurred_at", { mode: "number" }).notNull(),
|
|
170
|
+
actor: text().notNull(),
|
|
171
|
+
action: text().notNull(),
|
|
172
|
+
decision: text().notNull(),
|
|
173
|
+
code: text(),
|
|
174
|
+
subjectPrincipal: text("subject_principal"),
|
|
175
|
+
projectId: text("project_id"),
|
|
176
|
+
environmentId: text("environment_id"),
|
|
177
|
+
secretId: text("secret_id"),
|
|
178
|
+
secretVersionId: text("secret_version_id"),
|
|
179
|
+
operationId: text("operation_id"),
|
|
180
|
+
requestId: text("request_id"),
|
|
181
|
+
sourceIp: text("source_ip"),
|
|
182
|
+
relatedSeq: int64("related_seq"),
|
|
183
|
+
metadata: text().notNull().default("{}"),
|
|
184
|
+
prevHash: bytes("prev_hash").notNull(),
|
|
185
|
+
mac: bytes("mac").notNull(),
|
|
186
|
+
hash: bytes("hash").notNull()
|
|
187
|
+
}, (table) => [
|
|
188
|
+
check("audit_log_author_check", sql`${table.author} IN ('app', 'vault')`),
|
|
189
|
+
check("audit_log_actor_check", sql`${table.actor} GLOB 'user:?*' OR ${table.actor} GLOB 'token:?*' OR ${table.actor} GLOB 'sync:?*' OR ${table.actor} GLOB 'system:?*'`),
|
|
190
|
+
check("audit_log_decision_check", sql`${table.decision} IN ('allow', 'deny')`),
|
|
191
|
+
check("audit_log_metadata_check", sql`json_valid(${table.metadata})`),
|
|
192
|
+
check("audit_log_prev_hash_check", sql`octet_length(${table.prevHash}) = 32`),
|
|
193
|
+
check("audit_log_mac_check", sql`octet_length(${table.mac}) = 32`),
|
|
194
|
+
check("audit_log_hash_check", sql`octet_length(${table.hash}) = 32`),
|
|
195
|
+
foreignKey({
|
|
196
|
+
name: "audit_log_project_id_fkey",
|
|
197
|
+
columns: [table.projectId],
|
|
198
|
+
foreignColumns: [projects.id]
|
|
199
|
+
}).onDelete("restrict"),
|
|
200
|
+
foreignKey({
|
|
201
|
+
name: "audit_log_environment_id_fkey",
|
|
202
|
+
columns: [table.environmentId],
|
|
203
|
+
foreignColumns: [environments.id]
|
|
204
|
+
}).onDelete("restrict"),
|
|
205
|
+
foreignKey({
|
|
206
|
+
name: "audit_log_secret_id_fkey",
|
|
207
|
+
columns: [table.secretId],
|
|
208
|
+
foreignColumns: [secrets.id]
|
|
209
|
+
}).onDelete("restrict"),
|
|
210
|
+
foreignKey({
|
|
211
|
+
name: "audit_log_secret_version_id_fkey",
|
|
212
|
+
columns: [table.secretVersionId],
|
|
213
|
+
foreignColumns: [secretVersions.id]
|
|
214
|
+
}).onDelete("restrict"),
|
|
215
|
+
foreignKey({
|
|
216
|
+
name: "audit_log_related_seq_fkey",
|
|
217
|
+
columns: [table.relatedSeq],
|
|
218
|
+
foreignColumns: [table.seq]
|
|
219
|
+
}).onDelete("restrict"),
|
|
220
|
+
index("audit_log_project_idx").on(table.projectId, table.seq),
|
|
221
|
+
index("audit_log_environment_idx").on(table.environmentId, table.seq),
|
|
222
|
+
index("audit_log_secret_idx").on(table.secretId, table.seq),
|
|
223
|
+
index("audit_log_actor_idx").on(table.actor, table.seq),
|
|
224
|
+
index("audit_log_operation_idx").on(table.operationId, table.seq),
|
|
225
|
+
index("audit_log_action_idx").on(table.author, table.action, table.seq),
|
|
226
|
+
index("audit_log_releases_idx").on(table.author, table.actor, table.action, table.decision, table.occurredAt),
|
|
227
|
+
index("audit_log_subject_idx").on(table.author, table.subjectPrincipal, table.seq)
|
|
228
|
+
]);
|
|
229
|
+
const auditChainHead = sqliteTable("audit_chain_head", {
|
|
230
|
+
onlyRow: flag("only_row").primaryKey().default(true),
|
|
231
|
+
nextSeq: int64("next_seq").notNull().default(sql`0`),
|
|
232
|
+
headHash: bytes("head_hash").notNull()
|
|
233
|
+
}, (table) => [
|
|
234
|
+
check("audit_chain_head_only_row_check", sql`${table.onlyRow}`),
|
|
235
|
+
check("audit_chain_head_next_seq_check", sql`${table.nextSeq} >= 0`),
|
|
236
|
+
check("audit_chain_head_head_hash_check", sql`octet_length(${table.headHash}) = 32`)
|
|
237
|
+
]);
|
|
238
|
+
const identities = sqliteTable("identities", {
|
|
239
|
+
id: text().primaryKey(),
|
|
240
|
+
provider: text().notNull(),
|
|
241
|
+
authMac: bytes("auth_mac").notNull(),
|
|
242
|
+
subject: text().notNull(),
|
|
243
|
+
issuerHash: text("issuer_hash").notNull(),
|
|
244
|
+
generation: integer().notNull(),
|
|
245
|
+
principal: text().notNull(),
|
|
246
|
+
email: text(),
|
|
247
|
+
createdAt: createdAt(),
|
|
248
|
+
createdBy: text("created_by").notNull(),
|
|
249
|
+
lastSignInAt: time("last_sign_in_at"),
|
|
250
|
+
revokedAt: time("revoked_at"),
|
|
251
|
+
revokedBy: text("revoked_by"),
|
|
252
|
+
activeSubject: text("active_subject").generatedAlwaysAs(ACTIVE_SUBJECT, { mode: "stored" })
|
|
253
|
+
}, (table) => [
|
|
254
|
+
check("identities_principal_check", sql`${table.principal} LIKE 'user:%'`),
|
|
255
|
+
check("identities_provider_check", isSlug(table.provider, 32)),
|
|
256
|
+
check("identities_auth_mac_check", sql`octet_length(${table.authMac}) = 32`),
|
|
257
|
+
unique("identities_member_generation_key").on(table.id, table.principal, table.generation),
|
|
258
|
+
foreignKey({
|
|
259
|
+
name: "identities_principal_fkey",
|
|
260
|
+
columns: [table.principal],
|
|
261
|
+
foreignColumns: [vaultMembers.principal]
|
|
262
|
+
}).onDelete("restrict"),
|
|
263
|
+
uniqueIndex("identities_active_subject").on(table.provider, table.issuerHash, table.activeSubject),
|
|
264
|
+
index("identities_principal_idx").on(table.principal, table.generation)
|
|
265
|
+
]);
|
|
266
|
+
const credentials = sqliteTable("credentials", {
|
|
267
|
+
id: text().primaryKey(),
|
|
268
|
+
kind: text().notNull(),
|
|
269
|
+
authMac: bytes("auth_mac").notNull(),
|
|
270
|
+
tokenHash: bytes("token_hash").notNull(),
|
|
271
|
+
tokenHint: text("token_hint").notNull(),
|
|
272
|
+
generation: integer().notNull(),
|
|
273
|
+
principal: text().notNull(),
|
|
274
|
+
identityId: text("identity_id"),
|
|
275
|
+
label: text(),
|
|
276
|
+
createdAt: createdAt(),
|
|
277
|
+
createdBy: text("created_by").notNull(),
|
|
278
|
+
expiresAt: time("expires_at").notNull(),
|
|
279
|
+
lastUsedAt: time("last_used_at"),
|
|
280
|
+
lastUsedIp: text("last_used_ip"),
|
|
281
|
+
revokedAt: time("revoked_at"),
|
|
282
|
+
revokedBy: text("revoked_by")
|
|
283
|
+
}, (table) => [
|
|
284
|
+
unique("credentials_token_hash_key").on(table.tokenHash),
|
|
285
|
+
check("credentials_kind_check", sql`${table.kind} IN ('browser', 'cli', 'service')`),
|
|
286
|
+
check("credentials_principal_check", sql`${table.principal} LIKE 'user:%' OR ${table.principal} LIKE 'token:%'`),
|
|
287
|
+
check("credentials_kind_matches_principal", sql`(${table.kind} = 'service') = (${table.principal} LIKE 'token:%')`),
|
|
288
|
+
check("credentials_token_hash_check", sql`octet_length(${table.tokenHash}) = 32`),
|
|
289
|
+
check("credentials_auth_mac_check", sql`octet_length(${table.authMac}) = 32`),
|
|
290
|
+
foreignKey({
|
|
291
|
+
name: "credentials_principal_fkey",
|
|
292
|
+
columns: [table.principal],
|
|
293
|
+
foreignColumns: [vaultMembers.principal]
|
|
294
|
+
}).onDelete("restrict"),
|
|
295
|
+
foreignKey({
|
|
296
|
+
name: "credentials_identity_id_fkey",
|
|
297
|
+
columns: [
|
|
298
|
+
table.identityId,
|
|
299
|
+
table.principal,
|
|
300
|
+
table.generation
|
|
301
|
+
],
|
|
302
|
+
foreignColumns: [
|
|
303
|
+
identities.id,
|
|
304
|
+
identities.principal,
|
|
305
|
+
identities.generation
|
|
306
|
+
]
|
|
307
|
+
}).onDelete("restrict"),
|
|
308
|
+
index("credentials_principal_idx").on(table.principal, table.generation)
|
|
309
|
+
]);
|
|
310
|
+
const deviceAuthorizations = sqliteTable("device_authorizations", {
|
|
311
|
+
id: text().primaryKey(),
|
|
312
|
+
deviceCodeHash: bytes("device_code_hash").notNull(),
|
|
313
|
+
authMac: bytes("auth_mac").notNull(),
|
|
314
|
+
userCode: text("user_code").notNull(),
|
|
315
|
+
clientLabel: text("client_label"),
|
|
316
|
+
clientIp: text("client_ip"),
|
|
317
|
+
createdAt: createdAt(),
|
|
318
|
+
expiresAt: time("expires_at").notNull(),
|
|
319
|
+
decidedAt: time("decided_at"),
|
|
320
|
+
decision: text(),
|
|
321
|
+
generation: integer().notNull().default(0),
|
|
322
|
+
principal: text(),
|
|
323
|
+
consumedAt: time("consumed_at")
|
|
324
|
+
}, (table) => [
|
|
325
|
+
unique("device_authorizations_device_code_hash_key").on(table.deviceCodeHash),
|
|
326
|
+
unique("device_authorizations_user_code_key").on(table.userCode),
|
|
327
|
+
check("device_authorizations_auth_mac_check", sql`octet_length(${table.authMac}) = 32`),
|
|
328
|
+
check("device_authorizations_decision_check", sql`${table.decision} IS NULL OR ${table.decision} IN ('approved', 'denied')`),
|
|
329
|
+
check("device_authorizations_approval_names_principal", sql`(${table.decision} IS NULL AND ${table.decidedAt} IS NULL AND ${table.principal} IS NULL AND ${table.generation} = 0 AND ${table.consumedAt} IS NULL)
|
|
330
|
+
OR (${table.decision} IS NOT NULL AND ${table.decidedAt} IS NOT NULL AND (
|
|
331
|
+
(${table.decision} = 'denied' AND ${table.principal} IS NULL AND ${table.generation} = 0 AND ${table.consumedAt} IS NULL)
|
|
332
|
+
OR (${table.decision} = 'approved' AND ${table.principal} IS NOT NULL AND ${table.principal} LIKE 'user:%')
|
|
333
|
+
))`),
|
|
334
|
+
foreignKey({
|
|
335
|
+
name: "device_authorizations_principal_fkey",
|
|
336
|
+
columns: [table.principal],
|
|
337
|
+
foreignColumns: [vaultMembers.principal]
|
|
338
|
+
}).onDelete("restrict")
|
|
339
|
+
]);
|
|
340
|
+
const syncs = sqliteTable("syncs", {
|
|
341
|
+
id: text().primaryKey(),
|
|
342
|
+
projectId: text("project_id").notNull(),
|
|
343
|
+
environmentId: text("environment_id").notNull(),
|
|
344
|
+
provider: text().notNull(),
|
|
345
|
+
config: text().notNull(),
|
|
346
|
+
credentialSecretId: text("credential_secret_id").notNull(),
|
|
347
|
+
createdAt: createdAt(),
|
|
348
|
+
createdBy: text("created_by").notNull(),
|
|
349
|
+
pausedAt: time("paused_at"),
|
|
350
|
+
archivedAt: time("archived_at"),
|
|
351
|
+
leaseUntil: time("lease_until"),
|
|
352
|
+
lastRunAt: time("last_run_at"),
|
|
353
|
+
lastStatus: text("last_status"),
|
|
354
|
+
lastError: text("last_error")
|
|
355
|
+
}, (table) => [
|
|
356
|
+
check("syncs_config_check", sql`json_valid(${table.config})`),
|
|
357
|
+
check("syncs_last_status_check", sql`${table.lastStatus} IS NULL OR ${table.lastStatus} IN ('ok', 'partial', 'failed')`),
|
|
358
|
+
foreignKey({
|
|
359
|
+
name: "syncs_environment_in_project",
|
|
360
|
+
columns: [table.environmentId, table.projectId],
|
|
361
|
+
foreignColumns: [environments.id, environments.projectId]
|
|
362
|
+
}).onDelete("restrict"),
|
|
363
|
+
foreignKey({
|
|
364
|
+
name: "syncs_credential_secret_id_fkey",
|
|
365
|
+
columns: [table.credentialSecretId],
|
|
366
|
+
foreignColumns: [secrets.id]
|
|
367
|
+
}).onDelete("restrict"),
|
|
368
|
+
index("syncs_environment_idx").on(table.environmentId)
|
|
369
|
+
]);
|
|
370
|
+
const syncKeys = sqliteTable("sync_keys", {
|
|
371
|
+
syncId: text("sync_id").notNull(),
|
|
372
|
+
key: text().notNull(),
|
|
373
|
+
secretVersionId: text("secret_version_id"),
|
|
374
|
+
pushedAt: time("pushed_at").notNull().default(now),
|
|
375
|
+
removedAt: time("removed_at")
|
|
376
|
+
}, (table) => [
|
|
377
|
+
primaryKey({
|
|
378
|
+
name: "sync_keys_pkey",
|
|
379
|
+
columns: [table.syncId, table.key]
|
|
380
|
+
}),
|
|
381
|
+
foreignKey({
|
|
382
|
+
name: "sync_keys_sync_id_fkey",
|
|
383
|
+
columns: [table.syncId],
|
|
384
|
+
foreignColumns: [syncs.id]
|
|
385
|
+
}).onDelete("restrict"),
|
|
386
|
+
foreignKey({
|
|
387
|
+
name: "sync_keys_secret_version_id_fkey",
|
|
388
|
+
columns: [table.secretVersionId],
|
|
389
|
+
foreignColumns: [secretVersions.id]
|
|
390
|
+
}).onDelete("restrict")
|
|
391
|
+
]);
|
|
392
|
+
const { environmentsRelations, secretsRelations, syncsRelations, syncKeysRelations } = relationsOf(asPostgres({
|
|
393
|
+
projects,
|
|
394
|
+
environments,
|
|
395
|
+
secrets,
|
|
396
|
+
secretVersions,
|
|
397
|
+
syncs,
|
|
398
|
+
syncKeys
|
|
399
|
+
}));
|
|
400
|
+
//#endregion
|
|
401
|
+
export { auditChainHead, auditLog, credentials, deviceAuthorizations, environments, environmentsRelations, identities, projects, secretVersions, secrets, secretsRelations, syncKeys, syncKeysRelations, syncs, syncsRelations, vaultGrants, vaultMembers };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { r as Queryable } from "./database-CWpo5aF0.js";
|
|
2
|
+
import { Engine } from "./dialect.js";
|
|
3
|
+
//#region src/schema-version.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Minimum migration prefix required by this application image, per engine:
|
|
6
|
+
* each tree has its own history, all ending at the same schema. Until the
|
|
7
|
+
* first deployment, each is its baseline alone (see baseline.ts).
|
|
8
|
+
*/
|
|
9
|
+
export declare const REQUIRED_MIGRATIONS: Record<Engine, number>;
|
|
10
|
+
export declare function requiredMigrations(db: Queryable): number;
|
|
11
|
+
//#endregion
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { engineOf } from "./dialect.js";
|
|
2
|
+
//#region src/schema-version.ts
|
|
3
|
+
/**
|
|
4
|
+
* Minimum migration prefix required by this application image, per engine:
|
|
5
|
+
* each tree has its own history, all ending at the same schema. Until the
|
|
6
|
+
* first deployment, each is its baseline alone (see baseline.ts).
|
|
7
|
+
*/
|
|
8
|
+
const REQUIRED_MIGRATIONS = {
|
|
9
|
+
postgres: 1,
|
|
10
|
+
sqlite: 1
|
|
11
|
+
};
|
|
12
|
+
function requiredMigrations(db) {
|
|
13
|
+
return REQUIRED_MIGRATIONS[engineOf(db)];
|
|
14
|
+
}
|
|
15
|
+
//#endregion
|
|
16
|
+
export { REQUIRED_MIGRATIONS, requiredMigrations };
|
package/dist/schema.d.ts
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { _ as vaultGrants, a as environments, c as projects, d as secrets, f as secretsRelations, g as syncsRelations, h as syncs, i as deviceAuthorizations, m as syncKeysRelations, n as auditLog, o as environmentsRelations, p as syncKeys, r as credentials, s as identities, t as auditChainHead, u as secretVersions, v as vaultMembers } from "./schema-Cd4WOnB5.js";
|
|
2
|
+
export { auditChainHead, auditLog, credentials, deviceAuthorizations, environments, environmentsRelations, identities, projects, secretVersions, secrets, secretsRelations, syncKeys, syncKeysRelations, syncs, syncsRelations, vaultGrants, vaultMembers };
|