Merged
Conversation
Member
nahime0
commented
May 5, 2026
- Add apiauth package for Bearer token derivation and middleware
- Protect API endpoints with Bearer-token authentication
- Add passphrase subcommand to set or rotate the API passphrase
- Document passphrase-based API authentication
- Track empty internal/assets/dist for go:embed
- Tighten config file permissions to 0o600
- Scrub passphrase from Wails GetConfig binding
- Allow Authorization header in CORS preflight
- Standardize stdout/stderr for passphrase subcommand
- Warn when env var would override a passphrase rotation
- Test ResolvePassphrase priority ladder
- Warn about short passphrase before asking for confirmation
- Warn loudly when API server starts without authentication
- Flag env/config divergence in passphrase --show
- Document subtle invariants in apiauth and playground
- Harden API passphrase authentication
- Document hardened API authentication
- Remove unreachable search extractor code
The bearer token is derived from a passphrase stored in the config file. On --api startup, prompt for one if missing, save it, derive the token, and print it to stderr. The playground HTML page stays public; all data endpoints require Authorization: Bearer or ?token= for SSE clients. The passphrase is stripped from /api/config responses.
`lazyagent passphrase` always prompts (double-entry confirmation), saves the new passphrase to the config, and prints the derived bearer token. `--show` is read-only and prints the token for the configured passphrase or LAZYAGENT_API_PASSPHRASE without writing.
http-api.md gains an Authentication section with the PBKDF2 algorithm parameters, a pinned test vector, and reference snippets in JS, Swift, Kotlin, and shell. Recipes, CLI reference, configuration, quickstart, architecture, and roadmap are updated to reflect the new behavior and the passphrase subcommand.
The //go:embed all:dist directive in internal/assets/assets.go fails with 'no matching files found' on a fresh clone because frontend/dist/ hasn't been built yet. Keep an empty .gitkeep so go build works without running 'make build' first; ignore everything else placed inside internal/assets/dist/ (the Makefile copies the real bundle in).
The config file now carries the API passphrase, so anyone who can read it can derive the bearer token. Create with 0o600, chmod existing files on every save so old 0o644 configs get tightened on first upgrade-write, and tighten the parent directory to 0o700.
SessionService.GetConfig() is exposed to the Svelte frontend via Wails IPC. The HTTP /api/config handler already zeroes the field; mirror that here so the secret never crosses the IPC boundary either. Otherwise any script the Webview loads (or DevTools) can read the passphrase and derive the bearer token.
Cross-origin clients (a future web companion app served from a different origin, or the playground when --host is on a non-default address) need to send Authorization: Bearer. Without listing it in the preflight allow-list browsers reject the request.
`lazyagent passphrase --show` now writes only the raw bearer token to stdout so it can be captured in a pipe (TOKEN=$(lazyagent passphrase --show)). Everything else, including the rotation flow, keeps all output on stderr — same convention as the --api setup banner — so a piped invocation cannot accidentally land a token in someone else's pipe.
If LAZYAGENT_API_PASSPHRASE is set, the next `--api` start uses it regardless of what's saved in the config. Without a warning, a user running `lazyagent passphrase` to rotate would see the new bearer token printed but the next server start would still accept the old one — confusing footgun.
Cover env-var precedence, configured-value fallback, whitespace handling on both sources, and the ErrNoTTY path when no source is available. The interactive TTY branch is left to manual testing.
Previously the warning landed AFTER the user had already typed the passphrase twice; aborting meant rerunning the command. Surface the warning between the two prompts so Ctrl+C is a usable escape.
Empty bearerToken disables auth as a deliberate test/opt-out hook. Log a clear warning so an accidentally-empty value (e.g. via a typo'd env var pipeline) is surfaced instead of silently running an open server.
When both LAZYAGENT_API_PASSPHRASE and the config file are set but hold different values, the env var wins at --api start. Print a note so a user who just rotated and forgot to unset the env var sees the mismatch instead of being puzzled by a stale token.
ConstantTimeCompare leaks length on mismatch — call out why that's fine here (fixed 43-char tokens, length is public). Note in the playground that the bearerToken global is XSS-safe today only because no third-party scripts are loaded; flag it for future maintainers.
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.