Outgoing OAuth: promotion path from SaaS to core¶
Goal: Outgoing OAuth (third-party API credentials, OAuth link flow, refresh) is a core single-user capability. Incoming browser OAuth (GitHub login, tenant identity) stays SaaS enterprise UI + control plane only.
Do not conflate with saas-architecture.md §0.4 planes: outbound provider auth ≠ MCP transport keys ≠ execute JWT identity.
Current state¶
| Concern | Location |
|---|---|
| OAuth token/link logic | plasm-runtime (hosted_oauth_kv, oauth_client), plasm-agent-core (oauth_link_catalog, oauth_link_session, outbound_secret_provider) |
| Link + outbound-secret HTTP (hosted) | plasm-saas: http_oauth_link.rs, http_outbound_secrets.rs |
| Control-plane contract | private-control-plane-api.md — /internal/oauth-link/v1/*, /internal/outbound-secrets/v1/* |
| Phoenix metadata + UI | web/ contexts and LiveViews (ops providers, project outbound connect); sync via PlasmMcpClient.sync_oauth_link_*, sync_outbound_secret_* |
| Pure OSS binary | PlasmHostState.saas == None — no /internal/*; outbound today is limited unless extended |
Target seam¶
- Mount outgoing OAuth HTTP on OSS data plane — Move or duplicate the public link/callback and secret write surfaces from
plasm-saasintoplasm-agent-coreHTTP (http.rs/ dedicated module), gated for single-user / local use (e.g. localhost, shared local secret, or file-based allowlist — exact policy is a follow-on implementation task). - Keep SaaS control-plane variants — Hosted deployments may keep
/internal/*for Phoenix automation; contract doc remains the integrator surface. - Fence incoming OAuth — GitHub login,
IncomingAuthController,http_incoming_tenant, and workspace binding remain inweb/+plasm-saasonly. - Phoenix as composer — Ops/project UIs continue to call core or
/internal/*to upsert providers and secrets; they do not own the OAuth protocol implementation.
Migration notes¶
- Shared header auth for
/internal/*lives inplasm-agent-corecontrol_plane_http.rs; OSS-mounted outgoing routes need a different gate. PlasmSaaSHostExtensioncurrently wiresoauth_link_catalogandoutbound_secret_provider; pure OSS may need the same types attached toPlasmOssHostStateor a minimal extension without tenant MCP — seeserver_state.rsinplasm-agent-core.