Skip to content

feat(web): Serve a stable console on port 7777 from daemon start - #123

Merged
4ndreello merged 17 commits into
mainfrom
feat/web-access
Sep 25, 2026
Merged

4ndreello merged 17 commits into
mainfrom
feat/web-access

Conversation

@4ndreello

Copy link
Copy Markdown
Owner

Make the web console a stable, bookmarkable page on port 7777 that answers as soon as the daemon is up.

After #119 the console lived in the daemon, but it still started on demand on port 3100, and each web child minted a fresh token. A saved bookmark hit 403 after any restart, and localhost never got the cookie set for 127.0.0.1.

What changes:

  • The daemon starts the web child right after start() resolves, without awaiting it, on web.port from the config (default 7777). A new --preferred-port child argument falls back to an ephemeral port on any listen error. --port stays explicit, with no fallback.
  • The token is shared across children and restarts through ~/.run-agent/web-token (mode 0600, published with link so a racing reader never sees a partial file). Deleting the file rotates it.
  • The session cookie carries Max-Age=31536000 and is re-sent on every page visit with a valid cookie.
  • A page GET on localhost answers 302 to the same path on 127.0.0.1. Cookies are host-only (RFC 6265 §5.1.3), so without this the bookmark on localhost would always be forbidden.
  • The 403 page text tells the user to run codedeck ui once.
  • web.ensure gets explicit port rules. A request with port reuses a matching child. A request with preferredPort restarts a child that was not started for that port. A request with neither reuses. Starts are serialized, and a waiting request re-evaluates with its own params. The spec's Supersedes table lists the web-daemon ACs this replaces (WD-02, WD-03, WD-42, WD-44 and others).
  • scripts/pty-gate.sh and scripts/rename-gate.sh now kill their isolated daemon on exit. Otherwise the gate's web child would hold 7777 with another token.

DEFAULT_WEB_PORT moved to src/config/web-port.ts so the daemon can read it without importing src/web (WD-28 boundary). src/web/server.ts re-exports it.

One known rough edge is left for a follow-up. A child started with --port 7777, followed by a command without --port, restarts even though port and token do not change, which drops in-flight requests. Reusing whenever running.port === preferredPort would fix it.

Spec, tasks and the Verifier report live in .specs/features/web-access/. The Verifier passed all 25 ACs and killed 28 of 28 injected faults after one test-only fix round.

WA-17 now names daemon URLs only: the in-process fallback prints its own page line inside startWebServer, so a notice could not precede it.
Describe the daemon-owned console on web.port, the stable token file, the year-long cookie and the localhost redirect in the protocol doc. The pty and rename gates now kill their isolated daemon on exit instead of leaving it behind.
Close the Verifier's surviving mutants: the Host and POST rejection tests now assert the spec's forbidden body, and a source check pins that the --web-child entry feeds parseWebChildArgs into runWebChild. Also fix the spec coverage line and the tasks status header.
The Verifier passes all 25 acceptance criteria and kills 28 of 28 mutants after one fix round. Two candidate lessons come from the mutants that survived the first pass.
@sonarqubecloud

Copy link
Copy Markdown

@4ndreello
4ndreello marked this pull request as ready for review September 25, 2026 02:10
@4ndreello
4ndreello merged commit 93a397d into main Sep 25, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant