@native-knowledge/cli 0.1.0-rc.1 → 0.1.0-rc.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. package/LICENSE +202 -21
  2. package/NOTICE +29 -0
  3. package/dist/agent-entry-cli.js +90 -0
  4. package/dist/auth-commands.js +102 -0
  5. package/dist/cli.js +106 -4874
  6. package/dist/commands.js +41 -0
  7. package/dist/download.js +45 -0
  8. package/dist/errors.js +7 -0
  9. package/dist/input.js +89 -0
  10. package/dist/internal/contracts/artifact.js +103 -0
  11. package/dist/internal/contracts/collection-control.js +69 -0
  12. package/dist/internal/contracts/collection.js +174 -0
  13. package/dist/internal/contracts/common.js +16 -0
  14. package/dist/internal/contracts/currentness.js +221 -0
  15. package/dist/internal/contracts/event.js +35 -0
  16. package/dist/internal/contracts/evidence.js +171 -0
  17. package/dist/internal/contracts/index.js +55 -0
  18. package/dist/internal/contracts/material-capability.js +8 -0
  19. package/dist/internal/contracts/material-carrier.js +15 -0
  20. package/dist/internal/contracts/material-context.js +9 -0
  21. package/dist/internal/contracts/material-read.js +12 -0
  22. package/dist/internal/contracts/observation.js +39 -0
  23. package/dist/internal/contracts/persistence.js +239 -0
  24. package/dist/internal/contracts/project-intent.js +121 -0
  25. package/dist/internal/contracts/projection.js +194 -0
  26. package/dist/internal/contracts/public-reference.js +87 -0
  27. package/dist/internal/contracts/reference-record.js +55 -0
  28. package/dist/internal/contracts/remote-file.js +159 -0
  29. package/dist/internal/contracts/resource-scope.js +38 -0
  30. package/dist/internal/contracts/resource-transfer.js +11 -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 +137 -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 +7 -17
  94. package/README.md +0 -28
@@ -0,0 +1,76 @@
1
+ // Compatibility exports: immutable Reference facts are owned by contracts.
2
+ import { referenceRecordTypeSchema, referenceSelectorKeySchema, referenceSelectorValueSchema, referenceSelectorsSchema, referenceCurrentnessStateSchema, referenceCurrentnessSchema, referenceCorpusSummarySchema, referenceCorpusRecordSchema } from '../contracts/index.js';
3
+ export { referenceRecordTypeSchema, referenceSelectorKeySchema, referenceSelectorValueSchema, referenceSelectorsSchema, referenceCurrentnessStateSchema, referenceCurrentnessSchema, referenceCorpusSummarySchema, referenceCorpusRecordSchema } from '../contracts/index.js';
4
+ import { z } from 'zod';
5
+ import { accessClassificationSchema, artifactKindSchema, artifactStatusSchema, currentnessActionSchema, currentnessStateSchema, idSchema, isoDateTimeSchema, projectKeySchema, schemaVersionSchema, sha256Schema, stableUriSchema, } from '../contracts/index.js';
6
+ export const servingActionSchema = z.enum(['ALLOW', 'REVIEW_REQUIRED', 'DENY']);
7
+ export const servingProblemCodeSchema = z.enum([
8
+ 'NOT_FOUND', 'ACCESS_DENIED', 'CONTENT_ACCESS_DENIED', 'ARTIFACT_NOT_APPROVED', 'ARTIFACT_SUPERSEDED',
9
+ 'SEMANTIC_REVIEW_REQUIRED', 'SEMANTIC_DENIED', 'SEMANTIC_ADMISSION_MISSING',
10
+ 'CURRENTNESS_MISSING', 'CURRENTNESS_REVIEW_REQUIRED', 'CURRENTNESS_DENIED', 'STALE', 'VALIDITY_EXPIRED',
11
+ 'CLAIM_REVIEW_REQUIRED', 'CLAIM_DENIED', 'CLAIM_NOT_EFFECTIVE',
12
+ 'REFERENCE_NOT_COVERED', 'REFERENCE_NOT_EFFECTIVE', 'REFERENCE_VALIDITY_EXPIRED', 'REFERENCE_STALE', 'REFERENCE_UNAVAILABLE', 'REFERENCE_REVIEW_REQUIRED', 'REFERENCE_DENIED',
13
+ 'UNSUPPORTED_RESOURCE', 'GOVERNANCE_NOT_CONFIGURED', 'UNAVAILABLE', 'INTEGRITY_MISMATCH',
14
+ ]);
15
+ export const servingDecisionSchema = z.object({
16
+ schemaVersion: schemaVersionSchema,
17
+ action: servingActionSchema,
18
+ reasonCodes: z.array(servingProblemCodeSchema).max(32),
19
+ assessedAt: isoDateTimeSchema,
20
+ }).strict().superRefine((value, ctx) => {
21
+ if (value.action === 'ALLOW' && value.reasonCodes.length)
22
+ ctx.addIssue({ code: 'custom', path: ['reasonCodes'], message: 'ALLOW must not carry problem codes' });
23
+ if (value.action !== 'ALLOW' && !value.reasonCodes.length)
24
+ ctx.addIssue({ code: 'custom', path: ['reasonCodes'], message: 'Non-ALLOW decision requires a problem code' });
25
+ });
26
+ export const consumerProfileSchema = z.object({
27
+ schemaVersion: schemaVersionSchema,
28
+ consumerKey: projectKeySchema,
29
+ acceptedArtifactKinds: z.array(artifactKindSchema).max(16),
30
+ acceptedAccess: z.array(accessClassificationSchema).max(7),
31
+ contentAccess: z.array(accessClassificationSchema).max(7),
32
+ acceptedReferenceTypes: z.array(referenceRecordTypeSchema).max(128),
33
+ }).strict().superRefine((value, ctx) => {
34
+ if (new Set(value.acceptedArtifactKinds).size !== value.acceptedArtifactKinds.length)
35
+ ctx.addIssue({ code: 'custom', path: ['acceptedArtifactKinds'], message: 'acceptedArtifactKinds must be unique' });
36
+ if (new Set(value.acceptedAccess).size !== value.acceptedAccess.length)
37
+ ctx.addIssue({ code: 'custom', path: ['acceptedAccess'], message: 'acceptedAccess must be unique' });
38
+ if (new Set(value.contentAccess).size !== value.contentAccess.length)
39
+ ctx.addIssue({ code: 'custom', path: ['contentAccess'], message: 'contentAccess must be unique' });
40
+ if (value.contentAccess.some((access) => !value.acceptedAccess.includes(access)))
41
+ ctx.addIssue({ code: 'custom', path: ['contentAccess'], message: 'contentAccess must be a subset of acceptedAccess' });
42
+ if (value.contentAccess.some((access) => ['PUBLIC_METADATA', 'ACCESS_CONTROLLED', 'UNKNOWN'].includes(access)))
43
+ ctx.addIssue({ code: 'custom', path: ['contentAccess'], message: 'Metadata-only, access-controlled and unknown classes cannot grant content access' });
44
+ if (new Set(value.acceptedReferenceTypes).size !== value.acceptedReferenceTypes.length)
45
+ ctx.addIssue({ code: 'custom', path: ['acceptedReferenceTypes'], message: 'acceptedReferenceTypes must be unique' });
46
+ });
47
+ export const servingContentDescriptorSchema = z.object({
48
+ contentHash: sha256Schema, mediaType: z.string().trim().min(1).max(256), byteLength: z.number().int().nonnegative(),
49
+ }).strict();
50
+ export const servingArtifactSummarySchema = z.object({
51
+ ref: stableUriSchema, identityRef: stableUriSchema, projectKey: projectKeySchema, projectRef: stableUriSchema.nullable().default(null), artifactId: idSchema, kind: artifactKindSchema,
52
+ version: z.number().int().positive(), status: artifactStatusSchema, access: accessClassificationSchema, title: z.string().max(500).nullable(),
53
+ createdAt: isoDateTimeSchema, observedAt: isoDateTimeSchema.nullable(), validUntil: isoDateTimeSchema.nullable(), content: servingContentDescriptorSchema,
54
+ }).strict();
55
+ export const servingArtifactDetailSchema = servingArtifactSummarySchema.extend({
56
+ evidenceRefs: z.array(stableUriSchema).max(256), relatedRefs: z.array(stableUriSchema).max(256), supersedesRef: stableUriSchema.nullable(),
57
+ }).strict();
58
+ export const servingEvidenceSummarySchema = z.object({
59
+ evidenceRef: stableUriSchema, projectKey: projectKeySchema, sourceId: idSchema, contentHash: sha256Schema, observedAt: isoDateTimeSchema,
60
+ access: accessClassificationSchema, canonicalUri: stableUriSchema.nullable(), mediaType: z.string().max(256).nullable(), byteLength: z.number().int().nonnegative().nullable(),
61
+ projectRef: stableUriSchema.nullable().default(null), sourceSetRef: stableUriSchema.nullable(), sourceItemId: idSchema.nullable(), sourceRevisionRef: stableUriSchema.nullable().default(null), collectionBatchRef: stableUriSchema.nullable().default(null), collectionTaskId: idSchema.nullable().default(null),
62
+ }).strict();
63
+ export const servingSourceSummarySchema = z.object({
64
+ sourceId: idSchema, familyId: idSchema, authority: z.string().min(1).max(512), access: accessClassificationSchema, freshness: z.string().min(1).max(128),
65
+ declaredState: z.string().min(1).max(128), coverageState: z.string().max(128).nullable(), asOf: isoDateTimeSchema,
66
+ }).strict();
67
+ export const servingProjectIntentSummarySchema = z.object({
68
+ projectKey: projectKeySchema, projectRef: stableUriSchema, tenantId: idSchema, revisionRef: stableUriSchema, projectName: z.string().trim().min(1).max(256), updatedAt: isoDateTimeSchema,
69
+ }).strict();
70
+ export const servingProjectSourceSummarySchema = z.object({
71
+ projectKey: projectKeySchema, projectRef: stableUriSchema, projectIntentRef: stableUriSchema.nullable(), sourceId: idSchema, sourceRef: stableUriSchema, sourceRevisionRef: stableUriSchema, targetId: sha256Schema, targetKind: z.enum(['URL', 'FILE', 'EXECUTOR']), locator: stableUriSchema, executorId: idSchema.nullable().default(null), enabled: z.boolean(), access: accessClassificationSchema, refreshMode: z.enum(['MANUAL', 'INTERVAL']), intervalSeconds: z.number().int().min(60).nullable(), updatedAt: isoDateTimeSchema,
72
+ }).strict();
73
+ export const servingGovernanceSourceSummarySchema = servingSourceSummarySchema;
74
+ export const servingCurrentnessSchema = z.object({
75
+ subjectRef: stableUriSchema, projectRef: stableUriSchema.nullable().default(null), sourceRevisionRef: stableUriSchema.nullable().default(null), state: currentnessStateSchema, action: currentnessActionSchema, assessedAt: isoDateTimeSchema, dueAt: isoDateTimeSchema.nullable(), staleAt: isoDateTimeSchema.nullable(), reasonCode: z.string().min(1).max(128),
76
+ }).strict();
@@ -0,0 +1,64 @@
1
+ import { rawMaterialDirectoryItemSchema } from '../contracts/index.js';
2
+ import { z } from 'zod';
3
+ import { accessClassificationSchema, isoDateTimeSchema, projectKeySchema, richDocumentSchema, schemaVersionSchema, sha256Schema, stableUriSchema } from '../contracts/index.js';
4
+ import { referenceCorpusRecordSchema, referenceCorpusSummarySchema, servingArtifactDetailSchema, servingArtifactSummarySchema, servingCurrentnessSchema, servingDecisionSchema, servingEvidenceSummarySchema, servingSourceSummarySchema, servingProjectIntentSummarySchema, servingProjectSourceSummarySchema, } from './core.js';
5
+ import { consumerProjectRefSchema, consumerReferenceLookupItemSchema } from './consumer.js';
6
+ const decisionArtifactSummarySchema = z.object({ decision: servingDecisionSchema, artifact: servingArtifactSummarySchema }).strict();
7
+ const decisionEvidenceSummarySchema = z.object({ decision: servingDecisionSchema, evidence: servingEvidenceSummarySchema }).strict();
8
+ const decisionProjectSourceSummarySchema = z.object({ decision: servingDecisionSchema, source: servingProjectSourceSummarySchema }).strict();
9
+ const decisionReferenceSummarySchema = z.object({ decision: servingDecisionSchema, record: referenceCorpusSummarySchema }).strict();
10
+ export const servingApiErrorSchema = z.object({ errorCode: z.string().trim().min(1).max(128).regex(/^[A-Z0-9_]+$/) }).strict();
11
+ export const servingHealthResponseSchema = z.object({ schemaVersion: schemaVersionSchema, status: z.literal('ok'), service: z.literal('knowledge-api'), codeRevision: z.string().trim().min(1).max(128) }).strict();
12
+ export const servingArtifactListResponseSchema = z.object({ schemaVersion: schemaVersionSchema, projectKey: projectKeySchema, items: z.array(decisionArtifactSummarySchema).max(1000) }).strict();
13
+ /** Live, authorization-scoped page. A cursor is a position hint, never a grant or snapshot. */
14
+ export const servingArtifactPageResponseSchema = z.object({ schemaVersion: schemaVersionSchema, projectKey: projectKeySchema, items: z.array(decisionArtifactSummarySchema).max(100), nextAfter: z.string().max(4096).nullable(), scanSemantics: z.literal('LIVE_AUTHORIZED'), versionCoverage: z.literal('AUTHORIZED_REFERENCES_ONLY') }).strict();
15
+ /** Raw immutable snapshots remain separate from governed Knowledge decisions. */
16
+ export const servingArtifactMaterialPageResponseSchema = z.object({ schemaVersion: schemaVersionSchema, projectKey: projectKeySchema, contentClass: z.literal('ARTIFACT_SNAPSHOT'), items: z.array(z.object({ decision: servingDecisionSchema, governanceDecision: servingDecisionSchema, artifact: servingArtifactSummarySchema }).strict()).max(100), nextAfter: z.string().max(4096).nullable(), scanSemantics: z.literal('LIVE_AUTHORIZED'), versionCoverage: z.literal('AUTHORIZED_REFERENCES_ONLY') }).strict();
17
+ export const servingArtifactMaterialResponseSchema = z.object({ schemaVersion: schemaVersionSchema, projectKey: projectKeySchema, contentClass: z.literal('ARTIFACT_SNAPSHOT'), decision: servingDecisionSchema, governanceDecision: servingDecisionSchema, artifact: servingArtifactDetailSchema.nullable() }).strict();
18
+ export const servingArtifactResponseSchema = z.object({ schemaVersion: schemaVersionSchema, projectKey: projectKeySchema, decision: servingDecisionSchema, artifact: servingArtifactDetailSchema.nullable() }).strict();
19
+ export const servingEvidenceListResponseSchema = z.object({ schemaVersion: schemaVersionSchema, projectKey: projectKeySchema, items: z.array(decisionEvidenceSummarySchema).max(1000) }).strict();
20
+ // 不把文件可下载误称为结构化正文;状态不包含任何未授权的正文派生文本。
21
+ export const servingEvidenceFormatQualitySchema = z.object({ format: z.enum(['HTML', 'PDF', 'FEED', 'XML', 'MARKDOWN', 'CSV', 'JSON', 'IMAGE', 'VIDEO', 'AUDIO', 'TEXT', 'OTHER']), rawFile: z.enum(['AVAILABLE', 'DENIED']), projection: z.enum(['READY', 'EMPTY', 'MISSING', 'UNSUPPORTED', 'DENIED']), media: z.enum(['COMPLETE', 'PARTIAL', 'NONE', 'UNASSESSED']) }).strict();
22
+ // 通用文件发现页区分原始文件读取权和已审核知识的正文消费权。
23
+ export const servingEvidencePageResponseSchema = z.object({ schemaVersion: schemaVersionSchema, projectKey: projectKeySchema, items: z.array(decisionEvidenceSummarySchema.extend({ fileDecision: servingDecisionSchema, contentDecision: servingDecisionSchema, formatQuality: servingEvidenceFormatQualitySchema.optional(), presentation: z.object({ title: z.string().max(1000).nullable(), summary: z.string().max(4000).nullable(), byline: z.string().max(1000).nullable(), publishedAt: isoDateTimeSchema.nullable(), language: z.string().max(64).nullable(), topics: z.array(z.string().max(160)).max(32).optional(), documentRef: stableUriSchema, documentContentHash: sha256Schema, quality: z.object({ bodyCharacters: z.number().int().nonnegative(), mediaTotal: z.number().int().nonnegative(), mediaMirrored: z.number().int().nonnegative(), mediaUnavailable: z.number().int().nonnegative(), mediaTooLarge: z.number().int().nonnegative() }).strict() }).strict().nullable().optional() })).max(100), nextAfter: stableUriSchema.nullable() }).strict().superRefine((value, ctx) => { for (let index = 0; index < value.items.length; index++) {
24
+ const item = value.items[index];
25
+ if (item.presentation && item.fileDecision.action !== 'ALLOW')
26
+ ctx.addIssue({ code: 'custom', path: ['items', index, 'presentation'], message: 'Body-derived presentation requires raw-file authorization' });
27
+ } });
28
+ /** A readable representation of original Evidence, never a reviewed Knowledge artifact. */
29
+ export const servingEvidencePresentationResponseSchema = z.object({ schemaVersion: schemaVersionSchema, projectKey: projectKeySchema, decision: servingDecisionSchema, contentClass: z.literal('RAW_EVIDENCE_PRESENTATION'), presentation: z.object({ sourceEvidenceRef: stableUriSchema, sourceContentHash: sha256Schema, documentRef: stableUriSchema, documentContentHash: sha256Schema, document: richDocumentSchema }).strict().nullable() }).strict().superRefine((value, ctx) => {
30
+ if ((value.decision.action === 'ALLOW') !== Boolean(value.presentation))
31
+ ctx.addIssue({ code: 'custom', path: ['presentation'], message: 'Presentation must match the current decision' });
32
+ if (value.presentation && (value.presentation.document.role !== 'SOURCE_MIRROR' || value.presentation.document.sourceContentHash !== value.presentation.sourceContentHash || value.presentation.document.primarySourceEvidenceRef !== value.presentation.sourceEvidenceRef || value.presentation.document.projectKey !== /^evidence:\/\/([^/]+)\//.exec(value.presentation.sourceEvidenceRef)?.[1]))
33
+ ctx.addIssue({ code: 'custom', path: ['presentation'], message: 'Presentation source identity mismatch' });
34
+ });
35
+ export const oauthMaterialPresentationResponseSchema = servingEvidencePresentationResponseSchema.safeExtend({ projectRef: consumerProjectRefSchema });
36
+ export const servingEvidenceResponseSchema = z.object({ schemaVersion: schemaVersionSchema, projectKey: projectKeySchema, decision: servingDecisionSchema, evidence: servingEvidenceSummarySchema.nullable() }).strict();
37
+ export const servingProjectIntentResponseSchema = z.object({ schemaVersion: schemaVersionSchema, projectKey: projectKeySchema, decision: servingDecisionSchema, project: servingProjectIntentSummarySchema.nullable() }).strict();
38
+ export const servingProjectSourceListResponseSchema = z.object({ schemaVersion: schemaVersionSchema, projectKey: projectKeySchema, items: z.array(decisionProjectSourceSummarySchema).max(1000) }).strict();
39
+ export const servingProjectSourceResponseSchema = z.object({ schemaVersion: schemaVersionSchema, projectKey: projectKeySchema, decision: servingDecisionSchema, source: servingProjectSourceSummarySchema.nullable() }).strict();
40
+ export const servingSourceResponseSchema = z.object({ schemaVersion: schemaVersionSchema, projectKey: projectKeySchema, decision: servingDecisionSchema, source: servingSourceSummarySchema.nullable() }).strict();
41
+ export const servingCurrentnessResponseSchema = z.object({ schemaVersion: schemaVersionSchema, projectKey: projectKeySchema, decision: servingDecisionSchema, currentness: servingCurrentnessSchema.nullable() }).strict();
42
+ export const servingReferenceListResponseSchema = z.object({ schemaVersion: schemaVersionSchema, projectKey: projectKeySchema, items: z.array(decisionReferenceSummarySchema).max(1000) }).strict();
43
+ export const servingReferenceResponseSchema = z.object({ schemaVersion: schemaVersionSchema, projectKey: projectKeySchema, decision: servingDecisionSchema, record: referenceCorpusRecordSchema.nullable() }).strict();
44
+ export const servingReferenceMaterialPageResponseSchema = z.object({ schemaVersion: schemaVersionSchema, projectKey: projectKeySchema, contentClass: z.literal('REFERENCE_SNAPSHOT'), items: z.array(z.object({ decision: servingDecisionSchema, record: referenceCorpusSummarySchema }).strict()).max(100), nextAfter: stableUriSchema.nullable() }).strict();
45
+ export const servingReferenceMaterialResponseSchema = z.object({ schemaVersion: schemaVersionSchema, projectKey: projectKeySchema, contentClass: z.literal('REFERENCE_SNAPSHOT'), decision: servingDecisionSchema, record: referenceCorpusRecordSchema.nullable() }).strict();
46
+ /** Type-neutral discovery over current project references; kind is descriptive, never an admission list. */
47
+ export const servingMaterialDirectoryItemSchema = rawMaterialDirectoryItemSchema;
48
+ export const servingMaterialPageResponseSchema = z.object({ schemaVersion: schemaVersionSchema, projectKey: projectKeySchema, contentClass: z.literal('MATERIAL_DIRECTORY'), items: z.array(servingMaterialDirectoryItemSchema).max(100), nextAfter: stableUriSchema.nullable(), scanSemantics: z.literal('LIVE_AUTHORIZED') }).strict();
49
+ export const servingMaterialRoutePageResponseSchema = z.object({ schemaVersion: schemaVersionSchema, projectKey: projectKeySchema, routeId: z.string().regex(/^[a-f0-9]{64}$/), contentClass: z.literal('MATERIAL_DIRECTORY'), routeState: z.enum(['ACTIVE', 'REVOKED', 'UNBOUND']), items: z.array(servingMaterialDirectoryItemSchema).max(100), nextAfter: stableUriSchema.nullable() }).strict();
50
+ export const materialRoutePartitionSchema = z.object({ routeId: z.string().regex(/^[a-f0-9]{64}$/), sourceProjectKey: projectKeySchema, matchType: z.enum(['SOURCE_PROJECT', 'SOURCE_SET', 'REF']), matchValue: z.string().min(1).max(4096) }).strict();
51
+ export const servingMaterialPartitionsResponseSchema = z.object({ schemaVersion: schemaVersionSchema, projectKey: projectKeySchema, coverage: z.literal('OWNER_LEGACY_AND_ACTIVE_ROUTES'), items: z.array(materialRoutePartitionSchema).max(100), nextAfterRouteId: z.string().regex(/^[a-f0-9]{64}$/).nullable() }).strict();
52
+ export const servingMaterialPartitionPageResponseSchema = z.object({ schemaVersion: schemaVersionSchema, projectKey: projectKeySchema, contentClass: z.literal('MATERIAL_DIRECTORY'), partition: z.enum(['OWNER', 'LEGACY']), items: z.array(servingMaterialDirectoryItemSchema).max(100), nextAfter: stableUriSchema.nullable() }).strict();
53
+ export const servingMaterialSearchResponseSchema = z.object({ schemaVersion: schemaVersionSchema, projectKey: projectKeySchema, queryCoverage: z.literal('DESCRIPTIVE_METADATA_V1'), order: z.literal('INDEX_ROWID_ASC'), indexState: z.enum(['PARTIAL_BACKFILL', 'SYNCED_AS_OF_LAST_OBSERVATION']), configuredSourceCount: z.number().int().nonnegative(), items: z.array(z.object({ item: servingMaterialDirectoryItemSchema, title: z.string().max(512), summary: z.string().max(1024) }).strict()).max(20), nextAfterId: z.number().int().positive().nullable() }).strict();
54
+ export const oauthMaterialPageResponseSchema = z.discriminatedUnion('resourceType', [
55
+ z.object({ schemaVersion: schemaVersionSchema, projectRef: consumerProjectRefSchema, projectKey: projectKeySchema, resourceType: z.literal('all'), contentClass: z.literal('MATERIAL_DIRECTORY'), items: servingMaterialPageResponseSchema.shape.items, nextAfter: stableUriSchema.nullable() }).strict(),
56
+ z.object({ schemaVersion: schemaVersionSchema, projectRef: consumerProjectRefSchema, projectKey: projectKeySchema, resourceType: z.literal('artifact'), contentClass: z.literal('ARTIFACT_SNAPSHOT'), items: servingArtifactMaterialPageResponseSchema.shape.items, nextAfter: z.string().max(4096).nullable() }).strict(),
57
+ z.object({ schemaVersion: schemaVersionSchema, projectRef: consumerProjectRefSchema, projectKey: projectKeySchema, resourceType: z.literal('evidence'), contentClass: z.literal('RAW_EVIDENCE'), items: servingEvidencePageResponseSchema.shape.items, nextAfter: stableUriSchema.nullable() }).strict(),
58
+ z.object({ schemaVersion: schemaVersionSchema, projectRef: consumerProjectRefSchema, projectKey: projectKeySchema, resourceType: z.literal('reference'), contentClass: z.literal('REFERENCE_SNAPSHOT'), items: servingReferenceMaterialPageResponseSchema.shape.items, nextAfter: stableUriSchema.nullable() }).strict(),
59
+ ]);
60
+ export const servingReferenceLookupResponseSchema = z.object({ schemaVersion: schemaVersionSchema, projectKey: projectKeySchema, lookupCoverage: z.literal('AUTHORIZED_REFERENCE_SELECTORS_V1'), items: z.array(consumerReferenceLookupItemSchema).max(100) }).strict();
61
+ export const servingContentDecisionResponseSchema = z.object({ schemaVersion: schemaVersionSchema, projectKey: projectKeySchema, decision: servingDecisionSchema, content: z.null() }).strict();
62
+ export const servingContentHeadersSchema = z.object({ contentHash: sha256Schema, mediaType: z.string().trim().min(1).max(256), byteLength: z.number().int().nonnegative(), assessedAt: z.string().datetime({ offset: true }) }).strict();
63
+ /** Recovery checkpoint is captured before bootstrap; incremental replay starts after headSeq. */
64
+ export const materialOutboxWindowSchema = z.object({ schemaVersion: schemaVersionSchema, tenantId: z.string().min(1), retainedThroughSeq: z.number().int().nonnegative().safe(), headSeq: z.number().int().nonnegative().safe() }).strict().refine(value => value.retainedThroughSeq <= value.headSeq, { message: 'Outbox floor must not exceed head' });
@@ -0,0 +1,25 @@
1
+ export * from './core.js';
2
+ export * from './http.js';
3
+ export * from './consumer.js';
4
+ export * from './mcp.js';
5
+ export * from './management.js';
6
+ export * from './material-capabilities.js';
7
+ export * from './material-index-status.js';
8
+ // CLI、MCP 与 HTTPS 共享同一 Agent 治理合同,避免各入口自行解释状态。
9
+ export * from './workflow.js';
10
+ export * from './tenant-governance.js';
11
+ export * from './tenant-management.js';
12
+ export * from './tenant-workspace.js';
13
+ export * from './tenant-project.js';
14
+ export * from './tenant-runtime.js';
15
+ export * from './tenant-web.js';
16
+ export * from './tenant-web-crawl.js';
17
+ export * from './tenant-web-dynamic.js';
18
+ export * from './tenant-web-content.js';
19
+ export * from './tenant-web-workflow.js';
20
+ export * from './tenant-session.js';
21
+ export * from './agent-entry.js';
22
+ export * from './agent-catalog.js';
23
+ export * from './body-search.js';
24
+ export * from './agent-guidance-shapes.js';
25
+ export * from './agent-input-hints.js';
@@ -0,0 +1,15 @@
1
+ /** 管理 MCP 的参数只携带项目引用和治理输入;项目 Key、Tenant 和节点均由服务端绑定解析。 */
2
+ import { z } from 'zod';
3
+ import { artifactIdSchema, isoDateTimeSchema, publicationProfileSchema, richCompositionDraftSchema, stableUriSchema } from '../contracts/index.js';
4
+ import { consumerProjectRefSchema } from './consumer.js';
5
+ const version = z.number().int().nonnegative();
6
+ const base = z.object({ projectRef: consumerProjectRefSchema }).strict();
7
+ export const managementComposeInputSchema = base.extend({ sourceEvidenceRefs: z.array(stableUriSchema).min(1).max(64), primarySourceEvidenceRef: stableUriSchema.optional(), artifactId: artifactIdSchema, expectedVersion: version, composedAt: isoDateTimeSchema, validUntil: isoDateTimeSchema.optional(), outputKind: z.enum(['KNOWLEDGE', 'INSIGHT']), publicationProfile: publicationProfileSchema.optional(), title: z.string().trim().min(1).max(1000).optional(), composition: richCompositionDraftSchema.optional() }).strict();
8
+ export const managementSubmitInputSchema = base.extend({ ref: stableUriSchema, expectedVersion: version, createdAt: isoDateTimeSchema }).strict();
9
+ export const managementReviewInputSchema = base.extend({ targetRef: stableUriSchema, expectedVersion: version, decision: z.enum(['PASS', 'REWORK', 'REJECT']), reviewedAt: isoDateTimeSchema, summary: z.string().trim().min(1).max(8000), evidenceRefs: z.array(stableUriSchema).max(64).optional() }).strict();
10
+ export const managementFinalizeInputSchema = base.extend({ ref: stableUriSchema, expectedVersion: version, nextStatus: z.enum(['APPROVED', 'REWORK_REQUIRED', 'REJECTED']), reviewRef: stableUriSchema, createdAt: isoDateTimeSchema }).strict();
11
+ export const managementResultSchema = z.object({ schemaVersion: z.literal(1), projectRef: consumerProjectRefSchema, ref: stableUriSchema, kind: z.enum(['KNOWLEDGE', 'INSIGHT', 'REVIEW']), version: z.number().int().positive(), status: z.enum(['DRAFT', 'READY_FOR_REVIEW', 'APPROVED', 'REWORK_REQUIRED', 'REJECTED']), contentHash: z.string().regex(/^sha256:[a-f0-9]{64}$/), inserted: z.boolean() }).strict();
12
+ // MCP 公告和服务端参数校验从同一组合同生成,避免工具描述与实际输入漂移。
13
+ export const managementToolInputSchemas = { knowledge_compose: z.toJSONSchema(managementComposeInputSchema, { target: 'draft-07' }), knowledge_submit_review: z.toJSONSchema(managementSubmitInputSchema, { target: 'draft-07' }), knowledge_review: z.toJSONSchema(managementReviewInputSchema, { target: 'draft-07' }), knowledge_finalize_review: z.toJSONSchema(managementFinalizeInputSchema, { target: 'draft-07' }) };
14
+ export const managementToolErrorOutputSchema = { type: 'object', properties: { errorCode: { type: 'string' }, completedPhase: { type: 'string', enum: ['VALIDATED', 'PERSISTED', 'CATALOG_PROJECTED'] }, ref: z.toJSONSchema(stableUriSchema, { target: 'draft-07' }) }, required: ['errorCode'], additionalProperties: false };
15
+ export const managementToolOutputSchema = { type: 'object', oneOf: [z.toJSONSchema(managementResultSchema, { target: 'draft-07' }), managementToolErrorOutputSchema] };
@@ -0,0 +1,14 @@
1
+ import { rawRetrievalDecisionSchema } from '../contracts/index.js';
2
+ import { z } from 'zod';
3
+ import { projectKeySchema, stableUriSchema, sha256Schema } from '../contracts/index.js';
4
+ import { servingMaterialDirectoryItemSchema } from './http.js';
5
+ import { materialReadStateSchema, materialCapabilitySchema } from '../contracts/index.js';
6
+ export { materialReadStateSchema, materialCapabilitySchema } from '../contracts/index.js';
7
+ export const materialCapabilityResponseSchema = z.object({ schemaVersion: z.literal(2), projectKey: projectKeySchema, material: materialCapabilitySchema }).strict();
8
+ export const materialCapabilityPageSchema = z.object({ schemaVersion: z.literal(2), projectKey: projectKeySchema, items: z.array(materialCapabilitySchema).max(100), nextAfter: stableUriSchema.nullable() }).strict();
9
+ export const materialMediaCapabilityPageSchema = z.object({ schemaVersion: z.literal(2), projectKey: projectKeySchema, ref: stableUriSchema, sourceContentHash: sha256Schema, documentRef: stableUriSchema.nullable(), documentContentHash: sha256Schema.nullable(), state: z.enum(['READY', 'MISSING', 'DENIED', 'UNSUPPORTED', 'INTEGRITY_MISMATCH']), items: z.array(z.object({ ordinal: z.number().int().nonnegative(), kind: z.enum(['IMAGE', 'VIDEO', 'AUDIO']), sourceUrl: z.string().url(), canonicalUrl: z.string().url().nullable(), availability: z.enum(['MIRRORED', 'REMOTE_ONLY', 'UNAVAILABLE']), mediaRef: stableUriSchema.nullable(), contentHash: sha256Schema.nullable(), mediaType: z.string().nullable(), byteLength: z.number().int().nonnegative().safe().nullable(), state: z.enum(['READY', 'REMOTE_ONLY', 'UNAVAILABLE', 'MISSING', 'DENIED', 'INTEGRITY_MISMATCH']), representation: materialCapabilitySchema.shape.representation.nullable() }).strict()).max(100), nextAfterOrdinal: z.number().int().nonnegative().nullable() }).strict();
10
+ export const oauthMaterialCapabilityResponseSchema = materialCapabilityResponseSchema.extend({ projectRef: stableUriSchema }).strict();
11
+ export const oauthMaterialCapabilityPageSchema = materialCapabilityPageSchema.extend({ projectRef: stableUriSchema }).strict();
12
+ export const oauthMaterialMediaCapabilityPageSchema = materialMediaCapabilityPageSchema.extend({ projectRef: stableUriSchema }).strict();
13
+ /** Authenticated API-key discovery uses service-relative paths and never substitutes OAuth authority. */
14
+ export const apiKeyMaterialContractSchema = z.object({ schemaVersion: z.literal(2), projectKey: projectKeySchema, authentication: z.literal('API_KEY'), resourceTypeMode: z.literal('OPEN_IDENTIFIER'), capabilitiesEndpoint: z.literal('/v3/material-capabilities'), capabilityPageEndpoint: z.literal('/v3/material-page'), fileEndpoint: z.literal('/v2/material-file'), mediaPageEndpoint: z.literal('/v3/material-media-page'), indexStatusEndpoint: z.literal('/v3/material-index-status'), fileMethods: z.tuple([z.literal('GET'), z.literal('HEAD')]), fileRange: z.literal('SINGLE') }).strict();
@@ -0,0 +1,5 @@
1
+ import { z } from 'zod';
2
+ import { projectKeySchema, idSchema, stableUriSchema } from '../contracts/index.js';
3
+ export const materialIndexPositionSchema = z.object({ sourceProjectKey: projectKeySchema, nodeId: idSchema }).strict();
4
+ export const materialIndexStatusSchema = z.object({ schemaVersion: z.literal(2), projectKey: projectKeySchema, queryCoverage: z.literal('DESCRIPTIVE_METADATA_V1'), indexedFields: z.tuple([z.literal('TITLE'), z.literal('SUMMARY')]), bodyIndexed: z.literal(false), semanticIndexed: z.literal(false), items: z.array(materialIndexPositionSchema.extend({ directoryThroughSeq: z.number().int().nonnegative().safe(), searchThroughSeq: z.number().int().nonnegative().safe().nullable(), observedMaxSeq: z.number().int().nonnegative().safe().nullable(), checkpointUpdatedAt: z.string().datetime({ offset: true }).nullable(), state: z.enum(['PARTIAL_BACKFILL', 'SYNCED_AS_OF_CHECKPOINT']) }).strict()).max(100), nextAfter: materialIndexPositionSchema.nullable() }).strict();
5
+ export const oauthMaterialIndexStatusSchema = materialIndexStatusSchema.extend({ projectRef: stableUriSchema }).strict();
@@ -0,0 +1,137 @@
1
+ import { materialCapabilityResponseSchema, materialMediaCapabilityPageSchema } from './material-capabilities.js';
2
+ import { materialIndexStatusSchema } from './material-index-status.js';
3
+ import { materialResourceTypeSchema } from '../contracts/index.js';
4
+ import { z } from 'zod';
5
+ import { projectKeySchema, schemaVersionSchema, stableUriSchema, sha256Schema } from '../contracts/index.js';
6
+ import { consumerCurrentnessResponseSchema, consumerEvidencePageResponseSchema, consumerProjectRefSchema, consumerReadResponseSchema, consumerReferenceLookupResponseSchema, consumerSearchResponseSchema } from './consumer.js';
7
+ import { materialOutboxWindowSchema, materialRoutePartitionSchema, servingMaterialDirectoryItemSchema } from './http.js';
8
+ export const knowledgeMcpProtocolVersion = '2026-07-28';
9
+ export const knowledgeMcpToolNameSchema = z.enum(['knowledge_search', 'knowledge_read', 'knowledge_currentness', 'knowledge_reference_lookup']);
10
+ export const knowledgeMcpToolNameV2Schema = z.enum(['knowledge_search', 'knowledge_read', 'knowledge_currentness', 'knowledge_reference_lookup', 'knowledge_list_evidence']);
11
+ export const knowledgeMcpScopeSchema = z.enum(['knowledge.search', 'knowledge.read', 'knowledge.currentness']);
12
+ export const knowledgeMcpProviderContractSchema = z.object({
13
+ schemaVersion: schemaVersionSchema, provider: z.literal('knowledge-v2'), revision: z.string().trim().min(7).max(64), protocolVersion: z.literal(knowledgeMcpProtocolVersion),
14
+ validationStatus: z.enum(['NOT_VERIFIED', 'RUNTIME_CONFIGURED']), externalReachability: z.literal('NOT_VERIFIED'), endpoint: z.string().url().nullable(), mediaEndpoint: z.string().url().nullable(), resource: z.string().url().nullable(), protectedResourceMetadataUrl: z.string().url().nullable(), authorizationServerMetadataUrl: z.string().url().nullable(), authorizationEndpoint: z.string().url().nullable(), tokenEndpoint: z.string().url().nullable(), revocationEndpoint: z.string().url().nullable(),
15
+ authorizationMode: z.literal('OAUTH_2_1_AUTHORIZATION_CODE_PKCE_S256_USER_DELEGATED'), clientRegistration: z.literal('PRE_REGISTERED'), clientId: z.null(), authorizationMapping: z.object({ oauthResourceParameter: z.literal('resource'), externalTenantParameter: z.literal('external_tenant_id'), projectRefParameter: z.literal('project_ref'), externalSystemSource: z.literal('client_id'), grantBinding: z.literal('RESOURCE_EXTERNAL_TENANT_PROJECT_REF_SCOPES') }).strict(), searchCoverage: z.enum(['AUTHORIZED_METADATA_V1', 'AUTHORIZED_PRESENTATION_V1']),
16
+ scopes: z.array(knowledgeMcpScopeSchema).length(3), tools: z.array(z.object({ name: knowledgeMcpToolNameSchema, requiredScope: knowledgeMcpScopeSchema, inputSchema: z.json() }).strict()).length(4),
17
+ }).strict();
18
+ /** 版本化元数据只声明实际启用的协议;保留严格 v1,避免旧消费者误认新增生命周期。 */
19
+ const providerV2BaseSchema = knowledgeMcpProviderContractSchema.omit({ schemaVersion: true, protocolVersion: true }).extend({
20
+ schemaVersion: z.literal(2), defaultProtocolVersion: z.literal(knowledgeMcpProtocolVersion),
21
+ protocols: z.array(z.object({ version: z.literal('2026-07-28'), lifecycle: z.literal('STATELESS_DISCOVERY'), transport: z.literal('STREAMABLE_HTTP') }).strict()).length(1),
22
+ }).strict();
23
+ export const knowledgeMcpProviderContractV2Schema = providerV2BaseSchema.superRefine((value, ctx) => {
24
+ const versions = value.protocols.map(p => p.version);
25
+ if (new Set(versions).size !== versions.length || !versions.includes(value.defaultProtocolVersion))
26
+ ctx.addIssue({ code: 'custom', message: 'Protocols must be unique and include the default version' });
27
+ });
28
+ /** v3 区分原始 Evidence 文件和受治理正文端点,旧 provider 合同仍保持原样。 */
29
+ export const knowledgeMcpProviderContractV3Schema = providerV2BaseSchema.omit({ schemaVersion: true, tools: true }).extend({
30
+ schemaVersion: z.literal(3), contentEndpoint: z.string().url().nullable(), evidenceFileEndpoint: z.string().url().nullable(),
31
+ tools: z.array(z.object({ name: knowledgeMcpToolNameV2Schema, requiredScope: knowledgeMcpScopeSchema, inputSchema: z.json() }).strict()).length(5),
32
+ }).strict().superRefine((value, ctx) => {
33
+ const versions = value.protocols.map(p => p.version);
34
+ if (new Set(versions).size !== versions.length || !versions.includes(value.defaultProtocolVersion))
35
+ ctx.addIssue({ code: 'custom', message: 'Protocols must be unique and include the default version' });
36
+ });
37
+ // 五个工具的成功结构直接取通用消费 DTO;失败只返回错误码,不泄露被拒绝正文。
38
+ const toolErrorOutput = { type: 'object', properties: { errorCode: { type: 'string' } }, required: ['errorCode'], additionalProperties: false };
39
+ const toolOutput = (success) => ({ type: 'object', oneOf: [z.toJSONSchema(success, { target: 'draft-07' }), toolErrorOutput] });
40
+ export const knowledgeMaterialListInputSchema = z.object({ projectRef: consumerProjectRefSchema, after: stableUriSchema.optional(), limit: z.number().int().min(1).max(20).optional(), resourceType: materialResourceTypeSchema.optional(), sourceProjectKey: projectKeySchema.optional(), refPrefix: z.string().regex(/^[a-z][a-z0-9+.-]*:\/\/[!-~]*$/i).max(256).optional() }).strict();
41
+ export const knowledgeMaterialRefInputSchema = z.object({ projectRef: consumerProjectRefSchema, ref: stableUriSchema }).strict();
42
+ export const knowledgeMaterialWindowInputSchema = z.object({ projectRef: consumerProjectRefSchema }).strict();
43
+ export const knowledgeMaterialWindowResponseSchema = materialOutboxWindowSchema.safeExtend({ projectRef: consumerProjectRefSchema });
44
+ export const knowledgeMaterialChangesInputSchema = z.object({ projectRef: consumerProjectRefSchema, afterSeq: z.number().int().nonnegative().safe().optional(), limit: z.number().int().min(1).max(20).optional() }).strict();
45
+ export const knowledgeMaterialSearchInputSchema = z.object({ projectRef: consumerProjectRefSchema, query: z.string().min(2).max(200), afterId: z.number().int().nonnegative().safe().optional(), limit: z.number().int().min(1).max(20).optional(), resourceType: materialResourceTypeSchema.optional(), sourceProjectKey: projectKeySchema.optional() }).strict();
46
+ export const knowledgeMaterialPartitionsInputSchema = z.object({ projectRef: consumerProjectRefSchema, afterRouteId: z.string().regex(/^[a-f0-9]{64}$/).optional(), limit: z.number().int().min(1).max(20).optional() }).strict();
47
+ export const knowledgeMaterialPartitionPageInputSchema = z.object({ projectRef: consumerProjectRefSchema, partition: z.enum(['OWNER', 'LEGACY']), after: stableUriSchema.optional(), limit: z.number().int().min(1).max(20).optional() }).strict();
48
+ export const knowledgeMaterialRoutePageInputSchema = z.object({ projectRef: consumerProjectRefSchema, routeId: z.string().regex(/^[a-f0-9]{64}$/), after: stableUriSchema.optional(), limit: z.number().int().min(1).max(20).optional() }).strict();
49
+ export const knowledgeMaterialMediaInputSchema = knowledgeMaterialRefInputSchema.extend({ afterOrdinal: z.number().int().min(-1).safe().optional(), limit: z.number().int().min(1).max(20).optional(), documentRef: stableUriSchema.optional() }).strict();
50
+ export const knowledgeMaterialIndexStatusInputSchema = z.object({ projectRef: consumerProjectRefSchema, afterSourceKey: projectKeySchema.optional(), afterNodeId: z.string().min(1).max(128).optional(), sourceProjectKey: projectKeySchema.optional(), limit: z.number().int().min(1).max(20).optional() }).strict();
51
+ export const knowledgeMaterialCapabilitiesResponseSchema = materialCapabilityResponseSchema.omit({ projectKey: true }).extend({ projectRef: consumerProjectRefSchema, downloadUrl: z.string().url() }).strict();
52
+ export const knowledgeMaterialMediaResponseSchema = materialMediaCapabilityPageSchema.omit({ projectKey: true }).extend({ projectRef: consumerProjectRefSchema }).strict();
53
+ export const knowledgeMaterialIndexStatusResponseSchema = materialIndexStatusSchema.omit({ projectKey: true }).extend({ projectRef: consumerProjectRefSchema }).strict();
54
+ export const knowledgeMaterialToolInputSchemas = {
55
+ knowledge_material_capabilities: z.toJSONSchema(knowledgeMaterialRefInputSchema, { target: 'draft-07' }),
56
+ knowledge_material_media: z.toJSONSchema(knowledgeMaterialMediaInputSchema, { target: 'draft-07' }),
57
+ knowledge_material_index_status: z.toJSONSchema(knowledgeMaterialIndexStatusInputSchema, { target: 'draft-07' }),
58
+ knowledge_material_window: z.toJSONSchema(knowledgeMaterialWindowInputSchema, { target: 'draft-07' }),
59
+ knowledge_material_list: z.toJSONSchema(knowledgeMaterialListInputSchema, { target: 'draft-07' }),
60
+ knowledge_material_describe: z.toJSONSchema(knowledgeMaterialRefInputSchema, { target: 'draft-07' }),
61
+ knowledge_material_read: z.toJSONSchema(knowledgeMaterialRefInputSchema, { target: 'draft-07' }),
62
+ knowledge_material_changes: z.toJSONSchema(knowledgeMaterialChangesInputSchema, { target: 'draft-07' }),
63
+ knowledge_material_search: z.toJSONSchema(knowledgeMaterialSearchInputSchema, { target: 'draft-07' }),
64
+ knowledge_material_partitions: z.toJSONSchema(knowledgeMaterialPartitionsInputSchema, { target: 'draft-07' }),
65
+ knowledge_material_partition_page: z.toJSONSchema(knowledgeMaterialPartitionPageInputSchema, { target: 'draft-07' }),
66
+ knowledge_material_route_page: z.toJSONSchema(knowledgeMaterialRoutePageInputSchema, { target: 'draft-07' }),
67
+ };
68
+ export const knowledgeMaterialListResponseSchema = z.object({ schemaVersion: schemaVersionSchema, projectRef: consumerProjectRefSchema, contentClass: z.literal('MATERIAL_DIRECTORY'), queryCoverage: z.literal('INDEXED_REF_SOURCE_TYPE_V1'), order: z.literal('REF_ASC'), items: z.array(servingMaterialDirectoryItemSchema).max(20), nextAfter: stableUriSchema.nullable() }).strict();
69
+ export const knowledgeMaterialDescribeResponseSchema = z.object({ schemaVersion: schemaVersionSchema, projectRef: consumerProjectRefSchema, contentClass: z.literal('MATERIAL_DESCRIPTOR'), item: servingMaterialDirectoryItemSchema, metadataByteLength: z.number().int().nonnegative().nullable(), downloadUrl: z.string().url() }).strict();
70
+ export const knowledgeMaterialReadResponseSchema = knowledgeMaterialDescribeResponseSchema.omit({ contentClass: true }).extend({ contentClass: z.literal('MATERIAL_READ'), inlineComplete: z.boolean(), byteVerification: z.enum(['VERIFIED', 'ON_DOWNLOAD']), contentBase64: z.string().nullable(), fileDescriptor: z.object({ contentHash: sha256Schema, mediaType: z.string().min(1).max(256), byteLength: z.number().int().nonnegative() }).strict().nullable() }).strict();
71
+ export const knowledgeMaterialChangesResponseSchema = z.object({ schemaVersion: schemaVersionSchema, projectRef: consumerProjectRefSchema, tenantId: z.string().min(1), items: z.array(z.object({ seq: z.number().int().positive(), eventType: z.enum(['MATERIAL_REGISTERED', 'MATERIAL_LINEAGE_CHANGED', 'ROUTE_CHANGED', 'PROJECT_SCOPE_CHANGED']), artifactRef: stableUriSchema.nullable(), contentHash: sha256Schema.nullable(), routeId: z.string().nullable(), createdAt: z.string().datetime({ offset: true }) }).strict()).max(20), nextAfter: z.number().int().positive().nullable() }).strict();
72
+ export const knowledgeMaterialSearchResponseSchema = z.object({ schemaVersion: schemaVersionSchema, projectRef: consumerProjectRefSchema, queryCoverage: z.literal('DESCRIPTIVE_METADATA_V1'), order: z.literal('INDEX_ROWID_ASC'), indexState: z.enum(['PARTIAL_BACKFILL', 'SYNCED_AS_OF_LAST_OBSERVATION']), configuredSourceCount: z.number().int().nonnegative(), items: z.array(z.object({ item: servingMaterialDirectoryItemSchema, title: z.string().max(512), summary: z.string().max(1024) }).strict()).max(20), nextAfterId: z.number().int().positive().nullable() }).strict();
73
+ export const oauthMaterialRoutePageResponseSchema = z.object({ schemaVersion: schemaVersionSchema, projectRef: consumerProjectRefSchema, projectKey: projectKeySchema, routeId: z.string().regex(/^[a-f0-9]{64}$/), contentClass: z.literal('MATERIAL_DIRECTORY'), routeState: z.enum(['ACTIVE', 'REVOKED', 'UNBOUND']), items: z.array(servingMaterialDirectoryItemSchema).max(100), nextAfter: stableUriSchema.nullable() }).strict();
74
+ export const oauthMaterialPartitionsResponseSchema = z.object({ schemaVersion: schemaVersionSchema, projectRef: consumerProjectRefSchema, projectKey: projectKeySchema, coverage: z.literal('OWNER_LEGACY_AND_ACTIVE_ROUTES'), items: z.array(materialRoutePartitionSchema).max(100), nextAfterRouteId: z.string().regex(/^[a-f0-9]{64}$/).nullable() }).strict();
75
+ export const oauthMaterialPartitionPageResponseSchema = z.object({ schemaVersion: schemaVersionSchema, projectRef: consumerProjectRefSchema, projectKey: projectKeySchema, contentClass: z.literal('MATERIAL_DIRECTORY'), partition: z.enum(['OWNER', 'LEGACY']), items: z.array(servingMaterialDirectoryItemSchema).max(100), nextAfter: stableUriSchema.nullable() }).strict();
76
+ export const knowledgeMaterialPartitionsResponseSchema = oauthMaterialPartitionsResponseSchema.extend({ items: z.array(materialRoutePartitionSchema).max(20) }).omit({ projectKey: true }).strict();
77
+ export const knowledgeMaterialPartitionPageResponseSchema = oauthMaterialPartitionPageResponseSchema.extend({ items: z.array(servingMaterialDirectoryItemSchema).max(20) }).omit({ projectKey: true }).strict();
78
+ export const knowledgeMaterialRoutePageResponseSchema = oauthMaterialRoutePageResponseSchema.extend({ items: z.array(servingMaterialDirectoryItemSchema).max(20) }).omit({ projectKey: true }).strict();
79
+ export const knowledgeMcpToolOutputSchemas = {
80
+ knowledge_material_capabilities: toolOutput(knowledgeMaterialCapabilitiesResponseSchema),
81
+ knowledge_material_media: toolOutput(knowledgeMaterialMediaResponseSchema),
82
+ knowledge_material_index_status: toolOutput(knowledgeMaterialIndexStatusResponseSchema),
83
+ knowledge_material_window: toolOutput(knowledgeMaterialWindowResponseSchema),
84
+ knowledge_search: toolOutput(consumerSearchResponseSchema),
85
+ knowledge_read: toolOutput(consumerReadResponseSchema),
86
+ knowledge_list_evidence: toolOutput(consumerEvidencePageResponseSchema),
87
+ knowledge_currentness: toolOutput(consumerCurrentnessResponseSchema),
88
+ knowledge_reference_lookup: toolOutput(consumerReferenceLookupResponseSchema),
89
+ knowledge_material_list: toolOutput(knowledgeMaterialListResponseSchema),
90
+ knowledge_material_describe: toolOutput(knowledgeMaterialDescribeResponseSchema),
91
+ knowledge_material_read: toolOutput(knowledgeMaterialReadResponseSchema),
92
+ knowledge_material_changes: toolOutput(knowledgeMaterialChangesResponseSchema),
93
+ knowledge_material_search: toolOutput(knowledgeMaterialSearchResponseSchema),
94
+ knowledge_material_partitions: toolOutput(knowledgeMaterialPartitionsResponseSchema),
95
+ knowledge_material_partition_page: toolOutput(knowledgeMaterialPartitionPageResponseSchema),
96
+ knowledge_material_route_page: toolOutput(knowledgeMaterialRoutePageResponseSchema),
97
+ };
98
+ /** v4 在独立发现版本中公布工具输出合同,v1 至 v3 的严格结构不变。 */
99
+ export const knowledgeMcpProviderContractV4Schema = providerV2BaseSchema.omit({ schemaVersion: true, tools: true }).extend({
100
+ schemaVersion: z.literal(4), contentEndpoint: z.string().url().nullable(), evidenceFileEndpoint: z.string().url().nullable(),
101
+ tools: z.array(z.object({ name: knowledgeMcpToolNameV2Schema, requiredScope: knowledgeMcpScopeSchema, inputSchema: z.json(), outputSchema: z.json() }).strict()).length(5),
102
+ }).strict().superRefine((value, ctx) => {
103
+ const versions = value.protocols.map(p => p.version);
104
+ if (new Set(versions).size !== versions.length || !versions.includes(value.defaultProtocolVersion))
105
+ ctx.addIssue({ code: 'custom', message: 'Protocols must be unique and include the default version' });
106
+ });
107
+ /** v5 单独声明受治理写入工具;旧版本继续只描述只读消费合同。 */
108
+ export const knowledgeMcpProviderContractV5Schema = providerV2BaseSchema.omit({ schemaVersion: true, tools: true, scopes: true }).extend({
109
+ schemaVersion: z.literal(5), contentEndpoint: z.string().url().nullable(), evidenceFileEndpoint: z.string().url().nullable(), managementMode: z.literal('EXPLICIT_CLIENT_PROJECT_SCOPE'), managementEnabled: z.boolean(),
110
+ scopes: z.array(z.enum(['knowledge.search', 'knowledge.read', 'knowledge.currentness', 'knowledge.compose', 'knowledge.review', 'knowledge.approve'])).min(3).max(6),
111
+ tools: z.array(z.object({ name: z.enum(['knowledge_search', 'knowledge_read', 'knowledge_currentness', 'knowledge_reference_lookup', 'knowledge_list_evidence', 'knowledge_compose', 'knowledge_submit_review', 'knowledge_review', 'knowledge_finalize_review']), requiredScope: z.enum(['knowledge.search', 'knowledge.read', 'knowledge.currentness', 'knowledge.compose', 'knowledge.review', 'knowledge.approve']), inputSchema: z.json(), outputSchema: z.json() }).strict()).min(5).max(9),
112
+ }).strict();
113
+ /** v6 advertises tenant-scoped, immutable material discovery and byte reads. */
114
+ export const knowledgeMcpProviderContractV6Schema = knowledgeMcpProviderContractV5Schema.omit({ schemaVersion: true }).extend({ schemaVersion: z.literal(6), materialPageEndpoint: z.string().url(), materialEndpoint: z.string().url(), materialPresentationEndpoint: z.string().url() }).strict();
115
+ /** v7 publishes independent raw-material consent without changing older provider contracts. */
116
+ export const knowledgeMcpProviderContractV7Schema = knowledgeMcpProviderContractV6Schema.omit({ schemaVersion: true, scopes: true, tools: true }).extend({
117
+ schemaVersion: z.literal(7), materialReadMode: z.literal('OAUTH_SCOPE_AND_CLIENT_PROJECT_BINDING'),
118
+ scopes: z.array(z.enum(['knowledge.search', 'knowledge.read', 'knowledge.currentness', 'knowledge.material.read', 'knowledge.compose', 'knowledge.review', 'knowledge.approve', 'knowledge.material.route'])).min(4).max(8),
119
+ tools: z.array(z.object({ name: z.enum(['knowledge_search', 'knowledge_read', 'knowledge_currentness', 'knowledge_reference_lookup', 'knowledge_list_evidence', 'knowledge_material_list', 'knowledge_material_describe', 'knowledge_material_read', 'knowledge_material_changes', 'knowledge_compose', 'knowledge_submit_review', 'knowledge_review', 'knowledge_finalize_review', 'knowledge_material_route']), requiredScope: z.enum(['knowledge.search', 'knowledge.read', 'knowledge.currentness', 'knowledge.material.read', 'knowledge.compose', 'knowledge.review', 'knowledge.approve', 'knowledge.material.route']), inputSchema: z.json(), outputSchema: z.json() }).strict()).min(9).max(14),
120
+ }).strict();
121
+ /** v8 adds descriptive metadata search with an explicit index-coverage state. */
122
+ export const knowledgeMcpProviderContractV8Schema = knowledgeMcpProviderContractV7Schema.omit({ schemaVersion: true, tools: true }).extend({
123
+ schemaVersion: z.literal(8), materialSearchMode: z.literal('INDEXED_DESCRIPTIVE_METADATA'), materialSearchEndpoint: z.string().url(),
124
+ tools: z.array(z.object({ name: z.enum(['knowledge_search', 'knowledge_read', 'knowledge_currentness', 'knowledge_reference_lookup', 'knowledge_list_evidence', 'knowledge_material_list', 'knowledge_material_describe', 'knowledge_material_read', 'knowledge_material_changes', 'knowledge_material_search', 'knowledge_compose', 'knowledge_submit_review', 'knowledge_review', 'knowledge_finalize_review', 'knowledge_material_route']), requiredScope: z.enum(['knowledge.search', 'knowledge.read', 'knowledge.currentness', 'knowledge.material.read', 'knowledge.compose', 'knowledge.review', 'knowledge.approve', 'knowledge.material.route']), inputSchema: z.json(), outputSchema: z.json() }).strict()).min(10).max(15),
125
+ }).strict();
126
+ /** v9 advertises bounded per-route replay for null-ref change events. */
127
+ export const knowledgeMcpProviderContractV9Schema = knowledgeMcpProviderContractV8Schema.omit({ schemaVersion: true }).extend({ schemaVersion: z.literal(9), materialRoutePageEndpoint: z.string().url() }).strict();
128
+ /** v10 publishes route-count-independent partitioned material discovery. */
129
+ export const knowledgeMcpProviderContractV10Schema = knowledgeMcpProviderContractV9Schema.omit({ schemaVersion: true, tools: true }).extend({ schemaVersion: z.literal(10), materialPartitionsEndpoint: z.string().url(), materialPartitionPageEndpoint: z.string().url(), tools: z.array(z.object({ name: z.enum(['knowledge_search', 'knowledge_read', 'knowledge_currentness', 'knowledge_reference_lookup', 'knowledge_list_evidence', 'knowledge_material_list', 'knowledge_material_describe', 'knowledge_material_read', 'knowledge_material_changes', 'knowledge_material_search', 'knowledge_material_partitions', 'knowledge_material_partition_page', 'knowledge_material_route_page', 'knowledge_compose', 'knowledge_submit_review', 'knowledge_review', 'knowledge_finalize_review', 'knowledge_material_route']), requiredScope: z.enum(['knowledge.search', 'knowledge.read', 'knowledge.currentness', 'knowledge.material.read', 'knowledge.compose', 'knowledge.review', 'knowledge.approve', 'knowledge.material.route']), inputSchema: z.json(), outputSchema: z.json() }).strict()).min(13).max(18) }).strict();
130
+ /** v11 adds an Agent-native checkpoint for initial synchronization and retention-gap recovery. */
131
+ export const knowledgeMcpProviderContractV11Schema = knowledgeMcpProviderContractV10Schema.omit({ schemaVersion: true, tools: true }).extend({ schemaVersion: z.literal(11), materialOutboxWindowEndpoint: z.string().url(), tools: z.array(knowledgeMcpProviderContractV10Schema.shape.tools.element.extend({ name: knowledgeMcpProviderContractV10Schema.shape.tools.element.shape.name.or(z.literal('knowledge_material_window')) })).min(14).max(19) }).strict();
132
+ /** v12 exposes representation capabilities independently of raw authorization and search coverage. */
133
+ export const knowledgeMcpProviderContractV12Schema = knowledgeMcpProviderContractV11Schema.omit({ schemaVersion: true, tools: true }).extend({ schemaVersion: z.literal(12), materialCapabilitySchemaVersion: z.literal(2), materialCapabilitiesEndpoint: z.string().url(), materialCapabilityPageEndpoint: z.string().url(), materialMediaPageEndpoint: z.string().url(), materialIndexStatusEndpoint: z.string().url(), tools: z.array(knowledgeMcpProviderContractV11Schema.shape.tools.element.extend({ name: knowledgeMcpProviderContractV11Schema.shape.tools.element.shape.name.or(z.enum(['knowledge_material_capabilities', 'knowledge_material_media', 'knowledge_material_index_status'])) })).min(17).max(22) }).strict();
134
+ /** v13 adds explicit material production; older versions keep their scope and tool enums. */
135
+ export const knowledgeMcpProviderContractV13Schema = knowledgeMcpProviderContractV12Schema.omit({ schemaVersion: true, tools: true, scopes: true }).extend({ schemaVersion: z.literal(13), scopes: z.array(knowledgeMcpProviderContractV12Schema.shape.scopes.element.or(z.literal('knowledge.material.write'))).min(4).max(9), tools: z.array(knowledgeMcpProviderContractV12Schema.shape.tools.element.extend({ name: knowledgeMcpProviderContractV12Schema.shape.tools.element.shape.name.or(z.literal('knowledge_material_register')), requiredScope: knowledgeMcpProviderContractV12Schema.shape.tools.element.shape.requiredScope.or(z.literal('knowledge.material.write')) })).min(17).max(23), materialRegistration: z.object({ maxInlineBytes: z.literal(65536), retry: z.literal('EXACT_IMMUTABLE_REF'), phases: z.tuple([z.literal('PERSISTED'), z.literal('CATALOG_PROJECTED'), z.literal('REGISTERED')]) }).strict() }).strict();
136
+ /** v15 才扩展 Agent 治理工具和 scope;v1–v14 的严格枚举保持原样。 */
137
+ export const knowledgeMcpProviderContractV15Schema = knowledgeMcpProviderContractV13Schema.omit({ schemaVersion: true, tools: true, scopes: true }).extend({ schemaVersion: z.literal(15), workflowSchemaVersion: z.literal(1), managementEndpoint: z.string().url(), scopes: z.array(knowledgeMcpProviderContractV13Schema.shape.scopes.element.or(z.literal('knowledge.workflow.read'))).min(4).max(10), tools: z.array(knowledgeMcpProviderContractV13Schema.shape.tools.element.extend({ name: knowledgeMcpProviderContractV13Schema.shape.tools.element.shape.name.or(z.enum(['knowledge_workflow_guide', 'knowledge_workflow_plan', 'knowledge_workflow_advance', 'knowledge_agent_submit'])), requiredScope: knowledgeMcpProviderContractV13Schema.shape.tools.element.shape.requiredScope.or(z.literal('knowledge.workflow.read')) })).min(17).max(27) }).strict();
@@ -0,0 +1,13 @@
1
+ /** 显式 native consumer;旧 profile/Provider/Workflow schema 1 不自动升级。 */
2
+ import { z } from 'zod';
3
+ import { tenantResourceRefSchema, tenantManagementRequestIdSchema, materialTenantIdSchema, artifactStatusSchema, sha256Schema, tenantMaterialCurrentnessSchema, tenantPublicationReadinessSchema } from '../contracts/index.js';
4
+ import { consumerProfileSchema, servingDecisionSchema } from './core.js';
5
+ export const tenantConsumerProfileSchema = z.object({ ...consumerProfileSchema.shape, schemaVersion: z.literal(2), acceptedCurrentnessBases: z.array(z.literal('RETAINED_SNAPSHOT')).max(1), legacySourcePolicy: z.literal('PROJECT_POLICY_V1').optional() }).strict().superRefine((v, ctx) => { const { acceptedCurrentnessBases, legacySourcePolicy, schemaVersion, ...base } = v, checked = consumerProfileSchema.safeParse({ ...base, schemaVersion: 1 }); if (!checked.success)
6
+ for (const issue of checked.error.issues)
7
+ ctx.addIssue({ code: 'custom', path: issue.path, message: issue.message }); if (new Set(v.acceptedCurrentnessBases).size !== v.acceptedCurrentnessBases.length)
8
+ ctx.addIssue({ code: 'custom', message: 'currentness bases must be unique' }); });
9
+ const readDecision = z.object({ action: z.enum(['ALLOW', 'REVIEW_REQUIRED', 'DENY']), reasonCodes: z.array(z.string()).max(32), authority: z.enum(['AUTHENTICATED_READER', 'LOCAL_PROFILE_SIMULATION']) }).strict();
10
+ export const tenantWorkflowPlanInputSchema = z.object({ ref: tenantResourceRefSchema }).strict();
11
+ export const tenantWorkflowAdvanceInputSchema = z.object({ requestId: tenantManagementRequestIdSchema, ref: tenantResourceRefSchema, expectedVersion: z.number().int().positive().safe(), action: z.enum(['SUBMIT_REVIEW', 'FINALIZE_REVIEW']), reviewRef: tenantResourceRefSchema.optional() }).strict();
12
+ export const tenantWorkflowPlanSchema = z.object({ schemaVersion: z.literal(2), tenantId: materialTenantIdSchema, ref: tenantResourceRefSchema, contentHash: sha256Schema, resourceType: z.string(), kind: z.string(), version: z.number().int().positive(), status: artifactStatusSchema.or(z.enum(['RAW_MATERIAL', 'RAW_EVIDENCE', 'REFERENCE_SNAPSHOT', 'REGISTERED_MATERIAL'])), productionPhase: z.literal('REGISTERED'), readiness: tenantPublicationReadinessSchema.nullable(), currentness: tenantMaterialCurrentnessSchema.nullable(), governedPolicyReady: z.boolean(), consumerReadDecision: readDecision.nullable(), externalReady: z.boolean(), successorRef: tenantResourceRefSchema.nullable(), blockers: z.array(z.string()).max(64), nextActions: z.array(z.object({ id: z.string(), tool: z.string().nullable(), arguments: z.record(z.string(), z.json()), requiredScopes: z.array(z.string()), missingScopes: z.array(z.string()), missingFields: z.array(z.string()), canExecute: z.boolean(), automatic: z.boolean(), reasonCode: z.string() }).strict()).max(16) }).strict();
13
+ export const tenantGovernedReadResultSchema = z.object({ schemaVersion: z.literal(2), tenantId: materialTenantIdSchema, ref: tenantResourceRefSchema, decision: servingDecisionSchema, descriptor: z.object({ contentHash: sha256Schema, mediaType: z.string(), byteLength: z.number().int().nonnegative() }).strict().nullable() }).strict();
@@ -0,0 +1,89 @@
1
+ /** 新 Tenant 管理工具共同合同;认证 context/actor/authority 只由 adapter 注入。 */
2
+ import { z } from 'zod';
3
+ import { parseTenantResourceRef, tenantStorageKey, tenantRawSubmissionSchema, tenantArtifactDraftSchema, tenantComposeInputSchema, tenantReviewInputSchema, tenantPromoteInputSchema, tenantSnapshotInputSchema, tenantShareInputSchema, tenantRevokeShareInputSchema, tenantResourceManifestSchema, tenantMaterialCurrentnessSchema, tenantSourceSemanticsSchema, tenantSourceIdSchema, tenantSourceSnapshotSchema, collectionRefreshSchema, tenantCollectionCycleSchema, tenantCollectionRequestSchema, tenantCollectionBatchSchema, tenantCollectionCompletionSchema, tenantCollectionFailureSchema, tenantResourceRefSchema, materialTenantIdSchema, sha256Schema, isoDateTimeSchema, stableUriSchema } from '../contracts/index.js';
4
+ import { tenantWorkflowPlanSchema, tenantWorkflowPlanInputSchema, tenantWorkflowAdvanceInputSchema, tenantGovernedReadResultSchema } from './tenant-governance.js';
5
+ const base64 = z.string().min(4).max(87384).regex(/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/), ref = z.object({ ref: tenantResourceRefSchema }).strict(), page = z.object({ after: z.string().min(1).max(128).optional(), limit: z.number().int().min(1).max(100).optional() }).strict(), source = z.object({ sourceId: tenantSourceIdSchema }).strict();
6
+ export const tenantManagementToolSchemas = {
7
+ tenant_material_submit: tenantRawSubmissionSchema.extend({ contentBase64: base64 }).strict(),
8
+ tenant_artifact_draft: tenantArtifactDraftSchema.extend({ contentBase64: base64 }).strict(),
9
+ tenant_knowledge_compose: tenantComposeInputSchema,
10
+ tenant_knowledge_review: tenantReviewInputSchema,
11
+ tenant_artifact_promote: tenantPromoteInputSchema,
12
+ tenant_snapshot_declare: tenantSnapshotInputSchema,
13
+ tenant_snapshot_status: ref,
14
+ tenant_material_share: tenantShareInputSchema,
15
+ tenant_material_revoke: tenantRevokeShareInputSchema,
16
+ tenant_material_routes: page,
17
+ tenant_workflow_guide: z.object({}).strict(),
18
+ tenant_workflow_plan: tenantWorkflowPlanInputSchema,
19
+ tenant_workflow_advance: tenantWorkflowAdvanceInputSchema,
20
+ tenant_knowledge_read: ref,
21
+ tenant_source_define: z.object({ definition: z.object({ schemaVersion: z.literal(1), sourceId: tenantSourceIdSchema, title: z.string().trim().min(1).max(512), semantics: tenantSourceSemanticsSchema }).strict(), expectedGeneration: z.number().int().positive().safe().nullable() }).strict(),
22
+ tenant_source_configure: source.extend({ expectedGeneration: z.number().int().positive().safe(), paused: z.boolean(), tenantEnabled: z.boolean(), refresh: collectionRefreshSchema }).strict(),
23
+ tenant_source_get: source,
24
+ tenant_source_list: page,
25
+ tenant_collection_request: z.object({ requestId: tenantCollectionCycleSchema, sourceId: tenantSourceIdSchema, expectedSourceRevisionRef: stableUriSchema.optional(), cycleId: tenantCollectionCycleSchema.optional() }).strict(),
26
+ tenant_collection_status: z.object({ requestId: tenantCollectionCycleSchema }).strict(),
27
+ };
28
+ /** 固定能力索引;promote/advance 的调用鉴权必须使用 scopesForInput,发现使用 Authorization。 */
29
+ export const tenantManagementToolScopes = { tenant_material_submit: 'knowledge.material.write', tenant_artifact_draft: 'knowledge.material.write', tenant_knowledge_compose: 'knowledge.compose', tenant_knowledge_review: 'knowledge.review', tenant_artifact_promote: 'knowledge.material.write', tenant_snapshot_declare: 'knowledge.review', tenant_snapshot_status: 'knowledge.workflow.read', tenant_material_share: 'knowledge.material.route', tenant_material_revoke: 'knowledge.material.route', tenant_material_routes: 'knowledge.material.route', tenant_workflow_guide: 'knowledge.workflow.read', tenant_workflow_plan: 'knowledge.workflow.read', tenant_workflow_advance: 'knowledge.workflow.read', tenant_knowledge_read: 'knowledge.read', tenant_source_define: 'knowledge.source.manage', tenant_source_configure: 'knowledge.source.manage', tenant_source_get: 'knowledge.source.manage', tenant_source_list: 'knowledge.source.manage', tenant_collection_request: 'knowledge.collect', tenant_collection_status: 'knowledge.collect' };
30
+ /** 初始动作能力来自同一输入合同;依赖原件读取等附加检查仍在 application。 */
31
+ export function tenantManagementScopesForInput(name, raw) {
32
+ const input = tenantManagementToolSchemas[name].parse(raw);
33
+ if (name === 'tenant_artifact_promote')
34
+ return [tenantPromoteInputSchema.parse(input).nextStatus === 'READY_FOR_REVIEW' ? 'knowledge.material.write' : 'knowledge.approve'];
35
+ if (name === 'tenant_workflow_advance')
36
+ return ['knowledge.workflow.read', tenantWorkflowAdvanceInputSchema.parse(input).action === 'SUBMIT_REVIEW' ? 'knowledge.material.write' : 'knowledge.approve'];
37
+ return [tenantManagementToolScopes[name]];
38
+ }
39
+ export function tenantManagementAuthorization(name) {
40
+ if (name === 'tenant_artifact_promote')
41
+ return { selection: 'NEXT_STATUS', scopeAlternatives: [['knowledge.material.write'], ['knowledge.approve']] };
42
+ if (name === 'tenant_workflow_advance')
43
+ return { selection: 'WORKFLOW_ACTION', scopeAlternatives: [['knowledge.workflow.read', 'knowledge.material.write'], ['knowledge.workflow.read', 'knowledge.approve']] };
44
+ return { selection: 'FIXED', scopeAlternatives: [[tenantManagementToolScopes[name]]] };
45
+ }
46
+ // advance/promote 的实际动作、来源/审核读取能力继续由 application/context 逐项复核。
47
+ const production = z.object({ phase: z.literal('REGISTERED'), ref: tenantResourceRefSchema, registered: z.boolean(), seq: z.number().int().positive(), manifestRevision: sha256Schema }).strict();
48
+ const write = z.object({ inserted: z.boolean(), manifest: tenantResourceManifestSchema, production }).strict();
49
+ const projection = z.object({ changed: z.boolean(), seq: z.number().int().positive(), assessmentRevision: sha256Schema }).strict();
50
+ const route = z.object({ routeId: z.string().regex(/^[a-f0-9]{64}$/), ownerTenantId: materialTenantIdSchema, recipientTenantId: materialTenantIdSchema, sourceProjectKey: z.null(), matchType: z.enum(['SOURCE', 'REF']), matchValue: stableUriSchema, effect: z.enum(['ALLOW', 'DENY']), revokedAt: isoDateTimeSchema.nullable() }).strict();
51
+ const routeChange = z.object({ changed: z.boolean(), route, completedPhase: z.literal('ROUTE_COMMITTED'), operationRef: stableUriSchema }).strict();
52
+ const sourceHead = z.object({ tenantId: materialTenantIdSchema, sourceId: tenantSourceIdSchema, revisionRef: stableUriSchema, semanticKey: sha256Schema, generation: z.number().int().positive().safe(), paused: z.boolean(), tenantEnabled: z.boolean(), refresh: collectionRefreshSchema, snapshot: tenantSourceSnapshotSchema }).strict().superRefine((v, ctx) => { if (v.tenantId !== v.snapshot.tenantId || v.sourceId !== v.snapshot.sourceId || v.revisionRef !== v.snapshot.revisionRef || v.semanticKey !== v.snapshot.semanticKey)
53
+ ctx.addIssue({ code: 'custom', message: 'Source head preserves its exact snapshot identity' }); });
54
+ const governedRead = tenantGovernedReadResultSchema.extend({ contentBase64: base64.max(43692).nullable(), truncated: z.boolean(), continuation: z.object({ kind: z.literal('AUTHENTICATED_TENANT_GOVERNED_CONTENT'), ref: tenantResourceRefSchema }).strict().nullable() }).strict().superRefine((v, ctx) => {
55
+ const length = v.contentBase64 === null ? 0 : v.contentBase64.length / 4 * 3 - (v.contentBase64.endsWith('==') ? 2 : v.contentBase64.endsWith('=') ? 1 : 0);
56
+ if (v.decision.action === 'ALLOW' ? (!v.descriptor || v.contentBase64 === null || length > 32768 || (v.truncated ? (!v.continuation || v.continuation.ref !== v.ref || v.descriptor.byteLength <= length) : (v.continuation !== null || v.descriptor.byteLength !== length))) : (v.descriptor !== null || v.contentBase64 !== null || v.truncated || v.continuation !== null))
57
+ ctx.addIssue({ code: 'custom', message: 'Governed inline data and continuation must match the actual content decision and full length' });
58
+ });
59
+ const guide = z.object({ schemaVersion: z.literal(2), tenantId: materialTenantIdSchema, authorityVersion: z.literal(2), scopes: z.array(z.string()).max(32), tools: z.array(z.object({ name: z.string(), authorization: z.object({ selection: z.enum(['FIXED', 'NEXT_STATUS', 'WORKFLOW_ACTION']), scopeAlternatives: z.array(z.array(z.string()).min(1).max(8)).min(1).max(4) }).strict(), inputSchema: z.json(), outputSchema: z.json() }).strict()).max(64), rules: z.array(z.string()).max(32), limits: z.object({ requestMaxBytes: z.literal(131072), resultMaxBytes: z.literal(524288), submissionMaxBytes: z.literal(65536) }).strict() }).strict();
60
+ export const tenantManagementDataSchemas = {
61
+ tenant_material_submit: write, tenant_artifact_draft: write, tenant_knowledge_compose: write, tenant_knowledge_review: write, tenant_artifact_promote: write,
62
+ tenant_snapshot_declare: z.object({ subjectRef: tenantResourceRefSchema, declared: z.boolean(), declarationRef: stableUriSchema, assessment: tenantMaterialCurrentnessSchema, projection, completedPhase: z.literal('CURRENTNESS_NOTIFIED'), operationRef: stableUriSchema }).strict(),
63
+ tenant_snapshot_status: z.object({ subjectRef: tenantResourceRefSchema, state: z.enum(['NOT_AVAILABLE', 'NOT_DECLARED', 'PROJECTION_PENDING', 'READY', 'INTEGRITY_MISMATCH', 'UNAVAILABLE']), assessment: tenantMaterialCurrentnessSchema.nullable() }).strict(),
64
+ tenant_material_share: routeChange, tenant_material_revoke: routeChange, tenant_material_routes: z.object({ items: z.array(route).max(100), nextAfter: z.string().nullable() }).strict(),
65
+ tenant_workflow_guide: guide, tenant_workflow_plan: tenantWorkflowPlanSchema,
66
+ tenant_workflow_advance: z.object({ schemaVersion: z.literal(2), action: z.enum(['SUBMIT_REVIEW', 'FINALIZE_REVIEW']), previousRef: tenantResourceRefSchema, inserted: z.boolean(), production, plan: tenantWorkflowPlanSchema }).strict(),
67
+ tenant_knowledge_read: governedRead,
68
+ tenant_source_define: z.object({ changed: z.boolean(), reused: z.boolean(), phase: z.literal('SOURCE_REGISTERED'), head: sourceHead }).strict(),
69
+ tenant_source_configure: z.object({ changed: z.boolean(), head: sourceHead }).strict(), tenant_source_get: sourceHead.nullable(), tenant_source_list: z.object({ items: z.array(sourceHead).max(100), nextAfter: tenantSourceIdSchema.nullable() }).strict(),
70
+ tenant_collection_request: z.object({ inserted: z.boolean(), request: tenantCollectionRequestSchema, batch: tenantCollectionBatchSchema, phase: z.literal('BATCH_PERSISTED') }).strict(),
71
+ tenant_collection_status: z.object({ request: tenantCollectionRequestSchema, completion: tenantCollectionCompletionSchema.nullable(), failure: tenantCollectionFailureSchema.nullable().optional() }).strict().nullable(),
72
+ };
73
+ export const tenantManagementErrorCodeSchema = z.enum(['TENANT_MANAGEMENT_INVALID_INPUT', 'TENANT_MANAGEMENT_FORBIDDEN', 'TENANT_MANAGEMENT_AUTHORITY_CHANGED', 'TENANT_MANAGEMENT_RUNTIME_OWNER_REQUIRED', 'TENANT_MANAGEMENT_IDEMPOTENCY_CONFLICT', 'TENANT_MANAGEMENT_VERSION_CONFLICT', 'TENANT_MANAGEMENT_SOURCE_FORBIDDEN', 'TENANT_MANAGEMENT_REVIEW_REQUIRED', 'TENANT_MANAGEMENT_POLICY_BLOCKED', 'TENANT_MANAGEMENT_UNAVAILABLE', 'TENANT_MANAGEMENT_INCOMPLETE', 'TENANT_MANAGEMENT_INPUT_BUDGET', 'TENANT_MANAGEMENT_NOT_FOUND']);
74
+ export const tenantManagementErrorSchema = z.object({ errorCode: tenantManagementErrorCodeSchema, completedPhase: z.enum(['VALIDATED', 'PERSISTED', 'CATALOG_PROJECTED', 'REGISTERED', 'ROUTE_COMMITTED', 'DECLARATION_PERSISTED', 'CURRENTNESS_RECORDED', 'CURRENTNESS_NOTIFIED', 'SOURCE_PERSISTED', 'SOURCE_REGISTERED', 'REQUEST_PERSISTED', 'BATCH_PERSISTED']).optional(), ref: stableUriSchema.optional() }).strict();
75
+ export function tenantManagementEnvelopeSchema(tool) { return z.object({ schemaVersion: z.literal(2), tenantId: materialTenantIdSchema, tool: z.literal(tool), data: tenantManagementDataSchemas[tool] }).strict(); }
76
+ export const tenantManagementInputJsonSchemas = Object.fromEntries(Object.entries(tenantManagementToolSchemas).map(([name, schema]) => [name, z.toJSONSchema(schema, { target: 'draft-07' })]));
77
+ export const tenantManagementOutputJsonSchemas = Object.fromEntries(Object.keys(tenantManagementToolSchemas).map(name => [name, { type: 'object', oneOf: [z.toJSONSchema(tenantManagementEnvelopeSchema(name), { target: 'draft-07' }), z.toJSONSchema(tenantManagementErrorSchema, { target: 'draft-07' })] }]));
78
+ export const tenantManagementProviderBaseSchema = z.object({ schemaVersion: z.literal(17), provider: z.literal('knowledge-v2'), codeRevision: z.string().min(1).max(128), authorityVersion: z.literal(2), context: z.literal('TENANT_EXPLICIT_MANAGEMENT_V1'), managementConfigured: z.boolean(), resource: stableUriSchema, issuer: stableUriSchema, authorizationEndpoint: stableUriSchema, tokenEndpoint: stableUriSchema, revocationEndpoint: stableUriSchema, mcpEndpoint: stableUriSchema, callEndpoint: stableUriSchema, contentEndpoint: stableUriSchema, contentContextHeader: z.literal('x-knowledge-tenant-id'), legacyProviderEndpoint: stableUriSchema, protocols: z.array(z.literal('2026-07-28')).length(1), tools: z.array(z.string()).length(Object.keys(tenantManagementToolSchemas).length), requestMaxBytes: z.literal(131072), resultMaxBytes: z.literal(524288), submissionMaxBytes: z.literal(65536), inlineContentMaxBytes: z.literal(32768), contentReadMaxBytes: z.literal(16777216), collectionMode: z.literal('MANUAL_ONLY_OAUTH'), capabilities: z.tuple([z.literal('TENANT_MANAGEMENT_V1'), z.literal('TENANT_WORKFLOW_V1'), z.literal('TENANT_CURRENTNESS_V2'), z.literal('TENANT_SOURCE_V1')]) }).strict();
79
+ export const tenantManagementProviderSchema = tenantManagementProviderBaseSchema.superRefine((v, ctx) => { if (new Set(v.tools).size !== Object.keys(tenantManagementToolSchemas).length || v.tools.some(name => !Object.hasOwn(tenantManagementToolSchemas, name)))
80
+ ctx.addIssue({ code: 'custom', message: 'Provider tools must match the exact native tool contract' }); });
81
+ /** 诊断 ref 只允许当前访问 Tenant 的 canonical 原生身份;不接受 URL/本机路径。 */
82
+ export function tenantManagementSafeErrorRef(ref, tenantId) {
83
+ if (typeof ref !== 'string' || ref.length > 2048)
84
+ return undefined;
85
+ const key = tenantStorageKey(tenantId), resource = parseTenantResourceRef(ref);
86
+ if (resource?.storageKey === key)
87
+ return ref;
88
+ return new RegExp(`^(?:tenant-operation://${key}/[a-f0-9]{64}|tenant-collection-request://${key}/[a-f0-9]{64}|tenant-currentness://${key}/snapshot/[a-f0-9]{64}|tenant-source://${key}/[A-Za-z0-9][A-Za-z0-9._-]{0,127}(?:/v/[a-f0-9]{64})?)$`).test(ref) ? ref : undefined;
89
+ }
@@ -0,0 +1,39 @@
1
+ /** Provider19 extends Project context without changing the exact v17/v18 registries. */
2
+ import { z } from 'zod';
3
+ import { projectKeySchema, sha256Schema, stableUriSchema, isoDateTimeSchema, materialTenantIdSchema, resourceDirectoryItemSchema, tenantProjectScopeChangeSchema, tenantProjectLifecycleChangeSchema, tenantProjectControlResultSchema, tenantManagementRequestIdSchema } from '../contracts/index.js';
4
+ import { tenantWorkspaceToolSchemas, tenantWorkspaceDataSchemas, tenantWorkspaceScopesForInput, tenantWorkspaceAuthorization } from './tenant-workspace.js';
5
+ import { tenantManagementErrorSchema, tenantManagementProviderBaseSchema } from './tenant-management.js';
6
+ const cursor = z.string().min(1).max(4096), page = { after: cursor.optional(), limit: z.number().int().min(1).max(100).optional() };
7
+ export const tenantProjectToolSchemas = {
8
+ tenant_project_list: z.object(page).strict(),
9
+ tenant_project_get: z.object({ projectKey: projectKeySchema, purposeAfter: cursor.optional(), selectionAfter: cursor.optional(), requestId: tenantManagementRequestIdSchema.optional() }).strict(),
10
+ tenant_project_materials: z.object({ projectKey: projectKeySchema, ...page }).strict(),
11
+ tenant_project_scope_set: tenantProjectScopeChangeSchema,
12
+ tenant_project_lifecycle_set: tenantProjectLifecycleChangeSchema,
13
+ };
14
+ const result = tenantProjectControlResultSchema, receipt = z.object({ operationRef: stableUriSchema, action: z.enum(['SET_SCOPE', 'SET_LIFECYCLE']), result, committedAt: isoDateTimeSchema }).strict();
15
+ const purpose = z.object({ state: z.enum(['READY', 'NOT_REGISTERED', 'UNAVAILABLE', 'INTEGRITY_MISMATCH']), revisionRef: stableUriSchema.nullable(), identity: z.object({ name: z.string().max(256), summary: z.string().max(4000), domains: z.array(z.string().max(256)).max(32), domainTotal: z.number().int().min(0).max(256), notes: z.string().max(1000).nullable(), notesTruncated: z.boolean() }).strict().nullable(), scopes: z.array(z.object({ scopeId: z.string().max(128), title: z.string().max(256), description: z.string().max(512), descriptionTruncated: z.boolean(), sourceRequirementCount: z.number().int().min(0).max(256), sourceFamilyCount: z.number().int().min(0).max(256) }).strict()).max(20), scopeTotal: z.number().int().min(0).max(1000).nullable(), nextAfter: cursor.nullable() }).strict();
16
+ const selection = z.object({ state: z.enum(['READY', 'NOT_AUTHORIZED', 'UNAVAILABLE', 'BUDGET_EXCEEDED']), mode: z.enum(['TENANT', 'EXPLICIT']).nullable(), revision: sha256Schema.nullable(), selectors: z.array(z.object({ type: z.enum(['REF', 'SOURCE_PROJECT']), value: z.string().min(1).max(4096) }).strict()).max(20), nextAfter: cursor.nullable() }).strict();
17
+ export const tenantProjectDataSchemas = {
18
+ tenant_project_list: z.object({ items: z.array(z.object({ projectKey: projectKeySchema, state: z.enum(['ACTIVE', 'ARCHIVED']) }).strict()).max(100), nextAfter: cursor.nullable(), coverage: z.literal('OWN_TENANT_PROJECTS') }).strict(),
19
+ tenant_project_get: z.object({ projectKey: projectKeySchema, state: z.enum(['ACTIVE', 'ARCHIVED']), lifecycleRevision: sha256Schema, controlReady: z.boolean(), purpose, selection, receipt: receipt.nullable() }).strict(),
20
+ tenant_project_materials: z.object({ projectKey: projectKeySchema, policy: z.literal('TENANT_PROJECT_SCOPE'), items: z.array(resourceDirectoryItemSchema).max(100), nextAfter: cursor.nullable() }).strict(),
21
+ tenant_project_scope_set: z.object({ projectKey: projectKeySchema, replayed: z.boolean(), receipt, current: result, completedPhase: z.literal('PROJECT_CONTROL_COMMITTED'), operationRef: stableUriSchema }).strict(),
22
+ tenant_project_lifecycle_set: z.object({ projectKey: projectKeySchema, replayed: z.boolean(), receipt, current: result, completedPhase: z.literal('PROJECT_CONTROL_COMMITTED'), operationRef: stableUriSchema }).strict(),
23
+ };
24
+ export const tenantProjectErrorSchema = tenantManagementErrorSchema.extend({ completedPhase: z.enum([...tenantManagementErrorSchema.shape.completedPhase.unwrap().options, 'PROJECT_CONTROL_COMMITTED']).optional() }).strict();
25
+ export const tenantProjectWorkspaceToolSchemas = { ...tenantWorkspaceToolSchemas, ...tenantProjectToolSchemas };
26
+ export const tenantProjectWorkspaceDataSchemas = { ...tenantWorkspaceDataSchemas, ...tenantProjectDataSchemas };
27
+ export function tenantProjectScopesForInput(name, raw) { if (Object.hasOwn(tenantProjectToolSchemas, name)) {
28
+ tenantProjectToolSchemas[name].parse(raw);
29
+ return name === 'tenant_project_scope_set' ? ['knowledge.workflow.read', 'knowledge.material.scope'] : name === 'tenant_project_lifecycle_set' ? ['knowledge.workflow.read', 'knowledge.project.manage'] : name === 'tenant_project_materials' ? ['knowledge.material.read'] : ['knowledge.workflow.read'];
30
+ } return tenantWorkspaceScopesForInput(name, raw); }
31
+ export function tenantProjectAuthorization(name) { if (Object.hasOwn(tenantProjectToolSchemas, name)) {
32
+ const scopes = name === 'tenant_project_scope_set' ? ['knowledge.workflow.read', 'knowledge.material.scope'] : name === 'tenant_project_lifecycle_set' ? ['knowledge.workflow.read', 'knowledge.project.manage'] : name === 'tenant_project_materials' ? ['knowledge.material.read'] : ['knowledge.workflow.read'];
33
+ return { selection: 'FIXED', scopeAlternatives: [scopes] };
34
+ } return tenantWorkspaceAuthorization(name); }
35
+ export function tenantProjectEnvelopeSchema(tool) { return z.object({ schemaVersion: z.literal(2), tenantId: materialTenantIdSchema, tool: z.literal(tool), data: tenantProjectWorkspaceDataSchemas[tool] }).strict(); }
36
+ export const tenantProjectInputJsonSchemas = Object.fromEntries(Object.entries(tenantProjectWorkspaceToolSchemas).map(([name, schema]) => [name, z.toJSONSchema(schema, { target: 'draft-07' })]));
37
+ export const tenantProjectOutputJsonSchemas = Object.fromEntries(Object.keys(tenantProjectWorkspaceToolSchemas).map(name => [name, { type: 'object', oneOf: [z.toJSONSchema(tenantProjectEnvelopeSchema(name), { target: 'draft-07' }), z.toJSONSchema(tenantProjectErrorSchema, { target: 'draft-07' })] }]));
38
+ export const tenantProjectProviderSchema = tenantManagementProviderBaseSchema.extend({ schemaVersion: z.literal(19), projectContentEndpoint: stableUriSchema, projectContentPolicyHeader: z.literal('x-knowledge-authority-policy'), projectContentProjectHeader: z.literal('x-knowledge-project-key'), projectControlIdentitySchemaVersion: z.literal(19), tools: z.array(z.string()).length(Object.keys(tenantProjectWorkspaceToolSchemas).length), capabilities: z.tuple([z.literal('TENANT_MANAGEMENT_V1'), z.literal('TENANT_WORKFLOW_V1'), z.literal('TENANT_CURRENTNESS_V2'), z.literal('TENANT_SOURCE_V1'), z.literal('TENANT_WORKSPACE_METADATA_V1'), z.literal('TENANT_PROJECT_CONTEXT_V1')]) }).strict().superRefine((value, ctx) => { if (new Set(value.tools).size !== Object.keys(tenantProjectWorkspaceToolSchemas).length || value.tools.some(name => !Object.hasOwn(tenantProjectWorkspaceToolSchemas, name)))
39
+ ctx.addIssue({ code: 'custom', message: 'Project workspace tools must match the exact version19 contract' }); });