high priority low complexity infrastructure pending infrastructure specialist Tier 4

Acceptance Criteria

Every log entry is a single-line JSON string written to stdout via `console.log(JSON.stringify(entry))`
Every log entry contains at minimum: `timestamp` (ISO 8601 UTC), `run_id` (UUID generated once per invocation), `event` (string enum), `level` ('info' | 'warn' | 'error')
The `function_invoked` event is emitted as the very first log line and includes `trigger_source` ('cron' | 'manual')
The `kill_switch_status` event is emitted immediately after the kill switch check with field `enabled: boolean`
The `scheduler_start` event is emitted before the activity loop with `activity_count: number`
Per-activity outcome events include `activity_id` and `outcome` ('success' | 'skipped' | 'error'), plus `reason` for skip/error outcomes (max 200 chars)
The `run_summary` event is the last log line and includes `total`, `succeeded_count`, `skipped_count`, `error_count`, and `duration_ms`
No log entry contains raw PII fields (name, phone, email, address) from activity or peer records
Log entries are valid JSON parseable by `JSON.parse()` — no trailing commas, no unescaped characters

Technical Requirements

frameworks
Supabase Edge Functions (Deno/TypeScript)
performance requirements
Logging must be synchronous (JSON.stringify + console.log) — do not add async log shipping that could delay the response
Each log entry serialisation must complete in under 1ms — keep entry objects shallow
security requirements
PII scrubbing: before logging any field derived from activity or peer records, pass it through a `sanitize()` helper that replaces known PII patterns (email, phone, Norwegian national ID) with '[REDACTED]'
Log entries must not contain the service-role JWT or any secret values from environment variables

Execution Context

Execution Tier
Tier 4

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.

Component
Scenario Evaluation Edge Function
infrastructure medium
Epic Risks (2)
medium impact low prob technical

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.

medium impact low prob dependency

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.