@opengeni/contracts 0.23.0 → 0.27.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.
@@ -0,0 +1,171 @@
1
+ import { z } from "zod";
2
+
3
+ export const WORKSPACE_ARTIFACT_HTML_MAX_UTF8_BYTES = 512 * 1024;
4
+ export const WORKSPACE_ARTIFACT_TITLE_MAX_CHARS = 120;
5
+ export const WORKSPACE_ARTIFACT_DESCRIPTION_MAX_CHARS = 2_000;
6
+ export const WORKSPACE_ARTIFACT_LIST_MAX = 100;
7
+ export const WORKSPACE_ARTIFACT_LIST_DEFAULT = 50;
8
+ export const WORKSPACE_ARTIFACT_CURSOR_MAX_CHARS = 512;
9
+
10
+ const encoder = new TextEncoder();
11
+ const sha256 = z.string().regex(/^[0-9a-f]{64}$/);
12
+
13
+ export const WorkspaceArtifactSlug = z
14
+ .string()
15
+ .trim()
16
+ .min(1)
17
+ .max(96)
18
+ .regex(/^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/);
19
+ export type WorkspaceArtifactSlug = z.infer<typeof WorkspaceArtifactSlug>;
20
+
21
+ export const WorkspaceArtifactStatus = z.enum(["active", "archived"]);
22
+ export type WorkspaceArtifactStatus = z.infer<typeof WorkspaceArtifactStatus>;
23
+
24
+ export const WorkspaceArtifactVersion = z.object({
25
+ id: z.string().uuid(),
26
+ accountId: z.string().uuid(),
27
+ workspaceId: z.string().uuid(),
28
+ artifactId: z.string().uuid(),
29
+ revision: z.number().int().positive(),
30
+ contentType: z.literal("text/html"),
31
+ contentSha256: sha256,
32
+ sizeBytes: z.number().int().positive().max(WORKSPACE_ARTIFACT_HTML_MAX_UTF8_BYTES),
33
+ sourceSessionId: z.string().uuid().nullable(),
34
+ sourceTurnId: z.string().uuid().nullable(),
35
+ sourceAttemptId: z.string().uuid().nullable(),
36
+ sourceExecutionGeneration: z.number().int().positive().nullable(),
37
+ createdBySubjectId: z.string().min(1).max(1024),
38
+ createdAt: z.string().datetime({ offset: true }),
39
+ });
40
+ export type WorkspaceArtifactVersion = z.infer<typeof WorkspaceArtifactVersion>;
41
+
42
+ export const WorkspaceArtifact = z.object({
43
+ id: z.string().uuid(),
44
+ accountId: z.string().uuid(),
45
+ workspaceId: z.string().uuid(),
46
+ slug: WorkspaceArtifactSlug,
47
+ title: z.string().trim().min(1).max(WORKSPACE_ARTIFACT_TITLE_MAX_CHARS),
48
+ description: z.string().max(WORKSPACE_ARTIFACT_DESCRIPTION_MAX_CHARS).nullable(),
49
+ status: WorkspaceArtifactStatus,
50
+ currentVersion: WorkspaceArtifactVersion.nullable(),
51
+ createdBySubjectId: z.string().min(1).max(1024),
52
+ createdAt: z.string().datetime({ offset: true }),
53
+ updatedAt: z.string().datetime({ offset: true }),
54
+ });
55
+ export type WorkspaceArtifact = z.infer<typeof WorkspaceArtifact>;
56
+
57
+ export const WorkspaceArtifactEventType = z.enum(["published", "rolled_back"]);
58
+ export type WorkspaceArtifactEventType = z.infer<typeof WorkspaceArtifactEventType>;
59
+
60
+ export const WorkspaceArtifactEvent = z.object({
61
+ id: z.string().uuid(),
62
+ accountId: z.string().uuid(),
63
+ workspaceId: z.string().uuid(),
64
+ artifactId: z.string().uuid(),
65
+ type: WorkspaceArtifactEventType,
66
+ fromVersionId: z.string().uuid().nullable(),
67
+ toVersionId: z.string().uuid(),
68
+ sourceSessionId: z.string().uuid().nullable(),
69
+ sourceTurnId: z.string().uuid().nullable(),
70
+ sourceAttemptId: z.string().uuid().nullable(),
71
+ sourceExecutionGeneration: z.number().int().positive().nullable(),
72
+ actorSubjectId: z.string().min(1).max(1024),
73
+ reason: z.string().min(1).max(4096),
74
+ createdAt: z.string().datetime({ offset: true }),
75
+ });
76
+ export type WorkspaceArtifactEvent = z.infer<typeof WorkspaceArtifactEvent>;
77
+
78
+ export const WorkspaceArtifactListQuery = z.object({
79
+ limit: z.coerce
80
+ .number()
81
+ .int()
82
+ .positive()
83
+ .max(WORKSPACE_ARTIFACT_LIST_MAX)
84
+ .default(WORKSPACE_ARTIFACT_LIST_DEFAULT),
85
+ cursor: z.string().min(1).max(WORKSPACE_ARTIFACT_CURSOR_MAX_CHARS).optional(),
86
+ });
87
+ export type WorkspaceArtifactListQuery = z.infer<typeof WorkspaceArtifactListQuery>;
88
+
89
+ export const WorkspaceArtifactListResponse = z.object({
90
+ artifacts: z.array(WorkspaceArtifact).max(WORKSPACE_ARTIFACT_LIST_MAX),
91
+ nextCursor: z.string().max(WORKSPACE_ARTIFACT_CURSOR_MAX_CHARS).nullable(),
92
+ truncated: z.boolean(),
93
+ });
94
+ export type WorkspaceArtifactListResponse = z.infer<typeof WorkspaceArtifactListResponse>;
95
+
96
+ export const WorkspaceArtifactDetailResponse = z.object({
97
+ artifact: WorkspaceArtifact,
98
+ versions: z.array(WorkspaceArtifactVersion).max(WORKSPACE_ARTIFACT_LIST_MAX),
99
+ events: z.array(WorkspaceArtifactEvent).max(WORKSPACE_ARTIFACT_LIST_MAX),
100
+ versionsTruncated: z.boolean(),
101
+ eventsTruncated: z.boolean(),
102
+ });
103
+ export type WorkspaceArtifactDetailResponse = z.infer<typeof WorkspaceArtifactDetailResponse>;
104
+
105
+ export const WorkspaceArtifactHtml = z
106
+ .string()
107
+ .min(1)
108
+ .max(WORKSPACE_ARTIFACT_HTML_MAX_UTF8_BYTES)
109
+ .superRefine((value, ctx) => {
110
+ if (encoder.encode(value).byteLength > WORKSPACE_ARTIFACT_HTML_MAX_UTF8_BYTES) {
111
+ ctx.addIssue({
112
+ code: "custom",
113
+ message: `artifact HTML exceeds ${WORKSPACE_ARTIFACT_HTML_MAX_UTF8_BYTES} UTF-8 bytes`,
114
+ });
115
+ }
116
+ });
117
+
118
+ export const CreateWorkspaceArtifactRequest = z.object({
119
+ slug: WorkspaceArtifactSlug.optional(),
120
+ title: z.string().trim().min(1).max(WORKSPACE_ARTIFACT_TITLE_MAX_CHARS),
121
+ description: z.string().max(WORKSPACE_ARTIFACT_DESCRIPTION_MAX_CHARS).nullable().optional(),
122
+ html: WorkspaceArtifactHtml,
123
+ idempotencyKey: z.string().trim().min(1).max(200),
124
+ });
125
+ export type CreateWorkspaceArtifactRequest = z.infer<typeof CreateWorkspaceArtifactRequest>;
126
+
127
+ export const PublishWorkspaceArtifactVersionRequest = z.object({
128
+ title: z.string().trim().min(1).max(WORKSPACE_ARTIFACT_TITLE_MAX_CHARS).optional(),
129
+ description: z.string().max(WORKSPACE_ARTIFACT_DESCRIPTION_MAX_CHARS).nullable().optional(),
130
+ html: WorkspaceArtifactHtml,
131
+ expectedCurrentVersionId: z.string().uuid(),
132
+ idempotencyKey: z.string().trim().min(1).max(200),
133
+ });
134
+ export type PublishWorkspaceArtifactVersionRequest = z.infer<
135
+ typeof PublishWorkspaceArtifactVersionRequest
136
+ >;
137
+
138
+ export const RollbackWorkspaceArtifactRequest = z.object({
139
+ versionId: z.string().uuid(),
140
+ expectedCurrentVersionId: z.string().uuid(),
141
+ reason: z.string().trim().min(1).max(4096),
142
+ idempotencyKey: z.string().trim().min(1).max(200),
143
+ });
144
+ export type RollbackWorkspaceArtifactRequest = z.infer<typeof RollbackWorkspaceArtifactRequest>;
145
+
146
+ export const WorkspaceArtifactMutationResponse = z.object({
147
+ artifact: WorkspaceArtifact,
148
+ version: WorkspaceArtifactVersion,
149
+ event: WorkspaceArtifactEvent,
150
+ replayed: z.boolean(),
151
+ });
152
+ export type WorkspaceArtifactMutationResponse = z.infer<typeof WorkspaceArtifactMutationResponse>;
153
+
154
+ export const WorkspaceArtifactContentResponse = z.object({
155
+ artifactId: z.string().uuid(),
156
+ versionId: z.string().uuid(),
157
+ contentType: z.literal("text/html"),
158
+ contentSha256: sha256,
159
+ html: WorkspaceArtifactHtml,
160
+ });
161
+ export type WorkspaceArtifactContentResponse = z.infer<typeof WorkspaceArtifactContentResponse>;
162
+
163
+ export function normalizeWorkspaceArtifactSlug(value: string): string {
164
+ return value
165
+ .normalize("NFKD")
166
+ .toLowerCase()
167
+ .replace(/[^a-z0-9]+/g, "-")
168
+ .replace(/^-+|-+$/g, "")
169
+ .slice(0, 96)
170
+ .replace(/-+$/g, "");
171
+ }
@@ -0,0 +1,36 @@
1
+ export type ModalCheckpointProviderBinding = {
2
+ version: 1;
3
+ serverUrl: string;
4
+ workspaceName: string;
5
+ environment: string;
6
+ };
7
+
8
+ /**
9
+ * One canonical, non-secret identity for the Modal namespace that owns a
10
+ * checkpoint. The same bytes are used for uniqueness, durable storage, and
11
+ * destructive-call fencing.
12
+ */
13
+ export function canonicalModalCheckpointProviderBinding(
14
+ value: unknown,
15
+ ): { binding: ModalCheckpointProviderBinding; key: string } | null {
16
+ if (!value || typeof value !== "object") return null;
17
+ const candidate = value as Partial<ModalCheckpointProviderBinding>;
18
+ if (
19
+ candidate.version !== 1 ||
20
+ typeof candidate.serverUrl !== "string" ||
21
+ candidate.serverUrl.trim().length === 0 ||
22
+ typeof candidate.workspaceName !== "string" ||
23
+ candidate.workspaceName.trim().length === 0 ||
24
+ typeof candidate.environment !== "string"
25
+ ) {
26
+ return null;
27
+ }
28
+ const binding: ModalCheckpointProviderBinding = {
29
+ version: 1,
30
+ serverUrl: candidate.serverUrl,
31
+ workspaceName: candidate.workspaceName,
32
+ environment: candidate.environment,
33
+ };
34
+ const key = JSON.stringify(binding);
35
+ return key.length <= 1024 ? { binding, key } : null;
36
+ }
@@ -0,0 +1,101 @@
1
+ import { z } from "zod";
2
+
3
+ import { ConnectionMetadata } from "./index";
4
+
5
+ export const GOOGLE_DRIVE_PROVIDER_DOMAIN = "googleapis.com" as const;
6
+ export const GOOGLE_DRIVE_METADATA_READONLY_SCOPE =
7
+ "https://www.googleapis.com/auth/drive.metadata.readonly" as const;
8
+ export const GOOGLE_DRIVE_READONLY_SCOPE =
9
+ "https://www.googleapis.com/auth/drive.readonly" as const;
10
+ export const GOOGLE_DRIVE_CREDENTIAL_ROLE = "google_drive_metadata" as const;
11
+ export const GOOGLE_DRIVE_CREDENTIAL_LABEL = "Google Drive metadata browser" as const;
12
+
13
+ export const GoogleDriveTargetScope = z.enum(["user", "workspace", "organization"]);
14
+ export type GoogleDriveTargetScope = z.infer<typeof GoogleDriveTargetScope>;
15
+
16
+ export const GoogleDriveSyncCadence = z.enum(["manual", "hourly", "daily"]);
17
+ export type GoogleDriveSyncCadence = z.infer<typeof GoogleDriveSyncCadence>;
18
+
19
+ export const GoogleDriveReadPolicy = z.enum(["allow", "ask", "block"]);
20
+ export type GoogleDriveReadPolicy = z.infer<typeof GoogleDriveReadPolicy>;
21
+
22
+ export const GoogleDriveSelectedSource = z.object({
23
+ id: z.string().min(1).max(256),
24
+ name: z.string().min(1).max(1024),
25
+ mimeType: z.string().min(1).max(256),
26
+ driveId: z.string().min(1).max(256).nullable().default(null),
27
+ targetScope: GoogleDriveTargetScope,
28
+ syncCadence: GoogleDriveSyncCadence.default("hourly"),
29
+ readPolicy: GoogleDriveReadPolicy.default("allow"),
30
+ selectedAt: z.string().datetime({ offset: true }),
31
+ });
32
+ export type GoogleDriveSelectedSource = z.infer<typeof GoogleDriveSelectedSource>;
33
+
34
+ export const GoogleDriveConnectionMetadata = z
35
+ .object({
36
+ credentialRole: z.literal(GOOGLE_DRIVE_CREDENTIAL_ROLE),
37
+ credentialLabel: z.literal(GOOGLE_DRIVE_CREDENTIAL_LABEL),
38
+ googlePermissionId: z.string().min(1).max(256),
39
+ googleEmail: z.string().email().max(320),
40
+ googleDisplayName: z.string().min(1).max(512).nullable(),
41
+ verifiedAt: z.string().datetime({ offset: true }),
42
+ accessMode: z.enum(["metadata_readonly", "readonly"]),
43
+ selectedSources: z.array(GoogleDriveSelectedSource).max(100).optional(),
44
+ /** @deprecated Read `selectedSources`; retained while existing connections migrate. */
45
+ selectedSource: GoogleDriveSelectedSource.nullable().optional(),
46
+ })
47
+ .passthrough();
48
+ export type GoogleDriveConnectionMetadata = z.infer<typeof GoogleDriveConnectionMetadata>;
49
+
50
+ export const GoogleDriveOAuthStartRequest = z.object({
51
+ connectionId: z.string().uuid().optional(),
52
+ });
53
+ export type GoogleDriveOAuthStartRequest = z.infer<typeof GoogleDriveOAuthStartRequest>;
54
+
55
+ export const GoogleDriveOAuthStartResponse = z.object({
56
+ authorizationUrl: z.string().url(),
57
+ expiresAt: z.string().datetime({ offset: true }),
58
+ });
59
+ export type GoogleDriveOAuthStartResponse = z.infer<typeof GoogleDriveOAuthStartResponse>;
60
+
61
+ export const GoogleDriveBrowseItem = z.object({
62
+ id: z.string().min(1).max(256),
63
+ name: z.string().min(1).max(1024),
64
+ mimeType: z.string().min(1).max(256),
65
+ kind: z.enum(["folder", "file"]),
66
+ driveId: z.string().min(1).max(256).nullable(),
67
+ modifiedTime: z.string().datetime({ offset: true }).nullable(),
68
+ size: z.string().regex(/^\d+$/).nullable(),
69
+ webViewLink: z.string().url().nullable(),
70
+ });
71
+ export type GoogleDriveBrowseItem = z.infer<typeof GoogleDriveBrowseItem>;
72
+
73
+ export const GoogleDriveBrowseResponse = z.object({
74
+ connection: z.lazy(() => ConnectionMetadata),
75
+ parentId: z.string().min(1).max(256),
76
+ current: GoogleDriveBrowseItem.nullable(),
77
+ items: z.array(GoogleDriveBrowseItem),
78
+ nextPageToken: z.string().min(1).max(4096).nullable(),
79
+ incompleteSearch: z.boolean(),
80
+ });
81
+ export type GoogleDriveBrowseResponse = z.infer<typeof GoogleDriveBrowseResponse>;
82
+
83
+ export const SaveGoogleDriveSourceRequest = z.object({
84
+ sources: z
85
+ .array(
86
+ GoogleDriveBrowseItem.pick({
87
+ id: true,
88
+ name: true,
89
+ mimeType: true,
90
+ driveId: true,
91
+ }),
92
+ )
93
+ .max(100)
94
+ .refine((sources) => new Set(sources.map((source) => source.id)).size === sources.length, {
95
+ message: "Google Drive sources must be unique",
96
+ }),
97
+ targetScope: GoogleDriveTargetScope,
98
+ syncCadence: GoogleDriveSyncCadence.default("hourly"),
99
+ readPolicy: GoogleDriveReadPolicy.default("allow"),
100
+ });
101
+ export type SaveGoogleDriveSourceRequest = z.infer<typeof SaveGoogleDriveSourceRequest>;