(
input: OAuthCompleteInput,
)
| 1813 | // complete — redeem the session, exchange the code, mint the connection. |
| 1814 | // ----------------------------------------------------------------------- |
| 1815 | const complete = ( |
| 1816 | input: OAuthCompleteInput, |
| 1817 | ): Effect.Effect<Connection, OAuthCompleteError | OAuthSessionNotFoundError | StorageFailure> => |
| 1818 | Effect.gen(function* () { |
| 1819 | const sessionRow = yield* deps.fuma.use("oauth_session.findFirst", (db) => |
| 1820 | looseDb(db).findFirst("oauth_session", { |
| 1821 | where: (b: any) => b("state", "=", String(input.state)), |
| 1822 | }), |
| 1823 | ); |
| 1824 | if (!sessionRow) { |
| 1825 | return yield* new OAuthSessionNotFoundError({ state: input.state }); |
| 1826 | } |
| 1827 | const session = { |
| 1828 | owner: String(sessionRow.owner) as Owner, |
| 1829 | clientSlug: OAuthClientSlug.make(String(sessionRow.client_slug)), |
| 1830 | integration: IntegrationSlug.make(String(sessionRow.integration)), |
| 1831 | name: ConnectionName.make(String(sessionRow.name)), |
| 1832 | template: AuthTemplateSlug.make(String(sessionRow.template)), |
| 1833 | redirectUrl: String(sessionRow.redirect_url), |
| 1834 | pkceVerifier: sessionRow.pkce_verifier == null ? null : String(sessionRow.pkce_verifier), |
| 1835 | identityLabel: sessionRow.identity_label == null ? null : String(sessionRow.identity_label), |
| 1836 | expiresAt: Number(sessionRow.expires_at), |
| 1837 | // The scope set `start` requested (the integration's declared or |
| 1838 | // discovered scopes), persisted on the session payload. Drives the |
| 1839 | // recorded-scope fallback when the AS omits `scope`. Missing/legacy |
| 1840 | // payloads fall back to the client's scopes below. |
| 1841 | requestedScopes: requestedScopesFromPayload(sessionRow.payload), |
| 1842 | // The app's owner, recorded by `start` — reload the SAME app at |
| 1843 | // completion by explicit owner (no derivation). Defaults to the session |
| 1844 | // owner for same-owner connects. |
| 1845 | clientOwner: |
| 1846 | clientOwnerFromPayload(sessionRow.payload) ?? (String(sessionRow.owner) as Owner), |
| 1847 | }; |
| 1848 | |
| 1849 | // Annotate as soon as the session resolves the flow's identity, so even |
| 1850 | // a completion that fails at the exchange still says WHOSE connect died. |
| 1851 | yield* Effect.annotateCurrentSpan({ |
| 1852 | "executor.integration": String(session.integration), |
| 1853 | "executor.connection": String(session.name), |
| 1854 | "executor.template": String(session.template), |
| 1855 | "executor.oauth.client": String(session.clientSlug), |
| 1856 | "executor.oauth.client_first_party": isFirstPartyOAuthClientSlug( |
| 1857 | String(session.clientSlug), |
| 1858 | ), |
| 1859 | }); |
| 1860 | |
| 1861 | // Expired sessions are not redeemable — drop + treat as not found. |
| 1862 | if (Number.isFinite(session.expiresAt) && session.expiresAt <= Date.now()) { |
| 1863 | yield* deleteSession(input.state); |
| 1864 | return yield* new OAuthSessionNotFoundError({ state: input.state }); |
| 1865 | } |
| 1866 | |
| 1867 | // Reload the SAME app `start` resolved, by its explicit recorded owner. |
| 1868 | const client = yield* loadClient(session.clientOwner, session.clientSlug); |
| 1869 | if (!client) { |
| 1870 | return yield* new OAuthCompleteError({ |
| 1871 | message: `OAuth client not found: ${session.clientSlug}`, |
| 1872 | restartRequired: true, |
nothing calls this directly
no test coverage detected