History

refactor(v2): remove legacy oauth token and credential id schema

Drops the remaining legacy OAuth token model and old credential ID aliases so schema consumers align on auth connection and source auth binding identifiers.

Rhys Sullivan committed 8 months ago

Commit 336a0c81 parent 6d8f04411 files · +36 −64Browse files

Unified · Split

11 files
  1. apps/convex/convex/executor.test.ts +10 −10
  2. apps/web/components/credentials/credentials-view.tsx +2 −2
  3. apps/web/components/tools/source-management-panel.tsx +1 −1
  4. apps/web/lib/control-plane/atoms/credentials.ts +1 −2
  5. packages/engine/src/credential-resolver.ts +14 −5
  6. packages/management-api/src/credentials/api.ts +2 −2
  7. packages/management-api/src/credentials/service.ts +2 −2
  8. packages/schema/src/ids.ts +0 −8
  9. packages/schema/src/index.ts +0 −1
  10. packages/schema/src/models/oauth-token.ts +0 −27
  11. packages/schema/src/models/source-credential-binding.ts +4 −4
apps/convex/convex/executor.test.ts+10−10
@@ -200,8 +200,8 @@ describe("Convex executor and control-plane", () => { · 199 unmodified lines
200 t.action(api.controlPlane.upsertCredentialBinding, {200 t.action(api.controlPlane.upsertCredentialBinding, {
201 workspaceId: "ws_1",201 workspaceId: "ws_1",
202 payload: {202 payload: {
203 id: "credential_binding_1",203 id: "auth_binding_1",
204 credentialId: "cred_1",204 credentialId: "conn_1",
205 scopeType: "workspace",205 scopeType: "workspace",
206 sourceKey: "source:github",206 sourceKey: "source:github",
207 provider: "bearer",207 provider: "bearer",
@@ -216,7 +216,7 @@ describe("Convex executor and control-plane", () => { · 8 unmodified lines
216 workspaceId: string | null;216 workspaceId: string | null;
217 };217 };
218 218
219 expect(addedCredential.id).toBe("credential_binding_1");219 expect(addedCredential.id).toBe("auth_binding_1");
220 expect(addedCredential.workspaceId).toBe("ws_1");220 expect(addedCredential.workspaceId).toBe("ws_1");
221 221
222 const listedCredentials = (yield* Effect.tryPromise(() =>222 const listedCredentials = (yield* Effect.tryPromise(() =>
@@ -228,12 +228,12 @@ describe("Convex executor and control-plane", () => { · 5 unmodified lines
228 }>;228 }>;
229 229
230 expect(listedCredentials).toHaveLength(1);230 expect(listedCredentials).toHaveLength(1);
231 expect(listedCredentials[0]?.id).toBe("credential_binding_1");231 expect(listedCredentials[0]?.id).toBe("auth_binding_1");
232 232
233 const removedCredential = (yield* Effect.tryPromise(() =>233 const removedCredential = (yield* Effect.tryPromise(() =>
234 t.mutation(api.controlPlane.removeCredentialBinding, {234 t.mutation(api.controlPlane.removeCredentialBinding, {
235 workspaceId: "ws_1",235 workspaceId: "ws_1",
236 credentialBindingId: "credential_binding_1",236 credentialBindingId: "auth_binding_1",
237 }),237 }),
238 )) as {238 )) as {
239 removed: boolean;239 removed: boolean;
@@ -1127,8 +1127,8 @@ describe("Convex executor and control-plane", () => { · 887 unmodified lines
1127 t.action(api.controlPlane.upsertCredentialBinding, {1127 t.action(api.controlPlane.upsertCredentialBinding, {
1128 workspaceId: "ws_cred",1128 workspaceId: "ws_cred",
1129 payload: {1129 payload: {
1130 id: "credential_binding_linear",1130 id: "auth_binding_linear",
1131 credentialId: "cred_linear",1131 credentialId: "conn_linear",
1132 scopeType: "workspace",1132 scopeType: "workspace",
1133 sourceKey: "source:src_graphql_cred_1",1133 sourceKey: "source:src_graphql_cred_1",
1134 provider: "bearer",1134 provider: "bearer",
@@ -1320,8 +1320,8 @@ describe("Convex executor and control-plane", () => { · 185 unmodified lines
1320 t.action(api.controlPlane.upsertCredentialBinding, {1320 t.action(api.controlPlane.upsertCredentialBinding, {
1321 workspaceId: "ws_mcp_ingest",1321 workspaceId: "ws_mcp_ingest",
1322 payload: {1322 payload: {
1323 id: "credential_binding_mcp",1323 id: "auth_binding_mcp",
1324 credentialId: "cred_mcp",1324 credentialId: "conn_mcp",
1325 scopeType: "workspace",1325 scopeType: "workspace",
1326 sourceKey: "source:src_mcp_ingest_1",1326 sourceKey: "source:src_mcp_ingest_1",
1327 provider: "bearer",1327 provider: "bearer",
@@ -1612,7 +1612,7 @@ describe("Convex executor and control-plane", () => { · 284 unmodified lines
1612 t.action(api.controlPlane.upsertCredentialBinding, {1612 t.action(api.controlPlane.upsertCredentialBinding, {
1613 workspaceId,1613 workspaceId,
1614 payload: {1614 payload: {
1615 id: "credential_binding_oauth_runtime_1",1615 id: "auth_binding_oauth_runtime_1",
1616 credentialId: "conn_oauth_runtime_1",1616 credentialId: "conn_oauth_runtime_1",
1617 scopeType: "workspace",1617 scopeType: "workspace",
1618 sourceKey: `source:${sourceId}`,1618 sourceKey: `source:${sourceId}`,
apps/web/components/credentials/credentials-view.tsx+2−2
@@ -172,7 +172,7 @@ export function CredentialsView() { · 171 unmodified lines
172 172
173 const requestId =173 const requestId =
174 credentialEditingId ??174 credentialEditingId ??
175 (createLocalId("credential_binding_") as SourceCredentialBinding["id"]);175 (createLocalId("auth_binding_") as SourceCredentialBinding["id"]);
176 176
177 setCredentialBusyId(requestId);177 setCredentialBusyId(requestId);
178 178
@@ -319,7 +319,7 @@ export function CredentialsView() { · 140 unmodified lines
319 id="credential-id"319 id="credential-id"
320 value={credentialIdInput}320 value={credentialIdInput}
321 onChange={(event) => setCredentialIdInput(event.target.value)}321 onChange={(event) => setCredentialIdInput(event.target.value)}
322 placeholder="cred_123"322 placeholder="conn_123"
323 required323 required
324 disabled={credentialBusyId !== null}324 disabled={credentialBusyId !== null}
325 />325 />
apps/web/components/tools/source-management-panel.tsx+1−1
@@ -497,7 +497,7 @@ export function SourceManagementPanel({ editSource, onDone }: SourceManagementPa · 496 unmodified lines
497 workspaceId,497 workspaceId,
498 payload: toCredentialBindingUpsertPayload({498 payload: toCredentialBindingUpsertPayload({
499 ...(existingBinding ? { id: existingBinding.id } : {}),499 ...(existingBinding ? { id: existingBinding.id } : {}),
500 credentialId: (existingBinding?.credentialId ?? createLocalId("cred_")) as SourceCredentialBinding["credentialId"],500 credentialId: (existingBinding?.credentialId ?? createLocalId("conn_")) as SourceCredentialBinding["credentialId"],
501 scopeType,501 scopeType,
502 sourceKey,502 sourceKey,
503 provider: "oauth2",503 provider: "oauth2",
apps/web/lib/control-plane/atoms/credentials.ts+1−2
@@ -4,7 +4,6 @@ import type { · 3 unmodified lines
4 UpsertCredentialBindingPayload,4 UpsertCredentialBindingPayload,
5} from "@executor-v2/management-api/credentials/api";5} from "@executor-v2/management-api/credentials/api";
6import type {6import type {
7 CredentialBindingId,
8 CredentialProvider,7 CredentialProvider,
9 CredentialScopeType,8 CredentialScopeType,
10 SourceCredentialBinding,9 SourceCredentialBinding,
@@ -55,7 +54,7 @@ export const removeCredentialBinding = controlPlaneClient.mutation("credentials" · 44 unmodified lines
55// ---------------------------------------------------------------------------54// ---------------------------------------------------------------------------
56 55
57export const toCredentialBindingUpsertPayload = (input: {56export const toCredentialBindingUpsertPayload = (input: {
58 id?: CredentialBindingId;57 id?: SourceCredentialBinding["id"];
59 credentialId: SourceCredentialBinding["credentialId"];58 credentialId: SourceCredentialBinding["credentialId"];
60 scopeType: CredentialScopeType;59 scopeType: CredentialScopeType;
61 sourceKey: string;60 sourceKey: string;
packages/engine/src/credential-resolver.ts+14−5
@@ -1,7 +1,5 @@
1import type {1import type {
2 OAuthToken,
3 SourceCredentialBinding,2 SourceCredentialBinding,
4 WorkspaceId,
5} from "@executor-v2/schema";3} from "@executor-v2/schema";
6import type {4import type {
7 RuntimeToolCallCredentialContext,5 RuntimeToolCallCredentialContext,
@@ -157,11 +155,22 @@ const parseAdditionalHeaders = ( · 149 unmodified lines
157 return decoded.right;155 return decoded.right;
158};156};
159 157
158type OAuthAccessTokenRecord = {
159 workspaceId: string;
160 organizationId: string | null;
161 accountId: string | null;
162 sourceId: string;
163 accessTokenRef: string;
164 expiresAt: number | null;
165 createdAt: number;
166 updatedAt: number;
167};
168
160const tokenScopeScore = (169const tokenScopeScore = (
161 token: OAuthToken,170 token: OAuthAccessTokenRecord,
162 context: RuntimeToolCallCredentialContext,171 context: RuntimeToolCallCredentialContext,
163): number => {172): number => {
164 if (token.workspaceId !== (context.workspaceId as WorkspaceId)) {173 if (token.workspaceId !== context.workspaceId) {
165 return -1;174 return -1;
166 }175 }
167 176
@@ -196,7 +205,7 @@ const tokenScopeScore = ( · 28 unmodified lines
196};205};
197 206
198export const selectOAuthAccessToken = (207export const selectOAuthAccessToken = (
199 tokens: ReadonlyArray<OAuthToken>,208 tokens: ReadonlyArray<OAuthAccessTokenRecord>,
200 context: RuntimeToolCallCredentialContext,209 context: RuntimeToolCallCredentialContext,
201 sourceId: string,210 sourceId: string,
202): string | null => {211): string | null => {
packages/management-api/src/credentials/api.ts+2−2
@@ -1,6 +1,6 @@
1import { HttpApiEndpoint, HttpApiGroup, HttpApiSchema } from "@effect/platform";1import { HttpApiEndpoint, HttpApiGroup, HttpApiSchema } from "@effect/platform";
2import {2import {
3 CredentialBindingIdSchema,3 SourceAuthBindingIdSchema,
4 SourceCredentialBindingSchema,4 SourceCredentialBindingSchema,
5 WorkspaceIdSchema,5 WorkspaceIdSchema,
6} from "@executor-v2/schema";6} from "@executor-v2/schema";
@@ -60,7 +60,7 @@ export type RemoveCredentialBindingResult = · 53 unmodified lines
60const workspaceIdParam = HttpApiSchema.param("workspaceId", WorkspaceIdSchema);60const workspaceIdParam = HttpApiSchema.param("workspaceId", WorkspaceIdSchema);
61const credentialBindingIdParam = HttpApiSchema.param(61const credentialBindingIdParam = HttpApiSchema.param(
62 "credentialBindingId",62 "credentialBindingId",
63 CredentialBindingIdSchema,63 SourceAuthBindingIdSchema,
64);64);
65 65
66export class CredentialsApi extends HttpApiGroup.make("credentials")66export class CredentialsApi extends HttpApiGroup.make("credentials")
packages/management-api/src/credentials/service.ts+2−2
@@ -1,7 +1,7 @@
1import { type SourceStoreError } from "@executor-v2/persistence-ports";1import { type SourceStoreError } from "@executor-v2/persistence-ports";
2import {2import {
3 type CredentialBindingId,
4 type SourceCredentialBinding,3 type SourceCredentialBinding,
4 type SourceAuthBindingId,
5 type WorkspaceId,5 type WorkspaceId,
6} from "@executor-v2/schema";6} from "@executor-v2/schema";
7import * as Effect from "effect/Effect";7import * as Effect from "effect/Effect";
@@ -18,7 +18,7 @@ export type UpsertCredentialBindingInput = { · 10 unmodified lines
18 18
19export type RemoveCredentialBindingInput = {19export type RemoveCredentialBindingInput = {
20 workspaceId: WorkspaceId;20 workspaceId: WorkspaceId;
21 credentialBindingId: CredentialBindingId;21 credentialBindingId: SourceAuthBindingId;
22};22};
23 23
24export type ControlPlaneCredentialsServiceShape = {24export type ControlPlaneCredentialsServiceShape = {
packages/schema/src/ids.ts+0−8
@@ -6,11 +6,6 @@ export const ProfileIdSchema = Schema.String.pipe(Schema.brand("ProfileId")); · 5 unmodified lines
6export const WorkspaceIdSchema = Schema.String.pipe(Schema.brand("WorkspaceId"));6export const WorkspaceIdSchema = Schema.String.pipe(Schema.brand("WorkspaceId"));
7export const SourceIdSchema = Schema.String.pipe(Schema.brand("SourceId"));7export const SourceIdSchema = Schema.String.pipe(Schema.brand("SourceId"));
8export const ToolArtifactIdSchema = Schema.String.pipe(Schema.brand("ToolArtifactId"));8export const ToolArtifactIdSchema = Schema.String.pipe(Schema.brand("ToolArtifactId"));
9export const CredentialBindingIdSchema = Schema.String.pipe(
10 Schema.brand("CredentialBindingId"),
11);
12export const CredentialIdSchema = Schema.String.pipe(Schema.brand("CredentialId"));
13export const OAuthTokenIdSchema = Schema.String.pipe(Schema.brand("OAuthTokenId"));
14export const AuthConnectionIdSchema = Schema.String.pipe(9export const AuthConnectionIdSchema = Schema.String.pipe(
15 Schema.brand("AuthConnectionId"),10 Schema.brand("AuthConnectionId"),
16);11);
@@ -42,9 +37,6 @@ export type ProfileId = typeof ProfileIdSchema.Type; · 25 unmodified lines
42export type WorkspaceId = typeof WorkspaceIdSchema.Type;37export type WorkspaceId = typeof WorkspaceIdSchema.Type;
43export type SourceId = typeof SourceIdSchema.Type;38export type SourceId = typeof SourceIdSchema.Type;
44export type ToolArtifactId = typeof ToolArtifactIdSchema.Type;39export type ToolArtifactId = typeof ToolArtifactIdSchema.Type;
45export type CredentialBindingId = typeof CredentialBindingIdSchema.Type;
46export type CredentialId = typeof CredentialIdSchema.Type;
47export type OAuthTokenId = typeof OAuthTokenIdSchema.Type;
48export type AuthConnectionId = typeof AuthConnectionIdSchema.Type;40export type AuthConnectionId = typeof AuthConnectionIdSchema.Type;
49export type SourceAuthBindingId = typeof SourceAuthBindingIdSchema.Type;41export type SourceAuthBindingId = typeof SourceAuthBindingIdSchema.Type;
50export type AuthMaterialId = typeof AuthMaterialIdSchema.Type;42export type AuthMaterialId = typeof AuthMaterialIdSchema.Type;
packages/schema/src/index.ts+0−1
@@ -6,7 +6,6 @@ export * from "./models/profile"; · 5 unmodified lines
6export * from "./models/workspace";6export * from "./models/workspace";
7export * from "./models/source";7export * from "./models/source";
8export * from "./models/tool-artifact";8export * from "./models/tool-artifact";
9export * from "./models/oauth-token";
10export * from "./models/source-credential-binding";9export * from "./models/source-credential-binding";
11export * from "./models/auth-connection";10export * from "./models/auth-connection";
12export * from "./models/source-auth-binding";11export * from "./models/source-auth-binding";
packages/schema/src/models/oauth-token.ts+0−27
@@ -1,27 +0,0 @@
1import { Schema } from "effect";
2
3import { TimestampMsSchema } from "../common";
4import {
5 AccountIdSchema,
6 OAuthTokenIdSchema,
7 OrganizationIdSchema,
8 SourceIdSchema,
9 WorkspaceIdSchema,
10} from "../ids";
11
12export const OAuthTokenSchema = Schema.Struct({
13 id: OAuthTokenIdSchema,
14 workspaceId: WorkspaceIdSchema,
15 organizationId: Schema.NullOr(OrganizationIdSchema),
16 accountId: Schema.NullOr(AccountIdSchema),
17 sourceId: SourceIdSchema,
18 issuer: Schema.String,
19 accessTokenRef: Schema.String,
20 refreshTokenRef: Schema.NullOr(Schema.String),
21 scope: Schema.Array(Schema.String),
22 expiresAt: Schema.NullOr(TimestampMsSchema),
23 createdAt: TimestampMsSchema,
24 updatedAt: TimestampMsSchema,
25});
26
27export type OAuthToken = typeof OAuthTokenSchema.Type;
packages/schema/src/models/source-credential-binding.ts+4−4
@@ -8,15 +8,15 @@ import { · 7 unmodified lines
8} from "../enums";8} from "../enums";
9import {9import {
10 AccountIdSchema,10 AccountIdSchema,
11 CredentialBindingIdSchema,11 AuthConnectionIdSchema,
12 CredentialIdSchema,
13 OrganizationIdSchema,12 OrganizationIdSchema,
13 SourceAuthBindingIdSchema,
14 WorkspaceIdSchema,14 WorkspaceIdSchema,
15} from "../ids";15} from "../ids";
16 16
17export const SourceCredentialBindingSchema = Schema.Struct({17export const SourceCredentialBindingSchema = Schema.Struct({
18 id: CredentialBindingIdSchema,18 id: SourceAuthBindingIdSchema,
19 credentialId: CredentialIdSchema,19 credentialId: AuthConnectionIdSchema,
20 organizationId: OrganizationIdSchema,20 organizationId: OrganizationIdSchema,
21 workspaceId: Schema.NullOr(WorkspaceIdSchema),21 workspaceId: Schema.NullOr(WorkspaceIdSchema),
22 accountId: Schema.NullOr(AccountIdSchema),22 accountId: Schema.NullOr(AccountIdSchema),