critical priority medium complexity infrastructure pending infrastructure specialist Tier 0

Acceptance Criteria

Deno entry point at supabase/functions/generate-accounting-export/index.ts is present and passes `supabase functions serve` startup without errors
Every request without a valid Authorization: Bearer <JWT> header receives HTTP 401 with body {error: 'Unauthenticated'}
A valid JWT belonging to a peer-mentor role receives HTTP 403 with body {error: 'Insufficient permissions'}
A valid JWT belonging to coordinator or org-admin role proceeds to the next handler stage without error
Org ID is extracted from the JWT's app_metadata or custom claims (not from the request body) to prevent spoofing
Role claim is extracted from the same JWT source and validated against an allowlist ['coordinator', 'org-admin']
TypeScript interfaces ExportRequest and ExportResponse are defined in a shared types.ts file within the function directory
CORS headers are configured to allow requests from the mobile app's registered origin only
Function cold-start time is under 500ms (verified via `supabase functions serve` logs)

Technical Requirements

frameworks
Deno runtime (Supabase Edge Functions)
Supabase Edge Function auth helpers (@supabase/supabase-js server-side)
apis
Supabase Auth (JWT verification)
Supabase Edge Functions (Deno)
performance requirements
JWT verification must complete in under 50ms
Function must respond to auth-rejected requests in under 100ms total
No synchronous blocking operations in the Deno entry point
security requirements
JWT must be verified using Supabase's server-side auth helpers — never decoded client-side or manually
Org ID and role MUST come from JWT claims only — never trust request body for auth context
Service role key must only be used after role enforcement passes, never before
CORS origin allowlist must be explicit — wildcard '*' is not acceptable for this function
Function must not log JWT token values or user PII to console

Execution Context

Execution Tier
Tier 0

Tier 0 - 440 tasks

Implementation Notes

Use the `createClient` from `@supabase/supabase-js` with the SUPABASE_URL and SUPABASE_ANON_KEY env vars for JWT verification via `supabase.auth.getUser(token)`. Extract org and role from the returned user's `app_metadata` object — ensure the Flutter app and Supabase Auth hook write these claims consistently. Separate the auth middleware into its own `authGuard.ts` file for testability and reuse across other Edge Functions. Use TypeScript strict mode.

Define the Deno permission set explicitly in the function's import map — avoid `--allow-all`. For CORS, read the allowed origin from an environment variable so it can differ between staging and production without code changes.

Testing Requirements

Manual verification via `supabase functions serve` and curl/Postman for initial scaffolding. Write unit tests for the JWT extraction and role enforcement logic as pure TypeScript functions using Deno's built-in test runner (`Deno.test`). Test cases: (1) missing Authorization header → 401; (2) malformed JWT → 401; (3) valid JWT with peer-mentor role → 403; (4) valid JWT with coordinator role → passes guard; (5) valid JWT with org-admin role → passes guard; (6) org_id extracted matches JWT claim, not body param. Do not use real Supabase JWTs in tests — use a test SUPABASE_JWT_SECRET to sign fixture tokens.

Component
Supabase Edge Function: Generate Export
infrastructure high
Epic Risks (3)
high impact medium prob technical

The Edge Function may exceed Supabase's execution time limit (default 150 seconds, but effectively constrained by the 10-second client SLA) when processing large batches of claims with complex chart-of-accounts mapping, causing the export to fail after partial processing.

Mitigation & Contingency

Mitigation: Implement the export pipeline with early termination on timeout and an in-progress export run status. Add a benchmark test in CI that runs the full pipeline against 500 claims and fails if it exceeds 8 seconds. Optimize the approved claims query with indexes on status, org_id, and date fields.

Contingency: If performance targets cannot be met synchronously, convert the Edge Function to an async job pattern: the function queues the export and returns a job ID immediately; the client polls a status endpoint and downloads the file when ready. This requires a job queue table and a polling UI state.

high impact medium prob security

Supabase Vault access from the Edge Function may require specific service role key configuration that differs between staging and production environments, causing credential retrieval to fail silently and producing export runs that appear successful but have no valid accounting system target.

Mitigation & Contingency

Mitigation: Test Vault read access in the Edge Function in staging before implementing any business logic. Add an explicit credential validation step at Edge Function startup that fails fast with a clear error if Vault is unreachable or the secret is missing.

Contingency: If Vault access fails in production, fall back to environment variable-based credentials temporarily (never returned to client) while the Vault configuration is corrected. Alert on-call via a monitoring rule that fires if credential retrieval fails.

medium impact low prob technical

AccountingExporter Service may become tightly coupled to specific exporter implementations if the factory pattern is not implemented cleanly, making it difficult to add a third exporter in the future without modifying the orchestrator.

Mitigation & Contingency

Mitigation: Define an AccountingExporter abstract class with a strict interface contract before implementing any concrete class. Use a registry pattern (Map<orgType, AccountingExporter>) in the factory rather than conditionals. Code review should verify no concrete class is imported directly in the orchestrator.

Contingency: If tight coupling is discovered after implementation, refactor the factory before the Edge Function epic ships so the interface is stable before any external callers are wired in.