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 retried
  • create_idempotent / update_idempotent / delete_idempotent — mutation requiring an idempotency key
  • terminal_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_missing with 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.