File
Blob: src/worker/db/d1/schema/patNamespaceGrants.ts
| 1 | import { sql } from "drizzle-orm"; |
| 2 | import { check, index, primaryKey, sqliteTable, text } from "drizzle-orm/sqlite-core"; |
| 3 | |
| 4 | import { namespaces } from "./namespaces"; |
| 5 | import { personalAccessTokens } from "./personalAccessTokens"; |
| 6 | |
| 7 | // Permission level granted by a PAT to a namespace or repository. `push` |
| 8 | // includes everything `pull` allows; absence of a grant row encodes |
| 9 | // no-access. The DB CHECK constraint is the structural guard so callers |
| 10 | // (DAL, verifier, API, UI) can trust the value without defensive code. |
| 11 | export type PatGrantLevel = "pull" | "push"; |
| 12 | |
| 13 | // PAT scoped to an entire namespace. |
| 14 | export const patNamespaceGrants = sqliteTable( |
| 15 | "pat_namespace_grants", |
| 16 | { |
| 17 | patId: text("pat_id") |
| 18 | .notNull() |
| 19 | .references(() => personalAccessTokens.id, { onDelete: "cascade" }), |
| 20 | namespaceId: text("namespace_id") |
| 21 | .notNull() |
| 22 | .references(() => namespaces.id, { onDelete: "cascade" }), |
| 23 | level: text("level").$type<PatGrantLevel>().notNull(), |
| 24 | }, |
| 25 | (table) => [ |
| 26 | primaryKey({ columns: [table.patId, table.namespaceId] }), |
| 27 | index("idx_pat_namespace_grants_namespace").on(table.namespaceId), |
| 28 | check("chk_pat_namespace_grants_level", sql`"level" IN ('pull','push')`), |
| 29 | ] |
| 30 | ); |
| 31 | |
| 32 | export type PatNamespaceGrantRow = typeof patNamespaceGrants.$inferSelect; |
| 33 | export type NewPatNamespaceGrantRow = typeof patNamespaceGrants.$inferInsert; |