@amerged/ohmyhost-mcp 0.1.28 → 0.1.30

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 (39) hide show
  1. package/README.md +1 -1
  2. package/THIRD_PARTY_NOTICES.md +1419 -0
  3. package/dist/{chunk-GIP4M4CK.js → chunk-MVT76LJ5.js} +92 -28
  4. package/dist/index.js +1 -1
  5. package/dist/stdio-main.js +24153 -2354
  6. package/package.json +1 -1
  7. package/src/apps/mcp/package.json +1 -1
  8. package/src/apps/mcp/src/local-client.ts +12 -2
  9. package/src/apps/mcp/src/local-server.ts +333 -4
  10. package/src/apps/product-cli/package.json +4 -2
  11. package/src/apps/product-cli/src/cli.ts +312 -2
  12. package/src/apps/product-cli/src/command.ts +261 -0
  13. package/src/apps/product-cli/src/composition.ts +74 -4
  14. package/src/apps/product-cli/src/index.ts +6 -0
  15. package/src/apps/product-cli/src/product-api.ts +5 -0
  16. package/src/apps/product-cli/src/project-link-store.ts +92 -1
  17. package/src/apps/product-cli/src/repository-init.ts +2 -2
  18. package/src/apps/product-cli/src/runtime-contract.ts +34 -1
  19. package/src/apps/product-cli/src/source-managed-client.ts +189 -0
  20. package/src/apps/product-cli/src/source-publication-store.ts +563 -0
  21. package/src/apps/product-cli/src/source-publisher.ts +195 -0
  22. package/src/apps/product-cli/src/source-workspace.ts +552 -0
  23. package/src/packages/agent-skills/src/generated-skill-resources.ts +43 -15
  24. package/src/packages/contracts/package.json +10 -0
  25. package/src/packages/contracts/src/database-migration-admission.ts +65 -125
  26. package/src/packages/contracts/src/database-migration-errors.ts +14 -0
  27. package/src/packages/contracts/src/database-migration-lexical.ts +180 -0
  28. package/src/packages/contracts/src/database-migration-policies.ts +150 -0
  29. package/src/packages/contracts/src/framework-admission.ts +1 -1
  30. package/src/packages/contracts/src/framework-build-script.mjs +1 -2
  31. package/src/packages/contracts/src/managed-sources.ts +582 -0
  32. package/src/packages/contracts/src/mcp-source-codec.ts +150 -0
  33. package/src/packages/contracts/src/operation-failure.ts +22 -6
  34. package/src/packages/contracts/src/problem-policy.ts +61 -14
  35. package/src/packages/sdk-ts/package.json +1 -1
  36. package/src/packages/sdk-ts/src/generated/index.ts +92 -0
  37. package/src/packages/sdk-ts/src/generated/sdk.gen.ts +541 -0
  38. package/src/packages/sdk-ts/src/generated/types.gen.ts +911 -4
  39. package/src/packages/workos-auth-contracts/src/tokens.ts +61 -4
@@ -0,0 +1,582 @@
1
+ import { publicOperationFailure } from "./operation-failure.js";
2
+
3
+ /** Canonical, credential-free contracts shared by REST, CLI and both MCP transports. */
4
+ export const MANAGED_SOURCE_LIMITS = Object.freeze({
5
+ fileBytes: 2 * 1024 * 1024,
6
+ uploadBytes: 2 * 1024 * 1024,
7
+ treeBytes: 8 * 1024 * 1024,
8
+ files: 2000,
9
+ });
10
+
11
+ export interface ManagedProjectSource {
12
+ readonly provider: "managed";
13
+ readonly source_connection_id: string;
14
+ readonly source_generation: number;
15
+ readonly namespace: string;
16
+ readonly repository_name: string;
17
+ readonly branch: "main";
18
+ readonly current_commit_sha: string | null;
19
+ readonly status: "pending" | "ready" | "failed" | "revoked";
20
+ readonly linked_at: string;
21
+ readonly updated_at: string;
22
+ readonly initialization_operation_id?: string;
23
+ readonly initialization_error_code?: string;
24
+ }
25
+
26
+ /** Stable released GitHub projection used by existing clients and project status. */
27
+ export interface GithubProjectSource {
28
+ readonly provider: "github";
29
+ readonly installation_id: string;
30
+ readonly repository_full_name: string;
31
+ readonly status: "pending" | "ready" | "failed" | "revoked";
32
+ readonly linked_at: string;
33
+ readonly updated_at: string;
34
+ readonly failure_summary?: string;
35
+ }
36
+
37
+ /** Requested explicitly with GET source?include_binding=true; never inferred from missing fields. */
38
+ export interface GithubSourceBinding extends GithubProjectSource {
39
+ readonly source_connection_id: string;
40
+ readonly source_generation: number;
41
+ }
42
+
43
+ export type ProjectSource = GithubProjectSource | ManagedProjectSource;
44
+ export type ProjectSourceBinding = GithubSourceBinding | ManagedProjectSource;
45
+
46
+ export function assertGithubSourceResponse(kind: "legacy" | "binding", value: unknown): void {
47
+ const body = record(value);
48
+ exact(body, [
49
+ "provider",
50
+ "installation_id",
51
+ "repository_full_name",
52
+ "status",
53
+ "linked_at",
54
+ "updated_at",
55
+ ...(kind === "binding" ? ["source_connection_id", "source_generation"] : []),
56
+ ...("failure_summary" in body ? ["failure_summary"] : []),
57
+ ]);
58
+ if (
59
+ body["provider"] !== "github" ||
60
+ typeof body["installation_id"] !== "string" ||
61
+ !/^[1-9][0-9]{0,19}$/u.test(body["installation_id"]) ||
62
+ typeof body["repository_full_name"] !== "string" ||
63
+ body["repository_full_name"].length < 3 ||
64
+ body["repository_full_name"].length > 201 ||
65
+ !/^[^/]+\/[^/]+$/u.test(body["repository_full_name"]) ||
66
+ typeof body["status"] !== "string" ||
67
+ !["pending", "ready", "failed", "revoked"].includes(body["status"])
68
+ )
69
+ invalid();
70
+ timestamp(body["linked_at"]);
71
+ timestamp(body["updated_at"]);
72
+ if (
73
+ "failure_summary" in body &&
74
+ (typeof body["failure_summary"] !== "string" ||
75
+ body["failure_summary"].length < 1 ||
76
+ body["failure_summary"].length > 512)
77
+ )
78
+ invalid();
79
+ if (kind === "binding") {
80
+ ulid(body["source_connection_id"]);
81
+ generation(body["source_generation"]);
82
+ if (Number(body["source_generation"]) < 1) invalid();
83
+ }
84
+ }
85
+
86
+ export interface SourceManifestFile {
87
+ readonly path: string;
88
+ readonly sha256: string;
89
+ readonly byte_length: number;
90
+ readonly executable: boolean;
91
+ }
92
+
93
+ export interface SourceChange {
94
+ readonly path: string;
95
+ /** null deletes a file; canonical base64 replaces or creates it. */
96
+ readonly content_base64: string | null;
97
+ readonly executable: boolean;
98
+ }
99
+
100
+ export interface ManagedSourceWrite {
101
+ readonly expected_source_generation: number;
102
+ readonly expected_commit_sha: string | null;
103
+ readonly message: string;
104
+ }
105
+
106
+ export interface ManagedSourceUploadRequest extends ManagedSourceWrite {
107
+ readonly mode: "initialize" | "commit" | "switch";
108
+ readonly expected_source_connection_id: string | null;
109
+ }
110
+
111
+ export interface ManagedSourceChangesRequest extends ManagedSourceWrite {
112
+ readonly changes: readonly SourceChange[];
113
+ }
114
+
115
+ export interface ManagedSourceRestoreRequest extends ManagedSourceWrite {
116
+ readonly restore_commit_sha: string;
117
+ }
118
+
119
+ export interface ManagedSourceInitializeRequest {
120
+ readonly template: "vite-react" | "empty";
121
+ readonly expected_source_generation: number;
122
+ }
123
+
124
+ export interface ManagedSourceBlobRequest {
125
+ readonly path: string;
126
+ readonly content_base64: string;
127
+ readonly sha256: string;
128
+ readonly executable: boolean;
129
+ }
130
+
131
+ export interface ManagedSourceFinalizeRequest {
132
+ readonly files: readonly SourceManifestFile[];
133
+ readonly expected_source_generation: number;
134
+ }
135
+
136
+ export interface ManagedSourceSwitchRequest extends ManagedSourceFinalizeRequest {
137
+ readonly upload_operation_id: string;
138
+ readonly expected_source_connection_id: string;
139
+ }
140
+
141
+ export interface ManagedSourceFile extends SourceManifestFile {
142
+ readonly content_base64: string;
143
+ }
144
+
145
+ export interface ManagedSourceFiles {
146
+ readonly commit_sha: string;
147
+ readonly files: readonly SourceManifestFile[];
148
+ }
149
+
150
+ export interface ManagedSourceFileResponse {
151
+ readonly commit_sha: string;
152
+ readonly file: ManagedSourceFile;
153
+ }
154
+
155
+ export interface ManagedSourceVersion {
156
+ readonly commit_sha: string;
157
+ readonly parent_commit_sha: string | null;
158
+ readonly message: string;
159
+ readonly created_at: string;
160
+ }
161
+
162
+ export interface ManagedSourceVersions {
163
+ readonly versions: readonly ManagedSourceVersion[];
164
+ readonly next_commit_sha: string | null;
165
+ }
166
+
167
+ export interface ManagedSourceDiff {
168
+ readonly from_commit_sha: string;
169
+ readonly to_commit_sha: string;
170
+ readonly changes: readonly {
171
+ readonly path: string;
172
+ readonly change: "added" | "modified" | "deleted";
173
+ readonly before_sha256: string | null;
174
+ readonly after_sha256: string | null;
175
+ readonly before_executable: boolean | null;
176
+ readonly after_executable: boolean | null;
177
+ }[];
178
+ }
179
+
180
+ export interface ManagedSourceUploadReceipt {
181
+ readonly operation_id: string;
182
+ readonly state: "staging" | "sealed" | "committed" | "failed";
183
+ readonly expected_source_generation: number;
184
+ readonly expected_commit_sha: string | null;
185
+ readonly commit_sha: string | null;
186
+ readonly expires_at: string;
187
+ }
188
+
189
+ export function isManagedSourcePath(value: unknown): value is string {
190
+ return (
191
+ typeof value === "string" &&
192
+ value.length > 0 &&
193
+ value.length <= 240 &&
194
+ !/[^\x20-\x7e]/u.test(value) &&
195
+ !/[\p{Cc}\\]/u.test(value) &&
196
+ !value.startsWith("/") &&
197
+ !/^[a-z]:/iu.test(value) &&
198
+ managedSourceTarPath(value) &&
199
+ value
200
+ .split("/")
201
+ .every(
202
+ (segment) =>
203
+ segment !== "" &&
204
+ segment !== "." &&
205
+ segment !== ".." &&
206
+ ![
207
+ ".git",
208
+ ".ohmyhost",
209
+ ".aws",
210
+ ".ssh",
211
+ ".gnupg",
212
+ ".kube",
213
+ ".credentials",
214
+ ".git-credentials",
215
+ ".npmrc",
216
+ ".netrc",
217
+ ".pypirc",
218
+ ".dev.vars",
219
+ ].includes(segment.toLowerCase()) &&
220
+ !(
221
+ segment.toLowerCase().startsWith(".env") &&
222
+ (segment.toLowerCase() === ".env" || segment.toLowerCase().startsWith(".env.")) &&
223
+ segment.toLowerCase() !== ".env.example"
224
+ ) &&
225
+ !segment.toLowerCase().startsWith(".dev.vars.") &&
226
+ !/^(?:id_(?:rsa|dsa|ecdsa|ed25519)(?:\.|$)|service[-_]account(?:\.|$))/iu.test(segment) &&
227
+ !/\.(?:pem|key|p12|pfx|jks|keystore)$/iu.test(segment),
228
+ )
229
+ );
230
+ }
231
+
232
+ /** Matches the existing strict USTAR build inspector, including its source/ archive root. */
233
+ function managedSourceTarPath(value: string): boolean {
234
+ const path = `source/${value}`;
235
+ if (path.length <= 100) return true;
236
+ for (let index = path.lastIndexOf("/"); index > 0; index = path.lastIndexOf("/", index - 1)) {
237
+ if (index <= 155 && path.length - index - 1 > 0 && path.length - index - 1 <= 100) return true;
238
+ }
239
+ return false;
240
+ }
241
+
242
+ export function parseManagedSourceRequest(
243
+ kind: "initialize",
244
+ value: unknown,
245
+ ): ManagedSourceInitializeRequest;
246
+ export function parseManagedSourceRequest(
247
+ kind: "upload",
248
+ value: unknown,
249
+ ): ManagedSourceUploadRequest;
250
+ export function parseManagedSourceRequest(
251
+ kind: "changes",
252
+ value: unknown,
253
+ ): ManagedSourceChangesRequest;
254
+ export function parseManagedSourceRequest(
255
+ kind: "restore",
256
+ value: unknown,
257
+ ): ManagedSourceRestoreRequest;
258
+ export function parseManagedSourceRequest(kind: "blob", value: unknown): ManagedSourceBlobRequest;
259
+ export function parseManagedSourceRequest(
260
+ kind: "finalize",
261
+ value: unknown,
262
+ ): ManagedSourceFinalizeRequest;
263
+ export function parseManagedSourceRequest(
264
+ kind: "switch",
265
+ value: unknown,
266
+ ): ManagedSourceSwitchRequest;
267
+ export function parseManagedSourceRequest(
268
+ kind: "initialize" | "upload" | "changes" | "restore" | "blob" | "finalize" | "switch",
269
+ value: unknown,
270
+ ):
271
+ | ManagedSourceInitializeRequest
272
+ | ManagedSourceUploadRequest
273
+ | ManagedSourceChangesRequest
274
+ | ManagedSourceRestoreRequest
275
+ | ManagedSourceBlobRequest
276
+ | ManagedSourceFinalizeRequest
277
+ | ManagedSourceSwitchRequest {
278
+ const body = record(value);
279
+ if (kind === "initialize") {
280
+ exact(body, ["template", "expected_source_generation"]);
281
+ generation(body["expected_source_generation"]);
282
+ if (body["template"] !== "empty" && body["template"] !== "vite-react") invalid();
283
+ } else if (kind === "blob") {
284
+ exact(body, ["path", "content_base64", "sha256", "executable"]);
285
+ path(body["path"]);
286
+ base64(body["content_base64"]);
287
+ sha256(body["sha256"]);
288
+ if (typeof body["executable"] !== "boolean") invalid();
289
+ } else if (kind === "finalize" || kind === "switch") {
290
+ exact(
291
+ body,
292
+ kind === "switch"
293
+ ? [
294
+ "files",
295
+ "expected_source_generation",
296
+ "upload_operation_id",
297
+ "expected_source_connection_id",
298
+ ]
299
+ : ["files", "expected_source_generation"],
300
+ );
301
+ manifest(body["files"]);
302
+ generation(body["expected_source_generation"]);
303
+ if (kind === "switch") {
304
+ ulid(body["upload_operation_id"]);
305
+ ulid(body["expected_source_connection_id"]);
306
+ }
307
+ } else {
308
+ const extra =
309
+ kind === "upload"
310
+ ? ["mode", "expected_source_connection_id"]
311
+ : kind === "changes"
312
+ ? ["changes"]
313
+ : ["restore_commit_sha"];
314
+ exact(body, ["expected_source_generation", "expected_commit_sha", "message", ...extra]);
315
+ generation(body["expected_source_generation"]);
316
+ commit(body["expected_commit_sha"], true);
317
+ if (
318
+ typeof body["message"] !== "string" ||
319
+ body["message"].trim() !== body["message"] ||
320
+ body["message"].length < 1 ||
321
+ body["message"].length > 200 ||
322
+ /\p{Cc}/u.test(body["message"])
323
+ )
324
+ invalid();
325
+ if (kind === "upload") {
326
+ if (!["initialize", "commit", "switch"].includes(String(body["mode"]))) invalid();
327
+ if (body["expected_source_connection_id"] !== null)
328
+ ulid(body["expected_source_connection_id"]);
329
+ if ((body["mode"] === "initialize") !== (body["expected_source_connection_id"] === null))
330
+ invalid();
331
+ if (body["mode"] !== "commit" && body["expected_commit_sha"] !== null) invalid();
332
+ } else if (kind === "restore") commit(body["restore_commit_sha"]);
333
+ else {
334
+ const changes = body["changes"];
335
+ if (
336
+ !Array.isArray(changes) ||
337
+ changes.length < 1 ||
338
+ changes.length > MANAGED_SOURCE_LIMITS.files
339
+ )
340
+ invalid();
341
+ let total = 0;
342
+ const paths = new Set<string>();
343
+ for (const change of changes) {
344
+ const entry = record(change);
345
+ exact(entry, ["path", "content_base64", "executable"]);
346
+ path(entry["path"]);
347
+ if (typeof entry["executable"] !== "boolean") invalid();
348
+ if (paths.has(String(entry["path"]))) invalid();
349
+ paths.add(String(entry["path"]));
350
+ if (entry["content_base64"] !== null) total += base64(entry["content_base64"]);
351
+ }
352
+ if (total > MANAGED_SOURCE_LIMITS.uploadBytes) invalid();
353
+ }
354
+ }
355
+ return body as unknown as ReturnType<typeof parseManagedSourceRequest>;
356
+ }
357
+
358
+ export function assertManagedSourceResponse(
359
+ kind: "source" | "files" | "versions" | "diff" | "upload" | "blob",
360
+ value: unknown,
361
+ ): void {
362
+ const body = record(value);
363
+ if (kind === "source") {
364
+ exact(body, [
365
+ "provider",
366
+ "source_connection_id",
367
+ "source_generation",
368
+ "namespace",
369
+ "repository_name",
370
+ "branch",
371
+ "current_commit_sha",
372
+ "status",
373
+ "linked_at",
374
+ "updated_at",
375
+ ...("initialization_operation_id" in body ? ["initialization_operation_id"] : []),
376
+ ...("initialization_error_code" in body ? ["initialization_error_code"] : []),
377
+ ]);
378
+ if (body["provider"] !== "managed" || body["branch"] !== "main") invalid();
379
+ ulid(body["source_connection_id"]);
380
+ generation(body["source_generation"]);
381
+ for (const name of ["namespace", "repository_name"])
382
+ if (typeof body[name] !== "string" || !/^[a-z0-9][a-z0-9_-]{0,127}$/u.test(body[name]))
383
+ invalid();
384
+ commit(body["current_commit_sha"], true);
385
+ if (!["pending", "ready", "failed", "revoked"].includes(String(body["status"]))) invalid();
386
+ timestamp(body["linked_at"]);
387
+ timestamp(body["updated_at"]);
388
+ if ("initialization_operation_id" in body) ulid(body["initialization_operation_id"]);
389
+ if (
390
+ "initialization_error_code" in body &&
391
+ (typeof body["initialization_error_code"] !== "string" ||
392
+ publicOperationFailure(body["initialization_error_code"]).code !==
393
+ body["initialization_error_code"])
394
+ )
395
+ invalid();
396
+ if (
397
+ ("initialization_operation_id" in body || "initialization_error_code" in body) &&
398
+ body["status"] !== "pending" &&
399
+ body["status"] !== "failed"
400
+ )
401
+ invalid();
402
+ } else if (kind === "files") {
403
+ commit(body["commit_sha"]);
404
+ if ("file" in body) {
405
+ exact(body, ["commit_sha", "file"]);
406
+ const file = record(body["file"]);
407
+ exact(file, ["path", "sha256", "byte_length", "executable", "content_base64"]);
408
+ manifest([
409
+ {
410
+ path: file["path"],
411
+ sha256: file["sha256"],
412
+ byte_length: file["byte_length"],
413
+ executable: file["executable"],
414
+ },
415
+ ]);
416
+ if (base64(file["content_base64"]) !== file["byte_length"]) invalid();
417
+ } else {
418
+ exact(body, ["commit_sha", "files"]);
419
+ manifest(body["files"]);
420
+ }
421
+ } else if (kind === "versions") {
422
+ exact(body, ["versions", "next_commit_sha"]);
423
+ commit(body["next_commit_sha"], true);
424
+ if (!Array.isArray(body["versions"]) || body["versions"].length > 100) invalid();
425
+ for (const version of body["versions"]) {
426
+ const entry = record(version);
427
+ exact(entry, ["commit_sha", "parent_commit_sha", "message", "created_at"]);
428
+ commit(entry["commit_sha"]);
429
+ commit(entry["parent_commit_sha"], true);
430
+ if (typeof entry["message"] !== "string" || entry["message"].length > 20000) invalid();
431
+ timestamp(entry["created_at"]);
432
+ }
433
+ } else if (kind === "diff") {
434
+ exact(body, ["from_commit_sha", "to_commit_sha", "changes"]);
435
+ commit(body["from_commit_sha"]);
436
+ commit(body["to_commit_sha"]);
437
+ if (!Array.isArray(body["changes"]) || body["changes"].length > MANAGED_SOURCE_LIMITS.files * 2)
438
+ invalid();
439
+ for (const change of body["changes"]) {
440
+ const entry = record(change);
441
+ exact(entry, [
442
+ "path",
443
+ "change",
444
+ "before_sha256",
445
+ "after_sha256",
446
+ "before_executable",
447
+ "after_executable",
448
+ ]);
449
+ path(entry["path"]);
450
+ if (
451
+ ![true, false, null].includes(entry["before_executable"] as boolean | null) ||
452
+ ![true, false, null].includes(entry["after_executable"] as boolean | null)
453
+ )
454
+ invalid();
455
+ if (
456
+ (entry["before_sha256"] === null) !== (entry["before_executable"] === null) ||
457
+ (entry["after_sha256"] === null) !== (entry["after_executable"] === null)
458
+ )
459
+ invalid();
460
+ if (!["added", "modified", "deleted"].includes(String(entry["change"]))) invalid();
461
+ if (entry["before_sha256"] !== null) sha256(entry["before_sha256"]);
462
+ if (entry["after_sha256"] !== null) sha256(entry["after_sha256"]);
463
+ if (
464
+ entry["change"] === "added" &&
465
+ (entry["before_sha256"] !== null || entry["after_sha256"] === null)
466
+ )
467
+ invalid();
468
+ if (
469
+ entry["change"] === "deleted" &&
470
+ (entry["before_sha256"] === null || entry["after_sha256"] !== null)
471
+ )
472
+ invalid();
473
+ if (
474
+ entry["change"] === "modified" &&
475
+ (entry["before_sha256"] === null ||
476
+ entry["after_sha256"] === null ||
477
+ (entry["before_sha256"] === entry["after_sha256"] &&
478
+ entry["before_executable"] === entry["after_executable"]))
479
+ )
480
+ invalid();
481
+ }
482
+ } else if (kind === "blob") {
483
+ exact(body, ["path", "sha256", "byte_length", "executable"]);
484
+ manifest([body]);
485
+ } else {
486
+ exact(body, [
487
+ "operation_id",
488
+ "state",
489
+ "expected_source_generation",
490
+ "expected_commit_sha",
491
+ "commit_sha",
492
+ "expires_at",
493
+ ]);
494
+ ulid(body["operation_id"]);
495
+ if (!["staging", "sealed", "committed", "failed"].includes(String(body["state"]))) invalid();
496
+ generation(body["expected_source_generation"]);
497
+ commit(body["expected_commit_sha"], true);
498
+ commit(body["commit_sha"], true);
499
+ timestamp(body["expires_at"]);
500
+ if (body["state"] === "committed" && body["commit_sha"] === null) invalid();
501
+ }
502
+ }
503
+
504
+ function manifest(value: unknown): void {
505
+ if (!Array.isArray(value) || value.length > MANAGED_SOURCE_LIMITS.files) invalid();
506
+ let total = 0;
507
+ const seen = new Set<string>();
508
+ for (const file of value) {
509
+ const entry = record(file);
510
+ exact(entry, ["path", "sha256", "byte_length", "executable"]);
511
+ path(entry["path"]);
512
+ sha256(entry["sha256"]);
513
+ if (typeof entry["executable"] !== "boolean") invalid();
514
+ if (
515
+ !Number.isSafeInteger(entry["byte_length"]) ||
516
+ Number(entry["byte_length"]) < 0 ||
517
+ Number(entry["byte_length"]) > MANAGED_SOURCE_LIMITS.fileBytes ||
518
+ seen.has(String(entry["path"]))
519
+ )
520
+ invalid();
521
+ seen.add(String(entry["path"]));
522
+ total += Number(entry["byte_length"]);
523
+ }
524
+ if (total > MANAGED_SOURCE_LIMITS.treeBytes) invalid();
525
+ }
526
+
527
+ function base64(value: unknown): number {
528
+ if (
529
+ typeof value !== "string" ||
530
+ value.length > Math.ceil(MANAGED_SOURCE_LIMITS.fileBytes / 3) * 4 ||
531
+ !/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/u.test(value) ||
532
+ (value.endsWith("==") && !/[AQgw]==$/u.test(value)) ||
533
+ (!value.endsWith("==") && value.endsWith("=") && !/[AEIMQUYcgkosw048]=$/u.test(value))
534
+ )
535
+ invalid();
536
+ const size = (value.length / 4) * 3 - (value.endsWith("==") ? 2 : value.endsWith("=") ? 1 : 0);
537
+ if (size > MANAGED_SOURCE_LIMITS.fileBytes) invalid();
538
+ return size;
539
+ }
540
+
541
+ function record(value: unknown): Record<string, unknown> {
542
+ if (typeof value !== "object" || value === null || Array.isArray(value)) invalid();
543
+ return value as Record<string, unknown>;
544
+ }
545
+
546
+ function exact(value: Record<string, unknown>, keys: readonly string[]): void {
547
+ if (Object.keys(value).sort().join(",") !== [...keys].sort().join(",")) invalid();
548
+ }
549
+
550
+ function path(value: unknown): void {
551
+ if (!isManagedSourcePath(value)) invalid();
552
+ }
553
+
554
+ function generation(value: unknown): void {
555
+ if (!Number.isSafeInteger(value) || Number(value) < 0 || Number(value) > 2147483646) invalid();
556
+ }
557
+
558
+ function ulid(value: unknown): void {
559
+ if (typeof value !== "string" || !/^[0-7][0-9A-HJKMNP-TV-Z]{25}$/u.test(value)) invalid();
560
+ }
561
+
562
+ function commit(value: unknown, nullable = false): void {
563
+ if (nullable && value === null) return;
564
+ if (typeof value !== "string" || !/^[a-f0-9]{40}$/u.test(value)) invalid();
565
+ }
566
+
567
+ function sha256(value: unknown): void {
568
+ if (typeof value !== "string" || !/^sha256:[a-f0-9]{64}$/u.test(value)) invalid();
569
+ }
570
+
571
+ function timestamp(value: unknown): void {
572
+ if (
573
+ typeof value !== "string" ||
574
+ !Number.isFinite(Date.parse(value)) ||
575
+ new Date(value).toISOString() !== value
576
+ )
577
+ invalid();
578
+ }
579
+
580
+ function invalid(): never {
581
+ throw new TypeError("Managed source contract is invalid");
582
+ }