0.3.71: the diagnostics gate had no opener — a removal wearing a switch's clothes - #81
0.3.71: the diagnostics gate had no opener — a removal wearing a switch's clothes#81emooreatx wants to merge 1 commit into
Conversation
…ch's clothes
0.3.69 gated `/api/v1/debug/memory` on `ciris_server::diag::enabled()`
(CIRISStatus#73, my own fix for it answering unauthenticated on the published
port). Correct switch. No way to flip it.
`diag::enable()` is called from ciris-server's OWN binary entry point. This
binary does not run that; it calls `serve_with_adapter` as a library. So
`ENABLED` stayed false for the life of every process, `routers()` never mounted
the route, and neither `--diagnostics` (which this binary did not accept) nor
`CIRIS_DIAGNOSTICS=1` (which nothing here read) could change that. The route was
not gated in 0.3.69/0.3.70; it was gone.
Eric found it trying to take the `fordblks` reading this repo has been asking
for, which is the part that stings: the endpoint exists to answer a question we
are actively asking, and I removed it while believing I was securing it.
`mallinfo2` only exists inside the process, so there is no fallback — the
measurement is simply unavailable on those two releases.
Both openers now, matching the sibling exactly:
--diagnostics (its flag, added to our parser)
CIRIS_DIAGNOSTICS=1 (its env, read through `diag::env_requests()`
so the truthy set cannot drift from theirs)
Enabled BEFORE `serve_with_adapter`, because `routers()` asks `enabled()` while
building — flipping it later would be another switch that does nothing.
Still not loopback-bound, and DEPLOY.md now says so where an operator will read
it rather than only in a code comment: the server pairs its gate with
`require_loopback`, an adapter cannot, and the edge stays load-bearing.
117 tests (1 new: the flag parses, takes no value, does not swallow the next
argument, and is off by default).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 72ead42e46
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| | `GET /api/v1/status` (capabilities) | The same response now carries `capabilities` (per-pool rollup with `min_available`, `available`, and per-member `role`/`status`), an `indicator` (Statuspage v2 severity), and `vantage_failure`. The headline is derived from capabilities, not from whichever component is unhappiest — see `FSD/CAPABILITY_MONITORING.md` | | ||
| | `GET /api/v1/ci` | **Substrate build health**: the last 10 GitHub Actions runs per repo (verify → persist → edge → server → agent) as `{repo, runs[]}`, each run one of `success\|failure\|in_progress\|queued\|cancelled`. A ~600-byte projection so a microcontroller can read it in one request; polled server-side with conditional requests (see below). | | ||
| | `GET /api/v1/debug/memory` | **Only mounted when `CIRIS_DIAGNOSTICS=1`** (CIRISStatus#73 — it answered unauthenticated on the published port while ciris-server gated the identical report). The allocator's own accounting — `uordblks` (live) vs `fordblks` (freed-but-held), plus the kernel's `RssAnon`/`VmSwap`. glibc does not zero on `free()`, so only a call from inside the process can tell a live working set from churn the allocator kept. NOT loopback-bound: an adapter router cannot see the peer, so keep it off the public edge | | ||
| | `GET /api/v1/debug/memory` | **Only mounted when `--diagnostics` or `CIRIS_DIAGNOSTICS=1`** (CIRISStatus#73 — it answered unauthenticated on the published port while ciris-server gated the identical report). The allocator's own accounting — `uordblks` (live) vs `fordblks` (freed-but-held), plus the kernel's `RssAnon`/`VmSwap`. glibc does not zero on `free()`, so only a call from inside the process can tell a live working set from churn the allocator kept. NOT loopback-bound: an adapter router cannot see the peer, so keep it off the public edge | |
There was a problem hiding this comment.
Document diagnostics in the configuration sections
Once this commit makes CIRIS_DIAGNOSTICS and --diagnostics functional, the primary setup instructions become contradictory: README.md:20-24 and 87-97 still say there are no environment variables and only two CLI inputs, while .env.example:1-7 explicitly says there is nothing to put in an environment file. Operators reading the Configuration section can therefore overlook or reject the opener advertised here; update those sections and the example alongside this endpoint documentation.
Useful? React with 👍 / 👎.
| // Mirrors ciris-server's own flag. Takes no value; `--diagnostics=1` | ||
| // is accepted too so an operator who types it either way gets what | ||
| // they meant rather than "needs a value". | ||
| "--diagnostics" => diagnostics = true, |
There was a problem hiding this comment.
Reject values on the diagnostics switch
When a deployment renders this boolean as --diagnostics=false, --diagnostics=0, or even a mistyped value, split_once places that value in eq_value but this arm ignores it and enables diagnostics unconditionally. Because the newly enabled endpoint is explicitly unauthenticated and not loopback-gated, a configuration intended to keep diagnostics off can expose it; accept only the documented bare switch (or validate an explicit value rather than treating every value as true).
Useful? React with 👍 / 👎.
0.3.69 gated
/api/v1/debug/memoryonciris_server::diag::enabled()— CIRISStatus#73, my own fix for it answering unauthenticated on the published port. Correct switch. No way to flip it.diag::enable()is called from ciris-server's own binary entry point. This binary doesn't run that; it callsserve_with_adapteras a library. SoENABLEDstayed false for the life of every process,routers()never mounted the route, and neither--diagnostics(which our parser didn't accept) norCIRIS_DIAGNOSTICS=1(which nothing here read) could change it. In 0.3.69 and 0.3.70 the route wasn't gated — it was gone.Eric found it trying to take the
fordblksreading this repo has been asking for, which is the part that stings: the endpoint exists to answer a question we're actively asking, and I removed it while believing I was securing it.mallinfo2only exists inside the process, so there's no fallback — the measurement is simply unavailable on those two releases.Both openers, matching the sibling
Enabled before
serve_with_adapter, becauserouters()asksenabled()while building — flipping it later would be another switch that does nothing.Still not loopback-bound, and now said where operators read
ciris-server pairs its gate with
require_loopback; an adapter can't — that guard isn't exported and the read-API listener doesn't hand usConnectInfo. With diagnostics on, the route answers from wherever the port reaches, and the edge stays load-bearing. That's in DEPLOY.md now, not just a code comment, along with a note that 0.3.69/0.3.70 have no opener at all.### Boot inputs (CLI flags — the ONLY two)also stopped being true, so it says three.117 tests — one new, covering that the flag parses, takes no value, doesn't swallow the next argument, and is off by default.
🤖 Generated with Claude Code