GitHub's official OpenAPI description declares no securitySchemes, so the add flow offered OAuth (from the preset template) and nothing else, while a PAT bearer header is how most calls actually authenticate. The registry's declared placement now seeds an API key method alongside detected OAuth; a spec-declared key method still wins over the registry's version of the same fact. Preset-to-catalog matching moves from rendered titles to a product key (normalized name plus kind), so 'GitHub REST' and the registry's 'GitHub API' count as one product — titles and domains both proved unreliable joins. MCP surfaces carry their auth facts too.
Showing the changes to packages/plugins/openapi/src (1 of 2 files). Show all
Unified · Split
| @@ -25,6 +25,7 @@ import { · 24 unmodified lines | |||
| 25 | type AuthMethodRow, | 25 | type AuthMethodRow, |
| 26 | type AuthMethodSeed, | 26 | type AuthMethodSeed, |
| 27 | } from "@executor-js/react/components/auth-method-list-editor"; | 27 | } from "@executor-js/react/components/auth-method-list-editor"; |
| 28 | import { placementFromHeaderPattern } from "@executor-js/react/lib/auth-placements"; | ||
| 28 | import { CardStack, CardStackContent } from "@executor-js/react/components/card-stack"; | 29 | import { CardStack, CardStackContent } from "@executor-js/react/components/card-stack"; |
| 29 | import { FieldLabel } from "@executor-js/react/components/field"; | 30 | import { FieldLabel } from "@executor-js/react/components/field"; |
| 30 | import { FloatActions } from "@executor-js/react/components/float-actions"; | 31 | import { FloatActions } from "@executor-js/react/components/float-actions"; |
| @@ -170,6 +171,8 @@ export default function AddOpenApiIntegration(props: { · 139 unmodified lines | |||
| 170 | initialUrl?: string; | 171 | initialUrl?: string; |
| 171 | initialPreset?: string; | 172 | initialPreset?: string; |
| 172 | initialNamespace?: string; | 173 | initialNamespace?: string; |
| 174 | initialAuthHeader?: string; | ||
| 175 | initialAuthNote?: string; | ||
| 173 | }) { | 176 | }) { |
| 174 | const integrationPlugins = useIntegrationPlugins(); | 177 | const integrationPlugins = useIntegrationPlugins(); |
| 175 | const openApiPlugin = integrationPlugins.find((plugin) => plugin.key === "openapi"); | 178 | const openApiPlugin = integrationPlugins.find((plugin) => plugin.key === "openapi"); |
| @@ -297,14 +300,26 @@ export default function AddOpenApiIntegration(props: { · 121 unmodified lines | |||
| 297 | ...(preview?.headerPresets ?? []).map((preset) => preset.label), | 300 | ...(preview?.headerPresets ?? []).map((preset) => preset.label), |
| 298 | ...(preview?.oauth2Presets ?? []).map((preset) => preset.label), | 301 | ...(preview?.oauth2Presets ?? []).map((preset) => preset.label), |
| 299 | ]; | 302 | ]; |
| 300 | return authenticationTemplate.map( | 303 | const detected = authenticationTemplate.map( |
| 301 | (template: Authentication, index: number): AuthMethodSeed => ({ | 304 | (template: Authentication, index: number): AuthMethodSeed => ({ |
| 302 | value: editorValueFromAuthentication(template), | 305 | value: editorValueFromAuthentication(template), |
| 303 | slug: String(template.slug), | 306 | slug: String(template.slug), |
| 304 | ...(labels[index] !== undefined ? { label: labels[index] } : {}), | 307 | ...(labels[index] !== undefined ? { label: labels[index] } : {}), |
| 305 | }), | 308 | }), |
| 306 | ); | 309 | ); |
| 307 | }, [preview, authenticationTemplate]); | 310 | if (preview === null) return detected; |
| 311 | // The registry's declared credential placement fills what the document | ||
| 312 | // leaves out. GitHub's official description famously declares no | ||
| 313 | // securitySchemes at all, and even with the OAuth preset template a PAT | ||
| 314 | // bearer header is how most calls actually authenticate — so the key | ||
| 315 | // method is offered alongside OAuth. A spec-declared key method wins over | ||
| 316 | // the registry's version of the same fact. | ||
| 317 | const placement = props.initialAuthHeader | ||
| 318 | ? placementFromHeaderPattern(props.initialAuthHeader) | ||
| 319 | : null; | ||
| 320 | if (!placement || detected.some((seed) => seed.value.kind === "apikey")) return detected; | ||
| 321 | return [...detected, { value: { kind: "apikey", placements: [placement] } }]; | ||
| 322 | }, [preview, authenticationTemplate, props.initialAuthHeader]); | ||
| 308 | const authMethodList = useAuthMethodList(authMethodSeeds); | 323 | const authMethodList = useAuthMethodList(authMethodSeeds); |
| 309 | 324 | ||
| 310 | // The methods to register, mapped back to stored `Authentication[]`. Drops | 325 | // The methods to register, mapped back to stored `Authentication[]`. Drops |
| @@ -601,6 +616,10 @@ export default function AddOpenApiIntegration(props: { · 290 unmodified lines | |||
| 601 | /> | 616 | /> |
| 602 | )} | 617 | )} |
| 603 | 618 | ||
| 619 | {preview && props.initialAuthNote ? ( | ||
| 620 | <p className="text-xs leading-relaxed text-muted-foreground">{props.initialAuthNote}</p> | ||
| 621 | ) : null} | ||
| 622 | |||
| 604 | {preview ? ( | 623 | {preview ? ( |
| 605 | <AddOpenApiHealthCheckSection | 624 | <AddOpenApiHealthCheckSection |
| 606 | presetHealthCheck={activePreset?.healthCheck} | 625 | presetHealthCheck={activePreset?.healthCheck} |