Skills

Add OAuth Provider

Adds an OAuth provider with its code changes and approval steps.

Install

npx skills add superdesigndev/treg --skill add-oauth-provider -g -a claude-code -y
Category
Engineering
Updated
3d ago
License
See repository
Context cost
Mediumabout 2,360 tokens
Runs scripts
No, instructions only

What it does

Add a provider to treg's OAuth registry (the ones treg holds its own approved app for). Use when asked to "add YouTube/Notion/Meta OAuth", "support connecting X", "add a new OAuth provider", or when a connect flow, capability picker, channel/account picker, or provider health probe needs building. Covers the code changes, the platform-side approval steps, and the pitfalls that don't announce themselves.

Adding an OAuth provider

Two connect modes exist. BYO (POST /oauth/start with a caller-supplied client_id/secret) already works for any OAuth2 provider and needs no code. This skill is the registry path: treg owns the registered app, so the user picks a provider and supplies nothing. Only add a provider here if treg holds, or is willing to go get, the platform approval behind it.

Read src/treg/oauth_providers.py's module docstring first. The rule it states is the one most easily broken: scopes are per capability, never per provider.

The code changes

All of these, in order. Skipping any one produces a provider that looks fine in /oauth/providers and fails somewhere the tests don't reach.

1. Credentials → src/treg/config.py

Add <name>_client_id / <name>_client_secret to Settings, loaded from TREG_<NAME>_CLIENT_ID / _SECRET. Reuse an existing pair when the platform uses one app for several products, all four Google providers plus YouTube share google_client_id, because Google verification and API audits are scoped to the Cloud project, not to the OAuth client. A second client in the same project isolates nothing.

2. The provider → src/treg/oauth_providers.py

Add the OAuthProvider and register it in REGISTRY (easy to forget; the provider silently doesn't exist until you do).

Capabilities are cumulative supersets, never swaps:

scopes={
    "read":   [READ_SCOPES],
    "post":   [*READ_SCOPES, UPLOAD],           # post CONTAINS read
    "manage": [*READ_SCOPES, UPLOAD, WRITE],    # manage CONTAINS post
}

satisfied_capabilities() is set-containment, so a non-cumulative write yields a connection that can write but reports "no read". default_capability is the broadest (most scopes), deliberately, see its docstring.

Read the whole SKILL.md on GitHub

More in Engineering