feat(auth): standalone simple-auth fallback with headless prompt + hub token propagation#106
Merged
Conversation
…b token propagation Give devframe a built-in authentication fallback so a tool the author has not explicitly configured is gated out of the box, while a hub can keep authenticating centrally. - Standalone dev server gates by default: an unset (or `true`) `cli.auth` auto-wires the interactive OTP handler and prints its code banner; `false` (or the new `--no-auth` flag) opts out; a handler object passes through. - Client gains `simpleAuth` (default on): on refusal it tries the magic-link OTP, then falls back to a native `window.prompt()` for the code, re-prompting until success or cancel. It only prompts on a top-level, unframed page. - A framed plugin never prompts; it waits for a hub-propagated token. Hubs authenticate once at the top level and hand the token down — via the client host context same-origin, or a new `ConnectionMeta.authToken` for cross-origin iframes that cannot read the hub's localStorage. Created with the help of an agent.
✅ Deploy Preview for devfra ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
antfu
reviewed
Jul 17, 2026
| rpc: undefined!, | ||
| } | ||
| const authToken = getStoredAuthToken(options.authToken) | ||
| const authToken = getStoredAuthToken(options.authToken, connectionMeta.authToken) |
Contributor
There was a problem hiding this comment.
Suggested change
| const authToken = getStoredAuthToken(options.authToken, connectionMeta.authToken) | |
| const authToken = getStoredAuthToken(options.authToken || connectionMeta.authToken) |
so we don't need to change the getStoredAuthToken signaure
Collaborator
Author
There was a problem hiding this comment.
Done in 6c2c3bd — kept getStoredAuthToken's single-arg signature and pass options.authToken || connectionMeta.authToken.
Convert the prose "Default: x" notes on the auth-related options introduced in this branch (`simpleAuth`, `otpParam`, `cli.auth`) to the `@default` tag, matching the convention used elsewhere in the definition types.
…g arg Pass `options.authToken || connectionMeta.authToken` as the single token argument instead of adding a second parameter, per review.
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.
Why
devframe already ships the auth primitives —
createInteractiveAuth(OTP code + magic-link) on the node side, and a client that can exchange a code for a token — but nothing wires them up by default. A tool whose author does nothing runs ungated, and there is no story for a hub to authenticate once and let its plugins ride along.This adds a built-in fallback: a standalone tool is gated out of the box (opt-out), a browser with no configured auth UI can still get in via a zero-UI prompt, and a hub can keep owning authentication centrally.
What
Standalone (cli / spa / served build)
true)cli.authauto-wires the interactive OTP handler and prints its code + magic-link banner once listening.false— or the new composable--no-authflag — opts out. ADevframeAuthHandlerpasses straight through. The five built-in plugins keep their explicitauth: false.Client (
connectDevframe)simpleAuthoption (default on). On a refused connection it tries the magic-link URL OTP first, then falls back to a nativewindow.prompt()for the code — zero UI, so devframe stays headless — re-prompting on a wrong/expired code until success or Cancel.Hub / Vite-DevTools
ConnectionMeta.authTokenfor cross-origin iframes that cannot read the hub'slocalStorage. Managed plugin connections setsimpleAuth: false, so subframes mount already-authorized.Notes
ConnectionMeta.authTokenis documented as hub-served, per-frame only (a token in a fetchable JSON is only as safe as the URL serving it) — the standalone__connection.jsonnever carries one.connectionMeta.authToken→localStorage→ window globals.Tests cover connection-meta token precedence and adapter auth resolution (default gates /
auth: false/--no-auth); the./clientAPI snapshot is updated forsimpleAuth.lint,test(677),typecheck, andbuildall pass.This PR was created with the help of an agent.