A connection is a named, stored credential and configuration for an outside service, such as an email sender or a spam-check provider. Content that needs to reach that service refers to the connection by its id. A form action, for example, names a connectionId rather than carrying its own copy of an API key.
Connection kinds and providers
| Provider | Kind | Config (meta) | Secrets (credentials) |
|---|---|---|---|
brevo | esp | listId (optional) | apiKey (required) |
turnstile | captcha | siteKey (optional) | secretKey (required) |
webhook | webhook | events (optional, a subset of the fixed vocabulary entity.published, entity.unpublished; absent means all events), acceptsFormSubmissions (optional true/false, defaults to not accepting) | endpointUrl (required, https://, no embedded username or password), signingSecret (required, at least 32 characters) |
smtp | smtp | from (required), fromName (optional), to (optional), subjectTemplate (optional), allowedRecipients (optional, up to 16 fixed addresses) | host (required), port (fixed at 587), username (required), password (required) |
A webhook's endpoint URL is itself stored as a secret rather than as config, because a webhook URL commonly carries secret material in its path or query string.
The manage_connection tool
action is create, update, rotate, or revoke. Every input carries a provider (only at create) plus the action's own fields.
create takes provider, label, credentials, and optional meta:
{
"action": "create",
"input": {
"provider": "brevo",
"label": "Marketing ESP",
"credentials": { "apiKey": "xkeysib-..." },
"meta": { "listId": 4 }
}
}
update takes id, expectedRevision, and at least one of label or meta. It never touches credentials:
{
"action": "update",
"input": { "id": "conn_01h...", "expectedRevision": 1, "label": "Marketing ESP (EU list)" }
}
rotate takes id, expectedRevision, and credentials, and replaces the whole stored credential object with the new one. Nothing else about the connection changes:
{
"action": "rotate",
"input": { "id": "conn_01h...", "expectedRevision": 2, "credentials": { "apiKey": "xkeysib-new..." } }
}
revoke takes id and expectedRevision, and is permanent: it clears the stored credential and marks the connection revoked. There is no un-revoke. A revoked connection's metadata stays visible to query, but it can never be updated or rotated again.
{ "action": "revoke", "input": { "id": "conn_01h...", "expectedRevision": 3 } }
Every write is CAS-guarded with expectedRevision, exactly like a content write: a mismatch returns a revision_conflict error naming the current revision.
Secrets are write-only
Credentials never come back out of Noon, through any tool, through query, or under any scope. Query the connections collection to read everything else back: id, provider, kind, label, meta, revision, status, lastUsedAt, createdAt, and updatedAt. The stored credential itself is not a field you can select, filter on, or sort by. There is no path to it at all.
Scopes
Five scopes exist: root, content:read, content:write, query:read, secrets:write.
manage_connection requires secrets:write specifically. Holding content:write does not grant it: an agent that can rewrite every page on the site cannot administer connections unless it is also given secrets:write. There is no secrets:read. The only visible signal about a connection's credential is its status, never the credential itself. root bypasses every scope check.
Health checks
create and rotate both run the provider's health check, if it has one, and store the result as the connection's status: healthy, broken, or unchecked. update and revoke never run a health check.
brevoandwebhookmake one outbound request each and record only whether it succeeded; the response body is discarded either way.smtpopens a real session and authenticates, without sending any mail.turnstilehas no automatic check. A newly created or rotated Turnstile connection staysunchecked, because verifying it needs a response token only a real visitor can produce.
Who consumes which kind
A FormBlock's actions reference a connection by connectionId: an email action or an esp action uses an smtp or brevo connection to send; a captcha precondition uses a turnstile connection to verify the visitor before anything is written; a webhook action uses a webhook connection to notify an outside system.