跳转到正文

Read this guide in English

站点管理员与操作审计 ​

I9 已实现站点授权、用户搜索、封禁 / 解封、任务状态与带原因恢复、积分调整、账本 / 支付记录、主动支付对账和审计查看。已提供显式维护计划与确认执行命令;正式数据库上的初始化和恢复尚待独立环境验收。

角色与管理入口 ​

站点角色保存在 user.role:普通用户 user 和管理员 admin。团队角色仍在 member.role;团队所有者或管理员不会获得全站权限。每次请求从新鲜连接检查角色、邮箱验证、匿名与封禁状态;降权后的旧会话不能继续调用管理接口。菜单隐藏只负责呈现。管理员必须是邮箱已验证、未封禁的正式账号。

/admin 入口当前行为
账号名称 / 邮箱搜索,每页 20 条;%、_ 按普通字符搜索
账号管理原因、确认、封禁 / 解封、授予 / 移除站点角色
积分查看余额 / 审核限制、账本;选择账号后带原因调整,先复核再确认
支付购买、退款 / 争议快照、已存事件、个人与团队订阅;每页 20 条,积分包购买可带原因主动核对
任务按选中账号分页查看状态、尝试预算、故障码与扣费;带原因复核 / 确认重试或取消
审计分页查看执行者、目标、动作、原因、前后角色 / 封禁、余额或任务状态、账本 / 任务 / 对账事件 ID 与时间

任务接口不返回原始输入、文件名、摘要、参数或私有下载。任务和审计的高级检索界面尚未实现;服务端支持账户 / 状态筛选,后续补齐运营流程。

数据升级 ​

新增 0012_public_invisible_woman.sql,保留 0000—0011 和全部既有 ID。增加 user.role、banned、banReason、banExpires 与组件兼容字段 session.impersonatedBy。现有账号默认未封禁的普通用户,不因注册顺序或团队角色被提升。

新增 admin_audit,ID 前缀为 aud_。执行者和目标 ID 故意没有级联外键,账号删除不能抹去历史管理证据。审计不保存密码、会话 token 或原始输入;无公开修改 / 删除接口,但不宣称数据库所有者无法篡改。正式环境保留期限与数据库权限发布前另配。

运行新 API 前按增量迁移教程检查并应用本站历史。本任务主预览 127.0.0.1:54329/launchkit 已在明确授权后应用 0012,核对全部旧迁移摘要与账号普通用户角色。自动验收仍只创建、迁移并销毁自己的一次性数据库;其他数据库需要独立升级。积分、任务和支付对账审计使用现有 JSON 与动作字段,这些阶段没有新增 SQL 迁移或改写 0012。

明确指定首个管理员 ​

选定人员先走本站注册和邮箱验证,维护者核对准确 usr_ ID,再运行:

sh
bun admin:bootstrap --user-id usr_替换为实际账号ID --reason '明确指定本站首个管理员'

命令只允许 ENVIRONMENT=development 和 loopback PostgreSQL,拒绝远程数据库。不选第一个账号、不创建账号、不修改验证状态、不迁移;未验证、匿名、封禁或不存在的账号拒绝。中文占位不是有效 ID。

初始化调用 Better Auth 实际用户写入器,与审计处于同一事务;失败回滚。相同账号重跑只返回已处理,不能恢复后来撤销的角色;不同账号或已有管理员拒绝。后续由现有管理员填写原因并确认授权。正式环境或失去全部有效管理员时使用下节维护命令,不绕过限制或清空记录;没有公开初始化接口、默认超级管理员或环境变量账号白名单。

正式环境初始化与恢复 ​

admin:operator 是由可信数据库维护者运行的本地命令,没有 HTTP 初始化入口、启动时自动授权或环境变量管理员白名单。适用于 development、staging 和 production;本次仅用一次性本地 PostgreSQL 在 production 模式执行验收,未连接真实远程数据库。数据库 owner 凭据具有管理权限,必须与 Worker 的应用角色分开;维护命令会检查 owner 权限,不能用普通应用凭据初始化。

先确认目标站点的迁移已经由独立升级流程应用。命令核对当前 checkout 全部 SQL 摘要、时间及记录数量;缺失、多出或不一致都拒绝,不自动生成或运行迁移。维护者让选定人员完成本站注册及真实邮箱验证,并独立核对准确的 usr_ ID。命令不会创建账号、验证邮箱、解除封禁、改密码、找回凭据或提升团队 owner。

为每个站点和环境准备一份私有文件,例如 .local/administrator-production.env。文件使用本站 API 的环境变量契约,明确填写 ENVIRONMENT=production、本站裸 HTTPS APP_ORIGIN、APP_NAME、BETTER_AUTH_SECRET、邮件配置及数据库 owner 的 DATABASE_URL;已启用模块所需配置也必须完整。文件放在版本控制之外,限制本机读取权限。命令只解析 --config 指定的文件,完全不继承 shell 的数据库或服务凭据,也不回退 .env.local。远程数据库要求 TLS 和非 pooler origin;development 只接受 loopback。

第一次初始化 ​

以下是维护步骤示例,ID、站点、操作者和 UUID 必须替换为准确值:

sh
bun admin:operator plan \
  --config .local/administrator-production.env \
  --environment production \
  --origin https://your-product.example \
  --operation initialize \
  --user-id usr_替换为实际账号ID \
  --operator your-maintainer-id \
  --reason '明确指定该站点首位已验证管理员' \
  --request-id 替换为新的UUID \
  --plan .local/administrator-initialize.json

plan 只读数据库,暂时锁定授权状态以获得一致快照,不改角色或写审计。计划文件默认权限 0600,拒绝覆盖已有文件或符号链接。输出可核对的环境、站点、账号、原因、请求 ID、数据库指纹、状态指纹和 30 分钟有效期,以及 approval 摘要;不输出数据库 URL、密码、会话或服务密钥。维护者对照私有配置确认数据库目标、目标人员与操作内容。摘要用于匹配已复核内容,是本机确认机制,不是签名、权限凭证或防止数据库 owner 篡改的保护。

只有本站不存在管理员角色记录,也没有历史初始化 / 恢复审计时,initialize 才能执行。曾初始化后删除管理员的站点也必须走显式恢复,不能当作新站。复核计划后执行:

sh
bun admin:operator apply \
  --config .local/administrator-production.env \
  --environment production \
  --origin https://your-product.example \
  --plan .local/administrator-initialize.json \
  --approve 替换为刚才复核的approval摘要

执行重新核对站点、环境、数据库身份、原指令摘要、有效期和锁定后的实际授权状态。账号或管理员状态变化会拒绝旧计划,重新生成并复核;不能在 apply 额外传入另一目标、原因或动作。确认后的角色变更调用 Better Auth 实际写入器,和 user.initialize_admin 审计同事务提交。审计保存 operator:<维护者标识>、目标、原因、实际前后角色、环境、站点及数据库指纹,不将维护者冒充浏览器登录用户。维护者标识为其自报名称,实际操作身份还需由组织的数据库凭据管理与外部操作记录核查。

失去全部有效管理员时恢复 ​

有效管理员指 role=admin、邮箱已验证、非匿名、未封禁的账号。只要还有一位有效管理员,维护恢复拒绝;忘记密码但账号仍有效时应使用已有账号找回方式,或由其他管理员通过带审计的角色管理授权。命令不能用“忘记密码”当作绕过角色管理的理由。

确实没有任何有效管理员、但已有管理员记录或初始化历史时,维护者指定另一个已注册、已验证且未封禁的普通账号,以新 UUID 重新生成计划,将 --operation 改为 recover,计划文件另命名。复核后使用同一 apply 步骤。保存独立 user.recover_admin,保留既有角色 / 封禁和全部历史审计,不清空记录、不恢复被封禁账号或旧会话。没有历史管理的站点必须用 initialize。旧的开发初始化命令也不能绕过新维护历史。

状态检查、Better Auth 角色写入和审计使用与站内管理相同的事务级授权锁。8 个相同计划竞争只提交一次;不同恢复候选竞争只能产生一个有效管理员,等待者必须重新复核状态。请求按外部维护者标识与 UUID 去重,改变目标、动作、原因或环境却沿用 UUID 会拒绝。响应不确定可在有效期内以原计划和摘要手动重试;已提交重放只返回 replayed: true,不会恢复之后撤销的角色、解封或复活删除账号。过期后可用原始相同指令 / UUID 生成新计划核对已处理状态;新的恢复操作使用新 UUID。

完成后由获授权者正常登录本站并检查 /admin、当前账号角色与操作审计,再归档私有计划。操作失败不宣称已授权,刷新数据库及审计后恢复;审计存储故障使角色变更回滚,修复后原计划可以继续。正式站点的凭据交付、维护人员身份核实、邮箱送达与远程执行仍由本站发布验收承担,本地命令测试不代替这些证据。

原子变更与重试 ​

身份和会话仍由 Better Auth Admin 插件写入。账号权限边界负责输入、授权、并发和审计:只接受同源的封禁、解封和角色变更 POST 操作,原因 5—500 字符,正文至多 16 KiB;重新确认执行者,锁定管理变更与目标,调用真实插件,再保存前后状态。审计失败整个事务回滚,包括实际会话删除。

最后一位有效管理员不能被封禁 / 降权,不能封禁自己;授予角色前检查目标已验证且未封禁。事务级全局咨询锁串行处理较少发生的站点授权、人工积分、管理员任务恢复与对账写入,防止交叉降权移除所有管理员;普通任务与读取不走这把锁。

确认生成请求 ID,审计按执行者与 ID 去重。响应丢失后的手动重试沿用 ID;改变动作、目标、角色或原因却复用 ID 会拒绝。解封后重放旧封禁只返回已处理,不重新封禁;不同 ID 的无状态差异请求仍保存审计。前端不自动重试,成功 / 失败都重新读取状态和审计。

变更要求近期登录,过期时实际退出、登录并回到 /admin;退出失败不清空会话。模拟登录、创建 / 删除账号、替人改密码和其他未纳入审计的插件管理端点关闭。兼容字段存在不等于该功能可用;普通注册 / 资料更新不能注入管理角色。

账本与支付排查 ​

先在账号列表选择管理对象,积分区会显示其当前余额与支付审核限制。只读查看不会创建钱包或赠送欢迎积分;尚未初始化时明确提示。取消选择可查看全站账本、购买和个人 / 团队订阅。个人订阅筛选按 user.id,团队订阅按 organization.id,不会把团队套餐误作成员个人套餐。

购买区展示已保存的测试 / 正式模式、商品、金额、积分、退款 / 争议、扣回与不足差额,以及便于排查的 Checkout / Payment ID。事件仅返回保存的处理结果与快照;未保存显示“未记录”,真实零值显示零。没有访问支付供应商或用空值补造成功记录,不返回 Checkout URL、内部租约、请求键或原始供应商负载。展示数据库记录的 active 不替代已有套餐服务对当前周期、试用与配置的权益判断。

列表每页 20 条,按时间及 ID 排序;允许翻页。用户 / 购买 / 账单归属的筛选由服务端执行,每次重新检查站点权限。普通账号、团队 owner / admin 和已失权的旧会话无法读取。积分包购买的主动查询见下一节;订阅人工变更仍待后续阶段。

主动核对积分包购买 ​

切换到购买记录,选中购买查看事件。在服务器确认本站已配置对应测试 / 正式密钥及独立积分包 webhook 密钥,并且购买有 Checkout 或 Payment 引用后,可填写 5—500 字符原因,复核并确认当前支付检查。没有配置或引用时明确提示不可核对;读取列表不会访问供应商。检查原有购买不要求重新开启新积分包销售,不创建支付、退款或订阅变更。

服务端严格只接受购买 ID、请求 UUID 与原因,使用实际站点管理员、同源和近期 24 小时会话;每位管理员每分钟最多 10 次,重放也计入。请求审计 purchase.reconcile_requested 在供应商查询前提交,记录当时快照和稳定对账事件 ID。该历史记录只证明请求已记录,不能单独证明当前仍未完成或已经完成。

随后复用原结算服务读取 Stripe 当前 Checkout、PaymentIntent、Charge、退款与争议,校验归属、SKU / Price、模式、金额、币种及实际到账。供应商读取期间不持有管理 / 账本事务锁;购买仍使用原有限操作租约。读取结束、结算锁等待后再次检查实际管理员及会话,查询期间已撤销 / 降权的会话无法提交权益变更。

原结算规则决定发积分、退款扣回、争议恢复、差额和审核限制;管理员不能输入“已支付”、退款金额或手动清除审核。核对成功可能得到 review,不是自动判定支付正常;金额不符不发购买积分,余额不足返还扣回形成原有 shortfall / 账户限制,其他购买的审核限制不会被错误解除。

购买状态、钱包 / 账本、支付事件与 purchase.reconcile_completed 在同一事务提交。完成审计保存事件 ID、已应用 / 需审核结果与实际前后支付快照,包括积分是否已发、扣回和差额;不保存 Checkout URL、供应商原始负载或密钥。完成审计失败时全部财务写入回滚,先前请求记录保留以便排查和恢复。

同 UUID 的同购买 / 原因恢复使用同一稳定事件 ID;已完成请求重放不再查询供应商,也不恢复历史余额。改变原因、购买或复用其他账号 / 积分 / 任务动作 UUID 会拒绝。并发查询由原购买租约限制,正在查询可返回忙碌;刷新后沿用同 ID 手动重试,不自动重试。完成后的新一次核对必须重新复核并生成新 UUID,以读取后来发生的退款 / 争议。

供应商失败、超时或进程中断可能只留下请求审计,不能当作完成。页面保留原确认供手动恢复,成功 / 失败都重新读取购买、事件、余额、账本及审计。功能本地协议验收使用真实 SDK 和生产 Worker,但供应商响应受控;真实 Stripe 测试账户与四国币种流程仍按 I6 独立验收,不把本地结果宣称为真实交易。

带原因调整积分 ​

填写非零整数增减量与 5—500 字符原因,复核后确认。单次绝对值最多 1,000,000,扣减后余额不能低于零,也不能超过数据库整数上限。只允许本站 Origin 和实际近期登录会话;窗口与 Better Auth 共用 24 小时,过期先重新登录。锁等待后再次检查实际会话及角色,已撤销会话拒绝。

调整调用原有事务账本服务,记录独立 adjustment 类型;不伪造购买、任务扣费、退款或支付证明,不带任务 / 购买关联。未初始化钱包按本站欢迎积分规则在同一事务初始化,并记录独立 welcome。明确选择的封禁账号可修正账目,封禁本身不改变;增加积分仍保留支付审核限制,不自动填补 / 改写购买差额或解除限制。

余额、账本和 credits.adjustment 审计在同一事务提交;审计记录执行者、目标、原因、增减量、实际前后余额 / 审核状态和账本 ID。审计失败会回滚余额、账本,以及本次新建的钱包 / 欢迎积分。用户账本只保存通用调整说明,详细维护原因保存在管理审计。

请求 ID 与账号权限变更共用执行者命名空间,改变动作、对象、原因或金额的重用拒绝。相同请求只返回已处理,不把历史余额冒充当前余额;中途消费后重试不会恢复旧余额。账本存在却没有对应审计时拒绝继续,并要求排查,不能声称已经记录新的调整。页面失败保留原 ID 供手动重试,没有自动重试;每次结束重新读余额、账本和审计。

人工调整与任务预扣 / 返还、支付冲正共用钱包锁。账号锁采用 NO KEY UPDATE 保持账本外键的 KEY SHARE 可用;执行者账号先于会话锁定,与凭据管理一致。原生并发验收曾检出完整 UPDATE 锁造成的等待环,修复后验证独立连接同时调整、预扣、支付冲正及后续退款,余额与账本合计一致。

带原因恢复任务 ​

先选择账号并刷新任务记录。重试 / 取消按钮按当前状态显示;填写 5—500 字符原因,复核后再确认。实际近期登录、角色与未撤销会话在事务锁等待后重查;只接受本站 Origin,不接受客户端传入的尝试上限、扣费状态或任务所有者。每个管理员的任务恢复最多每分钟 10 次请求,重放也计入;读取不计入。

重试复用原任务服务:保留处理器、原尝试次数 / 上限、收费快照和原积分预扣,不重新扣费或增加预算。只有当前可恢复状态可以重试;超额尝试、已退款、未知处理器 / 版本、不可恢复故障、失效输入、容量用尽、支付审核限制和封禁账号均不能绕过。按钮只是提示,最终以服务器对新鲜状态的校验为准。

取消未运行的任务按原规则结束并释放输入保留,原积分服务只退款一次。正在运行或待核对的任务仅记录取消请求,仍保留原扣费;由持有实际租约的执行器结束 / 核对并结算。页面提示“请求已记录”,不将该提示冒充中断完成或已退款;刷新查看后续状态。封禁账号不能重试,但管理员可以取消其既有保留任务清理账目,账号不会自动解封。

任务状态、输入保留、退款与 task.retry / task.cancel 审计在同一事务提交;审计失败全部回滚。审计仅保存任务 ID、实际前后状态 / 扣费状态、尝试次数、派发版本、已知故障码及取消请求时间。原始输入、文件名、摘要、参数和私有结果不进入管理接口 / 审计。

请求 ID 与账号 / 积分变更共用执行者命名空间。相同动作、任务和原因只能提交一次;响应丢失可沿用 ID 手动重试,改变内容复用会拒绝。任务后来完成、取消或退款后,旧重放不会重新执行或恢复过去状态。前端不自动重试,每次请求结束重新读取任务、账本和审计。

重试事务提交后才发送 Queue 消息;队列发送失败或进程中断时,已提交的任务由原有数据库待派发记录和维护流程恢复。审计记录的是管理请求已提交,不宣称 Queue / 执行已完成;重复派发仍由原执行版本与租约保护。

封禁及在途任务 ​

当前支持永久封禁与显式解封,不接受过期时间,避免未经审计的自动恢复。封禁删除所有实际会话并拒绝后续登录,新私有请求没有有效身份;解封不会复活旧会话,需重新登录。

已经接受的后台任务继续原执行、扣费、取消和退款规则,封禁不额外取消或重复退款;不承诺中断所有已完成身份检查的在途请求。用户 API Key 已检查新鲜账户状态,封禁、失去邮箱验证或匿名会拒绝后续调用,见用户密钥教程。

审计检索与历史保留 ​

管理页的审计面板可填写对象、执行者和请求编号。使用完整编号精确匹配,不按邮箱、原因片段或通配符猜记录;填写多个条件时取交集。编辑输入不会立即查询,点击检索后从第一页开始;清空恢复全部历史,刷新重新向服务端核对权限和记录。每页最多 20 条,按记录时间和记录编号倒序。失败提示出现时不继续展示先前缓存结果,查询只读,不改变权限、账本、任务或审计。

请求编号是审计操作的去重标识,不是用户任务的原始请求摘要、登录凭据或供应商密钥。页面同时展示请求编号和审计记录编号,方便核对一次操作;同一 UUID 可由不同执行者使用,不能据此认定是同一人或唯一一项操作。需要单独定位时再填写执行者和对象编号。维护命令的 operator:<标识> 也可以检索,不能把维护者自报标识当作身份认证证据。

输入原请求编号,或复制带 :completed 的完成记录编号,都会读取该请求及其完成记录。支付对账和旧结账关联可成对核对;只有请求记录时仍可能失败或在处理中。历史审计只证明记录中的操作发生过,不能用旧完成记录推断当前支付已到账、任务已成功或账号仍有原权限;继续查看对应业务资源的当前状态。

增量 0034_admin_audit_request_lookup.sql 只为跨执行者请求检索增加索引,不改变旧表或审计内容。新站应用完整历史;本地一次性验收库已验证实际索引和查询。正常主预览仍保持 0012 / 13 条历史,不自动升级;旧表已有请求字段,检索仍兼容,但没有新增索引的站点需要在明确数据库升级时完成完整增量,不能手工跳过中间迁移。

默认保留审计,不提供前端删除、自动到期或清空按钮。账号删除不会连带删除历史对象 / 执行者编号;封禁和角色撤销也不删除历史。审计同时是重复行政请求、初始化 / 恢复历史和权益变更的证据,不能直接套用普通通知、使用事件或营销名单的定时清理。归档文件保留清理也不删除源库审计;复制一份备份不代表数据库里的去重证据可以删除。具体站点的保留期限、隐私安排与生产归档仍需要另行确定,本轮不引入未经验收的自动删除流程。

验收与排查 ​

旧订阅结账恢复位于管理页的订阅视图,具体人工检查与用户后续恢复见未标记旧结账核查。只补原会话关联,原购买阻塞仍保留;原因、原尝试和会话编号在本页审计展示。读供应商与确认分开,确认保留同一请求编号供失去响应后重试。当前会话或本地原请求发生变化时,重新核查,不能使用过期的核查摘要强行提交。

sh
bun run test -- --run
bun admin:validate
bun admin:validate-tasks
bun admin:validate-payments
bun admin:validate-operator
bun typecheck
bun lint
bun db:check
bun config:check

admin:validate、admin:validate-tasks 与 admin:validate-payments 各自创建独立本地数据库、应用完整历史、启动生产 Worker bundle;前两者禁止外部请求,对账验收仅以受控响应接收实际 SDK HTTP,最后销毁数据库 / Worker / 资源目录;不迁移当前配置数据库,不创建真实管理员。

admin:validate-payments 同时验旧结账人工关联:真实站点管理员 / 来源门禁、多个候选 / 当前状态变化保留待核查、原生审计触发器故障回滚、同请求恢复与重放,以及账号持有人使用原核查接口继续结账。旧请求记录为一次性库中的明确测试数据;供应商读取使用真实 SDK 与受控 HTTP,不发送真实付款请求。

同一验收还读取实际关联操作的请求 / 完成审计,按对象、执行者和完成编号组合检索,验证真实权限、严格输入及 PostgreSQL 请求索引。可选只读页面复验:bun app:build 后运行 ADMIN_AUDIT_UI_ACCEPTANCE=1 bun admin:validate-payments,登录上面的测试管理员,按日志提供的对象、执行者和请求编号在审计面板检索。完成后创建该次日志所示私有目录中的 browser-stop 文件;脚本核对审计总数、积分未变及原请求仍可查询后,销毁一次性资源。此开关与另外两种支付 / 旧结账页面验收互斥,不读取主预览数据。

可选界面复验:先运行 bun app:build,再运行 ADMIN_CHECKOUT_UI_ACCEPTANCE=1 bun admin:validate-payments。脚本提供独立本地管理页、测试账单主体和原会话编号;登录测试管理员 admin-payments@acceptance.example.test,密码 LocalPaymentAdministrator2026!,选择旧账单测试账号并在订阅视图核查 / 确认。验收原因填写 Browser legacy checkout verification;完成后创建日志中该次私有目录的 browser-stop 文件。脚本先核对实际关联、两条审计、原用户恢复及积分未变,再清理自己的 Worker / 数据库 / 目录。不要用真实账号或主预览数据复验,也不要同时开启旧积分对账界面开关。

已验证:明确初始化、团队 / 站点分权、财务筛选分页 / 私有字段、封禁撤销会话及新任务拒绝、账号 / 积分审计故障回滚、八请求去重 / 竞争扣减 / 交叉降权、旧会话失权、未审计端点拒绝;页面确认 / 取消 / 失败重试与近期登录。原生实际连接同时执行人工调整、任务预扣及支付冲正,后续退款与账本合计一致。任务恢复另验八请求去重 / 重试取消竞争、实际 Queue / R2 结果下载、审计触发器故障回滚、旧请求不复活任务、封禁与速率门禁;既有失败尝试为明确控制的元数据,重试执行来自实际消费者。浏览器使用独立测试账号,未修改主预览权限。

问题排查方向
菜单不显示 / API 403查 user.role、验证、封禁;团队角色不等于站点角色
提示近期登录重新登录,不关闭 freshness
最后一位管理员不能降权先明确授权另一位已验证且活跃的管理员
变更 500查日志 / 数据库;刷新状态与审计,保留原 ID 重试
旧封禁重试仍解封正确重放行为;新封禁需重新确认和新 ID
新 API 缺字段检查迁移,确保数据库和 bundle 版本匹配

admin:validate-operator 独立创建一次性本地 PostgreSQL,以实际 production 模式 CLI 验只读计划、显式文件覆盖错误 shell、owner / 迁移 / 审批 / 环境 / 数据库门禁、8 并发一次授权、双候选恢复竞争、真实审计故障回滚及原计划恢复、降权后的重放。它不连接远程资源,验收后销毁一次性数据库、角色与私有计划 / 配置。管理员审计页展示外部维护者、环境及站点。

可选用户 API Key 已本地验收并复用原权益 / 幂等规则;后续继续增长模块和真实外部环境验收。I9 与整体目标继续进行。

供语言模型读取:llms.txt · llms-full.txt
采用 MIT 许可证。