Repository navigation
Description
What problem would this solve?
Integration configuration is primarily instance-wide. Features that connect an individual user's account or data source currently need bespoke tables and services, making OAuth, secret storage, refresh, health, revocation, and account UI inconsistent.
What would you like to be able to do?
Add a generic end-user integration connection framework while keeping instance-level enablement and OAuth client configuration under administrator control. A connection should bind a user to an integration/provider account with encrypted credentials, declared scopes, refresh/revoke lifecycle, and privacy-safe health state.
Acceptance criteria
- Manifests distinguish instance enablement/configuration, system OAuth client secrets, and end-user connection credentials.
- A generic connection schema records user, integration, external subject, scopes, encrypted credential reference, status, timestamps, and metadata without plaintext secrets.
- The framework supports OAuth authorization-code/PKCE and API-token style connections with provider-specific adapters.
- Redirect/state/PKCE validation prevents CSRF, account-confusion, and redirect abuse.
- Server request context gives integrations an authorized user connection without exposing credentials to the browser or unrelated integrations.
- Refresh, expiry, re-consent, scope changes, revocation, provider errors, and account deletion have explicit lifecycle behavior.
- Users can connect, inspect status/scopes, reconnect, and disconnect from account settings.
- Admins can enable/disable a provider and configure the system client without seeing user tokens.
- Logs, metrics, health checks, and support diagnostics are redacted and tenant/user scoped.
- Authorization tests prevent cross-user connection lookup/use and confused-deputy requests.
- A migration/adoption plan evaluates Dawarich and linked accounts without forcing a risky flag-day rewrite.
- Developer documentation includes a reference provider and test harness.
Alternatives or workarounds
One custom table/service per provider is initially quick but duplicates security-sensitive lifecycle code. Making all integration config user-scoped would incorrectly expose deployment-level settings.
Additional context
Reported starting point
integration_configis unique per integration and serves administrator-managed settings.- Better Auth has linked OSM/Mapillary accounts.
- Dawarich uses a dedicated
personal_timeline_connectionand encrypted credential flow. - Integration manifests can declare
credentialOwner: end-user, but the framework does not operationalize a generic per-user connection lifecycle. - Document user-data trust boundaries and decide the E2EE architecture #312 is complete. The accepted confidentiality architecture classifies provider credentials needed by the server as server-required secrets, encrypted with a server-held key when plaintext use is required. This provides the trust-model baseline for this framework; general user-data E2EE is not implemented.
Area
Integration framework, authentication, secret storage, account settings, API.
Dependencies
The trust-model decision in #312 is complete, so it is no longer an unresolved design prerequisite. Credential and connected-data handling must follow docs/docs/developer/user-data-confidentiality-architecture.md and docs/docs/developer/user-data-trust-model.md. Future client encryption remains subject to the accepted architecture's design and security-review gates; it is not implied by encrypted provider-token storage.
Metadata
Metadata
Assignees
Labels
Type
Fields
Priority
Effort
Activity
[-]Create a generic end-user integration connection framework[/-][+]Add reusable per-user integration connections[/+]Medformatik commentedon Nov 1, 2026
Closing as not planned after a backlog review.
apps/api/src/db/timeline-connection-schema.ts), and it works.credentialOwner: "end-user"integration isreviews-mangrove, which uses a client-held keypair, not OAuth.Extract the shared framework when a second real server-side per-user provider actually lands. Reopen then.