Skip to content

Conversation

@kylecarbs
Copy link
Member

@kylecarbs kylecarbs commented Jan 5, 2026

Manually tested to ensure it works. Removed a mistaken duplicate runtime package at internal/api/runtime added during Turbopack migration.

@vercel
Copy link

vercel bot commented Jan 5, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (UTC)
blink Ready Ready Preview, Comment Jan 13, 2026 2:26pm

This PR migrates BLINK_INVOCATION_AUTH_TOKEN from a global environment
variable to use Node.js AsyncLocalStorage for request-scoped context.

## Problem

Previously, auth tokens were stored in a global environment variable that
would get overwritten on each request. This created a race condition when
handling concurrent requests in the Node wrapper:

    Request A: setAuthToken("token-A")
                        Request B: setAuthToken("token-B")  ← Overwrites!
    Request A: model() → reads "token-B" (WRONG TOKEN!)

## Solution

Use AsyncLocalStorage to store auth tokens in request-scoped context:

- Created `blink/internal` module with `runWithAuth()` and `getAuthToken()`
- Wrappers now call `runWithAuth(token, fn)` to establish context
- `model()` function reads token from ALS via `getAuthToken()`

For the internal API server (which makes HTTP calls to Blink Cloud API),
we use a hybrid approach: the closure-based `setAuthToken()` is kept
since HTTP requests cross async context boundaries. The ALS context is
used for direct function calls like `model()`.

## Files Changed

- `packages/blink/src/internal/`: New ALS context module
- `packages/blink/src/agent/agent.ts`: model() uses getAuthToken()
- `internal/runtime/src/`: Updated wrappers and server
- `internal/api/runtime/src/`: Mirror changes

## Tests

Added comprehensive tests for the AsyncLocalStorage context module:
- Context isolation between concurrent requests
- Nested context handling
- Async operation context preservation
Instead of the closure-based setAuthToken, this approach:

1. Patches fetch to add auth header to internal API requests
2. Internal API server reads auth token from request header
3. Uses ALS for direct function calls like model()
4. Falls back to module-level variable for HTTP boundary crossing

The fetch patch reads from ALS first (for code in the same async context),
then falls back to a module-level variable (for code after HTTP hop).
Lambda handles requests sequentially so the fallback is safe there.
For Node.js concurrent requests, ALS is used when available.

Also added 'packages: bundle' to generate scripts to properly resolve
workspace packages during bundling.
- Remove fallbackAuthToken from all wrappers (Node and Lambda)
- Use Symbol.for('@blink/authContext') to create global singleton ALS
- Both bundled wrapper and external blink/internal share same ALS instance
- Agent.fetch() sets up ALS context from x-blink-internal-auth header
- Test fixture now properly sets up ALS context for HTTP handlers

This simplifies the auth token flow: wrapper sets ALS context, all code
(including bundled code in generated wrappers) can read from it via
getAuthToken(). No fallbacks needed.
Move the fetch patching logic into a shared helper function in server.ts.
This is used by both Node and Lambda wrappers to add the auth token
header for requests to the internal API server.
- Fix typecheck error by preserving Bun's fetch.preconnect static property
- Add test for concurrent request auth context isolation
- Add echo-auth-token fixture for testing context propagation
The patched fetch now tries ALS context first (getAuthToken), then falls
back to BLINK_INVOCATION_AUTH_TOKEN env var for backwards compatibility
with older blink package versions that don't have Agent.fetch() with
ALS context re-establishment.

WARNING: The env var approach has race conditions with concurrent requests
in Node.js. It's safe for Lambda (single request at a time) but users
should upgrade to a new blink version for proper concurrent request support.
@kylecarbs kylecarbs merged commit fb0c070 into main Jan 13, 2026
6 checks passed
@kylecarbs kylecarbs deleted the auth-fv1v branch January 13, 2026 14:35
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