@native-knowledge/cli 0.1.0-rc.1 → 0.1.0-rc.3
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/dist/agent-entry-cli.js +90 -0
- package/dist/auth-commands.js +102 -0
- package/dist/cli.js +106 -4874
- package/dist/commands.js +41 -0
- package/dist/download.js +45 -0
- package/dist/errors.js +7 -0
- package/dist/input.js +89 -0
- 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/internal/contracts/index.js +55 -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/resource-transfer.js +11 -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/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 +137 -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.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/profile-store.js +142 -0
- package/package.json +7 -17
- package/README.md +0 -28
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { isoDateTimeSchema, projectKeySchema, schemaVersionSchema, stableUriSchema } from './common.js';
|
|
3
|
+
export const currentnessStateSchema = z.enum(['CURRENT', 'DUE', 'STALE', 'BLOCKED', 'UNKNOWN']);
|
|
4
|
+
export const currentnessActionSchema = z.enum(['ALLOW', 'REVIEW_REQUIRED', 'DENY']);
|
|
5
|
+
export const currentnessSubjectKindSchema = z.enum(['SOURCE', 'EVIDENCE', 'ARTIFACT']);
|
|
6
|
+
export const currentnessPolicySchema = z.object({
|
|
7
|
+
schemaVersion: schemaVersionSchema,
|
|
8
|
+
dueAfterSeconds: z.number().int().min(60).max(366 * 24 * 60 * 60),
|
|
9
|
+
staleAfterSeconds: z.number().int().min(60).max(5 * 366 * 24 * 60 * 60),
|
|
10
|
+
staleAction: currentnessActionSchema.default('REVIEW_REQUIRED'),
|
|
11
|
+
unknownAction: currentnessActionSchema.default('REVIEW_REQUIRED'),
|
|
12
|
+
blockedAction: currentnessActionSchema.default('REVIEW_REQUIRED'),
|
|
13
|
+
}).strict().superRefine((value, ctx) => {
|
|
14
|
+
if (value.staleAfterSeconds < value.dueAfterSeconds) {
|
|
15
|
+
ctx.addIssue({ code: 'custom', path: ['staleAfterSeconds'], message: 'staleAfterSeconds must be >= dueAfterSeconds' });
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
export const currentnessReasonCodeSchema = z.enum([
|
|
19
|
+
'CURRENT_WITHIN_CADENCE',
|
|
20
|
+
'REFRESH_DUE',
|
|
21
|
+
'STALE_AFTER_THRESHOLD',
|
|
22
|
+
'SOURCE_BLOCKED',
|
|
23
|
+
'SOURCE_CONTENT_CHANGED',
|
|
24
|
+
'NO_SUCCESSFUL_OBSERVATION',
|
|
25
|
+
]);
|
|
26
|
+
export const currentnessAssessmentSchema = z.object({
|
|
27
|
+
schemaVersion: schemaVersionSchema,
|
|
28
|
+
subjectRef: stableUriSchema,
|
|
29
|
+
subjectKind: currentnessSubjectKindSchema,
|
|
30
|
+
projectRef: stableUriSchema.optional(),
|
|
31
|
+
sourceRevisionRef: stableUriSchema.optional(),
|
|
32
|
+
basisRef: stableUriSchema.nullable().default(null),
|
|
33
|
+
state: currentnessStateSchema,
|
|
34
|
+
action: currentnessActionSchema,
|
|
35
|
+
assessedAt: isoDateTimeSchema,
|
|
36
|
+
observedAt: isoDateTimeSchema.nullable().default(null),
|
|
37
|
+
lastSuccessAt: isoDateTimeSchema.nullable().default(null),
|
|
38
|
+
lastAttemptAt: isoDateTimeSchema.nullable().default(null),
|
|
39
|
+
dueAt: isoDateTimeSchema.nullable().default(null),
|
|
40
|
+
staleAt: isoDateTimeSchema.nullable().default(null),
|
|
41
|
+
ageSeconds: z.number().int().nonnegative().nullable().default(null),
|
|
42
|
+
reasonCode: currentnessReasonCodeSchema,
|
|
43
|
+
policy: currentnessPolicySchema,
|
|
44
|
+
}).strict();
|
|
45
|
+
export const claimCurrentnessStatusSchema = z.enum([
|
|
46
|
+
'CURRENT',
|
|
47
|
+
'PARTIALLY_SUPERSEDED',
|
|
48
|
+
'SUPERSEDED',
|
|
49
|
+
'PENDING_CURRENTNESS_REVIEW',
|
|
50
|
+
'HISTORICAL_REFERENCE',
|
|
51
|
+
'DYNAMIC_CURRENT',
|
|
52
|
+
'DYNAMIC_EXPIRED',
|
|
53
|
+
]);
|
|
54
|
+
export const claimCurrentnessRiskSchema = z.enum(['STANDARD', 'HIGH']);
|
|
55
|
+
export const claimTimeSensitivitySchema = z.enum(['DURABLE', 'TIME_SENSITIVE', 'DYNAMIC']);
|
|
56
|
+
export const claimReviewTriggerSchema = z.enum([
|
|
57
|
+
'SCHEDULED_REFRESH',
|
|
58
|
+
'SAME_URL_DIFFERENT_HASH',
|
|
59
|
+
'LATER_OFFICIAL_SOURCE',
|
|
60
|
+
'REGULATORY_ACTION',
|
|
61
|
+
'OPERATOR_TRANSITION',
|
|
62
|
+
'CORRECTION',
|
|
63
|
+
'DYNAMIC_EXPIRY',
|
|
64
|
+
'INITIAL_REVIEW',
|
|
65
|
+
]);
|
|
66
|
+
const evidenceUriSchema = stableUriSchema.refine((value) => value.toLowerCase().startsWith('evidence://'), 'claim provenance must use EvidenceRef');
|
|
67
|
+
const claimIdSchema = z.string().trim().min(1).max(128).regex(/^[A-Za-z0-9][A-Za-z0-9._:-]*$/);
|
|
68
|
+
export const claimCurrentnessChangeSchema = z.object({
|
|
69
|
+
schemaVersion: schemaVersionSchema,
|
|
70
|
+
artifactRef: stableUriSchema,
|
|
71
|
+
claimId: claimIdSchema,
|
|
72
|
+
scope: z.string().trim().min(1).max(1000),
|
|
73
|
+
status: claimCurrentnessStatusSchema,
|
|
74
|
+
risk: claimCurrentnessRiskSchema.default('STANDARD'),
|
|
75
|
+
timeSensitivity: claimTimeSensitivitySchema.default('DURABLE'),
|
|
76
|
+
effectiveFrom: isoDateTimeSchema.nullable().default(null),
|
|
77
|
+
effectiveUntil: isoDateTimeSchema.nullable().default(null),
|
|
78
|
+
discoveredAt: isoDateTimeSchema,
|
|
79
|
+
reviewTrigger: claimReviewTriggerSchema,
|
|
80
|
+
previousEvidenceRefs: z.array(evidenceUriSchema).max(64).default([]),
|
|
81
|
+
currentEvidenceRefs: z.array(evidenceUriSchema).max(64).default([]),
|
|
82
|
+
replacementArtifactRef: stableUriSchema.nullable().default(null),
|
|
83
|
+
reason: z.string().trim().min(1).max(4000),
|
|
84
|
+
}).strict().superRefine((value, ctx) => {
|
|
85
|
+
const prior = new Set(value.previousEvidenceRefs);
|
|
86
|
+
const current = new Set(value.currentEvidenceRefs);
|
|
87
|
+
if (prior.size !== value.previousEvidenceRefs.length)
|
|
88
|
+
ctx.addIssue({ code: 'custom', path: ['previousEvidenceRefs'], message: 'duplicate previous EvidenceRef' });
|
|
89
|
+
if (current.size !== value.currentEvidenceRefs.length)
|
|
90
|
+
ctx.addIssue({ code: 'custom', path: ['currentEvidenceRefs'], message: 'duplicate current EvidenceRef' });
|
|
91
|
+
if ([...prior].some((ref) => current.has(ref)))
|
|
92
|
+
ctx.addIssue({ code: 'custom', path: ['currentEvidenceRefs'], message: 'previous and current EvidenceRefs must be distinct' });
|
|
93
|
+
if (value.effectiveFrom && value.effectiveUntil && Date.parse(value.effectiveUntil) <= Date.parse(value.effectiveFrom)) {
|
|
94
|
+
ctx.addIssue({ code: 'custom', path: ['effectiveUntil'], message: 'effectiveUntil must be later than effectiveFrom' });
|
|
95
|
+
}
|
|
96
|
+
if (value.timeSensitivity === 'TIME_SENSITIVE' && value.status !== 'PENDING_CURRENTNESS_REVIEW' && !value.effectiveFrom) {
|
|
97
|
+
ctx.addIssue({ code: 'custom', path: ['effectiveFrom'], message: 'time-sensitive reviewed claims require source-grounded effectiveFrom' });
|
|
98
|
+
}
|
|
99
|
+
if (value.timeSensitivity === 'DYNAMIC' && !value.effectiveUntil) {
|
|
100
|
+
ctx.addIssue({ code: 'custom', path: ['effectiveUntil'], message: 'dynamic claims require an explicit expiry boundary' });
|
|
101
|
+
}
|
|
102
|
+
if (value.status === 'DYNAMIC_CURRENT' && value.effectiveUntil && Date.parse(value.effectiveUntil) <= Date.parse(value.discoveredAt)) {
|
|
103
|
+
ctx.addIssue({ code: 'custom', path: ['effectiveUntil'], message: 'dynamic current claim must still be valid when discovered' });
|
|
104
|
+
}
|
|
105
|
+
if (value.status === 'DYNAMIC_EXPIRED' && value.effectiveUntil && Date.parse(value.discoveredAt) < Date.parse(value.effectiveUntil)) {
|
|
106
|
+
ctx.addIssue({ code: 'custom', path: ['effectiveUntil'], message: 'dynamic expired claim requires discovery at or after expiry' });
|
|
107
|
+
}
|
|
108
|
+
if (['CURRENT', 'DYNAMIC_CURRENT'].includes(value.status) && value.currentEvidenceRefs.length === 0) {
|
|
109
|
+
ctx.addIssue({ code: 'custom', path: ['currentEvidenceRefs'], message: 'current claim requires exact current EvidenceRef' });
|
|
110
|
+
}
|
|
111
|
+
if (['PARTIALLY_SUPERSEDED', 'SUPERSEDED'].includes(value.status)) {
|
|
112
|
+
if (value.previousEvidenceRefs.length === 0)
|
|
113
|
+
ctx.addIssue({ code: 'custom', path: ['previousEvidenceRefs'], message: 'supersession requires previous EvidenceRef' });
|
|
114
|
+
if (value.currentEvidenceRefs.length === 0)
|
|
115
|
+
ctx.addIssue({ code: 'custom', path: ['currentEvidenceRefs'], message: 'supersession requires replacement/current EvidenceRef' });
|
|
116
|
+
}
|
|
117
|
+
if (['HISTORICAL_REFERENCE', 'DYNAMIC_EXPIRED'].includes(value.status) && value.previousEvidenceRefs.length === 0) {
|
|
118
|
+
ctx.addIssue({ code: 'custom', path: ['previousEvidenceRefs'], message: 'historical/expired claim requires retained prior EvidenceRef' });
|
|
119
|
+
}
|
|
120
|
+
if (value.status === 'PENDING_CURRENTNESS_REVIEW' && value.previousEvidenceRefs.length === 0 && value.currentEvidenceRefs.length === 0) {
|
|
121
|
+
ctx.addIssue({ code: 'custom', path: ['currentEvidenceRefs'], message: 'pending currentness review requires at least one exact EvidenceRef' });
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
export const claimCurrentnessDecisionSchema = claimCurrentnessChangeSchema.safeExtend({
|
|
125
|
+
reviewedAt: isoDateTimeSchema,
|
|
126
|
+
}).superRefine((value, ctx) => {
|
|
127
|
+
if (Date.parse(value.reviewedAt) < Date.parse(value.discoveredAt)) {
|
|
128
|
+
ctx.addIssue({ code: 'custom', path: ['reviewedAt'], message: 'reviewedAt must not precede discoveredAt' });
|
|
129
|
+
}
|
|
130
|
+
if (value.status === 'DYNAMIC_CURRENT' && value.effectiveUntil && Date.parse(value.reviewedAt) >= Date.parse(value.effectiveUntil)) {
|
|
131
|
+
ctx.addIssue({ code: 'custom', path: ['effectiveUntil'], message: 'dynamic current claim must not already be expired at review time' });
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
export const claimCurrentnessProposalSchema = z.object({
|
|
135
|
+
schemaVersion: schemaVersionSchema,
|
|
136
|
+
type: z.literal('CLAIM_CURRENTNESS_PROPOSAL'),
|
|
137
|
+
projectKey: projectKeySchema,
|
|
138
|
+
proposalId: z.string().trim().min(3).max(80).regex(/^[a-z0-9][a-z0-9._-]*$/),
|
|
139
|
+
artifactRef: stableUriSchema,
|
|
140
|
+
createdAt: isoDateTimeSchema,
|
|
141
|
+
changes: z.array(claimCurrentnessChangeSchema).min(1).max(256),
|
|
142
|
+
}).strict().superRefine((value, ctx) => {
|
|
143
|
+
const ids = new Set();
|
|
144
|
+
value.changes.forEach((change, index) => {
|
|
145
|
+
if (change.artifactRef !== value.artifactRef)
|
|
146
|
+
ctx.addIssue({ code: 'custom', path: ['changes', index, 'artifactRef'], message: 'claim change artifactRef must match proposal artifactRef' });
|
|
147
|
+
if (ids.has(change.claimId))
|
|
148
|
+
ctx.addIssue({ code: 'custom', path: ['changes', index, 'claimId'], message: 'duplicate claimId in proposal' });
|
|
149
|
+
ids.add(change.claimId);
|
|
150
|
+
if (Date.parse(change.discoveredAt) > Date.parse(value.createdAt))
|
|
151
|
+
ctx.addIssue({ code: 'custom', path: ['changes', index, 'discoveredAt'], message: 'discoveredAt must not be after proposal createdAt' });
|
|
152
|
+
});
|
|
153
|
+
});
|
|
154
|
+
export const claimCurrentnessLedgerSchema = z.object({
|
|
155
|
+
schemaVersion: schemaVersionSchema,
|
|
156
|
+
ledgerId: z.string().regex(/^sha256:[a-f0-9]{64}$/),
|
|
157
|
+
projectKey: projectKeySchema,
|
|
158
|
+
artifactRef: stableUriSchema,
|
|
159
|
+
proposalRef: stableUriSchema,
|
|
160
|
+
reviewRef: stableUriSchema,
|
|
161
|
+
reviewedAt: isoDateTimeSchema,
|
|
162
|
+
decisionsHash: z.string().regex(/^sha256:[a-f0-9]{64}$/),
|
|
163
|
+
decisions: z.array(claimCurrentnessDecisionSchema).min(1).max(256),
|
|
164
|
+
}).strict().superRefine((value, ctx) => {
|
|
165
|
+
const ids = new Set();
|
|
166
|
+
value.decisions.forEach((decision, index) => {
|
|
167
|
+
if (decision.artifactRef !== value.artifactRef)
|
|
168
|
+
ctx.addIssue({ code: 'custom', path: ['decisions', index, 'artifactRef'], message: 'decision artifactRef must match ledger artifactRef' });
|
|
169
|
+
if (decision.reviewedAt !== value.reviewedAt)
|
|
170
|
+
ctx.addIssue({ code: 'custom', path: ['decisions', index, 'reviewedAt'], message: 'decision reviewedAt must match ledger review' });
|
|
171
|
+
if (ids.has(decision.claimId))
|
|
172
|
+
ctx.addIssue({ code: 'custom', path: ['decisions', index, 'claimId'], message: 'duplicate claimId in ledger' });
|
|
173
|
+
ids.add(decision.claimId);
|
|
174
|
+
});
|
|
175
|
+
});
|
|
176
|
+
export const artifactSemanticStatusSchema = z.enum(['REVIEWED', 'SUPERSEDED']);
|
|
177
|
+
export const artifactSupportStateSchema = z.enum([
|
|
178
|
+
'CURRENTLY_SUPPORTED',
|
|
179
|
+
'REFRESH_DUE',
|
|
180
|
+
'CURRENTNESS_REVIEW_REQUIRED',
|
|
181
|
+
'CURRENTNESS_DENIED',
|
|
182
|
+
'SUPERSEDED',
|
|
183
|
+
]);
|
|
184
|
+
export const artifactSupportEvidenceSchema = z.object({
|
|
185
|
+
evidenceRef: stableUriSchema,
|
|
186
|
+
state: currentnessStateSchema,
|
|
187
|
+
action: currentnessActionSchema,
|
|
188
|
+
assessedAt: isoDateTimeSchema,
|
|
189
|
+
lastSuccessAt: isoDateTimeSchema.nullable(),
|
|
190
|
+
reasonCode: currentnessReasonCodeSchema,
|
|
191
|
+
}).strict();
|
|
192
|
+
export const artifactSupportAssessmentSchema = z.object({
|
|
193
|
+
schemaVersion: schemaVersionSchema,
|
|
194
|
+
artifactRef: stableUriSchema,
|
|
195
|
+
identityRef: stableUriSchema,
|
|
196
|
+
projectKey: projectKeySchema,
|
|
197
|
+
artifactKind: z.enum(['KNOWLEDGE', 'INSIGHT']),
|
|
198
|
+
semanticStatus: artifactSemanticStatusSchema,
|
|
199
|
+
supportState: artifactSupportStateSchema,
|
|
200
|
+
action: currentnessActionSchema,
|
|
201
|
+
assessedAt: isoDateTimeSchema,
|
|
202
|
+
validUntil: isoDateTimeSchema.nullable(),
|
|
203
|
+
evidence: z.array(artifactSupportEvidenceSchema).max(256),
|
|
204
|
+
claims: z.array(claimCurrentnessDecisionSchema).max(256).default([]),
|
|
205
|
+
missingEvidenceRefs: z.array(stableUriSchema).max(256),
|
|
206
|
+
reasonCodes: z.array(z.enum([
|
|
207
|
+
'ALL_EVIDENCE_CURRENT',
|
|
208
|
+
'EVIDENCE_REFRESH_DUE',
|
|
209
|
+
'EVIDENCE_REVIEW_REQUIRED',
|
|
210
|
+
'EVIDENCE_DENIED',
|
|
211
|
+
'EVIDENCE_CURRENTNESS_MISSING',
|
|
212
|
+
'ARTIFACT_EVIDENCE_REQUIRED',
|
|
213
|
+
'ARTIFACT_VALIDITY_EXPIRED',
|
|
214
|
+
'ARTIFACT_EXPLICITLY_SUPERSEDED',
|
|
215
|
+
'CLAIM_PARTIALLY_SUPERSEDED',
|
|
216
|
+
'CLAIM_PENDING_CURRENTNESS_REVIEW',
|
|
217
|
+
'CLAIM_SUPERSEDED',
|
|
218
|
+
'CLAIM_HISTORICAL_REFERENCE',
|
|
219
|
+
'CLAIM_DYNAMIC_EXPIRED',
|
|
220
|
+
])).min(1).max(32),
|
|
221
|
+
}).strict();
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { idSchema, isoDateTimeSchema, projectKeySchema, schemaVersionSchema, sha256Schema, stableUriSchema, } from './common.js';
|
|
3
|
+
export const knowledgeEventTypeSchema = z.enum([
|
|
4
|
+
'SOURCE_CHANGED',
|
|
5
|
+
'SOURCE_FAILURE',
|
|
6
|
+
'REVIEW_READY',
|
|
7
|
+
'APPROVAL_READY',
|
|
8
|
+
'MATERIAL_DRIFT',
|
|
9
|
+
'BOUNDARY_RISK',
|
|
10
|
+
'CURRENTNESS_RISK',
|
|
11
|
+
'CLOSURE_MILESTONE',
|
|
12
|
+
'SCHEDULER_FAILURE',
|
|
13
|
+
'SIGNAL_READY',
|
|
14
|
+
'GAP_READY',
|
|
15
|
+
'PROGRAM_EVOLUTION_READY',
|
|
16
|
+
]);
|
|
17
|
+
export const eventSeveritySchema = z.enum(['INFO', 'NORMAL', 'WARNING', 'CRITICAL']);
|
|
18
|
+
export const knowledgeEventSchema = z.object({
|
|
19
|
+
schemaVersion: schemaVersionSchema,
|
|
20
|
+
eventId: idSchema,
|
|
21
|
+
projectKey: projectKeySchema.optional(),
|
|
22
|
+
projectRef: stableUriSchema.optional(),
|
|
23
|
+
sourceRef: stableUriSchema.optional(),
|
|
24
|
+
sourceRevisionRef: stableUriSchema.optional(),
|
|
25
|
+
collectionBatchRef: stableUriSchema.optional(),
|
|
26
|
+
type: knowledgeEventTypeSchema,
|
|
27
|
+
severity: eventSeveritySchema,
|
|
28
|
+
createdAt: isoDateTimeSchema,
|
|
29
|
+
runtimeNodeId: idSchema.optional(),
|
|
30
|
+
artifactRef: stableUriSchema.optional(),
|
|
31
|
+
evidenceRefs: z.array(stableUriSchema).max(256).default([]),
|
|
32
|
+
contentHash: sha256Schema.optional(),
|
|
33
|
+
requiresUserAction: z.boolean(),
|
|
34
|
+
dedupeKey: z.string().trim().min(1).max(512),
|
|
35
|
+
}).strict();
|
|
@@ -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,55 @@
|
|
|
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';
|
|
55
|
+
export * from './resource-transfer.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();
|