Add ObjectStack Spec v0.7.1 alignment analysis and implementation roadmap#300
Add ObjectStack Spec v0.7.1 alignment analysis and implementation roadmap#300
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
…ion schema types Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
…gine Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
…ent-as-planned
Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
…se-development-again
📦 Bundle Size Report
Size Limits
|
…sion parser Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
|
✅ All checks passed!
|
Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
📦 Bundle Size Report
Size Limits
|
|
✅ All checks passed!
|
There was a problem hiding this comment.
Pull request overview
This PR both completes the core implementation work needed for ObjectStack Spec v0.7.1 alignment (window functions, object-level validation, enhanced actions) and adds extensive documentation and release summaries that capture the alignment analysis and rollout plan towards v0.4.0.
Changes:
- Introduces spec-aligned query/data protocol extensions (window functions, new aggregations, object-level validation types, enhanced UI action schema) and wires them into the core query/validation engines with tests.
- Adds a new object-level validation engine with a safe expression evaluator to replace the previous dynamic
Function-based approach and re-exports it from the core validation module. - Adds a suite of alignment, phase, security, and release documentation (including bilingual spec-alignment docs) and links these from the README for discoverability.
Reviewed changes
Copilot reviewed 20 out of 20 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
packages/types/src/ui-action.ts |
Defines the enhanced ActionSchema, ActionParam, locations, and execution context/result types per ObjectStack Spec v0.7.1, to support location-based actions, parameter collection, and feedback. |
packages/types/src/index.ts |
Re-exports new query AST/window/validation types and the enhanced UI action types under UIActionSchema so downstream packages can consume the updated protocol. |
packages/types/src/data-protocol.ts |
Extends the data protocol with window-function AST/types (WindowNode, WindowConfig, frame types), new aggregation functions and separator, and a full object-level validation type hierarchy (BaseValidation, ScriptValidation, etc.). |
packages/types/src/app.ts |
Adds homePageId and requiredPermissions to AppSchema to support app-level default navigation and permission requirements as defined in the spec. |
packages/core/src/validation/validators/object-validation-engine.ts |
Implements the new object-level validation engine plus a safe, non-dynamic SimpleExpressionEvaluator, and concrete handlers for script, uniqueness, state machine, cross-field, async, conditional, format, and range validations. |
packages/core/src/validation/validators/index.ts |
Aggregates and re-exports the object-level validation engine types, default instance, and convenience validateRecord function. |
packages/core/src/validation/index.ts |
Extends the validation module’s public surface to re-export the new object-level validators alongside the existing validation engine/schema validator. |
packages/core/src/validation/__tests__/object-validation-engine.test.ts |
Adds unit tests covering most object-level validation types (script, uniqueness, state machine, cross-field, format, range, conditional) and engine behaviors (events, active flag, severity). |
packages/core/src/query/query-ast.ts |
Updates QueryASTBuilder to include WindowNode support in SelectNode, build window function nodes from WindowConfig, and use the extended aggregation function set. |
packages/core/src/query/__tests__/window-functions.test.ts |
Adds tests verifying that QueryASTBuilder correctly builds various window functions (ranking, lag/lead, aggregate windows, frame specs) into WindowNodes. |
SECURITY_FIX_SUMMARY.md |
Documents the replacement of dynamic new Function-based expression evaluation with the safe parser, including limitations, test/scan results, and overall security impact. |
RELEASE_SUMMARY_v0.4.0.md |
Provides a comprehensive v0.4.0 release summary: spec-alignment metrics, new features (window functions, validation, actions), test/security status, and planned next steps. |
README.md |
Links the new OBJECTSTACK_SPEC_ALIGNMENT.md (and Chinese version) from the docs section so contributors can easily find the spec-alignment analysis and roadmap. |
PR300_COMPLETION_SUMMARY.md |
Summarizes the work and verification steps associated with PR #300, including the security fix, alignment status, and readiness for production. |
PHASE4_IMPLEMENTATION.md |
Describes the overall completion of the spec alignment project (Phase 4), including metrics, security status, coverage, and remaining optional work. |
PHASE2_IMPLEMENTATION.md |
Documents the Phase 2 implementation details (security fixes, window functions, validation, action schema), including test and CodeQL status and remaining items; one section about the evaluator’s use of Function is now stale relative to the current code. |
PACKAGE_SCAN_SUMMARY.md |
Records the package inventory, which packages depend on ObjectStack, and a high-level alignment/gap summary to contextualize the work across the monorepo. |
OBJECTSTACK_SPEC_ALIGNMENT.zh-CN.md |
Chinese-language version of the spec-alignment analysis and implementation roadmap, tailored for Chinese-speaking stakeholders. |
OBJECTSTACK_SPEC_ALIGNMENT.md |
Detailed English analysis of ObjectUI vs. ObjectStack Spec v0.7.1, including gaps, proposed protocol types, and phased implementation plan. |
ALIGNMENT_SUMMARY.txt |
Visual/ASCII dashboard summarizing overall spec alignment, completed work, remaining optional gaps, and success metrics for quick executive review. |
| /** | ||
| * Simple expression evaluator using a simple parser (no dynamic code execution) | ||
| * | ||
| * SECURITY: This implementation parses expressions into an AST and evaluates them | ||
| * without using eval() or new Function(). It supports: | ||
| * - Comparison operators: ==, !=, >, <, >=, <= | ||
| * - Logical operators: &&, ||, ! | ||
| * - Property access: record.field, record['field'] | ||
| * - Literals: true, false, null, numbers, strings | ||
| * | ||
| * LIMITATIONS: | ||
| * - Single comparison operator per expression (no chaining like a > b > c) | ||
| * - Simple escape sequence handling (doesn't handle escaped backslashes) | ||
| * - Field names in bracket notation cannot contain escaped quotes | ||
| * | ||
| * For more complex expressions, integrate a dedicated library like: | ||
| * - JSONLogic (jsonlogic.com) | ||
| * - filtrex | ||
| * | ||
| * @see https://github.com/objectstack-ai/objectui/blob/main/SECURITY_FIX_SUMMARY.md | ||
| */ | ||
| class SimpleExpressionEvaluator implements ValidationExpressionEvaluator { | ||
| evaluate(expression: string, context: Record<string, any>): any { | ||
| try { | ||
| return this.evaluateSafeExpression(expression.trim(), context); | ||
| } catch (error) { | ||
| console.error('Expression evaluation error:', error); | ||
| return false; | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Safely evaluate an expression without using dynamic code execution | ||
| */ | ||
| private evaluateSafeExpression(expr: string, context: Record<string, any>): any { | ||
| // Handle boolean literals | ||
| if (expr === 'true') return true; | ||
| if (expr === 'false') return false; | ||
| if (expr === 'null') return null; | ||
|
|
||
| // Handle string literals | ||
| if ((expr.startsWith('"') && expr.endsWith('"')) || | ||
| (expr.startsWith("'") && expr.endsWith("'"))) { | ||
| return expr.slice(1, -1); | ||
| } | ||
|
|
||
| // Handle numeric literals | ||
| if (/^-?\d+(\.\d+)?$/.test(expr)) { | ||
| return parseFloat(expr); | ||
| } | ||
|
|
||
| // Handle logical NOT | ||
| if (expr.startsWith('!')) { | ||
| return !this.evaluateSafeExpression(expr.slice(1).trim(), context); | ||
| } | ||
|
|
||
| // Handle logical AND | ||
| if (expr.includes('&&')) { | ||
| const parts = this.splitOnOperator(expr, '&&'); | ||
| return parts.every(part => this.evaluateSafeExpression(part, context)); | ||
| } | ||
|
|
||
| // Handle logical OR | ||
| if (expr.includes('||')) { | ||
| const parts = this.splitOnOperator(expr, '||'); | ||
| return parts.some(part => this.evaluateSafeExpression(part, context)); | ||
| } | ||
|
|
||
| // Handle comparison operators | ||
| const comparisonMatch = expr.match(/^(.+?)\s*(===|!==|==|!=|>=|<=|>|<)\s*(.+)$/); | ||
| if (comparisonMatch) { | ||
| const [, left, op, right] = comparisonMatch; | ||
| const leftVal = this.evaluateSafeExpression(left.trim(), context); | ||
| const rightVal = this.evaluateSafeExpression(right.trim(), context); | ||
|
|
||
| switch (op) { | ||
| case '===': | ||
| return leftVal === rightVal; | ||
| case '==': | ||
| // Use loose equality for backward compatibility with existing expressions | ||
| // eslint-disable-next-line eqeqeq | ||
| return leftVal == rightVal; | ||
| case '!==': | ||
| return leftVal !== rightVal; | ||
| case '!=': | ||
| // Use loose inequality for backward compatibility with existing expressions | ||
| // eslint-disable-next-line eqeqeq | ||
| return leftVal != rightVal; | ||
| case '>': return leftVal > rightVal; | ||
| case '<': return leftVal < rightVal; | ||
| case '>=': return leftVal >= rightVal; | ||
| case '<=': return leftVal <= rightVal; | ||
| default: return false; | ||
| } | ||
| } | ||
|
|
||
| // Handle property access (e.g., record.field or context.field) | ||
| return this.getValueFromContext(expr, context); | ||
| } | ||
|
|
||
| /** | ||
| * Split expression on operator, respecting parentheses and quotes |
There was a problem hiding this comment.
The documentation for SimpleExpressionEvaluator advertises support for property access like record.field / record['field'], but validateScript (and other validation helpers) call expressionEvaluator.evaluate with context.record as the root context, meaning expressions that start with record. will not resolve as documented. Either pass the full ObjectValidationContext (or a wrapper like { record, oldRecord, user }) into the evaluator, or update the docs and examples to make it clear that expressions should reference fields directly (e.g., age >= 18) instead of record.age.
| ### Known Limitations | ||
| - Expression evaluator still uses `Function()` constructor (with sanitization) | ||
| - Recommendation for production: Use dedicated expression library (JSONLogic, expr-eval) | ||
| - Clear documentation added about security considerations |
There was a problem hiding this comment.
This document still describes the expression evaluator as using the Function() constructor with sanitization, but the current implementation in object-validation-engine.ts has been refactored to a non-dynamic, AST-style evaluator with no Function/eval usage. Please update this section to reflect the current implementation so security documentation stays accurate and does not overstate the remaining risk.
| table: string; | ||
| alias?: string; | ||
| on: OperatorNode; | ||
| strategy?: JoinStrategy; // Execution strategy hint for cross-datasource joins |
There was a problem hiding this comment.
JoinStrategy and the optional strategy property are defined on JoinNode, but there is no corresponding strategy field on JoinConfig in the high-level QuerySchema, so callers cannot actually set this hint and it will always be undefined in the AST. To fully support spec-level join strategy hints, consider adding an optional strategy?: JoinStrategy to JoinConfig and wiring it through the QueryASTBuilder.buildJoin implementation, or remove the unused strategy field here to avoid a dead configuration path.
| strategy?: JoinStrategy; // Execution strategy hint for cross-datasource joins |
… release; remove security fix summary and CRM app fix scripts.
Comprehensive analysis of all 26 packages against ObjectStack Spec v0.7.1. Current alignment: 80%. Identified critical gaps in window functions, validation framework, and action schema.
Analysis Results
Package Inventory
@objectstack/*dependenciesAlignment Breakdown
Critical Gaps (P0)
Window Functions - Enterprise analytics blocked
row_number,rank,lag,lead,first_value,last_valueValidation Framework - Only basic rules implemented
Action Schema - Basic buttons only
Documentation
OBJECTSTACK_SPEC_ALIGNMENT.md (850 lines)
OBJECTSTACK_SPEC_ALIGNMENT.zh-CN.md (400 lines)
PACKAGE_SCAN_SUMMARY.md (200 lines)
ALIGNMENT_SUMMARY.txt
Implementation Roadmap
Target: v0.4.0 with 95%+ spec compliance
Success metrics: Type compatibility 80%→95%, Validation 20%→100%, Actions 30%→95%, Query features 70%→90%
Original prompt
✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.