Add system protocols for caching, encryption, compliance, messaging, search, and masking#384
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
…earch-engine, and masking Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This PR implements Zod-first protocol schemas for six new system-level infrastructure and security protocols: caching, message queuing, search engines, field-level encryption, regulatory compliance, and data masking. All schemas follow ObjectStack conventions with camelCase properties and proper TypeScript type inference.
Changes:
- Added 6 new system protocol schemas with comprehensive configuration options for enterprise features
- Generated corresponding JSON schemas for all new types (34 JSON schema files)
- Created documentation files for all new protocols in the system layer
- Updated integration and data layer documentation to reflect schema reorganization
Reviewed changes
Copilot reviewed 46 out of 46 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/spec/src/system/cache.zod.ts | Multi-tier caching protocol with LRU/LFU/FIFO strategies and invalidation rules |
| packages/spec/src/system/message-queue.zod.ts | Async messaging protocol for Kafka, RabbitMQ, SQS with DLQ and SASL auth (has naming conflicts) |
| packages/spec/src/system/search-engine.zod.ts | Full-text search protocol for Elasticsearch, Algolia, etc. (has naming conflict) |
| packages/spec/src/system/encryption.zod.ts | Field-level encryption with AES-256-GCM/CBC, KMS integration, key rotation |
| packages/spec/src/system/compliance.zod.ts | GDPR, HIPAA, PCI-DSS compliance protocols with audit logging |
| packages/spec/src/system/masking.zod.ts | Role-based PII masking with redact/partial/hash strategies |
| packages/spec/src/system/index.ts | Updated exports to include new protocols |
| packages/spec/json-schema/system/*.json | Auto-generated JSON schemas (34 files) for all new types |
| content/docs/references/system/*.mdx | Documentation for cache, message-queue, search-engine, encryption, compliance, masking |
| content/docs/references/system/meta.json | Updated navigation to include new protocol pages |
| content/docs/references/system/index.mdx | Updated index page with new protocol cards |
| content/docs/references/integration/misc.mdx | Removed ConsumerConfig and MessageQueueProvider (moved to separate file) |
| content/docs/references/integration/message-queue.mdx | New documentation for integration layer message queue schemas |
| content/docs/references/data/search-engine.mdx | Invalid documentation file referencing non-existent source (should be removed) |
| content/docs/references/data/object.mdx | Updated to remove SearchConfig from imports (now separate) |
| export const MessageQueueProviderSchema = z.enum([ | ||
| 'kafka', | ||
| 'rabbitmq', | ||
| 'aws-sqs', | ||
| 'redis-pubsub', | ||
| 'google-pubsub', | ||
| 'azure-service-bus', | ||
| ]); | ||
|
|
||
| export type MessageQueueProvider = z.infer<typeof MessageQueueProviderSchema>; |
There was a problem hiding this comment.
There is a naming conflict with the integration layer. MessageQueueProviderSchema and MessageQueueProvider are already defined in packages/spec/src/integration/connector/message-queue.zod.ts with different enum values.
The integration layer has: rabbitmq, kafka, redis_pubsub, redis_streams, aws_sqs, aws_sns, google_pubsub, azure_service_bus, azure_event_hubs, nats, pulsar, activemq, custom
This file has: kafka, rabbitmq, aws-sqs, redis-pubsub, google-pubsub, azure-service-bus
These schemas serve different purposes (integration connectors vs system configuration) and should have distinct names to avoid conflicts. Consider renaming to SystemMessageQueueProviderSchema or MessageQueueSystemProviderSchema to differentiate from the integration layer's connector schema.
| export const ConsumerConfigSchema = z.object({ | ||
| groupId: z.string(), | ||
| autoOffsetReset: z.enum(['earliest', 'latest']).default('latest'), | ||
| enableAutoCommit: z.boolean().default(true), | ||
| maxPollRecords: z.number().default(500), | ||
| }); | ||
|
|
||
| export type ConsumerConfig = z.infer<typeof ConsumerConfigSchema>; |
There was a problem hiding this comment.
There is a naming conflict with the integration layer. ConsumerConfigSchema and ConsumerConfig are already defined in packages/spec/src/integration/connector/message-queue.zod.ts with different properties.
The integration layer ConsumerConfig includes: enabled, consumerGroup, concurrency, prefetchCount, ackMode, autoCommit, autoCommitIntervalMs, sessionTimeoutMs, rebalanceTimeoutMs
This file has: groupId, autoOffsetReset, enableAutoCommit, maxPollRecords
These schemas serve different purposes and should have distinct names. Consider renaming to SystemConsumerConfigSchema or TopicConsumerConfigSchema to differentiate from the integration layer's connector schema.
| export const SearchConfigSchema = z.object({ | ||
| provider: SearchProviderSchema, | ||
| indexes: z.array(SearchIndexConfigSchema), | ||
| analyzers: z.record(AnalyzerConfigSchema).optional(), | ||
| facets: z.array(FacetConfigSchema).optional(), | ||
| typoTolerance: z.boolean().default(true), | ||
| synonyms: z.record(z.array(z.string())).optional(), | ||
| ranking: z.array(z.enum(['typo', 'geo', 'words', 'filters', 'proximity', 'attribute', 'exact', 'custom'])).optional(), | ||
| }); | ||
|
|
||
| export type SearchConfig = z.infer<typeof SearchConfigSchema>; |
There was a problem hiding this comment.
There is a naming conflict with the data layer. SearchConfigSchema and SearchConfig are already defined in packages/spec/src/data/object.zod.ts with different properties.
The data layer SearchConfig defines object-level search configuration with: fields (for indexing), displayFields, filters
This file defines system-level search engine configuration with: provider, indexes, analyzers, facets, typoTolerance, synonyms, ranking
These schemas serve different purposes (object-level vs system-level search configuration) and should have distinct names. Consider renaming to SearchEngineConfigSchema or SystemSearchConfigSchema to differentiate from the data layer's object search configuration.
| # Search Engine | ||
|
|
||
| <Callout type="info"> | ||
| **Source:** `packages/spec/src/data/search-engine.zod.ts` |
There was a problem hiding this comment.
This documentation file references a non-existent source file. The file claims to document packages/spec/src/data/search-engine.zod.ts, but this file does not exist in the data layer.
The SearchConfigSchema is actually defined in packages/spec/src/data/object.zod.ts and is part of the Object protocol. This documentation file should either:
- Be removed entirely (since SearchConfig is documented in object.mdx), or
- Reference the correct source file (packages/spec/src/data/object.zod.ts)
| **Source:** `packages/spec/src/data/search-engine.zod.ts` | |
| **Source:** `packages/spec/src/data/object.zod.ts` |
| export const MessageQueueProviderSchema = z.enum([ | ||
| 'kafka', | ||
| 'rabbitmq', | ||
| 'aws-sqs', | ||
| 'redis-pubsub', | ||
| 'google-pubsub', | ||
| 'azure-service-bus', | ||
| ]); |
There was a problem hiding this comment.
Inconsistent enum value naming convention. The integration layer uses snake_case for provider enum values (e.g., redis_pubsub, aws_sqs), but this system layer uses kebab-case (e.g., redis-pubsub, aws-sqs).
While these are different schemas serving different purposes, maintaining consistency in enum value formatting across the codebase improves developer experience. Consider aligning with the existing integration layer convention and using snake_case (e.g., redis_pubsub, aws_sqs, google_pubsub, azure_service_bus) for consistency.
| export const KeyManagementProviderSchema = z.enum([ | ||
| 'local', | ||
| 'aws-kms', | ||
| 'azure-key-vault', | ||
| 'gcp-kms', | ||
| 'hashicorp-vault', | ||
| ]); |
There was a problem hiding this comment.
Inconsistent enum value naming convention. Other provider enums in the system use snake_case (e.g., in datasource.zod.ts), but this uses kebab-case (e.g., aws-kms, azure-key-vault, gcp-kms, hashicorp-vault).
For consistency with the broader codebase patterns, consider using snake_case (e.g., aws_kms, azure_key_vault, gcp_kms, hashicorp_vault) for provider identifiers.
| /** | ||
| * Compliance protocol for GDPR, CCPA, HIPAA, SOX, PCI-DSS | ||
| */ |
There was a problem hiding this comment.
The comment mentions "CCPA" and "SOX" in addition to GDPR, HIPAA, and PCI-DSS, but no schemas are defined for CCPA or SOX compliance.
If CCPA and SOX support is planned, consider adding schemas for them (CCPAConfigSchema, SOXConfigSchema). If not planned, remove them from the comment to avoid confusion. The comment should accurately reflect the implemented compliance frameworks.
| --- | ||
| title: Search Engine | ||
| description: Search Engine protocol schemas | ||
| --- | ||
|
|
||
| # Search Engine | ||
|
|
||
| <Callout type="info"> | ||
| **Source:** `packages/spec/src/data/search-engine.zod.ts` | ||
| </Callout> | ||
|
|
||
| ## TypeScript Usage | ||
|
|
||
| ```typescript | ||
| import { SearchConfigSchema } from '@objectstack/spec/data'; | ||
| import type { SearchConfig } from '@objectstack/spec/data'; | ||
|
|
||
| // Validate data | ||
| const result = SearchConfigSchema.parse(data); | ||
| ``` | ||
|
|
||
| --- | ||
|
|
||
| ## SearchConfig | ||
|
|
||
| ### Properties | ||
|
|
||
| | Property | Type | Required | Description | | ||
| | :--- | :--- | :--- | :--- | | ||
| | **fields** | `string[]` | ✅ | Fields to index for full-text search weighting | | ||
| | **displayFields** | `string[]` | optional | Fields to display in search result cards | | ||
| | **filters** | `string[]` | optional | Default filters for search results | | ||
|
|
There was a problem hiding this comment.
This documentation file should not exist in the data layer. The SearchConfig it documents is part of the Object protocol and is already documented in object.mdx. Additionally, this file references a non-existent source file (packages/spec/src/data/search-engine.zod.ts) and is not registered in the data layer's meta.json navigation file.
This file should be removed entirely. The object-level SearchConfig is already properly documented in the Object protocol documentation.
| --- | |
| title: Search Engine | |
| description: Search Engine protocol schemas | |
| --- | |
| # Search Engine | |
| <Callout type="info"> | |
| **Source:** `packages/spec/src/data/search-engine.zod.ts` | |
| </Callout> | |
| ## TypeScript Usage | |
| ```typescript | |
| import { SearchConfigSchema } from '@objectstack/spec/data'; | |
| import type { SearchConfig } from '@objectstack/spec/data'; | |
| // Validate data | |
| const result = SearchConfigSchema.parse(data); | |
| ``` | |
| --- | |
| ## SearchConfig | |
| ### Properties | |
| | Property | Type | Required | Description | | |
| | :--- | :--- | :--- | :--- | | |
| | **fields** | `string[]` | ✅ | Fields to index for full-text search weighting | | |
| | **displayFields** | `string[]` | optional | Fields to display in search result cards | | |
| | **filters** | `string[]` | optional | Default filters for search results | |
Implements Zod-first protocol schemas for infrastructure and security concerns: multi-tier caching, field-level encryption, regulatory compliance (GDPR/HIPAA/PCI-DSS), message queuing, full-text search, and data masking.
New Protocol Schemas
Infrastructure Protocols (
/packages/spec/src/system/)cache.zod.ts- Multi-tier caching (memory/Redis/CDN) with LRU/LFU/FIFO strategies and invalidation rulesmessage-queue.zod.ts- Async messaging for Kafka, RabbitMQ, SQS, Pub/Sub with DLQ and SASL authsearch-engine.zod.ts- Full-text search for Elasticsearch, Algolia, Meilisearch with analyzers and facetsSecurity & Compliance Protocols (
/packages/spec/src/system/)encryption.zod.ts- Field-level encryption with AES-256-GCM/CBC, KMS integration, key rotation, deterministic/searchable modescompliance.zod.ts- GDPR data subject rights, HIPAA PHI controls, PCI-DSS tokenization, audit loggingmasking.zod.ts- Role-based PII masking with redact/partial/hash/tokenize strategiesUsage Example
All schemas follow ObjectStack conventions: camelCase properties, snake_case identifiers, auto-generated JSON schemas and docs.
Original prompt
1.1 Database & Storage Protocols
GraphQL Protocol (Priority: ⭐⭐⭐)
File: packages/spec/src/api/graphql.zod.ts
import { z } from 'zod';
/**
*/
export const GraphQLTypeSchema = z.object({
typeName: z.string(),
description: z.string().optional(),
fields: z.record(z.object({
type: z.enum(['String', 'Int', 'Float', 'Boolean', 'ID', 'Custom']),
list: z.boolean().default(false),
nullable: z.boolean().default(true),
customType: z.string().optional(),
})),
});
export const GraphQLQueryConfigSchema = z.object({
enabled: z.boolean().default(true),
operationName: z.string(),
returnType: z.string(),
args: z.record(z.string()).optional(),
complexity: z.number().optional(),
});
export const GraphQLMutationConfigSchema = z.object({
enabled: z.boolean().default(true),
operationName: z.string(),
inputType: z.string(),
returnType: z.string(),
});
export const GraphQLSubscriptionConfigSchema = z.object({
enabled: z.boolean().default(false),
eventName: z.string(),
filter: z.string().optional(),
payload: z.string(),
});
export const GraphQLConfigSchema = z.object({
enabled: z.boolean().default(false),
endpoint: z.string().default('/graphql'),
playground: z.boolean().default(true),
introspection: z.boolean().default(true),
queryDepthLimit: z.number().default(10),
complexityLimit: z.number().default(1000),
queries: z.array(GraphQLQueryConfigSchema).optional(),
mutations: z.array(GraphQLMutationConfigSchema).optional(),
subscriptions: z.array(GraphQLSubscriptionConfigSchema).optional(),
});
export type GraphQLConfig = z.infer;
Rationale / 原因:
Hasura and Prisma prove GraphQL is essential for modern data APIs
Type-safe schema generation from ObjectQL definitions
Automatic resolver generation based on permissions
Cache Protocol (Priority: ⭐⭐⭐)
File: packages/spec/src/system/cache.zod.ts
import { z } from 'zod';
/**
*/
export const CacheStrategySchema = z.enum([
'lru', // Least Recently Used
'lfu', // Least Frequently Used
'fifo', // First In First Out
'ttl', // Time To Live only
'adaptive', // Dynamic strategy selection
]);
export const CacheTierSchema = z.object({
name: z.string(),
type: z.enum(['memory', 'redis', 'memcached', 'cdn']),
maxSize: z.number().optional().describe('Max size in MB'),
ttl: z.number().default(300).describe('Default TTL in seconds'),
strategy: CacheStrategySchema.default('lru'),
warmup: z.boolean().default(false),
});
export const CacheInvalidationSchema = z.object({
trigger: z.enum(['create', 'update', 'delete', 'manual']),
scope: z.enum(['key', 'pattern', 'tag', 'all']),
pattern: z.string().optional(),
tags: z.array(z.string()).optional(),
});
export const CacheConfigSchema = z.object({
enabled: z.boolean().default(false),
tiers: z.array(CacheTierSchema),
invalidation: z.array(CacheInvalidationSchema),
prefetch: z.boolean().default(false),
compression: z.boolean().default(false),
encryption: z.boolean().default(false),
});
export type CacheConfig = z.infer;
Object Storage Protocol (Priority: ⭐⭐)
File: packages/spec/src/system/object-storage.zod.ts
import { z } from 'zod';
/**
*/
export const StorageProviderSchema = z.enum([
's3',
'azure-blob',
'gcs',
'minio',
'local',
]);
export const BucketConfigSchema = z.object({
name: z.string(),
region: z.string().optional(),
public: z.boolean().default(false),
versioning: z.boolean().default(false),
encryption: z.enum(['none', 'aes256', 'kms']).default('none'),
lifecycle: z.object({
expirationDays: z.number().optional(),
transitionToArchive: z.number().optional(),
}).optional(),
});
export const PresignedUrlConfigSchema = z.object({
expiration: z.number().default(3600).describe('Expiration in seconds'),
allowedOperations: z.array(z.enum(['get', 'put', 'delete'])),
});
export const ObjectStorageConfigSchema = z.object({
provider: StorageProviderSchema,
accessKeyId: z.string().optional(),
secretAccessKey: z.string().optional(),
endpoint: z.string().optional(),
buckets: z.array(BucketConfigSchema),
multipartThreshold: z.number().default(5242880).describe('5MB in bytes'),
presignedUrls: PresignedUrlConfigSchema.optional(),
});
export type ObjectStorageConfig = z.infer;
Message Queue Protocol (Priority: ⭐⭐)
File: packages/spec/src/system/message-queue.zod.ts
import { z } from 'zod';
/**
*/
export const MessageQueueProviderSchema = z.enum([
'kafka',
'rabbitmq',
'aws-sqs',
'redis-pubsub',
'google-pubsub',
'azu...
💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.