Pristine.Client.foundation/1 builds the recommended production client profile.
It wires the Foundation retry, rate-limit, circuit-breaker, telemetry, and
admission-control adapters into one provider-agnostic runtime client.
Build A Foundation Client
This direct default_auth example is standalone compatibility. Governed
execution must use governed_authority instead of env-backed default_auth,
direct headers, or direct base URL inputs.
client =
Pristine.Client.foundation(
base_url: "https://api.example.com",
transport: Pristine.Adapters.Transport.Finch,
transport_opts: [finch: MyApp.Finch],
serializer: Pristine.Adapters.Serializer.JSON,
default_auth: [Pristine.Adapters.Auth.Bearer.new("example-api-token")],
telemetry: [namespace: [:my_sdk]]
)authority =
Pristine.GovernedAuthority.new!(
base_url: "https://api.example.com",
base_url_ref: "base-url://example/workspace-123",
credential_handle_ref: "credential-handle://example/workspace-123",
credential_lease_ref: "credential-lease://example/one-effect",
target_ref: "target://example/production",
request_scope_ref: "request-scope://example/widgets/list",
header_policy_ref: "header-policy://example/default",
materialization_kind: "bearer",
bearer_token_ref: "bearer-token://example/one-effect",
redaction_ref: "redaction://headers",
headers: %{"x-authority-target" => "target://example/production"},
credential_headers: %{"authorization" => "Bearer authority-materialized-token"},
allowed_header_names: ["authorization", "x-authority-target"]
)
client =
Pristine.Client.foundation(
governed_authority: authority,
transport: Pristine.Adapters.Transport.Finch,
transport_opts: [finch: MyApp.Finch],
serializer: Pristine.Adapters.Serializer.JSON,
telemetry: [namespace: [:my_sdk]]
)Feature Flags
Pristine.Client.foundation/1 forwards the same top-level Foundation feature
switches used by Pristine.Profiles.Foundation:
retryrate_limitcircuit_breakertelemetryadmission_control
Each feature accepts false, true, an adapter module, or an option list.
Reporter Helpers
Pristine.Profiles.Foundation still exposes the telemetry reporter helpers used
by production runtimes:
events = Pristine.Profiles.Foundation.default_telemetry_events([:my_sdk])
child_spec =
Pristine.Profiles.Foundation.reporter_child_spec(
handler_id: "my-sdk-reporter",
events: Map.values(events)
)When you already have a Foundation client, pass its internal context to the reporter helpers:
handler_id =
Pristine.Profiles.Foundation.attach_reporter(
client.context,
handler_id: "my-sdk-reporter"
)
events = Pristine.Profiles.Foundation.reporter_events(client.context)
:ok = Pristine.Profiles.Foundation.detach_reporter(handler_id)Registry lifetime (Pristine 0.3.1 / Foundation 0.2.2)
Default breaker, rate-limit and semaphore ETS registries belong to Foundation's
supervised registry owner. Short-lived HTTP workers no longer create competing
default tables or transfer them to Erlang :init on exit. Foundation recovers
stale default caches after owner restart; that restart resets resilience state.
Explicit registries are caller-owned and need no heir. Create shared explicit registries in a long-lived supervised process and pass them via adapter options. A deleted anonymous registry is an error, not a reason to silently bypass its limits with a replacement table. Named registry creation follows Foundation's normal named-registry behavior. This ownership fix does not add transport queue bounds or physical HTTP cancellation guarantees.
Cancellation During Retry Backoff (Pristine 0.4.0)
The existing Pristine.Adapters.Retry.Foundation loop accepts the request's
Pristine.Cancellation token. With the normal sleeper, a pending retry delay is
implemented as a cancellation-aware wait: cancellation returns promptly and no
later retry attempt begins. Retry-After and normal policy delays still use the
same Foundation runner and delay calculation.
This does not create a second retry engine and does not replace the existing
result classifier. before_attempt, retry budgets, policy backoff, Retry-After,
progress timeout, and attempt accounting remain on Foundation.
Custom sleep_fun hooks remain supported. Pristine checks cancellation before
and after such a hook; if a custom sleeper itself blocks for a long interval and
needs interruption inside that function, it must cooperate with the supplied
cancellation token.