Skip to content

Commit 2537664

Browse files
os-zhuangclaude
andcommitted
feat(spec): segment ObjectStackProtocol into per-domain protocol interfaces (ADR-0076 D9)
Split the 70-method, 11-domain ObjectStackProtocol god-interface into focused, exported per-domain contracts (DataProtocol, MetadataProtocol, AnalyticsProtocol, AutomationProtocol, PackageProtocol, ViewProtocol, PermissionProtocol, WorkflowProtocol, RealtimeProtocol, NotificationProtocol, AiProtocol, I18nProtocol, FeedProtocol). ObjectStackProtocol now `extends` all of them — shape-identical to the old flat interface, so non-breaking. This is the lowest-risk, foundational step of ADR-0076 D9: pure type-level, shape-preserving, no runtime change. Consumers can now depend on the narrowest slice (e.g. DataProtocol). The composed union is transitional (D9 rev.7). Verified: turbo build (spec + rest + metadata-protocol + objectql) green incl. DTS — the impl class still satisfies `implements ObjectStackProtocol`; spec suite 243 files / 6602 tests pass. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 4899c47 commit 2537664

2 files changed

Lines changed: 94 additions & 26 deletions

File tree

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
---
2+
'@objectstack/spec': minor
3+
---
4+
5+
Segment `ObjectStackProtocol` into per-domain protocol interfaces (ADR-0076 D9)
6+
7+
`ObjectStackProtocol` was a single 70-method interface spanning 11 unrelated domains. It is now the **composition** of focused per-domain contracts — `DataProtocol`, `MetadataProtocol`, `AnalyticsProtocol`, `AutomationProtocol`, `PackageProtocol`, `ViewProtocol`, `PermissionProtocol`, `WorkflowProtocol`, `RealtimeProtocol`, `NotificationProtocol`, `AiProtocol`, `I18nProtocol`, `FeedProtocol` — all newly exported.
8+
9+
`ObjectStackProtocol` now `extends` all of them and is **shape-identical** to the previous flat interface, so every existing implementation/consumer is unaffected (non-breaking). New code should depend on the narrowest slice it needs (e.g. `DataProtocol`). Per ADR-0076 D9 (rev.7) the composed union is transitional; capability availability is provided at runtime by the discovery `services` registry.

packages/spec/src/api/protocol.zod.ts

Lines changed: 85 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1376,7 +1376,34 @@ export type ObjectStackProtocolZod = z.infer<typeof ObjectStackProtocolSchema>;
13761376
* The Zod schema (ObjectStackProtocolSchema) is used for runtime validation,
13771377
* while this interface provides compile-time type safety for implementations.
13781378
*/
1379-
export interface ObjectStackProtocol {
1379+
// ─────────────────────────────────────────────────────────────────────────────
1380+
// Protocol contracts, segmented per domain (ADR-0076 D9).
1381+
//
1382+
// `ObjectStackProtocol` (below) is the composition of these per-domain contracts
1383+
// and is shape-identical to the historical flat interface — a back-compat alias.
1384+
// New code should depend on the narrowest slice it needs (e.g. `DataProtocol`).
1385+
// Per ADR-0076 D9 (rev.7) the union is transitional; the end-state dissolves it
1386+
// in favour of independent domain protocols + the discovery `services` registry.
1387+
// ─────────────────────────────────────────────────────────────────────────────
1388+
1389+
/** Business-data CRUD + batch operations (thin wire-normalizers over the engine). */
1390+
export interface DataProtocol {
1391+
// Data Operations (core)
1392+
findData(request: FindDataRequest): Promise<FindDataResponse>;
1393+
getData(request: GetDataRequest): Promise<GetDataResponse>;
1394+
createData(request: CreateDataRequest): Promise<CreateDataResponse>;
1395+
updateData(request: UpdateDataRequest): Promise<UpdateDataResponse>;
1396+
deleteData(request: DeleteDataRequest): Promise<DeleteDataResponse>;
1397+
1398+
// Batch Operations (optional)
1399+
batchData?(request: BatchDataRequest): Promise<BatchDataResponse>;
1400+
createManyData?(request: CreateManyDataRequest): Promise<CreateManyDataResponse>;
1401+
updateManyData?(request: UpdateManyDataRequest): Promise<UpdateManyDataResponse>;
1402+
deleteManyData?(request: DeleteManyDataRequest): Promise<DeleteManyDataResponse>;
1403+
}
1404+
1405+
/** Discovery + metadata (sys_metadata) management. */
1406+
export interface MetadataProtocol {
13801407
// Discovery & Metadata (core)
13811408
getDiscovery(request?: GetDiscoveryRequest): Promise<GetDiscoveryResponse>;
13821409
getMetaTypes(request?: GetMetaTypesRequest): Promise<GetMetaTypesResponse>;
@@ -1392,80 +1419,89 @@ export interface ObjectStackProtocol {
13921419
deleteMetaItem?(request: DeleteMetaItemRequest): Promise<DeleteMetaItemResponse>;
13931420
getMetaItemCached?(request: GetMetaItemCachedRequest): Promise<GetMetaItemCachedResponse>;
13941421
getUiView?(request: GetUiViewRequest): Promise<GetUiViewResponse>;
1395-
1396-
// Analytics (optional)
1422+
}
1423+
1424+
/** Analytics (optional). */
1425+
export interface AnalyticsProtocol {
13971426
analyticsQuery?(request: AnalyticsQueryRequest): Promise<AnalyticsResultResponse>;
13981427
getAnalyticsMeta?(request: GetAnalyticsMetaRequest): Promise<GetAnalyticsMetaResponse>;
1428+
}
13991429

1400-
// Automation (optional)
1430+
/** Automation (optional). */
1431+
export interface AutomationProtocol {
14011432
triggerAutomation?(request: AutomationTriggerRequest): Promise<AutomationTriggerResponse>;
1433+
}
14021434

1403-
// Package Management (optional)
1435+
/** Package lifecycle (optional). */
1436+
export interface PackageProtocol {
14041437
listPackages?(request: ListPackagesRequest): Promise<ListPackagesResponse>;
14051438
getPackage?(request: GetPackageRequest): Promise<GetPackageResponse>;
14061439
installPackage?(request: InstallPackageRequest): Promise<InstallPackageResponse>;
14071440
uninstallPackage?(request: UninstallPackageRequest): Promise<UninstallPackageResponse>;
14081441
enablePackage?(request: EnablePackageRequest): Promise<EnablePackageResponse>;
14091442
disablePackage?(request: DisablePackageRequest): Promise<DisablePackageResponse>;
1443+
}
14101444

1411-
// Data Operations (core)
1412-
findData(request: FindDataRequest): Promise<FindDataResponse>;
1413-
getData(request: GetDataRequest): Promise<GetDataResponse>;
1414-
createData(request: CreateDataRequest): Promise<CreateDataResponse>;
1415-
updateData(request: UpdateDataRequest): Promise<UpdateDataResponse>;
1416-
deleteData(request: DeleteDataRequest): Promise<DeleteDataResponse>;
1417-
1418-
// Batch Operations (optional)
1419-
batchData?(request: BatchDataRequest): Promise<BatchDataResponse>;
1420-
createManyData?(request: CreateManyDataRequest): Promise<CreateManyDataResponse>;
1421-
updateManyData?(request: UpdateManyDataRequest): Promise<UpdateManyDataResponse>;
1422-
deleteManyData?(request: DeleteManyDataRequest): Promise<DeleteManyDataResponse>;
1423-
1424-
// View Management (optional)
1445+
/** View management (optional). */
1446+
export interface ViewProtocol {
14251447
listViews?(request: ListViewsRequest): Promise<ListViewsResponse>;
14261448
getView?(request: GetViewRequest): Promise<GetViewResponse>;
14271449
createView?(request: CreateViewRequest): Promise<CreateViewResponse>;
14281450
updateView?(request: UpdateViewRequest): Promise<UpdateViewResponse>;
14291451
deleteView?(request: DeleteViewRequest): Promise<DeleteViewResponse>;
1452+
}
14301453

1431-
// Permissions (optional)
1454+
/** Permissions (optional). */
1455+
export interface PermissionProtocol {
14321456
checkPermission?(request: CheckPermissionRequest): Promise<CheckPermissionResponse>;
14331457
getObjectPermissions?(request: GetObjectPermissionsRequest): Promise<GetObjectPermissionsResponse>;
14341458
getEffectivePermissions?(request: GetEffectivePermissionsRequest): Promise<GetEffectivePermissionsResponse>;
1459+
}
14351460

1436-
// Workflows (optional)
1461+
/** Workflows (optional). */
1462+
export interface WorkflowProtocol {
14371463
getWorkflowConfig?(request: GetWorkflowConfigRequest): Promise<GetWorkflowConfigResponse>;
14381464
getWorkflowState?(request: GetWorkflowStateRequest): Promise<GetWorkflowStateResponse>;
14391465
workflowTransition?(request: WorkflowTransitionRequest): Promise<WorkflowTransitionResponse>;
1466+
}
14401467

1441-
// Realtime (optional)
1468+
/** Realtime / presence (optional). */
1469+
export interface RealtimeProtocol {
14421470
realtimeConnect?(request: RealtimeConnectRequest): Promise<RealtimeConnectResponse>;
14431471
realtimeDisconnect?(request: RealtimeDisconnectRequest): Promise<RealtimeDisconnectResponse>;
14441472
realtimeSubscribe?(request: RealtimeSubscribeRequest): Promise<RealtimeSubscribeResponse>;
14451473
realtimeUnsubscribe?(request: RealtimeUnsubscribeRequest): Promise<RealtimeUnsubscribeResponse>;
14461474
setPresence?(request: SetPresenceRequest): Promise<SetPresenceResponse>;
14471475
getPresence?(request: GetPresenceRequest): Promise<GetPresenceResponse>;
1476+
}
14481477

1449-
// Notifications (optional)
1478+
/** Notifications (optional). */
1479+
export interface NotificationProtocol {
14501480
registerDevice?(request: RegisterDeviceRequest): Promise<RegisterDeviceResponse>;
14511481
unregisterDevice?(request: UnregisterDeviceRequest): Promise<UnregisterDeviceResponse>;
14521482
getNotificationPreferences?(request: GetNotificationPreferencesRequest): Promise<GetNotificationPreferencesResponse>;
14531483
updateNotificationPreferences?(request: UpdateNotificationPreferencesRequest): Promise<UpdateNotificationPreferencesResponse>;
14541484
listNotifications?(request: ListNotificationsRequest): Promise<ListNotificationsResponse>;
14551485
markNotificationsRead?(request: MarkNotificationsReadRequest): Promise<MarkNotificationsReadResponse>;
14561486
markAllNotificationsRead?(request: MarkAllNotificationsReadRequest): Promise<MarkAllNotificationsReadResponse>;
1487+
}
14571488

1458-
// AI (optional — chat is now handled by Vercel AI SDK wire protocol)
1489+
/** AI (optional — chat is now handled by the Vercel AI SDK wire protocol). */
1490+
export interface AiProtocol {
14591491
aiNlq?(request: AiNlqRequest): Promise<AiNlqResponse>;
14601492
aiSuggest?(request: AiSuggestRequest): Promise<AiSuggestResponse>;
14611493
aiInsights?(request: AiInsightsRequest): Promise<AiInsightsResponse>;
1494+
}
14621495

1463-
// i18n (optional)
1496+
/** Localization (optional). */
1497+
export interface I18nProtocol {
14641498
getLocales?(request: GetLocalesRequest): Promise<GetLocalesResponse>;
14651499
getTranslations?(request: GetTranslationsRequest): Promise<GetTranslationsResponse>;
14661500
getFieldLabels?(request: GetFieldLabelsRequest): Promise<GetFieldLabelsResponse>;
1501+
}
14671502

1468-
// Feed (optional)
1503+
/** Feed / social (optional). */
1504+
export interface FeedProtocol {
14691505
listFeed?(request: GetFeedRequest): Promise<GetFeedResponse>;
14701506
createFeedItem?(request: CreateFeedItemRequest): Promise<CreateFeedItemResponse>;
14711507
updateFeedItem?(request: UpdateFeedItemRequest): Promise<UpdateFeedItemResponse>;
@@ -1481,3 +1517,26 @@ export interface ObjectStackProtocol {
14811517
feedSubscribe?(request: SubscribeRequest): Promise<SubscribeResponse>;
14821518
feedUnsubscribe?(request: FeedUnsubscribeRequest): Promise<UnsubscribeResponse>;
14831519
}
1520+
1521+
/**
1522+
* ObjectStackProtocol — composition of the per-domain contracts above
1523+
* (ADR-0076 D9). Shape-identical to the historical flat interface, so every
1524+
* existing implementation/consumer is unaffected. Prefer depending on the
1525+
* narrowest slice (e.g. `DataProtocol`). Per ADR-0076 D9 (rev.7) this union is
1526+
* transitional; the end-state dissolves it (capability availability comes from
1527+
* the discovery `services` registry, not a static union).
1528+
*/
1529+
export interface ObjectStackProtocol extends
1530+
DataProtocol,
1531+
MetadataProtocol,
1532+
AnalyticsProtocol,
1533+
AutomationProtocol,
1534+
PackageProtocol,
1535+
ViewProtocol,
1536+
PermissionProtocol,
1537+
WorkflowProtocol,
1538+
RealtimeProtocol,
1539+
NotificationProtocol,
1540+
AiProtocol,
1541+
I18nProtocol,
1542+
FeedProtocol {}

0 commit comments

Comments
 (0)