WebProbe
WebProbe v1.0.0 · API v1

Architecture

flowchart LR
    Client["Client"]

    API["Fastify API<br/>Auth + Validation + Limits"]

    HTTP["HTTP Engine"]
    Queue["BullMQ Queue"]
    Worker["Execution Worker"]
    Browser["Playwright + Chromium<br/>Isolated Context per Run"]

    DB[("PostgreSQL<br/>Runs, Attempts, Sessions,<br/>Usage, Metadata")]

    Redis[("Redis<br/>Queue State<br/>Leases<br/>Rate Limits<br/>Idempotency")]

    Artifacts[("Artifact Store<br/>Screenshots + Traces")]

    Egress["Safe Egress Layer<br/>HTTP Transport + Chromium Proxy"]

    Client --> API

    API --> HTTP
    HTTP --> Upstream["Upstream Services"]

    API --> Queue
    Queue --> Redis
    Queue --> Worker

    Worker --> Browser
    Browser --> Artifacts
    Worker --> DB

    API --> DB

    Browser --> Egress
PostgreSQL: principals, runs, attempts, actions, sessions, artifact metadata, usage, webhook deliveries
Redis: queue state, leases, rate/idempotency coordination
ArtifactStore: screenshots and traces outside relational rows
Safe egress: pinned HTTP transport + mandatory Chromium proxy

The API owns public contracts and admission control. Execution modules own fetching and deterministic domain behavior. The worker owns browser resources. PostgreSQL repositories and BullMQ adapters sit behind ports, so tests can use in-memory adapters without creating a second production architecture.

One long-lived Chromium process amortizes startup cost. Every run creates a new context, injects only requested state, and closes the context in finally. A disconnected process is discarded and recreated.

Workspace packages declare their own runtime dependencies and publish only dist JavaScript and declarations. A development export condition and TypeScript path map preserve source-level local development without weakening the package boundary.

Failures retain their layer: validation, target policy, upstream navigation, individual action, assertion, browser process, worker, schema, and artifact failures remain distinguishable.