Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ USTSACMLand 的定位是苏州科技大学 ACM 集训队官网,当前产品范
- 仓库与生产已完成:阻止普通成员绕过已隐藏的 WebChat 界面直接调用 own-history 写 RPC 创建或修改遗留会话;`202608090001_retire_webchat_mutations.sql` 已应用,撤销 `public`、`anon`、`authenticated` 与 `service_role` 对创建、重命名、归档和消息 upsert,以及两个管理员写 RPC 的执行权限,同时将 relay 请求开关与图片上传全局暂停状态持久化为关闭,保留本人历史读取/删除、个人导出、180 天清理和注销级联边界。生产共 76 个 migration,六个 writer 对三类应用角色全部撤权;部署后没有新增 WebChat 请求或额度账目。证据见 [`docs/evidence/webchat-retirement-production-2026-08-12.md`](./docs/evidence/webchat-retirement-production-2026-08-12.md)。
- 仓库与生产已完成:将管理员 WebChat 配置与成员 AI 权限界面收紧为只读关闭态,禁止通过站内后台修改中转站、模型、Key、预算、请求开关、成员授权或额度;`webchat-config` v14 的合法更新请求固定返回 `410 feature_retired`,同时保留关闭状态和历史用量诊断。管理员界面专项 20 项、Edge Function 专项 15 项、严格 Supabase readiness 通过,并已完成桌面、390px 与宽屏 Chrome 验收;本次仅部署 `webchat-config`,未修改 Secret/Vault、其他函数或 Pages。证据见 [`docs/evidence/webchat-retirement-production-2026-08-12.md`](./docs/evidence/webchat-retirement-production-2026-08-12.md)。
- 仓库已完成:同步 CI 回归到 WebChat 只读关闭态断言,并修复 WebKit 移动学习章节导航与邀请码注册页的异步时序;移动端锚点即时定位、当前章节导航同步收回,E2E 轮询最终可见几何状态并为低速路由加载保留充分等待,相关 WebKit 重复测试 20/20 通过。
- 仓库已完成:修复隐私说明和注册页与生产 Supabase 邮箱确认配置不一致的问题;隐私页现明确注册后需先确认邮箱才能登录,注册页明确确认并登录后再填写竞赛账号和成员资料,更新日期同步为 2026 年 8 月 13 日。定向 19 项测试通过;生产隐私一致性仍待本分支通过 CI、合并和 Pages 部署后关闭
- 仓库与生产已完成:修复隐私说明和注册页与生产 Supabase 邮箱确认配置不一致的问题;隐私页现明确注册后需先确认邮箱才能登录,注册页明确确认并登录后再填写竞赛账号和成员资料,更新日期同步为 2026 年 8 月 13 日。定向 19 项测试通过;PR #149 已合并为 `14e9f2257d51ee3578254ea3a2f1fba3387f1b6c`,`main` CI、Secret scan、Pages build/deploy 与 `production-ranking-audit` 全部成功,Chrome 桌面、390px 和宽屏复核确认新文案可见、旧文案不存在且无横向溢出或控制台 warning/error。证据见 [`docs/evidence/v1-release-gate-audit-2026-08-13.md`](./docs/evidence/v1-release-gate-audit-2026-08-13.md)

## 4. v1.0.0 发布后接入 Cloudflare

Expand Down
50 changes: 37 additions & 13 deletions docs/evidence/v1-release-gate-audit-2026-08-13.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ Vault、Function Secret、Edge Function、cron、Cloudflare 或 GitHub 设置,

## 发布候选与自动门禁

- 候选提交:`b9a9c919948107f6558e09c9174a3a453db788b2`,即 PR #148 的 merge SHA。
- CI run `31660849568`:`verify` 与 `database-security` 均成功;覆盖 Node 22 依赖安装、
- 当前已部署候选:`14e9f2257d51ee3578254ea3a2f1fba3387f1b6c`,即 PR #149 的 merge SHA。
- CI run `31706261357`:`verify` 与 `database-security` 均成功;覆盖 Node 22 依赖安装、
格式、Lint、单元测试、多浏览器 E2E、生产构建、Edge Function 检查、pgTAP 与并发围栏。
- Secret scan run `31660849595`:成功。
- Pages run `31661377686`:`build`、`deploy` 与 `production-ranking-audit` 均成功;生产榜单
复算 job 为 `94327075488`。
- Secret scan run `31706261269`:成功。
- Pages run `31707162024`:`build`、`deploy` 与 `production-ranking-audit` 均成功;生产榜单
复算 job 为 `94471191081`。
- `npm run check:repository-readiness -- greenthree/USTSACMLand` 通过:10 个 workflow、
仓库与 `production-operations` Secret 名称边界、7 个 Actions Variable、Pages 正式地址和
30 天默认 Actions 保留期均符合契约。检查只读取名称,不读取 Secret 值。
Expand All @@ -28,8 +28,8 @@ Vault、Function Secret、Edge Function、cron、Cloudflare 或 GitHub 设置,
`sync-avatar` v1、`member-avatar` v1。除公开头像代理 `member-avatar` 按设计关闭 JWT 验证外,
其余函数均启用 JWT 验证;12 个函数均启用仓库 import map。

本轮只是记录已部署版本,没有重新部署函数。PR #148 只更新证据文档,发布顺序中的数据库、
Edge Function 部署不适用;Pages 已由通过 CI 的精确 merge SHA 自动部署。
本轮没有重新部署函数。PR #149 只更新前端文案、测试和文档,发布顺序中的数据库、Edge
Function 部署不适用;Pages 已由通过 CI 的精确 merge SHA 自动部署。

## 保留窗口与外部服务

Expand Down Expand Up @@ -73,17 +73,17 @@ Edge Function 部署不适用;Pages 已由通过 CI 的精确 merge SHA 自动
- 榜单键盘焦点顺序和焦点可见性再次只读确认正常;完整首页、登录、注册、认证页面和后台
键盘证据继续引用 `docs/evidence/keyboard-focus-browser-2026-07-28.md`。

## 隐私说明一致性缺口与修复
## 隐私说明一致性修复与生产关闭

生产 Supabase 要求完成邮箱确认后才能首次登录,注册成功页也一直要求用户查收确认邮件;
但部署中的 `PRIVACY.md` 对应页面仍写有“注册后账号直接启用”,注册表单说明也暗示可以立即
填写资料。该表述与真实 Auth 配置不一致,因此当前生产隐私一致性门禁不能关闭
但审计时部署中的 `PRIVACY.md` 对应页面仍写有“注册后账号直接启用”,注册表单说明也暗示可以
立即填写资料。该表述与真实 Auth 配置不一致,因此当时生产隐私一致性门禁不能关闭

当前分支已将仓库隐私说明与站内隐私页改为“注册后需先完成邮箱确认,之后才能登录”,将
修复分支将仓库隐私说明与站内隐私页改为“注册后需先完成邮箱确认,之后才能登录”,将
更新日期改为 2026 年 8 月 13 日,并把注册页说明改为“完成邮箱确认并登录后”再填写资料。
`PrivacyPage` 与 `RegisterPage` 定向测试共 19 项通过,新增断言同时要求邮箱确认语义存在、
旧“直接启用”文案不存在。该修复仍需提交、通过 CI、合并并完成 Pages 发布后,才能把生产
隐私一致性条目标记完成
旧“直接启用”文案不存在。该修复已由 PR #149 合并并完成 Pages 发布及生产 Chrome 验收,
生产隐私一致性条目现已关闭

本地 Chrome 又在 `http://127.0.0.1:5173` 只读走通“注册页 → 隐私说明”导航:桌面隐私页
显示新日期和邮箱确认说明,旧文案不存在且没有 Vite 错误覆盖;390px 覆盖下注册说明正常
Expand All @@ -97,6 +97,30 @@ Node `v22.23.2`:`npm ci` 成功安装 443 个锁定包且审计为 0 漏洞;
验证 102 个运行时包的许可证清单、Pages SPA fallback、站点元数据、方形图标和 bundle 预算;
仅保留既有 Assistant 分块超过 Vite 500 kB 提示阈值的非失败警告。

## PR #149 合并、部署与生产验证

- PR #149 的已验证 head 为 `c6cc6d36ebe4189f345d1e02030f931c8b3b3405`,合并提交为
`14e9f2257d51ee3578254ea3a2f1fba3387f1b6c`。PR 的 `verify`、`database-security` 与
`gitleaks` 全部成功;没有在检查完成后追加提交。
- `main` CI run `31706261357` 与 Secret scan run `31706261269` 均成功并精确覆盖 merge
SHA。Pages run `31707162024` 的 build、deploy 和 `production-ranking-audit` 全部成功;
榜单审计重新计算生产公开排名并通过 3 项检查。
- 使用 Chrome 对正式 `/privacy` 与 `/register` 完成 1440、390 和 1920 三种视口只读复核。
隐私页显示“更新日期:2026 年 8 月 13 日”和“注册后需先完成邮箱确认,之后才能登录”;
注册页显示“完成邮箱确认并登录后,可以填写竞赛账号和其他成员资料”。两页旧文案匹配数均
为 0,页面级横向溢出为 0,控制台没有 warning/error。现有真实登录态只让提交按钮显示
“已登录”并保持禁用;本轮没有填写或提交表单、取得 CAPTCHA 或发送认证请求。
- `npm run check:cloudflare-domain` 通过:正式域名、旧 Pages 地址跳转、SPA fallback、HTML
`max-age=600`、指纹资源 `max-age=31536000` 与二次缓存 `HIT` 均符合契约。生产脚本资源已
切换到本次发布的指纹文件。
- GitHub Rulesets API 确认 `Protect main release branch` 处于 active,匹配默认分支、没有
bypass actor,当前维护账号也不能绕过;规则要求 PR、分支最新、review thread 解决以及
`verify`、`database-security`、`gitleaks`,并禁止删除和 non-fast-forward。旧 Branch
Protection API 返回 `404` 是 Rulesets 仓库的接口差异,不是保护缺失。`github-pages`
environment 的自定义部署分支策略只允许 `main`。
- 本轮发布只更新 Pages;没有修改 Supabase Auth、数据库、Vault、Secret、Edge Function、
cron、Cloudflare 配置或成员数据,也没有创建正式版本标签。

## 仍阻塞 v1.0.0

1. **Auth `429` 与窗口恢复。** 2026-08-04 的三次受控请求均为
Expand Down
10 changes: 5 additions & 5 deletions docs/release-checklist.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
- [ ] 已记录版本号、候选提交、变更摘要、项目负责人批准和执行 Agent/会话。
- [x] 工作树只包含本次发布审计、隐私文案修复和对应测试;临时截图、导出文件和根目录本地素材未被误纳入。
- [x] 当前候选只修改前端文案、测试和文档,不需要数据库或 Edge Function 部署;合并后仅由受保护 Pages 链路发布。
- [x] 已记录最后一个可用提交 `b9a9c919948107f6558e09c9174a3a453db788b2`、Pages run `31661377686` 和生产 76 个 migration、0 pending;见 [`docs/evidence/v1-release-gate-audit-2026-08-13.md`](./evidence/v1-release-gate-audit-2026-08-13.md)。
- [x] 已记录当前已部署提交 `14e9f2257d51ee3578254ea3a2f1fba3387f1b6c`、Pages run `31707162024` 和生产 76 个 migration、0 pending;见 [`docs/evidence/v1-release-gate-audit-2026-08-13.md`](./evidence/v1-release-gate-audit-2026-08-13.md)。
- [ ] 项目负责人已按 `docs/maintainer-handoff.md` 确认所需供应商权限与高风险操作范围;Agent 只使用当前授权会话,记录不包含账号标识或 Secret。

## 2. 本地与 CI 门禁
Expand Down Expand Up @@ -43,7 +43,7 @@
git diff --check
```

- [ ] GitHub `CI / verify`、`CI / database-security`、`Secret scan / gitleaks` 和部署后的 `production-ranking-audit` 全部通过。
- [x] GitHub `CI / verify`、`CI / database-security`、`Secret scan / gitleaks` 和部署后的 `production-ranking-audit` 全部通过。PR checks、`main` CI run `31706261357`、Secret scan run `31706261269` 与 Pages run `31707162024` 均覆盖已部署 merge SHA `14e9f2257d51ee3578254ea3a2f1fba3387f1b6c`
- [x] Dependabot 当前开放告警为 0;此前 4 条高危开发依赖告警已由 PR #147 修复,并由测试和生产构建验证。
- [x] 当前候选与最近通过的 Actions 只记录脱敏状态、数量和版本;构建日志、测试输出和 Artifact 核对未发现 Secret 或成员私有资料。
- [x] `Encrypted database backup` 最近一次手动任务成功;`MAX_BACKUP_ARTIFACT_BYTES=3500000000` 与 `MAX_STORAGE_OBJECTS=10000` 已按 50 名成员的账号级理论上限配置。最新 Schema v2 备份 run `31622577243` 与恢复 run `31622919641` 成功,Artifact 只包含 `.enc` 和 `.enc.sha256`;工作流在上传前完成 76 个 migration、8 个聚合行数、完整引用图片对象、解密校验和明文清理,Storage 失败时不会发布 database-only 的部分产物。证据见 [`docs/evidence/database-restore-drill-2026-08-13.md`](./evidence/database-restore-drill-2026-08-13.md)。
Expand Down Expand Up @@ -105,14 +105,14 @@
- [x] 正式首页、榜单、成员详情、隐私页、注册、登录、账号页和后台可直达并刷新;2026-08-13 又在独立 Chrome 标签复核 `/`、`/rankings`、`/privacy`、`/register`、`/login`、`/account` 与 `/admin`。
- 遗留关闭检查:普通注册页、成员账号页和主导航不展示推荐计划名称、邀请码、奖励摘要、AI 助手或暂停提示;管理员后台可继续显示遗留配置入口。关闭状态查询失败时成员端同样失败关闭。
- [x] 访客、普通成员、停用成员和管理员看到的导航与路由符合权限;管理员后台保留遗留 WebChat 只读配置入口,成员端不显示该入口。
- [x] 部署后的只读生产门禁拒绝演示回退,并用公开视图和明确允许的只读 RPC 逐页复算全部成员在总榜与各平台榜的排序、柔性平台覆盖总 Rating 和总题数;Pages run `31661377686` 的 `production-ranking-audit` 成功。
- [x] 桌面 1440、390px 移动端和 1920 宽屏视口均无页面级横向溢出;2026-08-13 的 21 个路由/视口组合全部通过
- [x] 部署后的只读生产门禁拒绝演示回退,并用公开视图和明确允许的只读 RPC 逐页复算全部成员在总榜与各平台榜的排序、柔性平台覆盖总 Rating 和总题数;Pages run `31707162024` 的 `production-ranking-audit` 成功。
- [x] 桌面 1440、390px 移动端和 1920 宽屏视口均无页面级横向溢出;2026-08-13 的 21 个基线路由/视口组合以及 PR #149 部署后的隐私页、注册页三视口复核全部通过
- [x] 键盘可完成主要导航、筛选、平台标签、分页和高风险确认;焦点可见且顺序合理。2026-08-13 榜单再次通过只读焦点顺序复核,完整证据见 [`docs/evidence/keyboard-focus-browser-2026-07-28.md`](./evidence/keyboard-focus-browser-2026-07-28.md)。
- [x] 独立 Chrome 站点标签没有捕获与当前部署相关的 error/warn;分享元数据与 `/favicon-192.png`、`/favicon-512.png` 由构建门禁核对。Chrome 扩展注入的 `data:` favicon 不作为站点图标证据。

## 7. 法务、隐私与发布决定

- [ ] `PRIVACY.md`、站内隐私页、第三方数据来源和实际数据生命周期一致。当前分支已修复“注册后账号直接启用”与生产邮箱确认配置的冲突并补 19 项定向测试;仍需合并并完成 Pages 部署后再关闭此项
- [x] `PRIVACY.md`、站内隐私页、第三方数据来源和实际数据生命周期一致。PR #149 已修复“注册后账号直接启用”与生产邮箱确认配置的冲突并补 19 项定向测试;merge SHA `14e9f2257d51ee3578254ea3a2f1fba3387f1b6c` 已由 Pages run `31707162024` 部署,Chrome 三视口确认新日期与邮箱确认说明可见、旧文案不存在且没有横向溢出或控制台 warning/error
- 遗留隐私检查:生产不再向中转站或模型发送新消息;既有私有会话、额度账本和图片元数据仍按当前隐私页、注销和备份边界处理,直至数据自然清理或由成员删除。
- [ ] 已在运维手册核验并填写 Supabase、GitHub Actions 和 Firecrawl 的实际保留窗口、负责人及删除/恢复限制。
- [x] 受控注销已验证三类结果:租约冲突/删除前续期失败或 GitHub 写入/确认失败返回 `503` 且 Auth 用户未删除;错误 owner/target、过期租约、管理员、活动同步或 Storage 所有权阻塞返回 `409` 或失败关闭且账号数据完整;成功时 Auth/Profile 级联、审计匿名化和租约消费在同一事务提交。
Expand Down
10 changes: 8 additions & 2 deletions docs/repository-settings.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@
- 禁止 force push 和删除默认分支。
- 不允许管理员默认绕过;紧急绕过只在故障处理中临时启用并记录原因。

2026-08-13 使用 GitHub Rulesets API 只读回读确认规则集 `Protect main release branch`
处于 `active`,匹配 `~DEFAULT_BRANCH`,没有 bypass actor,当前维护账号也不能绕过。规则实际包含
Pull Request、分支必须保持最新、review conversation 全部解决、上述三个 required checks、禁止
删除和禁止 non-fast-forward。旧 Branch Protection API 对 `main` 返回 `404` 只表示仓库使用
Rulesets,不表示默认分支未受保护;核验时应以 Rulesets API 和有效规则接口为准。

个人仓库只有一名维护者时可以暂不要求他人批准,但仍应通过 PR 和全部状态检查。增加第二名维护者后,至少要求 1 个非作者批准;涉及 migration、RLS、认证、凭据或删除流程的变更建议要求代码所有者复核。

`Deploy GitHub Pages / build` 只在 `main` 的 `CI` workflow 全部成功后由 `workflow_run` 触发,并检出通过 CI 的精确提交;不能作为 PR 合并前检查。CI 失败或 Pages 部署失败时保留上一可用版本,并按运维手册修复或 revert。
Expand All @@ -28,7 +34,7 @@
- 只允许已审查的 GitHub Actions;仓库 workflow 使用完整提交 SHA 固定第三方 Action,并由 Dependabot 提议更新。
- Dependabot security updates 保持启用;每周依赖 PR 必须经过现有测试,不自动合并大版本更新。
- Actions 日志和 artifact 不得包含 Supabase service role、洛谷 Cookie/CSRF、QOJ 密码、Firecrawl key 或成员私有数据。
- 仓库默认 Actions 日志/Artifact 保留建议设为 30 天以内;数据库备份 workflow 继续用 `retention-days: 14` 单独收紧。2026-07-15 GitHub API 核验的仓库默认值仍为 90 天,因此正式发布前需调整或在风险记录中明确接受
- 仓库默认 Actions 日志/Artifact 保留建议设为 30 天以内;数据库备份 workflow 继续用 `retention-days: 14` 单独收紧。2026-08-13 GitHub API 回读的仓库默认值为 30 天,符合当前发布契约

### 备份与注销恢复下限

Expand All @@ -54,7 +60,7 @@ Remove-Item Env:DELETION_RECOVERY_GITHUB_TOKEN
## 安全报告与环境

- 在 **Settings → Security → Private vulnerability reporting** 启用私密漏洞报告。
- GitHub Pages 使用 `github-pages` environment;生产 Secret 只授予必要 workflow,定期清理不再使用的 Secret。
- GitHub Pages 使用 `github-pages` environment;2026-08-13 API 回读确认其自定义部署分支策略只允许 `main`。生产 Secret 只授予必要 workflow,定期清理不再使用的 Secret。
- 启用仓库可用的 Secret scanning / push protection;Gitleaks workflow 是补充门禁,不替代 GitHub 原生保护。
- 若仓库转移到 Organization,先为 Gitleaks Action 配置其要求的组织许可证,或改用不需要外部许可证的固定版本 CLI 扫描方案。

Expand Down
Loading