Assert the /metrics 404 against Caddy on the host, not through the public name - #198
Merged
Merged
Conversation
…blic name Production's public name now resolves to a fronting edge that answers every path outside the MCP and OAuth ones with a 308 to internetcomputer.org. The release deploy's last check, exactly a 404 from https://$DOMAIN/metrics, can therefore no longer pass there (run 35884611192 failed on it after the deploy itself had gone through), and it no longer measured this host's configuration anyway. The assertion now asks Caddy on the host, over SSH with $DOMAIN pinned to loopback so its site block answers. The request through the public name stays, but only a 200 there fails the deploy: that alone proves the exposition public. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Xd7VT72Qt16qiAJynu9EKj
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
The public check infers metric exposure from status alone, causing false positives and missing redirected exposure.
Get a fresh assessment by requesting another Copilot review.
Review effort: Balanced
Findings: 1
What changed in this PR
Moves the /metrics exposure check to the deployed host’s Caddy instance to avoid production edge redirects.
Changes:
- Verifies Caddy’s local
/metricsroute returns 404. - Retains a public-origin check and updates deployment documentation.
| File | Description |
|---|---|
deploy/native/deploy.sh |
Adds host-local Caddy and public-origin checks. |
deploy/native/README.md |
Documents the revised verification behavior. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
sea-snake
previously approved these changes
Sep 23, 2026
A 200 through the public name is not proof the exposition is public (an edge may answer any unknown path with a page of its own), and a redirect left unfollowed could hide one that lands on it. The probe now follows redirects and fails the deploy only when the body carries imcp2_build_info, the marker the on-host checks already use; otherwise it reports the final status and URL. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Xd7VT72Qt16qiAJynu9EKj
sea-snake
approved these changes
Sep 23, 2026
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.

Summary
The release deploy to production (run 35884611192) failed at its last step:
https://$DOMAIN/metricsanswered308, not the404the check demands, on all five attempts. Production's public name now resolves to a fronting edge (the onehealth.ymlpins Internet Identity for) that answers every path outside the MCP and OAuth ones with a 308 tointernetcomputer.org/icp-mcp/…;/,/status/and/metricsall got it. So the check can no longer pass there, and it no longer measured what it was written to measure: whether this host's Caddyfile still carries the block that keeps the exposition off the public origin. Staging, whose name resolves to Caddy directly, still answers 404, and its deploy of the same commit passed.The deploy itself had gone through before the check ran: binary shipped, units rendered, services restarted, on-host
/metricsserving. What did not run: theVerify deployed versionstep and the release'spublishjob.Related issues
Follows up the production rollout of #191 (the commit the failed run deployed). The same edge is why #197 pins II in
health.yml.Changes
deploy/native/deploy.sh— the/metricsassertion asks Caddy on the host, over SSH with$DOMAINpinned to loopback (--resolve) so its site block answers;-k, since the question is the route, not the certificate. Exactly a 404, five attempts, else fatal, as before. The probe through the public name stays, redirects followed (at most five), and fails the deploy only when the body carriesimcp2_build_info, the marker the on-host checks already use: a status alone proves nothing either way behind an edge (review round 1). The final status and URL are reported for the record.deploy/native/README.md— says so.Testing
bash -n deploy/native/deploy.sh.github/scripts/scan-internal-identifiers.sh origin/main...HEAD— clean, both commitsmain) exercises the new on-host probe; the next production release exercises it behind the edge.Review rounds (Copilot): round 1, on e170ab5, found the public probe judging by status alone — a 200 from an edge's own page would have failed the deploy, and an unfollowed redirect could hide one that lands on the exposition (fixed in b6801c3: redirects followed, the body judged).
One thing this PR does not settle, for whoever runs the edge: through the public name,
/.well-known/oauth-authorization-serverstill lacksclient_id_metadata_document_supported, which the new build always emits (falsewhile CIMD is off; staging shows it), cache-buster or not. Either the edge serves that document itself, or it forwards to a host other than the one the release deploys to. Worth checkingcurl http://127.0.0.1:8000/versionon the deploy host and the edge's upstream before the next release, and before CIMD is enabled on production, since the flag would be invisible through a static copy.Checklist
🤖 Generated with Claude Code
https://claude.ai/code/session_01Xd7VT72Qt16qiAJynu9EKj