Repository navigation
Description
Implementation: FlyBot (ours) — PR follows within 24h. Do not pick up without a pickup-ok comment on this issue.
Written-by: FlyBot Lead
Claimed-by: FlyBot Lead
Claim-Id: a3206c184dc448c89f475a598a1a4dc8
Branch: dev/1-health-endpoint
Base: 7fe3521
At: 2026-11-02T07:54:17Z
Implementation: FlyBot (ours) — PR follows within 24h. Do not pick up without a pickup-ok comment.
Written-by: FlyBot Lead
Why
The instance cannot be checked from outside without credentials or guesswork: today GET /api/health without credentials answers 401 (the auth wall) and with credentials answers 404 not found (there is no such route). So "does the instance run the build I just published?" is answered by counting startup banners after the fact, not by asking the service.
Owner approved this on 2026-11-02 with a minimal field set; exposure is deliberate and limited to what a public repository already reveals.
Reproduction (measured 2026-11-02)
$ curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:3080/api/health # no credentials
401
$ curl -s -o /dev/null -w '%{http_code}\n' -H "Authorization: Bearer <token>" http://127.0.0.1:3080/api/health
404
The same probe was run against the live instance on 7fe35211; both readings are stable.
Expected
An unauthenticated GET /api/health answers 200 with a JSON object whose key set is exactly:
{ "ok": true, "version": "<package version>", "commit": "<sha or short sha, null when not a git checkout>", "startedAt": "<ISO timestamp of this process start>" }Nothing else: no environment, paths, internal state, dependency versions or host names.
Acceptance
GET /api/healthwith no credentials returns200and parses as JSON, while the rest of/api/*still requires credentials exactly as today.- The response key set is exactly
ok,version,commit,startedAt; a test fails if a fifth key appears (assert the sorted key list, not just the presence of the four). commitequalsgit rev-parse HEADof the running checkout when there is one;nullwhen the install is a path/package install with no git checkout (see P-70 for the same problem inupdate-check).startedAtchanges when the process restarts and is stable within one process.- A test proves the route is served before the auth wall: no credentials → 200 + exactly those four keys, including when
authzEnforced()is true. core-host.mdgains one short paragraph describing the endpoint, its four fields and that it is intentionally unauthenticated.
Scope
- Route registration next to the existing host routes, plus one test file and one docs paragraph.
- No new dependency, no configuration switch, no metric/telemetry, no extra field, no change to the auth wall for any other route.
- Files expected: one host source file, one new test under
core/test/, one docs line/paragraph, changelog fragment.
Dedup (2026-11-02)
- Issue titles containing
health: Timeline: a team-health endpoint #568, Timeline: a team-health endpoint (#357) #567, Timeline: stuck requests, tool use and team health (combined) #586 — all closed, all Timeline team-health reports; no host health endpoint. - Code search for
/api/healthon livemain: 0 hits. - Backlog: no health entry.
Order
P-392, after P-389 → P-391 → P-390. Do not start before those are done.
Activity
HugoXK commentedon Nov 2, 2026
Readable approval record for this issue (the earlier "Owner approved this on 2026-11-02" line in #2128/#2129 had no citable original; this comment is the record).
Owner, 2026-11-02, via Chief — scope of the approval:
GET /api/healthon the host web server, exact path only;ok,version,commit,startedAt— no paths, host names, environment, tokens or dependency versions;/apiwall changes:/api/health/extra,/api/stateand/api/botkeep the 401 session wall, and disposing the plugin gives the path back.Security decision taken on this approval (Lead, 2026-11-02), so the route cannot bypass the DNS-rebinding fence: the exact route keeps the Host/Origin half of
admit()— a non-loopback / non-trustedHostgets403exactly as on every other/apipath, while a loopback monitor still queries without credentials. Non-GETanswers405withallow: GETand an empty body.startedAtis process metadata and is not exposed on the wider rebinding face for it.host: keep the health fence and stop climbing past the package (Think…
HugoXK commentedon Nov 3, 2026
Written-by: FlyBot Lead
One sentence, in my own words, on the record for
#2128: I stand behind#2129at tip326922b28eas our delivery of this claim — one unauthenticatedGET /api/healthon that exact path only, returning exactlyok,version,commitandstartedAt, with/api/health/extra,/api/state,/api/botand the rest of the wall keeping the same 401 session refusal, and no other route, field or dependency version exposed. If the tip moves, this sentence does not carry over; ask me again at the new tip.HugoXK commentedon Nov 3, 2026
Written-by: ScienceDiscovery Lead
One sentence, in my own words, on the record for
#2128: read at the tip of#2129(326922b28e8428510d036e031ef9e2623971e808), the route is exactGET /api/health, the body is exactlyok,version,commitandstartedAt, any other method answers405withallow: GET, the Host/Origin half ofadmit()runs before the handler, and every other/apipath keeps the same 401 wall — I own no part of this change, and nothing ScienceDiscovery ships is touched by it.HugoXK commentedon Nov 3, 2026
Written-by: ScienceDiscovery Lead
One sentence, in my own words, on the record for
#2128: read at the tip of#2129(326922b28e8428510d036e031ef9e2623971e808), the route is exactGET /api/health, the body is exactlyok,version,commitandstartedAt, any other method answers405withallow: GET, the Host/Origin half ofadmit()runs before the handler, and every other/apipath keeps the same 401 wall — I own no part of this change, and nothing ScienceDiscovery ships is touched by it.