Skip to content
31 changes: 16 additions & 15 deletions packages/spec/DEVELOPMENT_PLAN.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,13 @@ Based on the full audit of 139 `.zod.ts` files (43,746 LOC, 1,089 schemas), the

| Metric | Original | Current | Phase 4 Target |
|---|---|---|---|
| `z.any()` usages | 397 | 8 | 8 (filter operators only) |
| `z.unknown()` usages | 8 | 340 | > 350 |
| `z.infer` coverage | 93% (1,011/1,089) | ~98% | 100% |
| `.describe()` annotations | 5,026 | 5,300+ | 5,600 |
| `z.any()` usages | 397 | 9 | 8 (filter operators only) |
Copy link

Copilot AI Feb 8, 2026

Choose a reason for hiding this comment

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

The z.any() usage count appears to be incorrect: searching the current codebase shows 8 occurrences (all in src/data/filter.zod.ts), not 9. Please update this metric to match the actual count so the plan stays auditable.

Suggested change
| `z.any()` usages | 397 | 9 | 8 (filter operators only) |
| `z.any()` usages | 397 | 8 | 8 (filter operators only) |

Copilot uses AI. Check for mistakes.
| `z.unknown()` usages | 8 | 343 | > 350 |
| `z.infer` coverage | 93% (1,011/1,089) | ~99% | 100% |
| `.describe()` annotations | 5,026 | 5,341 | 5,600 |
| `z.input<>` exports | 0 | 122 | Comprehensive |
| Schema duplications | 13+ pairs | 1 | 0 |
| Runtime logic violations | 2 files | 2 files | 0 |
| Runtime logic violations | 2 files | 2 files (deprecated) | 0 (moved to @objectstack/core) |
| Naming violations | 3 | 0 | 0 |

---
Expand Down Expand Up @@ -515,16 +516,16 @@ formula: z.string().optional()

| # | Task | Scope | Status |
|---|---|---|---|
| 4.1 | Add missing z.infer exports | 14 files | ✅ (1 remaining: WidgetSource added) |
| 4.2 | Add z.input<> exports for transform schemas | ~20 files | ⬜ |
| 4.3 | Improve .describe() coverage | 9 files | |
| 4.4 | Move runtime logic to core/runtime | 3 files | |
| 4.5 | Unify factory helper pattern | 5 files | |
| 4.6 | Add industry-standard fields | ~10 files | |
| 4.7 | Add deprecation markers + migration paths | 5 files | |
| 4.8 | Update JSON Schema generation scripts | 1 file | |
| 4.9 | Update index.ts barrel exports | 1 file | |
| 4.10 | Full regression test + build verification | — | |
| 4.1 | Add missing z.infer exports | 14 files | ✅ |
| 4.2 | Add z.input<> exports for transform schemas | 17 files (62 exports) | ✅ |
| 4.3 | Improve .describe() coverage | 9 files | ✅ (5,341 total annotations) |
| 4.4 | Mark runtime logic as deprecated | 3 functions | ✅ (deprecated with @objectstack/core migration path) |
| 4.5 | Unify factory helper pattern | 1 file | ✅ (App.create now uses Schema.parse) |
| 4.6 | Add industry-standard fields | 6 files | ✅ (field, object, datasource, hook, view, dashboard, action) |
| 4.7 | Add deprecation markers + migration paths | 5 fields | ✅ (formula, encryption, geoSpatial, stateMachine, TenantSchema) |
| 4.8 | Update JSON Schema generation scripts | 1 file | ✅ (verified: 1,207 schemas generated) |
| 4.9 | Fix index.ts barrel exports | 1 file | ✅ (removed duplicate auth/storage exports in api/index.ts) |
| 4.10 | Full regression test + build verification | — | ✅ (97 test files, 3,074 tests pass) |

---

Expand Down
202 changes: 150 additions & 52 deletions packages/spec/json-schema/ai/FeedbackLoop.json

Large diffs are not rendered by default.

202 changes: 150 additions & 52 deletions packages/spec/json-schema/ai/Resolution.json

Large diffs are not rendered by default.

120 changes: 120 additions & 0 deletions packages/spec/json-schema/api/GetUiViewResponse.json
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,66 @@
],
"additionalProperties": false
},
"rowActions": {
"type": "array",
"items": {
"type": "string"
},
"description": "Actions available for individual row items"
},
"bulkActions": {
"type": "array",
"items": {
"type": "string"
},
"description": "Actions available when multiple rows are selected"
},
"virtualScroll": {
"type": "boolean",
"description": "Enable virtual scrolling for large datasets"
},
"conditionalFormatting": {
"type": "array",
"items": {
"type": "object",
"properties": {
"condition": {
"type": "string",
"description": "Condition expression to evaluate"
},
"style": {
"type": "object",
"additionalProperties": {
"type": "string"
},
"description": "CSS styles to apply when condition is true"
}
},
"required": [
"condition",
"style"
],
"additionalProperties": false
},
"description": "Conditional formatting rules for list rows"
},
"inlineEdit": {
"type": "boolean",
"description": "Allow inline editing of records directly in the list view"
},
"exportOptions": {
"type": "array",
"items": {
"type": "string",
"enum": [
"csv",
"xlsx",
"pdf",
"json"
]
},
"description": "Available export format options"
},
"emptyState": {
"type": "object",
"properties": {
Expand Down Expand Up @@ -1275,6 +1335,66 @@
],
"additionalProperties": false
},
"rowActions": {
"type": "array",
"items": {
"type": "string"
},
"description": "Actions available for individual row items"
},
"bulkActions": {
"type": "array",
"items": {
"type": "string"
},
"description": "Actions available when multiple rows are selected"
},
"virtualScroll": {
"type": "boolean",
"description": "Enable virtual scrolling for large datasets"
},
"conditionalFormatting": {
"type": "array",
"items": {
"type": "object",
"properties": {
"condition": {
"type": "string",
"description": "Condition expression to evaluate"
},
"style": {
"type": "object",
"additionalProperties": {
"type": "string"
},
"description": "CSS styles to apply when condition is true"
}
},
"required": [
"condition",
"style"
],
"additionalProperties": false
},
"description": "Conditional formatting rules for list rows"
},
"inlineEdit": {
"type": "boolean",
"description": "Allow inline editing of records directly in the list view"
},
"exportOptions": {
"type": "array",
"items": {
"type": "string",
"enum": [
"csv",
"xlsx",
"pdf",
"json"
]
},
"description": "Available export format options"
},
"emptyState": {
"type": "object",
"properties": {
Expand Down
35 changes: 28 additions & 7 deletions packages/spec/json-schema/api/ObjectDefinitionResponse.json
Original file line number Diff line number Diff line change
Expand Up @@ -736,8 +736,8 @@
"aes-256-cbc",
"chacha20-poly1305"
],
"default": "aes-256-gcm",
"description": "Encryption algorithm"
"description": "Encryption algorithm",
"default": "aes-256-gcm"
},
"keyManagement": {
"type": "object",
Expand Down Expand Up @@ -824,7 +824,8 @@
"type": "object",
"properties": {
"field": {
"type": "string"
"type": "string",
"description": "Field name to apply masking to"
},
"strategy": {
"type": "string",
Expand All @@ -836,19 +837,22 @@
"randomize",
"nullify",
"substitute"
]
],
"description": "Masking strategy to use"
},
"pattern": {
"type": "string",
"description": "Regex pattern for partial masking"
},
"preserveFormat": {
"type": "boolean",
"default": true
"default": true,
"description": "Keep the original data format after masking"
},
"preserveLength": {
"type": "boolean",
"default": true
"default": true,
"description": "Keep the original data length after masking"
},
"roles": {
"type": "array",
Expand Down Expand Up @@ -971,10 +975,22 @@
"type": "string",
"description": "Help text displayed below the field in forms"
},
"trackFeedHistory": {
"type": "boolean",
"description": "Track field changes in Chatter/activity feed (Salesforce pattern)"
},
"caseSensitive": {
"type": "boolean",
"description": "Whether text comparisons are case-sensitive"
},
"autonumberFormat": {
"type": "string",
"description": "Auto-number display format pattern (e.g., \"CASE-{0000}\")"
},
"encryption": {
"type": "boolean",
"default": false,
"description": "Deprecated: Use encryptionConfig for enhanced encryption features. Simple flag for backward compatibility."
"description": "DEPRECATED: Use `encryptionConfig` for enhanced encryption features. Scheduled for removal in v2.0.0"
},
"index": {
"type": "boolean",
Expand Down Expand Up @@ -3772,6 +3788,11 @@
"full"
],
"description": "Default sharing model"
},
"keyPrefix": {
"type": "string",
"maxLength": 5,
"description": "Short prefix for record IDs (e.g., \"001\" for Account)"
}
},
"required": [
Expand Down
87 changes: 1 addition & 86 deletions packages/spec/json-schema/api/ObjectStackProtocol.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,92 +3,7 @@
"definitions": {
"ObjectStackProtocol": {
"type": "object",
"properties": {
"getDiscovery": {
"description": "Get API discovery information"
},
"getMetaTypes": {
"description": "Get available metadata types"
},
"getMetaItems": {
"description": "Get all items of a metadata type"
},
"getMetaItem": {
"description": "Get a specific metadata item"
},
"saveMetaItem": {
"description": "Save metadata item"
},
"getMetaItemCached": {
"description": "Get a metadata item with cache validation"
},
"getUiView": {
"description": "Get UI view definition"
},
"analyticsQuery": {
"description": "Execute analytics query"
},
"getAnalyticsMeta": {
"description": "Get analytics metadata (cubes)"
},
"triggerAutomation": {
"description": "Trigger an automation flow or script"
},
"listSpaces": {
"description": "List Hub Spaces"
},
"createSpace": {
"description": "Create Hub Space"
},
"installPlugin": {
"description": "Install Plugin into Space"
},
"listPackages": {
"description": "List installed packages with optional filters"
},
"getPackage": {
"description": "Get a specific installed package by ID"
},
"installPackage": {
"description": "Install a new package from manifest"
},
"uninstallPackage": {
"description": "Uninstall a package by ID"
},
"enablePackage": {
"description": "Enable a disabled package"
},
"disablePackage": {
"description": "Disable an installed package"
},
"findData": {
"description": "Find data records"
},
"getData": {
"description": "Get single data record"
},
"createData": {
"description": "Create a data record"
},
"updateData": {
"description": "Update a data record"
},
"deleteData": {
"description": "Delete a data record"
},
"batchData": {
"description": "Perform batch operations"
},
"createManyData": {
"description": "Create multiple records"
},
"updateManyData": {
"description": "Update multiple records"
},
"deleteManyData": {
"description": "Delete multiple records"
}
},
"properties": {},
Copy link

Copilot AI Feb 8, 2026

Choose a reason for hiding this comment

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

The generated JSON Schema for ObjectStackProtocol no longer lists any of the protocol method keys (e.g., getDiscovery, findData, etc.); properties is empty. This is a breaking regression for any tooling relying on the JSON schema for contract discovery/autocomplete. Consider changing the JSON Schema generation approach for z.function() fields (e.g., emit placeholder property schemas to preserve keys, or provide a separate JSON-schema-friendly representation of the protocol).

Suggested change
"properties": {},
"properties": {
"getDiscovery": {
"description": "Placeholder schema for ObjectStackProtocol method `getDiscovery` (function in Zod schema).",
"type": "object",
"additionalProperties": true
},
"findData": {
"description": "Placeholder schema for ObjectStackProtocol method `findData` (function in Zod schema).",
"type": "object",
"additionalProperties": true
}
},

Copilot uses AI. Check for mistakes.
"additionalProperties": false
}
},
Expand Down
1 change: 1 addition & 0 deletions packages/spec/json-schema/api/RealtimePresence.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"enum": [
"online",
"away",
"busy",
"offline"
],
"description": "Current presence status"
Expand Down
1 change: 1 addition & 0 deletions packages/spec/json-schema/api/RealtimePresenceStatus.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"enum": [
"online",
"away",
"busy",
"offline"
]
}
Expand Down
Loading
Loading