Emit structured JSON logs for observability
epic-scenario-based-follow-up-prompts-infrastructure-task-006 — Instrument the Edge Function to emit structured JSON log entries at key execution points: function invoked, kill switch status, scheduler start, per-activity outcome (success/skip/error with reason), and final run summary with counts and duration. Log format must include timestamp, run_id, activity_id where applicable, and outcome fields to support log-based monitoring and alerting.
Acceptance Criteria
Technical Requirements
Execution Context
Tier 4 - 323 tasks
Can start after Tier 3 completes
Implementation Notes
Create a thin `Logger` class instantiated once per function invocation with a frozen `run_id = crypto.randomUUID()`. Expose methods: `logger.info(event, extra?)`, `logger.warn(event, extra?)`, `logger.error(event, extra?)`. Each method calls `console.log(JSON.stringify({ timestamp: new Date().toISOString(), run_id, level, event, ...extra }))`. The `extra` object is spread last so callers cannot accidentally overwrite base fields.
Define a const enum `LogEvent` for all event names to prevent typos: `FUNCTION_INVOKED`, `KILL_SWITCH_STATUS`, `SCHEDULER_START`, `ACTIVITY_SUCCESS`, `ACTIVITY_SKIPPED`, `ACTIVITY_ERROR`, `RUN_SUMMARY`. Keep the `Logger` class in a separate `logger.ts` module alongside the Edge Function so it can be independently unit tested.
Testing Requirements
Unit tests: (1) `createLogger(run_id)` returns a logger where each emitted call produces a valid JSON string containing `run_id` and `timestamp`; (2) `sanitize()` correctly redacts email addresses, Norwegian mobile numbers (8-digit), and 11-digit national IDs; (3) per-activity log entries for success/skip/error contain the correct `outcome` field. No integration tests required for this task — log output is validated by reading stdout in the task-008 integration test suite.
Supabase Edge Functions on Deno can have cold-start latency of 500ms–2s. If the evaluation window contains many activities (e.g., post-holiday catch-up), the function may approach the 60-second invocation timeout before completing all evaluations.
Mitigation & Contingency
Mitigation: Implement pagination in the activity fetch query with a configurable page size; process pages sequentially and commit history records per page so partial runs are recoverable on the next invocation.
Contingency: If timeout remains an issue at scale, split the evaluation into per-chapter invocations triggered by a fan-out pattern using Supabase Realtime or a lightweight queue.
Supabase cron triggers (pg_cron or Edge Function schedules) may miss invocations during platform maintenance windows, causing evaluation gaps that delay time-sensitive prompts beyond their intended delivery window.
Mitigation & Contingency
Mitigation: Configure the look-back window to be 2× the cron interval (e.g., 2-hour look-back for hourly cron) so a single missed invocation does not result in missed prompts; log each run's look-back range for auditability.
Contingency: If missed invocations are detected via monitoring alerts, implement a manual re-trigger endpoint accessible to admins that runs the evaluation for a specified time range.