feat: allow loopback auth bypass in development - #15
Conversation
Keep non-development modes behind one-time launch tokens and strict session authentication even when Next rewrites NODE_ENV in bundled route code. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: Val Alexander <bunsthedev@gmail.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
Pull request overview
This PR introduces an explicit “development auth mode” that permits sessionless access only for loopback requests (after Host/Origin validation), while keeping strict session+token auth for production, test, and other environments. It also adjusts the launch URL behavior so development can print a plain URL while non-development environments print a tokenized fragment URL.
Changes:
- Add a runtime auth-mode signal (
COVEN_MEMORY_RUNTIME_AUTH_MODE) derived fromNODE_ENV, and use it to gate development-only session bypass. - Introduce
createLaunchUrlto emit bare URLs in development and one-time-token fragment URLs otherwise, and wire it intoserver.ts. - Update route/test coverage and documentation to reflect the development vs production behavior split.
Reviewed changes
Copilot reviewed 14 out of 14 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| src/server/request-guard.ts | Enables development-only sessionless behavior after loopback Host/Origin validation, returning session: null when bypassed. |
| src/server/request-guard.test.ts | Adds coverage for the development bypass and session preservation behavior. |
| src/server/launch-url.ts | Adds helper to create a dev (plain) vs non-dev (tokenized fragment) launch URL. |
| src/server/launch-url.test.ts | Tests launch URL behavior and ensures token issuance only when required. |
| src/server/auth-mode.ts | Adds runtime auth-mode derivation and query helpers (configureRuntimeAuthMode, isDevelopmentAuthMode). |
| src/server/auth-mode.test.ts | Verifies strict-by-default behavior and exact development enablement semantics. |
| src/app/api/session/session-routes.test.ts | Adds development-mode coverage for status/logout without a cookie and for revocation behavior when a cookie exists. |
| src/app/api/session/logout/route.ts | Avoids revoking a session when development mode returns session: null (sessionless path). |
| src/app/api/memory/routes.test.ts | Adds development-mode coverage allowing sessionless loopback reads. |
| server.ts | Configures runtime auth mode at startup and switches to printing a computed launch URL. |
| SECURITY.md | Documents the development vs production differences for tokens/sessions and loopback validation. |
| README.md | Updates usage docs to describe development plain-URL behavior and production token exchange. |
| docs/superpowers/specs/2026-07-26-standalone-memory-dashboard-design.md | Updates the design spec with additional hardening/UX/security details and endpoint list changes. |
| .beads/interactions.jsonl | Records bead status/field changes associated with the work. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| import { | ||
| guardLocalRequest, | ||
| guardLoopbackRequest, | ||
| SESSION_COOKIE | ||
| } from "./request-guard"; | ||
|
|
||
| const RUNTIME_AUTH_MODE_ENV = "COVEN_MEMORY_RUNTIME_AUTH_MODE"; | ||
|
|
| it("preserves a valid development session cookie", () => { | ||
| vi.stubEnv(RUNTIME_AUTH_MODE_ENV, "development"); | ||
| const hasSession = vi.fn((value: string) => value === "valid"); | ||
|
|
||
| expect( | ||
| guardLocalRequest( | ||
| request(undefined, { cookie: `${SESSION_COOKIE}=valid` }), | ||
| hasSession | ||
| ) | ||
| ).toEqual({ ok: true, session: "valid" }); | ||
| expect(hasSession).toHaveBeenCalledWith("valid"); | ||
| }); |
| import { GET as status, OPTIONS as statusOptions } from "./status/route"; | ||
| import { runtime } from "@/server/runtime"; | ||
| import { SESSION_COOKIE } from "@/server/request-guard"; | ||
|
|
||
| const RUNTIME_AUTH_MODE_ENV = "COVEN_MEMORY_RUNTIME_AUTH_MODE"; | ||
|
|
| const mockedRuntime = vi.mocked(runtime); | ||
| const id = "d251bc66-3e45-5d03-8d78-1e76919642f9"; | ||
| const RUNTIME_AUTH_MODE_ENV = "COVEN_MEMORY_RUNTIME_AUTH_MODE"; | ||
|
|
| The custom server binds to `127.0.0.1:3737` by default. In development it | ||
| prints a plain loopback URL; open that URL directly. Development skips the | ||
| session cookie only after the strict loopback Host and same-origin Origin | ||
| checks pass. |
| export function normalizeNodeEnvironment( | ||
| nodeEnvironment: string | undefined | ||
| ): string | undefined { | ||
| return nodeEnvironment; | ||
| } |
|
Superseded by #13, which removed launch tokens, browser sessions, logout, and lock state in favor of process-local transport proof. Merging this branch would reintroduce the retired security architecture. |
Summary
NODE_ENV=developmentafter loopback Host and Origin validationTest plan
pnpm test(121 tests)pnpm typecheckNODE_ENV=testlaunch prints a tokenized URL and unauthenticated status returns 401NODE_ENV=developmentlaunch prints a bare URL and unauthenticated status returns 200