Password lock UI (#13) - #16
Open
ableinc wants to merge 1 commit into
Open
Conversation
server.password, when set, requires it (or a session token obtained via POST /login) for every route except /healthz, /auth, /login, /, and /ui/*. The browser console stores its session token in sessionStorage, so closing the tab or browser logs the operator out; a daemon restart invalidates every session since tokens are held only in memory. Empty password (the default) keeps today's open behaviour unchanged. Closes #13.
Open
ableinc
marked this pull request as ready for review
August 26, 2026 10:06
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.
Closes #13
What the agent did
Committed as
59a27a7, and the correct pre-configured harness identity (coding-agent-loop[bot]) was used.Summary
Implemented the approved plan for issue #13 — an optional
server.passwordthat gates the control API and web console, with a session token kept insessionStorage(so closing the tab logs the operator out) and no changes to today's behavior when the password is left blank.Files changed:
internal/config/config.go— addedServerConfig.Password;config.example.jsonandREADME.mdupdated to document it (""= disabled).internal/server/auth.go(new) —sessionStore(token issue/valid/revoke, 12h sliding TTL, 10-failures/min login throttle),authEnabled(), and constant-time credential comparison accepting either a live session token or the raw configured password.internal/server/server.go—requireAuthmiddleware (allow-list:/healthz,/auth,/login,/,/ui/*), newGET /auth,POST /login,POST /logouthandlers, andgetConfignow redactsserver.passwordand reportspassword_set.internal/web/assets/{index.html,app.css,app.js}— lock-screen overlay, a Lock button,sessionStorage-based token storage,authHeaders()merged into everyapiFetchcall (including the one raw transcriptfetch), 401 handling that clears the token and re-locks, and aboot()sequence driven byGET /auth.internal/config/config_test.go,internal/server/server_test.go(auth-required/allow-list, login/logout, token reuse, raw-password-as-bearer, throttling, config redaction, and an explicit "no password → every route open" regression), andinternal/web/web_test.go.README.md— config table, sample config, route table, and the "Web interface" section updated per the plan.Verification:
go build ./...,go vet ./..., andgo test ./...all pass except two pre-existing failures ininternal/git(TestWorktreeLifecycle,TestEnsureRepoAppliesIdentityOverridingGlobalConfig) — that package was never touched by this change; the failures are an environment/git-identity artifact of this sandbox, not a regression from this work.Note on the environment: local Go tooling required
GOPATH=/tmp/gopathto download thego1.26.5toolchain pinned bygo.mod(the default~/go/pkg/sumdbpath is read-only in this sandbox). This is only a local verification workaround and required no repository changes.Worth a reviewer's second look: the two "decisions the reviewer may want to overrule" from the plan — accepting the raw password as a bearer credential (keeps
curlone-shot but puts the password on the wire on every call) and/ui/*assets being served unauthenticated (required so the lock screen itself can render).Verification
Tests failed (
make test). This PR is a draft — the failure is reported rather than hidden, so you can judge whether the change is salvageable.Test output (tail)
Changes
Opened automatically by coding-agent-loop (run
13d5a39a-e5c7-43d3-b133-c5307d79f4fa, attempt 2, modelclaude-sonnet-5, cost $2.6031, session46e18e3d-3452-40df-9c35-2c72d59ca8fd). Nothing here has been reviewed by a human yet.