Repository navigation
feat(gateway): forward /api/time to the time service - #151
Merged
Merged
Conversation
The Time page needs GET /api/time/report. The gateway now requires a time peer and forwards /api/time behind both locks, hiding the session cookie as for every service. mise run up starts the gateway once time is healthy, and the end-to-end gateway names the peer too.
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.
Brief
Goal. The gateway forwards
/api/time/*to thetimeservice behind both of its locks, the Tailscale identity and the session, and hides the session cookie from time. The Time page (time-page) can then callGET /api/time/report. The sixth oftime-tracking's twelve steps (decision 181); the homelab already names the peer (codedogapp/homelab#42).Scope.
services/gateway:timebecomes a required peer, and/api/timeis registered with the other services' routes.timein every hand-builtBAKHYARD_PEERS, and in the forwarding, lock and hidden-cookie tables.process-compose.yaml: the gateway namestimeon 8088 and waits for it to be healthy.apps/web/playwright.config.ts: the E2E gateway namestime.homelab-timeandtime-gatewaymarked done); setup.md.Out of scope.
time-page) and the time service itself.home-weekortime-attention).Acceptance criteria.
timepeer, and names it among the missing peers in name order./api/time/reportreaches time's/time/reportunchanged.mise run upstarts the gateway once time is healthy.mise run checkis green.What changed
services/gateway/main.go:upstreamsgainstime, andpeers()reads it between pulls and todos, so its error falls in name order. The local istimeURL, so that it doesn't shadow thetimepackage's name.services/gateway/router.go:proxy.Register(api, "time", …)in the API group, behind both locks andsession.Hide. The E2E build'sopenRoutesshareswire, so it forwards time too.peers_test.go: time in the forwarding table, awithPeers("time")row, and apeerNames()helper. The full list is now written once rather than four times; withtime, it no longer fit in 100 columns.lock_test.go: the 401 row, and the row that checks time never gets the cookie.open_test.go: the open gateway's forwarding row.headers_test.go,main_test.go:timein their peers.process-compose.yaml: the gateway'sBAKHYARD_PEERSnamestime=tcp://127.0.0.1:8088, anddepends_onwaits for it.apps/web/playwright.config.ts: the E2E gateway namestime(nowhere, like the others), and the comment's port range reads 8080 to 8088.docs/plan.md: the §0 row; §8.2 markshomelab-time(codedogapp/homelab#42) andtime-gatewaydone. §4.3's peers and §4.9'sdepends_onnow list every peer: notify and nudge had been missing since they landed.docs/setup.md: the gateway waits for time too.QA
Mutations: 13 of 13 caught (
files/qa-time-gateway/mutate.py):session.Hide; registered under another name; forwarded to todos; peer optional; its error out of order; read as todos; kept as pulls;BAKHYARD_PEERS has no peer "time"), and Playwright's web server fails;depends_on, it doesn't wait for time.process-compose up --dry-runchecks only the file's shape, so nothing inmise run checkpins these two; plan §0 already has the idea of a check that would.Live (
live.py, 21 checks, all passed), with the real gateway and time frommise run build, a QA session in the dev database (deleted after), and Jira off:bin/gatewaywith every peer but time exits 1 and names time alone.GET /api/time/reportgets time's own 404 "Jira is not set up", with the gateway's security headers. HEAD gets 404 with no body, and POST gets time's own 405 andAllow. Another path under/api/timegets time's 404,/api/timesdoesn't reach time, and a cross-site POST gets 403.The local dev stack doesn't start on this Mac today, for reasons outside this step: notes' vault folder (
BAKHYARD_VAULT) is gone, and notify and nudge have no databases or VAPID key here. The live run therefore merged a second process-compose file that replaces only those three commands with stand-ins answering/healthz. The gateway's and time's blocks ran as committed.Review
No blocking findings. Non-blocking:
timeURLbreaks its neighbours' naming pattern, for the reason above.-tags e2ebuild failsTestOnlyTheEndToEndBuildIsOpenby design: the test pins the default build as locked, andmise run testruns only the default build.Gates
mise run checkpassed locally:gen:check; govulncheck (none);-race, Go coverage 95.9% total (the gateway package 91.8%);tsc, knip,pnpm audit;SonarQube Cloud runs on demand (decision 132).
Merged under the user's standing OK (2026-10-26): merge once CI's
checkis green, and review everything at the end.