Skip to content

test(cloudflare): decouple native-binding coverage from token minting - #1376

Open
Mkassabov wants to merge 2 commits into
feat/email-dev-modefrom
fix/queue-http-token-gate
Open

test(cloudflare): decouple native-binding coverage from token minting#1376
Mkassabov wants to merge 2 commits into
feat/email-dev-modefrom
fix/queue-http-token-gate

Conversation

@Mkassabov

@Mkassabov Mkassabov commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Three Cloudflare binding suites deployed their native-binding workers and their HTTP-token workers in a single stack. The *Http layers mint a scoped AccountApiToken, so a credential without token-creation permission failed the whole deploy — taking down the native-binding coverage, which needs no token:

Unauthorized: Unauthorized to access requested resource
  at AccountApiToken.ts (provider.create)

Cloudflare OAuth credentials have no token-creation scope at all, so this is not recoverable by re-authorizing. On --profile alchemy-testing it meant zero coverage of the R2, KV, and Queue native bindings, presenting as a red suite rather than a gap.

Each suite now deploys the two transports separately and gates only the HTTP half.

Queue and KV split their test.provider in two:

-test.provider("Queue write producer over binding + http", (stack) =>
-  // one deploy: WriteBindingWorker + WriteHttpWorker
+test.provider("Queue write producer over the native binding", (stack) =>
+  // deploys WriteBindingWorker only — no token needed
+
+test.provider.skipIf(!process.env.CLOUDFLARE_TEST_API_TOKENS)(
+  "Queue write producer over a scoped HTTP token", (stack) =>
+  // deploys WriteHttpWorker only

R2 uses a shared beforeAll, so it splits fixtures/stack.ts into a binding stack plus a new fixtures/stack-http.ts and gates at the describe:

+describe("native binding", () => {
+  const stack = beforeAll(deploy(Stack), { timeout: HOOK_TIMEOUT });
+
+describe.skipIf(!process.env.CLOUDFLARE_TEST_API_TOKENS)("http token", () => {
+  const stack = beforeAll(deploy(HttpStack), { timeout: HOOK_TIMEOUT });

The gate sits on the describe rather than the individual tests so the suite's beforeAll never runs at all — runSuite skips a suite's hooks when every test below it is skipped (alchemy-test/src/Runner.ts). Both stacks stay independently inspectable via alchemy tail.

The env var matches CLOUDFLARE_TEST_USER_TOKENS on the UserApiToken lifecycle tests, and each skip comment records the exact error per the entitlement-gating convention.

Result

suite before after
test/Cloudflare/Queue 24 passed, 1 failed 25 passed, 1 gated
R2/Binding + KV/Binding 0 passed, 5 failed 3 passed, 3 gated

The native-binding cases are coverage that was previously lost entirely, not failures that were re-labelled. Confirmed the gates are not inert: with CLOUDFLARE_TEST_API_TOKENS=1 the HTTP tests run and reach the recorded token-creation error.

@Mkassabov Mkassabov changed the title test(cloudflare/queue): decouple native-binding coverage from token minting test(cloudflare): decouple native-binding coverage from token minting Aug 30, 2026
@Mkassabov
Mkassabov force-pushed the feat/email-dev-mode branch from 4d10667 to 2c4f3d5 Compare August 30, 2026 04:36
@Mkassabov
Mkassabov force-pushed the fix/queue-http-token-gate branch from eb03e1b to 10dbc6c Compare August 30, 2026 04:36
@alchemy-version-bot

alchemy-version-bot Bot commented Aug 30, 2026

Copy link
Copy Markdown
Contributor

Install the packages built from this commit:

Alchemy

alchemy

bun add https://pkg.ing/alchemy/a5646bb

@alchemy.run/better-auth

bun add https://pkg.ing/@alchemy.run/better-auth/a5646bb

@alchemy.run/cloudflare-runtime

bun add https://pkg.ing/@alchemy.run/cloudflare-runtime/a5646bb

@alchemy.run/frontend-frameworks

bun add https://pkg.ing/@alchemy.run/frontend-frameworks/a5646bb

@alchemy.run/node-utils

bun add https://pkg.ing/@alchemy.run/node-utils/a5646bb

@alchemy.run/pr-package

bun add https://pkg.ing/@alchemy.run/pr-package/a5646bb

@alchemy.run/floci

bun add https://pkg.ing/@alchemy.run/floci/a5646bb

Distilled

@distilled.cloud/core

bun add https://pkg.ing/@distilled.cloud/core/809f3d8

@distilled.cloud/aws

bun add https://pkg.ing/@distilled.cloud/aws/809f3d8

@distilled.cloud/axiom

bun add https://pkg.ing/@distilled.cloud/axiom/809f3d8

@distilled.cloud/cloudflare

bun add https://pkg.ing/@distilled.cloud/cloudflare/809f3d8

@distilled.cloud/hetzner

bun add https://pkg.ing/@distilled.cloud/hetzner/809f3d8

@distilled.cloud/neon

bun add https://pkg.ing/@distilled.cloud/neon/809f3d8

@distilled.cloud/planetscale

bun add https://pkg.ing/@distilled.cloud/planetscale/809f3d8

Mkassabov and others added 2 commits August 30, 2026 02:18
…inting

`Binding.test.ts` deployed the native-binding producer and the HTTP-token
producer in one stack. The `WriteQueueHttp` layer mints a scoped
`AccountApiToken`, so a credential without token-creation permission failed
the whole test — losing the native-binding coverage, which needs no token:

    Unauthorized: Unauthorized to access requested resource
      at AccountApiToken.ts (provider.create)

Cloudflare OAuth credentials have no token-creation scope at all, so this is
not recoverable by re-authorizing.

Split into two tests with separate deploys. The native-binding case now runs
everywhere; the HTTP case is gated behind `CLOUDFLARE_TEST_API_TOKENS`,
matching the `CLOUDFLARE_TEST_USER_TOKENS` gate on the `UserApiToken`
lifecycle tests.

`pnpm test test/Cloudflare/Queue --profile alchemy-testing` goes from
24 passed / 1 failed to 25 passed / 1 gated.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…inting

Same defect as the Queue suite in the previous commit. `R2/Binding.test.ts`
deployed all six workers (binding + http) from one shared `beforeAll`, and
`KV/Binding.test.ts` deployed all six inline in a single test — so minting
the `AccountApiToken` the `*Http` layers need took down the native-binding
coverage too, which needs no token:

    Unauthorized: Unauthorized to access requested resource
      at AccountApiToken.ts (provider.create)

R2 splits `fixtures/stack.ts` into a binding stack and a new
`fixtures/stack-http.ts`, driven by two `describe`s. The gate sits on the
`describe` rather than the tests so the suite's `beforeAll` never runs at
all: `runSuite` skips a suite's hooks when every test below it is skipped
(`alchemy-test/src/Runner.ts`). Both stacks stay independently inspectable
via `alchemy tail`.

KV splits its single `test.provider` into a native-binding test and a gated
HTTP-token test with separate deploys, matching the Queue shape.

`pnpm test test/Cloudflare/R2/Binding.test.ts test/Cloudflare/KV/Binding.test.ts
--profile alchemy-testing` goes from 5 failed / 0 passed to 0 failed /
3 passed / 3 gated. Verified the gate is not inert: with
CLOUDFLARE_TEST_API_TOKENS=1 the http tests run and reach the recorded
token-creation error.

Claude-Session: https://claude.ai/code/session_01QShcJ78QmS5g3rTfj6qdA5
@Mkassabov
Mkassabov force-pushed the fix/queue-http-token-gate branch from 10dbc6c to a5646bb Compare August 30, 2026 06:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant