@lucern/contracts 0.1.1-alpha.1 → 0.1.2-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (151) hide show
  1. package/CHANGELOG.md +3 -0
  2. package/README.md +3 -0
  3. package/dist/agents/v1.d.ts +2 -0
  4. package/dist/agents/v1.js +3 -0
  5. package/dist/agents/v1.js.map +1 -0
  6. package/dist/api-enums.contract.d.ts +60 -0
  7. package/dist/api-enums.contract.js +174 -0
  8. package/dist/api-enums.contract.js.map +1 -0
  9. package/dist/auth-context.contract.d.ts +2 -0
  10. package/dist/auth-context.contract.js +48 -0
  11. package/dist/auth-context.contract.js.map +1 -0
  12. package/dist/auth-session.contract.d.ts +2 -0
  13. package/dist/auth-session.contract.js +48 -0
  14. package/dist/auth-session.contract.js.map +1 -0
  15. package/dist/auth.contract.d.ts +92 -0
  16. package/dist/auth.contract.js +48 -0
  17. package/dist/auth.contract.js.map +1 -0
  18. package/dist/beliefs/v1.d.ts +2 -0
  19. package/dist/beliefs/v1.js +3 -0
  20. package/dist/beliefs/v1.js.map +1 -0
  21. package/dist/context-pack.contract.d.ts +496 -0
  22. package/dist/context-pack.contract.js +98 -0
  23. package/dist/context-pack.contract.js.map +1 -0
  24. package/dist/convex-admin.contract.d.ts +7 -0
  25. package/dist/convex-admin.contract.js +3 -0
  26. package/dist/convex-admin.contract.js.map +1 -0
  27. package/dist/events-types.contract.d.ts +1 -0
  28. package/dist/events-types.contract.js +136 -0
  29. package/dist/events-types.contract.js.map +1 -0
  30. package/dist/events.contract.d.ts +178 -0
  31. package/dist/events.contract.js +136 -0
  32. package/dist/events.contract.js.map +1 -0
  33. package/dist/evidence/v1.d.ts +2 -0
  34. package/dist/evidence/v1.js +3 -0
  35. package/dist/evidence/v1.js.map +1 -0
  36. package/dist/gateway.contract.d.ts +79 -0
  37. package/dist/gateway.contract.js +12 -0
  38. package/dist/gateway.contract.js.map +1 -0
  39. package/dist/graph/v1.d.ts +2 -0
  40. package/dist/graph/v1.js +3 -0
  41. package/dist/graph/v1.js.map +1 -0
  42. package/dist/ids.contract.d.ts +9 -0
  43. package/{src/ids.contract.ts → dist/ids.contract.js} +10 -17
  44. package/dist/ids.contract.js.map +1 -0
  45. package/dist/index.d.ts +15 -2004
  46. package/dist/index.js +61 -118
  47. package/dist/index.js.map +1 -0
  48. package/dist/lens-filter.contract.d.ts +72 -0
  49. package/dist/lens-filter.contract.js +71 -0
  50. package/dist/lens-filter.contract.js.map +1 -0
  51. package/dist/lens-workflow.contract.d.ts +87 -0
  52. package/dist/lens-workflow.contract.js +123 -0
  53. package/dist/lens-workflow.contract.js.map +1 -0
  54. package/dist/mcp-tools.contract-D8kXcP6d.d.ts +254 -0
  55. package/dist/mcp-tools.contract.d.ts +1 -0
  56. package/dist/mcp-tools.contract.js +3016 -0
  57. package/dist/mcp-tools.contract.js.map +1 -0
  58. package/dist/ontologies/v1.d.ts +2 -0
  59. package/dist/ontologies/v1.js +3 -0
  60. package/dist/ontologies/v1.js.map +1 -0
  61. package/dist/ontology-matching.contract.d.ts +1 -0
  62. package/dist/ontology-matching.contract.js +346 -0
  63. package/dist/ontology-matching.contract.js.map +1 -0
  64. package/dist/prompt.contract.d.ts +26 -0
  65. package/dist/prompt.contract.js +12 -0
  66. package/dist/prompt.contract.js.map +1 -0
  67. package/dist/questions/v1.d.ts +2 -0
  68. package/dist/questions/v1.js +3 -0
  69. package/dist/questions/v1.js.map +1 -0
  70. package/dist/sdk-methods.contract.d.ts +376 -0
  71. package/dist/sdk-methods.contract.js +3 -0
  72. package/dist/sdk-methods.contract.js.map +1 -0
  73. package/dist/sdk-tools.contract-BnV0hKLp.d.ts +150 -0
  74. package/dist/sdk-tools.contract.d.ts +2 -0
  75. package/dist/sdk-tools.contract.js +4252 -0
  76. package/dist/sdk-tools.contract.js.map +1 -0
  77. package/dist/text-matching.contract.d.ts +55 -0
  78. package/{src/text-matching.contract.ts → dist/text-matching.contract.js} +36 -137
  79. package/dist/text-matching.contract.js.map +1 -0
  80. package/dist/topic-scope.contract.d.ts +1 -0
  81. package/{src/v1/topics/v1.ts → dist/topic-scope.contract.js} +13 -38
  82. package/dist/topic-scope.contract.js.map +1 -0
  83. package/dist/topics/v1.d.ts +2 -0
  84. package/dist/topics/v1.js +3 -0
  85. package/dist/topics/v1.js.map +1 -0
  86. package/dist/v1/agents/v1.d.ts +2 -0
  87. package/dist/v1/agents/v1.js +3 -0
  88. package/dist/v1/agents/v1.js.map +1 -0
  89. package/dist/v1/beliefs/v1.d.ts +2 -0
  90. package/dist/v1/beliefs/v1.js +3 -0
  91. package/dist/v1/beliefs/v1.js.map +1 -0
  92. package/dist/v1/evidence/v1.d.ts +2 -0
  93. package/dist/v1/evidence/v1.js +3 -0
  94. package/dist/v1/evidence/v1.js.map +1 -0
  95. package/dist/v1/graph/v1.d.ts +2 -0
  96. package/dist/v1/graph/v1.js +3 -0
  97. package/dist/v1/graph/v1.js.map +1 -0
  98. package/dist/v1/ontologies/v1.d.ts +78 -0
  99. package/dist/v1/ontologies/v1.js +346 -0
  100. package/dist/v1/ontologies/v1.js.map +1 -0
  101. package/dist/v1/questions/v1.d.ts +2 -0
  102. package/dist/v1/questions/v1.js +3 -0
  103. package/dist/v1/questions/v1.js.map +1 -0
  104. package/dist/v1/topics/v1.d.ts +21 -0
  105. package/dist/v1/topics/v1.js +54 -0
  106. package/dist/v1/topics/v1.js.map +1 -0
  107. package/dist/v1/worktrees/v1.d.ts +2 -0
  108. package/dist/v1/worktrees/v1.js +3 -0
  109. package/dist/v1/worktrees/v1.js.map +1 -0
  110. package/dist/workflow-runtime.contract.d.ts +163 -0
  111. package/dist/workflow-runtime.contract.js +245 -0
  112. package/dist/workflow-runtime.contract.js.map +1 -0
  113. package/dist/worktrees/v1.d.ts +2 -0
  114. package/dist/worktrees/v1.js +3 -0
  115. package/dist/worktrees/v1.js.map +1 -0
  116. package/package.json +23 -7
  117. package/src/agents/v1.ts +0 -8
  118. package/src/api-enums.contract.ts +0 -183
  119. package/src/auth-context.contract.ts +0 -9
  120. package/src/auth-session.contract.ts +0 -9
  121. package/src/auth.contract.ts +0 -162
  122. package/src/beliefs/v1.ts +0 -8
  123. package/src/context-pack.contract.ts +0 -704
  124. package/src/convex-admin.contract.ts +0 -14
  125. package/src/events-types.contract.ts +0 -9
  126. package/src/events.contract.ts +0 -376
  127. package/src/evidence/v1.ts +0 -8
  128. package/src/gateway.contract.ts +0 -151
  129. package/src/graph/v1.ts +0 -8
  130. package/src/index.ts +0 -30
  131. package/src/lens-filter.contract.ts +0 -183
  132. package/src/lens-workflow.contract.ts +0 -162
  133. package/src/mcp-tools.contract.ts +0 -3636
  134. package/src/ontologies/v1.ts +0 -8
  135. package/src/ontology-matching.contract.ts +0 -9
  136. package/src/prompt.contract.ts +0 -50
  137. package/src/questions/v1.ts +0 -8
  138. package/src/sdk-methods.contract.ts +0 -522
  139. package/src/sdk-tools.contract.ts +0 -1545
  140. package/src/topic-scope.contract.ts +0 -9
  141. package/src/topics/v1.ts +0 -8
  142. package/src/v1/agents/v1.ts +0 -8
  143. package/src/v1/beliefs/v1.ts +0 -8
  144. package/src/v1/evidence/v1.ts +0 -8
  145. package/src/v1/graph/v1.ts +0 -8
  146. package/src/v1/ontologies/v1.ts +0 -276
  147. package/src/v1/questions/v1.ts +0 -8
  148. package/src/v1/worktrees/v1.ts +0 -8
  149. package/src/workflow-runtime.contract.ts +0 -440
  150. package/src/worktrees/v1.ts +0 -8
  151. package/tsconfig.json +0 -9
@@ -0,0 +1,136 @@
1
+ // src/events.contract.ts
2
+ var DOMAIN_EVENT_VERSION = "1.0";
3
+ var EVENT_RETENTION_DEFAULT_DAYS = 30;
4
+ var WEBHOOK_MAX_ATTEMPTS = 5;
5
+ var WEBHOOK_RETRY_DELAYS_MS = [1e3, 5e3, 3e4, 3e5];
6
+ var DOMAIN_EVENT_TYPES = [
7
+ "belief.created",
8
+ "belief.forked",
9
+ "belief.confidence_updated",
10
+ "belief.archived",
11
+ "belief.refined",
12
+ "belief.contract_created",
13
+ "belief.contract_evaluated",
14
+ "belief.lineage_queried",
15
+ "evidence.created",
16
+ "evidence.linked",
17
+ "evidence.search_executed",
18
+ "question.created",
19
+ "question.answered",
20
+ "question.refined",
21
+ "question.status_updated",
22
+ "question.archived",
23
+ "edge.created",
24
+ "contradiction.flagged",
25
+ "worktree.created",
26
+ "worktree.activated",
27
+ "worktree.merged",
28
+ "worktree.targets_updated",
29
+ "worktree.metadata_updated",
30
+ "topic.created",
31
+ "topic.updated",
32
+ "topic.archived",
33
+ "task.created",
34
+ "task.completed",
35
+ "task.updated",
36
+ "ontology.bound",
37
+ "context.compiled",
38
+ "identity.key_created",
39
+ "identity.key_rotated",
40
+ "identity.key_revoked",
41
+ "webhook.test"
42
+ ];
43
+ function toBase64(value) {
44
+ if (typeof Buffer !== "undefined") {
45
+ return Buffer.from(value, "utf8").toString("base64url");
46
+ }
47
+ return btoa(unescape(encodeURIComponent(value))).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "");
48
+ }
49
+ function fromBase64(value) {
50
+ if (typeof Buffer !== "undefined") {
51
+ return Buffer.from(value, "base64url").toString("utf8");
52
+ }
53
+ const normalized = value.replace(/-/g, "+").replace(/_/g, "/");
54
+ return decodeURIComponent(escape(atob(normalized)));
55
+ }
56
+ function createEventId() {
57
+ const random = crypto.randomUUID().replace(/-/g, "");
58
+ return `evt_${random}`;
59
+ }
60
+ function normalizeRetentionDays(value) {
61
+ if (!Number.isFinite(value) || typeof value !== "number" || value <= 0) {
62
+ return EVENT_RETENTION_DEFAULT_DAYS;
63
+ }
64
+ return Math.max(1, Math.trunc(value));
65
+ }
66
+ function buildDomainEvent(input) {
67
+ const timestamp = input.timestamp ?? Date.now();
68
+ const retentionDays = normalizeRetentionDays(input.retentionDays);
69
+ return {
70
+ eventId: input.eventId?.trim() || createEventId(),
71
+ type: input.type.trim(),
72
+ version: DOMAIN_EVENT_VERSION,
73
+ timestamp,
74
+ tenantId: input.tenantId?.trim() || void 0,
75
+ workspaceId: input.workspaceId?.trim() || void 0,
76
+ topicId: input.topicId.trim(),
77
+ resourceId: input.resourceId.trim(),
78
+ resourceType: input.resourceType.trim(),
79
+ actorId: input.actorId.trim(),
80
+ actorType: input.actorType,
81
+ data: input.data ?? {},
82
+ correlationId: input.correlationId?.trim() || void 0,
83
+ expiresAt: timestamp + retentionDays * 24 * 60 * 60 * 1e3
84
+ };
85
+ }
86
+ function compareEventCursor(left, right) {
87
+ if (left.timestamp !== right.timestamp) {
88
+ return left.timestamp - right.timestamp;
89
+ }
90
+ return left.eventId.localeCompare(right.eventId);
91
+ }
92
+ function encodeEventCursor(cursor) {
93
+ return toBase64(JSON.stringify(cursor));
94
+ }
95
+ function decodeEventCursor(cursor) {
96
+ if (!cursor || cursor.trim().length === 0) {
97
+ return null;
98
+ }
99
+ try {
100
+ const parsed = JSON.parse(fromBase64(cursor.trim()));
101
+ if (typeof parsed.timestamp !== "number" || !Number.isFinite(parsed.timestamp) || typeof parsed.eventId !== "string" || parsed.eventId.trim().length === 0) {
102
+ return null;
103
+ }
104
+ return {
105
+ timestamp: parsed.timestamp,
106
+ eventId: parsed.eventId.trim()
107
+ };
108
+ } catch {
109
+ return null;
110
+ }
111
+ }
112
+ function isAfterCursor(event, cursor) {
113
+ if (!cursor) {
114
+ return true;
115
+ }
116
+ return compareEventCursor(event, cursor) > 0;
117
+ }
118
+ function sortEventsByCursor(events) {
119
+ return [...events].sort((left, right) => compareEventCursor(left, right));
120
+ }
121
+ function inferActorType(args) {
122
+ if (args.sessionType === "agent") {
123
+ return "agent";
124
+ }
125
+ if (args.authMode === "service_principal" || args.authMode === "tenant_api_key" || args.principalType === "service") {
126
+ return "service";
127
+ }
128
+ return "human";
129
+ }
130
+ async function emitDomainEvent(invokeMutation, input) {
131
+ return await invokeMutation("events:recordEvent", input);
132
+ }
133
+
134
+ export { DOMAIN_EVENT_TYPES, DOMAIN_EVENT_VERSION, EVENT_RETENTION_DEFAULT_DAYS, WEBHOOK_MAX_ATTEMPTS, WEBHOOK_RETRY_DELAYS_MS, buildDomainEvent, compareEventCursor, createEventId, decodeEventCursor, emitDomainEvent, encodeEventCursor, inferActorType, isAfterCursor, normalizeRetentionDays, sortEventsByCursor };
135
+ //# sourceMappingURL=events-types.contract.js.map
136
+ //# sourceMappingURL=events-types.contract.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/events.contract.ts"],"names":[],"mappings":"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","file":"events-types.contract.js","sourcesContent":["/**\n * @lucern/contracts — events (canonical support contract)\n *\n * Consolidated flat support surface for Lucern's domain event stream:\n * - Event type definitions, constants, and shared enums\n * - Event construction + cursor helpers\n *\n * Consolidated from the former split type-definition module\n * and the prior src/events.contract.ts (helpers) in EK-16 T1 PR 3b.\n * Compat shim remains at the old events-types path until Lucern 1.0.0 (D12).\n */\n\n// =============================================================================\n// EVENT TYPE DEFINITIONS & CONSTANTS\n// (Formerly the split events type-definition module)\n// =============================================================================\n\nexport const DOMAIN_EVENT_VERSION = \"1.0\" as const;\nexport const EVENT_RETENTION_DEFAULT_DAYS = 30;\nexport const WEBHOOK_MAX_ATTEMPTS = 5;\nexport const WEBHOOK_RETRY_DELAYS_MS = [1_000, 5_000, 30_000, 300_000] as const;\n\nexport const DOMAIN_EVENT_TYPES = [\n \"belief.created\",\n \"belief.forked\",\n \"belief.confidence_updated\",\n \"belief.archived\",\n \"belief.refined\",\n \"belief.contract_created\",\n \"belief.contract_evaluated\",\n \"belief.lineage_queried\",\n \"evidence.created\",\n \"evidence.linked\",\n \"evidence.search_executed\",\n \"question.created\",\n \"question.answered\",\n \"question.refined\",\n \"question.status_updated\",\n \"question.archived\",\n \"edge.created\",\n \"contradiction.flagged\",\n \"worktree.created\",\n \"worktree.activated\",\n \"worktree.merged\",\n \"worktree.targets_updated\",\n \"worktree.metadata_updated\",\n \"topic.created\",\n \"topic.updated\",\n \"topic.archived\",\n \"task.created\",\n \"task.completed\",\n \"task.updated\",\n \"ontology.bound\",\n \"context.compiled\",\n \"identity.key_created\",\n \"identity.key_rotated\",\n \"identity.key_revoked\",\n \"webhook.test\",\n] as const;\n\nexport type DomainEventType = (typeof DOMAIN_EVENT_TYPES)[number];\n\nexport type DomainResourceType =\n | \"belief\"\n | \"evidence\"\n | \"question\"\n | \"edge\"\n | \"contradiction\"\n | \"worktree\"\n | \"topic\"\n | \"task\"\n | \"ontology\"\n | \"context\"\n | \"identity\"\n | \"webhook\";\n\nexport type DomainActorType = \"human\" | \"agent\" | \"service\";\n\nexport type DomainEventData = Record<string, unknown>;\n\nexport type DomainEvent = {\n eventId: string;\n type: DomainEventType | string;\n version: typeof DOMAIN_EVENT_VERSION;\n timestamp: number;\n tenantId?: string;\n workspaceId?: string;\n topicId: string;\n resourceId: string;\n resourceType: DomainResourceType | string;\n actorId: string;\n actorType: DomainActorType;\n data: DomainEventData;\n correlationId?: string;\n expiresAt: number;\n};\n\nexport type CreateDomainEventInput = {\n eventId?: string;\n timestamp?: number;\n tenantId?: string;\n workspaceId?: string;\n topicId: string;\n type: DomainEventType | string;\n resourceId: string;\n resourceType: DomainResourceType | string;\n actorId: string;\n actorType: DomainActorType;\n data?: DomainEventData;\n correlationId?: string;\n retentionDays?: number;\n};\n\nexport type EventCursor = {\n timestamp: number;\n eventId: string;\n};\n\nexport type EventListQuery = {\n topicId?: string;\n after?: string;\n types?: string[];\n startTime?: number;\n endTime?: number;\n limit?: number;\n};\n\nexport type EventListResult = {\n events: DomainEvent[];\n nextCursor: string | null;\n};\n\nexport type WebhookSecretMode = \"configured\";\n\nexport type WebhookRecord = {\n id: string;\n webhookId: string;\n tenantId?: string;\n workspaceId?: string;\n topicId?: string;\n url: string;\n events: string[];\n active: boolean;\n secretConfigured: boolean;\n createdAt: number;\n updatedAt: number;\n createdBy: string;\n updatedBy: string;\n lastDeliveryAt?: number;\n lastSuccessfulDeliveryAt?: number;\n};\n\nexport type WebhookCreateInput = {\n url: string;\n events: string[];\n secret: string;\n topicId?: string;\n active?: boolean;\n};\n\nexport type WebhookUpdateInput = {\n url?: string;\n events?: string[];\n secret?: string;\n topicId?: string | null;\n active?: boolean;\n};\n\nexport type WebhookDeliveryStatus =\n | \"pending\"\n | \"delivering\"\n | \"succeeded\"\n | \"failed\"\n | \"dead_letter\";\n\nexport type WebhookDeliveryRecord = {\n id: string;\n deliveryId: string;\n webhookId: string;\n eventId: string;\n eventType: string;\n topicId: string;\n status: WebhookDeliveryStatus;\n attemptCount: number;\n maxAttempts: number;\n nextAttemptAt?: number;\n lastAttemptAt?: number;\n lastStatusCode?: number;\n lastError?: string;\n deliveredAt?: number;\n createdAt: number;\n updatedAt: number;\n};\n\nexport type WebhookDeliveryAttemptRecord = {\n id: string;\n attemptId: string;\n deliveryId: string;\n webhookId: string;\n eventId: string;\n eventType: string;\n attemptNumber: number;\n status: \"succeeded\" | \"failed\";\n statusCode?: number;\n error?: string;\n responseBody?: string;\n durationMs?: number;\n createdAt: number;\n};\n\nexport type WebhookDeliveriesResult = {\n deliveries: Array<\n WebhookDeliveryRecord & {\n attempts?: WebhookDeliveryAttemptRecord[];\n }\n >;\n};\n\nexport type WebhookHealthResult = {\n webhookId: string;\n totalAttempts: number;\n successfulAttempts: number;\n failedAttempts: number;\n successRate: number;\n pendingDeliveries: number;\n deadLetterDeliveries: number;\n lastDeliveryAt?: number;\n lastSuccessfulDeliveryAt?: number;\n};\n\nexport type WebhookTestResult = {\n webhookId: string;\n deliveryId: string;\n status: WebhookDeliveryStatus;\n attempts: number;\n};\n\nexport type ReplayEventsInput = EventListQuery & {\n webhookId?: string;\n};\n\nexport type ReplayEventsResult = EventListResult & {\n replayedDeliveries?: number;\n replayedWebhookId?: string;\n};\n\n// =============================================================================\n// EVENT HELPERS\n// (Formerly the body of src/events.contract.ts)\n// =============================================================================\n\nfunction toBase64(value: string): string {\n if (typeof Buffer !== \"undefined\") {\n return Buffer.from(value, \"utf8\").toString(\"base64url\");\n }\n return btoa(unescape(encodeURIComponent(value)))\n .replace(/\\+/g, \"-\")\n .replace(/\\//g, \"_\")\n .replace(/=+$/g, \"\");\n}\n\nfunction fromBase64(value: string): string {\n if (typeof Buffer !== \"undefined\") {\n return Buffer.from(value, \"base64url\").toString(\"utf8\");\n }\n const normalized = value.replace(/-/g, \"+\").replace(/_/g, \"/\");\n return decodeURIComponent(escape(atob(normalized)));\n}\n\nexport function createEventId(): string {\n const random = crypto.randomUUID().replace(/-/g, \"\");\n return `evt_${random}`;\n}\n\nexport function normalizeRetentionDays(value: number | undefined): number {\n if (!Number.isFinite(value) || typeof value !== \"number\" || value <= 0) {\n return EVENT_RETENTION_DEFAULT_DAYS;\n }\n return Math.max(1, Math.trunc(value));\n}\n\nexport function buildDomainEvent(input: CreateDomainEventInput): DomainEvent {\n const timestamp = input.timestamp ?? Date.now();\n const retentionDays = normalizeRetentionDays(input.retentionDays);\n return {\n eventId: input.eventId?.trim() || createEventId(),\n type: input.type.trim(),\n version: DOMAIN_EVENT_VERSION,\n timestamp,\n tenantId: input.tenantId?.trim() || undefined,\n workspaceId: input.workspaceId?.trim() || undefined,\n topicId: input.topicId.trim(),\n resourceId: input.resourceId.trim(),\n resourceType: input.resourceType.trim(),\n actorId: input.actorId.trim(),\n actorType: input.actorType,\n data: input.data ?? {},\n correlationId: input.correlationId?.trim() || undefined,\n expiresAt: timestamp + retentionDays * 24 * 60 * 60 * 1000,\n };\n}\n\nexport function compareEventCursor(left: EventCursor, right: EventCursor): number {\n if (left.timestamp !== right.timestamp) {\n return left.timestamp - right.timestamp;\n }\n return left.eventId.localeCompare(right.eventId);\n}\n\nexport function encodeEventCursor(cursor: EventCursor): string {\n return toBase64(JSON.stringify(cursor));\n}\n\nexport function decodeEventCursor(cursor: string | undefined): EventCursor | null {\n if (!cursor || cursor.trim().length === 0) {\n return null;\n }\n try {\n const parsed = JSON.parse(fromBase64(cursor.trim())) as Partial<EventCursor>;\n if (\n typeof parsed.timestamp !== \"number\" ||\n !Number.isFinite(parsed.timestamp) ||\n typeof parsed.eventId !== \"string\" ||\n parsed.eventId.trim().length === 0\n ) {\n return null;\n }\n return {\n timestamp: parsed.timestamp,\n eventId: parsed.eventId.trim(),\n };\n } catch {\n return null;\n }\n}\n\nexport function isAfterCursor(\n event: Pick<DomainEvent, \"timestamp\" | \"eventId\">,\n cursor: EventCursor | null\n): boolean {\n if (!cursor) {\n return true;\n }\n return compareEventCursor(event, cursor) > 0;\n}\n\nexport function sortEventsByCursor<T extends Pick<DomainEvent, \"timestamp\" | \"eventId\">>(\n events: readonly T[]\n): T[] {\n return [...events].sort((left, right) => compareEventCursor(left, right));\n}\n\nexport function inferActorType(args: {\n sessionType?: \"agent\" | \"user\";\n authMode?: string;\n principalType?: string;\n}): DomainActorType {\n if (args.sessionType === \"agent\") {\n return \"agent\";\n }\n if (\n args.authMode === \"service_principal\" ||\n args.authMode === \"tenant_api_key\" ||\n args.principalType === \"service\"\n ) {\n return \"service\";\n }\n return \"human\";\n}\n\nexport async function emitDomainEvent(\n invokeMutation: (reference: any, args: CreateDomainEventInput) => Promise<unknown>,\n input: CreateDomainEventInput\n): Promise<unknown> {\n return await invokeMutation(\"events:recordEvent\" as any, input);\n}\n"]}
@@ -0,0 +1,178 @@
1
+ /**
2
+ * @lucern/contracts — events (canonical support contract)
3
+ *
4
+ * Consolidated flat support surface for Lucern's domain event stream:
5
+ * - Event type definitions, constants, and shared enums
6
+ * - Event construction + cursor helpers
7
+ *
8
+ * Consolidated from the former split type-definition module
9
+ * and the prior src/events.contract.ts (helpers) in EK-16 T1 PR 3b.
10
+ * Compat shim remains at the old events-types path until Lucern 1.0.0 (D12).
11
+ */
12
+ declare const DOMAIN_EVENT_VERSION: "1.0";
13
+ declare const EVENT_RETENTION_DEFAULT_DAYS = 30;
14
+ declare const WEBHOOK_MAX_ATTEMPTS = 5;
15
+ declare const WEBHOOK_RETRY_DELAYS_MS: readonly [1000, 5000, 30000, 300000];
16
+ declare const DOMAIN_EVENT_TYPES: readonly ["belief.created", "belief.forked", "belief.confidence_updated", "belief.archived", "belief.refined", "belief.contract_created", "belief.contract_evaluated", "belief.lineage_queried", "evidence.created", "evidence.linked", "evidence.search_executed", "question.created", "question.answered", "question.refined", "question.status_updated", "question.archived", "edge.created", "contradiction.flagged", "worktree.created", "worktree.activated", "worktree.merged", "worktree.targets_updated", "worktree.metadata_updated", "topic.created", "topic.updated", "topic.archived", "task.created", "task.completed", "task.updated", "ontology.bound", "context.compiled", "identity.key_created", "identity.key_rotated", "identity.key_revoked", "webhook.test"];
17
+ type DomainEventType = (typeof DOMAIN_EVENT_TYPES)[number];
18
+ type DomainResourceType = "belief" | "evidence" | "question" | "edge" | "contradiction" | "worktree" | "topic" | "task" | "ontology" | "context" | "identity" | "webhook";
19
+ type DomainActorType = "human" | "agent" | "service";
20
+ type DomainEventData = Record<string, unknown>;
21
+ type DomainEvent = {
22
+ eventId: string;
23
+ type: DomainEventType | string;
24
+ version: typeof DOMAIN_EVENT_VERSION;
25
+ timestamp: number;
26
+ tenantId?: string;
27
+ workspaceId?: string;
28
+ topicId: string;
29
+ resourceId: string;
30
+ resourceType: DomainResourceType | string;
31
+ actorId: string;
32
+ actorType: DomainActorType;
33
+ data: DomainEventData;
34
+ correlationId?: string;
35
+ expiresAt: number;
36
+ };
37
+ type CreateDomainEventInput = {
38
+ eventId?: string;
39
+ timestamp?: number;
40
+ tenantId?: string;
41
+ workspaceId?: string;
42
+ topicId: string;
43
+ type: DomainEventType | string;
44
+ resourceId: string;
45
+ resourceType: DomainResourceType | string;
46
+ actorId: string;
47
+ actorType: DomainActorType;
48
+ data?: DomainEventData;
49
+ correlationId?: string;
50
+ retentionDays?: number;
51
+ };
52
+ type EventCursor = {
53
+ timestamp: number;
54
+ eventId: string;
55
+ };
56
+ type EventListQuery = {
57
+ topicId?: string;
58
+ after?: string;
59
+ types?: string[];
60
+ startTime?: number;
61
+ endTime?: number;
62
+ limit?: number;
63
+ };
64
+ type EventListResult = {
65
+ events: DomainEvent[];
66
+ nextCursor: string | null;
67
+ };
68
+ type WebhookSecretMode = "configured";
69
+ type WebhookRecord = {
70
+ id: string;
71
+ webhookId: string;
72
+ tenantId?: string;
73
+ workspaceId?: string;
74
+ topicId?: string;
75
+ url: string;
76
+ events: string[];
77
+ active: boolean;
78
+ secretConfigured: boolean;
79
+ createdAt: number;
80
+ updatedAt: number;
81
+ createdBy: string;
82
+ updatedBy: string;
83
+ lastDeliveryAt?: number;
84
+ lastSuccessfulDeliveryAt?: number;
85
+ };
86
+ type WebhookCreateInput = {
87
+ url: string;
88
+ events: string[];
89
+ secret: string;
90
+ topicId?: string;
91
+ active?: boolean;
92
+ };
93
+ type WebhookUpdateInput = {
94
+ url?: string;
95
+ events?: string[];
96
+ secret?: string;
97
+ topicId?: string | null;
98
+ active?: boolean;
99
+ };
100
+ type WebhookDeliveryStatus = "pending" | "delivering" | "succeeded" | "failed" | "dead_letter";
101
+ type WebhookDeliveryRecord = {
102
+ id: string;
103
+ deliveryId: string;
104
+ webhookId: string;
105
+ eventId: string;
106
+ eventType: string;
107
+ topicId: string;
108
+ status: WebhookDeliveryStatus;
109
+ attemptCount: number;
110
+ maxAttempts: number;
111
+ nextAttemptAt?: number;
112
+ lastAttemptAt?: number;
113
+ lastStatusCode?: number;
114
+ lastError?: string;
115
+ deliveredAt?: number;
116
+ createdAt: number;
117
+ updatedAt: number;
118
+ };
119
+ type WebhookDeliveryAttemptRecord = {
120
+ id: string;
121
+ attemptId: string;
122
+ deliveryId: string;
123
+ webhookId: string;
124
+ eventId: string;
125
+ eventType: string;
126
+ attemptNumber: number;
127
+ status: "succeeded" | "failed";
128
+ statusCode?: number;
129
+ error?: string;
130
+ responseBody?: string;
131
+ durationMs?: number;
132
+ createdAt: number;
133
+ };
134
+ type WebhookDeliveriesResult = {
135
+ deliveries: Array<WebhookDeliveryRecord & {
136
+ attempts?: WebhookDeliveryAttemptRecord[];
137
+ }>;
138
+ };
139
+ type WebhookHealthResult = {
140
+ webhookId: string;
141
+ totalAttempts: number;
142
+ successfulAttempts: number;
143
+ failedAttempts: number;
144
+ successRate: number;
145
+ pendingDeliveries: number;
146
+ deadLetterDeliveries: number;
147
+ lastDeliveryAt?: number;
148
+ lastSuccessfulDeliveryAt?: number;
149
+ };
150
+ type WebhookTestResult = {
151
+ webhookId: string;
152
+ deliveryId: string;
153
+ status: WebhookDeliveryStatus;
154
+ attempts: number;
155
+ };
156
+ type ReplayEventsInput = EventListQuery & {
157
+ webhookId?: string;
158
+ };
159
+ type ReplayEventsResult = EventListResult & {
160
+ replayedDeliveries?: number;
161
+ replayedWebhookId?: string;
162
+ };
163
+ declare function createEventId(): string;
164
+ declare function normalizeRetentionDays(value: number | undefined): number;
165
+ declare function buildDomainEvent(input: CreateDomainEventInput): DomainEvent;
166
+ declare function compareEventCursor(left: EventCursor, right: EventCursor): number;
167
+ declare function encodeEventCursor(cursor: EventCursor): string;
168
+ declare function decodeEventCursor(cursor: string | undefined): EventCursor | null;
169
+ declare function isAfterCursor(event: Pick<DomainEvent, "timestamp" | "eventId">, cursor: EventCursor | null): boolean;
170
+ declare function sortEventsByCursor<T extends Pick<DomainEvent, "timestamp" | "eventId">>(events: readonly T[]): T[];
171
+ declare function inferActorType(args: {
172
+ sessionType?: "agent" | "user";
173
+ authMode?: string;
174
+ principalType?: string;
175
+ }): DomainActorType;
176
+ declare function emitDomainEvent(invokeMutation: (reference: any, args: CreateDomainEventInput) => Promise<unknown>, input: CreateDomainEventInput): Promise<unknown>;
177
+
178
+ export { type CreateDomainEventInput, DOMAIN_EVENT_TYPES, DOMAIN_EVENT_VERSION, type DomainActorType, type DomainEvent, type DomainEventData, type DomainEventType, type DomainResourceType, EVENT_RETENTION_DEFAULT_DAYS, type EventCursor, type EventListQuery, type EventListResult, type ReplayEventsInput, type ReplayEventsResult, WEBHOOK_MAX_ATTEMPTS, WEBHOOK_RETRY_DELAYS_MS, type WebhookCreateInput, type WebhookDeliveriesResult, type WebhookDeliveryAttemptRecord, type WebhookDeliveryRecord, type WebhookDeliveryStatus, type WebhookHealthResult, type WebhookRecord, type WebhookSecretMode, type WebhookTestResult, type WebhookUpdateInput, buildDomainEvent, compareEventCursor, createEventId, decodeEventCursor, emitDomainEvent, encodeEventCursor, inferActorType, isAfterCursor, normalizeRetentionDays, sortEventsByCursor };
@@ -0,0 +1,136 @@
1
+ // src/events.contract.ts
2
+ var DOMAIN_EVENT_VERSION = "1.0";
3
+ var EVENT_RETENTION_DEFAULT_DAYS = 30;
4
+ var WEBHOOK_MAX_ATTEMPTS = 5;
5
+ var WEBHOOK_RETRY_DELAYS_MS = [1e3, 5e3, 3e4, 3e5];
6
+ var DOMAIN_EVENT_TYPES = [
7
+ "belief.created",
8
+ "belief.forked",
9
+ "belief.confidence_updated",
10
+ "belief.archived",
11
+ "belief.refined",
12
+ "belief.contract_created",
13
+ "belief.contract_evaluated",
14
+ "belief.lineage_queried",
15
+ "evidence.created",
16
+ "evidence.linked",
17
+ "evidence.search_executed",
18
+ "question.created",
19
+ "question.answered",
20
+ "question.refined",
21
+ "question.status_updated",
22
+ "question.archived",
23
+ "edge.created",
24
+ "contradiction.flagged",
25
+ "worktree.created",
26
+ "worktree.activated",
27
+ "worktree.merged",
28
+ "worktree.targets_updated",
29
+ "worktree.metadata_updated",
30
+ "topic.created",
31
+ "topic.updated",
32
+ "topic.archived",
33
+ "task.created",
34
+ "task.completed",
35
+ "task.updated",
36
+ "ontology.bound",
37
+ "context.compiled",
38
+ "identity.key_created",
39
+ "identity.key_rotated",
40
+ "identity.key_revoked",
41
+ "webhook.test"
42
+ ];
43
+ function toBase64(value) {
44
+ if (typeof Buffer !== "undefined") {
45
+ return Buffer.from(value, "utf8").toString("base64url");
46
+ }
47
+ return btoa(unescape(encodeURIComponent(value))).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "");
48
+ }
49
+ function fromBase64(value) {
50
+ if (typeof Buffer !== "undefined") {
51
+ return Buffer.from(value, "base64url").toString("utf8");
52
+ }
53
+ const normalized = value.replace(/-/g, "+").replace(/_/g, "/");
54
+ return decodeURIComponent(escape(atob(normalized)));
55
+ }
56
+ function createEventId() {
57
+ const random = crypto.randomUUID().replace(/-/g, "");
58
+ return `evt_${random}`;
59
+ }
60
+ function normalizeRetentionDays(value) {
61
+ if (!Number.isFinite(value) || typeof value !== "number" || value <= 0) {
62
+ return EVENT_RETENTION_DEFAULT_DAYS;
63
+ }
64
+ return Math.max(1, Math.trunc(value));
65
+ }
66
+ function buildDomainEvent(input) {
67
+ const timestamp = input.timestamp ?? Date.now();
68
+ const retentionDays = normalizeRetentionDays(input.retentionDays);
69
+ return {
70
+ eventId: input.eventId?.trim() || createEventId(),
71
+ type: input.type.trim(),
72
+ version: DOMAIN_EVENT_VERSION,
73
+ timestamp,
74
+ tenantId: input.tenantId?.trim() || void 0,
75
+ workspaceId: input.workspaceId?.trim() || void 0,
76
+ topicId: input.topicId.trim(),
77
+ resourceId: input.resourceId.trim(),
78
+ resourceType: input.resourceType.trim(),
79
+ actorId: input.actorId.trim(),
80
+ actorType: input.actorType,
81
+ data: input.data ?? {},
82
+ correlationId: input.correlationId?.trim() || void 0,
83
+ expiresAt: timestamp + retentionDays * 24 * 60 * 60 * 1e3
84
+ };
85
+ }
86
+ function compareEventCursor(left, right) {
87
+ if (left.timestamp !== right.timestamp) {
88
+ return left.timestamp - right.timestamp;
89
+ }
90
+ return left.eventId.localeCompare(right.eventId);
91
+ }
92
+ function encodeEventCursor(cursor) {
93
+ return toBase64(JSON.stringify(cursor));
94
+ }
95
+ function decodeEventCursor(cursor) {
96
+ if (!cursor || cursor.trim().length === 0) {
97
+ return null;
98
+ }
99
+ try {
100
+ const parsed = JSON.parse(fromBase64(cursor.trim()));
101
+ if (typeof parsed.timestamp !== "number" || !Number.isFinite(parsed.timestamp) || typeof parsed.eventId !== "string" || parsed.eventId.trim().length === 0) {
102
+ return null;
103
+ }
104
+ return {
105
+ timestamp: parsed.timestamp,
106
+ eventId: parsed.eventId.trim()
107
+ };
108
+ } catch {
109
+ return null;
110
+ }
111
+ }
112
+ function isAfterCursor(event, cursor) {
113
+ if (!cursor) {
114
+ return true;
115
+ }
116
+ return compareEventCursor(event, cursor) > 0;
117
+ }
118
+ function sortEventsByCursor(events) {
119
+ return [...events].sort((left, right) => compareEventCursor(left, right));
120
+ }
121
+ function inferActorType(args) {
122
+ if (args.sessionType === "agent") {
123
+ return "agent";
124
+ }
125
+ if (args.authMode === "service_principal" || args.authMode === "tenant_api_key" || args.principalType === "service") {
126
+ return "service";
127
+ }
128
+ return "human";
129
+ }
130
+ async function emitDomainEvent(invokeMutation, input) {
131
+ return await invokeMutation("events:recordEvent", input);
132
+ }
133
+
134
+ export { DOMAIN_EVENT_TYPES, DOMAIN_EVENT_VERSION, EVENT_RETENTION_DEFAULT_DAYS, WEBHOOK_MAX_ATTEMPTS, WEBHOOK_RETRY_DELAYS_MS, buildDomainEvent, compareEventCursor, createEventId, decodeEventCursor, emitDomainEvent, encodeEventCursor, inferActorType, isAfterCursor, normalizeRetentionDays, sortEventsByCursor };
135
+ //# sourceMappingURL=events.contract.js.map
136
+ //# sourceMappingURL=events.contract.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/events.contract.ts"],"names":[],"mappings":";AAiBO,IAAM,oBAAA,GAAuB;AAC7B,IAAM,4BAAA,GAA+B;AACrC,IAAM,oBAAA,GAAuB;AAC7B,IAAM,uBAAA,GAA0B,CAAC,GAAA,EAAO,GAAA,EAAO,KAAQ,GAAO;AAE9D,IAAM,kBAAA,GAAqB;AAAA,EAChC,gBAAA;AAAA,EACA,eAAA;AAAA,EACA,2BAAA;AAAA,EACA,iBAAA;AAAA,EACA,gBAAA;AAAA,EACA,yBAAA;AAAA,EACA,2BAAA;AAAA,EACA,wBAAA;AAAA,EACA,kBAAA;AAAA,EACA,iBAAA;AAAA,EACA,0BAAA;AAAA,EACA,kBAAA;AAAA,EACA,mBAAA;AAAA,EACA,kBAAA;AAAA,EACA,yBAAA;AAAA,EACA,mBAAA;AAAA,EACA,cAAA;AAAA,EACA,uBAAA;AAAA,EACA,kBAAA;AAAA,EACA,oBAAA;AAAA,EACA,iBAAA;AAAA,EACA,0BAAA;AAAA,EACA,2BAAA;AAAA,EACA,eAAA;AAAA,EACA,eAAA;AAAA,EACA,gBAAA;AAAA,EACA,cAAA;AAAA,EACA,gBAAA;AAAA,EACA,cAAA;AAAA,EACA,gBAAA;AAAA,EACA,kBAAA;AAAA,EACA,sBAAA;AAAA,EACA,sBAAA;AAAA,EACA,sBAAA;AAAA,EACA;AACF;AAiMA,SAAS,SAAS,KAAA,EAAuB;AACvC,EAAA,IAAI,OAAO,WAAW,WAAA,EAAa;AACjC,IAAA,OAAO,OAAO,IAAA,CAAK,KAAA,EAAO,MAAM,CAAA,CAAE,SAAS,WAAW,CAAA;AAAA,EACxD;AACA,EAAA,OAAO,KAAK,QAAA,CAAS,kBAAA,CAAmB,KAAK,CAAC,CAAC,CAAA,CAC5C,OAAA,CAAQ,KAAA,EAAO,GAAG,EAClB,OAAA,CAAQ,KAAA,EAAO,GAAG,CAAA,CAClB,OAAA,CAAQ,QAAQ,EAAE,CAAA;AACvB;AAEA,SAAS,WAAW,KAAA,EAAuB;AACzC,EAAA,IAAI,OAAO,WAAW,WAAA,EAAa;AACjC,IAAA,OAAO,OAAO,IAAA,CAAK,KAAA,EAAO,WAAW,CAAA,CAAE,SAAS,MAAM,CAAA;AAAA,EACxD;AACA,EAAA,MAAM,UAAA,GAAa,MAAM,OAAA,CAAQ,IAAA,EAAM,GAAG,CAAA,CAAE,OAAA,CAAQ,MAAM,GAAG,CAAA;AAC7D,EAAA,OAAO,kBAAA,CAAmB,MAAA,CAAO,IAAA,CAAK,UAAU,CAAC,CAAC,CAAA;AACpD;AAEO,SAAS,aAAA,GAAwB;AACtC,EAAA,MAAM,SAAS,MAAA,CAAO,UAAA,EAAW,CAAE,OAAA,CAAQ,MAAM,EAAE,CAAA;AACnD,EAAA,OAAO,OAAO,MAAM,CAAA,CAAA;AACtB;AAEO,SAAS,uBAAuB,KAAA,EAAmC;AACxE,EAAA,IAAI,CAAC,OAAO,QAAA,CAAS,KAAK,KAAK,OAAO,KAAA,KAAU,QAAA,IAAY,KAAA,IAAS,CAAA,EAAG;AACtE,IAAA,OAAO,4BAAA;AAAA,EACT;AACA,EAAA,OAAO,KAAK,GAAA,CAAI,CAAA,EAAG,IAAA,CAAK,KAAA,CAAM,KAAK,CAAC,CAAA;AACtC;AAEO,SAAS,iBAAiB,KAAA,EAA4C;AAC3E,EAAA,MAAM,SAAA,GAAY,KAAA,CAAM,SAAA,IAAa,IAAA,CAAK,GAAA,EAAI;AAC9C,EAAA,MAAM,aAAA,GAAgB,sBAAA,CAAuB,KAAA,CAAM,aAAa,CAAA;AAChE,EAAA,OAAO;AAAA,IACL,OAAA,EAAS,KAAA,CAAM,OAAA,EAAS,IAAA,MAAU,aAAA,EAAc;AAAA,IAChD,IAAA,EAAM,KAAA,CAAM,IAAA,CAAK,IAAA,EAAK;AAAA,IACtB,OAAA,EAAS,oBAAA;AAAA,IACT,SAAA;AAAA,IACA,QAAA,EAAU,KAAA,CAAM,QAAA,EAAU,IAAA,EAAK,IAAK,MAAA;AAAA,IACpC,WAAA,EAAa,KAAA,CAAM,WAAA,EAAa,IAAA,EAAK,IAAK,MAAA;AAAA,IAC1C,OAAA,EAAS,KAAA,CAAM,OAAA,CAAQ,IAAA,EAAK;AAAA,IAC5B,UAAA,EAAY,KAAA,CAAM,UAAA,CAAW,IAAA,EAAK;AAAA,IAClC,YAAA,EAAc,KAAA,CAAM,YAAA,CAAa,IAAA,EAAK;AAAA,IACtC,OAAA,EAAS,KAAA,CAAM,OAAA,CAAQ,IAAA,EAAK;AAAA,IAC5B,WAAW,KAAA,CAAM,SAAA;AAAA,IACjB,IAAA,EAAM,KAAA,CAAM,IAAA,IAAQ,EAAC;AAAA,IACrB,aAAA,EAAe,KAAA,CAAM,aAAA,EAAe,IAAA,EAAK,IAAK,MAAA;AAAA,IAC9C,SAAA,EAAW,SAAA,GAAY,aAAA,GAAgB,EAAA,GAAK,KAAK,EAAA,GAAK;AAAA,GACxD;AACF;AAEO,SAAS,kBAAA,CAAmB,MAAmB,KAAA,EAA4B;AAChF,EAAA,IAAI,IAAA,CAAK,SAAA,KAAc,KAAA,CAAM,SAAA,EAAW;AACtC,IAAA,OAAO,IAAA,CAAK,YAAY,KAAA,CAAM,SAAA;AAAA,EAChC;AACA,EAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,aAAA,CAAc,KAAA,CAAM,OAAO,CAAA;AACjD;AAEO,SAAS,kBAAkB,MAAA,EAA6B;AAC7D,EAAA,OAAO,QAAA,CAAS,IAAA,CAAK,SAAA,CAAU,MAAM,CAAC,CAAA;AACxC;AAEO,SAAS,kBAAkB,MAAA,EAAgD;AAChF,EAAA,IAAI,CAAC,MAAA,IAAU,MAAA,CAAO,IAAA,EAAK,CAAE,WAAW,CAAA,EAAG;AACzC,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,IAAI;AACF,IAAA,MAAM,SAAS,IAAA,CAAK,KAAA,CAAM,WAAW,MAAA,CAAO,IAAA,EAAM,CAAC,CAAA;AACnD,IAAA,IACE,OAAO,MAAA,CAAO,SAAA,KAAc,YAC5B,CAAC,MAAA,CAAO,SAAS,MAAA,CAAO,SAAS,KACjC,OAAO,MAAA,CAAO,YAAY,QAAA,IAC1B,MAAA,CAAO,QAAQ,IAAA,EAAK,CAAE,WAAW,CAAA,EACjC;AACA,MAAA,OAAO,IAAA;AAAA,IACT;AACA,IAAA,OAAO;AAAA,MACL,WAAW,MAAA,CAAO,SAAA;AAAA,MAClB,OAAA,EAAS,MAAA,CAAO,OAAA,CAAQ,IAAA;AAAK,KAC/B;AAAA,EACF,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AACF;AAEO,SAAS,aAAA,CACd,OACA,MAAA,EACS;AACT,EAAA,IAAI,CAAC,MAAA,EAAQ;AACX,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,OAAO,kBAAA,CAAmB,KAAA,EAAO,MAAM,CAAA,GAAI,CAAA;AAC7C;AAEO,SAAS,mBACd,MAAA,EACK;AACL,EAAA,OAAO,CAAC,GAAG,MAAM,CAAA,CAAE,IAAA,CAAK,CAAC,IAAA,EAAM,KAAA,KAAU,kBAAA,CAAmB,IAAA,EAAM,KAAK,CAAC,CAAA;AAC1E;AAEO,SAAS,eAAe,IAAA,EAIX;AAClB,EAAA,IAAI,IAAA,CAAK,gBAAgB,OAAA,EAAS;AAChC,IAAA,OAAO,OAAA;AAAA,EACT;AACA,EAAA,IACE,IAAA,CAAK,aAAa,mBAAA,IAClB,IAAA,CAAK,aAAa,gBAAA,IAClB,IAAA,CAAK,kBAAkB,SAAA,EACvB;AACA,IAAA,OAAO,SAAA;AAAA,EACT;AACA,EAAA,OAAO,OAAA;AACT;AAEA,eAAsB,eAAA,CACpB,gBACA,KAAA,EACkB;AAClB,EAAA,OAAO,MAAM,cAAA,CAAe,oBAAA,EAA6B,KAAK,CAAA;AAChE","file":"events.contract.js","sourcesContent":["/**\n * @lucern/contracts — events (canonical support contract)\n *\n * Consolidated flat support surface for Lucern's domain event stream:\n * - Event type definitions, constants, and shared enums\n * - Event construction + cursor helpers\n *\n * Consolidated from the former split type-definition module\n * and the prior src/events.contract.ts (helpers) in EK-16 T1 PR 3b.\n * Compat shim remains at the old events-types path until Lucern 1.0.0 (D12).\n */\n\n// =============================================================================\n// EVENT TYPE DEFINITIONS & CONSTANTS\n// (Formerly the split events type-definition module)\n// =============================================================================\n\nexport const DOMAIN_EVENT_VERSION = \"1.0\" as const;\nexport const EVENT_RETENTION_DEFAULT_DAYS = 30;\nexport const WEBHOOK_MAX_ATTEMPTS = 5;\nexport const WEBHOOK_RETRY_DELAYS_MS = [1_000, 5_000, 30_000, 300_000] as const;\n\nexport const DOMAIN_EVENT_TYPES = [\n \"belief.created\",\n \"belief.forked\",\n \"belief.confidence_updated\",\n \"belief.archived\",\n \"belief.refined\",\n \"belief.contract_created\",\n \"belief.contract_evaluated\",\n \"belief.lineage_queried\",\n \"evidence.created\",\n \"evidence.linked\",\n \"evidence.search_executed\",\n \"question.created\",\n \"question.answered\",\n \"question.refined\",\n \"question.status_updated\",\n \"question.archived\",\n \"edge.created\",\n \"contradiction.flagged\",\n \"worktree.created\",\n \"worktree.activated\",\n \"worktree.merged\",\n \"worktree.targets_updated\",\n \"worktree.metadata_updated\",\n \"topic.created\",\n \"topic.updated\",\n \"topic.archived\",\n \"task.created\",\n \"task.completed\",\n \"task.updated\",\n \"ontology.bound\",\n \"context.compiled\",\n \"identity.key_created\",\n \"identity.key_rotated\",\n \"identity.key_revoked\",\n \"webhook.test\",\n] as const;\n\nexport type DomainEventType = (typeof DOMAIN_EVENT_TYPES)[number];\n\nexport type DomainResourceType =\n | \"belief\"\n | \"evidence\"\n | \"question\"\n | \"edge\"\n | \"contradiction\"\n | \"worktree\"\n | \"topic\"\n | \"task\"\n | \"ontology\"\n | \"context\"\n | \"identity\"\n | \"webhook\";\n\nexport type DomainActorType = \"human\" | \"agent\" | \"service\";\n\nexport type DomainEventData = Record<string, unknown>;\n\nexport type DomainEvent = {\n eventId: string;\n type: DomainEventType | string;\n version: typeof DOMAIN_EVENT_VERSION;\n timestamp: number;\n tenantId?: string;\n workspaceId?: string;\n topicId: string;\n resourceId: string;\n resourceType: DomainResourceType | string;\n actorId: string;\n actorType: DomainActorType;\n data: DomainEventData;\n correlationId?: string;\n expiresAt: number;\n};\n\nexport type CreateDomainEventInput = {\n eventId?: string;\n timestamp?: number;\n tenantId?: string;\n workspaceId?: string;\n topicId: string;\n type: DomainEventType | string;\n resourceId: string;\n resourceType: DomainResourceType | string;\n actorId: string;\n actorType: DomainActorType;\n data?: DomainEventData;\n correlationId?: string;\n retentionDays?: number;\n};\n\nexport type EventCursor = {\n timestamp: number;\n eventId: string;\n};\n\nexport type EventListQuery = {\n topicId?: string;\n after?: string;\n types?: string[];\n startTime?: number;\n endTime?: number;\n limit?: number;\n};\n\nexport type EventListResult = {\n events: DomainEvent[];\n nextCursor: string | null;\n};\n\nexport type WebhookSecretMode = \"configured\";\n\nexport type WebhookRecord = {\n id: string;\n webhookId: string;\n tenantId?: string;\n workspaceId?: string;\n topicId?: string;\n url: string;\n events: string[];\n active: boolean;\n secretConfigured: boolean;\n createdAt: number;\n updatedAt: number;\n createdBy: string;\n updatedBy: string;\n lastDeliveryAt?: number;\n lastSuccessfulDeliveryAt?: number;\n};\n\nexport type WebhookCreateInput = {\n url: string;\n events: string[];\n secret: string;\n topicId?: string;\n active?: boolean;\n};\n\nexport type WebhookUpdateInput = {\n url?: string;\n events?: string[];\n secret?: string;\n topicId?: string | null;\n active?: boolean;\n};\n\nexport type WebhookDeliveryStatus =\n | \"pending\"\n | \"delivering\"\n | \"succeeded\"\n | \"failed\"\n | \"dead_letter\";\n\nexport type WebhookDeliveryRecord = {\n id: string;\n deliveryId: string;\n webhookId: string;\n eventId: string;\n eventType: string;\n topicId: string;\n status: WebhookDeliveryStatus;\n attemptCount: number;\n maxAttempts: number;\n nextAttemptAt?: number;\n lastAttemptAt?: number;\n lastStatusCode?: number;\n lastError?: string;\n deliveredAt?: number;\n createdAt: number;\n updatedAt: number;\n};\n\nexport type WebhookDeliveryAttemptRecord = {\n id: string;\n attemptId: string;\n deliveryId: string;\n webhookId: string;\n eventId: string;\n eventType: string;\n attemptNumber: number;\n status: \"succeeded\" | \"failed\";\n statusCode?: number;\n error?: string;\n responseBody?: string;\n durationMs?: number;\n createdAt: number;\n};\n\nexport type WebhookDeliveriesResult = {\n deliveries: Array<\n WebhookDeliveryRecord & {\n attempts?: WebhookDeliveryAttemptRecord[];\n }\n >;\n};\n\nexport type WebhookHealthResult = {\n webhookId: string;\n totalAttempts: number;\n successfulAttempts: number;\n failedAttempts: number;\n successRate: number;\n pendingDeliveries: number;\n deadLetterDeliveries: number;\n lastDeliveryAt?: number;\n lastSuccessfulDeliveryAt?: number;\n};\n\nexport type WebhookTestResult = {\n webhookId: string;\n deliveryId: string;\n status: WebhookDeliveryStatus;\n attempts: number;\n};\n\nexport type ReplayEventsInput = EventListQuery & {\n webhookId?: string;\n};\n\nexport type ReplayEventsResult = EventListResult & {\n replayedDeliveries?: number;\n replayedWebhookId?: string;\n};\n\n// =============================================================================\n// EVENT HELPERS\n// (Formerly the body of src/events.contract.ts)\n// =============================================================================\n\nfunction toBase64(value: string): string {\n if (typeof Buffer !== \"undefined\") {\n return Buffer.from(value, \"utf8\").toString(\"base64url\");\n }\n return btoa(unescape(encodeURIComponent(value)))\n .replace(/\\+/g, \"-\")\n .replace(/\\//g, \"_\")\n .replace(/=+$/g, \"\");\n}\n\nfunction fromBase64(value: string): string {\n if (typeof Buffer !== \"undefined\") {\n return Buffer.from(value, \"base64url\").toString(\"utf8\");\n }\n const normalized = value.replace(/-/g, \"+\").replace(/_/g, \"/\");\n return decodeURIComponent(escape(atob(normalized)));\n}\n\nexport function createEventId(): string {\n const random = crypto.randomUUID().replace(/-/g, \"\");\n return `evt_${random}`;\n}\n\nexport function normalizeRetentionDays(value: number | undefined): number {\n if (!Number.isFinite(value) || typeof value !== \"number\" || value <= 0) {\n return EVENT_RETENTION_DEFAULT_DAYS;\n }\n return Math.max(1, Math.trunc(value));\n}\n\nexport function buildDomainEvent(input: CreateDomainEventInput): DomainEvent {\n const timestamp = input.timestamp ?? Date.now();\n const retentionDays = normalizeRetentionDays(input.retentionDays);\n return {\n eventId: input.eventId?.trim() || createEventId(),\n type: input.type.trim(),\n version: DOMAIN_EVENT_VERSION,\n timestamp,\n tenantId: input.tenantId?.trim() || undefined,\n workspaceId: input.workspaceId?.trim() || undefined,\n topicId: input.topicId.trim(),\n resourceId: input.resourceId.trim(),\n resourceType: input.resourceType.trim(),\n actorId: input.actorId.trim(),\n actorType: input.actorType,\n data: input.data ?? {},\n correlationId: input.correlationId?.trim() || undefined,\n expiresAt: timestamp + retentionDays * 24 * 60 * 60 * 1000,\n };\n}\n\nexport function compareEventCursor(left: EventCursor, right: EventCursor): number {\n if (left.timestamp !== right.timestamp) {\n return left.timestamp - right.timestamp;\n }\n return left.eventId.localeCompare(right.eventId);\n}\n\nexport function encodeEventCursor(cursor: EventCursor): string {\n return toBase64(JSON.stringify(cursor));\n}\n\nexport function decodeEventCursor(cursor: string | undefined): EventCursor | null {\n if (!cursor || cursor.trim().length === 0) {\n return null;\n }\n try {\n const parsed = JSON.parse(fromBase64(cursor.trim())) as Partial<EventCursor>;\n if (\n typeof parsed.timestamp !== \"number\" ||\n !Number.isFinite(parsed.timestamp) ||\n typeof parsed.eventId !== \"string\" ||\n parsed.eventId.trim().length === 0\n ) {\n return null;\n }\n return {\n timestamp: parsed.timestamp,\n eventId: parsed.eventId.trim(),\n };\n } catch {\n return null;\n }\n}\n\nexport function isAfterCursor(\n event: Pick<DomainEvent, \"timestamp\" | \"eventId\">,\n cursor: EventCursor | null\n): boolean {\n if (!cursor) {\n return true;\n }\n return compareEventCursor(event, cursor) > 0;\n}\n\nexport function sortEventsByCursor<T extends Pick<DomainEvent, \"timestamp\" | \"eventId\">>(\n events: readonly T[]\n): T[] {\n return [...events].sort((left, right) => compareEventCursor(left, right));\n}\n\nexport function inferActorType(args: {\n sessionType?: \"agent\" | \"user\";\n authMode?: string;\n principalType?: string;\n}): DomainActorType {\n if (args.sessionType === \"agent\") {\n return \"agent\";\n }\n if (\n args.authMode === \"service_principal\" ||\n args.authMode === \"tenant_api_key\" ||\n args.principalType === \"service\"\n ) {\n return \"service\";\n }\n return \"human\";\n}\n\nexport async function emitDomainEvent(\n invokeMutation: (reference: any, args: CreateDomainEventInput) => Promise<unknown>,\n input: CreateDomainEventInput\n): Promise<unknown> {\n return await invokeMutation(\"events:recordEvent\" as any, input);\n}\n"]}
@@ -0,0 +1,2 @@
1
+
2
+ export { }
@@ -0,0 +1,3 @@
1
+
2
+ //# sourceMappingURL=v1.js.map
3
+ //# sourceMappingURL=v1.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"v1.js"}
@@ -0,0 +1,79 @@
1
+ import { SessionPrincipalType, SessionAuthMode, SessionDelegationHop } from './auth.contract.js';
2
+ import './convex-admin.contract.js';
3
+
4
+ /**
5
+ * Gateway contract types — shared between Stack's gateway middleware and
6
+ * Lucern's server-core / gateway route handlers.
7
+ *
8
+ * These types describe the authenticated request context that flows from
9
+ * the gateway into Lucern route handlers. The gateway (Stack-side) creates
10
+ * the context; Lucern consumes it read-only.
11
+ *
12
+ * @module @lucern/contracts/src/gateway
13
+ */
14
+
15
+ type PlatformApiErrorCode = "AUTH_REQUIRED" | "AUTHENTICATION_REQUIRED" | "AUTH_TOKEN_MISSING" | "INVALID_REQUEST" | "IDEMPOTENCY_KEY_REQUIRED" | "FORBIDDEN" | "SCOPE_INSUFFICIENT" | "ENVIRONMENT_MISMATCH" | "KEY_EXPIRED" | "KEY_REVOKED" | "RATE_LIMIT_EXCEEDED" | "NOT_FOUND" | "CONFLICT" | "UPSTREAM_ERROR" | "INTERNAL_ERROR";
16
+ type GatewayScope = {
17
+ tenantId?: string;
18
+ workspaceId?: string;
19
+ };
20
+ type GatewayEnvironment = "sandbox" | "production";
21
+ type GatewayAuthMode = "interactive_user" | "service_principal" | "tenant_api_key" | "session_token";
22
+ type KeyLifecycleStatus = "active" | "rotating" | "rotated" | "expired" | "revoked";
23
+ type CutoverDomain = "graph" | "schema" | "identity" | "policy" | "audit" | "admin" | "agent" | "tool" | "prompt" | "intelligence";
24
+ type CutoverFlagState = "legacy" | "cutover" | "disabled";
25
+ /**
26
+ * Authenticated request context created by the gateway middleware.
27
+ * Lucern route handlers receive this as a read-only parameter.
28
+ *
29
+ * The `convex` field is typed as `unknown` in the contract because Lucern
30
+ * consumers should not use the gateway's Convex client directly — they
31
+ * have their own kernel client. The gateway (Stack-side) narrows this to
32
+ * `ConvexHttpClient` at the construction site.
33
+ */
34
+ type GatewayAuthContext = {
35
+ userId: string;
36
+ convexToken?: string;
37
+ /** Opaque in contract — narrowed to ConvexHttpClient at the gateway. */
38
+ convex: any;
39
+ authMode: GatewayAuthMode;
40
+ principalId?: string;
41
+ principalType?: SessionPrincipalType;
42
+ tenantId?: string;
43
+ workspaceId?: string;
44
+ roles?: string[];
45
+ sessionId?: string;
46
+ sessionAuthMode?: SessionAuthMode;
47
+ sessionExpiresAt?: number;
48
+ delegationChain?: SessionDelegationHop[];
49
+ servicePrincipalId?: string;
50
+ servicePrincipalKeyId?: string;
51
+ servicePrincipalTenantId?: string;
52
+ servicePrincipalWorkspaceId?: string;
53
+ requestEnvironment: GatewayEnvironment;
54
+ keyEnvironment?: GatewayEnvironment;
55
+ keyStatus: KeyLifecycleStatus | "unknown";
56
+ grantedScopes: Set<string>;
57
+ cutoverDomain: CutoverDomain;
58
+ cutoverState: CutoverFlagState;
59
+ };
60
+ type GatewayErrorArgs = {
61
+ code: PlatformApiErrorCode;
62
+ message: string;
63
+ status: number;
64
+ correlationId: string;
65
+ policyTraceId?: string;
66
+ invariant?: string;
67
+ suggestion?: string;
68
+ details?: unknown;
69
+ headers?: HeadersInit;
70
+ };
71
+ type GatewaySuccessArgs = {
72
+ status?: number;
73
+ correlationId: string;
74
+ policyTraceId?: string;
75
+ idempotentReplay?: boolean;
76
+ };
77
+ declare function requireActorPrincipalId(authContext: GatewayAuthContext): string;
78
+
79
+ export { type CutoverDomain, type CutoverFlagState, type GatewayAuthContext, type GatewayAuthMode, type GatewayEnvironment, type GatewayErrorArgs, type GatewayScope, type GatewaySuccessArgs, type KeyLifecycleStatus, type PlatformApiErrorCode, requireActorPrincipalId };
@@ -0,0 +1,12 @@
1
+ // src/gateway.contract.ts
2
+ function requireActorPrincipalId(authContext) {
3
+ const principalId = typeof authContext.principalId === "string" ? authContext.principalId.trim() : "";
4
+ if (principalId.length > 0) {
5
+ return principalId;
6
+ }
7
+ throw new Error("Access denied: federated principal context required.");
8
+ }
9
+
10
+ export { requireActorPrincipalId };
11
+ //# sourceMappingURL=gateway.contract.js.map
12
+ //# sourceMappingURL=gateway.contract.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/gateway.contract.ts"],"names":[],"mappings":";AA2IO,SAAS,wBACd,WAAA,EACQ;AACR,EAAA,MAAM,WAAA,GACJ,OAAO,WAAA,CAAY,WAAA,KAAgB,WAC/B,WAAA,CAAY,WAAA,CAAY,MAAK,GAC7B,EAAA;AACN,EAAA,IAAI,WAAA,CAAY,SAAS,CAAA,EAAG;AAC1B,IAAA,OAAO,WAAA;AAAA,EACT;AACA,EAAA,MAAM,IAAI,MAAM,sDAAsD,CAAA;AACxE","file":"gateway.contract.js","sourcesContent":["/**\n * Gateway contract types — shared between Stack's gateway middleware and\n * Lucern's server-core / gateway route handlers.\n *\n * These types describe the authenticated request context that flows from\n * the gateway into Lucern route handlers. The gateway (Stack-side) creates\n * the context; Lucern consumes it read-only.\n *\n * @module @lucern/contracts/src/gateway\n */\n\nimport type {\n SessionAuthMode,\n SessionDelegationHop,\n SessionPrincipalType,\n} from \"./auth-session.contract\";\n\n// ---------------------------------------------------------------------------\n// Error codes\n// ---------------------------------------------------------------------------\n\nexport type PlatformApiErrorCode =\n | \"AUTH_REQUIRED\"\n | \"AUTHENTICATION_REQUIRED\"\n | \"AUTH_TOKEN_MISSING\"\n | \"INVALID_REQUEST\"\n | \"IDEMPOTENCY_KEY_REQUIRED\"\n | \"FORBIDDEN\"\n | \"SCOPE_INSUFFICIENT\"\n | \"ENVIRONMENT_MISMATCH\"\n | \"KEY_EXPIRED\"\n | \"KEY_REVOKED\"\n | \"RATE_LIMIT_EXCEEDED\"\n | \"NOT_FOUND\"\n | \"CONFLICT\"\n | \"UPSTREAM_ERROR\"\n | \"INTERNAL_ERROR\";\n\n// ---------------------------------------------------------------------------\n// Gateway scope and environment\n// ---------------------------------------------------------------------------\n\nexport type GatewayScope = {\n tenantId?: string;\n workspaceId?: string;\n};\n\nexport type GatewayEnvironment = \"sandbox\" | \"production\";\n\nexport type GatewayAuthMode =\n | \"interactive_user\"\n | \"service_principal\"\n | \"tenant_api_key\"\n | \"session_token\";\n\nexport type KeyLifecycleStatus =\n | \"active\"\n | \"rotating\"\n | \"rotated\"\n | \"expired\"\n | \"revoked\";\n\nexport type CutoverDomain =\n | \"graph\"\n | \"schema\"\n | \"identity\"\n | \"policy\"\n | \"audit\"\n | \"admin\"\n | \"agent\"\n | \"tool\"\n | \"prompt\"\n | \"intelligence\";\n\nexport type CutoverFlagState = \"legacy\" | \"cutover\" | \"disabled\";\n\n// ---------------------------------------------------------------------------\n// Gateway auth context — the canonical authenticated request shape\n// ---------------------------------------------------------------------------\n\n/**\n * Authenticated request context created by the gateway middleware.\n * Lucern route handlers receive this as a read-only parameter.\n *\n * The `convex` field is typed as `unknown` in the contract because Lucern\n * consumers should not use the gateway's Convex client directly — they\n * have their own kernel client. The gateway (Stack-side) narrows this to\n * `ConvexHttpClient` at the construction site.\n */\nexport type GatewayAuthContext = {\n userId: string;\n convexToken?: string;\n /** Opaque in contract — narrowed to ConvexHttpClient at the gateway. */\n convex: any; // eslint-disable-line @typescript-eslint/no-explicit-any\n authMode: GatewayAuthMode;\n principalId?: string;\n principalType?: SessionPrincipalType;\n tenantId?: string;\n workspaceId?: string;\n roles?: string[];\n sessionId?: string;\n sessionAuthMode?: SessionAuthMode;\n sessionExpiresAt?: number;\n delegationChain?: SessionDelegationHop[];\n servicePrincipalId?: string;\n servicePrincipalKeyId?: string;\n servicePrincipalTenantId?: string;\n servicePrincipalWorkspaceId?: string;\n requestEnvironment: GatewayEnvironment;\n keyEnvironment?: GatewayEnvironment;\n keyStatus: KeyLifecycleStatus | \"unknown\";\n grantedScopes: Set<string>;\n cutoverDomain: CutoverDomain;\n cutoverState: CutoverFlagState;\n};\n\n// ---------------------------------------------------------------------------\n// Gateway response helpers — portable (no Next.js dependency)\n// ---------------------------------------------------------------------------\n\nexport type GatewayErrorArgs = {\n code: PlatformApiErrorCode;\n message: string;\n status: number;\n correlationId: string;\n policyTraceId?: string;\n invariant?: string;\n suggestion?: string;\n details?: unknown;\n headers?: HeadersInit;\n};\n\nexport type GatewaySuccessArgs = {\n status?: number;\n correlationId: string;\n policyTraceId?: string;\n idempotentReplay?: boolean;\n};\n\nexport function requireActorPrincipalId(\n authContext: GatewayAuthContext\n): string {\n const principalId =\n typeof authContext.principalId === \"string\"\n ? authContext.principalId.trim()\n : \"\";\n if (principalId.length > 0) {\n return principalId;\n }\n throw new Error(\"Access denied: federated principal context required.\");\n}\n"]}
@@ -0,0 +1,2 @@
1
+
2
+ export { }
@@ -0,0 +1,3 @@
1
+
2
+ //# sourceMappingURL=v1.js.map
3
+ //# sourceMappingURL=v1.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"v1.js"}
@@ -0,0 +1,9 @@
1
+ type DecodedPrefixedId = {
2
+ prefix: string;
3
+ value: string;
4
+ };
5
+ declare function encodePrefixedId(prefix: string, value: string): string;
6
+ declare function decodePrefixedId(id: string): DecodedPrefixedId;
7
+ declare function hasPrefixedIdPrefix(id: string, prefix: string): boolean;
8
+
9
+ export { type DecodedPrefixedId, decodePrefixedId, encodePrefixedId, hasPrefixedIdPrefix };