| event_payload |
{"ref":"refs/heads/main","befo {"ref":"refs/heads/main","before":"470495fbe7a9692bbb9ef869546e0050c9c73b7e","after":"b673ff8c2e248dbea016f88702215123aa58fd03","compare_url":"https://gitea.g-hi.com/luoanwu/haimate/compare/470495fbe7a9692bbb9ef869546e0050c9c73b7e...b673ff8c2e248dbea016f88702215123aa58fd03","commits":[{"id":"b673ff8c2e248dbea016f88702215123aa58fd03","message":"fix(ci): 修复 CI 恒红两处根因——测试计数被 ANSI 吞掉、篡改 JWT 构造可能零改动\n\n远端 CI 自 2026-08-14 起每次推送都红,共 7 次,无人当真。实测根因有二,\n都与本地环境差异有关,本机绿盘无法暴露(这正是 G14 不可被本地证据替代的原因)。\n\n根因一:假红——测试计数在 CI 下恒为 0\n`CI=true` 时 turbo 给子进程输出着色,实际字节是\n`Tests \\x1b[22m \\x1b[1m\\x1b[32m140 passed`;countPassedTests 的\n/Tests\\s+(\\d+)\\s+passed/ 匹配不到转义序列,于是本地 380、CI 0,\n报成「expected \u003e= 380, got 0」这种看似灾难性回归的消息。\n测试其实全过,坏的是计数器。修复:匹配前先剥 ANSI。\n注意这类假红不会被负向测试或空转测试发现——它们都在本地跑。\n\n根因二:flaky——「篡改 JWT」有约 1/64 概率篡改了个寂寞\ntampered 把签名第 5 位替换成 'A',但 payload 含 exp=now+600,签名每次都变;\n当该位恰好就是 'A' 时,产出的是与合法 token 逐字节相同的串,验签通过,\n断言 401 收到 200。base64url 64 字符 → 每次运行约 1.6% 触发,双后端同款。\n修复:先读该位,改成一个必定不同的字符。这类 flake 会悄悄削弱安全断言。\n\n验证:CI=true 条件下本地复现两处失败,修复后 pnpm check:runtime\nstatus=passed、testsPassed=380(地板 380)。\n\nCo-Authored-By: Claude Opus 5 \u003cnoreply@anthropic.com\u003e\n","url":"https://gitea.g-hi.com/luoanwu/haimate/commit/b673ff8c2e248dbea016f88702215123aa58fd03","author":{"name":"luoguoguo","email":"luoguoguo@gmail.com","username":""},"committer":{"name":"luoguoguo","email":"luoguoguo@gmail.com","username":""},"verification":null,"timestamp":"2026-08-17T16:52:28-07:00","added":[],"removed":[],"modified":["apps/api-fastify/test/security.http.test.ts","apps/api-nestjs/test/security.http.test.ts","scripts/check-runtime-acceptance.mjs"]}],"total_commits":0,"head_commit":{"id":"b673ff8c2e248dbea016f88702215123aa58fd03","message":"fix(ci): 修复 CI 恒红两处根因——测试计数被 ANSI 吞掉、篡改 JWT 构造可能零改动\n\n远端 CI 自 2026-08-14 起每次推送都红,共 7 次,无人当真。实测根因有二,\n都与本地环境差异有关,本机绿盘无法暴露(这正是 G14 不可被本地证据替代的原因)。\n\n根因一:假红——测试计数在 CI 下恒为 0\n`CI=true` 时 turbo 给子进程输出着色,实际字节是\n`Tests \\x1b[22m \\x1b[1m\\x1b[32m140 passed`;countPassedTests 的\n/Tests\\s+(\\d+)\\s+passed/ 匹配不到转义序列,于是本地 380、CI 0,\n报成「expected \u003e= 380, got 0」这种看似灾难性回归的消息。\n测试其实全过,坏的是计数器。修复:匹配前先剥 ANSI。\n注意这类假红不会被负向测试或空转测试发现——它们都在本地跑。\n\n根因二:flaky——「篡改 JWT」有约 1/64 概率篡改了个寂寞\ntampered 把签名第 5 位替换成 'A',但 payload 含 exp=now+600,签名每次都变;\n当该位恰好就是 'A' 时,产出的是与合法 token 逐字节相同的串,验签通过,\n断言 401 收到 200。base64url 64 字符 → 每次运行约 1.6% 触发,双后端同款。\n修复:先读该位,改成一个必定不同的字符。这类 flake 会悄悄削弱安全断言。\n\n验证:CI=true 条件下本地复现两处失败,修复后 pnpm check:runtime\nstatus=passed、testsPassed=380(地板 380)。\n\nCo-Authored-By: Claude Opus 5 \u003cnoreply@anthropic.com\u003e\n","url":"https://gitea.g-hi.com/luoanwu/haimate/commit/b673ff8c2e248dbea016f88702215123aa58fd03","author":{"name":"luoguoguo","email":"luoguoguo@gmail.com","username":""},"committer":{"name":"luoguoguo","email":"luoguoguo@gmail.com","username":""},"verification":null,"timestamp":"2026-08-17T16:52:28-07:00","added":[],"removed":[],"modified":["apps/api-fastify/test/security.http.test.ts","apps/api-nestjs/test/security.http.test.ts","scripts/check-runtime-acceptance.mjs"]},"repository":{"id":74,"owner":{"id":5,"login":"luoanwu","login_name":"","source_id":0,"full_name":"","email":"law@g-hi.com","avatar_url":"https://gitea.g-hi.com/avatar/627574a890388a2aadc80ab38d22f3a0","html_url":"https://gitea.g-hi.com/luoanwu","language":"","is_admin":false,"last_login":"0001-01-01T00:00:00Z","created":"2026-01-30T16:28:30+08:00","restricted":false,"active":false,"prohibit_login":false,"location":"","website":"","description":"","visibility":"public","followers_count":0,"following_count":0,"starred_repos_count":0,"username":"luoanwu"},"name":"haimate","full_name":"luoanwu/haimate","description":"","empty":false,"private":false,"fork":false,"template":false,"mirror":false,"size":5661,"language":"","languages_url":"https://gitea.g-hi.com/api/v1/repos/luoanwu/haimate/languages","html_url":"https://gitea.g-hi.com/luoanwu/haimate","url":"https://gitea.g-hi.com/api/v1/repos/luoanwu/haimate","link":"","ssh_url":"git@gitea.g-hi.com:luoanwu/haimate.git","clone_url":"https://gitea.g-hi.com/luoanwu/haimate.git","original_url":"","website":"","stars_count":0,"forks_count":0,"watchers_count":1,"branch_count":1,"open_issues_count":0,"open_pr_counter":0,"release_counter":0,"default_branch":"main","archived":false,"created_at":"2026-08-15T06:22:30+08:00","updated_at":"2026-08-18T07:42:38+08:00","archived_at":"1970-01-01T08:00:00+08:00","permissions":{"admin":true,"push":true,"pull":true},"has_code":true,"has_issues":true,"internal_tracker":{"enable_time_tracker":true,"allow_only_contributors_to_track_time":true,"enable_issue_dependencies":true},"has_wiki":true,"has_pull_requests":true,"has_projects":true,"projects_mode":"all","has_releases":true,"has_packages":true,"has_actions":true,"ignore_whitespace_conflicts":false,"allow_merge_commits":true,"allow_rebase":true,"allow_rebase_explicit":true,"allow_squash_merge":true,"allow_fast_forward_only_merge":true,"allow_rebase_update":true,"allow_manual_merge":false,"autodetect_manual_merge":false,"default_delete_branch_after_merge":false,"default_merge_style":"merge","default_allow_maintainer_edit":true,"avatar_url":"","internal":false,"mirror_interval":"","object_format_name":"sha1","mirror_updated":"0001-01-01T00:00:00Z","topics":[],"licenses":[]},"pusher":{"id":5,"login":"luoanwu","login_name":"","source_id":0,"full_name":"","email":"5+luoanwu@noreply.localhost","avatar_url":"https://gitea.g-hi.com/avatar/627574a890388a2aadc80ab38d22f3a0","html_url":"https://gitea.g-hi.com/luoanwu","language":"","is_admin":false,"last_login":"0001-01-01T00:00:00Z","created":"2026-01-30T16:28:30+08:00","restricted":false,"active":false,"prohibit_login":false,"location":"","website":"","description":"","visibility":"public","followers_count":0,"following_count":0,"starred_repos_count":0,"username":"luoanwu"},"sender":{"id":5,"login":"luoanwu","login_name":"","source_id":0,"full_name":"","email":"5+luoanwu@noreply.localhost","avatar_url":"https://gitea.g-hi.com/avatar/627574a890388a2aadc80ab38d22f3a0","html_url":"https://gitea.g-hi.com/luoanwu","language":"","is_admin":false,"last_login":"0001-01-01T00:00:00Z","created":"2026-01-30T16:28:30+08:00","restricted":false,"active":false,"prohibit_login":false,"location":"","website":"","description":"","visibility":"public","followers_count":0,"following_count":0,"starred_repos_count":0,"username":"luoanwu"}}... |