Skip to content

fix(web): check untrusted JSON and hub values against their schemas - #169

Merged
TheGreatAxios merged 4 commits into
cl-12110-remove-swallowed-errors-unchecked-casts-and-iifes-from-thefrom
cl-12110-check-untrusted-json-and-casts-in-the-interface
Nov 4, 2026
Merged

TheGreatAxios merged 4 commits into
cl-12110-remove-swallowed-errors-unchecked-casts-and-iifes-from-thefrom
cl-12110-check-untrusted-json-and-casts-in-the-interface

Conversation

@TheGreatAxios

@TheGreatAxios TheGreatAxios commented Nov 4, 2026 •

Copy link
Copy Markdown
Contributor

Part of CL-12110: the untrusted-JSON and unchecked-cast items from the Findings document, except the approval-package deck (#168). Stacked on #167.

Changes

  • New readJson(text, schema) in apps/web/src/json.ts: catches only SyntaxError, validates with arktype, and returns null for either failure.
  • Run-stream run frames are validated against a local schema of the fields the interface reads; a frame of the wrong shape is logged (without its contents) and dropped instead of reaching the transcript. A tool frame's string partial is accepted, and readers narrow it through partialOf.
  • Design bundles are read with DesignBundle from @corbits-builder/schemas, so a bundle whose files aren't strings shows the unreadable state.
  • Specialist mail: a valid JSON null or scalar no longer throws on .result; it reads as text.
  • Seen document versions in browser storage are validated as a map of numbers.
  • The sign-in response body is read with small arktype shapes (message, error.message, user) instead of a cast. Only better-auth's JSON null means signed out; a session reply of any other wrong shape is now an error instead of quietly showing the sign-in screen.
  • load-room.ts: the try/catch around parsing the settled keys is removed; every key is a roomDocumentKey, which always parses.
  • as unknown as number timers in run-stream.ts and room-reload.ts use window.setTimeout.
  • Design concepts on an ask are validated with DesignConcept.array(), so the length limits apply.
  • Subscription logins: ModelLoginPlugin is now an arktype schema in packages/schemas (the client type re-exports it), and an unknown plugin toasts a readable error instead of being sent to the hub.
  • Custom providers: Edit is disabled unless the provider's plugin is a CustomApi, instead of casting it. The hub already asserts this when it lists custom providers.
  • Install packages and document kinds on an ask are read with type("string[]") instead of casts.

packages/schemas changes on purpose although the issue lists only apps/web and packages/client: shared client/hub shapes belong there. Run-stream events and the auth body are read only by the interface, so their schemas stay in apps/web. The hub keeps its own list of login plugins in apps/hub, which this issue doesn't touch; making the hub import ModelLoginPlugin is a follow-up.

Verification

  • New tests: wrong-shape, null and non-JSON input read as null; a run frame of the wrong shape never reaches the handler; concepts over the label limit aren't offered; JSON null mail reads as text; only a JSON null session means signed out.
  • bun run lint, format:check, typecheck, test, pins:verify and vendor:verify pass.

@linear-code

linear-code Bot commented Nov 4, 2026

Copy link
Copy Markdown

CL-12110

@corbits-triage corbits-triage Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Triage requests changes:

  • Invented fallbacks: added code matches a code pattern
    • apps/web/src/api/run-stream.ts:58 empty-fallback: Invented fallback (an empty string, list, object or zero); handle the missing value instead.

@TheGreatAxios
TheGreatAxios force-pushed the cl-12110-check-untrusted-json-and-casts-in-the-interface branch from b5dede4 to 80edb8b Compare November 4, 2026 21:50
@corbits-triage

corbits-triage Bot commented Nov 4, 2026 •

Copy link
Copy Markdown

Triage: In progress

Triage is waiting for CI to finish before it decides. This comment shows the verdict once it has.

@corbits-triage
corbits-triage Bot dismissed their stale review November 4, 2026 22:08

Nothing triage asked to change still fails, so this request no longer stands.

@corbits-triage corbits-triage Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

No defects reported.

@TheGreatAxios
TheGreatAxios force-pushed the cl-12110-check-untrusted-json-and-casts-in-the-interface branch from 40483d7 to 0168c8e Compare November 4, 2026 22:30
@TheGreatAxios
TheGreatAxios merged commit 69a62c5 into cl-12110-remove-swallowed-errors-unchecked-casts-and-iifes-from-the Nov 4, 2026
2 checks passed

@corbits-triage corbits-triage Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

No defects reported.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant