/** * Global-scope `cleo.db` — **universal service-credential vault** (3 tables). * * EP-UNIVERSAL-SERVICE-VAULT (epic T11765 · saga SG-VAULT-CORE T10409 · M2 W1a · * task T11937). The **service** half of the universal vault — machine-wide OAuth / * API credentials for third-party SERVICES (github, google, notion, figma, …) — * cannibalized from onecli's `app_connections` / `app_configs` / * `agent_app_connections`, DROPPING every org / project / billing column (the * vault is machine-wide, exactly like the `accounts` LLM-credential pool — T11709, * the established precedent this directory mirrors). Three tables: * * - `service_connections` — one user-connected credential per `(provider, label)`: * the encrypted token blob + non-secret metadata (scopes, expiry, username). * - `service_configs` — per-provider BYOC (bring-your-own-client) OAuth app: * enabled flag + encrypted client secret + non-secret settings (client id, * scopes). One row per provider. * - `agent_service_grants` — per-agent access to a connection, plus the * `session_policy` (block / rate-limit / manual-approval) the trust gate * evaluates BEFORE any decrypt (T11937 AC4 — policy-before-decrypt). * * ## NOT the LLM credential pool (`accounts`) — do not confuse the two * * `accounts` (T11709) holds MODEL-API credentials (the pool the LLM runner picks * from). These `service_*` tables hold SERVICE-API credentials (the things an * agent's tools call: github, gmail, …). Different physical names, different * consumers, different egress path. The crypto, ISO-timestamp typing, and * accessor patterns are shared by design. * * ## Encrypted at rest (global KDF — reuse, no new crypto · T11710) * * `credentials_enc` (the `{access_token, refresh_token}` JSON blob) and * `client_secret_enc` (the BYOC client secret) are `encryptGlobal()` ciphertext * (packages/core/src/crypto/credentials.ts), NEVER plaintext. They keep the * versioned `0x01 + 12B IV + 16B authTag` framing and decrypt via the project- * INDEPENDENT KDF `HMAC-SHA256(machine-key || globalSalt, id)` with * `id = service:${provider}:${label}` — so a service credential decrypts * consistently for the machine regardless of the reading project's cwd. * * ## E10 typing (per docs/migration/sqlite-schema-canonical.md) * * TEXT ISO-8601 timestamps (`*_at`, GLOB-checked in the migration); named enums * ({@link SERVICE_CONNECTION_STATUSES}); typed booleans (`enabled`); JSON-as-TEXT * (`scopes`, `metadata`, `settings`, `session_policy`). The consolidated * schema-parity gate (T11364) re-derives the CHECK set from THIS metadata, so the * forward migration's CHECKs must match it exactly. * * @task T11937 * @epic T11765 * @saga T10409 * @see ../../../crypto/credentials.ts — `encryptGlobal` / `decryptGlobal` (T11710) * @see ./accounts.ts — `accounts` (the SIBLING LLM-credential-pool table, T11709) * @see ../../service-connections-accessor.ts — the store CRUD + sealed-handle egress * @see ../../service-trust-gate.ts — policy-before-decrypt grant evaluation * @see ../../../../migrations/drizzle-cleo-global — the forward migration */ /** * Legal `service_connections.status` values — the lifecycle of a connection. * * - `active` — usable; the token is (or can be refreshed to) valid. * - `expired` — the access token (and refresh, if any) has lapsed; needs re-auth. * - `revoked` — the user (or provider) revoked the grant; never usable again. * * @task T11937 */ export declare const SERVICE_CONNECTION_STATUSES: readonly ["active", "expired", "revoked"]; /** TypeScript union derived from {@link SERVICE_CONNECTION_STATUSES}. */ export type ServiceConnectionStatus = (typeof SERVICE_CONNECTION_STATUSES)[number]; /** * `service_connections` — one user-connected service credential per `(provider, label)`. * * `credentials_enc` is the `encryptGlobal()` ciphertext of the * `{access_token, refresh_token}` JSON blob (NEVER plaintext). `scopes` is the * JSON-serialized granted scope list; `metadata` is non-secret JSON (e.g. the * connected `username`/`email`) safe to display. The `(provider, label)` pair is * unique. The OAuth build/exchange/refresh that POPULATES `credentials_enc` is * T11939 — this table is the clean seam it writes into. * * @task T11937 */ export declare const serviceConnections: import("drizzle-orm/sqlite-core").SQLiteTableWithColumns<{ name: "service_connections"; schema: undefined; columns: { id: import("drizzle-orm/sqlite-core").SQLiteColumn<{ name: string; tableName: "service_connections"; dataType: "number int53"; data: number; driverParam: number; notNull: true; hasDefault: true; isPrimaryKey: true; isAutoincrement: false; hasRuntimeDefault: false; enumValues: undefined; baseColumn: never; identity: undefined; generated: undefined; }, {}>; provider: import("drizzle-orm/sqlite-core").SQLiteColumn<{ name: string; tableName: "service_connections"; dataType: "string"; data: string; driverParam: string; notNull: true; hasDefault: false; isPrimaryKey: false; isAutoincrement: false; hasRuntimeDefault: false; enumValues: [string, ...string[]]; baseColumn: never; identity: undefined; generated: undefined; }, {}>; label: import("drizzle-orm/sqlite-core").SQLiteColumn<{ name: string; tableName: "service_connections"; dataType: "string"; data: string; driverParam: string; notNull: true; hasDefault: false; isPrimaryKey: false; isAutoincrement: false; hasRuntimeDefault: false; enumValues: [string, ...string[]]; baseColumn: never; identity: undefined; generated: undefined; }, {}>; status: import("drizzle-orm/sqlite-core").SQLiteColumn<{ name: string; tableName: "service_connections"; dataType: "string enum"; data: "active" | "expired" | "revoked"; driverParam: string; notNull: true; hasDefault: true; isPrimaryKey: false; isAutoincrement: false; hasRuntimeDefault: false; enumValues: ["active", "expired", "revoked"]; baseColumn: never; identity: undefined; generated: undefined; }, {}>; credentialsEnc: import("drizzle-orm/sqlite-core").SQLiteColumn<{ name: string; tableName: "service_connections"; dataType: "string"; data: string; driverParam: string; notNull: false; hasDefault: false; isPrimaryKey: false; isAutoincrement: false; hasRuntimeDefault: false; enumValues: [string, ...string[]]; baseColumn: never; identity: undefined; generated: undefined; }, {}>; scopes: import("drizzle-orm/sqlite-core").SQLiteColumn<{ name: string; tableName: "service_connections"; dataType: "string"; data: string; driverParam: string; notNull: true; hasDefault: true; isPrimaryKey: false; isAutoincrement: false; hasRuntimeDefault: false; enumValues: [string, ...string[]]; baseColumn: never; identity: undefined; generated: undefined; }, {}>; expiresAt: import("drizzle-orm/sqlite-core").SQLiteColumn<{ name: string; tableName: "service_connections"; dataType: "string"; data: string; driverParam: string; notNull: false; hasDefault: false; isPrimaryKey: false; isAutoincrement: false; hasRuntimeDefault: false; enumValues: [string, ...string[]]; baseColumn: never; identity: undefined; generated: undefined; }, {}>; metadata: import("drizzle-orm/sqlite-core").SQLiteColumn<{ name: string; tableName: "service_connections"; dataType: "string"; data: string; driverParam: string; notNull: true; hasDefault: true; isPrimaryKey: false; isAutoincrement: false; hasRuntimeDefault: false; enumValues: [string, ...string[]]; baseColumn: never; identity: undefined; generated: undefined; }, {}>; connectedAt: import("drizzle-orm/sqlite-core").SQLiteColumn<{ name: string; tableName: "service_connections"; dataType: "string"; data: string; driverParam: string; notNull: true; hasDefault: true; isPrimaryKey: false; isAutoincrement: false; hasRuntimeDefault: false; enumValues: [string, ...string[]]; baseColumn: never; identity: undefined; generated: undefined; }, {}>; updatedAt: import("drizzle-orm/sqlite-core").SQLiteColumn<{ name: string; tableName: "service_connections"; dataType: "string"; data: string; driverParam: string; notNull: true; hasDefault: true; isPrimaryKey: false; isAutoincrement: false; hasRuntimeDefault: false; enumValues: [string, ...string[]]; baseColumn: never; identity: undefined; generated: undefined; }, {}>; }; dialect: "sqlite"; }>; /** Row type for `service_connections` SELECT queries. */ export type ServiceConnectionRow = typeof serviceConnections.$inferSelect; /** Row type for `service_connections` INSERT/UPSERT operations. */ export type NewServiceConnectionRow = typeof serviceConnections.$inferInsert; /** * `service_configs` — per-provider BYOC (bring-your-own-client) OAuth app config. * * When a user brings their own OAuth client (rather than using CLEO's first-party * app), the client id + non-secret OAuth settings live in `settings` (JSON) and * the client SECRET lives encrypted in `client_secret_enc`. One row per provider * (`UNIQUE(provider)`). `enabled` toggles whether the BYOC config is used. This * is the clean seam the OAuth flow (T11939) reads to prefer a user client over * the registry default. * * @task T11937 */ export declare const serviceConfigs: import("drizzle-orm/sqlite-core").SQLiteTableWithColumns<{ name: "service_configs"; schema: undefined; columns: { id: import("drizzle-orm/sqlite-core").SQLiteColumn<{ name: string; tableName: "service_configs"; dataType: "number int53"; data: number; driverParam: number; notNull: true; hasDefault: true; isPrimaryKey: true; isAutoincrement: false; hasRuntimeDefault: false; enumValues: undefined; baseColumn: never; identity: undefined; generated: undefined; }, {}>; provider: import("drizzle-orm/sqlite-core").SQLiteColumn<{ name: string; tableName: "service_configs"; dataType: "string"; data: string; driverParam: string; notNull: true; hasDefault: false; isPrimaryKey: false; isAutoincrement: false; hasRuntimeDefault: false; enumValues: [string, ...string[]]; baseColumn: never; identity: undefined; generated: undefined; }, {}>; enabled: import("drizzle-orm/sqlite-core").SQLiteColumn<{ name: string; tableName: "service_configs"; dataType: "boolean"; data: boolean; driverParam: number; notNull: true; hasDefault: true; isPrimaryKey: false; isAutoincrement: false; hasRuntimeDefault: false; enumValues: undefined; baseColumn: never; identity: undefined; generated: undefined; }, {}>; clientSecretEnc: import("drizzle-orm/sqlite-core").SQLiteColumn<{ name: string; tableName: "service_configs"; dataType: "string"; data: string; driverParam: string; notNull: false; hasDefault: false; isPrimaryKey: false; isAutoincrement: false; hasRuntimeDefault: false; enumValues: [string, ...string[]]; baseColumn: never; identity: undefined; generated: undefined; }, {}>; settings: import("drizzle-orm/sqlite-core").SQLiteColumn<{ name: string; tableName: "service_configs"; dataType: "string"; data: string; driverParam: string; notNull: true; hasDefault: true; isPrimaryKey: false; isAutoincrement: false; hasRuntimeDefault: false; enumValues: [string, ...string[]]; baseColumn: never; identity: undefined; generated: undefined; }, {}>; createdAt: import("drizzle-orm/sqlite-core").SQLiteColumn<{ name: string; tableName: "service_configs"; dataType: "string"; data: string; driverParam: string; notNull: true; hasDefault: true; isPrimaryKey: false; isAutoincrement: false; hasRuntimeDefault: false; enumValues: [string, ...string[]]; baseColumn: never; identity: undefined; generated: undefined; }, {}>; updatedAt: import("drizzle-orm/sqlite-core").SQLiteColumn<{ name: string; tableName: "service_configs"; dataType: "string"; data: string; driverParam: string; notNull: true; hasDefault: true; isPrimaryKey: false; isAutoincrement: false; hasRuntimeDefault: false; enumValues: [string, ...string[]]; baseColumn: never; identity: undefined; generated: undefined; }, {}>; }; dialect: "sqlite"; }>; /** Row type for `service_configs` SELECT queries. */ export type ServiceConfigRow = typeof serviceConfigs.$inferSelect; /** Row type for `service_configs` INSERT/UPSERT operations. */ export type NewServiceConfigRow = typeof serviceConfigs.$inferInsert; /** * `agent_service_grants` — per-agent access to a service connection + policy. * * A grant authorizes one `agent_id` to use one `service_connection_id`, carrying * the `session_policy` JSON (block / rate-limit / manual-approval) the trust gate * (T11937 AC4) evaluates BEFORE any `decryptGlobal`. ABSENCE of a grant denies; * a `block` policy denies; only a passing policy lets the store decrypt. The * composite `(agent_id, service_connection_id)` is the primary key. * * `service_connection_id` references `service_connections(id)` — both tables live * in the SAME global `cleo.db` file (Pattern A), so the FK is in-file and * enforceable. The FK is declared natively (intra-domain, single global file — * mirrors the agent-registry FK convention). * * @task T11937 */ export declare const agentServiceGrants: import("drizzle-orm/sqlite-core").SQLiteTableWithColumns<{ name: "agent_service_grants"; schema: undefined; columns: { agentId: import("drizzle-orm/sqlite-core").SQLiteColumn<{ name: string; tableName: "agent_service_grants"; dataType: "string"; data: string; driverParam: string; notNull: true; hasDefault: false; isPrimaryKey: false; isAutoincrement: false; hasRuntimeDefault: false; enumValues: [string, ...string[]]; baseColumn: never; identity: undefined; generated: undefined; }, {}>; serviceConnectionId: import("drizzle-orm/sqlite-core").SQLiteColumn<{ name: string; tableName: "agent_service_grants"; dataType: "number int53"; data: number; driverParam: number; notNull: true; hasDefault: false; isPrimaryKey: false; isAutoincrement: false; hasRuntimeDefault: false; enumValues: undefined; baseColumn: never; identity: undefined; generated: undefined; }, {}>; sessionPolicy: import("drizzle-orm/sqlite-core").SQLiteColumn<{ name: string; tableName: "agent_service_grants"; dataType: "string"; data: string; driverParam: string; notNull: true; hasDefault: true; isPrimaryKey: false; isAutoincrement: false; hasRuntimeDefault: false; enumValues: [string, ...string[]]; baseColumn: never; identity: undefined; generated: undefined; }, {}>; createdAt: import("drizzle-orm/sqlite-core").SQLiteColumn<{ name: string; tableName: "agent_service_grants"; dataType: "string"; data: string; driverParam: string; notNull: true; hasDefault: true; isPrimaryKey: false; isAutoincrement: false; hasRuntimeDefault: false; enumValues: [string, ...string[]]; baseColumn: never; identity: undefined; generated: undefined; }, {}>; updatedAt: import("drizzle-orm/sqlite-core").SQLiteColumn<{ name: string; tableName: "agent_service_grants"; dataType: "string"; data: string; driverParam: string; notNull: true; hasDefault: true; isPrimaryKey: false; isAutoincrement: false; hasRuntimeDefault: false; enumValues: [string, ...string[]]; baseColumn: never; identity: undefined; generated: undefined; }, {}>; }; dialect: "sqlite"; }>; /** Row type for `agent_service_grants` SELECT queries. */ export type AgentServiceGrantRow = typeof agentServiceGrants.$inferSelect; /** Row type for `agent_service_grants` INSERT/UPSERT operations. */ export type NewAgentServiceGrantRow = typeof agentServiceGrants.$inferInsert; //# sourceMappingURL=services.d.ts.map