Skip to content

fix(relay-runtime-workers): 撤销重判次数耗尽改为拒绝升级,控制对象异常不再让 jti 永久被拒 - #198

Merged
Owlbay merged 2 commits into
mainfrom
fix/workers-revocation
Nov 2, 2026
Merged

Owlbay merged 2 commits into
mainfrom
fix/workers-revocation

Conversation

@Owlbay

@Owlbay Owlbay commented Nov 2, 2026

Copy link
Copy Markdown
Collaborator

变更摘要 / Summary

中文:Workers 中继撤销判断的两处失败方向(审计 BA-56、BA-57)。

  • 根因 1:edgeUpgrade 的重判循环 retry < 2 用完后即使 epoch !== revocationEpoch 也退出循环,按最后一次可能过期的判定登记连接;isRevoked 在第 3 次仍过期时返回「未撤销」。现在循环结束后 epoch 仍变了就放掉名额并拒绝本次升级(4401 relay_token_invalid,客户端重连即可);isRevoked 次数耗尽时按已撤销处理且不写缓存。
  • 根因 2:controlStub().isRevoked 抛异常时 catch 里 revoked = true 并写入缓存,而命中 revoked 缓存不看 TTL,一次瞬时失败让该 jti 永久被拒(直到下一次 invalidate() 或缓存清空)。现在异常仍按已撤销处理,但不写缓存。

English: Two fail-direction fixes in the Workers relay revocation check (audit BA-56, BA-57).

  • Root cause 1: after retry < 2 ran out, edgeUpgrade left the loop even though epoch !== revocationEpoch and admitted the connection on a possibly stale decision; isRevoked returned "not revoked" on a stale third attempt. Now, if the epoch still changed after the loop, the slot is released and the upgrade refused (4401 relay_token_invalid, the client reconnects); isRevoked treats exhausted re-checks as revoked and does not cache it.
  • Root cause 2: when controlStub().isRevoked threw, the catch cached revoked = true, and a cached revoked entry ignores the TTL, so one transient failure rejected the jti until the next invalidate() or cache purge. Errors are still treated as revoked but are no longer cached.

关联 issue / Related issues

Closes #192

改动范围 / Scope

  • 中继 Workers 运行时 / relay Workers runtime(packages/relay-runtime-workers)
  • docs(CHANGELOG Unreleased)

契约与协议变化 / Contract and protocol changes

无 / None

数据库迁移 / Database migrations

无 / None

测试 / Testing

新增 packages/relay-runtime-workers/test/revocation.test.ts(4 条),修复前 3 条失败(控制对象异常后 jti 仍被拒、次数耗尽放行、升级重判耗尽仍登记),修复后全过。 / New test/revocation.test.ts (4 cases); 3 failed before the fix (jti still rejected after a transient error, exhausted re-check admits, exhausted upgrade re-decision still registers) and all pass after.

  • 单元测试 / Unit tests(pnpm test):relay-runtime-workers 65 passed、relay-workers 3 passed
  • 集成测试 / Integration tests: 无 / None
  • 跨仓端到端 / Cross-repo e2e: 无 / None
  • 镜像 / Images: 无 / None
  • pnpm check、pnpm go:check(未动 Go,用一次性 PostgreSQL / Redis 容器跑通)

检查清单 / Checklist

需要维护者提供的外部条件 / External prerequisites

无 / None(Workers 部署由维护者执行 / Workers deployment is done by maintainers)

已知限制 / Known limitations

测试通过替换对象内部的 controlStub / policy 注入失败,没有走真实的并发撤销。 / The tests inject failures by replacing the object's controlStub / policy, not through real concurrent revocations.

@Owlbay
Owlbay force-pushed the fix/workers-revocation branch from e885302 to 0c3ee8c Compare November 2, 2026 21:08
@Owlbay
Owlbay merged commit 6cb32c6 into main Nov 2, 2026
5 checks passed
@Owlbay
Owlbay deleted the fix/workers-revocation branch November 2, 2026 21:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant