@native-knowledge/knowledge-sdk 0.1.0-rc.1 → 0.1.0-rc.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 (206) hide show
  1. package/LICENSE +202 -21
  2. package/NOTICE +29 -0
  3. package/README.md +26 -38
  4. package/dist/{types/sdk/agent-entry.d.ts → agent-entry.d.ts} +3 -3
  5. package/dist/agent-entry.js +153 -0
  6. package/dist/{types/sdk/agent-guidance-error.d.ts → agent-guidance-error.d.ts} +1 -1
  7. package/dist/agent-guidance-error.js +46 -0
  8. package/dist/auth.d.ts +124 -0
  9. package/dist/auth.js +165 -0
  10. package/dist/{types/sdk/index.d.ts → index.d.ts} +15 -14
  11. package/dist/index.js +159 -6570
  12. package/dist/internal/contracts/artifact.js +103 -0
  13. package/dist/internal/contracts/collection-control.js +69 -0
  14. package/dist/internal/contracts/collection.js +174 -0
  15. package/dist/internal/contracts/common.js +16 -0
  16. package/dist/internal/contracts/currentness.js +221 -0
  17. package/dist/internal/contracts/event.js +35 -0
  18. package/dist/internal/contracts/evidence.js +171 -0
  19. package/dist/{types → internal}/contracts/index.d.ts +0 -1
  20. package/dist/internal/contracts/index.js +54 -0
  21. package/dist/internal/contracts/material-capability.js +8 -0
  22. package/dist/internal/contracts/material-carrier.js +15 -0
  23. package/dist/internal/contracts/material-context.js +9 -0
  24. package/dist/internal/contracts/material-read.js +12 -0
  25. package/dist/internal/contracts/observation.js +39 -0
  26. package/dist/internal/contracts/persistence.js +239 -0
  27. package/dist/internal/contracts/project-intent.js +121 -0
  28. package/dist/internal/contracts/projection.js +194 -0
  29. package/dist/internal/contracts/public-reference.js +87 -0
  30. package/dist/internal/contracts/reference-record.js +55 -0
  31. package/dist/internal/contracts/remote-file.js +159 -0
  32. package/dist/internal/contracts/resource-scope.js +38 -0
  33. package/dist/internal/contracts/review-packet.js +61 -0
  34. package/dist/internal/contracts/review-plane.js +89 -0
  35. package/dist/internal/contracts/rich-document.js +184 -0
  36. package/dist/internal/contracts/runtime-compatibility.js +55 -0
  37. package/dist/internal/contracts/runtime.js +68 -0
  38. package/dist/internal/contracts/scheduler.js +256 -0
  39. package/dist/internal/contracts/signal.js +77 -0
  40. package/dist/internal/contracts/source-governance.js +194 -0
  41. package/dist/internal/contracts/source.js +32 -0
  42. package/dist/internal/contracts/tenant-budget.js +34 -0
  43. package/dist/internal/contracts/tenant-collection-request.js +58 -0
  44. package/dist/internal/contracts/tenant-collection.js +66 -0
  45. package/dist/internal/contracts/tenant-currentness.js +26 -0
  46. package/dist/internal/contracts/tenant-management.js +27 -0
  47. package/dist/internal/contracts/tenant-material-api.js +46 -0
  48. package/dist/internal/contracts/tenant-material-json-schema.js +16 -0
  49. package/dist/internal/contracts/tenant-pdf-text.js +13 -0
  50. package/dist/internal/contracts/tenant-project-control.js +19 -0
  51. package/dist/internal/contracts/tenant-public-reference.js +26 -0
  52. package/dist/internal/contracts/tenant-resource-api.js +70 -0
  53. package/dist/internal/contracts/tenant-resource.js +118 -0
  54. package/dist/internal/contracts/tenant-rich-document.js +17 -0
  55. package/dist/internal/contracts/tenant-source-binding.js +33 -0
  56. package/dist/internal/contracts/tenant-source-bridge.js +9 -0
  57. package/dist/internal/contracts/tenant-source-cutover.js +26 -0
  58. package/dist/internal/contracts/tenant-source-document.js +38 -0
  59. package/dist/internal/contracts/tenant-source-lease.js +5 -0
  60. package/dist/internal/contracts/tenant-source.js +83 -0
  61. package/dist/internal/contracts/tenant-web-collection.js +118 -0
  62. package/dist/internal/contracts/tenant-web-content-plan.js +39 -0
  63. package/dist/internal/contracts/tenant-web-content-result.js +15 -0
  64. package/dist/internal/contracts/tenant-web-content.js +16 -0
  65. package/dist/internal/contracts/tenant-web-crawl.js +55 -0
  66. package/dist/internal/contracts/tenant-web-dynamic.js +68 -0
  67. package/dist/internal/contracts/tenant-web-results.js +41 -0
  68. package/dist/internal/contracts/tenant-web-workflow.js +29 -0
  69. package/dist/internal/serving-contracts/agent-catalog.js +56 -0
  70. package/dist/internal/serving-contracts/agent-entry.js +57 -0
  71. package/dist/internal/serving-contracts/agent-guidance-shapes.js +12 -0
  72. package/dist/internal/serving-contracts/agent-input-hints.js +104 -0
  73. package/dist/internal/serving-contracts/body-search.js +16 -0
  74. package/dist/internal/serving-contracts/consumer.js +45 -0
  75. package/dist/internal/serving-contracts/core.js +76 -0
  76. package/dist/internal/serving-contracts/http.js +64 -0
  77. package/dist/{types → internal}/serving-contracts/index.d.ts +1 -0
  78. package/dist/internal/serving-contracts/index.js +25 -0
  79. package/dist/internal/serving-contracts/management.js +15 -0
  80. package/dist/internal/serving-contracts/material-capabilities.js +14 -0
  81. package/dist/internal/serving-contracts/material-index-status.js +5 -0
  82. package/dist/internal/serving-contracts/mcp.js +140 -0
  83. package/dist/internal/serving-contracts/tenant-governance.js +13 -0
  84. package/dist/internal/serving-contracts/tenant-management.js +89 -0
  85. package/dist/internal/serving-contracts/tenant-project.js +39 -0
  86. package/dist/internal/serving-contracts/tenant-runtime.js +37 -0
  87. package/dist/internal/serving-contracts/tenant-session.d.ts +87 -0
  88. package/dist/internal/serving-contracts/tenant-session.js +8 -0
  89. package/dist/internal/serving-contracts/tenant-web-content.js +20 -0
  90. package/dist/internal/serving-contracts/tenant-web-crawl.js +13 -0
  91. package/dist/internal/serving-contracts/tenant-web-dynamic.js +20 -0
  92. package/dist/internal/serving-contracts/tenant-web-workflow.js +36 -0
  93. package/dist/internal/serving-contracts/tenant-web.js +53 -0
  94. package/dist/internal/serving-contracts/tenant-workspace.js +28 -0
  95. package/dist/internal/serving-contracts/workflow.js +37 -0
  96. package/dist/material-stream.js +29 -0
  97. package/dist/{types/sdk/oauth.d.ts → oauth.d.ts} +18 -18
  98. package/dist/oauth.js +539 -0
  99. package/dist/{types/sdk/resource.d.ts → resource.d.ts} +5 -5
  100. package/dist/resource.js +123 -0
  101. package/dist/session.d.ts +4 -0
  102. package/dist/session.js +3 -0
  103. package/dist/tenant-client.d.ts +169 -0
  104. package/dist/tenant-client.js +58 -0
  105. package/dist/{types/sdk/tenant-management.d.ts → tenant-management.d.ts} +6 -6
  106. package/dist/tenant-management.js +149 -0
  107. package/dist/{types/sdk/tenant-project.d.ts → tenant-project.d.ts} +1 -1
  108. package/dist/tenant-project.js +63 -0
  109. package/dist/{types/sdk/tenant-runtime.d.ts → tenant-runtime.d.ts} +1 -1
  110. package/dist/tenant-runtime.js +17 -0
  111. package/dist/{types/sdk/tenant-web-content.d.ts → tenant-web-content.d.ts} +1 -1
  112. package/dist/tenant-web-content.js +70 -0
  113. package/dist/{types/sdk/tenant-web-crawl.d.ts → tenant-web-crawl.d.ts} +1 -1
  114. package/dist/tenant-web-crawl.js +39 -0
  115. package/dist/{types/sdk/tenant-web-dynamic.d.ts → tenant-web-dynamic.d.ts} +1 -1
  116. package/dist/tenant-web-dynamic.js +39 -0
  117. package/dist/{types/sdk/tenant-web-workflow.d.ts → tenant-web-workflow.d.ts} +1 -1
  118. package/dist/tenant-web-workflow.js +63 -0
  119. package/dist/{types/sdk/tenant-web.d.ts → tenant-web.d.ts} +1 -1
  120. package/dist/tenant-web.js +39 -0
  121. package/dist/{types/sdk/tenant-workspace.d.ts → tenant-workspace.d.ts} +1 -1
  122. package/dist/tenant-workspace.js +21 -0
  123. package/dist/token-provider.d.ts +14 -0
  124. package/dist/token-provider.js +21 -0
  125. package/package.json +27 -15
  126. package/dist/types/contracts/resource-transfer.d.ts +0 -24
  127. package/dist/types/sdk/resource-integrity.d.ts +0 -21
  128. package/dist/types/sdk/transport.d.ts +0 -16
  129. /package/dist/{types → internal}/contracts/artifact.d.ts +0 -0
  130. /package/dist/{types → internal}/contracts/collection-control.d.ts +0 -0
  131. /package/dist/{types → internal}/contracts/collection.d.ts +0 -0
  132. /package/dist/{types → internal}/contracts/common.d.ts +0 -0
  133. /package/dist/{types → internal}/contracts/currentness.d.ts +0 -0
  134. /package/dist/{types → internal}/contracts/event.d.ts +0 -0
  135. /package/dist/{types → internal}/contracts/evidence.d.ts +0 -0
  136. /package/dist/{types → internal}/contracts/material-capability.d.ts +0 -0
  137. /package/dist/{types → internal}/contracts/material-carrier.d.ts +0 -0
  138. /package/dist/{types → internal}/contracts/material-context.d.ts +0 -0
  139. /package/dist/{types → internal}/contracts/material-read.d.ts +0 -0
  140. /package/dist/{types → internal}/contracts/observation.d.ts +0 -0
  141. /package/dist/{types → internal}/contracts/persistence.d.ts +0 -0
  142. /package/dist/{types → internal}/contracts/project-intent.d.ts +0 -0
  143. /package/dist/{types → internal}/contracts/projection.d.ts +0 -0
  144. /package/dist/{types → internal}/contracts/public-reference.d.ts +0 -0
  145. /package/dist/{types → internal}/contracts/reference-record.d.ts +0 -0
  146. /package/dist/{types → internal}/contracts/remote-file.d.ts +0 -0
  147. /package/dist/{types → internal}/contracts/resource-scope.d.ts +0 -0
  148. /package/dist/{types → internal}/contracts/review-packet.d.ts +0 -0
  149. /package/dist/{types → internal}/contracts/review-plane.d.ts +0 -0
  150. /package/dist/{types → internal}/contracts/rich-document.d.ts +0 -0
  151. /package/dist/{types → internal}/contracts/runtime-compatibility.d.ts +0 -0
  152. /package/dist/{types → internal}/contracts/runtime.d.ts +0 -0
  153. /package/dist/{types → internal}/contracts/scheduler.d.ts +0 -0
  154. /package/dist/{types → internal}/contracts/signal.d.ts +0 -0
  155. /package/dist/{types → internal}/contracts/source-governance.d.ts +0 -0
  156. /package/dist/{types → internal}/contracts/source.d.ts +0 -0
  157. /package/dist/{types → internal}/contracts/tenant-budget.d.ts +0 -0
  158. /package/dist/{types → internal}/contracts/tenant-collection-request.d.ts +0 -0
  159. /package/dist/{types → internal}/contracts/tenant-collection.d.ts +0 -0
  160. /package/dist/{types → internal}/contracts/tenant-currentness.d.ts +0 -0
  161. /package/dist/{types → internal}/contracts/tenant-management.d.ts +0 -0
  162. /package/dist/{types → internal}/contracts/tenant-material-api.d.ts +0 -0
  163. /package/dist/{types → internal}/contracts/tenant-pdf-text.d.ts +0 -0
  164. /package/dist/{types → internal}/contracts/tenant-project-control.d.ts +0 -0
  165. /package/dist/{types → internal}/contracts/tenant-public-reference.d.ts +0 -0
  166. /package/dist/{types → internal}/contracts/tenant-resource-api.d.ts +0 -0
  167. /package/dist/{types → internal}/contracts/tenant-resource.d.ts +0 -0
  168. /package/dist/{types → internal}/contracts/tenant-rich-document.d.ts +0 -0
  169. /package/dist/{types → internal}/contracts/tenant-source-binding.d.ts +0 -0
  170. /package/dist/{types → internal}/contracts/tenant-source-bridge.d.ts +0 -0
  171. /package/dist/{types → internal}/contracts/tenant-source-cutover.d.ts +0 -0
  172. /package/dist/{types → internal}/contracts/tenant-source-document.d.ts +0 -0
  173. /package/dist/{types → internal}/contracts/tenant-source-lease.d.ts +0 -0
  174. /package/dist/{types → internal}/contracts/tenant-source.d.ts +0 -0
  175. /package/dist/{types → internal}/contracts/tenant-web-collection.d.ts +0 -0
  176. /package/dist/{types → internal}/contracts/tenant-web-content-plan.d.ts +0 -0
  177. /package/dist/{types → internal}/contracts/tenant-web-content-result.d.ts +0 -0
  178. /package/dist/{types → internal}/contracts/tenant-web-content.d.ts +0 -0
  179. /package/dist/{types → internal}/contracts/tenant-web-crawl.d.ts +0 -0
  180. /package/dist/{types → internal}/contracts/tenant-web-dynamic.d.ts +0 -0
  181. /package/dist/{types → internal}/contracts/tenant-web-results.d.ts +0 -0
  182. /package/dist/{types → internal}/contracts/tenant-web-workflow.d.ts +0 -0
  183. /package/dist/{types → internal}/serving-contracts/agent-catalog.d.ts +0 -0
  184. /package/dist/{types → internal}/serving-contracts/agent-entry.d.ts +0 -0
  185. /package/dist/{types → internal}/serving-contracts/agent-guidance-shapes.d.ts +0 -0
  186. /package/dist/{types → internal}/serving-contracts/agent-input-hints.d.ts +0 -0
  187. /package/dist/{types → internal}/serving-contracts/body-search.d.ts +0 -0
  188. /package/dist/{types → internal}/serving-contracts/consumer.d.ts +0 -0
  189. /package/dist/{types → internal}/serving-contracts/core.d.ts +0 -0
  190. /package/dist/{types → internal}/serving-contracts/http.d.ts +0 -0
  191. /package/dist/{types → internal}/serving-contracts/management.d.ts +0 -0
  192. /package/dist/{types → internal}/serving-contracts/material-capabilities.d.ts +0 -0
  193. /package/dist/{types → internal}/serving-contracts/material-index-status.d.ts +0 -0
  194. /package/dist/{types → internal}/serving-contracts/mcp.d.ts +0 -0
  195. /package/dist/{types → internal}/serving-contracts/tenant-governance.d.ts +0 -0
  196. /package/dist/{types → internal}/serving-contracts/tenant-management.d.ts +0 -0
  197. /package/dist/{types → internal}/serving-contracts/tenant-project.d.ts +0 -0
  198. /package/dist/{types → internal}/serving-contracts/tenant-runtime.d.ts +0 -0
  199. /package/dist/{types → internal}/serving-contracts/tenant-web-content.d.ts +0 -0
  200. /package/dist/{types → internal}/serving-contracts/tenant-web-crawl.d.ts +0 -0
  201. /package/dist/{types → internal}/serving-contracts/tenant-web-dynamic.d.ts +0 -0
  202. /package/dist/{types → internal}/serving-contracts/tenant-web-workflow.d.ts +0 -0
  203. /package/dist/{types → internal}/serving-contracts/tenant-web.d.ts +0 -0
  204. /package/dist/{types → internal}/serving-contracts/tenant-workspace.d.ts +0 -0
  205. /package/dist/{types → internal}/serving-contracts/workflow.d.ts +0 -0
  206. /package/dist/{types/sdk/material-stream.d.ts → material-stream.d.ts} +0 -0
@@ -0,0 +1,171 @@
1
+ import { z } from 'zod';
2
+ import { accessClassificationSchema, idSchema, isoDateTimeSchema, projectKeySchema, schemaVersionSchema, sha256Schema, stableUriSchema, } from './common.js';
3
+ export const evidenceModalitySchema = z.enum(['TEXT', 'PDF', 'IMAGE', 'AUDIO', 'VIDEO', 'BINARY']);
4
+ export const evidenceReviewModeSchema = z.enum(['TEXT_NATIVE', 'MULTIMODAL_NATIVE', 'EXTERNAL_EXTRACTOR_REQUIRED']);
5
+ export const evidenceReviewInstructionSchema = z.enum([
6
+ 'READ_ORIGINAL_TEXT',
7
+ 'INSPECT_ORIGINAL_DOCUMENT',
8
+ 'INSPECT_ORIGINAL_IMAGE',
9
+ 'LISTEN_TO_ORIGINAL_AUDIO',
10
+ 'INSPECT_ORIGINAL_VIDEO',
11
+ 'USE_APPROVED_EXTERNAL_EXTRACTOR',
12
+ ]);
13
+ const pageRangeSchema = z.object({
14
+ startPage: z.number().int().positive(),
15
+ endPage: z.number().int().positive(),
16
+ }).strict().superRefine((value, ctx) => {
17
+ if (value.endPage < value.startPage)
18
+ ctx.addIssue({ code: 'custom', path: ['endPage'], message: 'endPage must be >= startPage' });
19
+ });
20
+ const timeRangeSchema = z.object({
21
+ startMs: z.number().int().nonnegative(),
22
+ endMs: z.number().int().nonnegative(),
23
+ }).strict().superRefine((value, ctx) => {
24
+ if (value.endMs < value.startMs)
25
+ ctx.addIssue({ code: 'custom', path: ['endMs'], message: 'endMs must be >= startMs' });
26
+ });
27
+ export const evidenceReviewHintsSchema = z.object({
28
+ pageRanges: z.array(pageRangeSchema).max(64).default([]),
29
+ timeRanges: z.array(timeRangeSchema).max(64).default([]),
30
+ frameTimestampsMs: z.array(z.number().int().nonnegative()).max(64).default([]),
31
+ }).strict();
32
+ export const evidenceReviewAttachmentSchema = z.object({
33
+ evidenceRef: stableUriSchema,
34
+ contentHash: sha256Schema,
35
+ mediaType: z.string().trim().min(1).max(256),
36
+ byteLength: z.number().int().nonnegative().nullable(),
37
+ modality: evidenceModalitySchema,
38
+ reviewMode: evidenceReviewModeSchema,
39
+ instruction: evidenceReviewInstructionSchema,
40
+ rawBytesEmbedded: z.literal(false),
41
+ materializationRequired: z.literal(true),
42
+ reviewHints: evidenceReviewHintsSchema.optional(),
43
+ }).strict().superRefine((value, ctx) => {
44
+ const expected = value.modality === 'TEXT' ? ['TEXT_NATIVE', 'READ_ORIGINAL_TEXT']
45
+ : value.modality === 'PDF' ? ['MULTIMODAL_NATIVE', 'INSPECT_ORIGINAL_DOCUMENT']
46
+ : value.modality === 'IMAGE' ? ['MULTIMODAL_NATIVE', 'INSPECT_ORIGINAL_IMAGE']
47
+ : value.modality === 'AUDIO' ? ['MULTIMODAL_NATIVE', 'LISTEN_TO_ORIGINAL_AUDIO']
48
+ : value.modality === 'VIDEO' ? ['MULTIMODAL_NATIVE', 'INSPECT_ORIGINAL_VIDEO']
49
+ : ['EXTERNAL_EXTRACTOR_REQUIRED', 'USE_APPROVED_EXTERNAL_EXTRACTOR'];
50
+ if (value.reviewMode !== expected[0])
51
+ ctx.addIssue({ code: 'custom', path: ['reviewMode'], message: `reviewMode must be ${expected[0]} for ${value.modality}` });
52
+ if (value.instruction !== expected[1])
53
+ ctx.addIssue({ code: 'custom', path: ['instruction'], message: `instruction must be ${expected[1]} for ${value.modality}` });
54
+ const hints = value.reviewHints;
55
+ if (hints?.pageRanges.length && value.modality !== 'PDF')
56
+ ctx.addIssue({ code: 'custom', path: ['reviewHints', 'pageRanges'], message: 'pageRanges require PDF modality' });
57
+ if (hints?.timeRanges.length && !['AUDIO', 'VIDEO'].includes(value.modality))
58
+ ctx.addIssue({ code: 'custom', path: ['reviewHints', 'timeRanges'], message: 'timeRanges require AUDIO or VIDEO modality' });
59
+ if (hints?.frameTimestampsMs.length && value.modality !== 'VIDEO')
60
+ ctx.addIssue({ code: 'custom', path: ['reviewHints', 'frameTimestampsMs'], message: 'frameTimestampsMs require VIDEO modality' });
61
+ });
62
+ export const evidenceMaterializationReceiptSchema = z.object({
63
+ schemaVersion: schemaVersionSchema,
64
+ evidenceRef: stableUriSchema,
65
+ contentHash: sha256Schema,
66
+ mediaType: z.string().trim().min(1).max(256),
67
+ byteLength: z.number().int().nonnegative(),
68
+ modality: evidenceModalitySchema,
69
+ reviewMode: evidenceReviewModeSchema,
70
+ instruction: evidenceReviewInstructionSchema,
71
+ reviewHints: evidenceReviewHintsSchema.optional(),
72
+ access: accessClassificationSchema,
73
+ runtimeNodeId: idSchema,
74
+ materializedAt: isoDateTimeSchema,
75
+ runtimeLocalPath: z.string().trim().min(1).max(4096).startsWith('/'),
76
+ reused: z.boolean(),
77
+ }).strict();
78
+ export const collectorIdentitySchema = z.object({
79
+ collectorId: idSchema,
80
+ version: z.string().trim().min(1).max(128),
81
+ }).strict();
82
+ /** 附属媒体沿用 Source 身份,但不能替代该 Source 的主文档。 */
83
+ export const RICH_MEDIA_COLLECTOR_ID = 'knowledge-v2.rich-document-media';
84
+ // 中文职责:保存只读 POST 的请求体对象索引,响应 contentHash 始终代表原始响应。
85
+ export const evidenceRequestSchema = z.object({
86
+ schemaVersion: z.literal(1), method: z.literal('POST'),
87
+ bodyContentHash: sha256Schema, bodyMediaType: z.literal('application/x-www-form-urlencoded'),
88
+ bodyByteLength: z.number().int().nonnegative().max(16 * 1024),
89
+ }).strict();
90
+ export const evidenceRefSchema = z.object({
91
+ // Re-admission preserves acquisition facts; this link records reuse rather than a new download.
92
+ recoveryProvenance: z.object({ mode: z.literal('REUSED_PRIOR_EVIDENCE'), originEvidenceRef: stableUriSchema, originProjectRef: stableUriSchema, originSourceRevisionRef: stableUriSchema, originRuntimeNodeId: idSchema, handoffReceiptRef: stableUriSchema }).strict().optional(),
93
+ request: evidenceRequestSchema.optional(),
94
+ schemaVersion: schemaVersionSchema,
95
+ evidenceId: idSchema,
96
+ sourceId: idSchema,
97
+ sourceIds: z.array(idSchema).min(1).max(64).optional(),
98
+ projectKey: projectKeySchema.optional(),
99
+ projectRef: stableUriSchema.optional(),
100
+ collector: collectorIdentitySchema,
101
+ contentHash: sha256Schema,
102
+ observedAt: isoDateTimeSchema,
103
+ runtimeNodeId: idSchema,
104
+ access: accessClassificationSchema,
105
+ canonicalUri: stableUriSchema.optional(),
106
+ mediaType: z.string().trim().min(1).max(256).optional(),
107
+ byteLength: z.number().int().nonnegative().optional(),
108
+ sourceSetRef: stableUriSchema.optional(),
109
+ sourceItemId: idSchema.optional(),
110
+ sourceRevisionRef: stableUriSchema.optional(),
111
+ collectionBatchRef: stableUriSchema.optional(),
112
+ collectionTaskId: idSchema.optional(),
113
+ reviewHints: evidenceReviewHintsSchema.optional(),
114
+ }).strict().superRefine((value, ctx) => {
115
+ if (value.recoveryProvenance) {
116
+ const origin = value.recoveryProvenance;
117
+ if (value.access !== 'PUBLIC')
118
+ ctx.addIssue({ code: 'custom', path: ['recoveryProvenance'], message: 'Recovery re-admission requires PUBLIC evidence' });
119
+ for (const [key, protocol] of [['originEvidenceRef', 'evidence:'], ['originProjectRef', 'knowledge-project:'], ['originSourceRevisionRef', 'project-source:'], ['handoffReceiptRef', 'runtime-handoff:']]) {
120
+ const url = new URL(origin[key]);
121
+ if (url.protocol !== protocol || url.hostname !== value.projectKey)
122
+ ctx.addIssue({ code: 'custom', path: ['recoveryProvenance', key], message: 'Recovery provenance must retain the same project and expected reference type' });
123
+ }
124
+ if (origin.originEvidenceRef === `evidence://${value.projectKey}/${encodeURIComponent(value.evidenceId)}`)
125
+ ctx.addIssue({ code: 'custom', path: ['recoveryProvenance'], message: 'Recovery origin cannot be self' });
126
+ }
127
+ if (Boolean(value.sourceSetRef) !== Boolean(value.sourceItemId))
128
+ ctx.addIssue({ code: 'custom', path: ['sourceSetRef'], message: 'sourceSetRef and sourceItemId must be provided together' });
129
+ if (Boolean(value.collectionBatchRef) !== Boolean(value.collectionTaskId))
130
+ ctx.addIssue({ code: 'custom', path: ['collectionBatchRef'], message: 'collectionBatchRef and collectionTaskId must be provided together' });
131
+ if (value.projectRef && value.projectKey) {
132
+ try {
133
+ const url = new URL(value.projectRef);
134
+ if (url.protocol !== 'knowledge-project:' || url.hostname.toLowerCase() !== value.projectKey.toLowerCase())
135
+ ctx.addIssue({ code: 'custom', path: ['projectRef'], message: 'projectRef project must match Evidence project' });
136
+ }
137
+ catch {
138
+ ctx.addIssue({ code: 'custom', path: ['projectRef'], message: 'Invalid projectRef' });
139
+ }
140
+ }
141
+ if (value.sourceSetRef && value.projectKey) {
142
+ try {
143
+ const url = new URL(value.sourceSetRef);
144
+ if (url.protocol !== 'source-set:' || url.hostname.toLowerCase() !== value.projectKey.toLowerCase())
145
+ ctx.addIssue({ code: 'custom', path: ['sourceSetRef'], message: 'sourceSetRef project must match Evidence project' });
146
+ }
147
+ catch {
148
+ ctx.addIssue({ code: 'custom', path: ['sourceSetRef'], message: 'Invalid sourceSetRef' });
149
+ }
150
+ }
151
+ if (value.sourceRevisionRef && value.projectKey) {
152
+ try {
153
+ const url = new URL(value.sourceRevisionRef);
154
+ if (url.protocol !== 'project-source:' || url.hostname.toLowerCase() !== value.projectKey.toLowerCase())
155
+ ctx.addIssue({ code: 'custom', path: ['sourceRevisionRef'], message: 'sourceRevisionRef project must match Evidence project' });
156
+ }
157
+ catch {
158
+ ctx.addIssue({ code: 'custom', path: ['sourceRevisionRef'], message: 'Invalid sourceRevisionRef' });
159
+ }
160
+ }
161
+ if (value.collectionBatchRef && value.projectKey) {
162
+ try {
163
+ const url = new URL(value.collectionBatchRef);
164
+ if (url.protocol !== 'collection-batch:' || url.hostname.toLowerCase() !== value.projectKey.toLowerCase())
165
+ ctx.addIssue({ code: 'custom', path: ['collectionBatchRef'], message: 'collectionBatchRef project must match Evidence project' });
166
+ }
167
+ catch {
168
+ ctx.addIssue({ code: 'custom', path: ['collectionBatchRef'], message: 'Invalid collectionBatchRef' });
169
+ }
170
+ }
171
+ });
@@ -52,4 +52,3 @@ export * from './tenant-web-content-plan.js';
52
52
  export * from './tenant-web-content-result.js';
53
53
  export * from './tenant-web-content.js';
54
54
  export * from './tenant-web-workflow.js';
55
- export * from './resource-transfer.js';
@@ -0,0 +1,54 @@
1
+ export * from './common.js';
2
+ export * from './source.js';
3
+ export * from './evidence.js';
4
+ export * from './observation.js';
5
+ export * from './runtime.js';
6
+ export * from './event.js';
7
+ export * from './signal.js';
8
+ export * from './artifact.js';
9
+ export * from './review-packet.js';
10
+ export * from './scheduler.js';
11
+ export * from './currentness.js';
12
+ export * from './projection.js';
13
+ export * from './source-governance.js';
14
+ export * from './review-plane.js';
15
+ export * from './persistence.js';
16
+ export * from './remote-file.js';
17
+ export * from './project-intent.js';
18
+ export * from './collection.js';
19
+ export * from './collection-control.js';
20
+ export * from './rich-document.js';
21
+ export * from './material-carrier.js';
22
+ export * from './reference-record.js';
23
+ export * from './material-read.js';
24
+ export * from './material-context.js';
25
+ export * from './tenant-material-api.js';
26
+ export * from './material-capability.js';
27
+ export * from './public-reference.js';
28
+ export * from './resource-scope.js';
29
+ export * from './tenant-resource.js';
30
+ export * from './tenant-resource-api.js';
31
+ export * from './tenant-source.js';
32
+ export * from './tenant-collection.js';
33
+ export * from './tenant-collection-request.js';
34
+ export * from './tenant-source-document.js';
35
+ export * from './tenant-source-bridge.js';
36
+ export * from './tenant-source-binding.js';
37
+ export * from './tenant-source-cutover.js';
38
+ export * from './tenant-rich-document.js';
39
+ export * from './tenant-management.js';
40
+ export * from './tenant-currentness.js';
41
+ export * from './tenant-public-reference.js';
42
+ export * from './tenant-project-control.js';
43
+ export * from './tenant-budget.js';
44
+ export * from './runtime-compatibility.js';
45
+ export * from './tenant-web-collection.js';
46
+ export * from './tenant-web-results.js';
47
+ export * from './tenant-web-crawl.js';
48
+ export * from './tenant-source-lease.js';
49
+ export * from './tenant-web-dynamic.js';
50
+ export * from './tenant-pdf-text.js';
51
+ export * from './tenant-web-content-plan.js';
52
+ export * from './tenant-web-content-result.js';
53
+ export * from './tenant-web-content.js';
54
+ export * from './tenant-web-workflow.js';
@@ -0,0 +1,8 @@
1
+ import { z } from 'zod';
2
+ import { rawRetrievalDecisionSchema, rawMaterialDirectoryItemSchema } from './material-read.js';
3
+ import { sha256Schema } from './common.js';
4
+ export const materialReadStateSchema = z.enum(['READY', 'UNSUPPORTED', 'MISSING', 'INTEGRITY_MISMATCH', 'DENIED']);
5
+ export const materialCapabilitySchema = z.object({
6
+ item: rawMaterialDirectoryItemSchema, materialAccess: rawRetrievalDecisionSchema,
7
+ representation: z.object({ state: materialReadStateSchema, format: z.enum(['BYTES', 'JSON']), transfer: z.enum(['VERIFIED_STREAM', 'BUFFERED_JSON', 'UNSUPPORTED']), contentHash: sha256Schema.nullable(), mediaType: z.string().min(1).max(256), byteLength: z.number().int().nonnegative().safe().nullable(), methods: z.array(z.enum(['GET', 'HEAD'])).max(2), range: z.enum(['SINGLE', 'NONE']), verification: z.literal('ON_READ'), verificationChunkBytes: z.number().int().positive().nullable() }).strict(),
8
+ }).strict();
@@ -0,0 +1,15 @@
1
+ import { z } from 'zod';
2
+ import { accessClassificationSchema, isoDateTimeSchema, projectKeySchema, sha256Schema, stableUriSchema } from './common.js';
3
+ export const materialResourceTypeSchema = z.string().regex(/^[a-z][a-z0-9._-]{0,63}$/);
4
+ /** Provenance-bearing immutable metadata; original bytes live only in the shared CAS. */
5
+ export const materialCarrierManifestSchema = z.object({
6
+ schemaVersion: z.literal(1), ref: stableUriSchema, projectKey: projectKeySchema, resourceType: materialResourceTypeSchema,
7
+ kind: z.string().min(1).max(128), access: accessClassificationSchema, title: z.string().max(512), summary: z.string().max(1024),
8
+ observedAt: isoDateTimeSchema, sourceRefs: z.array(stableUriSchema).min(1).max(128), sourceUri: stableUriSchema.nullable(), sourceSetRef: stableUriSchema.nullable().default(null),
9
+ storage: z.literal('CAS'), contentHash: sha256Schema, mediaType: z.string().min(1).max(256), byteLength: z.number().int().nonnegative().safe(),
10
+ }).strict().superRefine((value, ctx) => { if (value.sourceSetRef && !value.sourceSetRef.startsWith(`source-set://${value.projectKey}/`))
11
+ ctx.addIssue({ code: 'custom', path: ['sourceSetRef'], message: 'Source Set must belong to the material source project' }); if (['artifact', 'evidence', 'reference', 'media'].includes(value.resourceType))
12
+ ctx.addIssue({ code: 'custom', path: ['resourceType'], message: 'built-in carriers retain their existing canonical stores' }); });
13
+ export const materialRegistrationMetadataSchema = z.object({ ...materialCarrierManifestSchema.shape }).omit({ schemaVersion: true, contentHash: true, byteLength: true, storage: true });
14
+ export const materialRegistrationRequestSchema = z.object({ projectRef: stableUriSchema, metadata: materialRegistrationMetadataSchema, contentBase64: z.string().max(87384) }).strict();
15
+ export const materialRegistrationInputJsonSchema = z.toJSONSchema(materialRegistrationRequestSchema, { target: 'draft-07' });
@@ -0,0 +1,9 @@
1
+ import { z } from 'zod';
2
+ import { projectKeySchema, stableUriSchema } from './common.js';
3
+ export const materialTenantIdSchema = z.string().min(1).max(256).regex(/^[A-Za-z0-9][A-Za-z0-9._:-]*$/);
4
+ export const materialContextSchema = z.discriminatedUnion('type', [
5
+ z.object({ type: z.literal('TENANT'), tenantId: materialTenantIdSchema, tenantRef: stableUriSchema }).strict(),
6
+ z.object({ type: z.literal('PROJECT'), tenantId: materialTenantIdSchema, projectKey: projectKeySchema, projectRef: stableUriSchema }).strict(),
7
+ ]);
8
+ export const materialProjectScopeInputSchema = z.object({ mode: z.enum(['TENANT', 'EXPLICIT']).optional(), selectors: z.array(z.object({ type: z.enum(['SOURCE_PROJECT', 'REF']), value: z.string().min(1).max(4096), enabled: z.boolean() }).strict()).max(100).default([]) }).strict().superRefine((value, ctx) => { if (!value.mode && !value.selectors.length)
9
+ ctx.addIssue({ code: 'custom', message: 'An explicit scope mutation is required' }); });
@@ -0,0 +1,12 @@
1
+ /** Retrieval permissions and immutable descriptors, independent of business usage decisions. */
2
+ import { z } from 'zod';
3
+ import { accessClassificationSchema, idSchema, isoDateTimeSchema, projectKeySchema, schemaVersionSchema, sha256Schema, stableUriSchema } from './common.js';
4
+ import { materialResourceTypeSchema } from './material-carrier.js';
5
+ export const rawRetrievalProblemSchema = z.enum(['NOT_FOUND', 'CONTENT_ACCESS_DENIED', 'INTEGRITY_MISMATCH', 'UNAVAILABLE', 'UNSUPPORTED_RESOURCE']);
6
+ export const rawRetrievalDecisionSchema = z.object({ schemaVersion: schemaVersionSchema, action: z.enum(['ALLOW', 'DENY']), reasonCodes: z.array(rawRetrievalProblemSchema).max(32), assessedAt: isoDateTimeSchema }).strict().superRefine((value, ctx) => { if ((value.action === 'ALLOW') !== (value.reasonCodes.length === 0))
7
+ ctx.addIssue({ code: 'custom', path: ['reasonCodes'], message: 'Retrieval decision and reasons must agree' }); });
8
+ export const rawContentDescriptorSchema = z.object({ contentHash: sha256Schema, mediaType: z.string().trim().min(1).max(256), byteLength: z.number().int().nonnegative().safe() }).strict();
9
+ export const rawArtifactSummarySchema = z.object({ ref: stableUriSchema, identityRef: stableUriSchema, projectKey: projectKeySchema, projectRef: stableUriSchema.nullable().default(null), artifactId: idSchema, kind: z.string().trim().min(1).max(128), version: z.number().int().positive(), status: z.string().trim().min(1).max(128), access: accessClassificationSchema, title: z.string().max(500).nullable(), createdAt: isoDateTimeSchema, observedAt: isoDateTimeSchema.nullable(), validUntil: isoDateTimeSchema.nullable(), content: rawContentDescriptorSchema }).strict();
10
+ export const rawArtifactDetailSchema = rawArtifactSummarySchema.extend({ evidenceRefs: z.array(stableUriSchema).max(256), relatedRefs: z.array(stableUriSchema).max(256), supersedesRef: stableUriSchema.nullable() }).strict();
11
+ export const rawEvidenceSummarySchema = z.object({ evidenceRef: stableUriSchema, projectKey: projectKeySchema, sourceId: idSchema, contentHash: sha256Schema, observedAt: isoDateTimeSchema, access: accessClassificationSchema, canonicalUri: stableUriSchema.nullable(), mediaType: z.string().max(256).nullable(), byteLength: z.number().int().nonnegative().safe().nullable(), projectRef: stableUriSchema.nullable().default(null), sourceSetRef: stableUriSchema.nullable(), sourceItemId: idSchema.nullable(), sourceRevisionRef: stableUriSchema.nullable().default(null), collectionBatchRef: stableUriSchema.nullable().default(null), collectionTaskId: idSchema.nullable().default(null) }).strict();
12
+ export const rawMaterialDirectoryItemSchema = z.object({ ref: stableUriSchema, resourceType: materialResourceTypeSchema, sourceProjectKey: projectKeySchema, identityHash: sha256Schema, kind: z.string().min(1).max(128), classification: accessClassificationSchema, mediaType: z.string().min(1).max(256), decision: rawRetrievalDecisionSchema }).strict();
@@ -0,0 +1,39 @@
1
+ import { z } from 'zod';
2
+ import { idSchema, isoDateTimeSchema, projectKeySchema, schemaVersionSchema, sha256Schema, stableUriSchema, } from './common.js';
3
+ export const observationKindSchema = z.enum([
4
+ 'SOURCE_CHANGE',
5
+ 'WORLD_SIGNAL',
6
+ 'SOURCE_FAILURE',
7
+ 'BUSINESS_FEEDBACK',
8
+ 'AGENT_EVALUATION',
9
+ 'CONTENT_FEEDBACK',
10
+ 'OTHER',
11
+ ]);
12
+ export const observationSchema = z.object({
13
+ schemaVersion: schemaVersionSchema,
14
+ observationId: idSchema,
15
+ projectKey: projectKeySchema.optional(),
16
+ projectRef: stableUriSchema.optional(),
17
+ kind: observationKindSchema,
18
+ observedAt: isoDateTimeSchema,
19
+ expiresAt: isoDateTimeSchema.optional(),
20
+ evidenceRefs: z.array(stableUriSchema).min(1).max(256),
21
+ payloadHash: sha256Schema.optional(),
22
+ summary: z.string().trim().min(1).max(4000).optional(),
23
+ }).strict();
24
+ export const signalLaneSchema = z.enum(['DEMAND', 'PAIN', 'COMMERCIAL', 'OTHER']);
25
+ export const velocityStateSchema = z.enum(['NEW', 'RISING', 'STABLE', 'FALLING', 'REAPPEARED', 'UNKNOWN']);
26
+ export const signalObservationSchema = z.object({
27
+ schemaVersion: schemaVersionSchema,
28
+ observationId: idSchema,
29
+ projectKey: projectKeySchema.optional(),
30
+ projectRef: stableUriSchema.optional(),
31
+ observedAt: isoDateTimeSchema,
32
+ evidenceRefs: z.array(stableUriSchema).min(1).max(256),
33
+ signalFamily: z.string().trim().min(1).max(128),
34
+ subject: z.string().trim().min(1).max(1000),
35
+ lanes: z.array(signalLaneSchema).min(1).max(4),
36
+ velocity: velocityStateSchema,
37
+ attentionScore: z.number().finite().optional(),
38
+ sourceCount: z.number().int().nonnegative(),
39
+ }).strict();
@@ -0,0 +1,239 @@
1
+ import { z } from 'zod';
2
+ import { artifactKindSchema } from './artifact.js';
3
+ import { evidenceRefSchema } from './evidence.js';
4
+ import { accessClassificationSchema, idSchema, isoDateTimeSchema, projectKeySchema, schemaVersionSchema, sha256Schema, stableUriSchema, } from './common.js';
5
+ import { sourceDeclaredStateSchema } from './source-governance.js';
6
+ export const portableRelativePathSchema = z.string().trim().min(1).max(4096).superRefine((value, ctx) => {
7
+ if (value.startsWith('/') || value.includes('\\'))
8
+ ctx.addIssue({ code: 'custom', message: 'Path must be portable and relative' });
9
+ const parts = value.split('/');
10
+ if (parts.some((part) => !part || part === '.' || part === '..'))
11
+ ctx.addIssue({ code: 'custom', message: 'Path contains invalid segment' });
12
+ });
13
+ export const sourceSetRegistryHashSchema = z.object({
14
+ acquisitionSourceId: idSchema,
15
+ relativePath: portableRelativePathSchema,
16
+ contentHash: sha256Schema,
17
+ }).strict();
18
+ export const sourceSetItemBindingSchema = z.object({
19
+ acquisitionSourceId: idSchema,
20
+ concreteSourceId: idSchema,
21
+ authority: z.string().trim().min(1).max(512).nullable(),
22
+ access: accessClassificationSchema,
23
+ declaredGitSha: z.string().trim().min(1).max(128).nullable(),
24
+ }).strict();
25
+ export const sourceSetItemSchema = z.object({
26
+ itemId: idSchema,
27
+ kind: z.enum(['WEB', 'FILE']),
28
+ logicalSourceRef: stableUriSchema,
29
+ sourceIds: z.array(idSchema).min(1).max(64),
30
+ bindings: z.array(sourceSetItemBindingSchema).min(1).max(64),
31
+ contentPolicy: z.enum(['public-excerpt', 'metadata-only']),
32
+ cadenceMs: z.number().int().positive(),
33
+ url: z.url().nullable(),
34
+ rootBinding: projectKeySchema.nullable(),
35
+ relativePath: portableRelativePathSchema.nullable(),
36
+ }).strict().superRefine((value, ctx) => {
37
+ if (value.kind === 'WEB' && (!value.url || value.rootBinding || value.relativePath))
38
+ ctx.addIssue({ code: 'custom', path: ['url'], message: 'WEB item requires url only' });
39
+ if (value.kind === 'FILE' && (value.url || !value.rootBinding || !value.relativePath))
40
+ ctx.addIssue({ code: 'custom', path: ['relativePath'], message: 'FILE item requires rootBinding + relativePath only' });
41
+ });
42
+ export const sourceSetLogicalSourceSchema = z.object({
43
+ logicalSourceId: idSchema,
44
+ familyId: idSchema,
45
+ declaredState: sourceDeclaredStateSchema,
46
+ locator: stableUriSchema.nullable(),
47
+ acquisitionSourceIds: z.array(idSchema).max(64),
48
+ itemIds: z.array(idSchema).max(5000),
49
+ }).strict();
50
+ export const sourceSetSnapshotSchema = z.object({
51
+ schemaVersion: schemaVersionSchema,
52
+ sourceSetId: sha256Schema,
53
+ sourceSetRef: stableUriSchema,
54
+ projectKey: projectKeySchema,
55
+ programRevision: z.string().regex(/^[a-f0-9]{40,64}$/),
56
+ acquisitionConfigHash: sha256Schema,
57
+ sourceUniverseHash: sha256Schema.nullable(),
58
+ registryHashes: z.array(sourceSetRegistryHashSchema).max(256),
59
+ items: z.array(sourceSetItemSchema).max(20000),
60
+ logicalSources: z.array(sourceSetLogicalSourceSchema).max(5000),
61
+ }).strict().superRefine((value, ctx) => {
62
+ const digest = value.sourceSetId.slice('sha256:'.length);
63
+ if (value.sourceSetRef !== `source-set://${value.projectKey}/${digest}`)
64
+ ctx.addIssue({ code: 'custom', path: ['sourceSetRef'], message: 'sourceSetRef must match sourceSetId' });
65
+ const itemIds = value.items.map((row) => row.itemId);
66
+ if (new Set(itemIds).size !== itemIds.length)
67
+ ctx.addIssue({ code: 'custom', path: ['items'], message: 'itemId must be unique' });
68
+ const logicalIds = value.logicalSources.map((row) => row.logicalSourceId);
69
+ if (new Set(logicalIds).size !== logicalIds.length)
70
+ ctx.addIssue({ code: 'custom', path: ['logicalSources'], message: 'logicalSourceId must be unique' });
71
+ const registryKeys = value.registryHashes.map((row) => `${row.acquisitionSourceId}\n${row.relativePath}`);
72
+ if (new Set(registryKeys).size !== registryKeys.length)
73
+ ctx.addIssue({ code: 'custom', path: ['registryHashes'], message: 'registry hash binding must be unique' });
74
+ });
75
+ export const sourceSetPointerSchema = z.object({
76
+ schemaVersion: schemaVersionSchema,
77
+ projectKey: projectKeySchema,
78
+ sourceSetId: sha256Schema,
79
+ sourceSetRef: stableUriSchema,
80
+ manifestRelativePath: portableRelativePathSchema,
81
+ updatedAt: isoDateTimeSchema,
82
+ }).strict();
83
+ export const libraryProjectionSchema = z.object({
84
+ schemaVersion: schemaVersionSchema,
85
+ projectionId: sha256Schema,
86
+ projectKey: projectKeySchema,
87
+ subjectType: z.enum(['ARTIFACT', 'EVIDENCE']),
88
+ subjectRef: stableUriSchema,
89
+ contentHash: sha256Schema,
90
+ mediaType: z.string().trim().min(1).max(256),
91
+ byteLength: z.number().int().nonnegative(),
92
+ relativePath: portableRelativePathSchema,
93
+ manifestRelativePath: portableRelativePathSchema,
94
+ }).strict();
95
+ export const deliverySupportProofSchema = z.object({
96
+ action: z.literal('ALLOW'),
97
+ supportState: z.string().trim().min(1).max(128),
98
+ semanticHash: sha256Schema,
99
+ }).strict();
100
+ export const deliveryConsumerRequestSchema = z.object({
101
+ mediaType: z.string().trim().min(1).max(256),
102
+ contentHash: sha256Schema,
103
+ byteLength: z.number().int().nonnegative(),
104
+ }).strict();
105
+ export const knowledgeDeliveryEnvelopeSchema = z.object({
106
+ schemaVersion: schemaVersionSchema,
107
+ deliveryId: sha256Schema,
108
+ producerProjectKey: projectKeySchema,
109
+ producerProjectRef: stableUriSchema.optional(),
110
+ consumerKey: projectKeySchema,
111
+ artifactRef: stableUriSchema,
112
+ artifactKind: artifactKindSchema,
113
+ artifactAccess: accessClassificationSchema,
114
+ contentHash: sha256Schema,
115
+ mediaType: z.string().trim().min(1).max(256),
116
+ byteLength: z.number().int().nonnegative(),
117
+ libraryPath: portableRelativePathSchema,
118
+ observedAt: isoDateTimeSchema.nullable(),
119
+ validUntil: isoDateTimeSchema.nullable(),
120
+ support: deliverySupportProofSchema.nullable(),
121
+ consumerRequest: deliveryConsumerRequestSchema.nullable(),
122
+ createdAt: isoDateTimeSchema,
123
+ }).strict().superRefine((value, ctx) => { if (value.producerProjectRef) {
124
+ try {
125
+ const url = new URL(value.producerProjectRef);
126
+ if (url.protocol !== 'knowledge-project:' || url.hostname.toLowerCase() !== value.producerProjectKey.toLowerCase())
127
+ ctx.addIssue({ code: 'custom', path: ['producerProjectRef'], message: 'producerProjectRef project must match producer project' });
128
+ }
129
+ catch {
130
+ ctx.addIssue({ code: 'custom', path: ['producerProjectRef'], message: 'Invalid producerProjectRef' });
131
+ }
132
+ } });
133
+ export const knowledgeDeliveryClaimSchema = z.object({
134
+ schemaVersion: schemaVersionSchema,
135
+ deliveryId: sha256Schema,
136
+ producerProjectKey: projectKeySchema,
137
+ producerProjectRef: stableUriSchema.optional(),
138
+ consumerKey: projectKeySchema,
139
+ claimId: z.string().uuid(),
140
+ workerId: z.string().trim().min(1).max(128).regex(/^[A-Za-z0-9._-]+$/),
141
+ claimedAt: isoDateTimeSchema,
142
+ expiresAt: isoDateTimeSchema,
143
+ }).strict().superRefine((value, ctx) => {
144
+ if (value.producerProjectRef) {
145
+ try {
146
+ const url = new URL(value.producerProjectRef);
147
+ if (url.protocol !== 'knowledge-project:' || url.hostname.toLowerCase() !== value.producerProjectKey.toLowerCase())
148
+ ctx.addIssue({ code: 'custom', path: ['producerProjectRef'], message: 'producerProjectRef project must match producer project' });
149
+ }
150
+ catch {
151
+ ctx.addIssue({ code: 'custom', path: ['producerProjectRef'], message: 'Invalid producerProjectRef' });
152
+ }
153
+ }
154
+ const claimedAt = Date.parse(value.claimedAt), expiresAt = Date.parse(value.expiresAt), leaseSeconds = (expiresAt - claimedAt) / 1000;
155
+ if (expiresAt <= claimedAt)
156
+ ctx.addIssue({ code: 'custom', path: ['expiresAt'], message: 'Delivery claim expiry must be after claim time' });
157
+ else if (leaseSeconds < 30 || leaseSeconds > 3600)
158
+ ctx.addIssue({ code: 'custom', path: ['expiresAt'], message: 'Delivery claim lease must be between 30 and 3600 seconds' });
159
+ });
160
+ export const knowledgeDeliveryOutcomeSchema = z.enum(['DELIVERED', 'BLOCKED', 'FAILED_RETRYABLE', 'FAILED_TERMINAL']);
161
+ export const knowledgeDeliveryReceiptSchema = z.object({
162
+ schemaVersion: schemaVersionSchema,
163
+ deliveryId: sha256Schema,
164
+ producerProjectKey: projectKeySchema,
165
+ producerProjectRef: stableUriSchema.optional(),
166
+ consumerKey: projectKeySchema,
167
+ artifactRef: stableUriSchema,
168
+ contentHash: sha256Schema,
169
+ outcome: knowledgeDeliveryOutcomeSchema,
170
+ attempts: z.number().int().positive().max(999999),
171
+ deliveredAt: isoDateTimeSchema,
172
+ nextAttemptAt: isoDateTimeSchema.nullable(),
173
+ externalRef: stableUriSchema.nullable(),
174
+ consumerResponseHash: sha256Schema.nullable(),
175
+ message: z.string().trim().min(1).max(4000).nullable(),
176
+ }).strict().superRefine((value, ctx) => {
177
+ if (value.producerProjectRef) {
178
+ try {
179
+ const url = new URL(value.producerProjectRef);
180
+ if (url.protocol !== 'knowledge-project:' || url.hostname.toLowerCase() !== value.producerProjectKey.toLowerCase())
181
+ ctx.addIssue({ code: 'custom', path: ['producerProjectRef'], message: 'producerProjectRef project must match producer project' });
182
+ }
183
+ catch {
184
+ ctx.addIssue({ code: 'custom', path: ['producerProjectRef'], message: 'Invalid producerProjectRef' });
185
+ }
186
+ }
187
+ if (value.outcome === 'DELIVERED' && value.nextAttemptAt)
188
+ ctx.addIssue({ code: 'custom', path: ['nextAttemptAt'], message: 'DELIVERED cannot schedule retry' });
189
+ if (value.outcome === 'FAILED_RETRYABLE' && !value.nextAttemptAt)
190
+ ctx.addIssue({ code: 'custom', path: ['nextAttemptAt'], message: 'FAILED_RETRYABLE requires nextAttemptAt' });
191
+ if (value.outcome === 'FAILED_RETRYABLE' && value.nextAttemptAt && Date.parse(value.nextAttemptAt) <= Date.parse(value.deliveredAt))
192
+ ctx.addIssue({ code: 'custom', path: ['nextAttemptAt'], message: 'Retry must be scheduled after this attempt completes' });
193
+ if (value.outcome !== 'FAILED_RETRYABLE' && value.nextAttemptAt)
194
+ ctx.addIssue({ code: 'custom', path: ['nextAttemptAt'], message: 'Only retryable failure may schedule retry' });
195
+ });
196
+ export const distributionConsumerSchema = z.object({
197
+ consumerKey: projectKeySchema,
198
+ enabled: z.boolean(),
199
+ artifactKinds: z.array(artifactKindSchema).min(1).max(16),
200
+ acceptedAccess: z.array(accessClassificationSchema).min(1).max(7),
201
+ supportPolicy: z.enum(['NONE', 'REQUIRE_ALLOW']),
202
+ adapter: z.string().trim().min(1).max(128),
203
+ }).strict().superRefine((value, ctx) => {
204
+ if (value.artifactKinds.some((kind) => ['KNOWLEDGE', 'INSIGHT'].includes(kind)) && value.supportPolicy !== 'REQUIRE_ALLOW') {
205
+ ctx.addIssue({ code: 'custom', path: ['supportPolicy'], message: 'Knowledge/Insight distribution requires REQUIRE_ALLOW' });
206
+ }
207
+ if (new Set(value.acceptedAccess).size !== value.acceptedAccess.length)
208
+ ctx.addIssue({ code: 'custom', path: ['acceptedAccess'], message: 'acceptedAccess must be unique' });
209
+ });
210
+ export const distributionConfigSchema = z.object({
211
+ schemaVersion: schemaVersionSchema,
212
+ projectKey: projectKeySchema,
213
+ consumers: z.array(distributionConsumerSchema).max(128),
214
+ }).strict().superRefine((value, ctx) => {
215
+ const keys = value.consumers.map((row) => row.consumerKey);
216
+ if (new Set(keys).size !== keys.length)
217
+ ctx.addIssue({ code: 'custom', path: ['consumers'], message: 'consumerKey must be unique' });
218
+ });
219
+ export const durableEvidenceManifestSchema = z.object({
220
+ schemaVersion: schemaVersionSchema,
221
+ projectKey: projectKeySchema,
222
+ evidenceRef: stableUriSchema,
223
+ evidence: evidenceRefSchema,
224
+ }).strict().superRefine((value, ctx) => {
225
+ if (value.evidence.projectKey !== value.projectKey)
226
+ ctx.addIssue({ code: 'custom', path: ['evidence', 'projectKey'], message: 'Durable Evidence project must match manifest project' });
227
+ const expected = `evidence://${value.projectKey}/${encodeURIComponent(value.evidence.evidenceId)}`;
228
+ if (value.evidenceRef !== expected)
229
+ ctx.addIssue({ code: 'custom', path: ['evidenceRef'], message: 'Durable Evidence ref must match evidence identity' });
230
+ if (value.evidence.sourceSetRef) {
231
+ try {
232
+ if (new URL(value.evidence.sourceSetRef).hostname.toLowerCase() !== value.projectKey.toLowerCase())
233
+ ctx.addIssue({ code: 'custom', path: ['evidence', 'sourceSetRef'], message: 'Source Set project must match Evidence project' });
234
+ }
235
+ catch {
236
+ ctx.addIssue({ code: 'custom', path: ['evidence', 'sourceSetRef'], message: 'Invalid Source Set ref' });
237
+ }
238
+ }
239
+ });