Design: docs/connector-auth.md. Companion to #180.
The problem
Authorization-code OAuth encodes "the user is present and consents right now." An agent chain firing at 3am from a cron trigger has no user present.
FreeWebStore issues a 24h access token with no refresh grant (grant_types_supported: ["authorization_code"]). So even a perfect DCR+PKCE flow (#180) yields a chain that dies daily and needs a human at a browser to restart it.
Nothing in the platform models this. A subscriber can wire an interactive-only connector into a cron trigger or an agent-to-agent connection, and the failure surfaces ~24h later as deliveries piling into the dead-letter queue. The delivery outbox (migration 0058) makes that visible and replayable rather than silent — a real improvement — but replay cannot fix an expired credential, so every retry is doomed and the human still finds out late.
Whether a credential can survive unattended is a property of the connector, and the platform must know it before wiring, not after.
Scope
- Connectors declare
unattended: "yes" | "refresh" | "interactive-only", derived from discovered metadata where possible (refresh_token in grant_types_supported -> refresh).
- Wiring an
interactive-only connector into a cron trigger or an agent-to-agent connection warns at create time — same principle as validating connection filters at create time (a chain that looks healthy but cannot run is worse than one that fails loudly).
- Credential expiry becomes a distinct delivery outcome from a transient failure: a dead letter reading "reconnect FreeWebStore" is actionable; five backoff attempts against a 401 are noise. Do not burn the retry budget on auth failures.
- Notify before a grant lapses, not after.
Acceptance
- A connector exposes its unattended class; MCP connectors derive it from discovered metadata.
- Creating a cron trigger or connection against an interactive-only connector surfaces a warning.
- A 401/403 from an expired grant dead-letters immediately with a reconnect message rather than retrying.
- Expiring grants produce a notification ahead of expiry.
- Tests cover derivation, the wiring-time warning, and expiry-vs-transient classification.
Design:
docs/connector-auth.md. Companion to #180.The problem
Authorization-code OAuth encodes "the user is present and consents right now." An agent chain firing at 3am from a cron trigger has no user present.
FreeWebStore issues a 24h access token with no refresh grant (
grant_types_supported: ["authorization_code"]). So even a perfect DCR+PKCE flow (#180) yields a chain that dies daily and needs a human at a browser to restart it.Nothing in the platform models this. A subscriber can wire an interactive-only connector into a cron trigger or an agent-to-agent connection, and the failure surfaces ~24h later as deliveries piling into the dead-letter queue. The delivery outbox (migration 0058) makes that visible and replayable rather than silent — a real improvement — but replay cannot fix an expired credential, so every retry is doomed and the human still finds out late.
Scope
unattended: "yes" | "refresh" | "interactive-only", derived from discovered metadata where possible (refresh_tokeningrant_types_supported->refresh).interactive-onlyconnector into a cron trigger or an agent-to-agent connection warns at create time — same principle as validating connection filters at create time (a chain that looks healthy but cannot run is worse than one that fails loudly).Acceptance