v1.39.0.0 feat: buildFetchHandler factory unblocks gbrowser submodule consumption#1511
Merged
Conversation
Add buildFetchHandler(cfg: ServerConfig): ServerHandle in browse/src/server.ts.
Refactor start() to delegate handler construction to the factory and read env
once via resolveConfigFromEnv(). Wire the beforeRoute hook (runs after the
tunnel surface filter, before per-route dispatch).
Auth is now cfg-driven end-to-end. Module-level AUTH_TOKEN const +
initRegistry(AUTH_TOKEN) boot call, validateAuth, and shutdown are deleted;
factory closure owns them. start() threads cfg.authToken into launchHeaded,
the state-file write, and the factory.
initRegistry is idempotent for same-token re-init; throws clearly for
different-token re-init. __resetRegistry() test helper added (mirrors
__resetConnectRateLimit). Existing tests that did rotateRoot() ->
initRegistry('fixed-token') swap to __resetRegistry() to avoid the new guard.
14 factory contract tests added covering ServerHandle shape, auth wiring,
validation throws, hook semantics across both surfaces, and registry
idempotency.
Source-pattern tests in dual-listener.test.ts and server-auth.test.ts
updated for the new identifiers (handle.fetchLocal/fetchTunnel, authToken,
shutdownFn).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
E2E Evals: ✅ PASS8/8 tests passed | $1.40 total cost | 12 parallel runners
12x ubicloud-standard-8 (Docker: pre-baked toolchain + deps) | wall clock ≈ slowest suite |
# Conflicts: # CHANGELOG.md # VERSION # package.json
# Conflicts: # CHANGELOG.md # VERSION # browse/src/server.ts # package.json
kairin
pushed a commit
to kairin/gstack
that referenced
this pull request
May 17, 2026
… consumption (garrytan#1511) * feat: buildFetchHandler factory unblocks gbrowser submodule consumption Add buildFetchHandler(cfg: ServerConfig): ServerHandle in browse/src/server.ts. Refactor start() to delegate handler construction to the factory and read env once via resolveConfigFromEnv(). Wire the beforeRoute hook (runs after the tunnel surface filter, before per-route dispatch). Auth is now cfg-driven end-to-end. Module-level AUTH_TOKEN const + initRegistry(AUTH_TOKEN) boot call, validateAuth, and shutdown are deleted; factory closure owns them. start() threads cfg.authToken into launchHeaded, the state-file write, and the factory. initRegistry is idempotent for same-token re-init; throws clearly for different-token re-init. __resetRegistry() test helper added (mirrors __resetConnectRateLimit). Existing tests that did rotateRoot() -> initRegistry('fixed-token') swap to __resetRegistry() to avoid the new guard. 14 factory contract tests added covering ServerHandle shape, auth wiring, validation throws, hook semantics across both surfaces, and registry idempotency. Source-pattern tests in dual-listener.test.ts and server-auth.test.ts updated for the new identifiers (handle.fetchLocal/fetchTunnel, authToken, shutdownFn). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * chore: bump version and changelog (v1.39.0.0) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
RyotaKun
pushed a commit
to RyotaKun/gstack
that referenced
this pull request
May 18, 2026
… consumption (garrytan#1511) * feat: buildFetchHandler factory unblocks gbrowser submodule consumption Add buildFetchHandler(cfg: ServerConfig): ServerHandle in browse/src/server.ts. Refactor start() to delegate handler construction to the factory and read env once via resolveConfigFromEnv(). Wire the beforeRoute hook (runs after the tunnel surface filter, before per-route dispatch). Auth is now cfg-driven end-to-end. Module-level AUTH_TOKEN const + initRegistry(AUTH_TOKEN) boot call, validateAuth, and shutdown are deleted; factory closure owns them. start() threads cfg.authToken into launchHeaded, the state-file write, and the factory. initRegistry is idempotent for same-token re-init; throws clearly for different-token re-init. __resetRegistry() test helper added (mirrors __resetConnectRateLimit). Existing tests that did rotateRoot() -> initRegistry('fixed-token') swap to __resetRegistry() to avoid the new guard. 14 factory contract tests added covering ServerHandle shape, auth wiring, validation throws, hook semantics across both surfaces, and registry idempotency. Source-pattern tests in dual-listener.test.ts and server-auth.test.ts updated for the new identifiers (handle.fetchLocal/fetchTunnel, authToken, shutdownFn). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * chore: bump version and changelog (v1.39.0.0) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
buildFetchHandler ships — gbrowser v0.6.0.0 (phoenix overlay) can now consume gstack as a submodule and compose overlay routes on top of the browse server's dispatch.
buildFetchHandler(cfg: ServerConfig): ServerHandlefrombrowse/src/server.ts. CLI delegates to the same factory.AUTH_TOKENconst + bootinitRegistrycall,validateAuth, andshutdownare deleted; factory closure owns them so embedders' browsers actually get closed on shutdown.beforeRoutehook wired: runs after the tunnel surface filter, before per-route dispatch. ReturnsResponse→ short-circuit; returnsnull→ fall through to gstack. JSDoc now includes a security warning about not returning privileged data from the hook without re-checking auth (the hook fires for missing AND invalid bearer).initRegistrygains idempotency: same token = no-op, different token = throws clearly. New__resetRegistry()test helper mirrors__resetConnectRateLimit.browse/test/server-factory.test.tscover the ServerHandle shape, auth wiring, validation throws, hook semantics across both surfaces, and registry idempotency.Test Coverage
COVERAGE: 14/14 new paths tested (100%) | 28 server-factory tests pass | 154 tests across 6 directly-affected files pass
Pre-Landing Review
Pre-landing review ran during /plan-eng-review (clean) and Codex outside-voice in plan mode. All findings incorporated into the plan and the implementation. Key Codex findings addressed:
Bun.serve()return — capturedEval Results
No prompt-related files changed — evals skipped.
Plan Completion
All plan decisions (D1 through D14) accepted by the user and implemented. The CEO scope-expansion decision (D12) pulled the "real factory" refactor into this PR rather than deferring — module-level
AUTH_TOKEN/validateAuth/shutdownall deleted in favor of factory-scoped equivalents.Pre-existing test failures (not caused by this PR)
browse/test/server-auth.test.tshas 4 pre-existing failures verified againstorigin/main(via git stash) before this branch's work began:/activity/history requires authentication(marker mismatch:Sidebar endpoints→Sidebar chat endpoints ripped)/activity/history has no wildcard CORS header(same root cause)connect command status fetch body has no undefined variable references(CLI_SRC marker mismatch)pair-agent disables parent PID monitoring via BROWSE_PARENT_PID=0(CLI_SRC marker mismatch)These are source-pattern test drift unrelated to the factory work. Captured for a future cleanup PR.
Test plan
bun test browse/test/server-factory.test.ts— 28/28 passbun test browse/test/token-registry.test.ts— 49/49 passbun test browse/test/skill-token.test.ts— 15/15 passbun test browse/test/browser-skills-e2e.test.ts— 8/8 passbun test browse/test/browser-skill-commands.test.ts— 29/29 passbun test browse/test/dual-listener.test.ts— 25/25 pass (was 25/25 on main, no regression)🤖 Generated with Claude Code