Ferrite separates a secret value from an application’s ability to use it. The Dashboard and MCP can list secret names, but they never return stored values. Outbound HTTP crosses one audited Gateway boundary and only to destinations declared by the app.
Write a secret safely
Open the app’s Settings → Secrets view in the Dashboard, enter the name and
value, and save it over the authenticated browser session. An agent can call
the MCP set_secret tool with the app, name, and value, then use
list_secrets to confirm only the name is present. Never place a secret in a
shell argument or commit it to ferrite.json.
Declare egress
{
"services": [],
"applications": [{
"name": "shop",
"artifact_key": "apps/shop@v1",
"artifact_sha256": "0000000000000000000000000000000000000000000000000000000000000000",
"egress": [{
"handle": "stripe",
"destinations": ["https://api.stripe.com/v1/checkout/sessions"]
}]
}]
}
The app obtains this authority with ctx.egress("stripe"). Requests outside
the declared URL prefixes fail before network access. Do not allow a whole host
because one endpoint is convenient; add each required prefix deliberately.
Local development
ferrite dev denies real egress by default. Use ferrite dev --egress allow
only when you intend to call the destinations already declared by the app.
Provider fixtures remain preferable for deterministic tests.
Logging
Never log secret values, authorization headers, session cookies, password or reset material, TOTP seeds, raw SAML assertions, or complete payment payloads. Log a provider request ID and a redacted reason class instead.
See Webhooks and AI Gateway.