@opengeni/contracts 0.19.4 → 0.20.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opengeni/contracts",
3
- "version": "0.19.4",
3
+ "version": "0.20.0",
4
4
  "description": "Shared zod schemas and wire-contract types for the OpenGeni API.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
package/src/index.ts CHANGED
@@ -4273,6 +4273,10 @@ export const ScheduledTaskAgentConfig = z.object({
4273
4273
  resources: z.array(ResourceRef).default([]),
4274
4274
  tools: z.array(ToolRef).default([]),
4275
4275
  metadata: z.record(z.string(), z.unknown()).default({}),
4276
+ // Explicit workspace-shared OpenGeni Slack bot binding for scheduled runs.
4277
+ // The worker copies this non-secret pointer into session metadata; the
4278
+ // first-party Slack tools never fall back to a personal hosted-MCP grant.
4279
+ slackBotConnectionId: z.string().uuid().optional(),
4276
4280
  model: z.string().min(1).optional(),
4277
4281
  reasoningEffort: ReasoningEffort.optional(),
4278
4282
  sandboxBackend: SandboxBackend.optional(),
@@ -4657,6 +4661,34 @@ export type ConnectionKind = z.infer<typeof ConnectionKind>;
4657
4661
  export const ConnectionStatus = z.enum(["active", "needs_reauth", "revoked", "error"]);
4658
4662
  export type ConnectionStatus = z.infer<typeof ConnectionStatus>;
4659
4663
 
4664
+ export const OPENGENI_SLACK_BOT_CREDENTIAL_ROLE = "opengeni_slack_bot" as const;
4665
+ export const OPENGENI_SLACK_BOT_CREDENTIAL_LABEL = "OpenGeni Slack bot" as const;
4666
+ export const OPENGENI_SLACK_BOT_SESSION_METADATA_KEY = "opengeniSlackBotConnectionId" as const;
4667
+ export const OPENGENI_SLACK_BOT_REQUIRED_SCOPES = [
4668
+ "chat:write",
4669
+ "im:write",
4670
+ "channels:read",
4671
+ "channels:history",
4672
+ "groups:read",
4673
+ "groups:history",
4674
+ "users:read",
4675
+ ] as const;
4676
+ export const OPENGENI_SLACK_BOT_FORBIDDEN_SCOPES = ["channels:join", "chat:write.public"] as const;
4677
+
4678
+ export const OpenGeniSlackBotConnectionMetadata = z
4679
+ .object({
4680
+ credentialRole: z.literal(OPENGENI_SLACK_BOT_CREDENTIAL_ROLE),
4681
+ credentialLabel: z.literal(OPENGENI_SLACK_BOT_CREDENTIAL_LABEL),
4682
+ slackTeamId: z.string().min(1).max(64),
4683
+ slackTeamName: z.string().min(1).max(256),
4684
+ botUserId: z.string().min(1).max(64),
4685
+ botId: z.string().min(1).max(64),
4686
+ botDisplayName: z.literal("OpenGeni"),
4687
+ verifiedAt: z.string().datetime({ offset: true }),
4688
+ })
4689
+ .passthrough();
4690
+ export type OpenGeniSlackBotConnectionMetadata = z.infer<typeof OpenGeniSlackBotConnectionMetadata>;
4691
+
4660
4692
  export const ConnectionMetadata = z.object({
4661
4693
  id: z.string().uuid(),
4662
4694
  accountId: z.string().uuid(),
@@ -4671,6 +4703,8 @@ export const ConnectionMetadata = z.object({
4671
4703
  lastUsedAt: z.string().nullable(),
4672
4704
  lastError: z.string().nullable(),
4673
4705
  version: z.number().int().positive(),
4706
+ verifiedInstallAt: z.string().datetime({ offset: true }).nullable().optional(),
4707
+ verifiedInstallVersion: z.number().int().positive().nullable().optional(),
4674
4708
  metadata: z.record(z.string(), z.unknown()),
4675
4709
  createdBySubjectId: z.string().nullable(),
4676
4710
  updatedBySubjectId: z.string().nullable(),
@@ -4693,6 +4727,16 @@ export const CreateConnectionRequest = z.object({
4693
4727
  });
4694
4728
  export type CreateConnectionRequest = z.infer<typeof CreateConnectionRequest>;
4695
4729
 
4730
+ /**
4731
+ * Write-only Slack bot installation input. `token` is accepted only by the
4732
+ * dedicated validated endpoint and is never represented in a response schema.
4733
+ */
4734
+ export const ConnectOpenGeniSlackBotRequest = z.object({
4735
+ token: z.string().trim().startsWith("xoxb-").max(8192),
4736
+ connectionId: z.string().uuid().optional(),
4737
+ });
4738
+ export type ConnectOpenGeniSlackBotRequest = z.infer<typeof ConnectOpenGeniSlackBotRequest>;
4739
+
4696
4740
  export const UpdateConnectionRequest = z.object({
4697
4741
  providerDomain: z.string().min(1).optional(),
4698
4742
  subjectId: z.string().min(1).nullable().optional(),
@@ -8730,3 +8774,4 @@ export function evaluateWorkspaceModelPolicy(
8730
8774
 
8731
8775
  export * from "./codex-fleet-policy";
8732
8776
  export * from "./secret-redaction";
8777
+ export * from "./workspace-instruction-policies";
@@ -0,0 +1,267 @@
1
+ import { z } from "zod";
2
+
3
+ export const WORKSPACE_INSTRUCTION_POLICY_CONTENT_MAX_CHARS = 262_144;
4
+ export const WORKSPACE_INSTRUCTION_POLICY_REASON_MAX_CHARS = 4_096;
5
+ export const WORKSPACE_INSTRUCTION_POLICY_ROLE_KEY_MAX_CHARS = 64;
6
+ export const WORKSPACE_INSTRUCTION_POLICY_SOURCE_ID_MAX_CHARS = 512;
7
+
8
+ export const WorkspaceInstructionPolicyKind = z.enum(["charter", "policy"]);
9
+ export type WorkspaceInstructionPolicyKind = z.infer<typeof WorkspaceInstructionPolicyKind>;
10
+
11
+ export const WorkspaceInstructionPolicyScope = z.enum(["global", "role"]);
12
+ export type WorkspaceInstructionPolicyScope = z.infer<typeof WorkspaceInstructionPolicyScope>;
13
+
14
+ export const WorkspaceInstructionPolicyProvenanceSource = z.enum([
15
+ "human",
16
+ "onboarding",
17
+ "knowledge_proposal",
18
+ "legacy_import",
19
+ ]);
20
+ export type WorkspaceInstructionPolicyProvenanceSource = z.infer<
21
+ typeof WorkspaceInstructionPolicyProvenanceSource
22
+ >;
23
+
24
+ export const WorkspaceInstructionPolicyDraftProvenanceSource = z.enum([
25
+ "human",
26
+ "onboarding",
27
+ "knowledge_proposal",
28
+ ]);
29
+ export type WorkspaceInstructionPolicyDraftProvenanceSource = z.infer<
30
+ typeof WorkspaceInstructionPolicyDraftProvenanceSource
31
+ >;
32
+
33
+ export const WorkspaceInstructionPolicyActivationType = z.enum(["activate", "rollback"]);
34
+ export type WorkspaceInstructionPolicyActivationType = z.infer<
35
+ typeof WorkspaceInstructionPolicyActivationType
36
+ >;
37
+
38
+ export const WorkspaceInstructionPolicyRoleKey = z
39
+ .string()
40
+ .min(1)
41
+ .max(WORKSPACE_INSTRUCTION_POLICY_ROLE_KEY_MAX_CHARS)
42
+ .regex(/^[a-z0-9](?:[a-z0-9._-]*[a-z0-9])?$/);
43
+ export type WorkspaceInstructionPolicyRoleKey = z.infer<typeof WorkspaceInstructionPolicyRoleKey>;
44
+
45
+ /**
46
+ * Role-policy keys are identifiers rather than display names. Normalize once
47
+ * at ingress so activation uniqueness and every client use the same key.
48
+ */
49
+ export function normalizeWorkspaceInstructionPolicyRoleKey(value: string): string {
50
+ return value.normalize("NFKC").trim().toLowerCase().replace(/\s+/gu, "-").replace(/-+/g, "-");
51
+ }
52
+
53
+ const RequestRoleKey = z
54
+ .string()
55
+ .transform(normalizeWorkspaceInstructionPolicyRoleKey)
56
+ .pipe(WorkspaceInstructionPolicyRoleKey);
57
+
58
+ const targetShape = {
59
+ kind: WorkspaceInstructionPolicyKind,
60
+ scope: WorkspaceInstructionPolicyScope,
61
+ roleKey: WorkspaceInstructionPolicyRoleKey.nullable(),
62
+ };
63
+
64
+ function validateTarget(
65
+ value: {
66
+ kind: WorkspaceInstructionPolicyKind;
67
+ scope: WorkspaceInstructionPolicyScope;
68
+ roleKey: string | null;
69
+ },
70
+ context: z.RefinementCtx,
71
+ ): void {
72
+ if (value.kind === "charter" && (value.scope !== "global" || value.roleKey !== null)) {
73
+ context.addIssue({
74
+ code: "custom",
75
+ path: ["scope"],
76
+ message: "a charter must use global scope with no role key",
77
+ });
78
+ }
79
+ if (value.scope === "global" && value.roleKey !== null) {
80
+ context.addIssue({
81
+ code: "custom",
82
+ path: ["roleKey"],
83
+ message: "a global instruction policy must not have a role key",
84
+ });
85
+ }
86
+ if (value.scope === "role" && (value.kind !== "policy" || value.roleKey === null)) {
87
+ context.addIssue({
88
+ code: "custom",
89
+ path: ["roleKey"],
90
+ message: "role scope requires a policy and a normalized role key",
91
+ });
92
+ }
93
+ }
94
+
95
+ export const WorkspaceInstructionPolicyTarget = z.object(targetShape).superRefine(validateTarget);
96
+ export type WorkspaceInstructionPolicyTarget = z.infer<typeof WorkspaceInstructionPolicyTarget>;
97
+
98
+ export const WorkspaceInstructionPolicyProvenance = z.object({
99
+ source: WorkspaceInstructionPolicyProvenanceSource,
100
+ sourceId: z.string().min(1).max(WORKSPACE_INSTRUCTION_POLICY_SOURCE_ID_MAX_CHARS).nullable(),
101
+ });
102
+ export type WorkspaceInstructionPolicyProvenance = z.infer<
103
+ typeof WorkspaceInstructionPolicyProvenance
104
+ >;
105
+
106
+ const revisionIdentityShape = {
107
+ id: z.string().uuid(),
108
+ revision: z.number().int().positive(),
109
+ contentHash: z.string().regex(/^[0-9a-f]{64}$/),
110
+ };
111
+
112
+ export const WorkspaceInstructionPolicyRevisionIdentity = z.object(revisionIdentityShape);
113
+ export type WorkspaceInstructionPolicyRevisionIdentity = z.infer<
114
+ typeof WorkspaceInstructionPolicyRevisionIdentity
115
+ >;
116
+
117
+ export const WorkspaceInstructionPolicyRevision = z.object({
118
+ ...revisionIdentityShape,
119
+ accountId: z.string().uuid(),
120
+ workspaceId: z.string().uuid(),
121
+ ...targetShape,
122
+ content: z.string().min(1).max(WORKSPACE_INSTRUCTION_POLICY_CONTENT_MAX_CHARS),
123
+ provenance: WorkspaceInstructionPolicyProvenance,
124
+ supersedesRevisionId: z.string().uuid().nullable(),
125
+ createdBySubjectId: z.string().min(1),
126
+ createdAt: z.string().datetime(),
127
+ });
128
+ export type WorkspaceInstructionPolicyRevision = z.infer<typeof WorkspaceInstructionPolicyRevision>;
129
+
130
+ export const WorkspaceInstructionPolicyHead = z.object({
131
+ workspaceId: z.string().uuid(),
132
+ ...targetShape,
133
+ revisionId: z.string().uuid(),
134
+ revision: z.number().int().positive(),
135
+ contentHash: z.string().regex(/^[0-9a-f]{64}$/),
136
+ activationVersion: z.number().int().positive(),
137
+ activatedAt: z.string().datetime(),
138
+ });
139
+ export type WorkspaceInstructionPolicyHead = z.infer<typeof WorkspaceInstructionPolicyHead>;
140
+
141
+ export const WorkspaceInstructionPolicyActivationEvent = z.object({
142
+ id: z.string().uuid(),
143
+ accountId: z.string().uuid(),
144
+ workspaceId: z.string().uuid(),
145
+ ...targetShape,
146
+ type: WorkspaceInstructionPolicyActivationType,
147
+ activationVersion: z.number().int().positive(),
148
+ oldRevision: WorkspaceInstructionPolicyRevisionIdentity.nullable(),
149
+ newRevision: WorkspaceInstructionPolicyRevisionIdentity,
150
+ actorSubjectId: z.string().min(1),
151
+ reason: z.string().min(1).max(WORKSPACE_INSTRUCTION_POLICY_REASON_MAX_CHARS),
152
+ createdAt: z.string().datetime(),
153
+ });
154
+ export type WorkspaceInstructionPolicyActivationEvent = z.infer<
155
+ typeof WorkspaceInstructionPolicyActivationEvent
156
+ >;
157
+
158
+ export const CreateWorkspaceInstructionPolicyDraftRequest = z
159
+ .object({
160
+ kind: WorkspaceInstructionPolicyKind,
161
+ scope: WorkspaceInstructionPolicyScope,
162
+ roleKey: RequestRoleKey.nullable().default(null),
163
+ content: z
164
+ .string()
165
+ .min(1)
166
+ .max(WORKSPACE_INSTRUCTION_POLICY_CONTENT_MAX_CHARS)
167
+ .refine((value) => value.trim().length > 0, "instruction policy content must not be blank"),
168
+ provenanceSource: WorkspaceInstructionPolicyDraftProvenanceSource.default("human"),
169
+ provenanceSourceId: z
170
+ .string()
171
+ .min(1)
172
+ .max(WORKSPACE_INSTRUCTION_POLICY_SOURCE_ID_MAX_CHARS)
173
+ .nullable()
174
+ .default(null),
175
+ supersedesRevisionId: z.string().uuid().nullable().default(null),
176
+ })
177
+ .superRefine(validateTarget);
178
+ export type CreateWorkspaceInstructionPolicyDraftRequest = z.infer<
179
+ typeof CreateWorkspaceInstructionPolicyDraftRequest
180
+ >;
181
+
182
+ export const ImportLegacyWorkspaceInstructionPolicyDraftRequest = z
183
+ .object({
184
+ supersedesRevisionId: z.string().uuid().nullable().default(null),
185
+ })
186
+ .strict();
187
+ export type ImportLegacyWorkspaceInstructionPolicyDraftRequest = z.infer<
188
+ typeof ImportLegacyWorkspaceInstructionPolicyDraftRequest
189
+ >;
190
+
191
+ export const WorkspaceInstructionPolicyListQuery = z.object({
192
+ kind: WorkspaceInstructionPolicyKind.optional(),
193
+ scope: WorkspaceInstructionPolicyScope.optional(),
194
+ roleKey: RequestRoleKey.nullable().optional(),
195
+ afterRevision: z.coerce.number().int().positive().optional(),
196
+ limit: z.coerce.number().int().min(1).max(100).default(50),
197
+ });
198
+ export type WorkspaceInstructionPolicyListQuery = z.infer<
199
+ typeof WorkspaceInstructionPolicyListQuery
200
+ >;
201
+
202
+ export const WorkspaceInstructionPolicyListResponse = z.object({
203
+ revisions: z.array(WorkspaceInstructionPolicyRevision),
204
+ activeHeads: z.array(WorkspaceInstructionPolicyHead),
205
+ activationEvents: z.array(WorkspaceInstructionPolicyActivationEvent),
206
+ nextAfterRevision: z.number().int().positive().nullable(),
207
+ });
208
+ export type WorkspaceInstructionPolicyListResponse = z.infer<
209
+ typeof WorkspaceInstructionPolicyListResponse
210
+ >;
211
+
212
+ export const WorkspaceInstructionPolicyDiffRequest = z
213
+ .object({
214
+ fromRevisionId: z.string().uuid(),
215
+ toRevisionId: z.string().uuid(),
216
+ })
217
+ .refine((value) => value.fromRevisionId !== value.toRevisionId, {
218
+ message: "diff revisions must be different",
219
+ path: ["toRevisionId"],
220
+ });
221
+ export type WorkspaceInstructionPolicyDiffRequest = z.infer<
222
+ typeof WorkspaceInstructionPolicyDiffRequest
223
+ >;
224
+
225
+ export const WorkspaceInstructionPolicyDiffResponse = z.object({
226
+ from: WorkspaceInstructionPolicyRevision,
227
+ to: WorkspaceInstructionPolicyRevision,
228
+ format: z.literal("unified"),
229
+ diff: z.string(),
230
+ });
231
+ export type WorkspaceInstructionPolicyDiffResponse = z.infer<
232
+ typeof WorkspaceInstructionPolicyDiffResponse
233
+ >;
234
+
235
+ export const ActivateWorkspaceInstructionPolicyRequest = z.object({
236
+ expectedCurrentRevisionId: z.string().uuid().nullable(),
237
+ reason: z.string().trim().min(1).max(WORKSPACE_INSTRUCTION_POLICY_REASON_MAX_CHARS),
238
+ });
239
+ export type ActivateWorkspaceInstructionPolicyRequest = z.infer<
240
+ typeof ActivateWorkspaceInstructionPolicyRequest
241
+ >;
242
+
243
+ export const RollbackWorkspaceInstructionPolicyRequest = z.object({
244
+ targetRevisionId: z.string().uuid(),
245
+ expectedCurrentRevisionId: z.string().uuid(),
246
+ reason: z.string().trim().min(1).max(WORKSPACE_INSTRUCTION_POLICY_REASON_MAX_CHARS),
247
+ });
248
+ export type RollbackWorkspaceInstructionPolicyRequest = z.infer<
249
+ typeof RollbackWorkspaceInstructionPolicyRequest
250
+ >;
251
+
252
+ export const WorkspaceInstructionPolicyActivationResponse = z.object({
253
+ head: WorkspaceInstructionPolicyHead,
254
+ event: WorkspaceInstructionPolicyActivationEvent,
255
+ });
256
+ export type WorkspaceInstructionPolicyActivationResponse = z.infer<
257
+ typeof WorkspaceInstructionPolicyActivationResponse
258
+ >;
259
+
260
+ export const WorkspaceInstructionPolicyConflictResponse = z.object({
261
+ code: z.literal("WORKSPACE_INSTRUCTION_POLICY_CONFLICT"),
262
+ message: z.string(),
263
+ currentHead: WorkspaceInstructionPolicyHead.nullable(),
264
+ });
265
+ export type WorkspaceInstructionPolicyConflictResponse = z.infer<
266
+ typeof WorkspaceInstructionPolicyConflictResponse
267
+ >;