Skip to content

Commit b9222dc

Browse files
test(plugin-sharing): size the three scrypt cases near vitest's 5000 ms default to their measured work (#22426)
Fixes #22418 Clause-②: no ## What changes Three cases in `packages/plugins/plugin-sharing` get an explicit per-case timeout, sized to the work each one measures. Every other scrypt-reaching case in the package keeps vitest's 5000 ms default; the enumeration below gives each one's reading and the reason. | Case | Work (scrypt derivations) | Slowest `Test Core` reading | Budget | |:--|:--|:--|:--| | `share-link-password-webcontainer.test.ts:95`, "a password whose NFKC form differs from its input is one password on both paths" (the card's case, `:72` on `ca135dcc`) | 4 pure-JS + 4 native | timed out at 5030 and 5039 ms; 5515 ms projected | `17_000` | | `share-link-password-webcontainer.test.ts:74`, "a hash minted on WebContainer verifies natively, and the reverse" | 3 pure-JS + 3 native | 4136 ms | `13_000` | | `share-link-password.test.ts:481`, "no log line carries the presented password, on any outcome" | 9 native | 3805 ms | `12_000` | Spelled the way this repo spells a per-case budget, as the third argument of `it`: two named constants in the webcontainer file and a literal `12_000` in the other. A comment beside each records the rule, the derivation count and the readings, so the next author can re-size from a fresh reading. Not touched: the scrypt parameters (N, r, p), any production file, the vitest config, `testTimeout` anywhere, and the case bodies. No skip, no quarantine, no retry. No changeset: only two `*.test.ts` files change, and the package's `files[]` is `dist`, `README.md` and `CHANGELOG.md`. ## The rule and the margin - **Which cases get a budget:** a case whose slowest CI reading is over half of the 5000 ms default. The default leaves every other case that has a CI reading at least 2x headroom over its slowest reading, and 2x is above the largest spread one case showed between the two CI runs: 1.88x (`/resolve still accepts the ?password= query parameter`, 588 ms in one run and 1104 ms in the other). - **How big:** 3x the slowest CI reading, rounded up to the next second. 3x covers that measured 1.88x spread with room for a heavier shard. The suspected trigger for these reds, per the card, is a shard re-pack (`040184752c`, #22368), which can change a shard's load again without touching this package. - **The NFKC case's reading is projected, because CI cut it off at the timeout.** Its derivations are 4/3 of the cross-verify case's (4 + 4 against 3 + 3), and the cross-verify case read 4136 ms in the same run, so the projection is 5515 ms. The 4/3 ratio checks out locally: the two cases read 926 and 675 ms idle (1.37x), and 5557 and 4682 ms under contention (1.19x). Under contention the projection overestimates, so it errs toward a larger budget. ## Readings **CI** (per-case durations from vitest's default reporter in the two red `Test Core (5/6)` job logs on the card, read through the job-log API): job `113665992253` (push, `e75dceddd7`) and job `113668129564` (PR #22215 merge of `e75dceddd7`). The log API returns only the last 5000 lines of a 19k to 48k line log. In both red jobs, plugin-sharing's last 24 files fall in that window, and the two `share-link-eligibility.test.ts` cases do not. Three hourly scheduled `Test Core (5/6)` jobs (`113678118904` on `ca135dcc`, `113663806311`, `113649948997`) and the two green jobs on the card had no plugin-sharing lines in their windows. The direct REST log download is refused by this container's egress proxy, so no other log was reachable. **Local** (a 4-vCPU container; every timing run was taken under the shared verify lock, before the gate battery started, with no other run alongside; the load average was 0.2 when the work began). The census and idle readings use `--maxWorkers=2`. The contention runs pin the four scrypt-reaching files to one core beside 5 busy loops on that core, with `--maxWorkers=1`. That load was picked because the NFKC case's CI-to-local ratio is at least 5.4x (at least 5030 ms against 926 ms). Case by case, it reads 0.95x to 1.48x the slowest CI reading, across the 22 cases that read over 1 s in CI and passed under it. So it is a load as heavy as the red shard, or heavier. | Case | Contention, before (`ca135dcc`) | Contention, after (`616794ce1`) | Idle, before | Idle, after | |:--|:--|:--|--:|--:| | NFKC (webcontainer `:95`) | **`Test timed out in 5000ms`** (5024 ms) | passed, 5557 ms | 958 ms | 833 ms | | cross-verify (webcontainer `:74`) | passed, 3935 ms | passed, 4682 ms | 675 ms | 681 ms | | no-log (`share-link-password.test.ts:481`) | **`Test timed out in 5000ms`** (5067 ms) | passed, 5016 ms | 789 ms | 789 ms | | whole contention run, 4 files | 2 failed, 94 passed (96) | 96 passed (96) | | | | idle run, the two named files | | | 48 passed (48) | 48 passed (48) | The before contention run reproduces the card's failure shape: the same case, as a timeout and not an assertion. It also shows the no-log case is the next one to go. ## The enumeration pin: every case in the package that runs a scrypt-class derivation The only scrypt-class key derivation in the package is `share-link-password.ts`: `deriveKeyNode` (`node:crypto` scrypt) and `deriveKeyPureJs` (`@noble/hashes` scrypt). A test reaches them through `hashShareLinkPassword` / `verifyShareLinkPassword`, through `ShareLinkService.createLink` with a password, through `resolveToken` against a stored `scrypt$` hash, or through the legacy upgrade. The list is measured, not grepped: a temporary vitest setup file, never committed, wrapped `node:crypto`'s `scrypt` and `scryptSync`, synced them into the builtin ESM namespace, and counted the calls per case. It ran over the whole package at `ca135dcc`: 40 files, 1002 cases, 1002 census rows. **52 cases in 4 files reach a derivation**: - `share-link-password-webcontainer.test.ts`: 4 cases; - `share-link-password.test.ts`: 42 of its 44 cases. The two others are the injected-hasher case and the authenticated list-route case; - `share-link-internal-columns.test.ts`: 4 cases; - `share-link-eligibility.test.ts`: 2 cases. Pure-JS derivations cannot be counted that way, because `@noble/hashes` is a native ESM namespace. They are counted by reading the four webcontainer cases, which are the only cases in the package that set a WebContainer signal (a grep for `STACKBLITZ`, `/bin/jsh` and `webcontainer` across the package's tests finds no other). "Local, idle" is the census run. "CI" is the push / PR red run. | File:line at HEAD | Case | scrypt work | Local, idle (ms) | CI (ms), push / PR | Budget | |:--|:--|:--|--:|:--|:--| | `share-link-password-webcontainer.test.ts:95` | a password whose NFKC form differs from its input is one password on both paths | 4 pure-JS + 4 native | 926 | **timed out** at 5030 / 5039 | **17_000 ms** = 3 × 5515 (projected), rounded up | | `share-link-password-webcontainer.test.ts:74` | a hash minted on WebContainer verifies natively, and the reverse | 3 pure-JS + 3 native | 675 | 4136 / 3688 | **13_000 ms** = 3 × 4136, rounded up | | `share-link-password-webcontainer.test.ts:121` | the pure-JS key is byte-identical to node:crypto for the same password and salt | 1 pure-JS + 1 native | 216 | 1435 / 1137 | default: 29% of 5000 ms | | `share-link-password-webcontainer.test.ts:64` | the WebContainer path does not touch node:crypto.scrypt; the native path does | 1 pure-JS + 1 native | 270 | 1305 / 1393 | default: 28% of 5000 ms | | `share-link-password.test.ts:481` | no log line carries the presented password, on any outcome | 9 native | 793 | 3805 / 3417 | **12_000 ms** = 3 × 3805, rounded up | | `share-link-password.test.ts:352` | legacy plaintext row › still verifies, refuses a wrong password without touching the row, and is upgraded by the right one | 5 native | 584 | 2163 / 1342 | default: 43% of 5000 ms | | `share-link-password.test.ts:352` | legacy salted SHA-256 row › still verifies, refuses a wrong password without touching the row, and is upgraded by the right one | 5 native | 731 | 2132 / 1815 | default: 43% of 5000 ms | | `share-link-password.test.ts:617` | /resolve sends no-store + Vary on success and on every refusal | 3 native | 280 | 1573 / 938 | default: 31% of 5000 ms | | `share-link-password.test.ts:338` | the verifier accepts the right password and refuses a wrong one, an empty one and an unknown form | 4 native | 332 | 1407 / 1356 | default: 28% of 5000 ms | | `share-link-password.test.ts:284` | the list and the redemption result, through the service and through the route, carry no hash | 3 native | 291 | 1387 / 951 | default: 28% of 5000 ms | | `share-link-password.test.ts:617` | /messages sends no-store + Vary on success and on every refusal | 3 native | 289 | 1337 / 942 | default: 27% of 5000 ms | | `share-link-password.test.ts:582` | /resolve never falls back to a raw compare: an undecodable value that IS the raw password is still refused | 2 native | 212 | 1244 / 992 | default: 25% of 5000 ms | | `share-link-password.test.ts:391` | a refused upgrade write does not block the read, leaves the legacy form verifying, and is reported once without the password | 3 native | 260 | 900 / 1138 | default: 23% of 5000 ms | | `share-link-password.test.ts:552` | /messages still serves a raw with a %-escape password sent raw, with no encoding header | 2 native | 174 | 1110 / 896 | default: 22% of 5000 ms | | `share-link-password.test.ts:445` | /resolve still accepts the ?password= query parameter | 2 native | 197 | 588 / 1104 | default: 22% of 5000 ms | | `share-link-password.test.ts:535` | /messages does not guess: the same encoded value with no encoding header is compared raw | 2 native | 195 | 1092 / 955 | default: 22% of 5000 ms | | `share-link-password.test.ts:600` | /messages: the ?password= form still wins, and the header pair is then not read | 2 native | 212 | 1075 / 886 | default: 22% of 5000 ms | | `share-link-password.test.ts:552` | /messages still serves a Latin-1 password sent raw, with no encoding header | 2 native | 187 | 1072 / 822 | default: 21% of 5000 ms | | `share-link-password.test.ts:523` | /messages serves a emoji password sent percent-encoded under utf-8 | 2 native | 196 | 994 / 1046 | default: 21% of 5000 ms | | `share-link-password.test.ts:600` | /resolve: the ?password= form still wins, and the header pair is then not read | 2 native | 188 | 1044 / 828 | default: 21% of 5000 ms | | `share-link-password.test.ts:552` | /messages still serves a raw with a stray % password sent raw, with no encoding header | 2 native | 174 | 1038 / 951 | default: 21% of 5000 ms | | `share-link-password.test.ts:552` | /resolve still serves a raw with a %-escape password sent raw, with no encoding header | 2 native | 183 | 938 / 1033 | default: 21% of 5000 ms | | `share-link-password.test.ts:535` | /resolve does not guess: the same encoded value with no encoding header is compared raw | 2 native | 187 | 988 / 1000 | default: 20% of 5000 ms | | `share-link-password.test.ts:326` | a new link stores scrypt, with no plaintext, and two hashes of one password differ | 2 native | 172 | 710 / 951 | default: 19% of 5000 ms | | `share-link-password.test.ts:523` | /messages serves a CJK password sent percent-encoded under utf-8 | 2 native | 170 | 878 / 950 | default: 19% of 5000 ms | | `share-link-password.test.ts:433` | /resolve accepts the x-share-password header | 2 native | 179 | 712 / 945 | default: 19% of 5000 ms | | `share-link-password.test.ts:445` | /messages still accepts the ?password= query parameter | 2 native | 223 | 943 / 700 | default: 19% of 5000 ms | | `share-link-password.test.ts:552` | /resolve still serves a raw with a stray % password sent raw, with no encoding header | 2 native | 202 | 937 / 738 | default: 19% of 5000 ms | | `share-link-password.test.ts:460` | /resolve refuses a wrong password sent as a header | 2 native | 196 | 841 / 913 | default: 18% of 5000 ms | | `share-link-password.test.ts:552` | /resolve still serves a Latin-1 password sent raw, with no encoding header | 2 native | 210 | 912 / 865 | default: 18% of 5000 ms | | `share-link-password.test.ts:267` | the mint response, through the service and through the route, carries no hash | 2 native | 225 | 799 / 900 | default: 18% of 5000 ms | | `share-link-password.test.ts:433` | /messages accepts the x-share-password header | 2 native | 206 | 824 / 897 | default: 18% of 5000 ms | | `share-link-password.test.ts:305` | the list and the redemption result carry no hash even from an engine that does not strip it | 2 native | 191 | 884 / 895 | default: 18% of 5000 ms | | `share-link-password.test.ts:460` | /resolve refuses a wrong password sent as a query | 2 native | 217 | 894 / 874 | default: 18% of 5000 ms | | `share-link-password.test.ts:523` | /resolve serves a emoji password sent percent-encoded under utf-8 | 2 native | 178 | 843 / 819 | default: 17% of 5000 ms | | `share-link-password.test.ts:582` | /messages never falls back to a raw compare: an undecodable value that IS the raw password is still refused | 2 native | 221 | 795 / 834 | default: 17% of 5000 ms | | `share-link-password.test.ts:460` | /messages refuses a wrong password sent as a header | 2 native | 173 | 773 / 770 | default: 15% of 5000 ms | | `share-link-password.test.ts:460` | /messages refuses a wrong password sent as a query | 2 native | 208 | 652 / 741 | default: 15% of 5000 ms | | `share-link-password.test.ts:523` | /resolve serves a CJK password sent percent-encoded under utf-8 | 2 native | 200 | 616 / 691 | default: 14% of 5000 ms | | `share-link-password.test.ts:568` | /messages refuses an octet that is not UTF-8 with 400 VALIDATION_FAILED, before the token is looked up | 1 native | 87 | 574 / 513 | default: 11% of 5000 ms | | `share-link-password.test.ts:568` | /resolve refuses an encoding the server does not read with 400 VALIDATION_FAILED, before the token is looked up | 1 native | 88 | 550 / 365 | default: 11% of 5000 ms | | `share-link-password.test.ts:568` | /resolve refuses an octet that is not UTF-8 with 400 VALIDATION_FAILED, before the token is looked up | 1 native | 110 | 538 / 484 | default: 11% of 5000 ms | | `share-link-password.test.ts:568` | /messages refuses an encoding the server does not read with 400 VALIDATION_FAILED, before the token is looked up | 1 native | 104 | 537 / 450 | default: 11% of 5000 ms | | `share-link-password.test.ts:568` | /resolve refuses a truncated UTF-8 sequence with 400 VALIDATION_FAILED, before the token is looked up | 1 native | 86 | 446 / 497 | default: 10% of 5000 ms | | `share-link-password.test.ts:568` | /messages refuses a truncated UTF-8 sequence with 400 VALIDATION_FAILED, before the token is looked up | 1 native | 92 | 496 / 455 | default: 10% of 5000 ms | | `share-link-password.test.ts:375` | is not attempted for a switched-off object, whose redemption is refused | 1 native | 96 | 303 / 439 | default: 9% of 5000 ms | | `share-link-eligibility.test.ts:1191` | the `password_hash` shape — NEEDS_PASSWORD and WRONG_PASSWORD both become the unknown-token answer | 5 native | 662 | NOT MEASURED (outside both logs' tail windows) | default (eligibility note below) | | `share-link-eligibility.test.ts:1291` | fail-closed: an object whose schema the engine cannot answer for is refused, not probed | 2 native | 336 | NOT MEASURED (outside both logs' tail windows) | default (eligibility note below) | | `share-link-internal-columns.test.ts:143` | a password-protected link refuses without the password and with a wrong one, and opens with it | 3 native | 318 | 1361 / 1528 | default: 31% of 5000 ms | | `share-link-internal-columns.test.ts:155` | the redemption route answers password-required, refuses a wrong password, and opens with the right one | 3 native | 295 | 1489 / 1289 | default: 30% of 5000 ms | | `share-link-internal-columns.test.ts:130` | the generic read omits both columns; storage holds both | 1 native | 150 | 774 / 566 | default: 15% of 5000 ms | | `share-link-internal-columns.test.ts:182` | the creator's link list carries each link's token, and no hash | 1 native | 95 | 391 / 416 | default: 8% of 5000 ms | **The eligibility note.** Neither `share-link-eligibility.test.ts` case has a CI reading, because both finished before either red log's window opened. They keep the default, on two measured comparisons: - **The same work as the legacy rows.** The `password_hash`-shape case does 5 native derivations, exactly as many as each legacy row, and its idle reading is between theirs: 662 ms against 731 and 584 ms. The legacy rows' slowest CI reading is 2163 ms, 43% of the default. - **Under the contention load it passed,** at 2832 ms (before) and 2902 ms (after), beside the legacy rows at 2714 / 2638 ms and 2800 / 2988 ms in the same runs. That load reads up to 1.48x the CI shard, and the case was still at 58% of the default. Its CI time is NOT MEASURED, and is stated as such rather than inferred into the table. The fail-closed case does 2 derivations and read 336 ms idle and 1113 ms under contention. ## Mechanism assumptions, checked 1. *"Two test files run scrypt-class derivations."* **Four do.** `share-link-internal-columns.test.ts` (4 cases) and `share-link-eligibility.test.ts` (2 cases) reach the derivation through `ShareLinkService`. Neither is anywhere near the budget, so neither is edited, and the file surface stays the two claimed files. 2. *"5030 / 5039 ms for the NFKC case and 1.1 to 4.1 s for its siblings."* Confirmed from the same two job logs: siblings 1305 / 1393, 4136 / 3688 and 1435 / 1137 ms. The logs also show a third case near the budget in the other file, the no-log case at 3805 / 3417 ms. The contention run reproduces it as the next timeout. 3. *"Follow #21920's timeout spelling and margin comment."* **The precedent has no per-case timeout.** #21920 landed as PR #21925 (`7b6c65290`), which states "No global `testTimeout` change, no per-case timeout". It moved a module load out of the clocked window into collection, because that cost was loading, not the case's own work. The shape does not transfer here. The cost here is the case's own work, the triage ruled that work stays, and the derivation's only module load (`@noble/hashes`, on the first pure-JS call) is small: the two one-derivation-per-path cases read 1305 / 1393 and 1435 / 1137 ms in CI. So the spelling follows the repo's own per-case convention instead: the third argument of `it`, with a comment stating why and how much. `packages/drivers/driver-sql`'s "Why the it() below carries an explicit 60_000 budget" blocks are an example. ## Tests and gates All at `616794ce1` (`git rev-parse --short HEAD`), the PR head. - `pnpm --filter '@objectstack/plugin-sharing^...' build` (the dependency closure), under the verify lock: `VERDICT command-exit 0`. - `pnpm --filter @objectstack/plugin-sharing test`, under the lock: `Test Files 40 passed (40)`, `Tests 1002 passed (1002)`, `VERDICT command-exit 0`. - `pnpm --filter @objectstack/plugin-sharing typecheck`, under the lock: `VERDICT command-exit 0`, with `check:test-typecheck: OK`, 3 pre-existing ledgered errors held. `tsc -p tsconfig.test.json --listFiles` counts 40 `src/**/*.test.ts` in the program, both edited files among them. - The two named files, `pnpm --filter @objectstack/plugin-sharing exec vitest run --maxWorkers=2 FILES`: 48 passed (48), before and after. Per-case readings are in the table above. - The contention reproduction, before and after: shown in the readings table above. - Gates: `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` derived 57 commands for this diff, and all 57 exit 0. Three needed a second run, which is declared here: - `check:i18n` and `check:dual-build-cjs-loads` first answered `PREREQUISITE NOT MET` (exit 3, no `dist/`). Each was run again after building its prerequisite (the i18n closure the gate names, then the workspace build), and both exit 0. - `check:type-check-debt` first answered exit 3 because its own build collided with my concurrent closure build: `plugin-webhooks`' DTS step read a half-written `service-messaging` `dist/`. Run again alone, it exits 0. - `--ran` reconciliation: "57 derived famil(ies) accounted for — 57 run, 0 NOT-MEASURED (a DERIVED zero — all 57 recorded an exit code and none of them is 3)". - Lint, narrowed to the two changed files: `eslint --no-inline-config --format json` on both files gives 0 errors and 0 warnings. The narrowing loses nothing, for three reasons: - both files are inside `eslint.config.mjs`'s population, since an ignored file would come back with an ignore warning; - the JSON output counts 2 files; - the config never enables type-aware linting (its own comment says so: no `parserOptions.project`, no typed rules) and loads no import-resolving plugin, so this diff cannot move the verdict on any file it does not touch. The full `pnpm lint` is CI's run. - No ablation leg is needed beyond the before/after pair. The "before" leg is the committed `ca135dcc` tree, which is exactly this change removed, and it was run under the same load as the "after" leg. ## Acceptance notes - `share-link-password.test.ts`'s header lists, as pinned, "the pure-JS scrypt the WebContainer path uses and `node:crypto`'s produce interchangeable hashes". No case in that file pins it: the pin lives in `share-link-password-webcontainer.test.ts`. This is a stale doc bullet, an observation only, and not filed. Carrier: none. - The job-log API returns only a log's last 5000 lines, and this container's egress proxy refuses the REST log download. So per-case CI readings were reachable only for files that finish late in their shard. That is why the eligibility cases have no CI reading. It is an observation about the measuring instrument, not about the code. - Re-sizing: when a budgeted case's derivation count changes, its budget changes by the same ratio, from a fresh CI reading. Lowering N or r to make a case fit is ruled out by the triage on the card. --- _Generated by [Claude Code](https://claude.ai/code/session_01WYYhVJ78u7PhwFViWo1EmQ)_ Co-authored-by: Claude <noreply@anthropic.com>
1 parent c572fe2 commit b9222dc

2 files changed

Lines changed: 33 additions & 3 deletions

File tree

‎packages/plugins/plugin-sharing/src/share-link-password-webcontainer.test.ts‎

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,29 @@ vi.mock('node:crypto', async (importOriginal) => {
2727
const PASSWORD = 'Ünïcödé pass 21839';
2828
const nodeScrypt = vi.mocked(nodeCrypto.scrypt);
2929

30+
/**
31+
* [#22418] Explicit budgets, sized to the measured work. Every case here
32+
* derives scrypt keys at the production parameters (N=16384, r=16) on purpose,
33+
* the pure-JS path at several times the native cost, so a case's wall time is
34+
* its derivation count times what one derivation costs on the shard that runs
35+
* it. vitest's 5000 ms default is a number nobody chose for that work.
36+
*
37+
* The rule: a case whose slowest `Test Core` reading is over half the default
38+
* gets 3x that reading, rounded up to the next second. 3x clears the largest
39+
* spread one case showed between two CI runs (1.88x) with room for a heavier
40+
* shard. The two cases with one derivation per path (slowest reading 1435 ms)
41+
* keep the default, which already leaves them 3.4x. When a case's derivation
42+
* count changes, re-size it from a fresh reading, never by lowering the
43+
* parameters.
44+
*/
45+
/** 3 pure-JS + 3 native derivations; CI readings 4136 and 3688 ms. */
46+
const CROSS_VERIFY_BUDGET_MS = 13_000;
47+
/**
48+
* 4 pure-JS + 4 native; CI timed out at 5030 and 5039 ms, so the reading is
49+
* projected: 4/3 of the 3 + 3 case's 4136 ms in the same run, 5515 ms.
50+
*/
51+
const NFKC_BUDGET_MS = 17_000;
52+
3053
function onWebContainer(on: boolean) {
3154
vi.stubEnv('STACKBLITZ', on ? '1' : '');
3255
vi.stubEnv('SHELL', on ? '/bin/jsh' : '/bin/bash');
@@ -67,7 +90,7 @@ describe('[#21839] share-link password: node:crypto and pure-JS scrypt are inter
6790
expect(await verifyShareLinkPassword(PASSWORD, nativeHash)).toBe(true);
6891
expect(await verifyShareLinkPassword('wrong 21839', nativeHash)).toBe(false);
6992
expect(nodeScrypt).not.toHaveBeenCalled();
70-
});
93+
}, CROSS_VERIFY_BUDGET_MS);
7194

7295
it('a password whose NFKC form differs from its input is one password on both paths', async () => {
7396
// A decomposed e + combining acute, and a fullwidth A: NFKC rewrites both.
@@ -93,7 +116,7 @@ describe('[#21839] share-link password: node:crypto and pure-JS scrypt are inter
93116
expect(await verifyShareLinkPassword(normalised, nativeHash)).toBe(true);
94117
expect(await verifyShareLinkPassword('cafe A 21839', nativeHash)).toBe(false);
95118
expect(nodeScrypt).not.toHaveBeenCalled();
96-
});
119+
}, NFKC_BUDGET_MS);
97120

98121
it('the pure-JS key is byte-identical to node:crypto for the same password and salt', async () => {
99122
onWebContainer(true);

‎packages/plugins/plugin-sharing/src/share-link-password.test.ts‎

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,13 @@ describe('[#21839] how the password travels in', () => {
471471
expect(loggedText(logger)).not.toContain(wrong);
472472
});
473473

474+
// [#22418] An explicit budget, sized to the measured work: one mint and eight
475+
// redemptions are nine native scrypt derivations at the production
476+
// parameters, the most of any case in this file. Its slowest `Test Core`
477+
// reading was 3805 ms, over half of vitest's 5000 ms default, so it gets 3x
478+
// that, rounded up to the next second; the rule and why 3x is in
479+
// share-link-password-webcontainer.test.ts. Every other case here read at
480+
// most 2163 ms and keeps the default.
474481
it('no log line carries the presented password, on any outcome', async () => {
475482
const { http, link, logger } = await protectedConversation();
476483
for (const pw of [PASSWORD, 'wrong one 21839']) {
@@ -481,7 +488,7 @@ describe('[#21839] how the password travels in', () => {
481488
}
482489
expect(loggedText(logger)).not.toContain(PASSWORD);
483490
expect(loggedText(logger)).not.toContain('wrong one 21839');
484-
});
491+
}, 12_000);
485492
});
486493

487494
describe('[#22049] the password header declares its encoding', () => {

0 commit comments

Comments
 (0)