Skip to content

0.3.71: the diagnostics gate had no opener — a removal wearing a switch's clothes - #81

Open
emooreatx wants to merge 1 commit into
mainfrom
fix/diagnostics-gate-has-no-opener
Open

0.3.71: the diagnostics gate had no opener — a removal wearing a switch's clothes#81
emooreatx wants to merge 1 commit into
mainfrom
fix/diagnostics-gate-has-no-opener

Conversation

@emooreatx

Copy link
Copy Markdown
Contributor

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 doesn't 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 our parser didn't accept) nor CIRIS_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 fordblks reading 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. mallinfo2 only exists inside the process, so there's no fallback — the measurement is simply unavailable on those two releases.

Both openers, matching the sibling

--diagnostics          its flag, now accepted by 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 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 us ConnectInfo. 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

…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>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment thread README.md
| `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 |

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge 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 👍 / 👎.

Comment thread src/main.rs
Comment on lines +249 to +252
// 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,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge 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 👍 / 👎.

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