Contextfulv0.23.0

Docs / Guides

contract connector · 40-connector.md · 41-secrets.md · 42-drive-extensions.md · guide · card

Connectors and credentials

The problem a connector solves

A vendor is an outside service, such as a reporting API. Reading its data needs code that knows the vendor’s pages and cursors, and a credential the vendor accepts. That code runs inside the deployment, so it gets no store handle and sees no credential value. A connector holds the vendor knowledge; the host process runs the connector, checks every destination, reserves quota and attaches credentials.

The example is vendor-metrics, a connector reading reports from api.vendor.example with a bearer token named vendor-token.

Loading the connector

A connector is either a sandboxed WebAssembly component or a native source compiled into the binary, and dispatch treats both alike (authoring-path). vendor-metrics ships as a remote artifact, one of four distribution forms (distribution-form).

The host re-hashes the downloaded bytes and refuses a mismatch before the engine sees them (digest-mismatch). The component then runs under a memory limit and a per-call deadline (call-deadline).

Its manifest lists the hosts it reaches, and the host decides that grant at load (declared-grant). Code reaching past the list fails to load (undeclared-access). When a new version lists another host, the reload compares the two manifests: a candidate host succeeds only when an admitted host already covers it (host-inclusion).

What crosses the interface

The component imports outgoing HTTP, logging and a wall clock, and its standard library sees no files, environment or arguments (empty-context). Batches cross the interface as Arrow IPC, a binary columnar format (batch-encoding).

One request, end to end

vendor-metrics asks for a report page. Every outbound request goes through the host’s one mediated client (mediation-covers-every-egress). The host resolves the host name once and connects to the address it vetted (resolve-once). A name resolving to a private or metadata address fails (private-address).

The credential binding allows one exact host, api.vendor.example (bound-host). An [attach] block maps the Authorization header to the template Bearer ${secret://vendor-token} (value-template). The host fills that template afresh for each admitted request (per-request-hydration).

A redirect keeps the credential only at the configured host and port (redirect-pinning).

Where the credential comes from

A secret:// name is a reference, and a provider chain of adapters answers it, starting with the lease provider (provider-chain). The first adapter answering a name serves it for the run (first-hit-wins). A second adapter that also holds the name fails the lookup, so no adapter shadows another silently (shadowed-name).

A token typed into the manifest, such as X-Api-Key = "abc123", is a plaintext credential. A profile build refuses it at read, naming the key path but not the token; a development build, compiled with no profile, reads it (inline-outside-development).

Hydration places the resolved value into an outbound request. The host hydrates per request, and no record or log line holds the value (hydration-is-just-in-time). A cached value lives at most 300 s (cache-ttl).

The deployment declares vendor-token as a lease, so the lease adapter answers it first (head-of-chain). The resolver keeps a leased credential in memory only, and evicts it at expiry (lease).

Rotation replaces the value and keeps the logical name, so no declaration or pinned artifact changes (turnover-preserves-the-name). An operator audits names with contextful secrets list, which shows configured bindings and reads no value (inventory).

When quota or the lease fails

The operator binds the vendor’s quota name to a limiter (limiter-binding). Midway through the pull the limiter denies a permit. The component sees an ordinary 429 with a retry delay, and the run’s retry schedule handles it (synthesized-throttle).

Later the lease expires while its mint endpoint is down. The run then sends 0 requests to the vendor (vendor-requests-on-failure), and the transient failure returns to the step’s schedule.

Model calls

Every model call resolves to one operator-configured endpoint (model-endpoint). Data boundary markers enclose each ingested value (data-fence). The markers lower the success rate of injected instructions but bound nothing (fence-is-not-a-boundary).

Model output carries the least-trusted label among its inputs (output-taint).

Built-in sources and Drive

The engine compiles in sources such as a paginated HTTP walk; each walk declares exactly one pagination shape (pagination).

The Drive sources read Google Drive under an end user’s grant. gdrive-picks serves files a person selects through Picker (picker-source), and gdrive-sheet captures a Sheet as rows (source-name).

A selection keeps a change token, committed with the first complete listing (initial-token). If Drive rejects the token, the source lists the selection again (invalid-token).

Under domain-wide delegation, each request names one admitted Workspace user as its subject (impersonated-principal). A subject outside the declared domain fails before any token mint (domain-boundary).

A connection binds one secret name to its tenant and principal, and a run hydrates only that name (name-binding).