From 83886ea7a46173c7e678cfc9cdc9bc6424858f74 Mon Sep 17 00:00:00 2001 From: Alex Blank Date: Mon, 11 May 2026 20:04:24 +0200 Subject: [PATCH] docs: fix schedule field and add resolved_at to backup monitoring spec --- .../specs/2026-05-11-backup-monitoring-design.md | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/docs/superpowers/specs/2026-05-11-backup-monitoring-design.md b/docs/superpowers/specs/2026-05-11-backup-monitoring-design.md index b8576fc..ea362d4 100644 --- a/docs/superpowers/specs/2026-05-11-backup-monitoring-design.md +++ b/docs/superpowers/specs/2026-05-11-backup-monitoring-design.md @@ -58,7 +58,7 @@ Represents a backup job definition. Auto-created when the first report arrives. | `name` | string | Unique job name (e.g., "photos-daily") | | `source` | string | Source description (free text, e.g., "server-a:/data/photos") | | `target` | string | Target description (free text, e.g., "server-b:/backups/photos") | -| `expected_schedule` | string | Cron expression or interval (e.g., "0 2 * * *") | +| `schedule_interval_seconds` | integer | Expected interval between runs in seconds (e.g., 86400 for daily) | | `created_at` | datetime | When the job was first seen | ### `BackupRun` @@ -91,6 +91,7 @@ Represents an alert condition detected for a job. | `severity` | enum | `warning`, `critical` | | `message` | string | Human-readable description | | `acknowledged` | boolean | Whether a user has acknowledged this alert | +| `resolved_at` | datetime | When the alert was auto-resolved (nullable) | | `created_at` | datetime | When the alert was generated | ## API Specification @@ -107,6 +108,7 @@ Submit a backup run report. Creates the job if it doesn't exist. "name": "photos-daily", "source": "server-a:/data/photos", "target": "server-b:/backups/photos", + "schedule_interval_seconds": 86400, "started_at": "2026-05-11T02:00:00Z", "ended_at": "2026-05-11T02:15:30Z", "status": "success", @@ -124,6 +126,7 @@ Submit a backup run report. Creates the job if it doesn't exist. - `name`: required, non-empty string - `started_at`: required, ISO 8601 timestamp, must be in the past - `status`: required, one of `success`, `failure`, `in_progress` +- `schedule_interval_seconds`: optional, if provided must be > 0. Updates the job's schedule if the job exists or is being created. - If `status == "success"`: `ended_at` and `duration_ms` are required - `bytes_transferred`: if provided, must be >= 0 - Unknown fields in `details` are stored in `details_json` @@ -139,6 +142,7 @@ Mark a backup job as in_progress. Useful for long-running backups. { "name": "photos-daily", "source": "server-a:/data/photos", + "schedule_interval_seconds": 86400, "started_at": "2026-05-11T02:00:00Z" } ``` @@ -170,7 +174,7 @@ Alerts are generated in two ways: | Alert Type | Trigger | Severity | Auto-Resolve | |------------|---------|----------|--------------| | `failed_status` | `status == "failure"` | `critical` | On next successful run | -| `missed_schedule` | No run within `expected_schedule * 1.5` | `warning` | On next run arrival | +| `missed_schedule` | No run within `schedule_interval_seconds * 1.5` | `warning` | On next run arrival | | `anomaly_size` | `bytes_transferred == 0` or < 10% or > 300% of 7-day median | `warning` | On next normal run | | `anomaly_duration` | `duration_ms` > 300% of 7-day median | `warning` | On next normal run | @@ -207,10 +211,10 @@ Sortable table with columns: - Job name - Source - Target -- Expected schedule +- Schedule interval (human-readable, e.g., "Every 24 hours") - Last run status (color-coded chip) - Last run time -- Next expected run time +- Next expected run time (calculated from `last_run_started_at + schedule_interval_seconds`) Clicking a job row navigates to a job detail view showing historical runs. @@ -261,7 +265,7 @@ Reusing existing D3 chart infrastructure: ## Error Handling - Invalid report data returns `422 Unprocessable Entity` with detailed validation errors -- Duplicate reports for the same job within the same minute are idempotent (updates existing run) +- Duplicate reports: if a run with the same `job_id` and `started_at` (within 1-second precision) already exists, the report updates the existing run instead of creating a new one - Malformed JSON in `details` field is accepted but stored as string in `details_json` - Database errors are logged and return `500 Internal Server Error`