The session built: Appointments page: a single list, newest first. Block Time: edit and delete. Customer CSV export: with barber notes excluded. Guest-link regression test: a test that an appointment id alone is rejected, plus fixes to the stale docs. It built the scheduler, job runner with live progress, backup and restore, and the health alerts. Its own report says a real delete-and-restore on throwaway Docker passed, but I haven’t repeated that. It also says real SMTP and large dumps were not exercised. The manager image needs rebuilding for the backups to work, because it now installs 7zip.
This commit is contained in:
95 files changed
+7955
-150
No files matched your search
+49
-2
@@ -30,12 +30,59 @@ copied and adapted, not imported — see `src/lib/auth.ts` and
|
||||
reloads Caddy, starts the container, and runs its migrations. See
|
||||
`src/lib/provisioning.ts` for the exact sequence.
|
||||
- Per business: start / stop / restart / update (recreate the container
|
||||
against the current shared image tag — not a source rebuild) / view
|
||||
recent logs.
|
||||
against the current shared image tag — not a source rebuild, and run as
|
||||
a background job with live progress and an optional "back up first") /
|
||||
view recent logs.
|
||||
- Does **not** duplicate the `/install` wizard — after provisioning, the
|
||||
operator is linked to `https://<domain>/install` to finish that
|
||||
business's own setup.
|
||||
|
||||
## Scheduler, jobs, backups and alerts
|
||||
|
||||
All of this runs inside the Manager process — no host crontab, no extra
|
||||
service. State lives next to `global-settings.json`, under
|
||||
`STACKS_DIR/manager/` (and `STACKS_DIR/backups/`), so it survives rebuilds.
|
||||
|
||||
- **Scheduler** (`src/instrumentation.ts` → `src/lib/scheduler*.ts`): one
|
||||
guarded interval, a task registry with per-task intervals and
|
||||
per-business overlap guards, last-run results in `scheduler-state.json`
|
||||
(shown at Settings → Monitoring & scheduler). Tasks: notification cron
|
||||
(`POST /api/cron/process-notifications` with each stack's `CRON_SECRET`,
|
||||
every 30 s by default), daily Google reviews sync, health checks (every
|
||||
3 min by default), scheduled backups, hourly housekeeping, and an
|
||||
optional external heartbeat (`MANAGER_HEARTBEAT_URL`). Turn it off with
|
||||
`MANAGER_SCHEDULER_DISABLED=1`.
|
||||
**Fallback:** `stacks/infra/scripts/process-cron.sh` (host crontab) still
|
||||
works and does the same notification/reviews calls — use it only if the
|
||||
scheduler is disabled, never both.
|
||||
- **Jobs** (`src/lib/jobs.ts`, `locks.ts`): Update, Backup, Restore and
|
||||
Delete run as background jobs writing `manager/jobs/<id>.json` (status,
|
||||
steps, log tail); the UI polls `GET /api/jobs/<id>`. Each holds a
|
||||
per-business lock (`manager/locks/<slug>.json`) so they can't overlap.
|
||||
A lock whose heartbeat is older than 2 minutes is stale and may be taken
|
||||
over; on boot, jobs left "running" are marked failed and their locks
|
||||
released.
|
||||
- **Backups** (`src/lib/backup*.ts`, `restore.ts`; UI at a business's
|
||||
*Backups* page and the global *Restore* page): an encrypted `.7z`
|
||||
(`7zz`, AES-256, encrypted headers) of the database dump, media and
|
||||
config, in `STACKS_DIR/backups/<slug>/`. Written as `.partial`, verified
|
||||
with `7zz t`, then renamed; the newest N (default 2, per business) are
|
||||
kept. Safety backups (before an update or a replacing restore) and final
|
||||
backups (before a delete) are kept separately and never evict them. One
|
||||
passphrase protects everything: generated at the first enable / first
|
||||
*Back up now*, stored encrypted (`MANAGER_SETTINGS_ENCRYPTION_KEY`),
|
||||
**shown once** — save it, a fresh server needs it to restore. Restore
|
||||
works onto an existing business (after a safety backup) or a server that
|
||||
never had it; see `RESTORE_STEPS` in `src/lib/restore.ts`. A backup
|
||||
whose last migration is newer than the app image's is refused.
|
||||
- **Alerts** (`src/lib/health-watcher.ts`): per-business ok / degraded /
|
||||
down. Two consecutive bad checks before the first email; emails on
|
||||
change and on recovery, and a daily reminder while still bad. Set the
|
||||
operator address and toggles at Settings → Monitoring & scheduler (uses
|
||||
the Email settings' SMTP). Businesses stopped from the Manager, or mid
|
||||
update/backup/restore, are not probed. An external check is still needed
|
||||
for "the whole VPS is down" — use `MANAGER_HEARTBEAT_URL`.
|
||||
|
||||
## How auth works
|
||||
|
||||
A single dedicated platform-operator credential (`MANAGER_EMAIL` /
|
||||
|
||||
Reference in new issue
Block a user