Add enterprise protocol extensions: encryption, multi-tenancy, CDC, SQL drivers#385
Add enterprise protocol extensions: encryption, multi-tenancy, CDC, SQL drivers#385
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
…audit, caching, tenancy, versioning Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
…faults Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
|
This PR is very large. Consider breaking it into smaller PRs for easier review. |
There was a problem hiding this comment.
Pull request overview
Expands the ObjectStack spec with enterprise-oriented protocol additions across Field/Object/Driver schemas, plus a new SQL driver configuration schema, and regenerates the corresponding JSON Schemas and reference docs.
Changes:
- Extended
FieldSchemawith encryption config, masking, audit trail, dependencies, computed caching, and data quality rules (with deprecated legacyencryptionflag). - Extended
ObjectSchemawith tenancy, soft delete, versioning, partitioning (with refinement), CDC, and richer index definitions. - Standardized driver capabilities with granular flags + introduced SQL driver config schema, tests, and exports; regenerated JSON schema + docs.
Reviewed changes
Copilot reviewed 32 out of 32 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/spec/src/system/index.ts | Exports new SQL driver protocol from the system entrypoint. |
| packages/spec/src/system/driver.zod.ts | Adds granular driver capability flags; introduces PoolConfig/DriverConfig schemas. |
| packages/spec/src/system/driver.test.ts | Updates capability tests to account for defaults. |
| packages/spec/src/system/driver-sql.zod.ts | New SQL driver config protocol (dialect, type mapping, SSL config, refinement). |
| packages/spec/src/system/driver-sql.test.ts | Adds test coverage for SQL driver protocol and refinements. |
| packages/spec/src/data/object.zod.ts | Adds object-level tenancy/soft-delete/versioning/partitioning/CDC + index enhancements. |
| packages/spec/src/data/field.zod.ts | Adds field-level encryption config/masking/audit/dependencies/cache/data-quality + deprecates encryption boolean. |
| packages/spec/json-schema/ui/FieldWidgetProps.json | Regenerated UI JSON schema to reflect new Field props. |
| packages/spec/json-schema/system/SSLConfig.json | New generated JSON schema for SSLConfig. |
| packages/spec/json-schema/system/SQLDriverConfig.json | New generated JSON schema for SQLDriverConfig. |
| packages/spec/json-schema/system/SQLDialect.json | New generated JSON schema for SQLDialect. |
| packages/spec/json-schema/system/PoolConfig.json | New generated JSON schema for PoolConfig. |
| packages/spec/json-schema/system/DriverInterface.json | Regenerated JSON schema reflecting updated DriverCapabilities structure. |
| packages/spec/json-schema/system/DriverConfig.json | New generated JSON schema for DriverConfig. |
| packages/spec/json-schema/system/DriverCapabilities.json | Regenerated JSON schema reflecting granular driver capability flags. |
| packages/spec/json-schema/system/DataTypeMapping.json | New generated JSON schema for SQL data type mapping. |
| packages/spec/json-schema/data/VersioningConfig.json | New generated JSON schema for object versioning config. |
| packages/spec/json-schema/data/TenancyConfig.json | New generated JSON schema for multi-tenancy config. |
| packages/spec/json-schema/data/SoftDeleteConfig.json | New generated JSON schema for soft delete config. |
| packages/spec/json-schema/data/PartitioningConfig.json | New generated JSON schema for partitioning config. |
| packages/spec/json-schema/data/Object.json | Regenerated JSON schema for Object with new advanced config blocks. |
| packages/spec/json-schema/data/Index.json | Regenerated JSON schema for Index enhancements (type/unique/partial). |
| packages/spec/json-schema/data/Field.json | Regenerated JSON schema for Field with new security/quality/caching fields. |
| packages/spec/json-schema/data/DataQualityRules.json | New generated JSON schema for field data quality rules. |
| packages/spec/json-schema/data/ComputedFieldCache.json | New generated JSON schema for computed field caching. |
| packages/spec/json-schema/data/CDCConfig.json | New generated JSON schema for CDC config. |
| content/docs/references/system/meta.json | Adds driver-sql to system docs navigation metadata. |
| content/docs/references/system/index.mdx | Adds system docs card for the new driver-sql reference page. |
| content/docs/references/system/driver.mdx | Updates driver docs to include new DriverConfig/PoolConfig and expanded capabilities. |
| content/docs/references/system/driver-sql.mdx | New reference documentation page for SQL driver protocol. |
| content/docs/references/data/object.mdx | Updates object docs to include new advanced management configs and updated Index. |
| content/docs/references/data/field.mdx | Updates field docs to include new caching + data quality sections and new Field properties. |
| }).refine((data) => { | ||
| // Ensure deprecated geoSpatial and new geospatialQuery are consistent if both are provided | ||
| if (data.geoSpatial !== undefined && data.geospatialQuery !== undefined && data.geoSpatial !== data.geospatialQuery) { | ||
| return false; | ||
| } |
There was a problem hiding this comment.
DriverCapabilitiesSchema defaults mean geoSpatial/geospatialQuery are always present during parsing, so this refine will fail whenever a caller sets only one of them (e.g., geospatialQuery: true with geoSpatial omitted). That makes the new geospatialQuery flag unusable unless callers also set the deprecated geoSpatial field.
Consider making the deprecated geoSpatial optional without a default (or otherwise avoiding defaults on at least one of these fields) so the refinement truly checks "if both were provided"; alternatively, drop the refine and treat geoSpatial as an alias in higher-level code.
| export type DriverOptions = z.infer<typeof DriverOptionsSchema>; | ||
| export type DriverCapabilities = z.infer<typeof DriverCapabilitiesSchema>; | ||
| export type DriverInterface = z.infer<typeof DriverInterfaceSchema>; | ||
| export type DriverConfig = z.infer<typeof DriverConfigSchema>; | ||
| export type PoolConfig = z.infer<typeof PoolConfigSchema>; |
There was a problem hiding this comment.
The exported DriverCapabilities type is still derived from z.infer (parsed/output type), which will require all capability flags at the type level even though the schema now provides defaults. If the goal is to let driver authors omit unspecified flags in TypeScript (as the docs/PR description suggest), consider exporting a separate input type (e.g., DriverCapabilitiesInput = z.input<typeof DriverCapabilitiesSchema>) and updating docs/examples to use that for authoring configs.
| encryptionConfig: EncryptionConfigSchema.optional().describe('Field-level encryption configuration for sensitive data (GDPR/HIPAA/PCI-DSS)'), | ||
|
|
||
| // Data masking rules | ||
| maskingRule: MaskingRuleSchema.optional().describe('Data masking rules for PII protection'), | ||
|
|
There was a problem hiding this comment.
FieldSchema.maskingRule uses MaskingRuleSchema, but MaskingRuleSchema requires a field property. Since this config is already nested under a specific field, requiring/allowing a separate field name here is redundant and can be inconsistent with the actual FieldSchema.name.
Consider switching to a field-scoped masking schema (e.g., MaskingRuleSchema.omit({ field: true })) or introducing a dedicated FieldMaskingRuleSchema without the field attribute.
| export const DataQualityRulesSchema = z.object({ | ||
| /** Enforce uniqueness constraint */ | ||
| uniqueness: z.boolean().default(false).describe('Enforce unique values across all records'), | ||
|
|
||
| /** Completeness ratio (0-1) indicating minimum percentage of non-null values */ | ||
| completeness: z.number().min(0).max(1).default(0).describe('Minimum ratio of non-null values (0-1, default: 0 = no requirement)'), | ||
|
|
There was a problem hiding this comment.
New field-level config surfaces (DataQualityRulesSchema / ComputedFieldCacheSchema) are introduced here, but there are no accompanying tests in packages/spec/src/data/field.test.ts covering: defaulting behavior (e.g., completeness default 0), boundary validation (0–1), and basic acceptance of these configs when attached to FieldSchema.
Adding a small set of focused tests would help prevent regressions as these enterprise features evolve.
| export const TenancyConfigSchema = z.object({ | ||
| enabled: z.boolean().describe('Enable multi-tenancy for this object'), | ||
| strategy: z.enum(['shared', 'isolated', 'hybrid']).describe('Tenant isolation strategy: shared (single DB, row-level), isolated (separate DB per tenant), hybrid (mix)'), | ||
| tenantField: z.string().default('tenant_id').describe('Field name for tenant identifier'), | ||
| crossTenantAccess: z.boolean().default(false).describe('Allow cross-tenant data access (with explicit permission)'), |
There was a problem hiding this comment.
ObjectSchema adds several new advanced config schemas (tenancy/softDelete/versioning/partitioning/cdc), but packages/spec/src/data/object.test.ts currently has no coverage for parsing/validation of these new shapes (including the range-partition interval refinement).
Given this repo already has thorough schema tests, adding a few representative cases would help lock in the intended contract.
| it('should accept capabilities with defaults', () => { | ||
| const incomplete = { | ||
| transactions: true, | ||
| joins: true, | ||
| queryFilters: true, | ||
| // missing other fields | ||
| // missing other fields - they should use defaults | ||
| }; | ||
|
|
||
| const result = DriverCapabilitiesSchema.safeParse(incomplete); | ||
| expect(result.success).toBe(false); | ||
| expect(result.success).toBe(true); | ||
| if (result.success) { | ||
| // Check that defaults are applied | ||
| expect(result.data.create).toBe(true); // default | ||
| expect(result.data.bulkCreate).toBe(false); // default | ||
| expect(result.data.queryAggregations).toBe(false); // default | ||
| } |
There was a problem hiding this comment.
The updated test suite doesn’t cover the new geoSpatial/geospatialQuery consistency behavior. Adding explicit cases for "only geospatialQuery provided" and "only geoSpatial provided" would catch the current refinement/default interaction and ensure backward compatibility stays intact.
Extends ObjectStack protocol schemas with enterprise-grade features: field-level security (encryption, masking, audit), object-level data management (multi-tenancy, versioning, partitioning, CDC), and standardized driver capabilities with SQL-specific protocol.
Field Protocol (
field.zod.ts)Security & Compliance
encryptionConfig: References existingEncryptionConfigSchemafor GDPR/HIPAA field encryptionmaskingRule: References existingMaskingRuleSchemafor PII protectionauditTrail: Boolean flag for change trackingPerformance & Quality
cached: TTL-based caching for computed fields with invalidation rulesdataQuality: Uniqueness, completeness, accuracy validationdependencies: Field dependency graph for formula/visibility resolutionBreaking: Deprecated
encryption: booleanin favor ofencryptionConfigObject Protocol (
object.zod.ts)Data Architecture
tenancy: Row-level isolation (shared/isolated/hybrid strategies)softDelete: Recycle bin with cascade controlversioning: Snapshot/delta/event-sourcing with retention policiespartitioning: Range/hash/list partitioning with interval validationcdc: Change Data Capture endpoints for real-time streamingIndexes: Added
fulltexttype andpartial(conditional) index supportDriver Protocol (
driver.zod.ts)Capability Detection (44 flags with defaults):
create,read,update,deletebulkCreate,bulkUpdate,bulkDeletesavepoints,isolationLevels[]queryCTE,queryWindowFunctions,querySubqueriesjsonQuery,geospatialQuery,streaming,vectorSearchschemaSync,migrations,indexesconnectionPooling,preparedStatements,queryCacheConfig: Added
DriverConfigSchemaandPoolConfigSchemafor connection managementBreaking: Fields changed from required to optional-with-defaults. TypeScript no longer enforces explicit capability declaration.
SQL Driver Protocol (
driver-sql.zod.ts) - NEWSQL-specific driver configuration with dialect-aware type mapping:
Validation Refinements:
ssl: truerequiressslConfigcertandkeymust be provided togetherstrategy: 'range'requiresintervalgeoSpatialmust matchgeospatialQueryif both presentExports
All new schemas exported from
@objectstack/spec/dataand@objectstack/spec/system.Original prompt
2.1 Field Protocol Enhancement
Current: packages/spec/src/data/field.zod.ts
Enhancement: Add encryption, masking, audit, and caching
import { z } from 'zod';
import { EncryptionConfigSchema } from '../system/encryption.zod';
import { MaskingRuleSchema } from '../system/masking.zod';
export const FieldSchema = z.object({
// ... existing fields (name, label, type, etc.)
// ✅ NEW: Encryption support
encryption: EncryptionConfigSchema.optional(),
// ✅ NEW: Masking rules
masking: MaskingRuleSchema.optional(),
// ✅ NEW: Audit trail
auditTrail: z.boolean().default(false),
// ✅ NEW: Field dependencies
dependencies: z.array(z.string()).optional(),
// ✅ NEW: Computed field caching
cached: z.object({
enabled: z.boolean(),
ttl: z.number(),
invalidateOn: z.array(z.string()),
}).optional(),
// ✅ NEW: Data quality rules
dataQuality: z.object({
uniqueness: z.boolean().default(false),
completeness: z.number().min(0).max(1).default(1),
accuracy: z.object({
source: z.string(),
threshold: z.number(),
}).optional(),
}).optional(),
// ✅ NEW: File/attachment configuration
fileConfig: z.object({
maxSize: z.number(),
allowedTypes: z.array(z.string()),
virusScan: z.boolean().default(true),
storageProvider: z.string(),
}).optional(),
});
2.2 Object Protocol Enhancement
Current: packages/spec/src/data/object.zod.ts
Enhancement: Add multi-tenancy, soft delete, versioning, partitioning
import { z } from 'zod';
export const ObjectSchema = z.object({
// ... existing fields (name, label, fields, etc.)
// ✅ NEW: Multi-tenancy configuration
tenancy: z.object({
enabled: z.boolean(),
strategy: z.enum(['shared', 'isolated', 'hybrid']),
tenantField: z.string().default('tenant_id'),
crossTenantAccess: z.boolean().default(false),
}).optional(),
// ✅ NEW: Soft delete
softDelete: z.object({
enabled: z.boolean(),
field: z.string().default('deleted_at'),
cascadeDelete: z.boolean().default(false),
}).optional(),
// ✅ NEW: Versioning
versioning: z.object({
enabled: z.boolean(),
strategy: z.enum(['snapshot', 'delta', 'event-sourcing']),
retentionDays: z.number().optional(),
versionField: z.string().default('version'),
}).optional(),
// ✅ NEW: Partitioning strategy
partitioning: z.object({
enabled: z.boolean(),
strategy: z.enum(['range', 'hash', 'list']),
key: z.string(),
interval: z.string().optional(),
}).optional(),
// ✅ NEW: Index definitions
indexes: z.array(z.object({
name: z.string(),
fields: z.array(z.string()),
type: z.enum(['btree', 'hash', 'gin', 'gist', 'fulltext']),
unique: z.boolean().default(false),
partial: z.string().optional(),
})).optional(),
// ✅ NEW: Change Data Capture
cdc: z.object({
enabled: z.boolean(),
events: z.array(z.enum(['insert', 'update', 'delete'])),
destination: z.string(),
}).optional(),
});
3. Driver Protocol Standardization / 驱动协议标准化
3.1 Enhanced Driver Capabilities
Current: packages/spec/src/system/driver.zod.ts
Enhancement: More granular capability flags
import { z } from 'zod';
export const DriverCapabilitiesSchema = z.object({
// Basic CRUD
create: z.boolean().default(true),
read: z.boolean().default(true),
update: z.boolean().default(true),
delete: z.boolean().default(true),
// Bulk operations
bulkCreate: z.boolean().default(false),
bulkUpdate: z.boolean().default(false),
bulkDelete: z.boolean().default(false),
// Transactions
transactions: z.boolean().default(false),
savepoints: z.boolean().default(false),
isolationLevels: z.array(z.enum([
'read-uncommitted',
'read-committed',
'repeatable-read',
'serializable',
])).optional(),
// Query capabilities
queryFilters: z.boolean().default(true),
queryAggregations: z.boolean().default(false),
querySorting: z.boolean().default(true),
queryPagination: z.boolean().default(true),
queryWindowFunctions: z.boolean().default(false),
querySubqueries: z.boolean().default(false),
queryCTE: z.boolean().default(false),
// Advanced features
fullTextSearch: z.boolean().default(false),
jsonQuery: z.boolean().default(false),
geospatialQuery: z.boolean().default(false),
streaming: z.boolean().default(false),
// Schema management
schemaSync: z.boolean().default(false),
migrations: z.boolean().default(false),
indexes: z.boolean().default(false),
// Performance
connectionPooling: z.boolean().default(false),
preparedStatements: z.boolean().default(false),
queryCache: z.boolean().default(false),
});
export const DriverConfigSchema = z.object({
name: z.string(),
type: z.enum(['sql', 'nosql', 'cache', 'search', 'graph', 'timeseries']),
capabilities: DriverCapabilitiesSchema,
connectionString: z.string().optional(),
poolConfig: z.object({
min: z.number().defaul...
💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.