Skip to content

Assert the /metrics 404 against Caddy on the host, not through the public name - #198

Merged
aterga merged 2 commits into
mainfrom
claude/deploy-metrics-check-on-host
Sep 23, 2026
Merged

aterga merged 2 commits into
mainfrom
claude/deploy-metrics-check-on-host

Conversation

@aterga

@aterga aterga commented Sep 23, 2026

Copy link
Copy Markdown
Collaborator

Summary

The release deploy to production (run 35884611192) failed at its last step: https://$DOMAIN/metrics answered 308, not the 404 the check demands, on all five attempts. Production's public name now resolves to a fronting edge (the one health.yml pins Internet Identity for) that answers every path outside the MCP and OAuth ones with a 308 to internetcomputer.org/icp-mcp/…; /, /status/ and /metrics all 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 /metrics serving. What did not run: the Verify deployed version step and the release's publish job.

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 /metrics assertion asks Caddy on the host, over SSH with $DOMAIN pinned 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 carries imcp2_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 commits
  • Against a host: not possible from here. The next staging deploy (any push to main) exercises the new on-host probe; the next production release exercises it behind the edge.
  • Cargo and dashboard checks do not apply: no Rust or dashboard code changed.

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-server still lacks client_id_metadata_document_supported, which the new build always emits (false while 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 checking curl http://127.0.0.1:8000/version on 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

  • I have read the Contributing guidelines.
  • Docs (README / comments) updated for any user-visible change.
  • No secrets, credentials, or internal-only information are included.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Xd7VT72Qt16qiAJynu9EKj

…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
@aterga
aterga requested a balanced review from Copilot September 23, 2026 16:24
@aterga
aterga marked this pull request as ready for review September 23, 2026 16:24
@aterga
aterga requested a review from a team September 23, 2026 16:24

Copilot AI 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.

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 Medium severity

Open (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 /metrics route 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.

Comment thread deploy/native/deploy.sh Outdated
sea-snake
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
Copilot AI review requested due to automatic review settings September 23, 2026 16:29

Copilot AI 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.

Copilot review overview

🟢 Approval recommended

The focused deployment checks correctly handle production’s fronting edge without weakening exposure detection.

Review effort: Balanced
Findings: None

Resolved since last review (1)

@aterga
aterga requested a review from sea-snake September 23, 2026 16:32
@aterga
aterga merged commit 62fee9c into main Sep 23, 2026
15 checks passed
@aterga aterga mentioned this pull request Sep 23, 2026
8 tasks
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.

4 participants