feat(services): use_default_connection opt-out + atomic pin_service_ids#431
Merged
Conversation
…ds on connection creation White-label integrations couldn't atomically associate a new service with a new connection. Two additions close the gap: - Per-instance `use_default_connection` flag (migration 090, default true). When false, an unbound OAuth instance no longer falls back to the identity's default connection — it reports needs_authentication until one is pinned. Honored in resolve_instance_auth, the scope pre-gate, and the credentials classifier so the dashboard badge matches execution. Plumbed through the service create/update API, responses, and a dashboard toggle. - `pin_service_ids` on connection creation. The import path (POST /v1/connections/import) binds atomically via OrgScope::create_connection_and_pin — a bad id rolls the whole import back so no orphan connection is left behind. The OAuth-orchestrated flow carries the ids on the flow row (migration 091, UUID[]) and binds them on callback, staying best-effort to preserve the exchanged tokens and the existing spoofed-id security contract. Singular service_instance_id kept as an alias. Adds tests/service_pin_connection.rs covering the fallback gate, atomic bind, and rollback-on-bad-id. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Codecov Report❌ Patch coverage is 📢 Thoughts on this report? Let us know! |
… design
Addresses the Sentry review on the OAuth callback: the browser success
redirect deliberately does not enumerate bound_service_instance_ids in the
query string. A user-controllable, browser-visible URL is the wrong transport
for authoritative binding state and can't losslessly carry a list. The
authoritative set is the DB — a partner reads it back via
GET /v1/connections/{connection_id} (its `used_by` list), keyed off the
connection_id already present in the redirect. The JSON branch keeps the full
list as a convenience for programmatic callers (authenticated response body,
not a URL).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
angel-manuel
added a commit
that referenced
this pull request
Jul 6, 2026
…ion tab (#432) PR #431 added the per-service use_default_connection opt-out toggle but placed it on the overview tab, not the credentials (Connection) tab where the provider connection is actually managed. Users looking at connection settings could neither see nor change the fallback behavior. Relocate the toggle into the credentials tab's OAuth branch, directly below the Connection picker and above the Save/Connect actions. The field was already wired end-to-end (types, updateService, save() diff); the same credentials-tab Save button persists it, so no other changes are needed. Co-authored-by: Factory <factory@overslash.dev> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This was referenced Jul 8, 2026
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Context
White-label integrations struggle to associate a new service with a new connection atomically. Two gaps drove this:
What changed
A. Per-instance
use_default_connection(migration090, defaulttrue)A service-instance column. When
false, an unbound OAuth instance never borrows the identity's default connection — it reportsneeds_authenticationuntil one is pinned. Honored consistently in all three resolution sites so the dashboard badge can't disagree with execution:resolve_instance_auth(execution)check_required_scopes(scope pre-gate)resolve_effective_scopes/ list classifierPlumbed through
CreateServiceInput/UpdateServiceInput, the summary/detail responses,types.ts, and a toggle on the service create + detail pages.B. Atomic
pin_service_idson connection creationPOST /v1/connections/import, the white-label case): fully atomic via newOrgScope::create_connection_and_pin— connection insert + instance binds in one transaction. A bad / foreign-owned / org-level id rolls the whole import back, leaving no orphan connection.POST /v1/connections+ callback): plural ids persisted on the flow row (migration091,UUID[]), bound on callback. Kept best-effort here (keeps the exchanged tokens, surfacesservice_instance_bind_error) to preserve the existing spoofed-id security contract.service_instance_idretained as a back-compat alias on both paths.Tests
tests/service_pin_connection.rs(3 new): the fallback gate, atomic bind on import, and rollback-on-bad-id. Full local runs pass acrossconnection_import,services_auto_connect,oauth_return_url,multi_org,connection_credential_source,oauth_connections_ux,connections_admin_view,instance_visibility_consistency. Clippy clean; sqlx offline cache regenerated; dashboardsvelte-check+ strict build pass; vet clean.🤖 Generated with Claude Code