Imported from mcowger/plexus (
packages/backend/AGENTS.md). Install upstream withnpx skills add mcowger/plexus --skill backend. Copyright stays with the author.
Backend agent rules
Adding an OAuth provider
A new OAuth provider is not done when its auth module works. The
muse-code integration (Sep 2026) shipped a working device flow, dispatch
path, quota checker, and model discovery — but the provider never appeared
in the UI because its facade registration was missing. Every item below is
required; verify each against the live server, not just unit tests.
Checklist
- Auth module (
src/services/oauth/{id}.ts): implement pi-ai'sOAuthAuth(login/refresh/toAuth). Keep credentials opaque — parse/encode helpers live beside the flow. - Facade registration (
src/services/oauth/oauth-providers.ts): add aCUSTOM_OAUTH_PROVIDERSentry when pi-ai ships no provider with that id. This single registration drives config validation (isKnownOAuthProviderId), the management UI list (listOAuthProviders), and login sessions. Without it, everything else on this list is dead code from the user's perspective. - Dispatch (
src/services/oauth/oauth-native-request.ts): base-URL fallback entry (pi-ai has nobaseUrlfor custom providers), wire-type mapping,prepare{Id}OAuthRequest, andisNativeOAuthProvidermembership. Add same-format bypass insrc/services/dispatch/request-payload-builder.tswhen the wire type needs it. Provider-specific wire quirks (dropped/rejected fields, tool coercions) go in an implicit adapter (src/transformers/adapters/, registered inindex.ts, injected inadapter-resolver.ts) — never in the native prep function. - Quota checker: follow the
add-quota-checkerskill (.agents/skills/add-quota-checker/SKILL.md), then map the provider id to the checker type ingetOAuthCheckerType(packages/frontend/src/hooks/useProviderForm.tsx) so the provider form auto-selects it. - Model discovery: add the provider branch in both
discoverProviderModels(src/services/providers/provider-model-discovery.ts, for configured providers) and the management login-flow route (src/routes/management/oauth.ts, for pre-configuration Fetch Models). A provider with no pi-ai catalog entry gets an empty list unless both are wired. - Tests: unit tests per seam (auth flow, dispatch headers, checker
mapping, discovery + fallback, management route). Seed
OAuthAuthManageronly afterawait manager.initialize()— the constructor's async DB load rebuildsauthDataon landing and wipes earlier seeds (flakes only in multi-file runs).
Verification
bun x tsc --noEmitfrompackages/backend, biome on touched files, and the affected vitest suites.- Curl the live dev server (default
ADMIN_KEY=passwordlocally):curl -H "x-admin-key: password" localhost:<port>/v0/management/oauth/providersmust list the new id. Unit tests run against the working tree — only the live endpoint proves the committed code serves it. When the UI disagrees with the tests, check this endpoint first: a missing id means a missing registration, not a stale server. - After every commit:
git show --stat HEADmust list all intended files (see thegit-commitskill's Verify Every Commit section).