Capabilities
Declare what a page needs. The framework runs the protocol and owns the secrets.
What a capability is
A capability is a host-owned named service — auth, data, payments,
files, images — that the application invokes through one ABI. The app
declares intent; Crisptastic owns the provider protocol, the credentials, the
retry and redirect policy, and the observability.
@call account = data.accounts_search({ email: request.body.email })
@telemetry "account.search" = { found: account.ok }
Normalized results
Every invocation returns the same shape. Success:
{ "ok": true, "value": { ... }, "status": 200,
"meta": { "request_id": "...", "cached": false } }
Failure:
{ "ok": false, "value": null, "status": 503,
"error": { "code": "capability.unavailable",
"message": "...", "retryable": true } }
Provider response bodies are never passed through automatically. Adapter schemas select safe fields explicitly.
Operation classes
Every operation declares one class, which controls retry and replay:
read— no external mutation; may be cached or retriedcreate_idempotent/update_idempotent/delete_idempotent— mutation requiring an idempotency keyterminal_once— cannot be safely replayed; forbidden from automatic route retry
Adapters also declare timeout bounds, input/output size, retry policy and required secrets per operation.
Secret attachment
Capability configuration references secret names. At invocation the adapter resolves those names from the application's immutable in-memory secret generation.
- A missing required secret returns
capability.secret_missingwith no network request. - Secret values never enter the invocation input, result, telemetry, cache key or diagnostic formatting.
- Authorization headers are built only after URL and policy validation.
- A redirect never carries a secret header to a different origin.
- A request keeps its starting secret generation through completion.
The shared network executor
Every adapter uses one policy-enforcing executor: DNS and address validation, connection and request deadlines, bounded bodies, redirect policy, TLS verification, connection pools partitioned by application and provider, and structural header redaction. Outbound requests to private, loopback, link-local and metadata ranges are refused by default. See the security model.
Circuit breaking
Each application / provider / operation has an independent breaker. It opens after a burst of qualifying failures, probes after a pause, and closes after several successful probes. Authentication and authorization 4xx failures do not open the breaker — they surface as configuration errors.
Local development uses fakes
Every capability has a deterministic local fake, so you build and test a page that logs in or takes a payment without a live account or network. The fake and the real adapter share the same contract, so behaviour that works locally works in production.