Skip to content

feat(maintenance): add sm down/up + middleware (closes #160)#201

Open
antosubash wants to merge 2 commits into
mainfrom
issue-160-maintenance-mode
Open

feat(maintenance): add sm down/up + middleware (closes #160)#201
antosubash wants to merge 2 commits into
mainfrom
issue-160-maintenance-mode

Conversation

@antosubash
Copy link
Copy Markdown
Owner

Summary

Closes #160.

  • New MaintenanceModeMiddleware polls a JSON sentinel (<content-root>/.maintenance) every second. While the sentinel exists the middleware short-circuits with 503.
  • ?sm_bypass=<secret> verifies the SHA-256 hash and drops an HttpOnly, SameSite=Lax, Secure-when-HTTPS sm_bypass cookie so the deploying engineer can keep verifying the release.
  • Inertia / API requests get a JSON 503 with Retry-After; browsers get a minimal HTML 503 that renders without a JS bundle. The Inertia route System/Maintenance resolves to the existing ErrorPage503 component, so once an authenticated admin endpoint wants to render the maintenance page through Inertia it just works.
  • Health probes (/health/live, /health/ready) are exempt — load balancers can still distinguish "host down" from "deploying".
  • CLI: sm down --secret X --message ... --retry 60 [--until ISO], sm down --status, sm up. The secret is hashed before it touches disk — only the hash sits in the sentinel.

Test plan

  • dotnet test tests/SimpleModule.Core.Tests --filter Maintenance — 9/9 pass (state-off, state-on, health exemption, bypass query right/wrong, bypass cookie, Inertia vs browser response)
  • dotnet test tests/SimpleModule.Cli.Tests -p:IsTestProject=true --filter MaintenanceSentinel — 4/4 pass (write hashes secret, delete, idempotent delete, hash format)
  • dotnet test tests/SimpleModule.Core.Tests — full suite still 222/222
  • dotnet build — green
  • Smoke locally: dotnet run --project template/SimpleModule.Host, then in another shell sm down --secret xyz, hit / (expect 503), hit /?sm_bypass=xyz (expect 302+cookie), hit / again (expect 200), sm up, hit / (expect 200). Reviewer to verify.

Not in scope (deferred)

  • Per-tenant maintenance (called out in the issue as a follow-up).
  • Distributed coordination for multi-replica deploys — the sentinel lives on each instance's filesystem; ops can sm down over a shared volume or wire it into the deploy pipeline.

Tracks the 17 open issues with priority order, cross-issue
dependencies, and execution protocol. Per-issue sub-plans land
on the corresponding feature branches.
Drops a JSON sentinel at the host content root that the new
MaintenanceModeMiddleware polls every second. While active:

- health probes (/health/live, /health/ready) pass through
- ?sm_bypass=<secret> verifies the SHA-256 hash and sets an
  HttpOnly, SameSite=Lax sm_bypass cookie
- Inertia / API callers get a JSON 503 with Retry-After
- browsers get a minimal styled HTML 503 (renders without JS)
- the React side resolves System/Maintenance to the existing
  ErrorPage503, so future Inertia.Render("System/Maintenance")
  calls light up automatically

CLI:
  sm down --secret X --message ... --retry 60 [--until ISO]
  sm down --status
  sm up

Tests:
- 9 middleware tests cover state-off, state-on, health exemption,
  bypass query (correct + wrong secret), bypass cookie, and the
  Inertia-vs-browser response branch
- 4 sentinel tests cover write hashes the secret, delete, and
  HashSecret determinism
@cloudflare-workers-and-pages
Copy link
Copy Markdown

Deploying simplemodule-website with  Cloudflare Pages  Cloudflare Pages

Latest commit: d91aa1c
Status: ✅  Deploy successful!
Preview URL: https://b61e6953.simplemodule-website.pages.dev
Branch Preview URL: https://issue-160-maintenance-mode.simplemodule-website.pages.dev

View logs

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.

Add maintenance mode (sm down / sm up + bypass token)

1 participant