diff --git a/changelog.d/fixes/10851-openapi-spec-auth-contract.md b/changelog.d/fixes/10851-openapi-spec-auth-contract.md new file mode 100644 index 0000000000..e2b038592c --- /dev/null +++ b/changelog.d/fixes/10851-openapi-spec-auth-contract.md @@ -0,0 +1 @@ +- Document the conditional management authentication and 401/403 responses for `GET /api/openapi/spec`. diff --git a/docs/openapi.yaml b/docs/openapi.yaml index 73941f37ea..540f2abd52 100644 --- a/docs/openapi.yaml +++ b/docs/openapi.yaml @@ -6866,7 +6866,11 @@ paths: Returns a structured JSON catalog parsed from this `openapi.yaml`, including info, servers, tags, schemas, and a flat list of endpoints (method, path, tags, summary, security, parameters, responses). - Used by the in-app API explorer. + Used by the in-app API explorer. When `requireLogin` is enabled, this + management endpoint requires an authenticated dashboard session; + otherwise it is available without authentication. + security: + - ManagementSessionAuth: [] responses: "200": description: Parsed OpenAPI catalog @@ -6920,6 +6924,10 @@ paths: type: string "404": description: openapi.yaml file not found on disk + "401": + $ref: "#/components/responses/ManagementAuthenticationRequired" + "403": + $ref: "#/components/responses/ManagementInvalidToken" "500": description: Failed to parse OpenAPI spec diff --git a/skills/cli-mcp/SKILL.md b/skills/cli-mcp/SKILL.md index 2d5ce4a259..8068fa5dde 100644 --- a/skills/cli-mcp/SKILL.md +++ b/skills/cli-mcp/SKILL.md @@ -75,76 +75,3 @@ omniroute mcp call [argsJson] ```bash omniroute mcp scopes ``` - -### `mcp tools` - -**Example:** - -```bash -omniroute mcp tools -``` - -### `mcp list` - -**Flags:** - -- `--scope ` - -**Example:** - -```bash -omniroute mcp list -``` - -### `mcp info ` - -**Example:** - -```bash -omniroute mcp info -``` - -### `mcp schema ` - -**Flags:** - -- `--io ` - -**Example:** - -```bash -omniroute mcp schema -``` - -### `mcp audit` - -**Example:** - -```bash -omniroute mcp audit -``` - -### `mcp tail` - -**Flags:** - -- `--follow` -- `--limit ` - -**Example:** - -```bash -omniroute mcp tail -``` - -### `mcp stats` - -**Flags:** - -- `--period

` - -**Example:** - -```bash -omniroute mcp stats -``` diff --git a/tests/unit/openapi-security-tiers.test.ts b/tests/unit/openapi-security-tiers.test.ts index 35c5d31520..9cff84f00c 100644 --- a/tests/unit/openapi-security-tiers.test.ts +++ b/tests/unit/openapi-security-tiers.test.ts @@ -34,6 +34,21 @@ test("every x-loopback-only path matches a LOCAL_ONLY prefix in routeGuard.ts", } }); +test("GET /api/openapi/spec documents its conditional management auth contract", () => { + const operation = paths["/api/openapi/spec"]?.get; + + assert.deepEqual(operation?.security, [{ ManagementSessionAuth: [] }]); + assert.match(operation?.description ?? "", /When `requireLogin` is enabled/); + assert.equal( + operation?.responses?.["401"]?.$ref, + "#/components/responses/ManagementAuthenticationRequired" + ); + assert.equal( + operation?.responses?.["403"]?.$ref, + "#/components/responses/ManagementInvalidToken" + ); +}); + test("every x-always-protected path matches ALWAYS_PROTECTED_API_PATHS in routeGuard.ts", () => { for (const [pathStr, methods] of Object.entries(paths)) { if (!methods || typeof methods !== "object") continue;