@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,256 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { idSchema, isoDateTimeSchema, projectKeySchema, schemaVersionSchema } from './common.js';
|
|
3
|
+
import { signalProfileNameSchema } from './signal.js';
|
|
4
|
+
import { runtimeCapabilitySchema } from './runtime.js';
|
|
5
|
+
export const TIPP_UNIVERSE_MAX_RESOURCE_BYTES = 8 * 1024 * 1024;
|
|
6
|
+
const deploymentPathSchema = z.string().trim().min(1).max(4096).refine((value) => !value.includes('\0'), 'path must not contain NUL');
|
|
7
|
+
const scheduledWorkloadBaseSchema = z.object({
|
|
8
|
+
workloadId: idSchema,
|
|
9
|
+
projectKey: projectKeySchema,
|
|
10
|
+
priority: z.number().int().min(0).max(1000),
|
|
11
|
+
intervalSeconds: z.number().int().min(60).max(7 * 24 * 60 * 60),
|
|
12
|
+
timeoutSeconds: z.number().int().min(30).max(2 * 60 * 60).default(15 * 60),
|
|
13
|
+
assignmentFile: deploymentPathSchema,
|
|
14
|
+
initialDueAt: isoDateTimeSchema.optional(),
|
|
15
|
+
}).strict();
|
|
16
|
+
const acquisitionInvocationSchema = z.object({
|
|
17
|
+
command: z.literal('acquisition-run'),
|
|
18
|
+
programDirectory: deploymentPathSchema,
|
|
19
|
+
fileRootsFile: deploymentPathSchema.optional(),
|
|
20
|
+
}).strict();
|
|
21
|
+
const reviewPacketInvocationSchema = z.object({
|
|
22
|
+
command: z.literal('review-packet-project'),
|
|
23
|
+
}).strict();
|
|
24
|
+
// 自动发布只消费已持久化的事件和 Agent 输入,不触发任何来源采集。
|
|
25
|
+
const autoPublicationInvocationSchema = z.object({
|
|
26
|
+
command: z.literal('auto-publication-tick'),
|
|
27
|
+
// 同项目发布并发有固定上限;旧 manifest 无此字段时采用 Runner 默认值。
|
|
28
|
+
concurrency: z.number().int().min(1).max(4).optional(),
|
|
29
|
+
}).strict();
|
|
30
|
+
const publicReferenceInvocationSchema = z.object({ command: z.literal('public-reference-tick'), policyFile: deploymentPathSchema, identityDatabase: deploymentPathSchema }).strict();
|
|
31
|
+
const feedProjectInvocationSchema = z.object({
|
|
32
|
+
command: z.literal('feed-project'),
|
|
33
|
+
}).strict();
|
|
34
|
+
const procurementProjectInvocationSchema = z.object({
|
|
35
|
+
command: z.literal('procurement-project'),
|
|
36
|
+
}).strict();
|
|
37
|
+
const pkValuationStatusProjectInvocationSchema = z.object({
|
|
38
|
+
command: z.literal('pk-valuation-status-project'),
|
|
39
|
+
}).strict();
|
|
40
|
+
const pkStandardsProjectInvocationSchema = z.object({
|
|
41
|
+
command: z.literal('pk-standards-project'),
|
|
42
|
+
}).strict();
|
|
43
|
+
const cpecProjectInvocationSchema = z.object({
|
|
44
|
+
command: z.literal('cpec-project'),
|
|
45
|
+
}).strict();
|
|
46
|
+
const tippUniverseProjectInvocationSchema = z.object({
|
|
47
|
+
command: z.literal('tipp-universe-project'),
|
|
48
|
+
chapterBatch: z.number().int().min(1).max(96).default(4),
|
|
49
|
+
maxResourceBytes: z.number().int().min(64 * 1024).max(16 * 1024 * 1024).default(TIPP_UNIVERSE_MAX_RESOURCE_BYTES),
|
|
50
|
+
}).strict();
|
|
51
|
+
const tippDetailProjectInvocationSchema = z.object({
|
|
52
|
+
command: z.literal('tipp-detail-project'),
|
|
53
|
+
detailBatch: z.number().int().min(1).max(1000).default(50),
|
|
54
|
+
detailConcurrency: z.number().int().min(1).max(4).optional(),
|
|
55
|
+
maxResourceBytes: z.number().int().min(64 * 1024).max(16 * 1024 * 1024).default(4 * 1024 * 1024),
|
|
56
|
+
}).strict();
|
|
57
|
+
const tippTariffProjectInvocationSchema = z.object({
|
|
58
|
+
command: z.literal('tipp-tariff-project'),
|
|
59
|
+
}).strict();
|
|
60
|
+
const tippRegulatoryProjectInvocationSchema = z.object({
|
|
61
|
+
command: z.literal('tipp-regulatory-project'),
|
|
62
|
+
}).strict();
|
|
63
|
+
const pkTariffReconciliationProjectInvocationSchema = z.object({
|
|
64
|
+
command: z.literal('pk-tariff-reconciliation-project'),
|
|
65
|
+
}).strict();
|
|
66
|
+
const collectionInvocationSchema = z.object({
|
|
67
|
+
command: z.literal('collection-tick'),
|
|
68
|
+
maxResourceBytes: z.number().int().min(1024).max(64 * 1024 * 1024).default(16 * 1024 * 1024),
|
|
69
|
+
batchLimit: z.number().int().min(1).max(10_000).default(100),
|
|
70
|
+
fileRootsFile: deploymentPathSchema.optional(),
|
|
71
|
+
}).strict();
|
|
72
|
+
const collectionProjectionInvocationSchema = z.object({ command: z.literal('collection-projection-tick'), limit: z.number().int().min(1).max(100).default(25) }).strict();
|
|
73
|
+
const signalCollectInvocationSchema = z.object({
|
|
74
|
+
command: z.literal('signal-collect'),
|
|
75
|
+
programFile: deploymentPathSchema,
|
|
76
|
+
profile: signalProfileNameSchema,
|
|
77
|
+
}).strict();
|
|
78
|
+
const signalComposeInvocationSchema = z.object({
|
|
79
|
+
command: z.literal('signal-compose'),
|
|
80
|
+
programFile: deploymentPathSchema,
|
|
81
|
+
}).strict();
|
|
82
|
+
const customsCorpusInvocationSchema = z.object({
|
|
83
|
+
command: z.literal('customs-corpus-run'),
|
|
84
|
+
programFile: deploymentPathSchema,
|
|
85
|
+
adapter: z.enum(['us-hts', 'us-cross', 'ca-tariff', 'ca-rulings', 'eu-ebti', 'pk-tariff', 'pk-import-sro', 'pk-tax-authorities', 'pk-classification', 'pk-valuation', 'za-determinations', 'eg-nafeza', 'ae-tariff', 'sa-tariff', 'ru-eaeu']),
|
|
86
|
+
refreshStoredDocuments: z.boolean().optional(),
|
|
87
|
+
// GCC 重新访问官方来源必须显式启用,历史文件导入不触发网络。
|
|
88
|
+
refreshRemoteBundle: z.boolean().optional(),
|
|
89
|
+
}).strict();
|
|
90
|
+
const locationCorpusInvocationSchema = z.object({
|
|
91
|
+
command: z.literal('location-corpus-run'),
|
|
92
|
+
programFile: deploymentPathSchema,
|
|
93
|
+
adapter: z.literal('unlocode'),
|
|
94
|
+
}).strict();
|
|
95
|
+
export const schedulerInvocationSchema = z.discriminatedUnion('command', [
|
|
96
|
+
z.object({ command: z.literal('business-information-collect'), maxSources: z.number().int().min(1).max(32).default(8), maxResourceBytes: z.number().int().min(1024).max(16 * 1024 * 1024).default(2 * 1024 * 1024), fileRootsFile: deploymentPathSchema.optional() }).strict(),
|
|
97
|
+
z.object({ command: z.literal('pk-import-rules-project'), acquireLinkedDocuments: z.boolean().default(false), documentBatch: z.number().int().min(1).max(50).default(20), maxDocumentBytes: z.number().int().min(1024).max(32 * 1024 * 1024).default(16 * 1024 * 1024) }).strict(),
|
|
98
|
+
acquisitionInvocationSchema,
|
|
99
|
+
collectionInvocationSchema,
|
|
100
|
+
collectionProjectionInvocationSchema,
|
|
101
|
+
z.object({ command: z.literal('project-projection-tick'),
|
|
102
|
+
maxRows: z.number().int().min(1).max(100).optional(),
|
|
103
|
+
maxDependencyRows: z.number().int().min(1).max(10000).optional(),
|
|
104
|
+
maxBytes: z.number().int().min(1).max(16 * 1024 ** 3).optional(),
|
|
105
|
+
maxMs: z.number().int().min(1).max(600000).optional(),
|
|
106
|
+
}).strict(),
|
|
107
|
+
reviewPacketInvocationSchema,
|
|
108
|
+
autoPublicationInvocationSchema,
|
|
109
|
+
publicReferenceInvocationSchema,
|
|
110
|
+
feedProjectInvocationSchema,
|
|
111
|
+
procurementProjectInvocationSchema,
|
|
112
|
+
pkValuationStatusProjectInvocationSchema,
|
|
113
|
+
pkStandardsProjectInvocationSchema,
|
|
114
|
+
cpecProjectInvocationSchema,
|
|
115
|
+
tippUniverseProjectInvocationSchema,
|
|
116
|
+
tippDetailProjectInvocationSchema,
|
|
117
|
+
tippTariffProjectInvocationSchema,
|
|
118
|
+
tippRegulatoryProjectInvocationSchema,
|
|
119
|
+
pkTariffReconciliationProjectInvocationSchema,
|
|
120
|
+
signalCollectInvocationSchema,
|
|
121
|
+
signalComposeInvocationSchema,
|
|
122
|
+
customsCorpusInvocationSchema,
|
|
123
|
+
locationCorpusInvocationSchema,
|
|
124
|
+
]);
|
|
125
|
+
export const scheduledWorkloadSchema = scheduledWorkloadBaseSchema.extend({
|
|
126
|
+
invocation: schedulerInvocationSchema,
|
|
127
|
+
}).strict().superRefine((value, ctx) => {
|
|
128
|
+
let expected;
|
|
129
|
+
switch (value.invocation.command) {
|
|
130
|
+
case 'acquisition-run':
|
|
131
|
+
expected = `project:${value.projectKey}:acquisition`;
|
|
132
|
+
break;
|
|
133
|
+
case 'collection-projection-tick':
|
|
134
|
+
expected = `project:${value.projectKey}:material-projection`;
|
|
135
|
+
break;
|
|
136
|
+
case 'project-projection-tick':
|
|
137
|
+
expected = `project:${value.projectKey}:catalog-projection`;
|
|
138
|
+
break;
|
|
139
|
+
case 'collection-tick':
|
|
140
|
+
expected = `project:${value.projectKey}:collection`;
|
|
141
|
+
break;
|
|
142
|
+
case 'review-packet-project':
|
|
143
|
+
expected = `project:${value.projectKey}:review-packets`;
|
|
144
|
+
break;
|
|
145
|
+
case 'auto-publication-tick':
|
|
146
|
+
expected = `project:${value.projectKey}:auto-publication`;
|
|
147
|
+
break;
|
|
148
|
+
case 'public-reference-tick':
|
|
149
|
+
expected = `project:${value.projectKey}:public-reference-publication`;
|
|
150
|
+
break;
|
|
151
|
+
case 'feed-project':
|
|
152
|
+
expected = `project:${value.projectKey}:feed-project`;
|
|
153
|
+
break;
|
|
154
|
+
case 'procurement-project':
|
|
155
|
+
expected = `project:${value.projectKey}:procurement-project`;
|
|
156
|
+
break;
|
|
157
|
+
case 'pk-valuation-status-project':
|
|
158
|
+
expected = `project:${value.projectKey}:pk-valuation-status-project`;
|
|
159
|
+
break;
|
|
160
|
+
case 'pk-standards-project':
|
|
161
|
+
expected = `project:${value.projectKey}:pk-standards-project`;
|
|
162
|
+
break;
|
|
163
|
+
case 'pk-import-rules-project':
|
|
164
|
+
expected = `project:${value.projectKey}:pk-import-rules-project`;
|
|
165
|
+
break;
|
|
166
|
+
case 'cpec-project':
|
|
167
|
+
expected = `project:${value.projectKey}:cpec-project`;
|
|
168
|
+
break;
|
|
169
|
+
case 'business-information-collect':
|
|
170
|
+
expected = `project:${value.projectKey}:business-information-collect`;
|
|
171
|
+
break;
|
|
172
|
+
case 'tipp-universe-project':
|
|
173
|
+
expected = `project:${value.projectKey}:tipp-universe-project`;
|
|
174
|
+
break;
|
|
175
|
+
case 'tipp-detail-project':
|
|
176
|
+
expected = `project:${value.projectKey}:tipp-detail-project`;
|
|
177
|
+
break;
|
|
178
|
+
case 'tipp-tariff-project':
|
|
179
|
+
expected = `project:${value.projectKey}:tipp-tariff-project`;
|
|
180
|
+
break;
|
|
181
|
+
case 'tipp-regulatory-project':
|
|
182
|
+
expected = `project:${value.projectKey}:tipp-regulatory-project`;
|
|
183
|
+
break;
|
|
184
|
+
case 'pk-tariff-reconciliation-project':
|
|
185
|
+
expected = `project:${value.projectKey}:pk-tariff-reconciliation-project`;
|
|
186
|
+
break;
|
|
187
|
+
case 'signal-collect':
|
|
188
|
+
expected = `project:${value.projectKey}:signal:${value.invocation.profile}`;
|
|
189
|
+
break;
|
|
190
|
+
case 'signal-compose':
|
|
191
|
+
expected = `project:${value.projectKey}:signal:compose`;
|
|
192
|
+
break;
|
|
193
|
+
case 'customs-corpus-run':
|
|
194
|
+
expected = `project:${value.projectKey}:customs:${value.invocation.adapter}`;
|
|
195
|
+
break;
|
|
196
|
+
case 'location-corpus-run':
|
|
197
|
+
expected = `project:${value.projectKey}:locations:${value.invocation.adapter}`;
|
|
198
|
+
break;
|
|
199
|
+
}
|
|
200
|
+
if (value.workloadId !== expected) {
|
|
201
|
+
ctx.addIssue({ code: 'custom', path: ['workloadId'], message: `workloadId must be ${expected}` });
|
|
202
|
+
}
|
|
203
|
+
});
|
|
204
|
+
export const nodeSchedulerManifestSchema = z.object({
|
|
205
|
+
schemaVersion: schemaVersionSchema,
|
|
206
|
+
nodeId: idSchema,
|
|
207
|
+
capabilities: z.array(runtimeCapabilitySchema).max(128).default(['network:http']),
|
|
208
|
+
maxWorkloadsPerTick: z.number().int().min(1).max(32).default(8),
|
|
209
|
+
workloads: z.array(scheduledWorkloadSchema).max(256),
|
|
210
|
+
}).strict().superRefine((value, ctx) => {
|
|
211
|
+
const seen = new Set();
|
|
212
|
+
const capabilities = new Set(value.capabilities);
|
|
213
|
+
value.workloads.forEach((workload, index) => {
|
|
214
|
+
if (seen.has(workload.workloadId))
|
|
215
|
+
ctx.addIssue({ code: 'custom', path: ['workloads', index, 'workloadId'], message: 'duplicate workloadId' });
|
|
216
|
+
seen.add(workload.workloadId);
|
|
217
|
+
if (workload.invocation.command === 'business-information-collect' && !capabilities.has('network:http'))
|
|
218
|
+
ctx.addIssue({ code: 'custom', path: ['workloads', index, 'invocation'], message: 'public business collection requires network:http capability' });
|
|
219
|
+
if ((workload.invocation.command === 'collection-tick' || workload.invocation.command === 'collection-projection-tick') && !capabilities.has('network:http')) {
|
|
220
|
+
ctx.addIssue({ code: 'custom', path: ['workloads', index, 'invocation'], message: 'collection tick requires network:http capability' });
|
|
221
|
+
}
|
|
222
|
+
if (workload.invocation.command === 'signal-collect') {
|
|
223
|
+
if (!capabilities.has('network:http')) {
|
|
224
|
+
ctx.addIssue({ code: 'custom', path: ['workloads', index, 'invocation'], message: 'signal collection requires network:http capability' });
|
|
225
|
+
}
|
|
226
|
+
if (['tiktok', 'douyin', 'meta', 'deep-social'].includes(workload.invocation.profile) && !capabilities.has('browser:playwright')) {
|
|
227
|
+
ctx.addIssue({ code: 'custom', path: ['workloads', index, 'invocation'], message: `profile ${workload.invocation.profile} requires browser:playwright capability` });
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
if (workload.invocation.command === 'location-corpus-run' && !capabilities.has('network:http')) {
|
|
231
|
+
ctx.addIssue({ code: 'custom', path: ['workloads', index, 'invocation'], message: 'reference corpus collection requires network:http capability' });
|
|
232
|
+
}
|
|
233
|
+
if (workload.invocation.command === 'tipp-universe-project' && !capabilities.has('network:http')) {
|
|
234
|
+
ctx.addIssue({ code: 'custom', path: ['workloads', index, 'invocation'], message: 'TIPP universe collection requires network:http capability' });
|
|
235
|
+
}
|
|
236
|
+
if (workload.invocation.command === 'tipp-detail-project' && !capabilities.has('network:http')) {
|
|
237
|
+
ctx.addIssue({ code: 'custom', path: ['workloads', index, 'invocation'], message: 'TIPP detail collection requires network:http capability' });
|
|
238
|
+
}
|
|
239
|
+
if (workload.invocation.command === 'customs-corpus-run') {
|
|
240
|
+
if (workload.invocation.refreshRemoteBundle) {
|
|
241
|
+
if (!['ae-tariff', 'sa-tariff'].includes(workload.invocation.adapter))
|
|
242
|
+
ctx.addIssue({ code: 'custom', path: ['workloads', index, 'invocation', 'refreshRemoteBundle'], message: 'GCC refresh requires ae-tariff or sa-tariff adapter' });
|
|
243
|
+
if (!capabilities.has('network:http'))
|
|
244
|
+
ctx.addIssue({ code: 'custom', path: ['workloads', index, 'invocation'], message: 'GCC refresh requires network:http capability' });
|
|
245
|
+
}
|
|
246
|
+
if (workload.invocation.refreshStoredDocuments && !['pk-import-sro', 'ru-eaeu'].includes(workload.invocation.adapter)) {
|
|
247
|
+
ctx.addIssue({ code: 'custom', path: ['workloads', index, 'invocation', 'refreshStoredDocuments'], message: 'stored document refresh requires pk-import-sro or ru-eaeu adapter' });
|
|
248
|
+
}
|
|
249
|
+
const localVerifiedBundleAdapter = ['pk-valuation', 'za-determinations', 'ae-tariff', 'sa-tariff'].includes(workload.invocation.adapter);
|
|
250
|
+
if (!localVerifiedBundleAdapter && !capabilities.has('network:http')) {
|
|
251
|
+
ctx.addIssue({ code: 'custom', path: ['workloads', index, 'invocation'], message: `customs adapter ${workload.invocation.adapter} requires network:http capability` });
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
});
|
|
255
|
+
});
|
|
256
|
+
export const scheduledWorkerCommands = schedulerInvocationSchema.options.map(option => option.shape.command.value);
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { idSchema, isoDateTimeSchema, projectKeySchema, schemaVersionSchema, sha256Schema, stableUriSchema, } from './common.js';
|
|
3
|
+
export const signalProfileNameSchema = z.enum([
|
|
4
|
+
'trends',
|
|
5
|
+
'hn',
|
|
6
|
+
'github',
|
|
7
|
+
'autocomplete',
|
|
8
|
+
'youtube',
|
|
9
|
+
'tiktok',
|
|
10
|
+
'douyin',
|
|
11
|
+
'meta',
|
|
12
|
+
'deep-social',
|
|
13
|
+
]);
|
|
14
|
+
export const signalSourceHealthSchema = z.object({
|
|
15
|
+
ok: z.boolean(),
|
|
16
|
+
items: z.number().int().nonnegative().optional(),
|
|
17
|
+
state: z.string().trim().min(1).max(128).optional(),
|
|
18
|
+
note: z.string().trim().max(2000).optional(),
|
|
19
|
+
error: z.string().trim().max(2000).optional(),
|
|
20
|
+
}).catchall(z.unknown());
|
|
21
|
+
export const signalSourceSnapshotSchema = z.object({
|
|
22
|
+
schemaVersion: schemaVersionSchema,
|
|
23
|
+
projectKey: projectKeySchema,
|
|
24
|
+
projectRef: stableUriSchema.optional(),
|
|
25
|
+
sourceRef: stableUriSchema.optional(),
|
|
26
|
+
sourceRevisionRef: stableUriSchema.optional(),
|
|
27
|
+
sourceKey: idSchema,
|
|
28
|
+
profile: signalProfileNameSchema,
|
|
29
|
+
collectedAt: isoDateTimeSchema,
|
|
30
|
+
contentHash: sha256Schema,
|
|
31
|
+
evidenceId: idSchema,
|
|
32
|
+
signalCount: z.number().int().nonnegative(),
|
|
33
|
+
health: signalSourceHealthSchema,
|
|
34
|
+
}).strict();
|
|
35
|
+
export const signalSourceAttemptSchema = z.object({
|
|
36
|
+
schemaVersion: schemaVersionSchema,
|
|
37
|
+
projectKey: projectKeySchema,
|
|
38
|
+
projectRef: stableUriSchema.optional(),
|
|
39
|
+
sourceRef: stableUriSchema.optional(),
|
|
40
|
+
sourceRevisionRef: stableUriSchema.optional(),
|
|
41
|
+
sourceKey: idSchema,
|
|
42
|
+
profile: signalProfileNameSchema,
|
|
43
|
+
lastAttemptAt: isoDateTimeSchema,
|
|
44
|
+
lastSuccessAt: isoDateTimeSchema.nullable(),
|
|
45
|
+
success: z.boolean(),
|
|
46
|
+
durationMs: z.number().int().nonnegative(),
|
|
47
|
+
state: z.string().trim().min(1).max(128).nullable(),
|
|
48
|
+
error: z.string().trim().max(2000).nullable(),
|
|
49
|
+
}).strict();
|
|
50
|
+
export const signalGenerationSchema = z.object({
|
|
51
|
+
schemaVersion: schemaVersionSchema,
|
|
52
|
+
projectKey: projectKeySchema,
|
|
53
|
+
projectRef: stableUriSchema.optional(),
|
|
54
|
+
generationKey: sha256Schema,
|
|
55
|
+
scoringProfile: z.string().trim().min(1).max(128),
|
|
56
|
+
generatedAt: isoDateTimeSchema,
|
|
57
|
+
snapshotManifest: z.record(idSchema, sha256Schema),
|
|
58
|
+
historyBasis: z.array(sha256Schema).max(512).default([]),
|
|
59
|
+
contentHash: sha256Schema,
|
|
60
|
+
candidateCount: z.number().int().nonnegative(),
|
|
61
|
+
observationCount: z.number().int().nonnegative(),
|
|
62
|
+
}).strict();
|
|
63
|
+
export const signalHistoryCandidateSchema = z.object({
|
|
64
|
+
query: z.string().trim().min(1).max(1000),
|
|
65
|
+
score: z.number().finite(),
|
|
66
|
+
sources: z.array(idSchema).max(64),
|
|
67
|
+
}).strict();
|
|
68
|
+
export const signalHistorySeedSchema = z.object({
|
|
69
|
+
schemaVersion: schemaVersionSchema,
|
|
70
|
+
projectKey: projectKeySchema,
|
|
71
|
+
projectRef: stableUriSchema.optional(),
|
|
72
|
+
historyKey: sha256Schema,
|
|
73
|
+
generatedAt: isoDateTimeSchema,
|
|
74
|
+
scoringVersion: z.number().int().positive(),
|
|
75
|
+
origin: z.string().trim().min(1).max(128),
|
|
76
|
+
candidates: z.array(signalHistoryCandidateSchema).max(120),
|
|
77
|
+
}).strict();
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { accessClassificationSchema, idSchema, isoDateTimeSchema, projectKeySchema, schemaVersionSchema, stableUriSchema, } from './common.js';
|
|
3
|
+
export const sourceExpectationSchema = z.enum(['REQUIRED', 'OPTIONAL', 'CONDITIONAL']);
|
|
4
|
+
export const sourceDeclaredStateSchema = z.enum([
|
|
5
|
+
'CONFIGURED',
|
|
6
|
+
'PENDING_DISCOVERY',
|
|
7
|
+
'KNOWN_MISSING',
|
|
8
|
+
'ACCESS_CONTROLLED',
|
|
9
|
+
'NEED_AUTHORIZED_SOURCE',
|
|
10
|
+
'DEFERRED',
|
|
11
|
+
'RETIRED',
|
|
12
|
+
]);
|
|
13
|
+
export const sourceCoverageStateSchema = z.enum([
|
|
14
|
+
'ACQUIRED',
|
|
15
|
+
'CONFIGURED_UNOBSERVED',
|
|
16
|
+
'PARTIAL',
|
|
17
|
+
'BLOCKED',
|
|
18
|
+
'ACCESS_CONTROLLED',
|
|
19
|
+
'PENDING_DISCOVERY',
|
|
20
|
+
'KNOWN_MISSING',
|
|
21
|
+
'NEED_AUTHORIZED_SOURCE',
|
|
22
|
+
'DEFERRED',
|
|
23
|
+
'RETIRED',
|
|
24
|
+
]);
|
|
25
|
+
const shortText = z.string().trim().min(1).max(512);
|
|
26
|
+
const roleSchema = z.string().trim().min(1).max(256);
|
|
27
|
+
export const sourceDiscoveryPolicySchema = z.object({
|
|
28
|
+
hostMode: z.enum(['ALLOWLIST', 'EVIDENCE_OBSERVED']).default('ALLOWLIST'),
|
|
29
|
+
allowedHosts: z.array(z.string().trim().toLowerCase().min(1).max(253)).max(256).default([]),
|
|
30
|
+
forbiddenHostSuffixes: z.array(z.string().trim().toLowerCase().min(1).max(253)).max(256).default([]),
|
|
31
|
+
allowedPathPrefixes: z.array(z.string().trim().startsWith('/').max(2048)).min(1).max(128),
|
|
32
|
+
}).strict().superRefine((value, ctx) => {
|
|
33
|
+
if (value.hostMode === 'ALLOWLIST' && !value.allowedHosts.length)
|
|
34
|
+
ctx.addIssue({ code: 'custom', path: ['allowedHosts'], message: 'ALLOWLIST discovery requires at least one allowed host' });
|
|
35
|
+
const allowed = new Set(value.allowedHosts);
|
|
36
|
+
for (const suffix of value.forbiddenHostSuffixes)
|
|
37
|
+
if (allowed.has(suffix))
|
|
38
|
+
ctx.addIssue({ code: 'custom', path: ['forbiddenHostSuffixes'], message: `Host cannot be both allowed and forbidden: ${suffix}` });
|
|
39
|
+
});
|
|
40
|
+
export const sourceUniverseEntrySchema = z.object({
|
|
41
|
+
sourceId: idSchema,
|
|
42
|
+
familyId: idSchema,
|
|
43
|
+
acquisitionSourceIds: z.array(idSchema).max(64).default([]),
|
|
44
|
+
expectation: sourceExpectationSchema,
|
|
45
|
+
authority: shortText,
|
|
46
|
+
access: accessClassificationSchema,
|
|
47
|
+
freshness: shortText,
|
|
48
|
+
semanticRoles: z.array(roleSchema).max(64).default([]),
|
|
49
|
+
locator: stableUriSchema.nullable().default(null),
|
|
50
|
+
declaredState: sourceDeclaredStateSchema,
|
|
51
|
+
expectedOwner: shortText.nullable().default(null),
|
|
52
|
+
requiredFor: z.array(idSchema).max(128).default([]),
|
|
53
|
+
discoveryPolicy: sourceDiscoveryPolicySchema.nullable().default(null),
|
|
54
|
+
notes: z.string().trim().max(2000).nullable().default(null),
|
|
55
|
+
}).strict().superRefine((value, ctx) => {
|
|
56
|
+
if (value.declaredState === 'CONFIGURED' && value.locator === null) {
|
|
57
|
+
ctx.addIssue({ code: 'custom', path: ['locator'], message: 'CONFIGURED source requires locator' });
|
|
58
|
+
}
|
|
59
|
+
if (['PENDING_DISCOVERY', 'KNOWN_MISSING', 'ACCESS_CONTROLLED', 'NEED_AUTHORIZED_SOURCE'].includes(value.declaredState) && value.expectation === 'OPTIONAL' && !value.requiredFor.length) {
|
|
60
|
+
ctx.addIssue({ code: 'custom', path: ['requiredFor'], message: 'unresolved optional source must declare why it is tracked' });
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
export const sourceUniverseSchema = z.object({
|
|
64
|
+
schemaVersion: schemaVersionSchema,
|
|
65
|
+
projectKey: projectKeySchema,
|
|
66
|
+
asOf: isoDateTimeSchema,
|
|
67
|
+
sources: z.array(sourceUniverseEntrySchema).min(1).max(5000),
|
|
68
|
+
}).strict().superRefine((value, ctx) => {
|
|
69
|
+
const ids = new Set();
|
|
70
|
+
for (let i = 0; i < value.sources.length; i += 1) {
|
|
71
|
+
const id = value.sources[i].sourceId;
|
|
72
|
+
if (ids.has(id))
|
|
73
|
+
ctx.addIssue({ code: 'custom', path: ['sources', i, 'sourceId'], message: 'sourceId must be unique' });
|
|
74
|
+
ids.add(id);
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
export const sourceCoverageEntrySchema = z.object({
|
|
78
|
+
sourceId: idSchema,
|
|
79
|
+
familyId: idSchema,
|
|
80
|
+
expectation: sourceExpectationSchema,
|
|
81
|
+
declaredState: sourceDeclaredStateSchema,
|
|
82
|
+
coverageState: sourceCoverageStateSchema,
|
|
83
|
+
configuredItemCount: z.number().int().nonnegative(),
|
|
84
|
+
observedItemCount: z.number().int().nonnegative(),
|
|
85
|
+
acquiredItemCount: z.number().int().nonnegative(),
|
|
86
|
+
blockedItemCount: z.number().int().nonnegative(),
|
|
87
|
+
accessControlledItemCount: z.number().int().nonnegative(),
|
|
88
|
+
evidenceRefs: z.array(stableUriSchema).max(2048),
|
|
89
|
+
blockers: z.array(shortText).max(256),
|
|
90
|
+
}).strict();
|
|
91
|
+
export const sourceCoverageAssessmentSchema = z.object({
|
|
92
|
+
schemaVersion: schemaVersionSchema,
|
|
93
|
+
projectKey: projectKeySchema,
|
|
94
|
+
assessedAt: isoDateTimeSchema,
|
|
95
|
+
complete: z.boolean(),
|
|
96
|
+
requiredSourceCount: z.number().int().nonnegative(),
|
|
97
|
+
coveredRequiredSourceCount: z.number().int().nonnegative(),
|
|
98
|
+
entries: z.array(sourceCoverageEntrySchema).max(5000),
|
|
99
|
+
blockers: z.array(shortText).max(1000),
|
|
100
|
+
}).strict();
|
|
101
|
+
export const sourceGapStateSchema = z.enum([
|
|
102
|
+
'PENDING_DISCOVERY',
|
|
103
|
+
'KNOWN_MISSING',
|
|
104
|
+
'ACCESS_CONTROLLED',
|
|
105
|
+
'NEED_AUTHORIZED_SOURCE',
|
|
106
|
+
'DEFERRED',
|
|
107
|
+
]);
|
|
108
|
+
export const sourceGapSchema = z.object({
|
|
109
|
+
schemaVersion: schemaVersionSchema,
|
|
110
|
+
gapId: idSchema,
|
|
111
|
+
projectKey: projectKeySchema,
|
|
112
|
+
sourceId: idSchema,
|
|
113
|
+
familyId: idSchema,
|
|
114
|
+
state: sourceGapStateSchema,
|
|
115
|
+
access: accessClassificationSchema,
|
|
116
|
+
expectedOwner: shortText.nullable(),
|
|
117
|
+
reason: z.string().trim().min(1).max(2000),
|
|
118
|
+
requiredFor: z.array(idSchema).max(128),
|
|
119
|
+
evidenceRefs: z.array(stableUriSchema).max(256),
|
|
120
|
+
recordedAt: isoDateTimeSchema,
|
|
121
|
+
}).strict();
|
|
122
|
+
const discoveryLinkIdSchema = z.string().trim().min(1).max(128).regex(/^[A-Za-z0-9][A-Za-z0-9._-]*$/);
|
|
123
|
+
const discoveredLinkSchema = z.object({
|
|
124
|
+
linkId: discoveryLinkIdSchema,
|
|
125
|
+
url: z.url(),
|
|
126
|
+
locator: z.string().trim().min(1).max(2048),
|
|
127
|
+
parentEvidenceRef: stableUriSchema,
|
|
128
|
+
title: z.string().trim().min(1).max(500).optional(),
|
|
129
|
+
}).strict();
|
|
130
|
+
export const sourceDiscoveryProposalSchema = z.object({
|
|
131
|
+
schemaVersion: schemaVersionSchema,
|
|
132
|
+
projectKey: projectKeySchema,
|
|
133
|
+
proposalId: idSchema,
|
|
134
|
+
familyId: idSchema,
|
|
135
|
+
createdAt: isoDateTimeSchema,
|
|
136
|
+
observedLinks: z.array(discoveredLinkSchema).min(1).max(1000),
|
|
137
|
+
selectedLinkIds: z.array(discoveryLinkIdSchema).max(1000),
|
|
138
|
+
completeness: z.object({
|
|
139
|
+
claim: z.enum(['COMPLETE', 'INCOMPLETE']),
|
|
140
|
+
missing: z.array(z.string().trim().min(1).max(500)).max(1000),
|
|
141
|
+
notes: z.string().trim().max(4000).nullable().default(null),
|
|
142
|
+
}).strict(),
|
|
143
|
+
}).strict();
|
|
144
|
+
export const sourceDiscoveryValidationSchema = z.object({
|
|
145
|
+
schemaVersion: schemaVersionSchema,
|
|
146
|
+
projectKey: projectKeySchema,
|
|
147
|
+
proposalId: idSchema,
|
|
148
|
+
familyId: idSchema,
|
|
149
|
+
proposalHash: z.string().regex(/^sha256:[a-f0-9]{64}$/),
|
|
150
|
+
valid: z.boolean(),
|
|
151
|
+
selectedSources: z.array(z.object({ linkId: idSchema, url: z.url(), parentEvidenceRef: stableUriSchema }).strict()).max(1000),
|
|
152
|
+
completeness: z.object({ claim: z.enum(['COMPLETE', 'INCOMPLETE']), missing: z.array(z.string()).max(1000), notes: z.string().nullable() }).strict(),
|
|
153
|
+
evidenceRefs: z.array(stableUriSchema).max(1000),
|
|
154
|
+
errors: z.array(shortText).max(1000),
|
|
155
|
+
warnings: z.array(shortText).max(1000),
|
|
156
|
+
}).strict();
|
|
157
|
+
export const sourceDiscoveryReceiptSchema = z.object({
|
|
158
|
+
schemaVersion: schemaVersionSchema,
|
|
159
|
+
projectKey: projectKeySchema,
|
|
160
|
+
proposalId: idSchema,
|
|
161
|
+
familyId: idSchema,
|
|
162
|
+
proposalHash: z.string().regex(/^sha256:[a-f0-9]{64}$/),
|
|
163
|
+
state: z.enum(['COMPLETE', 'REVIEWED_PARTIAL']),
|
|
164
|
+
proposalRef: stableUriSchema,
|
|
165
|
+
reviewRef: stableUriSchema,
|
|
166
|
+
reviewedAt: isoDateTimeSchema,
|
|
167
|
+
selectedSources: z.array(z.object({ linkId: idSchema, url: z.url(), parentEvidenceRef: stableUriSchema }).strict()).max(1000),
|
|
168
|
+
completeness: z.object({ claim: z.enum(['COMPLETE', 'INCOMPLETE']), missing: z.array(z.string()).max(1000), notes: z.string().nullable() }).strict(),
|
|
169
|
+
evidenceRefs: z.array(stableUriSchema).max(1000),
|
|
170
|
+
configMutationPerformed: z.literal(false),
|
|
171
|
+
}).strict().superRefine((value, ctx) => {
|
|
172
|
+
if (value.state === 'COMPLETE' && (value.completeness.claim !== 'COMPLETE' || value.completeness.missing.length))
|
|
173
|
+
ctx.addIssue({ code: 'custom', path: ['state'], message: 'COMPLETE receipt requires complete proposal without missing sources' });
|
|
174
|
+
if (value.state === 'REVIEWED_PARTIAL' && value.completeness.claim !== 'INCOMPLETE')
|
|
175
|
+
ctx.addIssue({ code: 'custom', path: ['state'], message: 'REVIEWED_PARTIAL receipt requires INCOMPLETE proposal' });
|
|
176
|
+
});
|
|
177
|
+
export const sourceAdmissionMatchSchema = z.object({
|
|
178
|
+
url: z.url(),
|
|
179
|
+
status: z.enum(['ADMITTED', 'BLOCKED', 'MISSING', 'DUPLICATE']),
|
|
180
|
+
universeSourceId: idSchema.nullable(),
|
|
181
|
+
acquisitionSourceId: idSchema.nullable(),
|
|
182
|
+
concreteSourceId: idSchema.nullable(),
|
|
183
|
+
issues: z.array(shortText).max(128),
|
|
184
|
+
}).strict();
|
|
185
|
+
export const sourceAdmissionAssessmentSchema = z.object({
|
|
186
|
+
schemaVersion: schemaVersionSchema,
|
|
187
|
+
projectKey: projectKeySchema,
|
|
188
|
+
familyId: idSchema,
|
|
189
|
+
state: z.enum(['ADMITTED', 'BLOCKED']),
|
|
190
|
+
selectedSourceCount: z.number().int().nonnegative(),
|
|
191
|
+
matches: z.array(sourceAdmissionMatchSchema).max(1000),
|
|
192
|
+
blockers: z.array(shortText).max(1000),
|
|
193
|
+
configMutationPerformed: z.literal(false),
|
|
194
|
+
}).strict();
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { accessClassificationSchema, idSchema, projectKeySchema, schemaVersionSchema, stableUriSchema, } from './common.js';
|
|
3
|
+
export const sourceKindSchema = z.enum([
|
|
4
|
+
'WEB',
|
|
5
|
+
'API',
|
|
6
|
+
'FILE',
|
|
7
|
+
'REPOSITORY',
|
|
8
|
+
'FEED',
|
|
9
|
+
'SOCIAL',
|
|
10
|
+
'BROWSER',
|
|
11
|
+
'MANUAL',
|
|
12
|
+
'OTHER',
|
|
13
|
+
]);
|
|
14
|
+
export const sourceDefinitionSchema = z.object({
|
|
15
|
+
schemaVersion: schemaVersionSchema,
|
|
16
|
+
sourceId: idSchema,
|
|
17
|
+
projectKey: projectKeySchema.optional(),
|
|
18
|
+
kind: sourceKindSchema,
|
|
19
|
+
authority: z.string().trim().min(1).max(256),
|
|
20
|
+
access: accessClassificationSchema,
|
|
21
|
+
canonicalUri: stableUriSchema.optional(),
|
|
22
|
+
refreshPolicy: z.string().trim().min(1).max(256),
|
|
23
|
+
enabled: z.boolean(),
|
|
24
|
+
tags: z.array(z.string().trim().min(1).max(128)).max(64).default([]),
|
|
25
|
+
}).strict();
|
|
26
|
+
export const collectorDefinitionSchema = z.object({
|
|
27
|
+
schemaVersion: schemaVersionSchema,
|
|
28
|
+
collectorId: idSchema,
|
|
29
|
+
version: z.string().trim().min(1).max(128),
|
|
30
|
+
supportedSourceKinds: z.array(sourceKindSchema).min(1),
|
|
31
|
+
capabilities: z.array(z.string().trim().min(1).max(128)).max(64),
|
|
32
|
+
}).strict();
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/** Host-authored admission accounting, independent of business authorization and receipt schemas. */
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { createHash } from 'node:crypto';
|
|
4
|
+
import { materialTenantIdSchema } from './material-context.js';
|
|
5
|
+
import { isoDateTimeSchema } from './common.js';
|
|
6
|
+
import { parseTenantCollectionBatchRef } from './tenant-collection.js';
|
|
7
|
+
import { tenantStorageKey } from './resource-scope.js';
|
|
8
|
+
const positive = (max) => z.number().int().min(1).max(max);
|
|
9
|
+
export const tenantBudgetPolicySchema = z.object({ tenantId: materialTenantIdSchema, maxInFlight: positive(32), maxWorkUnits: positive(1_000_000), maxRuntimeMs: positive(86_400_000), weight: positive(8), paused: z.boolean() }).strict();
|
|
10
|
+
export const tenantBudgetConfigSchema = z.object({ schemaVersion: z.literal(1), windowSeconds: z.number().int().min(60).max(86400), maxInFlight: positive(128), maxWaitRounds: positive(2048), tenants: z.array(tenantBudgetPolicySchema).min(1).max(128) }).strict().superRefine((value, ctx) => {
|
|
11
|
+
if (new Set(value.tenants.map(t => t.tenantId)).size !== value.tenants.length || value.tenants.some(t => t.maxInFlight > value.maxInFlight) || value.tenants.reduce((sum, t) => sum + t.weight, 0) > value.maxWaitRounds)
|
|
12
|
+
ctx.addIssue({ code: 'custom', message: 'Unique Tenants, Host limits and weighted waiting bound are required' });
|
|
13
|
+
});
|
|
14
|
+
export const tenantBudgetCandidateSchema = z.object({ key: z.string().regex(/^[a-f0-9]{64}$/), tenantId: materialTenantIdSchema, workUnits: positive(100_000), runtimeMs: z.number().int().min(1000).max(7_200_000) }).strict();
|
|
15
|
+
export const tenantBudgetReservationSchema = tenantBudgetCandidateSchema.extend({ admissionId: z.string().uuid(), nodeId: z.string().regex(/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/), startedAt: isoDateTimeSchema, expiresAt: isoDateTimeSchema, windowStart: isoDateTimeSchema }).strict();
|
|
16
|
+
export const tenantBudgetReasonSchema = z.enum(['READY', 'TENANT_UNCONFIGURED', 'PAUSED', 'HOST_IN_FLIGHT', 'TENANT_IN_FLIGHT', 'WORK_BUDGET', 'TIME_BUDGET', 'WORK_ACTIVE']);
|
|
17
|
+
/** 两小时是整个准入的硬上限;短任务保留结算余量,合法的上限任务不因此被排除。 */
|
|
18
|
+
export function tenantLegacyAdmissionRuntimeMs(timeoutSeconds) {
|
|
19
|
+
if (!Number.isInteger(timeoutSeconds) || timeoutSeconds < 30 || timeoutSeconds > 7200)
|
|
20
|
+
throw new Error('TENANT_LEGACY_TIMEOUT_INVALID');
|
|
21
|
+
return Math.min(7_200_000, timeoutSeconds * 1000 + 2000);
|
|
22
|
+
}
|
|
23
|
+
export function tenantCollectionAdmissionKey(tenantId, batchRef) {
|
|
24
|
+
const batch = parseTenantCollectionBatchRef(batchRef);
|
|
25
|
+
if (!batch || batch.storageKey !== tenantStorageKey(tenantId))
|
|
26
|
+
throw new Error('TENANT_BUDGET_WORK_SCOPE_INVALID');
|
|
27
|
+
return createHash('sha256').update(JSON.stringify(['TENANT_COLLECTION_ADMISSION_V1', tenantId, batchRef])).digest('hex');
|
|
28
|
+
}
|
|
29
|
+
export function tenantLegacyAdmissionKey(tenantId, workloadId) {
|
|
30
|
+
materialTenantIdSchema.parse(tenantId);
|
|
31
|
+
if (typeof workloadId !== 'string' || workloadId.length > 256 || !/^project:[A-Za-z0-9][A-Za-z0-9._-]{0,127}:.+$/.test(workloadId))
|
|
32
|
+
throw new Error('TENANT_BUDGET_WORK_SCOPE_INVALID');
|
|
33
|
+
return createHash('sha256').update(JSON.stringify(['TENANT_LEGACY_ADMISSION_V1', tenantId, workloadId])).digest('hex');
|
|
34
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/** 请求归因与 project-blind 批次分离;只保存委托身份,不保存可使用的 token。 */
|
|
2
|
+
import { createHash } from 'node:crypto';
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
import { idSchema, isoDateTimeSchema, stableUriSchema, sha256Schema } from './common.js';
|
|
5
|
+
import { resourceScopeSchema, tenantStorageKey, parseTenantResourceRef, tenantResourceRefSchema } from './resource-scope.js';
|
|
6
|
+
import { materialTenantIdSchema } from './material-context.js';
|
|
7
|
+
import { knowledgeActorContextSchema } from './project-intent.js';
|
|
8
|
+
import { tenantCollectionPlanSchema, tenantCollectionCycleSchema, tenantCollectionBatchIdentity, tenantCapturedEvidenceIdentity } from './tenant-collection.js';
|
|
9
|
+
export const tenantCollectionRequestAuthoritySchema = z.discriminatedUnion('type', [
|
|
10
|
+
z.object({ type: z.literal('HOST') }).strict(),
|
|
11
|
+
z.object({ type: z.literal('OAUTH'), authorityVersion: z.literal(2), clientId: idSchema, grantId: idSchema, resource: stableUriSchema }).strict(),
|
|
12
|
+
]);
|
|
13
|
+
export function tenantCollectionRequestKey(requestId) { return createHash('sha256').update(tenantCollectionCycleSchema.parse(requestId)).digest('hex'); }
|
|
14
|
+
export function tenantCollectionRequestRef(tenantId, requestId) { return `tenant-collection-request://${tenantStorageKey(tenantId)}/${tenantCollectionRequestKey(requestId)}`; }
|
|
15
|
+
export const tenantCollectionRequestSchema = z.object({
|
|
16
|
+
schemaVersion: z.literal(2), tenantId: materialTenantIdSchema, requestId: tenantCollectionCycleSchema, requestRef: stableUriSchema,
|
|
17
|
+
context: resourceScopeSchema, actor: knowledgeActorContextSchema, authority: tenantCollectionRequestAuthoritySchema,
|
|
18
|
+
plan: tenantCollectionPlanSchema, trigger: z.enum(['MANUAL', 'DUE']), cycleId: tenantCollectionCycleSchema, batchId: z.string().regex(/^batch_[a-f0-9]{64}$/), batchRef: stableUriSchema, requestedAt: isoDateTimeSchema,
|
|
19
|
+
}).strict().superRefine((value, ctx) => {
|
|
20
|
+
const expected = tenantCollectionBatchIdentity(value.tenantId, value.plan.revision, value.trigger, value.cycleId);
|
|
21
|
+
if (value.context.tenantId !== value.tenantId || value.actor.tenantId !== value.tenantId || value.plan.tenantId !== value.tenantId || value.requestRef !== tenantCollectionRequestRef(value.tenantId, value.requestId))
|
|
22
|
+
ctx.addIssue({ code: 'custom', path: ['context'], message: 'Request must retain exact Tenant/context/request identity' });
|
|
23
|
+
if (value.batchId !== expected.batchId || value.batchRef !== expected.batchRef)
|
|
24
|
+
ctx.addIssue({ code: 'custom', path: ['batchRef'], message: 'Request cannot retarget a different frozen batch' });
|
|
25
|
+
if (value.trigger === 'DUE' && value.authority.type !== 'HOST')
|
|
26
|
+
ctx.addIssue({ code: 'custom', path: ['trigger'], message: 'Only an explicit Host dispatcher may request DUE' });
|
|
27
|
+
});
|
|
28
|
+
const completionV1 = z.object({
|
|
29
|
+
schemaVersion: z.literal(1), tenantId: materialTenantIdSchema, requestRef: stableUriSchema, batchRef: stableUriSchema,
|
|
30
|
+
phase: z.enum(['RAW_REGISTERED', 'DERIVED_REGISTERED']), evidenceRef: stableUriSchema, contentHash: sha256Schema,
|
|
31
|
+
runId: idSchema, runtimeNodeId: idSchema, completedAt: isoDateTimeSchema,
|
|
32
|
+
}).strict();
|
|
33
|
+
export const tenantCollectionCompletionSchema = z.union([completionV1, completionV1.extend({ schemaVersion: z.literal(2), phase: z.literal('DERIVED_REGISTERED'), documentRef: tenantResourceRefSchema }).strict()]);
|
|
34
|
+
export function assertTenantCollectionCompletion(request, raw) {
|
|
35
|
+
const completion = tenantCollectionCompletionSchema.parse(raw), expected = tenantCapturedEvidenceIdentity({ tenantId: request.tenantId, batchRef: request.batchRef, sourceRevisionRef: request.plan.source.revisionRef });
|
|
36
|
+
const expectedPhase = request.plan.source.semantics.representation.format === 'RAW' ? 'RAW_REGISTERED' : 'DERIVED_REGISTERED';
|
|
37
|
+
if (completion.tenantId !== request.tenantId || completion.requestRef !== request.requestRef || completion.batchRef !== request.batchRef || completion.evidenceRef !== expected.ref || completion.phase !== expectedPhase)
|
|
38
|
+
throw new Error('TENANT_COLLECTION_COMPLETION_MISMATCH');
|
|
39
|
+
if (expectedPhase === 'DERIVED_REGISTERED') {
|
|
40
|
+
const document = completion.schemaVersion === 2 ? parseTenantResourceRef(completion.documentRef) : null;
|
|
41
|
+
if (!document || document.storageKey !== tenantStorageKey(request.tenantId) || document.resourceType !== 'source_document')
|
|
42
|
+
throw new Error('TENANT_COLLECTION_DERIVATION_UNPROVEN');
|
|
43
|
+
}
|
|
44
|
+
else if (completion.schemaVersion !== 1)
|
|
45
|
+
throw new Error('TENANT_COLLECTION_COMPLETION_MISMATCH');
|
|
46
|
+
return completion;
|
|
47
|
+
}
|
|
48
|
+
/** Admission retirement is not acquisition failure or business completion. */
|
|
49
|
+
export const TENANT_REQUEST_ADMISSION_STOP_CAPABILITY = 'TENANT_REQUEST_ADMISSION_STOP_V1';
|
|
50
|
+
export const tenantCollectionAdmissionStopSchema = z.object({ schemaVersion: z.literal(1), tenantId: materialTenantIdSchema, requestRef: stableUriSchema, requestHash: sha256Schema, reason: z.enum(['GRANT_REVOKED', 'DELEGATION_SUPERSEDED']), stoppedAt: isoDateTimeSchema }).strict();
|
|
51
|
+
/** Acquisition outcome only: a failed request is neither completed nor delegation-retired. */
|
|
52
|
+
export const tenantCollectionFailureSchema = z.object({
|
|
53
|
+
schemaVersion: z.literal(1), tenantId: materialTenantIdSchema, requestRef: stableUriSchema, requestHash: sha256Schema, batchRef: stableUriSchema,
|
|
54
|
+
runId: idSchema, runtimeNodeId: idSchema, receiptHash: sha256Schema, failedAt: isoDateTimeSchema, errorCode: z.literal('TENANT_SOURCE_HTTP_TERMINAL'),
|
|
55
|
+
}).strict();
|
|
56
|
+
export function isTenantCollectionTerminalFailure(request, receipt) {
|
|
57
|
+
return receipt.status === 'FAILED' && receipt.errorCode === 'TENANT_SOURCE_HTTP_TERMINAL' && receipt.workloadId === request.plan.workloadId && receipt.collectionBatchRef === request.batchRef && receipt.inputFingerprint === request.plan.revision && receipt.projectRef === undefined && receipt.projectIntentRef === undefined && receipt.evidenceCount === 0 && receipt.observationCount === 0 && Date.parse(receipt.finishedAt) >= Date.parse(receipt.startedAt) && request.plan.source.semantics.target.kind === 'URL' && request.plan.source.semantics.credential.type === 'PUBLIC';
|
|
58
|
+
}
|