Skip to main content

Portal Task Automation — Integration Contract (PF-119)

Spec: PF-119 · Owner: Platform Foundation · Status: Phase 2 (framework) built; Phase 3 (live worker) pilot pending. Portal Task Automation is a PF capability that runs “portal bots” (log into an external web portal with no API and repeat steps) on a shared headless-browser worker. Consumer cores dispatch a run and receive the result without importing any browser code or another core (constitution §1).

Consumer seam (the only supported entry point)

  • Client (Vite SPA): @/platform/automation/portaldispatchPortalRun(input), getPortalRunStatus(runId), and the usePortal* hooks. No Playwright/Chromium is reachable through this import.
  • Server (edge → edge): supabase/functions/_shared/portal-runner.tsdispatchPortalRun(supabase, params). A consumer-core edge function (e.g. CE-69) calls this with the service client; it enforces the ToS gate, creates the run, enqueues it to FW-46, and (fixture/inline) returns the terminal result.

Edge / control plane (Deno — no browser)

Success envelope: { data: {...} }. Error envelope: { error: { code, message } } (sanitized, no PHI). Edge-functions rules apply (getCorsHeaders, createLogger, service-role sentinel).

Reused platform substrate (no parallel infrastructure)

  • FW-46 durable worker — runs ride workflow_execution_queue (pgmq) with trigger_type='portal_task' + portal_run_id; the workflow-executor-worker routes them to the runner before any rule lookup. pf_portal_enqueue_due_runs() (pg_cron, every minute) enqueues due schedules. Retry/DLQ/timeout handling is inherited (FR-3).
  • PF-75/76 vault — bot credentials are stored at source (pf_portal_flows, 'bot_credential', flowId) and brokered at run time via pf_retrieve_credential_by_source (service-role friendly). Flows store a handle, never secret material (FR-5).
  • Execution transport_shared/portal-transport.ts: deterministic Playwright (Phase 3 external worker) → AI self-heal → vision fallback; fixture for hermetic tests; unavailable default in the edge runtime. The orchestration + DB shape are stable across transports.

ToS gate (AC-4)

A flow is dispatchable only when its pf_portal_definitions.terms_of_service_status='approved' and the flow’s tos_acknowledged_at is set. The gate is enforced in three places: the UI enable dialog, dispatchPortalRun (403, no run created), and the runner (defense in depth).

Consumer registry

Failure modes

  • Worker unreachable / no browser → run failed with PORTAL_AUTOMATION_UNAVAILABLE; consumer cores degrade to their existing manual fallback (e.g. CE-69 AC-6). FW-46 retry/DLQ applies to scheduled runs.
  • Selector drift → AI self-heal re-locates and caches the locator into the flow’s step graph (AC-3); a hard miss fails loudly with a screenshot — never a silent wrong-data success.
  • Cross-tenant → impossible by RLS on every pf_portal_* table (AC-6, verified).