Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions openapi/agentstorage.v1.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ paths:
properties:
permanent:
type: boolean
const: true
enum: [true]
required: [permanent]
additionalProperties: false
- type: object
Expand All @@ -208,7 +208,9 @@ paths:
minimum: 1
maximum: 604800
permanent:
enum: [false, null]
type: boolean
enum: [false]
nullable: true
Comment on lines +211 to +213
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

OpenAPI 3.0.x nullable true enum specification null validation

💡 Result:

In OpenAPI 3.0.x, nullable: true means null is added to the allowed type, but all other schema constraints still apply—and those constraints can still reject null (the spec explicitly calls this out). So if you also have an enum, validation will only pass for values in that enum; therefore null must be explicitly present in the enum list for null to validate. [1][2]

Example (OAS 3.0.x):

type: string
nullable: true
enum:
  - asc
  - desc
  - null   # must be actual null, not "null"

Many linters/validators enforce this behavior (nullable + enum ⇒ enum must contain null). [2][3]

Sources: OpenAPI Spec v3.0.3 on nullable semantics and constraints [1]; Swagger docs on “Nullable enums” [2]; vacuum linter rule nullable-enum-contains-null [3].


nullable: true with enum: [false] will reject null values.

In OpenAPI 3.0.x, when both nullable: true and enum are specified, null must be explicitly included in the enum array for null validation to pass. The current definition will reject null despite the nullable constraint, causing validator and client-generator mismatches.

Add null to the enum:

Suggested fix
                      type: boolean
-                      enum: [false]
+                      enum: [false, null]
                       nullable: true
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
type: boolean
enum: [false]
nullable: true
type: boolean
enum: [false, null]
nullable: true
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@openapi/agentstorage.v1.yaml` around lines 211 - 213, The OpenAPI schema
currently has "type: boolean", "enum: [false]" and "nullable: true" which will
still reject null; update the enum to explicitly include null (i.e., change the
enum for the schema that contains enum: [false] and nullable: true to include
null as an allowed value) so validators and client generators accept nulls
alongside false.

required: [expiresInSeconds]
additionalProperties: false
responses:
Expand Down
12 changes: 11 additions & 1 deletion packages/cli/src/commands/setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ class HttpError extends Error {
}
}

class InvalidPayloadError extends Error {
constructor(message: string) {
super(message);
}
}

const FETCH_TIMEOUT_MS = 30_000;

function isTimeoutError(e: unknown): e is Error {
Expand Down Expand Up @@ -114,7 +120,9 @@ export async function runSetup(argv: string[]): Promise<void> {
}
const payload = await res.json();
if (!isCreateWorkspacePayload(payload)) {
throw new Error("Invalid workspace creation response");
throw new InvalidPayloadError(
"POST /v1/workspaces returned an invalid payload.",
);
Comment on lines +123 to +125
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Non-JSON success payloads are still reported as “network error.”

InvalidPayloadError is only thrown after a successful res.json() parse. If Line 121 throws (malformed JSON), execution falls through to the generic branch and misclassifies the failure.

💡 Suggested fix
-    const payload = await res.json();
+    let payload: unknown;
+    try {
+      payload = await res.json();
+    } catch {
+      throw new InvalidPayloadError(
+        "POST /v1/workspaces returned a non-JSON payload.",
+      );
+    }
     if (!isCreateWorkspacePayload(payload)) {
       throw new InvalidPayloadError(
         "POST /v1/workspaces returned an invalid payload.",
       );
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/cli/src/commands/setup.ts` around lines 123 - 125, The current code
only throws InvalidPayloadError after a successful res.json() call, so
malformed-JSON responses fall through to the generic network error path; wrap
the res.json() call in a try/catch (or use await res.text() then attempt
JSON.parse) when handling the POST /v1/workspaces response and, on parse
failure, throw InvalidPayloadError including the raw response/text for
diagnostics; update the branch that currently throws InvalidPayloadError (the
one referencing InvalidPayloadError and res.json()) to ensure JSON parse errors
are caught and re-thrown as InvalidPayloadError so they are not misclassified as
generic network errors.

}
created = payload;
console.log(c.green + "✓" + c.reset);
Expand All @@ -128,6 +136,8 @@ export async function runSetup(argv: string[]): Promise<void> {
console.error(
fail(`POST /v1/workspaces timed out after ${FETCH_TIMEOUT_MS}ms.`),
);
} else if (e instanceof InvalidPayloadError) {
console.error(fail(e.message));
} else {
console.error(
fail(
Expand Down