Skip to content

docs: correct the SYNC_MODE deploy section after #14 added health checks - #16

Merged
guarzo merged 1 commit into
mainfrom
worktree-ops-health-syncmode
Aug 3, 2026
Merged

docs: correct the SYNC_MODE deploy section after #14 added health checks#16
guarzo merged 1 commit into
mainfrom
worktree-ops-health-syncmode

Conversation

@guarzo

@guarzo guarzo commented Aug 3, 2026

Copy link
Copy Markdown
Owner

Small docs-only correction. Not part of the local-dev stage sequence — it fixes a claim I wrote in #12 that #14 made false.

The stale claim

docs/ops.md said:

There is no automatic rollback if you forget. fly.toml defines no health checks, and only the worker validates config at startup…

fly.toml now defines an http_service check on /api/health (#14).

Why the wrong reason matters more than the wrong fact

The conclusion — no automatic rollback for a missing SYNC_MODE — is still correct. But the stated reason is now false in a way that actively misleads: someone who reads that line, opens fly.toml, and sees a health check will reasonably conclude the gap was closed. It wasn't.

/api/health never calls getConfig():

  • getDb() reads process.env.DATABASE_URL directly (src/db/index.ts), not through config
  • checkLiveness only runs select 1 (src/services/health.ts)

So with SYNC_MODE unset, /api/health returns 200 healthy while every real page 500s. The machine stays in rotation and the deploy is never gated. The new check genuinely gates deploys — but only on database reachability, which is exactly what #14 designed it for.

The fix

Replaced the paragraph with a per-component table stating which layer catches what:

Component Behavior Why
Release command succeeds migrate.ts reads DATABASE_URL directly
worker crash-loops getConfig() at startup
web boots, then 500s on every page getConfig() is lazy, called per request
/api/health returns 200 — healthy never calls getConfig()

with the last row called out as the trap.

Two smaller updates while in there:

  • Example now uses fly secrets set --stage, which avoids restarting machines for a value the running code doesn't read yet. (Plain fly secrets set still works; noted.)
  • Notes .nvmrc and scripts/check-node-version.sh from ci: GitHub Actions workflow, Node pin, and version-drift guard #13 next to the existing engines/.npmrc mention, so a future Node bump knows all three pins must agree.

Verification

$ bash scripts/check-node-version.sh
node version OK: Dockerfile=22 .nvmrc=22 engines='>=22.9'

$ npm run format:check
All matched files use Prettier code style!

Docs-only; no source, no test changes.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Documentation
    • Updated deployment guidance to configure staging for live synchronization before release.
    • Documented component behavior when synchronization settings are missing, including cases where health checks may pass while web requests fail.
    • Clarified local development requirements for consistent Node.js versions across environments.
    • Added documentation for CI validation of the required Node.js version.

#14 added an http_service check on /api/health, which makes a claim I wrote in
#12 false: docs/ops.md said "fly.toml defines no health checks". It now does.

The conclusion was right for the wrong reason, and the wrong reason is the
dangerous part — a reader who checks fly.toml now sees a health check and
reasonably concludes config errors are covered. They are not:

  /api/health never calls getConfig(). getDb() reads process.env.DATABASE_URL
  directly (src/db/index.ts) and checkLiveness only runs `select 1`
  (src/services/health.ts). With SYNC_MODE unset the endpoint returns 200 and
  the machine stays in rotation while every real page 500s.

Replaced the paragraph with a per-component table that says exactly which
layer catches what, and names /api/health's 200 as the trap. Also switched the
example to `fly secrets set --stage`, which avoids restarting machines for a
value the running code does not yet read.

Separately, notes .nvmrc and scripts/check-node-version.sh from #13 alongside
the existing engines/.npmrc mention, so a future Node bump knows all three pins
must agree.
@coderabbitai

coderabbitai Bot commented Aug 3, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The operations guide now documents SYNC_MODE=live deployment steps, missing-variable behavior, health-check limitations, and Node.js 22.9+ version consistency across local development files.

Changes

Operations documentation

Layer / File(s) Summary
Deployment and development guidance
docs/ops.md
The guide documents staged SYNC_MODE=live updates, component behavior when the variable is missing, database-only health checks, and Node.js version consistency requirements enforced by CI.

Estimated code review effort: 1 (Trivial) | ~5 minutes

Possibly related PRs

  • guarzo/authGD#14: Both PRs update deployment and health-check guidance in docs/ops.md.
  • guarzo/authGD#15: This PR extends the deployment and local-development guidance introduced there.

Poem

A rabbit reads the ops notes bright,
SYNC_MODE guides the launch tonight.
Health checks tell what databases know,
Node pins keep local builds in a row.
Hop, deploy, with docs in sight!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the documentation update to the SYNC_MODE deployment section after health checks were added.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch worktree-ops-health-syncmode
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch worktree-ops-health-syncmode

Comment @coderabbitai help to get the list of available commands.

@guarzo
guarzo merged commit dfac83c into main Aug 3, 2026
3 of 4 checks passed

@coderabbitai coderabbitai 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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/ops.md`:
- Around line 222-237: Revise the opening statement in the “missing SYNC_MODE”
section to scope the issue to automatic deployment gating: state that a missing
SYNC_MODE does not automatically fail or roll back the deploy, and that
/api/health does not detect it. Preserve the existing component behavior table
and supporting explanation.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 02b33686-53eb-43a6-8d5f-6dff6dbfb6b7

📥 Commits

Reviewing files that changed from the base of the PR and between d7a40ef and c94a372.

📒 Files selected for processing (1)
  • docs/ops.md

Comment thread docs/ops.md
Comment on lines +222 to +237
**A missing `SYNC_MODE` is not caught by anything, including the health check.**
Per component:

| Component | Behavior | Why |
|---|---|---|
| Release command | **succeeds** | `src/db/migrate.ts` reads `DATABASE_URL` directly, never `getConfig()` |
| `worker` | **crash-loops** | `getConfig()` runs at `src/worker/index.ts` startup |
| `web` | **boots, then 500s on every page** | `getConfig()` is lazily cached (`src/config.ts`) and every caller is inside a route handler or page |
| `/api/health` | **returns 200 — healthy** | it never calls `getConfig()`: `getDb()` reads `process.env.DATABASE_URL` directly (`src/db/index.ts`) and `checkLiveness` only runs `select 1` |

That last row is the trap. `fly.toml` *does* define an `http_service` check on
`/api/health`, and that check genuinely gates deploys — but only on database
reachability. A config error leaves it reporting healthy while every real page
is broken, so the machine stays in rotation and the deploy is never gated.

Setting the secret first is the safety net. There is no automatic one.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Scope the “not caught” claim to automatic deployment gating.

The table states that worker crash-loops and web returns 500s. Therefore, “not caught by anything” is too broad. State that missing SYNC_MODE does not automatically fail or roll back the deploy, and that /api/health does not detect it.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/ops.md` around lines 222 - 237, Revise the opening statement in the
“missing SYNC_MODE” section to scope the issue to automatic deployment gating:
state that a missing SYNC_MODE does not automatically fail or roll back the
deploy, and that /api/health does not detect it. Preserve the existing component
behavior table and supporting explanation.

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