Repository navigation
Commit bcf8a37
test(service-automation): sealed-envelope pin no longer matches short fixture strings against random ciphertext (#30998)
<!-- claude-projects-attribution: {"github_login":"os-tesla"} -->
_Requested by **Tesla** · [project
thread](https://claude.ai/code/project/chan_01AXsQkLFKRdQCqQ3RTr6Jao?thread=cmsg_01AXsQkLFKRdQCqQ3RTr6JaoCRAyW1nbzvK9mcvgPRf542)_
Fixes #30957
Clause-②: no
Metadata-protocol: none
## 维护者速读
- 改了什么:只改一个测试文件。密封信封钉子的夹具值都换成带 `.` 的长字符串,并加一条断言:存进 KV 的信封里一个 `.` 都没有。
- 为什么改:原夹具连接器名是 `crm`,随机 base64url 密文大约每 1,100 次运行就会碰巧含有它,`Test Core`
在无关 PR 上偶发变红。
- 风险与回滚:只动测试,不动生产代码、不发布;回滚即 revert 本 PR。
-
先看:`packages/services/service-automation/src/oauth2-grant/authorization.test.ts`
中 sealed 那一组 describe 的 `begun` 夹具与第一条用例。
- 两分钟验证:`pnpm --filter @objectstack/service-automation exec vitest run
src/oauth2-grant/authorization.test.ts`,预期 11 个用例全绿。
- 需要你做的:无,席位落地。
## What changes
`ADR-0143 D5 — a begun connect is held sealed` in `service-automation`'s
`oauth2-grant/authorization.test.ts`:
- The describe's `begun` fixture now gives every plaintext field the pin
looks for (connector, organization, user, verifier, redirect URI) and
the state a value that carries a `.`. Neither base64url nor the
envelope's JSON frame (`{"v":1,"iv":…,"ct":…,"tag":…}`) ever emits a
`.`, so random `iv` / `ct` / `tag` text can never contain one of those
values by chance.
- The pin asserts that precondition (every looked-for value contains
`.`) and that the stringified stored envelope contains no `.` at all,
then keeps the per-field `not.toContain` loop and the `['ct', 'iv',
'tag', 'v']` key check.
What the pin proves is unchanged: if the store writes any plaintext
field into the KV, it goes red (ablation below). The short `org_a` /
`usr_1` values the card also names are replaced in this describe as
well. Test only, so no changeset (the file is not in the package's
`files`; `skip-changeset`).
Siblings checked (`grep -rn "not.toContain"
packages/services/service-automation/src/oauth2-grant/`): the other hits
match fixed strings against error messages (`app-credential`,
`grant-handle`, `mcp-authorization`, `token-endpoint`), or
`'raw-state-value'` against a fixed prefix plus a hex SHA-256 digest
(`authorization.test.ts`, the KV-key pin). None matches a short value
against random text, so none shares the flake; no other file changed.
## Tests
- `pnpm --filter @objectstack/service-automation exec vitest run
--maxWorkers=2 src/oauth2-grant/authorization.test.ts`: Test Files 1
passed, Tests 11 passed.
<details><summary>Ablation (one leg): the store writes the plaintext
connector beside the envelope</summary>
Via `node scripts/ablation-replace.mjs` on
`src/oauth2-grant/authorization.ts`, `kvPendingAuthorizationStore().put`
changed from `sealPendingAuthorization(state, pending)` to `{
...sealPendingAuthorization(state, pending), connector:
pending.connector }`:
```
ablation-replace: ok mutation landed: anchor 1 -> 0, blob 75c236c -> aa62fda5748e
× the KV holds no verifier, user, organization, instance or redirect URI — only an envelope 7ms
FAIL src/oauth2-grant/authorization.test.ts > ADR-0143 D5 — a begun connect is held sealed (the KV trust boundary) > the KV holds no verifier, user, organization, instance or redirect URI — only an envelope
AssertionError: expected '{"v":1,"iv":"Lzv2WBDpLmRysSC_","ct":"…' not to contain '.'
Tests 1 failed | 10 passed (11)
ablation-replace: ok restored: blob == HEAD (75c236c) and `git diff HEAD` is empty
```
The test imports `./authorization.js` from source, so no dist rebuild
sits between the mutation and the run.
</details>
## Verification
All readings on head `bdbe3023`.
- `dispatch-gates --commands` derived 51 families for the one-file diff
(21 changed lines); all 51 ran locally with exit 0, and `dispatch-gates
--ran` reconciles: "51 derived famil(ies) accounted for — 51 run, 0
NOT-MEASURED".
- First-pass exit 3s were prerequisites, re-run after meeting them:
`check-plugin-teardown-shape --self-test` needed its pinned fixture
commit fetched into the shallow clone; `check:dual-build-cjs-loads`
needed a full workspace build (`turbo run build`, 82/82 tasks).
`check:type-check-debt` hit my own 300 s per-command timeout on the
first pass and passed on re-run.
- `pnpm --filter @objectstack/service-automation typecheck`: exit 0
(includes `check:test-typecheck` over the test layer). `pnpm exec
eslint` on the changed file: exit 0.
- Whole package: `pnpm --filter @objectstack/service-automation exec
vitest run --maxWorkers=2`: Test Files 264 passed, Tests 3431 passed.
<details><summary>Gate record (command :: exit)</summary>
```
node scripts/check-closing-keyword-parity.mjs :: exit 0
node scripts/check-closing-keyword-parity.mjs --self-test :: exit 0
node scripts/check-comment-mask-adoption.mjs :: exit 0
node scripts/check-comment-mask-adoption.mjs --self-test :: exit 0
node scripts/check-comment-mask-corpus.mjs :: exit 0
node scripts/check-dts-emitted.mjs --self-test :: exit 0
node scripts/check-issue-citations.mjs :: exit 0
node scripts/check-plugin-teardown-shape.mjs :: exit 0
node scripts/check-plugin-teardown-shape.mjs --self-test :: exit 0
node scripts/check-tenant-audit-census.mjs :: exit 0
node scripts/check-tenant-audit-census.mjs --self-test :: exit 0
node scripts/ci/assert-turbo-remote-cache.mjs --self-test :: exit 0
node scripts/ci/plan-test-core-shards.mjs --self-test :: exit 0
node scripts/ci/prune-turbo-cache.mjs --self-test :: exit 0
node scripts/docs-audit/check-affected-docs.mjs :: exit 0
node scripts/docs-audit/check-drift-comment.mjs :: exit 0
pnpm --filter @objectstack/spec run check:duration-unit-keys :: exit 0
pnpm check:ci-filter-parity :: exit 0
pnpm check:closed-ceremony-text :: exit 0
pnpm check:cross-package-test-inputs :: exit 0
pnpm check:doc-authoring :: exit 0
pnpm check:driver-memory-census :: exit 0
pnpm check:dts-closure :: exit 0
pnpm check:dual-build-cjs-loads :: exit 0
pnpm check:engine-double-contract :: exit 0
pnpm check:gitlink-declared :: exit 0
pnpm check:issue-citations :: exit 0
pnpm check:keyed-text-bounds :: exit 0
pnpm check:lean-entry-closure :: exit 0
pnpm check:logger-receiver-detach :: exit 0
pnpm check:nul-bytes :: exit 0
pnpm check:objectql-double-limit :: exit 0
pnpm check:org-identifier :: exit 0
pnpm check:package-naming :: exit 0
pnpm check:page-declaration-shape :: exit 0
pnpm check:platform-object-tenancy-census :: exit 0
pnpm check:published-files :: exit 0
pnpm check:query-options-erasure :: exit 0
pnpm check:refd-timer-probe :: exit 0
pnpm check:registry-log-declared :: exit 0
pnpm check:rest-log-spy-declared :: exit 0
pnpm check:slot-lookup :: exit 0
pnpm check:sourcemap-no-sources-content :: exit 0
pnpm check:system-context-census :: exit 0
pnpm check:test-source-alias :: exit 0
pnpm check:tier-file-adoption :: exit 0
pnpm check:type-check-coverage :: exit 0
pnpm check:type-check-debt :: exit 0
pnpm check:undeclared-dep-imports :: exit 0
pnpm check:watch-hint-literal :: exit 0
pnpm check:where-matcher :: exit 0
```
</details>
## Acceptance notes
- The new `expect(stored).not.toContain('.')` is deterministic: the
envelope is `v` (the number 1) plus three base64url strings inside a
JSON frame, none of which can emit `.`. If the envelope format ever
gains a field that may hold a `.`, this line goes red and the fixture
choice needs revisiting, which is the intended signal.
---
_Generated by [Claude
Code](https://claude.ai/code/session_01L9qibyj2zTjgu4ZNg8WmHE)_
Co-authored-by: Claude <noreply@anthropic.com>1 parent 26f5719 commit bcf8a37
1 file changed
Lines changed: 18 additions & 3 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
126 | 126 | | |
127 | 127 | | |
128 | 128 | | |
129 | | - | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
130 | 142 | | |
131 | 143 | | |
132 | 144 | | |
133 | 145 | | |
134 | | - | |
| 146 | + | |
135 | 147 | | |
136 | 148 | | |
137 | | - | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
138 | 153 | | |
139 | 154 | | |
140 | 155 | | |
| |||
0 commit comments