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/portal—dispatchPortalRun(input),getPortalRunStatus(runId), and theusePortal*hooks. No Playwright/Chromium is reachable through this import. - Server (edge → edge):
supabase/functions/_shared/portal-runner.ts—dispatchPortalRun(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) withtrigger_type='portal_task'+portal_run_id; theworkflow-executor-workerroutes 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 viapf_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;fixturefor hermetic tests;unavailabledefault in the edge runtime. The orchestration + DB shape are stable across transports.
ToS gate (AC-4)
A flow is dispatchable only when itspf_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
failedwithPORTAL_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).