// Schema for the {{projectName}} RBAC backend — a `notes` domain guarded by // GLOBAL scopes, plus a `teams` domain guarded PER RESOURCE. `actors` + // `tenants` are the framework core tables. import { boolean, databaseHandle, id, table, text, timestamp, type InferRow, } from '@voltro/database' import { tenant } from '@voltro/plugin-multitenancy' export const actors = table('actors', { id: id(), kind: text().oneOf(['user', 'serviceAccount', 'apiKey', 'system']), displayName: text().nullable(), createdAt: timestamp().default('now'), }) export const tenants = table('tenants', { id: id(), name: text(), createdAt: timestamp().default('now'), }) export const notes = table('notes', { id: id({ prefix: 'note' }), title: text(), body: text(), // `notes.delete` demonstrates authz that a descriptor guard CANNOT express: // whether a note may be hard-deleted depends on this column, which is only // known after the row is loaded. archived: boolean().default(false), }) .with(tenant()) // Guarded per-resource rather than globally: holding `teams:rename` on // `team_core` must not let you rename `team_marketing`. The grant comes from // `resolveResourceRoles` in app.config.ts. export const teams = table('teams', { id: id({ prefix: 'team' }), name: text(), }) .with(tenant()) export type Note = InferRow export type Team = InferRow export const database = databaseHandle({ actors, tenants, notes, teams })