@cat-factory/contracts 0.50.1 → 0.52.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.
@@ -254,62 +254,116 @@ export declare const environmentManifestSchema: v.ObjectSchema<{
254
254
  readonly providerConfig: v.OptionalSchema<v.RecordSchema<v.StringSchema<undefined>, v.UnknownSchema, undefined>, undefined>;
255
255
  }, undefined>;
256
256
  export type EnvironmentManifest = v.InferOutput<typeof environmentManifestSchema>;
257
- /** Resolved access creds for a provisioned env, as surfaced to a tester agent. */
258
- export declare const environmentAccessHandleSchema: v.ObjectSchema<{
259
- readonly scheme: v.PicklistSchema<["none", "bearer", "basic", "custom_header"], undefined>;
260
- readonly token: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
261
- readonly username: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
262
- readonly password: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
263
- readonly headerName: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
264
- readonly headerValue: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
265
- }, undefined>;
266
- export type EnvironmentAccessHandle = v.InferOutput<typeof environmentAccessHandleSchema>;
267
- /** A provisioned environment, as exposed to clients and downstream agents. */
268
- export declare const environmentHandleSchema: v.ObjectSchema<{
269
- readonly id: v.StringSchema<undefined>;
270
- readonly workspaceId: v.StringSchema<undefined>;
271
- readonly blockId: v.NullableSchema<v.StringSchema<undefined>, undefined>;
272
- readonly executionId: v.NullableSchema<v.StringSchema<undefined>, undefined>;
273
- readonly providerId: v.StringSchema<undefined>;
274
- readonly externalId: v.NullableSchema<v.StringSchema<undefined>, undefined>;
275
- readonly url: v.NullableSchema<v.StringSchema<undefined>, undefined>;
276
- readonly status: v.PicklistSchema<["provisioning", "ready", "failed", "expired", "tearing_down", "torn_down"], undefined>;
277
- /** Present only on the dedicated access endpoint / in agent context. */
278
- readonly access: v.OptionalSchema<v.ObjectSchema<{
279
- readonly scheme: v.PicklistSchema<["none", "bearer", "basic", "custom_header"], undefined>;
280
- readonly token: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
281
- readonly username: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
282
- readonly password: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
283
- readonly headerName: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
284
- readonly headerValue: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
285
- }, undefined>, undefined>;
286
- readonly createdAt: v.NumberSchema<undefined>;
287
- readonly expiresAt: v.NullableSchema<v.NumberSchema<undefined>, undefined>;
288
- readonly lastError: v.NullableSchema<v.StringSchema<undefined>, undefined>;
289
- }, undefined>;
290
- export type EnvironmentHandle = v.InferOutput<typeof environmentHandleSchema>;
291
- /** A workspace's provider binding, as exposed to clients (never secret values). */
292
- export declare const environmentConnectionSchema: v.ObjectSchema<{
293
- readonly providerId: v.StringSchema<undefined>;
294
- readonly label: v.StringSchema<undefined>;
295
- readonly baseUrl: v.StringSchema<undefined>;
296
- readonly connectedAt: v.NumberSchema<undefined>;
297
- /** Which secret keys are set (names only), so the UI can show completeness. */
298
- readonly secretKeys: v.ArraySchema<v.StringSchema<undefined>, undefined>;
257
+ /** The secret-bundle key the Kubernetes env backend reads the ServiceAccount token from. */
258
+ export declare const KUBERNETES_ENV_TOKEN_SECRET_KEY = "apiToken";
259
+ /**
260
+ * Where the per-PR manifests are read from. `colocated` reads them from the block's
261
+ * own repo at the PR head branch; `separate` reads them from a different repo (the
262
+ * Kubernetes definition often lives outside the service repo).
263
+ */
264
+ export declare const kubernetesManifestSourceSchema: v.VariantSchema<"type", [v.ObjectSchema<{
265
+ readonly type: v.LiteralSchema<"colocated", undefined>;
266
+ /** File or directory path within the PR repo (read at the PR head branch). */
267
+ readonly path: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 500, undefined>]>;
268
+ }, undefined>, v.ObjectSchema<{
269
+ readonly type: v.LiteralSchema<"separate", undefined>;
270
+ /** `owner/repo` of the manifests repo. */
271
+ readonly repo: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.RegexAction<string, "must be \"owner/repo\"">]>;
272
+ /** Branch/tag/sha to read at; absent ⇒ that repo's default branch. */
273
+ readonly ref: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>]>, undefined>;
274
+ /** File or directory path within the manifests repo. */
275
+ readonly path: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 500, undefined>]>;
276
+ }, undefined>], undefined>;
277
+ export type KubernetesManifestSource = v.InferOutput<typeof kubernetesManifestSourceSchema>;
278
+ /** How the environment URL is derived once the manifests are applied. */
279
+ export declare const kubernetesUrlSourceSchema: v.VariantSchema<"source", [v.ObjectSchema<{
280
+ readonly source: v.LiteralSchema<"ingressTemplate", undefined>;
281
+ /** Host template, e.g. `{{branch}}.preview.example.com`; rendered with the provision vars. */
282
+ readonly hostTemplate: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 500, undefined>]>;
283
+ readonly scheme: v.OptionalSchema<v.PicklistSchema<["http", "https"], undefined>, undefined>;
284
+ }, undefined>, v.ObjectSchema<{
285
+ readonly source: v.LiteralSchema<"ingressStatus", undefined>;
286
+ /** Ingress object to read `.status.loadBalancer` from; absent ⇒ the only Ingress applied. */
287
+ readonly ingressName: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>]>, undefined>;
288
+ readonly scheme: v.OptionalSchema<v.PicklistSchema<["http", "https"], undefined>, undefined>;
289
+ }, undefined>, v.ObjectSchema<{
290
+ readonly source: v.LiteralSchema<"serviceStatus", undefined>;
291
+ /** Service object to read `.status.loadBalancer` (k3s ServiceLB) from. */
292
+ readonly serviceName: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>]>;
293
+ readonly port: v.OptionalSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 1, undefined>, v.MaxValueAction<number, 65535, undefined>]>, undefined>;
294
+ readonly scheme: v.OptionalSchema<v.PicklistSchema<["http", "https"], undefined>, undefined>;
295
+ }, undefined>], undefined>;
296
+ export type KubernetesUrlSource = v.InferOutput<typeof kubernetesUrlSourceSchema>;
297
+ export declare const kubernetesEnvironmentConfigSchema: v.ObjectSchema<{
298
+ /** Human label for the connection (shown in the UI). */
299
+ readonly label: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 120, undefined>]>;
300
+ /** kube-apiserver root URL, e.g. `https://my-cluster.example:6443`. */
301
+ readonly apiServerUrl: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 2000, undefined>]>;
302
+ /** PEM CA bundle to verify the apiserver TLS cert (omit only for a publicly-trusted CA). */
303
+ readonly caCertPem: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
304
+ /** Skip apiserver TLS verification — strongly discouraged; kind/dev clusters only. */
305
+ readonly insecureSkipTlsVerify: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
306
+ /**
307
+ * Namespace name template for the per-PR environment, e.g. `cf-env-{{pullNumber}}`.
308
+ * Rendered with the provision vars then sanitized to an RFC1123 label; absent ⇒ a
309
+ * default derived from the PR number / block id.
310
+ */
311
+ readonly namespaceTemplate: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 200, undefined>]>, undefined>;
312
+ /** Where the manifests are read from (co-located in the PR repo, or a separate repo). */
313
+ readonly manifestSource: v.VariantSchema<"type", [v.ObjectSchema<{
314
+ readonly type: v.LiteralSchema<"colocated", undefined>;
315
+ /** File or directory path within the PR repo (read at the PR head branch). */
316
+ readonly path: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 500, undefined>]>;
317
+ }, undefined>, v.ObjectSchema<{
318
+ readonly type: v.LiteralSchema<"separate", undefined>;
319
+ /** `owner/repo` of the manifests repo. */
320
+ readonly repo: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.RegexAction<string, "must be \"owner/repo\"">]>;
321
+ /** Branch/tag/sha to read at; absent ⇒ that repo's default branch. */
322
+ readonly ref: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>]>, undefined>;
323
+ /** File or directory path within the manifests repo. */
324
+ readonly path: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 500, undefined>]>;
325
+ }, undefined>], undefined>;
326
+ /** How the environment URL is derived once applied. */
327
+ readonly url: v.VariantSchema<"source", [v.ObjectSchema<{
328
+ readonly source: v.LiteralSchema<"ingressTemplate", undefined>;
329
+ /** Host template, e.g. `{{branch}}.preview.example.com`; rendered with the provision vars. */
330
+ readonly hostTemplate: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 500, undefined>]>;
331
+ readonly scheme: v.OptionalSchema<v.PicklistSchema<["http", "https"], undefined>, undefined>;
332
+ }, undefined>, v.ObjectSchema<{
333
+ readonly source: v.LiteralSchema<"ingressStatus", undefined>;
334
+ /** Ingress object to read `.status.loadBalancer` from; absent ⇒ the only Ingress applied. */
335
+ readonly ingressName: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>]>, undefined>;
336
+ readonly scheme: v.OptionalSchema<v.PicklistSchema<["http", "https"], undefined>, undefined>;
337
+ }, undefined>, v.ObjectSchema<{
338
+ readonly source: v.LiteralSchema<"serviceStatus", undefined>;
339
+ /** Service object to read `.status.loadBalancer` (k3s ServiceLB) from. */
340
+ readonly serviceName: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>]>;
341
+ readonly port: v.OptionalSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 1, undefined>, v.MaxValueAction<number, 65535, undefined>]>, undefined>;
342
+ readonly scheme: v.OptionalSchema<v.PicklistSchema<["http", "https"], undefined>, undefined>;
343
+ }, undefined>], undefined>;
344
+ /**
345
+ * Optional image reference made available to the manifests as `{{image}}` (e.g. a
346
+ * CI-built image tagged by branch/sha). Itself a template over the provision vars.
347
+ */
348
+ readonly imageTemplate: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MaxLengthAction<string, 500, undefined>]>, undefined>;
349
+ /** Fallback TTL (ms) after which the env is swept + torn down. */
350
+ readonly defaultTtlMs: v.OptionalSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.MinValueAction<number, 60000, undefined>]>, undefined>;
351
+ /** Extra labels stamped on the namespace + every applied resource. */
352
+ readonly labels: v.OptionalSchema<v.RecordSchema<v.StringSchema<undefined>, v.StringSchema<undefined>, undefined>, undefined>;
353
+ /** Extra annotations stamped on the namespace. */
354
+ readonly annotations: v.OptionalSchema<v.RecordSchema<v.StringSchema<undefined>, v.StringSchema<undefined>, undefined>, undefined>;
299
355
  }, undefined>;
300
- export type EnvironmentConnection = v.InferOutput<typeof environmentConnectionSchema>;
356
+ export type KubernetesEnvironmentConfig = v.InferOutput<typeof kubernetesEnvironmentConfigSchema>;
301
357
  /**
302
- * Register (or replace) a workspace's environment provider. The org supplies the
303
- * actual per-tenant secret values here (write-only); they are encrypted and
304
- * stored in D1 and never returned. Every `secretRef.key` in the manifest must
305
- * have a matching entry in `secrets`.
306
- *
307
- * A native adapter is configured through the SAME manifest path (see
308
- * `backend/docs/native-environment-adapter.md`): its non-secret per-workspace
309
- * settings ride the manifest's opaque `providerConfig` bag and its secrets via
310
- * the manifest `auth` scheme — there is deliberately no separate config channel.
358
+ * An ephemeral-environment backend config, discriminated by `kind`. The universal
359
+ * abstraction over HOW a workspace's preview environments are provisioned: today
360
+ * `manifest` (the generic BYO HTTP management API) and `kubernetes` (native per-PR
361
+ * namespaces). Future kinds add a member here + a provider in
362
+ * `@cat-factory/integrations` — no new table/service/controller. Mirrors
363
+ * `runnerBackendConfigSchema`; the provider-registry seam keys on `kind`.
311
364
  */
312
- export declare const registerEnvironmentProviderSchema: v.ObjectSchema<{
365
+ export declare const environmentBackendConfigSchema: v.VariantSchema<"kind", [v.ObjectSchema<{
366
+ readonly kind: v.LiteralSchema<"manifest", undefined>;
313
367
  readonly manifest: v.ObjectSchema<{
314
368
  readonly providerId: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, undefined>, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 64, undefined>]>;
315
369
  readonly label: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 120, undefined>]>;
@@ -438,6 +492,514 @@ export declare const registerEnvironmentProviderSchema: v.ObjectSchema<{
438
492
  */
439
493
  readonly providerConfig: v.OptionalSchema<v.RecordSchema<v.StringSchema<undefined>, v.UnknownSchema, undefined>, undefined>;
440
494
  }, undefined>;
495
+ }, undefined>, v.ObjectSchema<{
496
+ readonly kind: v.LiteralSchema<"kubernetes", undefined>;
497
+ readonly kubernetes: v.ObjectSchema<{
498
+ /** Human label for the connection (shown in the UI). */
499
+ readonly label: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 120, undefined>]>;
500
+ /** kube-apiserver root URL, e.g. `https://my-cluster.example:6443`. */
501
+ readonly apiServerUrl: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 2000, undefined>]>;
502
+ /** PEM CA bundle to verify the apiserver TLS cert (omit only for a publicly-trusted CA). */
503
+ readonly caCertPem: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
504
+ /** Skip apiserver TLS verification — strongly discouraged; kind/dev clusters only. */
505
+ readonly insecureSkipTlsVerify: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
506
+ /**
507
+ * Namespace name template for the per-PR environment, e.g. `cf-env-{{pullNumber}}`.
508
+ * Rendered with the provision vars then sanitized to an RFC1123 label; absent ⇒ a
509
+ * default derived from the PR number / block id.
510
+ */
511
+ readonly namespaceTemplate: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 200, undefined>]>, undefined>;
512
+ /** Where the manifests are read from (co-located in the PR repo, or a separate repo). */
513
+ readonly manifestSource: v.VariantSchema<"type", [v.ObjectSchema<{
514
+ readonly type: v.LiteralSchema<"colocated", undefined>;
515
+ /** File or directory path within the PR repo (read at the PR head branch). */
516
+ readonly path: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 500, undefined>]>;
517
+ }, undefined>, v.ObjectSchema<{
518
+ readonly type: v.LiteralSchema<"separate", undefined>;
519
+ /** `owner/repo` of the manifests repo. */
520
+ readonly repo: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.RegexAction<string, "must be \"owner/repo\"">]>;
521
+ /** Branch/tag/sha to read at; absent ⇒ that repo's default branch. */
522
+ readonly ref: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>]>, undefined>;
523
+ /** File or directory path within the manifests repo. */
524
+ readonly path: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 500, undefined>]>;
525
+ }, undefined>], undefined>;
526
+ /** How the environment URL is derived once applied. */
527
+ readonly url: v.VariantSchema<"source", [v.ObjectSchema<{
528
+ readonly source: v.LiteralSchema<"ingressTemplate", undefined>;
529
+ /** Host template, e.g. `{{branch}}.preview.example.com`; rendered with the provision vars. */
530
+ readonly hostTemplate: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 500, undefined>]>;
531
+ readonly scheme: v.OptionalSchema<v.PicklistSchema<["http", "https"], undefined>, undefined>;
532
+ }, undefined>, v.ObjectSchema<{
533
+ readonly source: v.LiteralSchema<"ingressStatus", undefined>;
534
+ /** Ingress object to read `.status.loadBalancer` from; absent ⇒ the only Ingress applied. */
535
+ readonly ingressName: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>]>, undefined>;
536
+ readonly scheme: v.OptionalSchema<v.PicklistSchema<["http", "https"], undefined>, undefined>;
537
+ }, undefined>, v.ObjectSchema<{
538
+ readonly source: v.LiteralSchema<"serviceStatus", undefined>;
539
+ /** Service object to read `.status.loadBalancer` (k3s ServiceLB) from. */
540
+ readonly serviceName: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>]>;
541
+ readonly port: v.OptionalSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 1, undefined>, v.MaxValueAction<number, 65535, undefined>]>, undefined>;
542
+ readonly scheme: v.OptionalSchema<v.PicklistSchema<["http", "https"], undefined>, undefined>;
543
+ }, undefined>], undefined>;
544
+ /**
545
+ * Optional image reference made available to the manifests as `{{image}}` (e.g. a
546
+ * CI-built image tagged by branch/sha). Itself a template over the provision vars.
547
+ */
548
+ readonly imageTemplate: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MaxLengthAction<string, 500, undefined>]>, undefined>;
549
+ /** Fallback TTL (ms) after which the env is swept + torn down. */
550
+ readonly defaultTtlMs: v.OptionalSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.MinValueAction<number, 60000, undefined>]>, undefined>;
551
+ /** Extra labels stamped on the namespace + every applied resource. */
552
+ readonly labels: v.OptionalSchema<v.RecordSchema<v.StringSchema<undefined>, v.StringSchema<undefined>, undefined>, undefined>;
553
+ /** Extra annotations stamped on the namespace. */
554
+ readonly annotations: v.OptionalSchema<v.RecordSchema<v.StringSchema<undefined>, v.StringSchema<undefined>, undefined>, undefined>;
555
+ }, undefined>;
556
+ }, undefined>], undefined>;
557
+ export type EnvironmentBackendConfig = v.InferOutput<typeof environmentBackendConfigSchema>;
558
+ export type EnvironmentBackendKind = EnvironmentBackendConfig['kind'];
559
+ /** Resolved access creds for a provisioned env, as surfaced to a tester agent. */
560
+ export declare const environmentAccessHandleSchema: v.ObjectSchema<{
561
+ readonly scheme: v.PicklistSchema<["none", "bearer", "basic", "custom_header"], undefined>;
562
+ readonly token: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
563
+ readonly username: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
564
+ readonly password: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
565
+ readonly headerName: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
566
+ readonly headerValue: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
567
+ }, undefined>;
568
+ export type EnvironmentAccessHandle = v.InferOutput<typeof environmentAccessHandleSchema>;
569
+ /** A provisioned environment, as exposed to clients and downstream agents. */
570
+ export declare const environmentHandleSchema: v.ObjectSchema<{
571
+ readonly id: v.StringSchema<undefined>;
572
+ readonly workspaceId: v.StringSchema<undefined>;
573
+ readonly blockId: v.NullableSchema<v.StringSchema<undefined>, undefined>;
574
+ readonly executionId: v.NullableSchema<v.StringSchema<undefined>, undefined>;
575
+ readonly providerId: v.StringSchema<undefined>;
576
+ readonly externalId: v.NullableSchema<v.StringSchema<undefined>, undefined>;
577
+ readonly url: v.NullableSchema<v.StringSchema<undefined>, undefined>;
578
+ readonly status: v.PicklistSchema<["provisioning", "ready", "failed", "expired", "tearing_down", "torn_down"], undefined>;
579
+ /** Present only on the dedicated access endpoint / in agent context. */
580
+ readonly access: v.OptionalSchema<v.ObjectSchema<{
581
+ readonly scheme: v.PicklistSchema<["none", "bearer", "basic", "custom_header"], undefined>;
582
+ readonly token: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
583
+ readonly username: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
584
+ readonly password: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
585
+ readonly headerName: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
586
+ readonly headerValue: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
587
+ }, undefined>, undefined>;
588
+ readonly createdAt: v.NumberSchema<undefined>;
589
+ readonly expiresAt: v.NullableSchema<v.NumberSchema<undefined>, undefined>;
590
+ readonly lastError: v.NullableSchema<v.StringSchema<undefined>, undefined>;
591
+ }, undefined>;
592
+ export type EnvironmentHandle = v.InferOutput<typeof environmentHandleSchema>;
593
+ /** A workspace's provider binding, as exposed to clients (never secret values). */
594
+ export declare const environmentConnectionSchema: v.ObjectSchema<{
595
+ /** Which backend kind is configured (`manifest` | `kubernetes` | …). */
596
+ readonly kind: v.StringSchema<undefined>;
597
+ readonly providerId: v.StringSchema<undefined>;
598
+ readonly label: v.StringSchema<undefined>;
599
+ readonly baseUrl: v.StringSchema<undefined>;
600
+ readonly connectedAt: v.NumberSchema<undefined>;
601
+ /** Which secret keys are set (names only), so the UI can show completeness. */
602
+ readonly secretKeys: v.ArraySchema<v.StringSchema<undefined>, undefined>;
603
+ /**
604
+ * The stored discriminated backend config, sans secrets (those live in the
605
+ * write-only secret bundle), so the connect form can prefill its non-secret fields
606
+ * on edit. Omitted only for an unparsable row.
607
+ */
608
+ readonly config: v.OptionalSchema<v.VariantSchema<"kind", [v.ObjectSchema<{
609
+ readonly kind: v.LiteralSchema<"manifest", undefined>;
610
+ readonly manifest: v.ObjectSchema<{
611
+ readonly providerId: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, undefined>, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 64, undefined>]>;
612
+ readonly label: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 120, undefined>]>;
613
+ /** Management API root; provision/status/teardown paths are appended to it. */
614
+ readonly baseUrl: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 2000, undefined>]>;
615
+ readonly auth: v.VariantSchema<"type", [v.ObjectSchema<{
616
+ readonly type: v.LiteralSchema<"none", undefined>;
617
+ }, undefined>, v.ObjectSchema<{
618
+ readonly type: v.LiteralSchema<"api_key", undefined>;
619
+ readonly headerName: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>;
620
+ readonly secretRef: v.ObjectSchema<{
621
+ readonly key: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, undefined>, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 64, undefined>]>;
622
+ }, undefined>;
623
+ /** Optional prefix prepended to the secret value, e.g. `Token `. */
624
+ readonly valuePrefix: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
625
+ }, undefined>, v.ObjectSchema<{
626
+ readonly type: v.LiteralSchema<"bearer", undefined>;
627
+ readonly secretRef: v.ObjectSchema<{
628
+ readonly key: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, undefined>, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 64, undefined>]>;
629
+ }, undefined>;
630
+ }, undefined>, v.ObjectSchema<{
631
+ readonly type: v.LiteralSchema<"basic", undefined>;
632
+ readonly usernameSecretRef: v.ObjectSchema<{
633
+ readonly key: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, undefined>, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 64, undefined>]>;
634
+ }, undefined>;
635
+ readonly passwordSecretRef: v.ObjectSchema<{
636
+ readonly key: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, undefined>, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 64, undefined>]>;
637
+ }, undefined>;
638
+ }, undefined>, v.ObjectSchema<{
639
+ readonly type: v.LiteralSchema<"oauth2_client_credentials", undefined>;
640
+ readonly tokenUrl: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 2000, undefined>]>;
641
+ readonly clientIdSecretRef: v.ObjectSchema<{
642
+ readonly key: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, undefined>, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 64, undefined>]>;
643
+ }, undefined>;
644
+ readonly clientSecretSecretRef: v.ObjectSchema<{
645
+ readonly key: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, undefined>, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 64, undefined>]>;
646
+ }, undefined>;
647
+ readonly scope: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
648
+ readonly audience: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
649
+ }, undefined>, v.ObjectSchema<{
650
+ readonly type: v.LiteralSchema<"custom_headers", undefined>;
651
+ readonly headers: v.ArraySchema<v.ObjectSchema<{
652
+ readonly name: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>;
653
+ readonly secretRef: v.ObjectSchema<{
654
+ readonly key: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, undefined>, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 64, undefined>]>;
655
+ }, undefined>;
656
+ }, undefined>, undefined>;
657
+ }, undefined>], undefined>;
658
+ readonly provision: v.ObjectSchema<{
659
+ readonly method: v.PicklistSchema<["GET", "POST", "PUT", "PATCH", "DELETE"], undefined>;
660
+ readonly pathTemplate: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MaxLengthAction<string, 2000, undefined>]>;
661
+ readonly query: v.OptionalSchema<v.ArraySchema<v.ObjectSchema<{
662
+ readonly key: v.StringSchema<undefined>;
663
+ readonly value: v.StringSchema<undefined>;
664
+ }, undefined>, undefined>, undefined>;
665
+ readonly headers: v.OptionalSchema<v.ArraySchema<v.ObjectSchema<{
666
+ readonly name: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>;
667
+ readonly value: v.StringSchema<undefined>;
668
+ }, undefined>, undefined>, undefined>;
669
+ readonly bodyTemplate: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
670
+ /** Per-call timeout (ms). Bounded; defaults applied by the adapter. */
671
+ readonly timeoutMs: v.OptionalSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.MinValueAction<number, 1, undefined>, v.MaxValueAction<number, 60000, undefined>]>, undefined>;
672
+ }, undefined>;
673
+ /** Optional: polled to observe async provisioning progress. */
674
+ readonly status: v.OptionalSchema<v.ObjectSchema<{
675
+ readonly method: v.PicklistSchema<["GET", "POST", "PUT", "PATCH", "DELETE"], undefined>;
676
+ readonly pathTemplate: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MaxLengthAction<string, 2000, undefined>]>;
677
+ readonly query: v.OptionalSchema<v.ArraySchema<v.ObjectSchema<{
678
+ readonly key: v.StringSchema<undefined>;
679
+ readonly value: v.StringSchema<undefined>;
680
+ }, undefined>, undefined>, undefined>;
681
+ readonly headers: v.OptionalSchema<v.ArraySchema<v.ObjectSchema<{
682
+ readonly name: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>;
683
+ readonly value: v.StringSchema<undefined>;
684
+ }, undefined>, undefined>, undefined>;
685
+ readonly bodyTemplate: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
686
+ /** Per-call timeout (ms). Bounded; defaults applied by the adapter. */
687
+ readonly timeoutMs: v.OptionalSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.MinValueAction<number, 1, undefined>, v.MaxValueAction<number, 60000, undefined>]>, undefined>;
688
+ }, undefined>, undefined>;
689
+ /** Optional: called to destroy the environment (manual or on TTL expiry). */
690
+ readonly teardown: v.OptionalSchema<v.ObjectSchema<{
691
+ readonly method: v.PicklistSchema<["GET", "POST", "PUT", "PATCH", "DELETE"], undefined>;
692
+ readonly pathTemplate: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MaxLengthAction<string, 2000, undefined>]>;
693
+ readonly query: v.OptionalSchema<v.ArraySchema<v.ObjectSchema<{
694
+ readonly key: v.StringSchema<undefined>;
695
+ readonly value: v.StringSchema<undefined>;
696
+ }, undefined>, undefined>, undefined>;
697
+ readonly headers: v.OptionalSchema<v.ArraySchema<v.ObjectSchema<{
698
+ readonly name: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>;
699
+ readonly value: v.StringSchema<undefined>;
700
+ }, undefined>, undefined>, undefined>;
701
+ readonly bodyTemplate: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
702
+ /** Per-call timeout (ms). Bounded; defaults applied by the adapter. */
703
+ readonly timeoutMs: v.OptionalSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.MinValueAction<number, 1, undefined>, v.MaxValueAction<number, 60000, undefined>]>, undefined>;
704
+ }, undefined>, undefined>;
705
+ readonly response: v.ObjectSchema<{
706
+ readonly urlPath: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
707
+ readonly statusPath: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
708
+ readonly statusMap: v.OptionalSchema<v.ArraySchema<v.ObjectSchema<{
709
+ readonly from: v.StringSchema<undefined>;
710
+ readonly to: v.PicklistSchema<["provisioning", "ready", "failed", "expired", "tearing_down", "torn_down"], undefined>;
711
+ }, undefined>, undefined>, undefined>;
712
+ readonly expiresAtPath: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
713
+ readonly externalIdPath: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
714
+ readonly access: v.OptionalSchema<v.ObjectSchema<{
715
+ readonly scheme: v.PicklistSchema<["none", "bearer", "basic", "custom_header"], undefined>;
716
+ readonly tokenPath: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
717
+ readonly usernamePath: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
718
+ readonly passwordPath: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
719
+ readonly headerName: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
720
+ readonly headerValuePath: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
721
+ }, undefined>, undefined>;
722
+ }, undefined>;
723
+ /** Fallback TTL (ms) when the response carries no explicit expiry. */
724
+ readonly defaultTtlMs: v.OptionalSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.MinValueAction<number, 60000, undefined>]>, undefined>;
725
+ /**
726
+ * Opaque, provider-specific configuration for a *native* injected adapter (e.g. a
727
+ * Kargo project, link-selection key, status map). The generic HttpEnvironmentProvider
728
+ * ignores it entirely; a native adapter (injected via `buildNodeContainer({
729
+ * environmentProvider })` / `startLocal({ environmentProvider })`) reads + validates it
730
+ * off the per-call `manifest`. This is the per-WORKSPACE config carrier for native
731
+ * adapters — the deployment-wide provider singleton has no other way to receive
732
+ * per-workspace settings. NOT covered by the manifest URL/SSRF checks (which only guard
733
+ * `baseUrl`/`tokenUrl`); an adapter that puts a URL here must guard it itself (reuse the
734
+ * exported `UrlSafetyPolicy`). See `backend/docs/native-environment-adapter.md`.
735
+ */
736
+ readonly providerConfig: v.OptionalSchema<v.RecordSchema<v.StringSchema<undefined>, v.UnknownSchema, undefined>, undefined>;
737
+ }, undefined>;
738
+ }, undefined>, v.ObjectSchema<{
739
+ readonly kind: v.LiteralSchema<"kubernetes", undefined>;
740
+ readonly kubernetes: v.ObjectSchema<{
741
+ /** Human label for the connection (shown in the UI). */
742
+ readonly label: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 120, undefined>]>;
743
+ /** kube-apiserver root URL, e.g. `https://my-cluster.example:6443`. */
744
+ readonly apiServerUrl: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 2000, undefined>]>;
745
+ /** PEM CA bundle to verify the apiserver TLS cert (omit only for a publicly-trusted CA). */
746
+ readonly caCertPem: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
747
+ /** Skip apiserver TLS verification — strongly discouraged; kind/dev clusters only. */
748
+ readonly insecureSkipTlsVerify: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
749
+ /**
750
+ * Namespace name template for the per-PR environment, e.g. `cf-env-{{pullNumber}}`.
751
+ * Rendered with the provision vars then sanitized to an RFC1123 label; absent ⇒ a
752
+ * default derived from the PR number / block id.
753
+ */
754
+ readonly namespaceTemplate: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 200, undefined>]>, undefined>;
755
+ /** Where the manifests are read from (co-located in the PR repo, or a separate repo). */
756
+ readonly manifestSource: v.VariantSchema<"type", [v.ObjectSchema<{
757
+ readonly type: v.LiteralSchema<"colocated", undefined>;
758
+ /** File or directory path within the PR repo (read at the PR head branch). */
759
+ readonly path: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 500, undefined>]>;
760
+ }, undefined>, v.ObjectSchema<{
761
+ readonly type: v.LiteralSchema<"separate", undefined>;
762
+ /** `owner/repo` of the manifests repo. */
763
+ readonly repo: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.RegexAction<string, "must be \"owner/repo\"">]>;
764
+ /** Branch/tag/sha to read at; absent ⇒ that repo's default branch. */
765
+ readonly ref: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>]>, undefined>;
766
+ /** File or directory path within the manifests repo. */
767
+ readonly path: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 500, undefined>]>;
768
+ }, undefined>], undefined>;
769
+ /** How the environment URL is derived once applied. */
770
+ readonly url: v.VariantSchema<"source", [v.ObjectSchema<{
771
+ readonly source: v.LiteralSchema<"ingressTemplate", undefined>;
772
+ /** Host template, e.g. `{{branch}}.preview.example.com`; rendered with the provision vars. */
773
+ readonly hostTemplate: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 500, undefined>]>;
774
+ readonly scheme: v.OptionalSchema<v.PicklistSchema<["http", "https"], undefined>, undefined>;
775
+ }, undefined>, v.ObjectSchema<{
776
+ readonly source: v.LiteralSchema<"ingressStatus", undefined>;
777
+ /** Ingress object to read `.status.loadBalancer` from; absent ⇒ the only Ingress applied. */
778
+ readonly ingressName: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>]>, undefined>;
779
+ readonly scheme: v.OptionalSchema<v.PicklistSchema<["http", "https"], undefined>, undefined>;
780
+ }, undefined>, v.ObjectSchema<{
781
+ readonly source: v.LiteralSchema<"serviceStatus", undefined>;
782
+ /** Service object to read `.status.loadBalancer` (k3s ServiceLB) from. */
783
+ readonly serviceName: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>]>;
784
+ readonly port: v.OptionalSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 1, undefined>, v.MaxValueAction<number, 65535, undefined>]>, undefined>;
785
+ readonly scheme: v.OptionalSchema<v.PicklistSchema<["http", "https"], undefined>, undefined>;
786
+ }, undefined>], undefined>;
787
+ /**
788
+ * Optional image reference made available to the manifests as `{{image}}` (e.g. a
789
+ * CI-built image tagged by branch/sha). Itself a template over the provision vars.
790
+ */
791
+ readonly imageTemplate: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MaxLengthAction<string, 500, undefined>]>, undefined>;
792
+ /** Fallback TTL (ms) after which the env is swept + torn down. */
793
+ readonly defaultTtlMs: v.OptionalSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.MinValueAction<number, 60000, undefined>]>, undefined>;
794
+ /** Extra labels stamped on the namespace + every applied resource. */
795
+ readonly labels: v.OptionalSchema<v.RecordSchema<v.StringSchema<undefined>, v.StringSchema<undefined>, undefined>, undefined>;
796
+ /** Extra annotations stamped on the namespace. */
797
+ readonly annotations: v.OptionalSchema<v.RecordSchema<v.StringSchema<undefined>, v.StringSchema<undefined>, undefined>, undefined>;
798
+ }, undefined>;
799
+ }, undefined>], undefined>, undefined>;
800
+ }, undefined>;
801
+ export type EnvironmentConnection = v.InferOutput<typeof environmentConnectionSchema>;
802
+ /**
803
+ * Register (or replace) a workspace's environment provider. `config` is the
804
+ * discriminated backend config (the generic HTTP manifest, or a native Kubernetes
805
+ * backend); the org supplies the actual per-tenant secret values here (write-only) —
806
+ * a manifest's management-API credentials, or a Kubernetes ServiceAccount token
807
+ * (`apiToken`). Secrets are encrypted at rest and never returned. Every secret key
808
+ * the chosen backend references must have a matching entry in `secrets`.
809
+ */
810
+ export declare const registerEnvironmentProviderSchema: v.ObjectSchema<{
811
+ readonly config: v.VariantSchema<"kind", [v.ObjectSchema<{
812
+ readonly kind: v.LiteralSchema<"manifest", undefined>;
813
+ readonly manifest: v.ObjectSchema<{
814
+ readonly providerId: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, undefined>, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 64, undefined>]>;
815
+ readonly label: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 120, undefined>]>;
816
+ /** Management API root; provision/status/teardown paths are appended to it. */
817
+ readonly baseUrl: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 2000, undefined>]>;
818
+ readonly auth: v.VariantSchema<"type", [v.ObjectSchema<{
819
+ readonly type: v.LiteralSchema<"none", undefined>;
820
+ }, undefined>, v.ObjectSchema<{
821
+ readonly type: v.LiteralSchema<"api_key", undefined>;
822
+ readonly headerName: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>;
823
+ readonly secretRef: v.ObjectSchema<{
824
+ readonly key: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, undefined>, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 64, undefined>]>;
825
+ }, undefined>;
826
+ /** Optional prefix prepended to the secret value, e.g. `Token `. */
827
+ readonly valuePrefix: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
828
+ }, undefined>, v.ObjectSchema<{
829
+ readonly type: v.LiteralSchema<"bearer", undefined>;
830
+ readonly secretRef: v.ObjectSchema<{
831
+ readonly key: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, undefined>, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 64, undefined>]>;
832
+ }, undefined>;
833
+ }, undefined>, v.ObjectSchema<{
834
+ readonly type: v.LiteralSchema<"basic", undefined>;
835
+ readonly usernameSecretRef: v.ObjectSchema<{
836
+ readonly key: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, undefined>, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 64, undefined>]>;
837
+ }, undefined>;
838
+ readonly passwordSecretRef: v.ObjectSchema<{
839
+ readonly key: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, undefined>, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 64, undefined>]>;
840
+ }, undefined>;
841
+ }, undefined>, v.ObjectSchema<{
842
+ readonly type: v.LiteralSchema<"oauth2_client_credentials", undefined>;
843
+ readonly tokenUrl: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 2000, undefined>]>;
844
+ readonly clientIdSecretRef: v.ObjectSchema<{
845
+ readonly key: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, undefined>, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 64, undefined>]>;
846
+ }, undefined>;
847
+ readonly clientSecretSecretRef: v.ObjectSchema<{
848
+ readonly key: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, undefined>, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 64, undefined>]>;
849
+ }, undefined>;
850
+ readonly scope: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
851
+ readonly audience: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
852
+ }, undefined>, v.ObjectSchema<{
853
+ readonly type: v.LiteralSchema<"custom_headers", undefined>;
854
+ readonly headers: v.ArraySchema<v.ObjectSchema<{
855
+ readonly name: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>;
856
+ readonly secretRef: v.ObjectSchema<{
857
+ readonly key: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, undefined>, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 64, undefined>]>;
858
+ }, undefined>;
859
+ }, undefined>, undefined>;
860
+ }, undefined>], undefined>;
861
+ readonly provision: v.ObjectSchema<{
862
+ readonly method: v.PicklistSchema<["GET", "POST", "PUT", "PATCH", "DELETE"], undefined>;
863
+ readonly pathTemplate: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MaxLengthAction<string, 2000, undefined>]>;
864
+ readonly query: v.OptionalSchema<v.ArraySchema<v.ObjectSchema<{
865
+ readonly key: v.StringSchema<undefined>;
866
+ readonly value: v.StringSchema<undefined>;
867
+ }, undefined>, undefined>, undefined>;
868
+ readonly headers: v.OptionalSchema<v.ArraySchema<v.ObjectSchema<{
869
+ readonly name: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>;
870
+ readonly value: v.StringSchema<undefined>;
871
+ }, undefined>, undefined>, undefined>;
872
+ readonly bodyTemplate: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
873
+ /** Per-call timeout (ms). Bounded; defaults applied by the adapter. */
874
+ readonly timeoutMs: v.OptionalSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.MinValueAction<number, 1, undefined>, v.MaxValueAction<number, 60000, undefined>]>, undefined>;
875
+ }, undefined>;
876
+ /** Optional: polled to observe async provisioning progress. */
877
+ readonly status: v.OptionalSchema<v.ObjectSchema<{
878
+ readonly method: v.PicklistSchema<["GET", "POST", "PUT", "PATCH", "DELETE"], undefined>;
879
+ readonly pathTemplate: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MaxLengthAction<string, 2000, undefined>]>;
880
+ readonly query: v.OptionalSchema<v.ArraySchema<v.ObjectSchema<{
881
+ readonly key: v.StringSchema<undefined>;
882
+ readonly value: v.StringSchema<undefined>;
883
+ }, undefined>, undefined>, undefined>;
884
+ readonly headers: v.OptionalSchema<v.ArraySchema<v.ObjectSchema<{
885
+ readonly name: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>;
886
+ readonly value: v.StringSchema<undefined>;
887
+ }, undefined>, undefined>, undefined>;
888
+ readonly bodyTemplate: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
889
+ /** Per-call timeout (ms). Bounded; defaults applied by the adapter. */
890
+ readonly timeoutMs: v.OptionalSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.MinValueAction<number, 1, undefined>, v.MaxValueAction<number, 60000, undefined>]>, undefined>;
891
+ }, undefined>, undefined>;
892
+ /** Optional: called to destroy the environment (manual or on TTL expiry). */
893
+ readonly teardown: v.OptionalSchema<v.ObjectSchema<{
894
+ readonly method: v.PicklistSchema<["GET", "POST", "PUT", "PATCH", "DELETE"], undefined>;
895
+ readonly pathTemplate: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MaxLengthAction<string, 2000, undefined>]>;
896
+ readonly query: v.OptionalSchema<v.ArraySchema<v.ObjectSchema<{
897
+ readonly key: v.StringSchema<undefined>;
898
+ readonly value: v.StringSchema<undefined>;
899
+ }, undefined>, undefined>, undefined>;
900
+ readonly headers: v.OptionalSchema<v.ArraySchema<v.ObjectSchema<{
901
+ readonly name: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>;
902
+ readonly value: v.StringSchema<undefined>;
903
+ }, undefined>, undefined>, undefined>;
904
+ readonly bodyTemplate: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
905
+ /** Per-call timeout (ms). Bounded; defaults applied by the adapter. */
906
+ readonly timeoutMs: v.OptionalSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.MinValueAction<number, 1, undefined>, v.MaxValueAction<number, 60000, undefined>]>, undefined>;
907
+ }, undefined>, undefined>;
908
+ readonly response: v.ObjectSchema<{
909
+ readonly urlPath: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
910
+ readonly statusPath: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
911
+ readonly statusMap: v.OptionalSchema<v.ArraySchema<v.ObjectSchema<{
912
+ readonly from: v.StringSchema<undefined>;
913
+ readonly to: v.PicklistSchema<["provisioning", "ready", "failed", "expired", "tearing_down", "torn_down"], undefined>;
914
+ }, undefined>, undefined>, undefined>;
915
+ readonly expiresAtPath: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
916
+ readonly externalIdPath: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
917
+ readonly access: v.OptionalSchema<v.ObjectSchema<{
918
+ readonly scheme: v.PicklistSchema<["none", "bearer", "basic", "custom_header"], undefined>;
919
+ readonly tokenPath: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
920
+ readonly usernamePath: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
921
+ readonly passwordPath: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
922
+ readonly headerName: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
923
+ readonly headerValuePath: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
924
+ }, undefined>, undefined>;
925
+ }, undefined>;
926
+ /** Fallback TTL (ms) when the response carries no explicit expiry. */
927
+ readonly defaultTtlMs: v.OptionalSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.MinValueAction<number, 60000, undefined>]>, undefined>;
928
+ /**
929
+ * Opaque, provider-specific configuration for a *native* injected adapter (e.g. a
930
+ * Kargo project, link-selection key, status map). The generic HttpEnvironmentProvider
931
+ * ignores it entirely; a native adapter (injected via `buildNodeContainer({
932
+ * environmentProvider })` / `startLocal({ environmentProvider })`) reads + validates it
933
+ * off the per-call `manifest`. This is the per-WORKSPACE config carrier for native
934
+ * adapters — the deployment-wide provider singleton has no other way to receive
935
+ * per-workspace settings. NOT covered by the manifest URL/SSRF checks (which only guard
936
+ * `baseUrl`/`tokenUrl`); an adapter that puts a URL here must guard it itself (reuse the
937
+ * exported `UrlSafetyPolicy`). See `backend/docs/native-environment-adapter.md`.
938
+ */
939
+ readonly providerConfig: v.OptionalSchema<v.RecordSchema<v.StringSchema<undefined>, v.UnknownSchema, undefined>, undefined>;
940
+ }, undefined>;
941
+ }, undefined>, v.ObjectSchema<{
942
+ readonly kind: v.LiteralSchema<"kubernetes", undefined>;
943
+ readonly kubernetes: v.ObjectSchema<{
944
+ /** Human label for the connection (shown in the UI). */
945
+ readonly label: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 120, undefined>]>;
946
+ /** kube-apiserver root URL, e.g. `https://my-cluster.example:6443`. */
947
+ readonly apiServerUrl: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 2000, undefined>]>;
948
+ /** PEM CA bundle to verify the apiserver TLS cert (omit only for a publicly-trusted CA). */
949
+ readonly caCertPem: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
950
+ /** Skip apiserver TLS verification — strongly discouraged; kind/dev clusters only. */
951
+ readonly insecureSkipTlsVerify: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
952
+ /**
953
+ * Namespace name template for the per-PR environment, e.g. `cf-env-{{pullNumber}}`.
954
+ * Rendered with the provision vars then sanitized to an RFC1123 label; absent ⇒ a
955
+ * default derived from the PR number / block id.
956
+ */
957
+ readonly namespaceTemplate: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 200, undefined>]>, undefined>;
958
+ /** Where the manifests are read from (co-located in the PR repo, or a separate repo). */
959
+ readonly manifestSource: v.VariantSchema<"type", [v.ObjectSchema<{
960
+ readonly type: v.LiteralSchema<"colocated", undefined>;
961
+ /** File or directory path within the PR repo (read at the PR head branch). */
962
+ readonly path: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 500, undefined>]>;
963
+ }, undefined>, v.ObjectSchema<{
964
+ readonly type: v.LiteralSchema<"separate", undefined>;
965
+ /** `owner/repo` of the manifests repo. */
966
+ readonly repo: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.RegexAction<string, "must be \"owner/repo\"">]>;
967
+ /** Branch/tag/sha to read at; absent ⇒ that repo's default branch. */
968
+ readonly ref: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>]>, undefined>;
969
+ /** File or directory path within the manifests repo. */
970
+ readonly path: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 500, undefined>]>;
971
+ }, undefined>], undefined>;
972
+ /** How the environment URL is derived once applied. */
973
+ readonly url: v.VariantSchema<"source", [v.ObjectSchema<{
974
+ readonly source: v.LiteralSchema<"ingressTemplate", undefined>;
975
+ /** Host template, e.g. `{{branch}}.preview.example.com`; rendered with the provision vars. */
976
+ readonly hostTemplate: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 500, undefined>]>;
977
+ readonly scheme: v.OptionalSchema<v.PicklistSchema<["http", "https"], undefined>, undefined>;
978
+ }, undefined>, v.ObjectSchema<{
979
+ readonly source: v.LiteralSchema<"ingressStatus", undefined>;
980
+ /** Ingress object to read `.status.loadBalancer` from; absent ⇒ the only Ingress applied. */
981
+ readonly ingressName: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>]>, undefined>;
982
+ readonly scheme: v.OptionalSchema<v.PicklistSchema<["http", "https"], undefined>, undefined>;
983
+ }, undefined>, v.ObjectSchema<{
984
+ readonly source: v.LiteralSchema<"serviceStatus", undefined>;
985
+ /** Service object to read `.status.loadBalancer` (k3s ServiceLB) from. */
986
+ readonly serviceName: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>]>;
987
+ readonly port: v.OptionalSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 1, undefined>, v.MaxValueAction<number, 65535, undefined>]>, undefined>;
988
+ readonly scheme: v.OptionalSchema<v.PicklistSchema<["http", "https"], undefined>, undefined>;
989
+ }, undefined>], undefined>;
990
+ /**
991
+ * Optional image reference made available to the manifests as `{{image}}` (e.g. a
992
+ * CI-built image tagged by branch/sha). Itself a template over the provision vars.
993
+ */
994
+ readonly imageTemplate: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MaxLengthAction<string, 500, undefined>]>, undefined>;
995
+ /** Fallback TTL (ms) after which the env is swept + torn down. */
996
+ readonly defaultTtlMs: v.OptionalSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.MinValueAction<number, 60000, undefined>]>, undefined>;
997
+ /** Extra labels stamped on the namespace + every applied resource. */
998
+ readonly labels: v.OptionalSchema<v.RecordSchema<v.StringSchema<undefined>, v.StringSchema<undefined>, undefined>, undefined>;
999
+ /** Extra annotations stamped on the namespace. */
1000
+ readonly annotations: v.OptionalSchema<v.RecordSchema<v.StringSchema<undefined>, v.StringSchema<undefined>, undefined>, undefined>;
1001
+ }, undefined>;
1002
+ }, undefined>], undefined>;
441
1003
  readonly secrets: v.RecordSchema<v.StringSchema<undefined>, v.StringSchema<undefined>, undefined>;
442
1004
  }, undefined>;
443
1005
  export type RegisterEnvironmentProviderInput = v.InferOutput<typeof registerEnvironmentProviderSchema>;
@@ -447,140 +1009,202 @@ export declare const updateEnvironmentSecretsSchema: v.ObjectSchema<{
447
1009
  }, undefined>;
448
1010
  export type UpdateEnvironmentSecretsInput = v.InferOutput<typeof updateEnvironmentSecretsSchema>;
449
1011
  /**
450
- * Test (probe) a provider connection before saving. A manifest-driven provider
451
- * supplies the candidate `manifest` + `secrets`; a native provider supplies its
452
- * `config` (non-secret fields) + `secrets`. Nothing is persisted by a test.
1012
+ * Test (probe) a provider connection before saving: supply the candidate
1013
+ * discriminated `config` + its `secrets`. Nothing is persisted by a test.
453
1014
  */
454
1015
  export declare const testEnvironmentConnectionSchema: v.ObjectSchema<{
455
- readonly manifest: v.OptionalSchema<v.ObjectSchema<{
456
- readonly providerId: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, undefined>, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 64, undefined>]>;
457
- readonly label: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 120, undefined>]>;
458
- /** Management API root; provision/status/teardown paths are appended to it. */
459
- readonly baseUrl: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 2000, undefined>]>;
460
- readonly auth: v.VariantSchema<"type", [v.ObjectSchema<{
461
- readonly type: v.LiteralSchema<"none", undefined>;
462
- }, undefined>, v.ObjectSchema<{
463
- readonly type: v.LiteralSchema<"api_key", undefined>;
464
- readonly headerName: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>;
465
- readonly secretRef: v.ObjectSchema<{
466
- readonly key: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, undefined>, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 64, undefined>]>;
467
- }, undefined>;
468
- /** Optional prefix prepended to the secret value, e.g. `Token `. */
469
- readonly valuePrefix: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
470
- }, undefined>, v.ObjectSchema<{
471
- readonly type: v.LiteralSchema<"bearer", undefined>;
472
- readonly secretRef: v.ObjectSchema<{
473
- readonly key: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, undefined>, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 64, undefined>]>;
474
- }, undefined>;
475
- }, undefined>, v.ObjectSchema<{
476
- readonly type: v.LiteralSchema<"basic", undefined>;
477
- readonly usernameSecretRef: v.ObjectSchema<{
478
- readonly key: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, undefined>, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 64, undefined>]>;
479
- }, undefined>;
480
- readonly passwordSecretRef: v.ObjectSchema<{
481
- readonly key: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, undefined>, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 64, undefined>]>;
482
- }, undefined>;
483
- }, undefined>, v.ObjectSchema<{
484
- readonly type: v.LiteralSchema<"oauth2_client_credentials", undefined>;
485
- readonly tokenUrl: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 2000, undefined>]>;
486
- readonly clientIdSecretRef: v.ObjectSchema<{
487
- readonly key: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, undefined>, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 64, undefined>]>;
488
- }, undefined>;
489
- readonly clientSecretSecretRef: v.ObjectSchema<{
490
- readonly key: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, undefined>, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 64, undefined>]>;
491
- }, undefined>;
492
- readonly scope: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
493
- readonly audience: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
494
- }, undefined>, v.ObjectSchema<{
495
- readonly type: v.LiteralSchema<"custom_headers", undefined>;
496
- readonly headers: v.ArraySchema<v.ObjectSchema<{
497
- readonly name: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>;
1016
+ readonly config: v.OptionalSchema<v.VariantSchema<"kind", [v.ObjectSchema<{
1017
+ readonly kind: v.LiteralSchema<"manifest", undefined>;
1018
+ readonly manifest: v.ObjectSchema<{
1019
+ readonly providerId: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, undefined>, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 64, undefined>]>;
1020
+ readonly label: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 120, undefined>]>;
1021
+ /** Management API root; provision/status/teardown paths are appended to it. */
1022
+ readonly baseUrl: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 2000, undefined>]>;
1023
+ readonly auth: v.VariantSchema<"type", [v.ObjectSchema<{
1024
+ readonly type: v.LiteralSchema<"none", undefined>;
1025
+ }, undefined>, v.ObjectSchema<{
1026
+ readonly type: v.LiteralSchema<"api_key", undefined>;
1027
+ readonly headerName: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>;
498
1028
  readonly secretRef: v.ObjectSchema<{
499
1029
  readonly key: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, undefined>, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 64, undefined>]>;
500
1030
  }, undefined>;
1031
+ /** Optional prefix prepended to the secret value, e.g. `Token `. */
1032
+ readonly valuePrefix: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
1033
+ }, undefined>, v.ObjectSchema<{
1034
+ readonly type: v.LiteralSchema<"bearer", undefined>;
1035
+ readonly secretRef: v.ObjectSchema<{
1036
+ readonly key: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, undefined>, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 64, undefined>]>;
1037
+ }, undefined>;
1038
+ }, undefined>, v.ObjectSchema<{
1039
+ readonly type: v.LiteralSchema<"basic", undefined>;
1040
+ readonly usernameSecretRef: v.ObjectSchema<{
1041
+ readonly key: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, undefined>, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 64, undefined>]>;
1042
+ }, undefined>;
1043
+ readonly passwordSecretRef: v.ObjectSchema<{
1044
+ readonly key: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, undefined>, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 64, undefined>]>;
1045
+ }, undefined>;
1046
+ }, undefined>, v.ObjectSchema<{
1047
+ readonly type: v.LiteralSchema<"oauth2_client_credentials", undefined>;
1048
+ readonly tokenUrl: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 2000, undefined>]>;
1049
+ readonly clientIdSecretRef: v.ObjectSchema<{
1050
+ readonly key: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, undefined>, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 64, undefined>]>;
1051
+ }, undefined>;
1052
+ readonly clientSecretSecretRef: v.ObjectSchema<{
1053
+ readonly key: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, undefined>, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 64, undefined>]>;
1054
+ }, undefined>;
1055
+ readonly scope: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
1056
+ readonly audience: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
1057
+ }, undefined>, v.ObjectSchema<{
1058
+ readonly type: v.LiteralSchema<"custom_headers", undefined>;
1059
+ readonly headers: v.ArraySchema<v.ObjectSchema<{
1060
+ readonly name: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>;
1061
+ readonly secretRef: v.ObjectSchema<{
1062
+ readonly key: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, undefined>, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 64, undefined>]>;
1063
+ }, undefined>;
1064
+ }, undefined>, undefined>;
1065
+ }, undefined>], undefined>;
1066
+ readonly provision: v.ObjectSchema<{
1067
+ readonly method: v.PicklistSchema<["GET", "POST", "PUT", "PATCH", "DELETE"], undefined>;
1068
+ readonly pathTemplate: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MaxLengthAction<string, 2000, undefined>]>;
1069
+ readonly query: v.OptionalSchema<v.ArraySchema<v.ObjectSchema<{
1070
+ readonly key: v.StringSchema<undefined>;
1071
+ readonly value: v.StringSchema<undefined>;
1072
+ }, undefined>, undefined>, undefined>;
1073
+ readonly headers: v.OptionalSchema<v.ArraySchema<v.ObjectSchema<{
1074
+ readonly name: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>;
1075
+ readonly value: v.StringSchema<undefined>;
1076
+ }, undefined>, undefined>, undefined>;
1077
+ readonly bodyTemplate: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
1078
+ /** Per-call timeout (ms). Bounded; defaults applied by the adapter. */
1079
+ readonly timeoutMs: v.OptionalSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.MinValueAction<number, 1, undefined>, v.MaxValueAction<number, 60000, undefined>]>, undefined>;
1080
+ }, undefined>;
1081
+ /** Optional: polled to observe async provisioning progress. */
1082
+ readonly status: v.OptionalSchema<v.ObjectSchema<{
1083
+ readonly method: v.PicklistSchema<["GET", "POST", "PUT", "PATCH", "DELETE"], undefined>;
1084
+ readonly pathTemplate: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MaxLengthAction<string, 2000, undefined>]>;
1085
+ readonly query: v.OptionalSchema<v.ArraySchema<v.ObjectSchema<{
1086
+ readonly key: v.StringSchema<undefined>;
1087
+ readonly value: v.StringSchema<undefined>;
1088
+ }, undefined>, undefined>, undefined>;
1089
+ readonly headers: v.OptionalSchema<v.ArraySchema<v.ObjectSchema<{
1090
+ readonly name: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>;
1091
+ readonly value: v.StringSchema<undefined>;
1092
+ }, undefined>, undefined>, undefined>;
1093
+ readonly bodyTemplate: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
1094
+ /** Per-call timeout (ms). Bounded; defaults applied by the adapter. */
1095
+ readonly timeoutMs: v.OptionalSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.MinValueAction<number, 1, undefined>, v.MaxValueAction<number, 60000, undefined>]>, undefined>;
501
1096
  }, undefined>, undefined>;
502
- }, undefined>], undefined>;
503
- readonly provision: v.ObjectSchema<{
504
- readonly method: v.PicklistSchema<["GET", "POST", "PUT", "PATCH", "DELETE"], undefined>;
505
- readonly pathTemplate: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MaxLengthAction<string, 2000, undefined>]>;
506
- readonly query: v.OptionalSchema<v.ArraySchema<v.ObjectSchema<{
507
- readonly key: v.StringSchema<undefined>;
508
- readonly value: v.StringSchema<undefined>;
509
- }, undefined>, undefined>, undefined>;
510
- readonly headers: v.OptionalSchema<v.ArraySchema<v.ObjectSchema<{
511
- readonly name: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>;
512
- readonly value: v.StringSchema<undefined>;
513
- }, undefined>, undefined>, undefined>;
514
- readonly bodyTemplate: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
515
- /** Per-call timeout (ms). Bounded; defaults applied by the adapter. */
516
- readonly timeoutMs: v.OptionalSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.MinValueAction<number, 1, undefined>, v.MaxValueAction<number, 60000, undefined>]>, undefined>;
517
- }, undefined>;
518
- /** Optional: polled to observe async provisioning progress. */
519
- readonly status: v.OptionalSchema<v.ObjectSchema<{
520
- readonly method: v.PicklistSchema<["GET", "POST", "PUT", "PATCH", "DELETE"], undefined>;
521
- readonly pathTemplate: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MaxLengthAction<string, 2000, undefined>]>;
522
- readonly query: v.OptionalSchema<v.ArraySchema<v.ObjectSchema<{
523
- readonly key: v.StringSchema<undefined>;
524
- readonly value: v.StringSchema<undefined>;
525
- }, undefined>, undefined>, undefined>;
526
- readonly headers: v.OptionalSchema<v.ArraySchema<v.ObjectSchema<{
527
- readonly name: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>;
528
- readonly value: v.StringSchema<undefined>;
529
- }, undefined>, undefined>, undefined>;
530
- readonly bodyTemplate: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
531
- /** Per-call timeout (ms). Bounded; defaults applied by the adapter. */
532
- readonly timeoutMs: v.OptionalSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.MinValueAction<number, 1, undefined>, v.MaxValueAction<number, 60000, undefined>]>, undefined>;
533
- }, undefined>, undefined>;
534
- /** Optional: called to destroy the environment (manual or on TTL expiry). */
535
- readonly teardown: v.OptionalSchema<v.ObjectSchema<{
536
- readonly method: v.PicklistSchema<["GET", "POST", "PUT", "PATCH", "DELETE"], undefined>;
537
- readonly pathTemplate: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MaxLengthAction<string, 2000, undefined>]>;
538
- readonly query: v.OptionalSchema<v.ArraySchema<v.ObjectSchema<{
539
- readonly key: v.StringSchema<undefined>;
540
- readonly value: v.StringSchema<undefined>;
541
- }, undefined>, undefined>, undefined>;
542
- readonly headers: v.OptionalSchema<v.ArraySchema<v.ObjectSchema<{
543
- readonly name: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>;
544
- readonly value: v.StringSchema<undefined>;
545
- }, undefined>, undefined>, undefined>;
546
- readonly bodyTemplate: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
547
- /** Per-call timeout (ms). Bounded; defaults applied by the adapter. */
548
- readonly timeoutMs: v.OptionalSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.MinValueAction<number, 1, undefined>, v.MaxValueAction<number, 60000, undefined>]>, undefined>;
549
- }, undefined>, undefined>;
550
- readonly response: v.ObjectSchema<{
551
- readonly urlPath: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
552
- readonly statusPath: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
553
- readonly statusMap: v.OptionalSchema<v.ArraySchema<v.ObjectSchema<{
554
- readonly from: v.StringSchema<undefined>;
555
- readonly to: v.PicklistSchema<["provisioning", "ready", "failed", "expired", "tearing_down", "torn_down"], undefined>;
556
- }, undefined>, undefined>, undefined>;
557
- readonly expiresAtPath: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
558
- readonly externalIdPath: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
559
- readonly access: v.OptionalSchema<v.ObjectSchema<{
560
- readonly scheme: v.PicklistSchema<["none", "bearer", "basic", "custom_header"], undefined>;
561
- readonly tokenPath: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
562
- readonly usernamePath: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
563
- readonly passwordPath: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
564
- readonly headerName: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
565
- readonly headerValuePath: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
1097
+ /** Optional: called to destroy the environment (manual or on TTL expiry). */
1098
+ readonly teardown: v.OptionalSchema<v.ObjectSchema<{
1099
+ readonly method: v.PicklistSchema<["GET", "POST", "PUT", "PATCH", "DELETE"], undefined>;
1100
+ readonly pathTemplate: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MaxLengthAction<string, 2000, undefined>]>;
1101
+ readonly query: v.OptionalSchema<v.ArraySchema<v.ObjectSchema<{
1102
+ readonly key: v.StringSchema<undefined>;
1103
+ readonly value: v.StringSchema<undefined>;
1104
+ }, undefined>, undefined>, undefined>;
1105
+ readonly headers: v.OptionalSchema<v.ArraySchema<v.ObjectSchema<{
1106
+ readonly name: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>;
1107
+ readonly value: v.StringSchema<undefined>;
1108
+ }, undefined>, undefined>, undefined>;
1109
+ readonly bodyTemplate: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
1110
+ /** Per-call timeout (ms). Bounded; defaults applied by the adapter. */
1111
+ readonly timeoutMs: v.OptionalSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.MinValueAction<number, 1, undefined>, v.MaxValueAction<number, 60000, undefined>]>, undefined>;
566
1112
  }, undefined>, undefined>;
1113
+ readonly response: v.ObjectSchema<{
1114
+ readonly urlPath: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
1115
+ readonly statusPath: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
1116
+ readonly statusMap: v.OptionalSchema<v.ArraySchema<v.ObjectSchema<{
1117
+ readonly from: v.StringSchema<undefined>;
1118
+ readonly to: v.PicklistSchema<["provisioning", "ready", "failed", "expired", "tearing_down", "torn_down"], undefined>;
1119
+ }, undefined>, undefined>, undefined>;
1120
+ readonly expiresAtPath: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
1121
+ readonly externalIdPath: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
1122
+ readonly access: v.OptionalSchema<v.ObjectSchema<{
1123
+ readonly scheme: v.PicklistSchema<["none", "bearer", "basic", "custom_header"], undefined>;
1124
+ readonly tokenPath: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
1125
+ readonly usernamePath: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
1126
+ readonly passwordPath: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
1127
+ readonly headerName: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
1128
+ readonly headerValuePath: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
1129
+ }, undefined>, undefined>;
1130
+ }, undefined>;
1131
+ /** Fallback TTL (ms) when the response carries no explicit expiry. */
1132
+ readonly defaultTtlMs: v.OptionalSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.MinValueAction<number, 60000, undefined>]>, undefined>;
1133
+ /**
1134
+ * Opaque, provider-specific configuration for a *native* injected adapter (e.g. a
1135
+ * Kargo project, link-selection key, status map). The generic HttpEnvironmentProvider
1136
+ * ignores it entirely; a native adapter (injected via `buildNodeContainer({
1137
+ * environmentProvider })` / `startLocal({ environmentProvider })`) reads + validates it
1138
+ * off the per-call `manifest`. This is the per-WORKSPACE config carrier for native
1139
+ * adapters — the deployment-wide provider singleton has no other way to receive
1140
+ * per-workspace settings. NOT covered by the manifest URL/SSRF checks (which only guard
1141
+ * `baseUrl`/`tokenUrl`); an adapter that puts a URL here must guard it itself (reuse the
1142
+ * exported `UrlSafetyPolicy`). See `backend/docs/native-environment-adapter.md`.
1143
+ */
1144
+ readonly providerConfig: v.OptionalSchema<v.RecordSchema<v.StringSchema<undefined>, v.UnknownSchema, undefined>, undefined>;
567
1145
  }, undefined>;
568
- /** Fallback TTL (ms) when the response carries no explicit expiry. */
569
- readonly defaultTtlMs: v.OptionalSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.MinValueAction<number, 60000, undefined>]>, undefined>;
570
- /**
571
- * Opaque, provider-specific configuration for a *native* injected adapter (e.g. a
572
- * Kargo project, link-selection key, status map). The generic HttpEnvironmentProvider
573
- * ignores it entirely; a native adapter (injected via `buildNodeContainer({
574
- * environmentProvider })` / `startLocal({ environmentProvider })`) reads + validates it
575
- * off the per-call `manifest`. This is the per-WORKSPACE config carrier for native
576
- * adapters the deployment-wide provider singleton has no other way to receive
577
- * per-workspace settings. NOT covered by the manifest URL/SSRF checks (which only guard
578
- * `baseUrl`/`tokenUrl`); an adapter that puts a URL here must guard it itself (reuse the
579
- * exported `UrlSafetyPolicy`). See `backend/docs/native-environment-adapter.md`.
580
- */
581
- readonly providerConfig: v.OptionalSchema<v.RecordSchema<v.StringSchema<undefined>, v.UnknownSchema, undefined>, undefined>;
582
- }, undefined>, undefined>;
583
- readonly config: v.OptionalSchema<v.RecordSchema<v.StringSchema<undefined>, v.StringSchema<undefined>, undefined>, undefined>;
1146
+ }, undefined>, v.ObjectSchema<{
1147
+ readonly kind: v.LiteralSchema<"kubernetes", undefined>;
1148
+ readonly kubernetes: v.ObjectSchema<{
1149
+ /** Human label for the connection (shown in the UI). */
1150
+ readonly label: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 120, undefined>]>;
1151
+ /** kube-apiserver root URL, e.g. `https://my-cluster.example:6443`. */
1152
+ readonly apiServerUrl: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 2000, undefined>]>;
1153
+ /** PEM CA bundle to verify the apiserver TLS cert (omit only for a publicly-trusted CA). */
1154
+ readonly caCertPem: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
1155
+ /** Skip apiserver TLS verification strongly discouraged; kind/dev clusters only. */
1156
+ readonly insecureSkipTlsVerify: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
1157
+ /**
1158
+ * Namespace name template for the per-PR environment, e.g. `cf-env-{{pullNumber}}`.
1159
+ * Rendered with the provision vars then sanitized to an RFC1123 label; absent ⇒ a
1160
+ * default derived from the PR number / block id.
1161
+ */
1162
+ readonly namespaceTemplate: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 200, undefined>]>, undefined>;
1163
+ /** Where the manifests are read from (co-located in the PR repo, or a separate repo). */
1164
+ readonly manifestSource: v.VariantSchema<"type", [v.ObjectSchema<{
1165
+ readonly type: v.LiteralSchema<"colocated", undefined>;
1166
+ /** File or directory path within the PR repo (read at the PR head branch). */
1167
+ readonly path: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 500, undefined>]>;
1168
+ }, undefined>, v.ObjectSchema<{
1169
+ readonly type: v.LiteralSchema<"separate", undefined>;
1170
+ /** `owner/repo` of the manifests repo. */
1171
+ readonly repo: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.RegexAction<string, "must be \"owner/repo\"">]>;
1172
+ /** Branch/tag/sha to read at; absent ⇒ that repo's default branch. */
1173
+ readonly ref: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>]>, undefined>;
1174
+ /** File or directory path within the manifests repo. */
1175
+ readonly path: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 500, undefined>]>;
1176
+ }, undefined>], undefined>;
1177
+ /** How the environment URL is derived once applied. */
1178
+ readonly url: v.VariantSchema<"source", [v.ObjectSchema<{
1179
+ readonly source: v.LiteralSchema<"ingressTemplate", undefined>;
1180
+ /** Host template, e.g. `{{branch}}.preview.example.com`; rendered with the provision vars. */
1181
+ readonly hostTemplate: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 500, undefined>]>;
1182
+ readonly scheme: v.OptionalSchema<v.PicklistSchema<["http", "https"], undefined>, undefined>;
1183
+ }, undefined>, v.ObjectSchema<{
1184
+ readonly source: v.LiteralSchema<"ingressStatus", undefined>;
1185
+ /** Ingress object to read `.status.loadBalancer` from; absent ⇒ the only Ingress applied. */
1186
+ readonly ingressName: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>]>, undefined>;
1187
+ readonly scheme: v.OptionalSchema<v.PicklistSchema<["http", "https"], undefined>, undefined>;
1188
+ }, undefined>, v.ObjectSchema<{
1189
+ readonly source: v.LiteralSchema<"serviceStatus", undefined>;
1190
+ /** Service object to read `.status.loadBalancer` (k3s ServiceLB) from. */
1191
+ readonly serviceName: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>]>;
1192
+ readonly port: v.OptionalSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 1, undefined>, v.MaxValueAction<number, 65535, undefined>]>, undefined>;
1193
+ readonly scheme: v.OptionalSchema<v.PicklistSchema<["http", "https"], undefined>, undefined>;
1194
+ }, undefined>], undefined>;
1195
+ /**
1196
+ * Optional image reference made available to the manifests as `{{image}}` (e.g. a
1197
+ * CI-built image tagged by branch/sha). Itself a template over the provision vars.
1198
+ */
1199
+ readonly imageTemplate: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MaxLengthAction<string, 500, undefined>]>, undefined>;
1200
+ /** Fallback TTL (ms) after which the env is swept + torn down. */
1201
+ readonly defaultTtlMs: v.OptionalSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.MinValueAction<number, 60000, undefined>]>, undefined>;
1202
+ /** Extra labels stamped on the namespace + every applied resource. */
1203
+ readonly labels: v.OptionalSchema<v.RecordSchema<v.StringSchema<undefined>, v.StringSchema<undefined>, undefined>, undefined>;
1204
+ /** Extra annotations stamped on the namespace. */
1205
+ readonly annotations: v.OptionalSchema<v.RecordSchema<v.StringSchema<undefined>, v.StringSchema<undefined>, undefined>, undefined>;
1206
+ }, undefined>;
1207
+ }, undefined>], undefined>, undefined>;
584
1208
  readonly secrets: v.OptionalSchema<v.RecordSchema<v.StringSchema<undefined>, v.StringSchema<undefined>, undefined>, undefined>;
585
1209
  }, undefined>;
586
1210
  export type TestEnvironmentConnectionInput = v.InferOutput<typeof testEnvironmentConnectionSchema>;