@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.
- package/LICENSE +202 -21
- package/NOTICE +29 -0
- package/README.md +26 -38
- package/dist/{types/sdk/agent-entry.d.ts → agent-entry.d.ts} +3 -3
- package/dist/agent-entry.js +153 -0
- package/dist/{types/sdk/agent-guidance-error.d.ts → agent-guidance-error.d.ts} +1 -1
- package/dist/agent-guidance-error.js +46 -0
- package/dist/auth.d.ts +124 -0
- package/dist/auth.js +165 -0
- package/dist/{types/sdk/index.d.ts → index.d.ts} +15 -14
- package/dist/index.js +159 -6570
- package/dist/internal/contracts/artifact.js +103 -0
- package/dist/internal/contracts/collection-control.js +69 -0
- package/dist/internal/contracts/collection.js +174 -0
- package/dist/internal/contracts/common.js +16 -0
- package/dist/internal/contracts/currentness.js +221 -0
- package/dist/internal/contracts/event.js +35 -0
- package/dist/internal/contracts/evidence.js +171 -0
- package/dist/{types → internal}/contracts/index.d.ts +0 -1
- package/dist/internal/contracts/index.js +54 -0
- package/dist/internal/contracts/material-capability.js +8 -0
- package/dist/internal/contracts/material-carrier.js +15 -0
- package/dist/internal/contracts/material-context.js +9 -0
- package/dist/internal/contracts/material-read.js +12 -0
- package/dist/internal/contracts/observation.js +39 -0
- package/dist/internal/contracts/persistence.js +239 -0
- package/dist/internal/contracts/project-intent.js +121 -0
- package/dist/internal/contracts/projection.js +194 -0
- package/dist/internal/contracts/public-reference.js +87 -0
- package/dist/internal/contracts/reference-record.js +55 -0
- package/dist/internal/contracts/remote-file.js +159 -0
- package/dist/internal/contracts/resource-scope.js +38 -0
- package/dist/internal/contracts/review-packet.js +61 -0
- package/dist/internal/contracts/review-plane.js +89 -0
- package/dist/internal/contracts/rich-document.js +184 -0
- package/dist/internal/contracts/runtime-compatibility.js +55 -0
- package/dist/internal/contracts/runtime.js +68 -0
- package/dist/internal/contracts/scheduler.js +256 -0
- package/dist/internal/contracts/signal.js +77 -0
- package/dist/internal/contracts/source-governance.js +194 -0
- package/dist/internal/contracts/source.js +32 -0
- package/dist/internal/contracts/tenant-budget.js +34 -0
- package/dist/internal/contracts/tenant-collection-request.js +58 -0
- package/dist/internal/contracts/tenant-collection.js +66 -0
- package/dist/internal/contracts/tenant-currentness.js +26 -0
- package/dist/internal/contracts/tenant-management.js +27 -0
- package/dist/internal/contracts/tenant-material-api.js +46 -0
- package/dist/internal/contracts/tenant-material-json-schema.js +16 -0
- package/dist/internal/contracts/tenant-pdf-text.js +13 -0
- package/dist/internal/contracts/tenant-project-control.js +19 -0
- package/dist/internal/contracts/tenant-public-reference.js +26 -0
- package/dist/internal/contracts/tenant-resource-api.js +70 -0
- package/dist/internal/contracts/tenant-resource.js +118 -0
- package/dist/internal/contracts/tenant-rich-document.js +17 -0
- package/dist/internal/contracts/tenant-source-binding.js +33 -0
- package/dist/internal/contracts/tenant-source-bridge.js +9 -0
- package/dist/internal/contracts/tenant-source-cutover.js +26 -0
- package/dist/internal/contracts/tenant-source-document.js +38 -0
- package/dist/internal/contracts/tenant-source-lease.js +5 -0
- package/dist/internal/contracts/tenant-source.js +83 -0
- package/dist/internal/contracts/tenant-web-collection.js +118 -0
- package/dist/internal/contracts/tenant-web-content-plan.js +39 -0
- package/dist/internal/contracts/tenant-web-content-result.js +15 -0
- package/dist/internal/contracts/tenant-web-content.js +16 -0
- package/dist/internal/contracts/tenant-web-crawl.js +55 -0
- package/dist/internal/contracts/tenant-web-dynamic.js +68 -0
- package/dist/internal/contracts/tenant-web-results.js +41 -0
- package/dist/internal/contracts/tenant-web-workflow.js +29 -0
- package/dist/internal/serving-contracts/agent-catalog.js +56 -0
- package/dist/internal/serving-contracts/agent-entry.js +57 -0
- package/dist/internal/serving-contracts/agent-guidance-shapes.js +12 -0
- package/dist/internal/serving-contracts/agent-input-hints.js +104 -0
- package/dist/internal/serving-contracts/body-search.js +16 -0
- package/dist/internal/serving-contracts/consumer.js +45 -0
- package/dist/internal/serving-contracts/core.js +76 -0
- package/dist/internal/serving-contracts/http.js +64 -0
- package/dist/{types → internal}/serving-contracts/index.d.ts +1 -0
- package/dist/internal/serving-contracts/index.js +25 -0
- package/dist/internal/serving-contracts/management.js +15 -0
- package/dist/internal/serving-contracts/material-capabilities.js +14 -0
- package/dist/internal/serving-contracts/material-index-status.js +5 -0
- package/dist/internal/serving-contracts/mcp.js +140 -0
- package/dist/internal/serving-contracts/tenant-governance.js +13 -0
- package/dist/internal/serving-contracts/tenant-management.js +89 -0
- package/dist/internal/serving-contracts/tenant-project.js +39 -0
- package/dist/internal/serving-contracts/tenant-runtime.js +37 -0
- package/dist/internal/serving-contracts/tenant-session.d.ts +87 -0
- package/dist/internal/serving-contracts/tenant-session.js +8 -0
- package/dist/internal/serving-contracts/tenant-web-content.js +20 -0
- package/dist/internal/serving-contracts/tenant-web-crawl.js +13 -0
- package/dist/internal/serving-contracts/tenant-web-dynamic.js +20 -0
- package/dist/internal/serving-contracts/tenant-web-workflow.js +36 -0
- package/dist/internal/serving-contracts/tenant-web.js +53 -0
- package/dist/internal/serving-contracts/tenant-workspace.js +28 -0
- package/dist/internal/serving-contracts/workflow.js +37 -0
- package/dist/material-stream.js +29 -0
- package/dist/{types/sdk/oauth.d.ts → oauth.d.ts} +18 -18
- package/dist/oauth.js +539 -0
- package/dist/{types/sdk/resource.d.ts → resource.d.ts} +5 -5
- package/dist/resource.js +123 -0
- package/dist/session.d.ts +4 -0
- package/dist/session.js +3 -0
- package/dist/tenant-client.d.ts +169 -0
- package/dist/tenant-client.js +58 -0
- package/dist/{types/sdk/tenant-management.d.ts → tenant-management.d.ts} +6 -6
- package/dist/tenant-management.js +149 -0
- package/dist/{types/sdk/tenant-project.d.ts → tenant-project.d.ts} +1 -1
- package/dist/tenant-project.js +63 -0
- package/dist/{types/sdk/tenant-runtime.d.ts → tenant-runtime.d.ts} +1 -1
- package/dist/tenant-runtime.js +17 -0
- package/dist/{types/sdk/tenant-web-content.d.ts → tenant-web-content.d.ts} +1 -1
- package/dist/tenant-web-content.js +70 -0
- package/dist/{types/sdk/tenant-web-crawl.d.ts → tenant-web-crawl.d.ts} +1 -1
- package/dist/tenant-web-crawl.js +39 -0
- package/dist/{types/sdk/tenant-web-dynamic.d.ts → tenant-web-dynamic.d.ts} +1 -1
- package/dist/tenant-web-dynamic.js +39 -0
- package/dist/{types/sdk/tenant-web-workflow.d.ts → tenant-web-workflow.d.ts} +1 -1
- package/dist/tenant-web-workflow.js +63 -0
- package/dist/{types/sdk/tenant-web.d.ts → tenant-web.d.ts} +1 -1
- package/dist/tenant-web.js +39 -0
- package/dist/{types/sdk/tenant-workspace.d.ts → tenant-workspace.d.ts} +1 -1
- package/dist/tenant-workspace.js +21 -0
- package/dist/token-provider.d.ts +14 -0
- package/dist/token-provider.js +21 -0
- package/package.json +27 -15
- package/dist/types/contracts/resource-transfer.d.ts +0 -24
- package/dist/types/sdk/resource-integrity.d.ts +0 -21
- package/dist/types/sdk/transport.d.ts +0 -16
- /package/dist/{types → internal}/contracts/artifact.d.ts +0 -0
- /package/dist/{types → internal}/contracts/collection-control.d.ts +0 -0
- /package/dist/{types → internal}/contracts/collection.d.ts +0 -0
- /package/dist/{types → internal}/contracts/common.d.ts +0 -0
- /package/dist/{types → internal}/contracts/currentness.d.ts +0 -0
- /package/dist/{types → internal}/contracts/event.d.ts +0 -0
- /package/dist/{types → internal}/contracts/evidence.d.ts +0 -0
- /package/dist/{types → internal}/contracts/material-capability.d.ts +0 -0
- /package/dist/{types → internal}/contracts/material-carrier.d.ts +0 -0
- /package/dist/{types → internal}/contracts/material-context.d.ts +0 -0
- /package/dist/{types → internal}/contracts/material-read.d.ts +0 -0
- /package/dist/{types → internal}/contracts/observation.d.ts +0 -0
- /package/dist/{types → internal}/contracts/persistence.d.ts +0 -0
- /package/dist/{types → internal}/contracts/project-intent.d.ts +0 -0
- /package/dist/{types → internal}/contracts/projection.d.ts +0 -0
- /package/dist/{types → internal}/contracts/public-reference.d.ts +0 -0
- /package/dist/{types → internal}/contracts/reference-record.d.ts +0 -0
- /package/dist/{types → internal}/contracts/remote-file.d.ts +0 -0
- /package/dist/{types → internal}/contracts/resource-scope.d.ts +0 -0
- /package/dist/{types → internal}/contracts/review-packet.d.ts +0 -0
- /package/dist/{types → internal}/contracts/review-plane.d.ts +0 -0
- /package/dist/{types → internal}/contracts/rich-document.d.ts +0 -0
- /package/dist/{types → internal}/contracts/runtime-compatibility.d.ts +0 -0
- /package/dist/{types → internal}/contracts/runtime.d.ts +0 -0
- /package/dist/{types → internal}/contracts/scheduler.d.ts +0 -0
- /package/dist/{types → internal}/contracts/signal.d.ts +0 -0
- /package/dist/{types → internal}/contracts/source-governance.d.ts +0 -0
- /package/dist/{types → internal}/contracts/source.d.ts +0 -0
- /package/dist/{types → internal}/contracts/tenant-budget.d.ts +0 -0
- /package/dist/{types → internal}/contracts/tenant-collection-request.d.ts +0 -0
- /package/dist/{types → internal}/contracts/tenant-collection.d.ts +0 -0
- /package/dist/{types → internal}/contracts/tenant-currentness.d.ts +0 -0
- /package/dist/{types → internal}/contracts/tenant-management.d.ts +0 -0
- /package/dist/{types → internal}/contracts/tenant-material-api.d.ts +0 -0
- /package/dist/{types → internal}/contracts/tenant-pdf-text.d.ts +0 -0
- /package/dist/{types → internal}/contracts/tenant-project-control.d.ts +0 -0
- /package/dist/{types → internal}/contracts/tenant-public-reference.d.ts +0 -0
- /package/dist/{types → internal}/contracts/tenant-resource-api.d.ts +0 -0
- /package/dist/{types → internal}/contracts/tenant-resource.d.ts +0 -0
- /package/dist/{types → internal}/contracts/tenant-rich-document.d.ts +0 -0
- /package/dist/{types → internal}/contracts/tenant-source-binding.d.ts +0 -0
- /package/dist/{types → internal}/contracts/tenant-source-bridge.d.ts +0 -0
- /package/dist/{types → internal}/contracts/tenant-source-cutover.d.ts +0 -0
- /package/dist/{types → internal}/contracts/tenant-source-document.d.ts +0 -0
- /package/dist/{types → internal}/contracts/tenant-source-lease.d.ts +0 -0
- /package/dist/{types → internal}/contracts/tenant-source.d.ts +0 -0
- /package/dist/{types → internal}/contracts/tenant-web-collection.d.ts +0 -0
- /package/dist/{types → internal}/contracts/tenant-web-content-plan.d.ts +0 -0
- /package/dist/{types → internal}/contracts/tenant-web-content-result.d.ts +0 -0
- /package/dist/{types → internal}/contracts/tenant-web-content.d.ts +0 -0
- /package/dist/{types → internal}/contracts/tenant-web-crawl.d.ts +0 -0
- /package/dist/{types → internal}/contracts/tenant-web-dynamic.d.ts +0 -0
- /package/dist/{types → internal}/contracts/tenant-web-results.d.ts +0 -0
- /package/dist/{types → internal}/contracts/tenant-web-workflow.d.ts +0 -0
- /package/dist/{types → internal}/serving-contracts/agent-catalog.d.ts +0 -0
- /package/dist/{types → internal}/serving-contracts/agent-entry.d.ts +0 -0
- /package/dist/{types → internal}/serving-contracts/agent-guidance-shapes.d.ts +0 -0
- /package/dist/{types → internal}/serving-contracts/agent-input-hints.d.ts +0 -0
- /package/dist/{types → internal}/serving-contracts/body-search.d.ts +0 -0
- /package/dist/{types → internal}/serving-contracts/consumer.d.ts +0 -0
- /package/dist/{types → internal}/serving-contracts/core.d.ts +0 -0
- /package/dist/{types → internal}/serving-contracts/http.d.ts +0 -0
- /package/dist/{types → internal}/serving-contracts/management.d.ts +0 -0
- /package/dist/{types → internal}/serving-contracts/material-capabilities.d.ts +0 -0
- /package/dist/{types → internal}/serving-contracts/material-index-status.d.ts +0 -0
- /package/dist/{types → internal}/serving-contracts/mcp.d.ts +0 -0
- /package/dist/{types → internal}/serving-contracts/tenant-governance.d.ts +0 -0
- /package/dist/{types → internal}/serving-contracts/tenant-management.d.ts +0 -0
- /package/dist/{types → internal}/serving-contracts/tenant-project.d.ts +0 -0
- /package/dist/{types → internal}/serving-contracts/tenant-runtime.d.ts +0 -0
- /package/dist/{types → internal}/serving-contracts/tenant-web-content.d.ts +0 -0
- /package/dist/{types → internal}/serving-contracts/tenant-web-crawl.d.ts +0 -0
- /package/dist/{types → internal}/serving-contracts/tenant-web-dynamic.d.ts +0 -0
- /package/dist/{types → internal}/serving-contracts/tenant-web-workflow.d.ts +0 -0
- /package/dist/{types → internal}/serving-contracts/tenant-web.d.ts +0 -0
- /package/dist/{types → internal}/serving-contracts/tenant-workspace.d.ts +0 -0
- /package/dist/{types → internal}/serving-contracts/workflow.d.ts +0 -0
- /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
|
+
});
|
|
@@ -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
|
+
});
|