@native-knowledge/cli 0.0.0-stage → 0.1.0-rc.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (93) hide show
  1. package/LICENSE +202 -0
  2. package/NOTICE +29 -0
  3. package/README.md +34 -2
  4. package/dist/agent-entry-cli.js +88 -0
  5. package/dist/auth-commands.js +102 -0
  6. package/dist/cli.js +104 -0
  7. package/dist/commands.js +17 -0
  8. package/dist/download.js +45 -0
  9. package/dist/errors.js +7 -0
  10. package/dist/input.js +89 -0
  11. package/dist/internal/contracts/artifact.js +103 -0
  12. package/dist/internal/contracts/collection-control.js +69 -0
  13. package/dist/internal/contracts/collection.js +174 -0
  14. package/dist/internal/contracts/common.js +16 -0
  15. package/dist/internal/contracts/currentness.js +221 -0
  16. package/dist/internal/contracts/event.js +35 -0
  17. package/dist/internal/contracts/evidence.js +171 -0
  18. package/dist/internal/contracts/index.js +54 -0
  19. package/dist/internal/contracts/material-capability.js +8 -0
  20. package/dist/internal/contracts/material-carrier.js +15 -0
  21. package/dist/internal/contracts/material-context.js +9 -0
  22. package/dist/internal/contracts/material-read.js +12 -0
  23. package/dist/internal/contracts/observation.js +39 -0
  24. package/dist/internal/contracts/persistence.js +239 -0
  25. package/dist/internal/contracts/project-intent.js +121 -0
  26. package/dist/internal/contracts/projection.js +194 -0
  27. package/dist/internal/contracts/public-reference.js +87 -0
  28. package/dist/internal/contracts/reference-record.js +55 -0
  29. package/dist/internal/contracts/remote-file.js +159 -0
  30. package/dist/internal/contracts/resource-scope.js +38 -0
  31. package/dist/internal/contracts/review-packet.js +61 -0
  32. package/dist/internal/contracts/review-plane.js +89 -0
  33. package/dist/internal/contracts/rich-document.js +184 -0
  34. package/dist/internal/contracts/runtime-compatibility.js +55 -0
  35. package/dist/internal/contracts/runtime.js +68 -0
  36. package/dist/internal/contracts/scheduler.js +256 -0
  37. package/dist/internal/contracts/signal.js +77 -0
  38. package/dist/internal/contracts/source-governance.js +194 -0
  39. package/dist/internal/contracts/source.js +32 -0
  40. package/dist/internal/contracts/tenant-budget.js +34 -0
  41. package/dist/internal/contracts/tenant-collection-request.js +58 -0
  42. package/dist/internal/contracts/tenant-collection.js +66 -0
  43. package/dist/internal/contracts/tenant-currentness.js +26 -0
  44. package/dist/internal/contracts/tenant-management.js +27 -0
  45. package/dist/internal/contracts/tenant-material-api.js +46 -0
  46. package/dist/internal/contracts/tenant-material-json-schema.js +16 -0
  47. package/dist/internal/contracts/tenant-pdf-text.js +13 -0
  48. package/dist/internal/contracts/tenant-project-control.js +19 -0
  49. package/dist/internal/contracts/tenant-public-reference.js +26 -0
  50. package/dist/internal/contracts/tenant-resource-api.js +70 -0
  51. package/dist/internal/contracts/tenant-resource.js +118 -0
  52. package/dist/internal/contracts/tenant-rich-document.js +17 -0
  53. package/dist/internal/contracts/tenant-source-binding.js +33 -0
  54. package/dist/internal/contracts/tenant-source-bridge.js +9 -0
  55. package/dist/internal/contracts/tenant-source-cutover.js +26 -0
  56. package/dist/internal/contracts/tenant-source-document.js +38 -0
  57. package/dist/internal/contracts/tenant-source-lease.js +5 -0
  58. package/dist/internal/contracts/tenant-source.js +83 -0
  59. package/dist/internal/contracts/tenant-web-collection.js +118 -0
  60. package/dist/internal/contracts/tenant-web-content-plan.js +39 -0
  61. package/dist/internal/contracts/tenant-web-content-result.js +15 -0
  62. package/dist/internal/contracts/tenant-web-content.js +16 -0
  63. package/dist/internal/contracts/tenant-web-crawl.js +55 -0
  64. package/dist/internal/contracts/tenant-web-dynamic.js +68 -0
  65. package/dist/internal/contracts/tenant-web-results.js +41 -0
  66. package/dist/internal/contracts/tenant-web-workflow.js +29 -0
  67. package/dist/internal/serving-contracts/agent-catalog.js +56 -0
  68. package/dist/internal/serving-contracts/agent-entry.js +57 -0
  69. package/dist/internal/serving-contracts/agent-guidance-shapes.js +12 -0
  70. package/dist/internal/serving-contracts/agent-input-hints.js +104 -0
  71. package/dist/internal/serving-contracts/body-search.js +16 -0
  72. package/dist/internal/serving-contracts/consumer.js +45 -0
  73. package/dist/internal/serving-contracts/core.js +76 -0
  74. package/dist/internal/serving-contracts/http.js +64 -0
  75. package/dist/internal/serving-contracts/index.js +25 -0
  76. package/dist/internal/serving-contracts/management.js +15 -0
  77. package/dist/internal/serving-contracts/material-capabilities.js +14 -0
  78. package/dist/internal/serving-contracts/material-index-status.js +5 -0
  79. package/dist/internal/serving-contracts/mcp.js +140 -0
  80. package/dist/internal/serving-contracts/tenant-governance.js +13 -0
  81. package/dist/internal/serving-contracts/tenant-management.js +89 -0
  82. package/dist/internal/serving-contracts/tenant-project.js +39 -0
  83. package/dist/internal/serving-contracts/tenant-runtime.js +37 -0
  84. package/dist/internal/serving-contracts/tenant-session.js +8 -0
  85. package/dist/internal/serving-contracts/tenant-web-content.js +20 -0
  86. package/dist/internal/serving-contracts/tenant-web-crawl.js +13 -0
  87. package/dist/internal/serving-contracts/tenant-web-dynamic.js +20 -0
  88. package/dist/internal/serving-contracts/tenant-web-workflow.js +36 -0
  89. package/dist/internal/serving-contracts/tenant-web.js +53 -0
  90. package/dist/internal/serving-contracts/tenant-workspace.js +28 -0
  91. package/dist/internal/serving-contracts/workflow.js +37 -0
  92. package/dist/profile-store.js +142 -0
  93. package/package.json +26 -3
@@ -0,0 +1,239 @@
1
+ import { z } from 'zod';
2
+ import { artifactKindSchema } from './artifact.js';
3
+ import { evidenceRefSchema } from './evidence.js';
4
+ import { accessClassificationSchema, idSchema, isoDateTimeSchema, projectKeySchema, schemaVersionSchema, sha256Schema, stableUriSchema, } from './common.js';
5
+ import { sourceDeclaredStateSchema } from './source-governance.js';
6
+ export const portableRelativePathSchema = z.string().trim().min(1).max(4096).superRefine((value, ctx) => {
7
+ if (value.startsWith('/') || value.includes('\\'))
8
+ ctx.addIssue({ code: 'custom', message: 'Path must be portable and relative' });
9
+ const parts = value.split('/');
10
+ if (parts.some((part) => !part || part === '.' || part === '..'))
11
+ ctx.addIssue({ code: 'custom', message: 'Path contains invalid segment' });
12
+ });
13
+ export const sourceSetRegistryHashSchema = z.object({
14
+ acquisitionSourceId: idSchema,
15
+ relativePath: portableRelativePathSchema,
16
+ contentHash: sha256Schema,
17
+ }).strict();
18
+ export const sourceSetItemBindingSchema = z.object({
19
+ acquisitionSourceId: idSchema,
20
+ concreteSourceId: idSchema,
21
+ authority: z.string().trim().min(1).max(512).nullable(),
22
+ access: accessClassificationSchema,
23
+ declaredGitSha: z.string().trim().min(1).max(128).nullable(),
24
+ }).strict();
25
+ export const sourceSetItemSchema = z.object({
26
+ itemId: idSchema,
27
+ kind: z.enum(['WEB', 'FILE']),
28
+ logicalSourceRef: stableUriSchema,
29
+ sourceIds: z.array(idSchema).min(1).max(64),
30
+ bindings: z.array(sourceSetItemBindingSchema).min(1).max(64),
31
+ contentPolicy: z.enum(['public-excerpt', 'metadata-only']),
32
+ cadenceMs: z.number().int().positive(),
33
+ url: z.url().nullable(),
34
+ rootBinding: projectKeySchema.nullable(),
35
+ relativePath: portableRelativePathSchema.nullable(),
36
+ }).strict().superRefine((value, ctx) => {
37
+ if (value.kind === 'WEB' && (!value.url || value.rootBinding || value.relativePath))
38
+ ctx.addIssue({ code: 'custom', path: ['url'], message: 'WEB item requires url only' });
39
+ if (value.kind === 'FILE' && (value.url || !value.rootBinding || !value.relativePath))
40
+ ctx.addIssue({ code: 'custom', path: ['relativePath'], message: 'FILE item requires rootBinding + relativePath only' });
41
+ });
42
+ export const sourceSetLogicalSourceSchema = z.object({
43
+ logicalSourceId: idSchema,
44
+ familyId: idSchema,
45
+ declaredState: sourceDeclaredStateSchema,
46
+ locator: stableUriSchema.nullable(),
47
+ acquisitionSourceIds: z.array(idSchema).max(64),
48
+ itemIds: z.array(idSchema).max(5000),
49
+ }).strict();
50
+ export const sourceSetSnapshotSchema = z.object({
51
+ schemaVersion: schemaVersionSchema,
52
+ sourceSetId: sha256Schema,
53
+ sourceSetRef: stableUriSchema,
54
+ projectKey: projectKeySchema,
55
+ programRevision: z.string().regex(/^[a-f0-9]{40,64}$/),
56
+ acquisitionConfigHash: sha256Schema,
57
+ sourceUniverseHash: sha256Schema.nullable(),
58
+ registryHashes: z.array(sourceSetRegistryHashSchema).max(256),
59
+ items: z.array(sourceSetItemSchema).max(20000),
60
+ logicalSources: z.array(sourceSetLogicalSourceSchema).max(5000),
61
+ }).strict().superRefine((value, ctx) => {
62
+ const digest = value.sourceSetId.slice('sha256:'.length);
63
+ if (value.sourceSetRef !== `source-set://${value.projectKey}/${digest}`)
64
+ ctx.addIssue({ code: 'custom', path: ['sourceSetRef'], message: 'sourceSetRef must match sourceSetId' });
65
+ const itemIds = value.items.map((row) => row.itemId);
66
+ if (new Set(itemIds).size !== itemIds.length)
67
+ ctx.addIssue({ code: 'custom', path: ['items'], message: 'itemId must be unique' });
68
+ const logicalIds = value.logicalSources.map((row) => row.logicalSourceId);
69
+ if (new Set(logicalIds).size !== logicalIds.length)
70
+ ctx.addIssue({ code: 'custom', path: ['logicalSources'], message: 'logicalSourceId must be unique' });
71
+ const registryKeys = value.registryHashes.map((row) => `${row.acquisitionSourceId}\n${row.relativePath}`);
72
+ if (new Set(registryKeys).size !== registryKeys.length)
73
+ ctx.addIssue({ code: 'custom', path: ['registryHashes'], message: 'registry hash binding must be unique' });
74
+ });
75
+ export const sourceSetPointerSchema = z.object({
76
+ schemaVersion: schemaVersionSchema,
77
+ projectKey: projectKeySchema,
78
+ sourceSetId: sha256Schema,
79
+ sourceSetRef: stableUriSchema,
80
+ manifestRelativePath: portableRelativePathSchema,
81
+ updatedAt: isoDateTimeSchema,
82
+ }).strict();
83
+ export const libraryProjectionSchema = z.object({
84
+ schemaVersion: schemaVersionSchema,
85
+ projectionId: sha256Schema,
86
+ projectKey: projectKeySchema,
87
+ subjectType: z.enum(['ARTIFACT', 'EVIDENCE']),
88
+ subjectRef: stableUriSchema,
89
+ contentHash: sha256Schema,
90
+ mediaType: z.string().trim().min(1).max(256),
91
+ byteLength: z.number().int().nonnegative(),
92
+ relativePath: portableRelativePathSchema,
93
+ manifestRelativePath: portableRelativePathSchema,
94
+ }).strict();
95
+ export const deliverySupportProofSchema = z.object({
96
+ action: z.literal('ALLOW'),
97
+ supportState: z.string().trim().min(1).max(128),
98
+ semanticHash: sha256Schema,
99
+ }).strict();
100
+ export const deliveryConsumerRequestSchema = z.object({
101
+ mediaType: z.string().trim().min(1).max(256),
102
+ contentHash: sha256Schema,
103
+ byteLength: z.number().int().nonnegative(),
104
+ }).strict();
105
+ export const knowledgeDeliveryEnvelopeSchema = z.object({
106
+ schemaVersion: schemaVersionSchema,
107
+ deliveryId: sha256Schema,
108
+ producerProjectKey: projectKeySchema,
109
+ producerProjectRef: stableUriSchema.optional(),
110
+ consumerKey: projectKeySchema,
111
+ artifactRef: stableUriSchema,
112
+ artifactKind: artifactKindSchema,
113
+ artifactAccess: accessClassificationSchema,
114
+ contentHash: sha256Schema,
115
+ mediaType: z.string().trim().min(1).max(256),
116
+ byteLength: z.number().int().nonnegative(),
117
+ libraryPath: portableRelativePathSchema,
118
+ observedAt: isoDateTimeSchema.nullable(),
119
+ validUntil: isoDateTimeSchema.nullable(),
120
+ support: deliverySupportProofSchema.nullable(),
121
+ consumerRequest: deliveryConsumerRequestSchema.nullable(),
122
+ createdAt: isoDateTimeSchema,
123
+ }).strict().superRefine((value, ctx) => { if (value.producerProjectRef) {
124
+ try {
125
+ const url = new URL(value.producerProjectRef);
126
+ if (url.protocol !== 'knowledge-project:' || url.hostname.toLowerCase() !== value.producerProjectKey.toLowerCase())
127
+ ctx.addIssue({ code: 'custom', path: ['producerProjectRef'], message: 'producerProjectRef project must match producer project' });
128
+ }
129
+ catch {
130
+ ctx.addIssue({ code: 'custom', path: ['producerProjectRef'], message: 'Invalid producerProjectRef' });
131
+ }
132
+ } });
133
+ export const knowledgeDeliveryClaimSchema = z.object({
134
+ schemaVersion: schemaVersionSchema,
135
+ deliveryId: sha256Schema,
136
+ producerProjectKey: projectKeySchema,
137
+ producerProjectRef: stableUriSchema.optional(),
138
+ consumerKey: projectKeySchema,
139
+ claimId: z.string().uuid(),
140
+ workerId: z.string().trim().min(1).max(128).regex(/^[A-Za-z0-9._-]+$/),
141
+ claimedAt: isoDateTimeSchema,
142
+ expiresAt: isoDateTimeSchema,
143
+ }).strict().superRefine((value, ctx) => {
144
+ if (value.producerProjectRef) {
145
+ try {
146
+ const url = new URL(value.producerProjectRef);
147
+ if (url.protocol !== 'knowledge-project:' || url.hostname.toLowerCase() !== value.producerProjectKey.toLowerCase())
148
+ ctx.addIssue({ code: 'custom', path: ['producerProjectRef'], message: 'producerProjectRef project must match producer project' });
149
+ }
150
+ catch {
151
+ ctx.addIssue({ code: 'custom', path: ['producerProjectRef'], message: 'Invalid producerProjectRef' });
152
+ }
153
+ }
154
+ const claimedAt = Date.parse(value.claimedAt), expiresAt = Date.parse(value.expiresAt), leaseSeconds = (expiresAt - claimedAt) / 1000;
155
+ if (expiresAt <= claimedAt)
156
+ ctx.addIssue({ code: 'custom', path: ['expiresAt'], message: 'Delivery claim expiry must be after claim time' });
157
+ else if (leaseSeconds < 30 || leaseSeconds > 3600)
158
+ ctx.addIssue({ code: 'custom', path: ['expiresAt'], message: 'Delivery claim lease must be between 30 and 3600 seconds' });
159
+ });
160
+ export const knowledgeDeliveryOutcomeSchema = z.enum(['DELIVERED', 'BLOCKED', 'FAILED_RETRYABLE', 'FAILED_TERMINAL']);
161
+ export const knowledgeDeliveryReceiptSchema = z.object({
162
+ schemaVersion: schemaVersionSchema,
163
+ deliveryId: sha256Schema,
164
+ producerProjectKey: projectKeySchema,
165
+ producerProjectRef: stableUriSchema.optional(),
166
+ consumerKey: projectKeySchema,
167
+ artifactRef: stableUriSchema,
168
+ contentHash: sha256Schema,
169
+ outcome: knowledgeDeliveryOutcomeSchema,
170
+ attempts: z.number().int().positive().max(999999),
171
+ deliveredAt: isoDateTimeSchema,
172
+ nextAttemptAt: isoDateTimeSchema.nullable(),
173
+ externalRef: stableUriSchema.nullable(),
174
+ consumerResponseHash: sha256Schema.nullable(),
175
+ message: z.string().trim().min(1).max(4000).nullable(),
176
+ }).strict().superRefine((value, ctx) => {
177
+ if (value.producerProjectRef) {
178
+ try {
179
+ const url = new URL(value.producerProjectRef);
180
+ if (url.protocol !== 'knowledge-project:' || url.hostname.toLowerCase() !== value.producerProjectKey.toLowerCase())
181
+ ctx.addIssue({ code: 'custom', path: ['producerProjectRef'], message: 'producerProjectRef project must match producer project' });
182
+ }
183
+ catch {
184
+ ctx.addIssue({ code: 'custom', path: ['producerProjectRef'], message: 'Invalid producerProjectRef' });
185
+ }
186
+ }
187
+ if (value.outcome === 'DELIVERED' && value.nextAttemptAt)
188
+ ctx.addIssue({ code: 'custom', path: ['nextAttemptAt'], message: 'DELIVERED cannot schedule retry' });
189
+ if (value.outcome === 'FAILED_RETRYABLE' && !value.nextAttemptAt)
190
+ ctx.addIssue({ code: 'custom', path: ['nextAttemptAt'], message: 'FAILED_RETRYABLE requires nextAttemptAt' });
191
+ if (value.outcome === 'FAILED_RETRYABLE' && value.nextAttemptAt && Date.parse(value.nextAttemptAt) <= Date.parse(value.deliveredAt))
192
+ ctx.addIssue({ code: 'custom', path: ['nextAttemptAt'], message: 'Retry must be scheduled after this attempt completes' });
193
+ if (value.outcome !== 'FAILED_RETRYABLE' && value.nextAttemptAt)
194
+ ctx.addIssue({ code: 'custom', path: ['nextAttemptAt'], message: 'Only retryable failure may schedule retry' });
195
+ });
196
+ export const distributionConsumerSchema = z.object({
197
+ consumerKey: projectKeySchema,
198
+ enabled: z.boolean(),
199
+ artifactKinds: z.array(artifactKindSchema).min(1).max(16),
200
+ acceptedAccess: z.array(accessClassificationSchema).min(1).max(7),
201
+ supportPolicy: z.enum(['NONE', 'REQUIRE_ALLOW']),
202
+ adapter: z.string().trim().min(1).max(128),
203
+ }).strict().superRefine((value, ctx) => {
204
+ if (value.artifactKinds.some((kind) => ['KNOWLEDGE', 'INSIGHT'].includes(kind)) && value.supportPolicy !== 'REQUIRE_ALLOW') {
205
+ ctx.addIssue({ code: 'custom', path: ['supportPolicy'], message: 'Knowledge/Insight distribution requires REQUIRE_ALLOW' });
206
+ }
207
+ if (new Set(value.acceptedAccess).size !== value.acceptedAccess.length)
208
+ ctx.addIssue({ code: 'custom', path: ['acceptedAccess'], message: 'acceptedAccess must be unique' });
209
+ });
210
+ export const distributionConfigSchema = z.object({
211
+ schemaVersion: schemaVersionSchema,
212
+ projectKey: projectKeySchema,
213
+ consumers: z.array(distributionConsumerSchema).max(128),
214
+ }).strict().superRefine((value, ctx) => {
215
+ const keys = value.consumers.map((row) => row.consumerKey);
216
+ if (new Set(keys).size !== keys.length)
217
+ ctx.addIssue({ code: 'custom', path: ['consumers'], message: 'consumerKey must be unique' });
218
+ });
219
+ export const durableEvidenceManifestSchema = z.object({
220
+ schemaVersion: schemaVersionSchema,
221
+ projectKey: projectKeySchema,
222
+ evidenceRef: stableUriSchema,
223
+ evidence: evidenceRefSchema,
224
+ }).strict().superRefine((value, ctx) => {
225
+ if (value.evidence.projectKey !== value.projectKey)
226
+ ctx.addIssue({ code: 'custom', path: ['evidence', 'projectKey'], message: 'Durable Evidence project must match manifest project' });
227
+ const expected = `evidence://${value.projectKey}/${encodeURIComponent(value.evidence.evidenceId)}`;
228
+ if (value.evidenceRef !== expected)
229
+ ctx.addIssue({ code: 'custom', path: ['evidenceRef'], message: 'Durable Evidence ref must match evidence identity' });
230
+ if (value.evidence.sourceSetRef) {
231
+ try {
232
+ if (new URL(value.evidence.sourceSetRef).hostname.toLowerCase() !== value.projectKey.toLowerCase())
233
+ ctx.addIssue({ code: 'custom', path: ['evidence', 'sourceSetRef'], message: 'Source Set project must match Evidence project' });
234
+ }
235
+ catch {
236
+ ctx.addIssue({ code: 'custom', path: ['evidence', 'sourceSetRef'], message: 'Invalid Source Set ref' });
237
+ }
238
+ }
239
+ });
@@ -0,0 +1,121 @@
1
+ import { z } from 'zod';
2
+ import { accessClassificationSchema, idSchema, isoDateTimeSchema, projectKeySchema, schemaVersionSchema, sha256Schema, stableUriSchema, } from './common.js';
3
+ const text = (max) => z.string().trim().min(1).max(max);
4
+ const optionalText = (max) => z.string().trim().min(1).max(max).nullable().default(null);
5
+ /**
6
+ * Attribution for an Agent-native Knowledge write. This is provenance, not an
7
+ * authorization decision. agentId is deliberately nullable because humans,
8
+ * schedulers and migrations may write without an Agent identity.
9
+ */
10
+ export const knowledgeActorContextSchema = z.object({
11
+ tenantId: idSchema,
12
+ userId: idSchema,
13
+ agentId: idSchema.nullable().default(null),
14
+ }).strict();
15
+ export const projectIntentScopeSchema = z.object({
16
+ scopeId: idSchema,
17
+ title: text(256),
18
+ description: text(4000),
19
+ sourceRequirements: z.array(text(1000)).max(256).default([]),
20
+ sourceFamilies: z.array(idSchema).max(256).default([]),
21
+ notes: optionalText(4000),
22
+ }).strict();
23
+ export const projectIdentitySchema = z.object({
24
+ name: text(256),
25
+ summary: text(4000),
26
+ domains: z.array(text(256)).max(256).default([]),
27
+ notes: optionalText(4000),
28
+ }).strict();
29
+ export const projectIntentBasisSchema = z.object({
30
+ schemaVersion: schemaVersionSchema,
31
+ projectKey: projectKeySchema,
32
+ actor: knowledgeActorContextSchema,
33
+ projectIdentity: projectIdentitySchema,
34
+ scopes: z.array(projectIntentScopeSchema).max(1000).default([]),
35
+ }).strict().superRefine((value, ctx) => {
36
+ const seen = new Set();
37
+ for (let i = 0; i < value.scopes.length; i += 1) {
38
+ const scopeId = value.scopes[i].scopeId;
39
+ if (seen.has(scopeId))
40
+ ctx.addIssue({ code: 'custom', path: ['scopes', i, 'scopeId'], message: 'scopeId must be unique' });
41
+ seen.add(scopeId);
42
+ }
43
+ });
44
+ export const projectIntentSnapshotSchema = projectIntentBasisSchema.extend({
45
+ projectRef: stableUriSchema,
46
+ revisionId: sha256Schema,
47
+ revisionRef: stableUriSchema,
48
+ }).strict();
49
+ export const projectIntentPointerSchema = z.object({
50
+ schemaVersion: schemaVersionSchema,
51
+ projectKey: projectKeySchema,
52
+ tenantId: idSchema,
53
+ projectRef: stableUriSchema,
54
+ revisionId: sha256Schema,
55
+ revisionRef: stableUriSchema,
56
+ manifestRelativePath: text(2048),
57
+ updatedAt: isoDateTimeSchema,
58
+ }).strict();
59
+ export const collectionRefreshSchema = z.discriminatedUnion('mode', [
60
+ z.object({ mode: z.literal('MANUAL') }).strict(),
61
+ z.object({ mode: z.literal('INTERVAL'), intervalSeconds: z.number().int().min(60).max(31_536_000) }).strict(),
62
+ ]);
63
+ /** Project-neutral executable target. Project/domain semantics stay on ProjectSource. */
64
+ const relativeTargetPathSchema = z.string().trim().min(1).max(2048).superRefine((value, ctx) => {
65
+ if (value.includes('\\') || value.startsWith('/') || value.endsWith('/')) {
66
+ ctx.addIssue({ code: 'custom', message: 'FILE target path must be a normalized relative file path' });
67
+ return;
68
+ }
69
+ const parts = value.split('/');
70
+ if (parts.some((part) => !part || part === '.' || part === '..'))
71
+ ctx.addIssue({ code: 'custom', message: 'FILE target path must not contain empty, dot or parent segments' });
72
+ });
73
+ const executorParameterScalarSchema = z.union([z.string().max(4000), z.number().finite(), z.boolean(), z.null()]);
74
+ const executorParameterValueSchema = z.union([executorParameterScalarSchema, z.array(executorParameterScalarSchema).max(256)]);
75
+ const urlAcquisitionTargetSchema = z.object({ kind: z.literal('URL'), locator: z.url() }).strict();
76
+ const fileAcquisitionTargetSchema = z.object({ kind: z.literal('FILE'), rootBinding: projectKeySchema, relativePath: relativeTargetPathSchema }).strict();
77
+ const executorAcquisitionTargetSchema = z.object({
78
+ kind: z.literal('EXECUTOR'), executorId: idSchema, bindingRef: stableUriSchema.nullable().default(null), parameters: z.record(z.string().trim().min(1).max(128), executorParameterValueSchema).default({}),
79
+ }).strict().superRefine((value, ctx) => {
80
+ if (Object.keys(value.parameters).length > 128)
81
+ ctx.addIssue({ code: 'custom', path: ['parameters'], message: 'EXECUTOR target supports at most 128 parameters' });
82
+ if (Buffer.byteLength(JSON.stringify(value.parameters), 'utf8') > 32 * 1024)
83
+ ctx.addIssue({ code: 'custom', path: ['parameters'], message: 'EXECUTOR target parameters exceed 32 KiB' });
84
+ });
85
+ export const acquisitionTargetSchema = z.discriminatedUnion('kind', [urlAcquisitionTargetSchema, fileAcquisitionTargetSchema, executorAcquisitionTargetSchema]);
86
+ const metadataScalarSchema = z.union([z.string().max(4000), z.number(), z.boolean(), z.null()]);
87
+ export const projectSourceBasisSchema = z.object({
88
+ schemaVersion: schemaVersionSchema,
89
+ projectKey: projectKeySchema,
90
+ actor: knowledgeActorContextSchema,
91
+ target: acquisitionTargetSchema,
92
+ enabled: z.boolean().default(true),
93
+ access: accessClassificationSchema.default('PUBLIC'),
94
+ scopeIds: z.array(idSchema).max(256).default([]),
95
+ sourceFamilies: z.array(idSchema).max(256).default([]),
96
+ purpose: optionalText(4000),
97
+ refresh: collectionRefreshSchema.default({ mode: 'MANUAL' }),
98
+ metadata: z.record(z.string().trim().min(1).max(128), metadataScalarSchema).default({}),
99
+ }).strict();
100
+ export const projectSourceSnapshotSchema = projectSourceBasisSchema.extend({
101
+ projectRef: stableUriSchema,
102
+ projectIntentRef: stableUriSchema.nullable().default(null),
103
+ targetId: sha256Schema,
104
+ sourceId: idSchema,
105
+ revisionId: sha256Schema,
106
+ sourceRef: stableUriSchema,
107
+ revisionRef: stableUriSchema,
108
+ }).strict();
109
+ export const projectSourcePointerSchema = z.object({
110
+ schemaVersion: schemaVersionSchema,
111
+ projectKey: projectKeySchema,
112
+ projectRef: stableUriSchema,
113
+ projectIntentRef: stableUriSchema.nullable(),
114
+ sourceId: idSchema,
115
+ targetId: sha256Schema,
116
+ sourceRef: stableUriSchema,
117
+ revisionId: sha256Schema,
118
+ revisionRef: stableUriSchema,
119
+ manifestRelativePath: text(2048),
120
+ updatedAt: isoDateTimeSchema,
121
+ }).strict();
@@ -0,0 +1,194 @@
1
+ import { z } from 'zod';
2
+ import { artifactKindSchema, artifactStatusSchema } from './artifact.js';
3
+ import { idSchema, isoDateTimeSchema, projectKeySchema, schemaVersionSchema, sha256Schema, stableUriSchema } from './common.js';
4
+ export const driveRelativePathSchema = z.string().trim().min(1).max(2048).refine((value) => {
5
+ if (value.startsWith('/') || value.startsWith('\\'))
6
+ return false;
7
+ if (value.includes('\\'))
8
+ return false;
9
+ return !value.split('/').some((part) => !part || part === '.' || part === '..');
10
+ }, 'Drive relative path must be normalized and traversal-free');
11
+ export const driveArtifactProjectionSchema = z.object({
12
+ schemaVersion: schemaVersionSchema,
13
+ projectionType: z.literal('GOOGLE_DRIVE'),
14
+ projectionId: sha256Schema,
15
+ relativePath: driveRelativePathSchema,
16
+ projectKey: projectKeySchema,
17
+ projectRef: stableUriSchema.optional(),
18
+ artifactRef: stableUriSchema,
19
+ identityRef: stableUriSchema,
20
+ contentHash: sha256Schema,
21
+ mediaType: z.string().trim().min(1).max(256),
22
+ byteLength: z.number().int().nonnegative(),
23
+ artifactKind: artifactKindSchema,
24
+ artifactStatus: artifactStatusSchema,
25
+ artifactVersion: z.number().int().positive(),
26
+ }).strict().superRefine((value, ctx) => {
27
+ if (!value.relativePath.startsWith(`Knowledge V2/${value.projectKey}/`))
28
+ ctx.addIssue({ code: 'custom', path: ['relativePath'], message: 'Drive path project must match projectKey' });
29
+ if (value.projectRef) {
30
+ try {
31
+ const project = new URL(value.projectRef);
32
+ if (project.protocol !== 'knowledge-project:' || project.hostname.toLowerCase() !== value.projectKey.toLowerCase())
33
+ ctx.addIssue({ code: 'custom', path: ['projectRef'], message: 'projectRef project must match projectKey' });
34
+ }
35
+ catch {
36
+ ctx.addIssue({ code: 'custom', path: ['projectRef'], message: 'Invalid projectRef' });
37
+ }
38
+ }
39
+ try {
40
+ const artifact = new URL(value.artifactRef);
41
+ const identity = new URL(value.identityRef);
42
+ if (artifact.hostname.toLowerCase() !== value.projectKey.toLowerCase() || identity.hostname.toLowerCase() !== value.projectKey.toLowerCase())
43
+ ctx.addIssue({ code: 'custom', path: ['artifactRef'], message: 'Artifact refs must match projectKey' });
44
+ }
45
+ catch {
46
+ ctx.addIssue({ code: 'custom', path: ['artifactRef'], message: 'Artifact refs must be valid stable URLs' });
47
+ }
48
+ });
49
+ export const driveReviewPlaneProjectionSchema = z.object({
50
+ schemaVersion: schemaVersionSchema,
51
+ projectionType: z.literal('GOOGLE_DRIVE_REVIEW'),
52
+ projectionId: sha256Schema,
53
+ relativePath: driveRelativePathSchema,
54
+ workspaceRoot: driveRelativePathSchema,
55
+ reviewStage: z.enum(['PROGRAM', 'INBOX', 'REVIEWED', 'USER_APPROVED', 'PROMOTION_RECEIPTS', 'GUIDES', 'REJECTED_SUPERSEDED']),
56
+ projectKey: projectKeySchema,
57
+ projectRef: stableUriSchema.optional(),
58
+ artifactRef: stableUriSchema,
59
+ identityRef: stableUriSchema,
60
+ contentHash: sha256Schema,
61
+ mediaType: z.string().trim().min(1).max(256),
62
+ byteLength: z.number().int().nonnegative(),
63
+ artifactKind: artifactKindSchema,
64
+ artifactStatus: artifactStatusSchema,
65
+ artifactVersion: z.number().int().positive(),
66
+ }).strict().superRefine((value, ctx) => {
67
+ if (!value.relativePath.startsWith(`${value.workspaceRoot}/`))
68
+ ctx.addIssue({ code: 'custom', path: ['relativePath'], message: 'Review projection path must stay under workspaceRoot' });
69
+ if (value.projectRef) {
70
+ try {
71
+ const project = new URL(value.projectRef);
72
+ if (project.protocol !== 'knowledge-project:' || project.hostname.toLowerCase() !== value.projectKey.toLowerCase())
73
+ ctx.addIssue({ code: 'custom', path: ['projectRef'], message: 'projectRef project must match projectKey' });
74
+ }
75
+ catch {
76
+ ctx.addIssue({ code: 'custom', path: ['projectRef'], message: 'Invalid projectRef' });
77
+ }
78
+ }
79
+ try {
80
+ const artifact = new URL(value.artifactRef);
81
+ const identity = new URL(value.identityRef);
82
+ if (artifact.hostname.toLowerCase() !== value.projectKey.toLowerCase() || identity.hostname.toLowerCase() !== value.projectKey.toLowerCase())
83
+ ctx.addIssue({ code: 'custom', path: ['artifactRef'], message: 'Artifact refs must match projectKey' });
84
+ }
85
+ catch {
86
+ ctx.addIssue({ code: 'custom', path: ['artifactRef'], message: 'Artifact refs must be valid stable URLs' });
87
+ }
88
+ });
89
+ export const driveUploadProjectionSchema = z.union([driveArtifactProjectionSchema, driveReviewPlaneProjectionSchema]);
90
+ export const driveProviderIdSchema = z.string().trim().regex(/^[A-Za-z0-9_-]{10,512}$/);
91
+ export const driveProviderDeliverySchema = z.object({
92
+ provider: z.literal('GOOGLE_DRIVE'),
93
+ fileId: driveProviderIdSchema,
94
+ mimeType: z.string().trim().min(1).max(256),
95
+ byteLength: z.number().int().nonnegative(),
96
+ md5Checksum: z.string().regex(/^[a-f0-9]{32}$/),
97
+ version: z.string().trim().min(1).max(128).nullable(),
98
+ modifiedTime: isoDateTimeSchema.nullable(),
99
+ }).strict();
100
+ export const driveDeliveryReceiptSchema = z.object({
101
+ schemaVersion: schemaVersionSchema,
102
+ projectionId: sha256Schema,
103
+ projectKey: projectKeySchema,
104
+ projectRef: stableUriSchema.optional(),
105
+ artifactRef: stableUriSchema,
106
+ contentHash: sha256Schema,
107
+ relativePath: driveRelativePathSchema,
108
+ deliveredAt: isoDateTimeSchema,
109
+ provider: driveProviderDeliverySchema,
110
+ }).strict().superRefine((value, ctx) => {
111
+ if (value.projectRef) {
112
+ try {
113
+ const project = new URL(value.projectRef);
114
+ if (project.protocol !== 'knowledge-project:' || project.hostname.toLowerCase() !== value.projectKey.toLowerCase())
115
+ ctx.addIssue({ code: 'custom', path: ['projectRef'], message: 'projectRef project must match projectKey' });
116
+ }
117
+ catch {
118
+ ctx.addIssue({ code: 'custom', path: ['projectRef'], message: 'Invalid projectRef' });
119
+ }
120
+ }
121
+ });
122
+ export const driveUploadFolderBindingSchema = z.object({
123
+ relativePath: driveRelativePathSchema,
124
+ name: z.string().trim().min(1).max(255),
125
+ parentFileId: driveProviderIdSchema,
126
+ fileId: driveProviderIdSchema,
127
+ disposition: z.enum(['EXISTING', 'RESERVED']),
128
+ }).strict();
129
+ export const driveUploadFileBindingSchema = z.object({
130
+ name: z.string().trim().min(1).max(255),
131
+ parentFileId: driveProviderIdSchema,
132
+ fileId: driveProviderIdSchema,
133
+ disposition: z.enum(['EXISTING', 'RESERVED']),
134
+ }).strict();
135
+ export const driveUploadIntentSchema = z.object({
136
+ schemaVersion: schemaVersionSchema,
137
+ projectionId: sha256Schema,
138
+ projectKey: projectKeySchema,
139
+ projectRef: stableUriSchema.optional(),
140
+ artifactRef: stableUriSchema,
141
+ contentHash: sha256Schema,
142
+ relativePath: driveRelativePathSchema,
143
+ rootParentFolderId: driveProviderIdSchema,
144
+ sharedDriveId: driveProviderIdSchema.nullable(),
145
+ reservedAt: isoDateTimeSchema,
146
+ folders: z.array(driveUploadFolderBindingSchema).max(32),
147
+ file: driveUploadFileBindingSchema,
148
+ }).strict().superRefine((value, ctx) => {
149
+ if (value.projectRef) {
150
+ try {
151
+ const project = new URL(value.projectRef);
152
+ if (project.protocol !== 'knowledge-project:' || project.hostname.toLowerCase() !== value.projectKey.toLowerCase())
153
+ ctx.addIssue({ code: 'custom', path: ['projectRef'], message: 'projectRef project must match projectKey' });
154
+ }
155
+ catch {
156
+ ctx.addIssue({ code: 'custom', path: ['projectRef'], message: 'Invalid projectRef' });
157
+ }
158
+ }
159
+ });
160
+ export const driveProjectionOutboxEntrySchema = z.object({
161
+ schemaVersion: schemaVersionSchema,
162
+ deliveryId: sha256Schema,
163
+ state: z.enum(['PENDING', 'DELIVERED', 'BLOCKED', 'FAILED_RETRYABLE', 'FAILED_TERMINAL']),
164
+ projection: driveUploadProjectionSchema,
165
+ outboxDirectory: z.string().trim().min(1).max(4096).startsWith('/'),
166
+ descriptorPath: z.string().trim().min(1).max(4096).startsWith('/'),
167
+ payloadPath: z.string().trim().min(1).max(4096).startsWith('/'),
168
+ uploadIntentPath: z.string().trim().min(1).max(4096).startsWith('/').nullable(),
169
+ uploadIntent: driveUploadIntentSchema.nullable(),
170
+ deliveryPath: z.string().trim().min(1).max(4096).startsWith('/').nullable(),
171
+ delivery: driveDeliveryReceiptSchema.nullable(),
172
+ }).strict().superRefine((value, ctx) => {
173
+ if ((value.uploadIntentPath === null) !== (value.uploadIntent === null))
174
+ ctx.addIssue({ code: 'custom', path: ['uploadIntent'], message: 'upload intent path/value must appear together' });
175
+ if (value.state !== 'DELIVERED' && (value.deliveryPath !== null || value.delivery !== null))
176
+ ctx.addIssue({ code: 'custom', path: ['delivery'], message: 'Only DELIVERED entry may carry Drive provider delivery' });
177
+ if (value.state === 'DELIVERED' && (value.deliveryPath === null || value.delivery === null))
178
+ ctx.addIssue({ code: 'custom', path: ['delivery'], message: 'DELIVERED entry requires delivery' });
179
+ });
180
+ export const driveProjectionStagingReceiptSchema = z.object({
181
+ schemaVersion: schemaVersionSchema,
182
+ deliveryId: sha256Schema,
183
+ projectionId: sha256Schema,
184
+ projectRef: stableUriSchema.optional(),
185
+ artifactRef: stableUriSchema,
186
+ contentHash: sha256Schema,
187
+ relativePath: driveRelativePathSchema,
188
+ runtimeNodeId: idSchema,
189
+ stagedAt: isoDateTimeSchema,
190
+ outboxDirectory: z.string().trim().min(1).max(4096).startsWith('/'),
191
+ descriptorPath: z.string().trim().min(1).max(4096).startsWith('/'),
192
+ payloadPath: z.string().trim().min(1).max(4096).startsWith('/'),
193
+ reused: z.boolean(),
194
+ }).strict();
@@ -0,0 +1,87 @@
1
+ import { z } from 'zod';
2
+ import { isoDateTimeSchema, projectKeySchema, sha256Schema, stableUriSchema } from './common.js';
3
+ export const publicReferenceCatalogueScopeSchema = z.object({
4
+ countryCode: z.string().regex(/^[A-Z]{2}$/),
5
+ topicKey: projectKeySchema,
6
+ scopeRef: stableUriSchema,
7
+ // Publication permission is distinct from an independent completeness proof.
8
+ coverage: z.enum(['OBSERVED', 'PARTIAL']),
9
+ }).strict();
10
+ export const publicReferenceApprovedSourceSchema = z.object({ sourceRef: stableUriSchema, contentHash: sha256Schema }).strict();
11
+ export const publicReferenceLegacyReviewSchema = z.object({
12
+ authority: z.literal('AUTHORIZED_PUBLISHER'),
13
+ reviewedAt: isoDateTimeSchema,
14
+ note: z.string().trim().min(1).max(2000),
15
+ approvedSources: z.array(publicReferenceApprovedSourceSchema).min(1).max(256),
16
+ }).strict().superRefine((value, ctx) => {
17
+ if (new Set(value.approvedSources.map(s => s.sourceRef)).size !== value.approvedSources.length)
18
+ ctx.addIssue({ code: 'custom', message: 'approvedSources must be unique' });
19
+ });
20
+ export const publicReferencePolicySchema = z.object({
21
+ schemaVersion: z.literal(1), policyId: projectKeySchema, revision: z.number().int().positive(), enabled: z.boolean(),
22
+ sourceProjectKey: projectKeySchema,
23
+ entries: z.array(z.object({
24
+ corpusKey: projectKeySchema, catalogue: publicReferenceCatalogueScopeSchema,
25
+ recordTypes: z.array(projectKeySchema).min(1).max(128), authorities: z.array(z.string().trim().min(1).max(256)).min(1).max(128),
26
+ minimumRecordCount: z.number().int().positive().max(100_000),
27
+ maximumAssessmentAgeSeconds: z.number().int().positive().max(31_536_000),
28
+ sources: z.array(z.object({
29
+ collectorId: z.string().trim().min(1).max(128), sourceIds: z.array(z.string().trim().min(1).max(128)).min(1).max(256),
30
+ origin: z.string().url().refine(value => { const u = new URL(value); return u.protocol === 'https:' && u.origin === value; }),
31
+ pathPrefixes: z.array(z.string().regex(/^\//).max(2048)).min(1).max(128),
32
+ }).strict()).min(1).max(256),
33
+ }).strict()).min(1).max(128),
34
+ }).strict().superRefine((value, ctx) => {
35
+ if (Buffer.byteLength(JSON.stringify(value)) > 1024 * 1024)
36
+ ctx.addIssue({ code: 'custom', message: 'Policy exceeds 1 MiB' });
37
+ if (new Set(value.entries.map(entry => entry.corpusKey)).size !== value.entries.length)
38
+ ctx.addIssue({ code: 'custom', message: 'Policy corpus keys must be unique' });
39
+ });
40
+ export const publicReferenceMachineReviewSchema = z.object({
41
+ authority: z.literal('POLICY_ENGINE'), reviewedAt: isoDateTimeSchema,
42
+ note: z.literal('DETERMINISTIC_PUBLIC_SOURCE_VALIDATION'),
43
+ validationRule: z.literal('public-reference.policy.v1'), policyId: projectKeySchema,
44
+ policyRevision: z.number().int().positive(), policyDigest: sha256Schema,
45
+ executorRevision: z.string().regex(/^[a-f0-9]{40,64}$/),
46
+ approvedSources: z.array(publicReferenceApprovedSourceSchema).max(256),
47
+ }).strict();
48
+ export const publicReferenceReviewSchema = z.union([publicReferenceLegacyReviewSchema, publicReferenceMachineReviewSchema]);
49
+ export const publicReferencePublishInputSchema = z.object({
50
+ publicationKey: projectKeySchema, corpusKey: projectKeySchema, releaseId: sha256Schema, recordsContentHash: sha256Schema,
51
+ catalogue: publicReferenceCatalogueScopeSchema, review: publicReferenceReviewSchema,
52
+ }).strict();
53
+ export const publicReferenceWithdrawInputSchema = z.object({
54
+ publicationRef: z.string().regex(/^public-reference:\/\/[a-f0-9]{64}$/),
55
+ reason: z.string().trim().min(1).max(2000),
56
+ }).strict();
57
+ export const publicReferencePublicationBasisSchema = z.object({
58
+ schemaVersion: z.union([z.literal(1), z.literal(2)]), visibility: z.literal('PUBLIC_REFERENCE'),
59
+ sourceProjectKey: projectKeySchema, corpusKey: projectKeySchema,
60
+ sourceReleaseId: sha256Schema, sourceReleaseRef: stableUriSchema,
61
+ recordsContentHash: sha256Schema, recordsByteLength: z.number().int().positive().max(512 * 1024 * 1024),
62
+ recordCount: z.number().int().positive().max(100_000),
63
+ recordTypes: z.array(projectKeySchema).min(1).max(128),
64
+ sourceCreatedAt: isoDateTimeSchema,
65
+ catalogue: publicReferenceCatalogueScopeSchema, review: publicReferenceReviewSchema,
66
+ publishedAt: isoDateTimeSchema, checkedAt: isoDateTimeSchema, validUntil: isoDateTimeSchema,
67
+ }).strict();
68
+ export const publicReferencePublicationSchema = publicReferencePublicationBasisSchema.extend({
69
+ publicationId: sha256Schema,
70
+ publicationRef: z.string().regex(/^public-reference:\/\/[a-f0-9]{64}$/),
71
+ }).strict().superRefine((value, ctx) => {
72
+ if ((value.schemaVersion === 2) !== (value.review.authority === 'POLICY_ENGINE') || !value.review.approvedSources.length)
73
+ ctx.addIssue({ code: 'custom', message: 'Publication validation authority invalid' });
74
+ if (value.publicationRef !== 'public-reference://' + value.publicationId.slice(7))
75
+ ctx.addIssue({ code: 'custom', message: 'publication identity mismatch' });
76
+ if (Date.parse(value.validUntil) <= Date.parse(value.publishedAt) || Date.parse(value.checkedAt) > Date.parse(value.publishedAt)
77
+ || Date.parse(value.review.reviewedAt) > Date.parse(value.publishedAt) || Date.parse(value.review.reviewedAt) < Date.parse(value.sourceCreatedAt))
78
+ ctx.addIssue({ code: 'custom', message: 'publication chronology invalid' });
79
+ });
80
+ export const publicReferenceCatalogueQuerySchema = z.object({
81
+ countryCode: z.string().regex(/^[A-Z]{2}$/).optional(), topicKey: projectKeySchema.optional(),
82
+ after: sha256Schema.optional(), limit: z.number().int().min(1).max(100).default(20),
83
+ }).strict();
84
+ export function publicReferencePublicationBasis(value) {
85
+ const { publicationId: _id, publicationRef: _ref, ...basis } = value;
86
+ return publicReferencePublicationBasisSchema.parse(basis);
87
+ }