Context Store Requirements
ECM Protocol-compliant context stores must implement the store interface specification. This guide covers building a compliant store implementation.
Storage Backend
Interface Implementation
class ECMContextStore implements ContextStore {
constructor(private backend: StorageBackend) {}
async put(context: Context): Promise<ContextRef> {
this.validate(context);
const ref = await this.backend.insert(context);
await this.emit('context.created', context, ref);
return ref;
}
async get(id: ContextId): Promise<Context | null> {
return await this.backend.findById(id);
}
async update(id: ContextId, context: Context, etag?: string): Promise<ContextRef> {
const existing = await this.backend.findById(id);
if (!existing) throw new NotFoundError(id);
if (etag && existing.etag !== etag) throw new ConcurrencyError();
const ref = await this.backend.update(id, context);
await this.emit('context.updated', context, ref);
return ref;
}
}
Query Implementation
ECM-QL Parser
class QueryParser {
parse(ecmQuery: ECMQuery): BackendQuery {
const filters = this.parseFilters(ecmQuery.filter);
const projection = this.parseProjection(ecmQuery.projection);
const sort = this.parseSort(ecmQuery.sort);
return {
filters,
projection,
sort,
limit: ecmQuery.limit || 100,
offset: ecmQuery.offset || 0
};
}
private parseFilters(filter: FilterExpression): BackendFilter {
if (filter.and) {
return { $and: filter.and.map(f => this.parseFilters(f)) };
}
return this.parseSimpleFilter(filter);
}
}
Concurrency Control
Version Tracking
class VersionedStore {
async update(id: string, context: Context, expectedVersion?: number): Promise<ContextRef> {
return await this.backend.transaction(async (tx) => {
const current = await tx.findById(id);
if (expectedVersion && current.version !== expectedVersion) {
throw new ConcurrencyError(\`Expected version \${expectedVersion}, found \${current.version}\`);
}
const newVersion = current.version + 1;
await tx.update(id, {...context, version: newVersion});
return {
id,
version: newVersion,
etag: this.computeEtag(context, newVersion)
};
});
}
}
Event Emission
Event Publisher
class EventPublisher {
constructor(private transport: EventTransport) {}
async publish(event: ContextEvent): Promise<void> {
const envelope = {
event_id: generateUUID(),
event_type: event.type,
timestamp: new Date().toISOString(),
payload: event.data
};
await this.transport.publish(event.type, envelope);
}
}
Indexing Strategy
Index Configuration
const indexConfig = {
primary: { field: 'id', unique: true },
secondary: [
{ fields: ['context_type', 'created_at'], name: 'type_created' },
{ fields: ['metadata.tenant_id'], name: 'tenant' }
],
text: { fields: ['data.*'], name: 'content_search' },
vector: { field: 'embedding', dimensions: 1536, metric: 'cosine' }
};
Compliance Testing
Verify compliance with test suite:
- CRUD operations: All basic operations work
- Query support: ECM-QL queries execute correctly
- Concurrency: ETag/version conflicts detected
- Events: Change events emitted
- Error codes: Correct error responses
Conclusion
Building a compliant context store requires attention to interface contracts, query parsing, concurrency control, and event emission. Use the compliance test suite to verify implementation correctness.