Get unstuck

Hint 1: Locate the state that disappears

Each call to createAllocator creates a new next variable. Restart and two-worker tests each create more than one allocator.

Hint 2: Use the reservation contract

The shared store owns uniqueness. Use await store.reserve(key.materialId), not key.label. The store’s rejection should stop allocation.

Reveal the reference patch and explanation
Fixedallocator.mjsJavaScript
export function createAllocator({key, store, encodeNonce}) {
  return async function allocate() {
    const counter = await store.reserve(key.materialId);
    return encodeNonce(counter);
  };
}

The shared store reserves counter 0 for the first material-A allocation and counter 1 after allocator recreation, producing different 12-byte encodings. Two writers and two display labels still use that same material scope. The large-counter case must preserve 9007199254740993 and 9007199254740994 as BigInts. When a two-reservation store rejects its third call, the allocator propagates the error and encryption stops. A new material-B key may start its own counter, because uniqueness is required per actual key, not across unrelated keys.

Compare it with your own fix, then rerun the tests. The editor is not changed when you open this explanation.

Inspect the actual test harness

The browser and the lab download run the same cases, including cases that catch common wrong fixes, such as comparing with one fixture value instead of the real rule. The download includes the complete test adapter and cryptographic fixtures.

Download cases.mjs
How the browser sandbox runs your code

Your code runs in QuickJS 2025-09-13 (quickjs-emscripten 0.32.0) inside a Web Worker, isolated from the page, with a 32 MiB memory limit and a 2.5-second time limit. The test cases and the pass or fail verdict run outside that sandbox, so changing built-ins such as Array.prototype.push cannot change the result. The lab download runs the same cases under Node.js, where your code runs directly.

The same as in current Node.js:

  • ES2025 syntax and built-ins, including Set methods such as intersection, iterator helpers, Promise.try, RegExp.escape and the RegExp v flag

Added to the sandbox so that it behaves like Node.js:

  • structuredClone, Array.fromAsync, queueMicrotask, atob and btoa
  • URL and URLSearchParams, parsed by your browser’s own URL implementation
  • TextEncoder and TextDecoder for UTF-8
  • Intl.Collator and a locale-aware String.prototype.localeCompare
  • console.log and related methods, whose output appears with your results

Not available in the browser sandbox:

  • Timers (setTimeout, setInterval), fetch and other network or storage APIs; the exercises are deterministic and offline
  • Node.js modules and globals: import, require, process and Buffer
  • Web Crypto (crypto.getRandomValues, crypto.subtle); each workshop supplies the cryptographic operations it needs
  • Intl other than Collator: toLocaleString and toLocaleDateString ignore the locale, so numbers have no digit grouping and dates use one fixed format in the device’s time zone
  • using declarations, Symbol.dispose and DisposableStack (explicit resource management)
  • Uint8Array.fromBase64 and toBase64, JSON.rawJSON, Atomics and Error.captureStackTrace

Use the lesson in your own system

The restart test recreates the allocator; it does not restart the browser or reload the module. The pre-existing reservation test also checks that a module-local counter cannot replace the shared store. The supplied store is a deterministic model of an atomic durable reservation service. Building that service, surviving rollback, key retirement, and production GCM usage limits are outside this exercise. The fixed public keys and messages are test fixtures. The XOR demonstration exposes plaintext at known positions, not the AES key; GCM reuse can also break authentication.

Your next task: List the writers sharing a real encryption key in your system. What durable component coordinates them, and what happens after a backup restore or reservation outage?

RFC 5116: AES-GCM nonce reuse

Related guide: AEAD records: AES-GCM nonces, associated data and key limits