Deploy & runbook¶
Practical operations for whoever ships and maintains the platform. Product managers can skim this to understand how changes go live and how the center is kept safe.
How a change goes live¶
There is no automatic deploy pipeline — shipping is a deliberate, manual command.
# From the Cloudflare project directory:
npm run deploy # builds the web app, then deploys the Worker
This single command:
- Builds the React app.
- Bundles it as the Worker's static assets.
- Deploys the Worker to
kategeneral.long-cao.dev.
Because web and API ship together, there is never a version mismatch between the two.
Node version
The deploy tooling needs a recent Node.js (22+). If the deploy errors on an old Node, switch versions first.
Before you deploy (checklist)¶
- [ ] Secrets are set in production —
wrangler secret listshowsJWT_SECRET,AZURE_SPEECH_KEY,OCR_SECRET. - [ ] The end-to-end role/permission suite passes against production.
- [ ] Any database change is a safe, additive migration (see below) — never the destructive reset.
Database migrations¶
Schema changes are applied as idempotent migration files (safe to run more than once):
npm run db:migrate:remote # applies the additive migration set to production
The one command never to run against production
A separate script rebuilds the database from scratch — it drops every table and reseeds demo data. It is deliberately renamed to a RESET…DANGER name with a countdown warning so it can't be run by accident. It must never be used on the live center's data.
Backups & recovery¶
- D1 Time Travel provides point-in-time recovery — the database can be restored to an earlier moment. This is the safety net against a bad bulk operation.
- Practically: if a wrong mass update happens, restore to just before it rather than trying to undo by hand.
- Test content (mock tests, demo data) is reproducible from seed scripts, so it can always be regenerated.
Monitoring & logs¶
- Live logs:
wrangler tailstreams the Worker's logs in real time. - Observability is enabled on the Worker (request/error visibility in the Cloudflare dashboard).
- AI budget: the manager watches monthly AI usage vs. caps on the Reports → AI usage panel; the caps themselves fail closed, so an overrun is prevented, not just observed.
Health checks¶
GET /healthandGET /api/healthreturn a simple OK (and confirm the database and storage bindings are reachable). They do not leak internal error details.
Routine operational tasks¶
| Task | How |
|---|---|
| Add a manager/teacher/student | Admin creates the account in the app (no SQL needed) |
| Onboard a class of students | Enroll them into a class → a tuition charge is raised automatically from the class fee |
| Block a departed account | Admin toggles the user's status — effective immediately |
| Regenerate a demo/mock test | Run the corresponding seed script |
| Investigate a stuck grading | Grading is idempotent; re-triggering is safe. Check logs via wrangler tail |
Incident quick-reference¶
- "Everyone is logged out / auth failing" → check
JWT_SECRETis still set (the app fails closed without it). - "Audio won't play" → media is signed-URL only; a link may have expired (they're short-lived by design). Reload the page to get a fresh URL.
- "AI stopped grading" → likely the monthly cap; check the AI usage panel. New essays go to the teacher queue in the meantime.
- "A bad bulk edit hit the DB" → restore via D1 Time Travel to just before it.