Summary
For configurable integrations (Google Content Safety API, OpenAI, Zentropi), Coop only checks that an API key is present, never that it is valid:
setIntegrationConfig stores whatever string is submitted with no validation call against the provider.
- Each signal's
getDisabledInfo only tests key presence (e.g. !credential?.apiKey), so a wrong, revoked, or unauthorized key shows the integration as fully configured and its signals as enabled.
- The first sign of a bad key is at rule execution time: the provider returns 401/403, the fetcher throws a generic error (
server/services/signalsService/signals/third_party_signals/open_ai/moderation/openAIModerationUtils.ts and equivalents), and because auth failures are not classified as SignalPermanentError, Coop retries the same doomed call on every subsequent item.
Impact
- Adopters get a silently broken integration: settings UI looks healthy while every signal invocation fails, visible only in traces.
- Rules evaluate with the signal value unavailable, so detection silently degrades.
- Repeated retries hammer the provider's API with requests that can never succeed.
Proposal
- Validate on save: when a key is saved in integration settings, make a cheap authenticated call to the provider and surface success or failure immediately in the UI.
- Classify auth failures as permanent: treat 401/403 from providers as
SignalPermanentError so the rejection is cached instead of retried per item.
- Surface key health: show a clear state in integration settings when the last provider response indicated an invalid or unauthorized key, with guidance to re-check the key.
🤖 Generated with Claude Code
https://claude.ai/code/session_01Wx3nmYtSe8Cb37QQ8WY3mx
Summary
For configurable integrations (Google Content Safety API, OpenAI, Zentropi), Coop only checks that an API key is present, never that it is valid:
setIntegrationConfigstores whatever string is submitted with no validation call against the provider.getDisabledInfoonly tests key presence (e.g.!credential?.apiKey), so a wrong, revoked, or unauthorized key shows the integration as fully configured and its signals as enabled.server/services/signalsService/signals/third_party_signals/open_ai/moderation/openAIModerationUtils.tsand equivalents), and because auth failures are not classified asSignalPermanentError, Coop retries the same doomed call on every subsequent item.Impact
Proposal
SignalPermanentErrorso the rejection is cached instead of retried per item.🤖 Generated with Claude Code
https://claude.ai/code/session_01Wx3nmYtSe8Cb37QQ8WY3mx