@opengeni/contracts 0.28.1 → 0.31.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/index.ts CHANGED
@@ -2548,6 +2548,46 @@ export const McpServerConnectionRef = z
2548
2548
  });
2549
2549
  export type McpServerConnectionRef = z.infer<typeof McpServerConnectionRef>;
2550
2550
 
2551
+ /** Internal frozen authority for one personal MCP connection. */
2552
+ export const McpPersonalConnectionDelegation = z
2553
+ .object({
2554
+ serverId: z.string().min(1).max(256),
2555
+ connectionId: z.string().uuid(),
2556
+ ownerSubjectId: z.string().min(1).max(512),
2557
+ providerDomain: z.string().min(1).max(2048),
2558
+ kind: z.enum(["oauth2", "api_key", "app_install", "delegated"]).optional(),
2559
+ })
2560
+ .strict();
2561
+ export type McpPersonalConnectionDelegation = z.infer<typeof McpPersonalConnectionDelegation>;
2562
+
2563
+ /**
2564
+ * Exact personal MCP authority frozen on one causal turn or scheduled task.
2565
+ * One server can have at most one grant; bounded validation keeps corrupt JSON
2566
+ * from becoming executable credential authority at a DB read boundary.
2567
+ */
2568
+ export const McpPersonalConnectionDelegations = z
2569
+ .array(McpPersonalConnectionDelegation)
2570
+ .max(128)
2571
+ .superRefine((delegations, context) => {
2572
+ const seen = new Set<string>();
2573
+ for (const [index, delegation] of delegations.entries()) {
2574
+ if (seen.has(delegation.serverId)) {
2575
+ context.addIssue({
2576
+ code: "custom",
2577
+ message: "personal MCP delegations must be unique by serverId",
2578
+ path: [index, "serverId"],
2579
+ });
2580
+ }
2581
+ seen.add(delegation.serverId);
2582
+ }
2583
+ });
2584
+
2585
+ export const McpPersonalConnectionSummary = McpPersonalConnectionDelegation.pick({
2586
+ serverId: true,
2587
+ providerDomain: true,
2588
+ });
2589
+ export type McpPersonalConnectionSummary = z.infer<typeof McpPersonalConnectionSummary>;
2590
+
2551
2591
  export type McpCredentialsRequest = {
2552
2592
  accountId: string;
2553
2593
  workspaceId: string;
@@ -2575,6 +2615,7 @@ export type McpCredentialsRequest = {
2575
2615
 
2576
2616
  export type McpCredentialAuthNeededReason =
2577
2617
  | CredentialAuthNeededReason
2618
+ | "personal_authority_unavailable"
2578
2619
  | "unsupported_auth"
2579
2620
  | "resource_scope_unavailable";
2580
2621
 
@@ -4021,6 +4062,8 @@ export const SessionTurn = z.object({
4021
4062
  lineage: z.record(z.string(), z.unknown()),
4022
4063
  initiator: TurnInitiator,
4023
4064
  initiatorContext: TurnInitiatorContext,
4065
+ /** Secret-safe projection of the exact personal authority frozen on this turn. */
4066
+ personalConnections: z.array(McpPersonalConnectionSummary).default([]),
4024
4067
  cancelledBy: z.string().nullable(),
4025
4068
  cancelReason: z.string().nullable(),
4026
4069
  startedAt: z.string().nullable(),
@@ -4508,6 +4551,8 @@ export type SessionPendingInputPreview = z.infer<typeof SessionPendingInputPrevi
4508
4551
  export const SessionQueueSnapshot = z.object({
4509
4552
  version: z.number().int().nonnegative(),
4510
4553
  effectiveControl: EffectiveSessionControl,
4554
+ /** Secret-safe personal MCP summaries frozen on the exact active turn. */
4555
+ activePersonalConnections: z.array(McpPersonalConnectionSummary).default([]),
4511
4556
  /**
4512
4557
  * True while the latest attempt is interrupted but has not durably proved
4513
4558
  * quiescence: no more inference, user-visible output, or workspace-persistence
@@ -4875,6 +4920,9 @@ export const ScheduledTask = z.object({
4875
4920
  runMode: ScheduledTaskRunMode,
4876
4921
  overlapPolicy: ScheduledTaskOverlapPolicy,
4877
4922
  agentConfig: ScheduledTaskAgentConfig,
4923
+ createdBy: TurnInitiator.default({ kind: "service", subjectId: "unattributed-legacy" }),
4924
+ createdByContext: TurnInitiatorContext.default({}),
4925
+ personalConnections: z.array(McpPersonalConnectionSummary).default([]),
4878
4926
  reusableSessionId: z.string().uuid().nullable(),
4879
4927
  variableSetId: z.string().uuid().nullable().default(null),
4880
4928
  /** @deprecated use variableSetId */
@@ -5117,43 +5165,83 @@ export const CapabilityPack = z.preprocess(
5117
5165
  }
5118
5166
  return record;
5119
5167
  },
5120
- z.object({
5121
- id: z.string().min(1),
5122
- name: z.string().min(1),
5123
- description: z.string().min(1),
5124
- role: z.string().min(1),
5125
- category: z.string().min(1),
5126
- version: z.string().min(1),
5127
- // Container image ref (digest-pinned recommended) the pack's sessions run
5128
- // in. At most one enabled pack per workspace may declare one; with none,
5129
- // sessions use the deployment-wide image settings.
5130
- sandboxImage: z.string().trim().min(1).max(512).optional(),
5131
- // Skills delivered into the sandbox skill index when the pack is enabled.
5132
- skills: z
5133
- .array(CapabilityPackSkill)
5134
- .max(32)
5135
- .superRefine((skills, ctx) => {
5136
- const seen = new Set<string>();
5137
- skills.forEach((skill, index) => {
5138
- const key = skill.name.toLowerCase();
5139
- if (seen.has(key)) {
5140
- ctx.addIssue({
5141
- code: "custom",
5142
- message: `duplicate pack skill name: ${skill.name}`,
5143
- path: [index, "name"],
5144
- });
5145
- }
5146
- seen.add(key);
5168
+ z
5169
+ .object({
5170
+ id: z.string().min(1),
5171
+ name: z.string().min(1),
5172
+ description: z.string().min(1),
5173
+ role: z.string().min(1),
5174
+ category: z.string().min(1),
5175
+ version: z.string().min(1),
5176
+ // Container image ref (digest-pinned recommended) the pack's sessions run
5177
+ // in. At most one enabled pack per workspace may declare one; with none,
5178
+ // sessions use the deployment-wide image settings.
5179
+ sandboxImage: z.string().trim().min(1).max(512).optional(),
5180
+ // Optional provider-native immutable identities for the exact logical
5181
+ // sandboxImage above. These avoid re-importing a private registry image on
5182
+ // every provider while preserving sandboxImage as the cross-provider image
5183
+ // provenance and lease-conflict identity.
5184
+ sandboxProviderImages: z
5185
+ .object({
5186
+ modal: z
5187
+ .object({
5188
+ imageId: z
5189
+ .string()
5190
+ .trim()
5191
+ .regex(/^im-[A-Za-z0-9]{22}$/),
5192
+ })
5193
+ .strict()
5194
+ .optional(),
5195
+ })
5196
+ .strict()
5197
+ .optional(),
5198
+ // Skills delivered into the sandbox skill index when the pack is enabled.
5199
+ skills: z
5200
+ .array(CapabilityPackSkill)
5201
+ .max(32)
5202
+ .superRefine((skills, ctx) => {
5203
+ const seen = new Set<string>();
5204
+ skills.forEach((skill, index) => {
5205
+ const key = skill.name.toLowerCase();
5206
+ if (seen.has(key)) {
5207
+ ctx.addIssue({
5208
+ code: "custom",
5209
+ message: `duplicate pack skill name: ${skill.name}`,
5210
+ path: [index, "name"],
5211
+ });
5212
+ }
5213
+ seen.add(key);
5214
+ });
5215
+ })
5216
+ .default([]),
5217
+ tools: z.array(ToolRef).default([]),
5218
+ connectors: z.array(CapabilityPackConnector).default([]),
5219
+ knowledge: z.array(CapabilityPackKnowledge).default([]),
5220
+ scheduledTaskTemplates: z.array(CapabilityPackScheduledTaskTemplate).default([]),
5221
+ variableSet: CapabilityPackVariableSet.optional(),
5222
+ metadata: z.record(z.string(), z.unknown()).default({}),
5223
+ })
5224
+ .superRefine((pack, ctx) => {
5225
+ if (!pack.sandboxProviderImages?.modal) {
5226
+ return;
5227
+ }
5228
+ if (!pack.sandboxImage) {
5229
+ ctx.addIssue({
5230
+ code: "custom",
5231
+ message: "sandboxProviderImages.modal requires sandboxImage",
5232
+ path: ["sandboxProviderImages", "modal"],
5147
5233
  });
5148
- })
5149
- .default([]),
5150
- tools: z.array(ToolRef).default([]),
5151
- connectors: z.array(CapabilityPackConnector).default([]),
5152
- knowledge: z.array(CapabilityPackKnowledge).default([]),
5153
- scheduledTaskTemplates: z.array(CapabilityPackScheduledTaskTemplate).default([]),
5154
- variableSet: CapabilityPackVariableSet.optional(),
5155
- metadata: z.record(z.string(), z.unknown()).default({}),
5156
- }),
5234
+ return;
5235
+ }
5236
+ if (!/@sha256:[0-9a-f]{64}$/i.test(pack.sandboxImage)) {
5237
+ ctx.addIssue({
5238
+ code: "custom",
5239
+ message:
5240
+ "sandboxProviderImages.modal requires sandboxImage to be pinned by an OCI sha256 digest",
5241
+ path: ["sandboxImage"],
5242
+ });
5243
+ }
5244
+ }),
5157
5245
  );
5158
5246
  export type CapabilityPack = z.infer<typeof CapabilityPack>;
5159
5247
 
@@ -5397,9 +5485,14 @@ function compareDescending(left: number | string, right: number | string): numbe
5397
5485
  export const ConnectionCredentialBundle = z.record(z.string(), z.unknown());
5398
5486
  export type ConnectionCredentialBundle = z.infer<typeof ConnectionCredentialBundle>;
5399
5487
 
5488
+ export const ConnectionOwnership = z.enum(["workspace", "personal"]);
5489
+ export type ConnectionOwnership = z.infer<typeof ConnectionOwnership>;
5490
+
5400
5491
  export const CreateConnectionRequest = z.object({
5401
5492
  providerDomain: z.string().min(1),
5402
5493
  kind: ConnectionKind,
5494
+ ownership: ConnectionOwnership.optional(),
5495
+ /** @deprecated use ownership */
5403
5496
  subjectId: z.string().min(1).nullable().optional(),
5404
5497
  credential: ConnectionCredentialBundle,
5405
5498
  grantedScopes: z.array(z.string().min(1)).default([]),
@@ -5449,6 +5542,7 @@ export const OAuthStartRequest = z
5449
5542
  requestedScopes: z.array(z.string().min(1)).default([]),
5450
5543
  returnPath: z.string().min(1).optional(),
5451
5544
  connectionId: z.string().uuid().optional(),
5545
+ ownership: ConnectionOwnership.optional(),
5452
5546
  oauthClient: z
5453
5547
  .object({
5454
5548
  clientId: z.string().min(1),
@@ -6243,6 +6337,7 @@ export const ToolAuthNeededPayload = z.object({
6243
6337
  "expired",
6244
6338
  "insufficient_scope",
6245
6339
  "refresh_failed",
6340
+ "personal_authority_unavailable",
6246
6341
  "unsupported_auth",
6247
6342
  "resource_scope_unavailable",
6248
6343
  ]),
@@ -9539,3 +9634,4 @@ export * from "./secret-redaction";
9539
9634
  export * from "./workspace-instruction-policies";
9540
9635
  export * from "./workspace-state";
9541
9636
  export * from "./preference-registry";
9637
+ export * from "./scoped-knowledge";
@@ -0,0 +1,216 @@
1
+ import { z } from "zod";
2
+
3
+ /** Tenant scope for normalized knowledge and source provenance. */
4
+ export const ScopedKnowledgeScopeKind = z.enum(["organization", "workspace", "personal"]);
5
+ export type ScopedKnowledgeScopeKind = z.infer<typeof ScopedKnowledgeScopeKind>;
6
+
7
+ export type ScopedKnowledgeScope =
8
+ | { kind: "organization"; workspaceId: null; subjectId: null }
9
+ | { kind: "workspace"; workspaceId: string; subjectId: null }
10
+ | { kind: "personal"; workspaceId: string | null; subjectId: string };
11
+
12
+ export const ScopedKnowledgeActorKind = z.enum(["human", "service"]);
13
+ export type ScopedKnowledgeActorKind = z.infer<typeof ScopedKnowledgeActorKind>;
14
+
15
+ /**
16
+ * Immutable write provenance. A service actor may retain a causal human, but
17
+ * the service identity never substitutes for that human on personal reads.
18
+ */
19
+ export type ScopedKnowledgeActor = {
20
+ kind: ScopedKnowledgeActorKind;
21
+ subjectId: string;
22
+ initiatingHumanSubjectId: string | null;
23
+ };
24
+
25
+ export const KnowledgeLifecycleState = z.enum(["active", "deleted", "revoked"]);
26
+ export type KnowledgeLifecycleState = z.infer<typeof KnowledgeLifecycleState>;
27
+
28
+ export const KnowledgeLifecycleEventType = z.enum([
29
+ "deleted",
30
+ "revoked",
31
+ "restored",
32
+ "acl_changed",
33
+ "sync_succeeded",
34
+ "sync_failed",
35
+ "object_version_added",
36
+ ]);
37
+ export type KnowledgeLifecycleEventType = z.infer<typeof KnowledgeLifecycleEventType>;
38
+
39
+ export const KnowledgeSyncRunState = z.enum(["started", "succeeded", "failed"]);
40
+ export type KnowledgeSyncRunState = z.infer<typeof KnowledgeSyncRunState>;
41
+
42
+ export const KnowledgeClaimOrigin = z.enum(["explicit", "inferred"]);
43
+ export type KnowledgeClaimOrigin = z.infer<typeof KnowledgeClaimOrigin>;
44
+
45
+ export const KnowledgeClaimRelationType = z.enum(["supersedes", "conflicts_with"]);
46
+ export type KnowledgeClaimRelationType = z.infer<typeof KnowledgeClaimRelationType>;
47
+
48
+ export const KnowledgeClaimEvidencePolarity = z.enum(["supports", "contradicts"]);
49
+ export type KnowledgeClaimEvidencePolarity = z.infer<typeof KnowledgeClaimEvidencePolarity>;
50
+
51
+ export const KnowledgeClaimReviewState = z.enum(["proposed", "approved", "rejected", "revoked"]);
52
+ export type KnowledgeClaimReviewState = z.infer<typeof KnowledgeClaimReviewState>;
53
+
54
+ export const KnowledgeFactObjectKind = z.enum([
55
+ "entity",
56
+ "text",
57
+ "number",
58
+ "boolean",
59
+ "json",
60
+ "timestamp",
61
+ ]);
62
+ export type KnowledgeFactObjectKind = z.infer<typeof KnowledgeFactObjectKind>;
63
+
64
+ export const KnowledgeChangeProposalTargetKind = z.enum(["instruction_policy", "preference"]);
65
+ export type KnowledgeChangeProposalTargetKind = z.infer<typeof KnowledgeChangeProposalTargetKind>;
66
+
67
+ export type KnowledgeProviderRecord = {
68
+ id: string;
69
+ accountId: string;
70
+ scope: ScopedKnowledgeScope;
71
+ providerKey: string;
72
+ externalTenantId: string;
73
+ lifecycleState: KnowledgeLifecycleState;
74
+ lifecycleGeneration: number;
75
+ createdAt: string;
76
+ updatedAt: string;
77
+ };
78
+
79
+ export type KnowledgeSourceRecord = {
80
+ id: string;
81
+ accountId: string;
82
+ providerId: string;
83
+ scope: ScopedKnowledgeScope;
84
+ externalSourceId: string;
85
+ sourceKind: string;
86
+ sourceUri: string | null;
87
+ currentAclGeneration: number | null;
88
+ syncGeneration: number;
89
+ syncCursor: string | null;
90
+ lifecycleState: KnowledgeLifecycleState;
91
+ lifecycleGeneration: number;
92
+ createdAt: string;
93
+ updatedAt: string;
94
+ };
95
+
96
+ export type KnowledgeSourceAclVersionRecord = {
97
+ id: string;
98
+ accountId: string;
99
+ sourceId: string;
100
+ generation: number;
101
+ aclVersion: string | null;
102
+ aclHash: string;
103
+ audience: ScopedKnowledgeScope;
104
+ agentAccess: boolean;
105
+ createdAt: string;
106
+ };
107
+
108
+ export type KnowledgeSyncRunRecord = {
109
+ id: string;
110
+ accountId: string;
111
+ sourceId: string;
112
+ operationId: string;
113
+ state: KnowledgeSyncRunState;
114
+ inputSyncGeneration: number;
115
+ inputLifecycleGeneration: number;
116
+ inputCursor: string | null;
117
+ outputCursor: string | null;
118
+ watermark: string | null;
119
+ metadata: Record<string, unknown>;
120
+ errorCode: string | null;
121
+ startedAt: string;
122
+ completedAt: string | null;
123
+ };
124
+
125
+ export type KnowledgeSourceObjectRecord = {
126
+ id: string;
127
+ accountId: string;
128
+ sourceId: string;
129
+ scope: ScopedKnowledgeScope;
130
+ externalObjectId: string;
131
+ documentId: string | null;
132
+ lifecycleState: KnowledgeLifecycleState;
133
+ lifecycleGeneration: number;
134
+ versionGeneration: number;
135
+ currentVersionId: string | null;
136
+ createdAt: string;
137
+ updatedAt: string;
138
+ };
139
+
140
+ export type KnowledgeDocumentVersionRecord = {
141
+ id: string;
142
+ accountId: string;
143
+ sourceId: string;
144
+ objectId: string;
145
+ scope: ScopedKnowledgeScope;
146
+ versionGeneration: number;
147
+ externalVersionId: string;
148
+ contentSha256: string;
149
+ ingestionKey: string;
150
+ aclVersionId: string;
151
+ aclGeneration: number;
152
+ documentId: string | null;
153
+ fileId: string | null;
154
+ createdAt: string;
155
+ };
156
+
157
+ export type KnowledgeEntityRecord = {
158
+ id: string;
159
+ accountId: string;
160
+ scope: ScopedKnowledgeScope;
161
+ entityType: string;
162
+ normalizedKey: string;
163
+ displayName: string;
164
+ createdAt: string;
165
+ };
166
+
167
+ export type KnowledgeFactRecord = {
168
+ id: string;
169
+ accountId: string;
170
+ scope: ScopedKnowledgeScope;
171
+ subjectEntityId: string;
172
+ predicateKey: string;
173
+ objectKind: KnowledgeFactObjectKind;
174
+ objectEntityId: string | null;
175
+ objectValue: unknown | null;
176
+ objectHash: string;
177
+ createdAt: string;
178
+ };
179
+
180
+ export type KnowledgeClaimRecord = {
181
+ id: string;
182
+ accountId: string;
183
+ scope: ScopedKnowledgeScope;
184
+ factId: string;
185
+ origin: KnowledgeClaimOrigin;
186
+ confidenceBps: number;
187
+ effectiveAt: string;
188
+ expiresAt: string | null;
189
+ extractionMethod: string;
190
+ modelProvider: string | null;
191
+ modelName: string | null;
192
+ modelVersion: string | null;
193
+ createdAt: string;
194
+ };
195
+
196
+ export type EligibleKnowledgeClaim = {
197
+ claim: KnowledgeClaimRecord;
198
+ fact: KnowledgeFactRecord;
199
+ reviewState: "approved";
200
+ supportingEvidenceCount: number;
201
+ };
202
+
203
+ export type KnowledgeChangeProposalRecord = {
204
+ id: string;
205
+ accountId: string;
206
+ scope: ScopedKnowledgeScope;
207
+ targetKind: KnowledgeChangeProposalTargetKind;
208
+ targetScope: string;
209
+ targetKey: string | null;
210
+ content: string;
211
+ contentHash: string;
212
+ claimId: string;
213
+ evidenceId: string;
214
+ status: "proposed";
215
+ createdAt: string;
216
+ };