Skip to content

Conversation

@acfranzen
Copy link
Owner

@acfranzen acfranzen commented Feb 5, 2026

Summary

  • Three-layer enforcement to prevent AI agents from "forgetting" required fields when generating widgets
  • JSON Schema for structured output modes (Anthropic tool_use, OpenAI response_format)
  • Stricter TypeScript types making data_schema and credentials required
  • Enhanced validation in validateDashboardFormat() and validateWidgetPackage()

Changes

Layer 1: Stricter TypeScript Types

  • CustomWidget.data_schema is now required (non-nullable)
  • DashboardExportFormat.widgets[].data_schema and credentials are now required
  • WidgetPackage.data_schema is now required

Layer 2: JSON Schema for Structured Output (NEW)

  • Added docs/schemas/widget-schema.json
  • Comprehensive schema that AI APIs can use with structured output modes
  • Enforces: name, slug, source_code, default_size, min_size, fetch, data_schema, credentials
  • Conditional requirements (fetch.instructions/schedule required when type is agent_refresh)
  • data_schema.required must include "fetchedAt"

Layer 3: Enhanced Validation

  • validateDashboardFormat() now validates:
    • data_schema must have type="object", properties, and required (including "fetchedAt")
    • fetch.type must be valid enum
    • fetch.instructions and fetch.schedule required for agent_refresh
    • default_size and min_size must have positive w/h integers
    • credentials must be array (can be empty [])
    • Slug format validation (lowercase kebab-case)
  • validateWidgetPackage() now validates data_schema requirements

Layer 4: Documentation

  • Added "AI Structured Output Generation (REQUIRED)" section to SKILL.md
  • Required fields checklist with table format
  • Minimal valid widget example
  • Updated Rules & Gotchas

Test plan

  • npx tsc --noEmit passes
  • npm run lint passes (no new errors)
  • JSON Schema file is valid JSON
  • Test import/export with widget that has data_schema
  • Test import rejection when data_schema is missing

🤖 Generated with Claude Code


Note

Medium Risk
Changes tighten contracts around import/export and widget packaging, so existing dashboards/packages missing data_schema/credentials may now fail validation or import. Mostly validation/type enforcement, but it affects core data interchange paths.

Overview
Widget definitions are now enforced as fully-specified objects by making data_schema and credentials required (no longer optional/nullable) across dashboard export format, widget packages, and the CustomWidget DB type.

Adds a new docs/schemas/widget-schema.json JSON Schema intended for AI structured output, with conditional requirements for agent_refresh (e.g., fetch.instructions/fetch.schedule) and a hard requirement that data_schema.required contains fetchedAt; SKILL.md is updated to require using this schema and to document the required-field checklist.

Tightens runtime validation: validateDashboardFormat() now validates slug format, widget sizes, fetch config, data_schema structure, and credentials shape; export/import routes are adjusted to always include/persist required fields, and DB row mapping provides a fallback minimal data_schema when missing.

Written by Cursor Bugbot for commit 16efca2. This will update automatically on new commits. Configure here.

Three-layer enforcement for widget definitions:

1. **Stricter TypeScript Types**
   - Made `data_schema` required (non-nullable) in CustomWidget interface
   - Made `credentials` and `data_schema` required in DashboardExportFormat
   - Made `data_schema` required in WidgetPackage interface

2. **JSON Schema for Structured Output** (NEW: docs/schemas/widget-schema.json)
   - Comprehensive schema for AI structured output modes (Anthropic tool_use, OpenAI response_format)
   - Enforces all required fields at generation time
   - Conditional requirements (fetch.instructions/schedule required for agent_refresh)
   - data_schema.required must include "fetchedAt"

3. **Enhanced Validation**
   - validateDashboardFormat() now validates: data_schema structure, fetch config,
     size constraints, credentials array, and slug format
   - validateWidgetPackage() now validates data_schema requirements
   - Return type includes warnings array for non-critical issues

Also updated SKILL.md with:
- "AI Structured Output Generation (REQUIRED)" section
- Required fields checklist table
- Minimal valid widget example

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@vercel
Copy link

vercel bot commented Feb 5, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
glance Ready Ready Preview, Comment Feb 5, 2026 4:17pm

Request Review

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 3 potential issues.

Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.

widget.cache || null,
null, // author
widget.data_schema || null
widget.data_schema
Copy link

Choose a reason for hiding this comment

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

Inconsistent data_schema fallback removed in only some import paths

Medium Severity

The || null fallback for widget.data_schema was removed at lines 174 and 208 (for conflict resolution "rename" and "overwrite" cases), but line 241 in the non-conflict code path still uses widget.data_schema || null. This creates inconsistent behavior across different import paths—conflicting widgets pass undefined when data_schema is missing, while new widgets pass null.

Additional Locations (1)

Fix in Cursor Fix in Web

}
if (typeof s.h !== "number" || !Number.isInteger(s.h) || s.h < 1) {
errors.push(`Widget ${widgetId}: ${fieldName}.h must be a positive integer`);
}
Copy link

Choose a reason for hiding this comment

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

Size validation missing maximum bounds check

Medium Severity

The validateSize function only validates minimum bounds (s.w < 1 and s.h < 1) but doesn't check maximum bounds. The JSON schema specifies w must be 1-12 and h must be 1-20, and the SKILL.md documentation shows the same ranges. Widgets with excessively large dimensions like { w: 100, h: 100 } would pass runtime validation but violate the documented constraints and could cause layout issues.

Fix in Cursor Fix in Web


const validTypes = ["api_key", "local_software", "oauth", "agent"];
for (let i = 0; i < credentials.length; i++) {
const cred = credentials[i] as Record<string, unknown>;
Copy link

Choose a reason for hiding this comment

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

Missing null check causes crash on malformed credentials

Medium Severity

The validateCredentials function iterates over the credentials array and immediately accesses properties like cred.id without first checking if each element is a non-null object. If the input contains credentials: [null] or credentials: [123], accessing cred.id on a null value will throw a TypeError: Cannot read properties of null, crashing the validation. Other validation functions like validateSize, validateFetch, and validateDataSchema correctly include if (!x || typeof x !== "object") guards, but this function is missing that check.

Fix in Cursor Fix in Web

@acfranzen acfranzen merged commit 3905b0d into main Feb 5, 2026
8 checks passed
@acfranzen acfranzen deleted the feat/strengthen-widget-schema-validation branch February 5, 2026 16:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant