import pg from "pg"; import type { AuthSection, AuthTriggerInfo, AuthPolicyInfo } from "./manifest.js"; /** * Supabase Auth 用户(auth.users + auth.identities)的备份。 * * 只备这两张表:用户 ID、邮箱、密码哈希、metadata、登录方式。sessions、refresh token、MFA 因子、 * SSO 配置一律不备——恢复到新项目后用户重新登录一次即可,MFA 因子可能用旧项目的密钥加密过, * 带过去反而可能把用户锁在外面。 * * 不打扰现有备份是硬约束: * - "off"(库调用的默认值)时,备份命令、上传的文件、manifest 与没有这个功能时逐字节一致。 * - 主 dump 的参数永远不动;Auth 一侧任何失败都不影响主 dump。 * - 默认开启("default")时,读不到、不支持、出错都只记进 manifest、打警告,不让备份失败; * 只有调用方显式要求("on")时,出错才算失败。 */ export type AuthMode = "off" | "default" | "on"; export declare const AUTH_TABLES: readonly ["users", "identities"]; /** auth.dump 的技术上限:对应数百万用户或巨大的 metadata。超过就跳过,不拖慢和撑爆演练与恢复 */ export declare const AUTH_DUMP_MAX_BYTES: number; /** * schemas 配置和 Auth 备份的关系。单独的 Auth 备份只在每一项都是普通 schema 名字时才做: * 模式写法(通配、正则、"库.schema")由 PostgreSQL 自己解析,我们在这里算不准它最终选中哪些 schema, * 也就没法可靠地判断"会不会重复导出"和"恢复时目标里哪些 schema 该是空的"——干脆不做。 * - "yes":明写了 auth(主 dump 里已经有),或某个模式确定匹配得到 auth(例如 "*"); * - "maybe":有模式写法,而又不能确定它包含 auth; * - "no":全是普通名字,且没有 auth。 */ export declare function authInSchemas(schemas: string[]): "yes" | "maybe" | "no"; /** * 普通 schema 名字:不加引号、只有字母数字和下划线,按 pg_dump 的规则折成小写。其余一律返回 null, * 按模式写法处理(不另备 Auth)。名字会进 RECOVERY.md 里给人复制的 SQL 和 shell,只收这种最朴素的, * 加引号的名字(可以含换行、引号、$$)不给任何拼接出错的机会 */ export declare function plainSchemaName(pattern: string): string | null; /** 默认模式用:确定会、或说不准,都算"可能已含 auth"——宁可少做,不碰现有备份 */ export declare function schemasMayIncludeAuth(schemas: string[]): boolean; /** * 连库,但能被 signal 随时打断:到点时直接断开连接,不管它还在连接池里排队、还是正在跑查询。 * Auth 这两条连接都在主 dump 之前用,绝不能让它们占着连接、把数据库备份堵在后面。 */ export declare function connectCancellable(databaseUrl: string, signal?: AbortSignal): Promise; /** * 报错文字里可能是用户数据的部分换成 "…":冒号后面引起来的值(例如 invalid input syntax for type uuid: "…")、 * 单引号字面量、邮箱、UUID。表名、约束名这类标识符(relation "x"、constraint "y")留着,排查要用 */ export declare function redactValues(text: string): string; /** 共享快照:导出快照的连接 + 快照号。导出连接只需活到两份 pg_dump 都导入快照为止 */ export interface SharedSnapshot { id: string; /** 提交并关闭导出连接;重复调用无害 */ release(): Promise; } /** * 开一个 REPEATABLE READ 只读事务导出快照。主 dump、auth dump、统计都导入这一个快照, * 两份归档看到的是同一时刻的库(否则两次导出之间的注册、删号会让两份对不上)。 * 失败就返回 null:调用方按今天的方式导出主 dump,只把 Auth 段标掉。 */ export declare function exportSharedSnapshot(databaseUrl: string, signal?: AbortSignal): Promise; /** 统计结果:只读,和两份 dump 同一个快照 */ export type AuthInspection = { readable: false; reason: "no_auth_schema" | "no_permission"; } | { readable: true; users: number; identities: number; passwordHashes: AuthSection["passwordHashes"]; anonymousUsers: number; ssoUsers: number; mfaUsers: number | null; triggers: AuthTriggerInfo[]; policies: AuthPolicyInfo[]; grants: Array<{ table: string; grantee: string; privilege: string; }>; }; /** * 在另一个连接里导入共享快照做统计。统计出错只影响这个连接,导出快照的事务和主 dump 不受牵连。 * 能不能读到全部行要先确认:auth.users 开着 RLS,角色既不是超级用户、又没有 BYPASSRLS 时, * pg_dump 照样"成功",导出的却是空表——看着干净,其实什么都没备上。 */ export declare function inspectAuth(databaseUrl: string, snapshotId: string, signal?: AbortSignal): Promise; /** * 恢复(含 RECOVERY.md 的手工步骤)自动补建的 Auth 表对象。只建同时满足下面几条的触发器: * - 源库里是普通启用状态(O)。D 停用、R 只在复制会话触发的,在普通会话里本来就不起作用; * A(总是触发)恢复时 pg_dump 会带一句 ENABLE ALWAYS,那需要表的属主身份,新项目里做不到。 * - 触发函数所在的 schema 在这次备份里(或是平台 schema),否则建不出来。 * - 名字是普通标识符。 * 策略一律不自动建:CREATE POLICY 需要表的属主身份,新项目里 auth 两张表的属主是平台角色; * 放进单事务恢复里建不出来,会让整个恢复回滚。少了它们,这两张开着 RLS 的表对 API 角色一律拒绝, * 是收紧而不是放开。 */ export declare function restorableAuthObjects(auth: { triggers: AuthTriggerInfo[]; policies: AuthPolicyInfo[]; }, backedUpSchemas: string[]): { triggers: AuthTriggerInfo[]; }; /** * 恢复时不会自动补建、需要人手处理的 Auth 表对象,写成给人看的句子。备份时提示一次(好让用户把缺的 * schema 加进备份),RECOVERY.md 和恢复报告里列成手工步骤。 */ export declare function manualAuthObjects(auth: { triggers: AuthTriggerInfo[]; policies: AuthPolicyInfo[]; }, backedUpSchemas: string[]): string[]; /** pg_dump 参数:只导两张表(结构 + 数据 + 它们上的索引、约束、触发器、策略),同一个共享快照 */ export declare function authDumpArgs(snapshotId: string): string[];