@opengeni/contracts 0.35.0 → 0.37.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.
@@ -4,6 +4,7 @@ export declare const WORKSPACE_INSTRUCTION_POLICY_PROMPT_MAX_UTF8_BYTES = 131072
4
4
  export declare const WORKSPACE_INSTRUCTION_POLICY_REASON_MAX_CHARS = 4096;
5
5
  export declare const WORKSPACE_INSTRUCTION_POLICY_ROLE_KEY_MAX_CHARS = 64;
6
6
  export declare const WORKSPACE_INSTRUCTION_POLICY_SOURCE_ID_MAX_CHARS = 512;
7
+ export declare const WORKSPACE_INSTRUCTION_POLICY_ONBOARDING_SOURCE_VERSION_MAX_CHARS = 256;
7
8
  export declare const WorkspaceInstructionPolicyKind: z.ZodEnum<{
8
9
  charter: "charter";
9
10
  policy: "policy";
@@ -598,3 +599,215 @@ export declare const WorkspaceInstructionPolicyOperationReuseResponse: z.ZodObje
598
599
  message: z.ZodString;
599
600
  }, z.core.$strip>;
600
601
  export type WorkspaceInstructionPolicyOperationReuseResponse = z.infer<typeof WorkspaceInstructionPolicyOperationReuseResponse>;
602
+ export declare const WorkspaceInstructionPolicyOnboardingProposalSource: z.ZodObject<{
603
+ id: z.ZodString;
604
+ version: z.ZodString;
605
+ confidenceBps: z.ZodNumber;
606
+ }, z.core.$strip>;
607
+ export type WorkspaceInstructionPolicyOnboardingProposalSource = z.infer<typeof WorkspaceInstructionPolicyOnboardingProposalSource>;
608
+ export declare const CreateWorkspaceInstructionPolicyOnboardingProposalRequest: z.ZodObject<{
609
+ operationId: z.ZodOptional<z.ZodString>;
610
+ kind: z.ZodEnum<{
611
+ charter: "charter";
612
+ policy: "policy";
613
+ }>;
614
+ scope: z.ZodEnum<{
615
+ global: "global";
616
+ role: "role";
617
+ }>;
618
+ roleKey: z.ZodDefault<z.ZodNullable<z.ZodPipe<z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>, z.ZodString>>>;
619
+ content: z.ZodString;
620
+ sourceId: z.ZodString;
621
+ sourceVersion: z.ZodString;
622
+ confidenceBps: z.ZodNumber;
623
+ expectedCurrentRevisionId: z.ZodNullable<z.ZodString>;
624
+ expectedActivationVersion: z.ZodNumber;
625
+ }, z.core.$strip>;
626
+ export type CreateWorkspaceInstructionPolicyOnboardingProposalRequest = z.infer<typeof CreateWorkspaceInstructionPolicyOnboardingProposalRequest>;
627
+ export declare const WorkspaceInstructionPolicyOnboardingProposal: z.ZodObject<{
628
+ kind: z.ZodEnum<{
629
+ charter: "charter";
630
+ policy: "policy";
631
+ }>;
632
+ scope: z.ZodEnum<{
633
+ global: "global";
634
+ role: "role";
635
+ }>;
636
+ roleKey: z.ZodNullable<z.ZodString>;
637
+ id: z.ZodString;
638
+ operationId: z.ZodString;
639
+ accountId: z.ZodString;
640
+ workspaceId: z.ZodString;
641
+ source: z.ZodObject<{
642
+ id: z.ZodString;
643
+ version: z.ZodString;
644
+ confidenceBps: z.ZodNumber;
645
+ }, z.core.$strip>;
646
+ baseline: z.ZodNullable<z.ZodObject<{
647
+ kind: z.ZodEnum<{
648
+ charter: "charter";
649
+ policy: "policy";
650
+ }>;
651
+ scope: z.ZodEnum<{
652
+ global: "global";
653
+ role: "role";
654
+ }>;
655
+ roleKey: z.ZodNullable<z.ZodString>;
656
+ workspaceId: z.ZodString;
657
+ revisionId: z.ZodString;
658
+ revision: z.ZodNumber;
659
+ contentHash: z.ZodString;
660
+ activationVersion: z.ZodNumber;
661
+ activatedAt: z.ZodString;
662
+ }, z.core.$strip>>;
663
+ draft: z.ZodObject<{
664
+ kind: z.ZodEnum<{
665
+ charter: "charter";
666
+ policy: "policy";
667
+ }>;
668
+ scope: z.ZodEnum<{
669
+ global: "global";
670
+ role: "role";
671
+ }>;
672
+ roleKey: z.ZodNullable<z.ZodString>;
673
+ id: z.ZodString;
674
+ revision: z.ZodNumber;
675
+ contentHash: z.ZodString;
676
+ operationId: z.ZodString;
677
+ accountId: z.ZodString;
678
+ workspaceId: z.ZodString;
679
+ content: z.ZodString;
680
+ provenance: z.ZodObject<{
681
+ source: z.ZodEnum<{
682
+ human: "human";
683
+ knowledge_proposal: "knowledge_proposal";
684
+ legacy_import: "legacy_import";
685
+ onboarding: "onboarding";
686
+ }>;
687
+ sourceId: z.ZodNullable<z.ZodString>;
688
+ }, z.core.$strip>;
689
+ supersedesRevisionId: z.ZodNullable<z.ZodString>;
690
+ createdBySubjectId: z.ZodString;
691
+ createdAt: z.ZodString;
692
+ }, z.core.$strip>;
693
+ status: z.ZodLiteral<"proposed">;
694
+ createdBySubjectId: z.ZodString;
695
+ createdAt: z.ZodString;
696
+ }, z.core.$strip>;
697
+ export type WorkspaceInstructionPolicyOnboardingProposal = z.infer<typeof WorkspaceInstructionPolicyOnboardingProposal>;
698
+ export declare const WorkspaceInstructionPolicyOnboardingProposalListQuery: z.ZodObject<{
699
+ limit: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
700
+ }, z.core.$strip>;
701
+ export type WorkspaceInstructionPolicyOnboardingProposalListQuery = z.infer<typeof WorkspaceInstructionPolicyOnboardingProposalListQuery>;
702
+ export declare const WorkspaceInstructionPolicyOnboardingProposalListResponse: z.ZodObject<{
703
+ proposals: z.ZodArray<z.ZodObject<{
704
+ kind: z.ZodEnum<{
705
+ charter: "charter";
706
+ policy: "policy";
707
+ }>;
708
+ scope: z.ZodEnum<{
709
+ global: "global";
710
+ role: "role";
711
+ }>;
712
+ roleKey: z.ZodNullable<z.ZodString>;
713
+ id: z.ZodString;
714
+ operationId: z.ZodString;
715
+ accountId: z.ZodString;
716
+ workspaceId: z.ZodString;
717
+ source: z.ZodObject<{
718
+ id: z.ZodString;
719
+ version: z.ZodString;
720
+ confidenceBps: z.ZodNumber;
721
+ }, z.core.$strip>;
722
+ baseline: z.ZodNullable<z.ZodObject<{
723
+ kind: z.ZodEnum<{
724
+ charter: "charter";
725
+ policy: "policy";
726
+ }>;
727
+ scope: z.ZodEnum<{
728
+ global: "global";
729
+ role: "role";
730
+ }>;
731
+ roleKey: z.ZodNullable<z.ZodString>;
732
+ workspaceId: z.ZodString;
733
+ revisionId: z.ZodString;
734
+ revision: z.ZodNumber;
735
+ contentHash: z.ZodString;
736
+ activationVersion: z.ZodNumber;
737
+ activatedAt: z.ZodString;
738
+ }, z.core.$strip>>;
739
+ draft: z.ZodObject<{
740
+ kind: z.ZodEnum<{
741
+ charter: "charter";
742
+ policy: "policy";
743
+ }>;
744
+ scope: z.ZodEnum<{
745
+ global: "global";
746
+ role: "role";
747
+ }>;
748
+ roleKey: z.ZodNullable<z.ZodString>;
749
+ id: z.ZodString;
750
+ revision: z.ZodNumber;
751
+ contentHash: z.ZodString;
752
+ operationId: z.ZodString;
753
+ accountId: z.ZodString;
754
+ workspaceId: z.ZodString;
755
+ content: z.ZodString;
756
+ provenance: z.ZodObject<{
757
+ source: z.ZodEnum<{
758
+ human: "human";
759
+ knowledge_proposal: "knowledge_proposal";
760
+ legacy_import: "legacy_import";
761
+ onboarding: "onboarding";
762
+ }>;
763
+ sourceId: z.ZodNullable<z.ZodString>;
764
+ }, z.core.$strip>;
765
+ supersedesRevisionId: z.ZodNullable<z.ZodString>;
766
+ createdBySubjectId: z.ZodString;
767
+ createdAt: z.ZodString;
768
+ }, z.core.$strip>;
769
+ status: z.ZodLiteral<"proposed">;
770
+ createdBySubjectId: z.ZodString;
771
+ createdAt: z.ZodString;
772
+ }, z.core.$strip>>;
773
+ truncated: z.ZodBoolean;
774
+ }, z.core.$strip>;
775
+ export type WorkspaceInstructionPolicyOnboardingProposalListResponse = z.infer<typeof WorkspaceInstructionPolicyOnboardingProposalListResponse>;
776
+ export declare const WorkspaceInstructionPolicyOnboardingProposalContentErrorResponse: z.ZodObject<{
777
+ code: z.ZodEnum<{
778
+ WORKSPACE_INSTRUCTION_POLICY_ONBOARDING_PROPOSAL_EMPTY: "WORKSPACE_INSTRUCTION_POLICY_ONBOARDING_PROPOSAL_EMPTY";
779
+ WORKSPACE_INSTRUCTION_POLICY_ONBOARDING_PROPOSAL_OVERSIZED: "WORKSPACE_INSTRUCTION_POLICY_ONBOARDING_PROPOSAL_OVERSIZED";
780
+ }>;
781
+ message: z.ZodString;
782
+ maxChars: z.ZodNumber;
783
+ }, z.core.$strip>;
784
+ export type WorkspaceInstructionPolicyOnboardingProposalContentErrorResponse = z.infer<typeof WorkspaceInstructionPolicyOnboardingProposalContentErrorResponse>;
785
+ export declare const WorkspaceInstructionPolicyOnboardingProposalStaleResponse: z.ZodObject<{
786
+ code: z.ZodLiteral<"WORKSPACE_INSTRUCTION_POLICY_ONBOARDING_PROPOSAL_STALE">;
787
+ message: z.ZodString;
788
+ currentHead: z.ZodNullable<z.ZodObject<{
789
+ kind: z.ZodEnum<{
790
+ charter: "charter";
791
+ policy: "policy";
792
+ }>;
793
+ scope: z.ZodEnum<{
794
+ global: "global";
795
+ role: "role";
796
+ }>;
797
+ roleKey: z.ZodNullable<z.ZodString>;
798
+ workspaceId: z.ZodString;
799
+ revisionId: z.ZodString;
800
+ revision: z.ZodNumber;
801
+ contentHash: z.ZodString;
802
+ activationVersion: z.ZodNumber;
803
+ activatedAt: z.ZodString;
804
+ }, z.core.$strip>>;
805
+ }, z.core.$strip>;
806
+ export type WorkspaceInstructionPolicyOnboardingProposalStaleResponse = z.infer<typeof WorkspaceInstructionPolicyOnboardingProposalStaleResponse>;
807
+ export declare const WorkspaceInstructionPolicyOnboardingProposalConflictResponse: z.ZodObject<{
808
+ code: z.ZodLiteral<"WORKSPACE_INSTRUCTION_POLICY_ONBOARDING_PROPOSAL_CONFLICT">;
809
+ message: z.ZodString;
810
+ existingProposalId: z.ZodString;
811
+ existingDraftRevisionId: z.ZodString;
812
+ }, z.core.$strip>;
813
+ export type WorkspaceInstructionPolicyOnboardingProposalConflictResponse = z.infer<typeof WorkspaceInstructionPolicyOnboardingProposalConflictResponse>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opengeni/contracts",
3
- "version": "0.35.0",
3
+ "version": "0.37.0",
4
4
  "description": "Shared zod schemas and wire-contract types for the OpenGeni API.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -29,6 +29,10 @@
29
29
  "./google-drive": {
30
30
  "types": "./dist/google-drive.d.ts",
31
31
  "import": "./dist/google-drive.js"
32
+ },
33
+ "./connector-destinations": {
34
+ "types": "./dist/connector-destinations.d.ts",
35
+ "import": "./dist/connector-destinations.js"
32
36
  }
33
37
  },
34
38
  "publishConfig": {
@@ -0,0 +1,132 @@
1
+ import { z } from "zod";
2
+
3
+ export const ConnectorDocumentDestinationAuthority = z.enum([
4
+ "organization",
5
+ "workspace",
6
+ "personal",
7
+ ]);
8
+ export type ConnectorDocumentDestinationAuthority = z.infer<
9
+ typeof ConnectorDocumentDestinationAuthority
10
+ >;
11
+
12
+ export const ConnectorDocumentDestinationSelection = z.object({
13
+ authorityKind: ConnectorDocumentDestinationAuthority,
14
+ collectionId: z.string().uuid().nullable().default(null),
15
+ });
16
+ export type ConnectorDocumentDestinationSelection = z.infer<
17
+ typeof ConnectorDocumentDestinationSelection
18
+ >;
19
+
20
+ export const ConnectorDocumentDestination = z
21
+ .object({
22
+ authorityKind: ConnectorDocumentDestinationAuthority,
23
+ authorityAccountId: z.string().uuid(),
24
+ authorityWorkspaceId: z.string().uuid().nullable(),
25
+ authoritySubjectId: z.string().trim().min(1).max(1024).nullable(),
26
+ collectionId: z.string().uuid().nullable().default(null),
27
+ })
28
+ .superRefine((destination, context) => {
29
+ if (destination.authorityKind === "organization") {
30
+ if (destination.authorityWorkspaceId !== null || destination.authoritySubjectId !== null) {
31
+ context.addIssue({
32
+ code: "custom",
33
+ message: "organization connector destinations cannot bind workspace or subject authority",
34
+ });
35
+ }
36
+ return;
37
+ }
38
+ if (destination.authorityWorkspaceId === null) {
39
+ context.addIssue({
40
+ code: "custom",
41
+ message: "workspace and personal connector destinations require workspace authority",
42
+ });
43
+ }
44
+ if (destination.authorityKind === "workspace" && destination.authoritySubjectId !== null) {
45
+ context.addIssue({
46
+ code: "custom",
47
+ message: "workspace connector destinations cannot bind subject authority",
48
+ });
49
+ }
50
+ if (destination.authorityKind === "personal" && destination.authoritySubjectId === null) {
51
+ context.addIssue({
52
+ code: "custom",
53
+ message: "personal connector destinations require immutable subject authority",
54
+ });
55
+ }
56
+ });
57
+ export type ConnectorDocumentDestination = z.infer<typeof ConnectorDocumentDestination>;
58
+
59
+ export function bindConnectorDocumentDestination(
60
+ selection: ConnectorDocumentDestinationSelection,
61
+ context: { accountId: string; workspaceId: string; initiatingSubjectId: string },
62
+ ): ConnectorDocumentDestination {
63
+ return ConnectorDocumentDestination.parse({
64
+ authorityKind: selection.authorityKind,
65
+ authorityAccountId: context.accountId,
66
+ authorityWorkspaceId: selection.authorityKind === "organization" ? null : context.workspaceId,
67
+ authoritySubjectId: selection.authorityKind === "personal" ? context.initiatingSubjectId : null,
68
+ collectionId: selection.collectionId,
69
+ });
70
+ }
71
+
72
+ export function legacyWorkspaceConnectorDocumentDestination(context: {
73
+ accountId: string;
74
+ workspaceId: string;
75
+ }): ConnectorDocumentDestination {
76
+ return ConnectorDocumentDestination.parse({
77
+ authorityKind: "workspace",
78
+ authorityAccountId: context.accountId,
79
+ authorityWorkspaceId: context.workspaceId,
80
+ authoritySubjectId: null,
81
+ collectionId: null,
82
+ });
83
+ }
84
+
85
+ export function resolveConnectorDocumentDestination(
86
+ value: unknown,
87
+ context: {
88
+ accountId: string;
89
+ workspaceId: string;
90
+ connectionSubjectId?: string | null | undefined;
91
+ },
92
+ ): ConnectorDocumentDestination {
93
+ if (value === undefined || value === null) {
94
+ return legacyWorkspaceConnectorDocumentDestination(context);
95
+ }
96
+ const destination = ConnectorDocumentDestination.parse(value);
97
+ if (destination.authorityAccountId !== context.accountId) {
98
+ throw new Error("connector destination organization authority mismatch");
99
+ }
100
+ if (
101
+ destination.authorityKind !== "organization" &&
102
+ destination.authorityWorkspaceId !== context.workspaceId
103
+ ) {
104
+ throw new Error("connector destination workspace authority mismatch");
105
+ }
106
+ if (
107
+ destination.authorityKind === "personal" &&
108
+ destination.authoritySubjectId !== context.connectionSubjectId
109
+ ) {
110
+ throw new Error("connector destination personal authority mismatch");
111
+ }
112
+ return destination;
113
+ }
114
+
115
+ export function connectorDestinationDocumentAuthority(destination: ConnectorDocumentDestination): {
116
+ authorityKind: ConnectorDocumentDestinationAuthority;
117
+ authorityWorkspaceId: string | null;
118
+ authoritySubjectId: string | null;
119
+ } {
120
+ return {
121
+ authorityKind: destination.authorityKind,
122
+ authorityWorkspaceId: destination.authorityWorkspaceId,
123
+ authoritySubjectId: destination.authoritySubjectId,
124
+ };
125
+ }
126
+
127
+ export function connectorDocumentDestinationCollectionId(
128
+ destination: ConnectorDocumentDestination,
129
+ defaultCollectionId: string,
130
+ ): string {
131
+ return destination.collectionId ?? z.string().uuid().parse(defaultCollectionId);
132
+ }
@@ -1,6 +1,10 @@
1
1
  import { z } from "zod";
2
2
 
3
3
  import { ConnectionMetadata } from "./index";
4
+ import {
5
+ ConnectorDocumentDestination,
6
+ ConnectorDocumentDestinationSelection,
7
+ } from "./connector-destinations";
4
8
 
5
9
  export const GOOGLE_DRIVE_PROVIDER_DOMAIN = "googleapis.com" as const;
6
10
  export const GOOGLE_DRIVE_FULL_SCOPE = "https://www.googleapis.com/auth/drive" as const;
@@ -63,6 +67,7 @@ export function googleDriveScopesAllowCapability(
63
67
  return googleDriveOAuthScopeDecision(grantedScopes).capabilities.includes(capability);
64
68
  }
65
69
 
70
+ /** @deprecated Connector document destinations use organization/workspace/personal authority. */
66
71
  export const GoogleDriveTargetScope = z.enum(["user", "workspace", "organization"]);
67
72
  export type GoogleDriveTargetScope = z.infer<typeof GoogleDriveTargetScope>;
68
73
 
@@ -130,7 +135,9 @@ export const GoogleDriveSelectedSource = z.object({
130
135
  name: z.string().min(1).max(1024),
131
136
  mimeType: z.string().min(1).max(256),
132
137
  driveId: z.string().min(1).max(256).nullable().default(null),
133
- targetScope: GoogleDriveTargetScope,
138
+ destination: ConnectorDocumentDestination.optional(),
139
+ /** @deprecated Missing destinations resolve to the current workspace boundary. */
140
+ targetScope: GoogleDriveTargetScope.optional(),
134
141
  syncCadence: GoogleDriveSyncCadence.default("hourly"),
135
142
  readPolicy: GoogleDriveReadPolicy.default("allow"),
136
143
  selectedAt: z.string().datetime({ offset: true }),
@@ -147,6 +154,7 @@ export const GoogleDriveConnectionMetadata = z
147
154
  verifiedAt: z.string().datetime({ offset: true }),
148
155
  accessMode: z.enum(["metadata_readonly", "readonly"]),
149
156
  lifecycle: GoogleDriveConnectionLifecycle.optional(),
157
+ documentDestination: ConnectorDocumentDestination.optional(),
150
158
  selectedSources: z.array(GoogleDriveSelectedSource).max(100).optional(),
151
159
  /** @deprecated Read `selectedSources`; retained while existing connections migrate. */
152
160
  selectedSource: GoogleDriveSelectedSource.nullable().optional(),
@@ -199,22 +207,28 @@ export const GoogleDriveBrowseResponse = z.object({
199
207
  });
200
208
  export type GoogleDriveBrowseResponse = z.infer<typeof GoogleDriveBrowseResponse>;
201
209
 
202
- export const SaveGoogleDriveSourceRequest = z.object({
203
- sources: z
204
- .array(
205
- GoogleDriveBrowseItem.pick({
206
- id: true,
207
- name: true,
208
- mimeType: true,
209
- driveId: true,
210
+ export const SaveGoogleDriveSourceRequest = z
211
+ .object({
212
+ sources: z
213
+ .array(
214
+ GoogleDriveBrowseItem.pick({
215
+ id: true,
216
+ name: true,
217
+ mimeType: true,
218
+ driveId: true,
219
+ }),
220
+ )
221
+ .max(100)
222
+ .refine((sources) => new Set(sources.map((source) => source.id)).size === sources.length, {
223
+ message: "Google Drive sources must be unique",
210
224
  }),
211
- )
212
- .max(100)
213
- .refine((sources) => new Set(sources.map((source) => source.id)).size === sources.length, {
214
- message: "Google Drive sources must be unique",
215
- }),
216
- targetScope: GoogleDriveTargetScope,
217
- syncCadence: GoogleDriveSyncCadence.default("hourly"),
218
- readPolicy: GoogleDriveReadPolicy.default("allow"),
219
- });
225
+ destination: ConnectorDocumentDestinationSelection.optional(),
226
+ /** @deprecated Legacy requests are accepted but resolve to workspace authority. */
227
+ targetScope: GoogleDriveTargetScope.optional(),
228
+ syncCadence: GoogleDriveSyncCadence.default("hourly"),
229
+ readPolicy: GoogleDriveReadPolicy.default("allow"),
230
+ })
231
+ .refine((request) => request.destination !== undefined || request.targetScope !== undefined, {
232
+ message: "Google Drive document destination is required",
233
+ });
220
234
  export type SaveGoogleDriveSourceRequest = z.infer<typeof SaveGoogleDriveSourceRequest>;
package/src/index.ts CHANGED
@@ -8,6 +8,7 @@ import {
8
8
  import { WorkspaceInstructionPolicyRoleKeyInput } from "./workspace-instruction-policies";
9
9
 
10
10
  export * from "./slack-bot-scopes";
11
+ export * from "./connector-destinations";
11
12
 
12
13
  export {
13
14
  CreateWorkspaceArtifactRequest,
@@ -1149,7 +1150,11 @@ export const ClientVoiceInputConfig = z
1149
1150
  .object({
1150
1151
  available: z.boolean(),
1151
1152
  maxDurationSeconds: z.number().int().positive().max(600),
1152
- maxSizeBytes: z.number().int().positive(),
1153
+ maxSizeBytes: z
1154
+ .number()
1155
+ .int()
1156
+ .positive()
1157
+ .max(25 * 1024 * 1024),
1153
1158
  acceptedMimeTypes: z.array(z.string().trim().min(1).max(128)).min(1).max(32),
1154
1159
  })
1155
1160
  .strict();
@@ -1164,7 +1169,7 @@ export const TranscribeAudioResponse = z
1164
1169
  .strict();
1165
1170
  export type TranscribeAudioResponse = z.infer<typeof TranscribeAudioResponse>;
1166
1171
 
1167
- /** Default ceilings for native voice input (hard-stop recording + upload). */
1172
+ /** Default safety ceiling for one-shot native voice input (60 seconds). */
1168
1173
  export const VOICE_INPUT_MAX_DURATION_SECONDS = 60 as const;
1169
1174
  export const VOICE_INPUT_MAX_SIZE_BYTES = 25 * 1024 * 1024;
1170
1175
  export const VOICE_INPUT_ACCEPTED_MIME_TYPES = [
@@ -5,6 +5,7 @@ export const WORKSPACE_INSTRUCTION_POLICY_PROMPT_MAX_UTF8_BYTES = 131_072;
5
5
  export const WORKSPACE_INSTRUCTION_POLICY_REASON_MAX_CHARS = 4_096;
6
6
  export const WORKSPACE_INSTRUCTION_POLICY_ROLE_KEY_MAX_CHARS = 64;
7
7
  export const WORKSPACE_INSTRUCTION_POLICY_SOURCE_ID_MAX_CHARS = 512;
8
+ export const WORKSPACE_INSTRUCTION_POLICY_ONBOARDING_SOURCE_VERSION_MAX_CHARS = 256;
8
9
 
9
10
  export const WorkspaceInstructionPolicyKind = z.enum(["charter", "policy"]);
10
11
  export type WorkspaceInstructionPolicyKind = z.infer<typeof WorkspaceInstructionPolicyKind>;
@@ -353,3 +354,100 @@ export const WorkspaceInstructionPolicyOperationReuseResponse = z.object({
353
354
  export type WorkspaceInstructionPolicyOperationReuseResponse = z.infer<
354
355
  typeof WorkspaceInstructionPolicyOperationReuseResponse
355
356
  >;
357
+
358
+ export const WorkspaceInstructionPolicyOnboardingProposalSource = z.object({
359
+ id: z.string().min(1).max(WORKSPACE_INSTRUCTION_POLICY_SOURCE_ID_MAX_CHARS),
360
+ version: z.string().min(1).max(WORKSPACE_INSTRUCTION_POLICY_ONBOARDING_SOURCE_VERSION_MAX_CHARS),
361
+ confidenceBps: z.number().int().min(0).max(10_000),
362
+ });
363
+ export type WorkspaceInstructionPolicyOnboardingProposalSource = z.infer<
364
+ typeof WorkspaceInstructionPolicyOnboardingProposalSource
365
+ >;
366
+
367
+ export const CreateWorkspaceInstructionPolicyOnboardingProposalRequest = z
368
+ .object({
369
+ operationId: z.string().uuid().optional(),
370
+ kind: WorkspaceInstructionPolicyKind,
371
+ scope: WorkspaceInstructionPolicyScope,
372
+ roleKey: WorkspaceInstructionPolicyRoleKeyInput.nullable().default(null),
373
+ // Content bounds are enforced by the domain layer so empty and oversized
374
+ // proposals retain their typed API outcomes instead of collapsing into a
375
+ // generic request-shape error.
376
+ content: z.string(),
377
+ sourceId: z.string().trim().min(1).max(WORKSPACE_INSTRUCTION_POLICY_SOURCE_ID_MAX_CHARS),
378
+ sourceVersion: z
379
+ .string()
380
+ .trim()
381
+ .min(1)
382
+ .max(WORKSPACE_INSTRUCTION_POLICY_ONBOARDING_SOURCE_VERSION_MAX_CHARS),
383
+ confidenceBps: z.number().int().min(0).max(10_000),
384
+ expectedCurrentRevisionId: z.string().uuid().nullable(),
385
+ expectedActivationVersion: z.number().int().nonnegative(),
386
+ })
387
+ .superRefine(validateTarget);
388
+ export type CreateWorkspaceInstructionPolicyOnboardingProposalRequest = z.infer<
389
+ typeof CreateWorkspaceInstructionPolicyOnboardingProposalRequest
390
+ >;
391
+
392
+ export const WorkspaceInstructionPolicyOnboardingProposal = z.object({
393
+ id: z.string().uuid(),
394
+ operationId: z.string().uuid(),
395
+ accountId: z.string().uuid(),
396
+ workspaceId: z.string().uuid(),
397
+ ...targetShape,
398
+ source: WorkspaceInstructionPolicyOnboardingProposalSource,
399
+ baseline: WorkspaceInstructionPolicyHead.nullable(),
400
+ draft: WorkspaceInstructionPolicyRevision,
401
+ status: z.literal("proposed"),
402
+ createdBySubjectId: z.string().min(1),
403
+ createdAt: z.string().datetime(),
404
+ });
405
+ export type WorkspaceInstructionPolicyOnboardingProposal = z.infer<
406
+ typeof WorkspaceInstructionPolicyOnboardingProposal
407
+ >;
408
+
409
+ export const WorkspaceInstructionPolicyOnboardingProposalListQuery = z.object({
410
+ limit: z.coerce.number().int().min(1).max(100).default(50),
411
+ });
412
+ export type WorkspaceInstructionPolicyOnboardingProposalListQuery = z.infer<
413
+ typeof WorkspaceInstructionPolicyOnboardingProposalListQuery
414
+ >;
415
+
416
+ export const WorkspaceInstructionPolicyOnboardingProposalListResponse = z.object({
417
+ proposals: z.array(WorkspaceInstructionPolicyOnboardingProposal),
418
+ truncated: z.boolean(),
419
+ });
420
+ export type WorkspaceInstructionPolicyOnboardingProposalListResponse = z.infer<
421
+ typeof WorkspaceInstructionPolicyOnboardingProposalListResponse
422
+ >;
423
+
424
+ export const WorkspaceInstructionPolicyOnboardingProposalContentErrorResponse = z.object({
425
+ code: z.enum([
426
+ "WORKSPACE_INSTRUCTION_POLICY_ONBOARDING_PROPOSAL_EMPTY",
427
+ "WORKSPACE_INSTRUCTION_POLICY_ONBOARDING_PROPOSAL_OVERSIZED",
428
+ ]),
429
+ message: z.string(),
430
+ maxChars: z.number().int().positive(),
431
+ });
432
+ export type WorkspaceInstructionPolicyOnboardingProposalContentErrorResponse = z.infer<
433
+ typeof WorkspaceInstructionPolicyOnboardingProposalContentErrorResponse
434
+ >;
435
+
436
+ export const WorkspaceInstructionPolicyOnboardingProposalStaleResponse = z.object({
437
+ code: z.literal("WORKSPACE_INSTRUCTION_POLICY_ONBOARDING_PROPOSAL_STALE"),
438
+ message: z.string(),
439
+ currentHead: WorkspaceInstructionPolicyHead.nullable(),
440
+ });
441
+ export type WorkspaceInstructionPolicyOnboardingProposalStaleResponse = z.infer<
442
+ typeof WorkspaceInstructionPolicyOnboardingProposalStaleResponse
443
+ >;
444
+
445
+ export const WorkspaceInstructionPolicyOnboardingProposalConflictResponse = z.object({
446
+ code: z.literal("WORKSPACE_INSTRUCTION_POLICY_ONBOARDING_PROPOSAL_CONFLICT"),
447
+ message: z.string(),
448
+ existingProposalId: z.string().uuid(),
449
+ existingDraftRevisionId: z.string().uuid(),
450
+ });
451
+ export type WorkspaceInstructionPolicyOnboardingProposalConflictResponse = z.infer<
452
+ typeof WorkspaceInstructionPolicyOnboardingProposalConflictResponse
453
+ >;