---
url: /docs/agentbuff-stack/database-roles.md
---
# 数据库角色与凭据变更

## 当前能力

I15 已在独立的 PostgreSQL 17 密码认证实例中验收应用角色、环境连接权限与密码变更，再用真实本地 Worker 完成注册、上传、任务、扣费和私有下载。验收使用两个一次性数据库，不修改正常预览的角色、密码、授权或 0012 迁移；真实 Neon / Hyperdrive 连接池仍待指定环境验收。

## 三种角色分开安排

| 身份 | 用途 | 权限与配置 |
| --- | --- | --- |
| 数据库迁移所有者 | 建表、增量迁移、备份和独立恢复 | CLI 的管理连接；本教程授权脚本要求实际 `current_user` 是目标数据库、公共模式及其中表 / 序列的所有者 |
| 数据库应用角色 | API 经 Hyperdrive 日常读写 | 每个站、每个环境独立登录账号；只授予公共模式的业务读写与序列使用 |
| 网站用户 / 管理员 | 登录、查看自己的文件、站内管理 | 数据库 `user.role` 和接口鉴权；与数据库登录账号分开 |

应用角色是服务端凭据，能读写公共模式的业务表。文件与任务的用户隔离由原接口鉴权实现，本脚本不提供数据库逐用户行隔离，也不会把网站普通用户提升为管理员。

## 1. 在指定环境授予应用权限

先审查并应用该环境需要的增量迁移，再执行 `db/scripts/grant-app-role.sql`。脚本不会创建数据库或应用迁移，正常启动、发布与生成新站也不会自动执行它。

从仓库根目录运行，连接字段替换为自己已确认的环境；管理密码放在权限为 600 的私有 `PGPASSFILE` 中。按实际服务配置 TLS，避免沿用上一环境的连接字段：

```sh
export PGHOST='自己的数据库主机'
export PGPORT='5432'
export PGDATABASE='自己的测试数据库'
export PGUSER='实际迁移所有者'
export PGPASSFILE='/自己的私有目录/数据库密码文件'
psql --no-psqlrc --no-password \
  --set role=app_staging \
  --file db/scripts/grant-app-role.sql
```

首次创建时 `psql` 会请求新应用密码并确认，不把密码写进命令参数或 SQL 文本。**不要使用旧写法 `-v password=...`**，脚本会拒绝。已有角色重复授权不会修改密码；密码变更在下节单独处理。这一方式依据 [PostgreSQL 的 `\password` 说明](https://www.postgresql.org/docs/17/app-psql.html)，核对日期为 2026-10-11。

脚本先检查实际所有者和已有角色，拒绝继承其他所有者权限后代运行、已拥有对象的账号、特权属性、角色成员关系、额外直接授权及不合规默认授权。公共表 / 序列分属不同所有者也会拒绝，避免 PostgreSQL 仅警告而跳过授权。直接函数授权也需另行审查，不能作为普通应用角色自动接入。

创建角色、密码设置、当前授权与默认授权都在同一事务中；中途失败回滚。本地受控验收已在最后的默认授权处制造失败，确认新角色未留下，原授权不变。脚本不会偷偷撤销已有角色的其他直接权限；需要额外权限的角色应由操作者单独处理。

## 2. 核对实际权限

| 操作 | 本地实际结果 |
| --- | --- |
| 公共业务表查询、插入、更新、删除 | 允许；真实账号、文件、任务与积分流程通过 |
| 同一迁移所有者之后新增的公共表与序列 | 默认授权生效，插入及 `nextval` 可用 |
| 建表、建模式、临时表、修改或删除表 | 拒绝 |
| `TRUNCATE`、序列 `setval` | 拒绝；清理数据应走原业务入口 |
| 读取 `drizzle.__drizzle_migrations` | 拒绝；迁移核查使用管理连接 |
| 另一环境的应用账号连接已加固的目标库 | 拒绝 |

脚本撤销**所选数据库**对 `PUBLIC` 的连接 / 临时表权限，以及所选库公共模式的公开建表权限，再授予指定账号连接与业务权限。测试库和正式库需分别执行；不自动调整其他库、其他账号或自定义公开授权。全局对象所有权和数据库直接授权会检查，但其他数据库内部的模式、函数与表授权不在本次检查范围。不要据此声称整个集群已完全隔离。

授权返回成功后，仍要用应用账号新建连接并走完整业务流程，确认认证、默认权限和环境绑定。恢复归档不带原所有者与授权，重新安排权限后执行同样的检查，见[备份与恢复](./backup-restore)。

## 3. 更换密码与处理旧连接

用已确认环境的所有者连接执行：

```sh
psql --no-psqlrc --no-password --command '\password app_staging'
```

交互输入新密码后，更新所选环境缓存和无缓存两个 Hyperdrive 的源凭据。部署使用 Terraform 管理这两项资源，实际变更需遵循该环境的资源管理流程，不能只改电脑的 `DATABASE_URL`。

本地实测：旧密码的新连接被拒绝，新密码的新连接可用，**修改密码不会断开已经建立的连接**。撤销 `CONNECT` 同样只影响新连接。验收记录同一连接的后端编号，在修改密码及撤销连接权限后仍能查询；只有明确终止该自有测试连接后才断开。真实环境需先安排业务暂停、在途任务和连接更新，再决定是否终止旧连接；本教程不提供跨环境批量终止操作。

Cloudflare 也明确说明，更新 Hyperdrive 配置不会自动清除缓存或关闭原连接池；新连接采用新配置，立即替换已有连接需另行重启连接池。也可创建新配置并切换 Worker，但模板的资源管理与回滚安排需一起核对。[官方凭据变更说明](https://developers.cloudflare.com/hyperdrive/configuration/rotate-credentials/)，核对日期为 2026-10-11；这不是本项目已完成云端连接池验收的证明。

更换后检查原用户登录、原私有结果下载、任务重复提交、积分账本及队列消费。本地在更新 Worker 凭据后验证了原结果可下载，同一任务仍原编号、一次尝试、17 积分，无再次扣费。数据库密码变更不自动撤销网站登录会话；[认证密钥轮换](./auth-key-rotation)是另一项维护。

## 本地复验

准备 `initdb`、`pg_ctl`、`psql` 并加入 PATH，从仓库根目录运行：

```sh
bun db:validate-app-role
```

命令自建仅回环监听、SCRAM 密码认证的 PostgreSQL 实例，应用两份完整迁移，验证权限、错误密码、环境连接隔离、额外授权拒绝、事务回滚及真实 Worker 流程。随后更改自有角色密码、处理自有连接、重启隔离 Worker，核对原下载和扣费去重，再停止并清理自己的实例与目录。它不读取管理连接去修改正常预览或远程角色，也不向真实供应商发送请求。日志只报告阶段和结论；私有本地诊断会隐藏生成的密码与密码校验值。
