mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-23 17:33:51 +02:00
Bumps [zod](https://github.com/colinhacks/zod) from 3.25.76 to 4.4.3. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/colinhacks/zod/releases">zod's releases</a>.</em></p> <blockquote> <h2>v4.4.3</h2> <h2>Commits:</h2> <ul> <li>4c2fa95ce3f3390fbc522324e406b4e9e89b88f9 docs: use Zernio primary wordmark for gold sponsor logo</li> <li>2aeec83eb135e3a83756e973ef44845fc5a455d2 docs: prune lapsed gold sponsors and rebalance logo sizing</li> <li>7391be88ac1ee5cd02057f5ccc012a1f5df4efd0 docs: prune lapsed silver/bronze sponsors and add active ones</li> <li>2c703322a21b4e2b12f33f49ea8430c451a68b4f docs: normalize bronze sponsor logos to github avatar pattern</li> <li>9195250cab0e7950efe39c3926d6c203b4b0a170 docs: remove Mintlify from bronze sponsors (churned)</li> <li>b8dffe9e62f17e6571e6249d05cc5102b54d94e4 docs: remove Numeric and Speakeasy (2+ missed monthly cycles)</li> <li>1cab69383fcdeae2a366d5e2a2fc4d8fc765d168 fix(v4): restore catch handling for absent object keys (<a href="https://redirect.github.com/colinhacks/zod/issues/5937">#5937</a>) (<a href="https://redirect.github.com/colinhacks/zod/issues/5939">#5939</a>)</li> <li>c2be4f819064eed62c7c350a2d399b5faecd15f8 fix(v4): generalize optin/fallback to transform; restore preprocess on absent keys (<a href="https://redirect.github.com/colinhacks/zod/issues/5941">#5941</a>)</li> <li>f3c9ec03ba7a28ae72d25cc295f38674bee0f559 4.4.3</li> <li>1fb56a5c18c27102dbc92260a4007c7732a0ccca docs: document release procedure in AGENTS.md</li> </ul> <h2>v4.4.2</h2> <h2>Commits:</h2> <ul> <li>0c62df0ea19fd05abdf90473e9eef7eea530fab2 Clean up docs navigation and stale labels (<a href="https://redirect.github.com/colinhacks/zod/issues/5901">#5901</a>)</li> <li>20cc794895cc8604fe0c87d83a5d1c3f89fad0ac chore: add security policy and refresh tooling deps</li> <li>6fbe07b0177efdd1bf1c0b05160e70d7a0702337 fix(docs): heading anchor links now include the hash so it doesnt scoll all the way up, follows navbar logic (<a href="https://redirect.github.com/colinhacks/zod/issues/5791">#5791</a>)</li> <li>4bbed1b1c73eca4ce9e59b1189ed236aa6c8b5bd Tighten discriminated union option typing</li> <li>bbac3e567e7fccfaaf7cdc97f1ce30c295e2c908 Update PR guidance for agents</li> <li>cf0dc942a32805c292fff59ade20a7ace980735a Merge remote-tracking branch 'origin/main' into fix-discriminated-union-key-constraint</li> <li>292c894a5fd2aa42e527900b83d8d7a3009a709c docs: add Zernio gold sponsor</li> <li>1fc9f311c28dcf80d0bb5a36b177086cbc3d8eca docs: document codec inversion</li> <li>1373c85da9aeff704a9762d27bc58699618aefb7 docs: remove AI disclosure guidance</li> <li>e20d02b473c08e3a4e557bc610b1b5fac079b649 chore: ignore triage notes</li> <li>e58ea4d91b1dfe8194b73508203213cbc7e9c936 docs: test Zod Mini tab code heights</li> <li>905761a5d127e8d5dd2ebb3bc88c75cb0b8149ff docs: document preprocess input type narrowing</li> <li>bf64bac850d4dee2b7dde7e64909d5d796d32043 chore: tighten test guidance in AGENTS.md</li> <li>8ec4e73f4c4693b6361ad591be40fb41eb8a9f95 chore: update play.ts scratch</li> <li>02c2baf7d0d615872fa4528a8020603b71211702 Make z.preprocess defer optionality to inner schema (<a href="https://redirect.github.com/colinhacks/zod/issues/5929">#5929</a>)</li> <li>88015df8e25c44fb5385eb3ef28935119cd5edea fix(docs): drop deprecated <code>baseUrl</code> from tsconfig</li> <li>c59d4474e3b4cad1b323462186cf607178ce8267 4.4.2</li> </ul> <h2>v4.4.1</h2> <h2>Commits:</h2> <ul> <li>481f7be4238c83ed58183f921b2646f340a91c6a ci: gate release publishing on full test workflow</li> <li>95ccab423aec720b2523c3a64cdc7e3204537cc7 test(v3): restore optional undefined expectations</li> <li>cede2c63739a5823d6aa5093d291e9a111da943d fix(v4): reject tuple holes before required defaults (<a href="https://redirect.github.com/colinhacks/zod/issues/5900">#5900</a>)</li> <li>edd0bf0f5ada4a8dc581c259407d7bbad0a71ea7 release: 4.4.1</li> <li>180d83d1dbe6a59260710cc8637a3dea2281ee56 docs: remove Jazz featured sponsor</li> </ul> <h2>v4.4.0</h2> <h2>4.4.0</h2> <p>This is a minor release with a wide set of correctness and soundness fixes. Some fixes intentionally make Zod stricter, so code that depended on previously accepted invalid or ambiguous inputs may need small updates.</p> <h2>Potentially breaking bug fixes</h2> <!-- raw HTML omitted --> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/colinhacks/zod/commit/1fb56a5c18c27102dbc92260a4007c7732a0ccca"><code>1fb56a5</code></a> docs: document release procedure in AGENTS.md</li> <li><a href="https://github.com/colinhacks/zod/commit/f3c9ec03ba7a28ae72d25cc295f38674bee0f559"><code>f3c9ec0</code></a> 4.4.3</li> <li><a href="https://github.com/colinhacks/zod/commit/c2be4f819064eed62c7c350a2d399b5faecd15f8"><code>c2be4f8</code></a> fix(v4): generalize optin/fallback to transform; restore preprocess on absent...</li> <li><a href="https://github.com/colinhacks/zod/commit/1cab69383fcdeae2a366d5e2a2fc4d8fc765d168"><code>1cab693</code></a> fix(v4): restore catch handling for absent object keys (<a href="https://redirect.github.com/colinhacks/zod/issues/5937">#5937</a>) (<a href="https://redirect.github.com/colinhacks/zod/issues/5939">#5939</a>)</li> <li><a href="https://github.com/colinhacks/zod/commit/b8dffe9e62f17e6571e6249d05cc5102b54d94e4"><code>b8dffe9</code></a> docs: remove Numeric and Speakeasy (2+ missed monthly cycles)</li> <li><a href="https://github.com/colinhacks/zod/commit/9195250cab0e7950efe39c3926d6c203b4b0a170"><code>9195250</code></a> docs: remove Mintlify from bronze sponsors (churned)</li> <li><a href="https://github.com/colinhacks/zod/commit/2c703322a21b4e2b12f33f49ea8430c451a68b4f"><code>2c70332</code></a> docs: normalize bronze sponsor logos to github avatar pattern</li> <li><a href="https://github.com/colinhacks/zod/commit/7391be88ac1ee5cd02057f5ccc012a1f5df4efd0"><code>7391be8</code></a> docs: prune lapsed silver/bronze sponsors and add active ones</li> <li><a href="https://github.com/colinhacks/zod/commit/2aeec83eb135e3a83756e973ef44845fc5a455d2"><code>2aeec83</code></a> docs: prune lapsed gold sponsors and rebalance logo sizing</li> <li><a href="https://github.com/colinhacks/zod/commit/4c2fa95ce3f3390fbc522324e406b4e9e89b88f9"><code>4c2fa95</code></a> docs: use Zernio primary wordmark for gold sponsor logo</li> <li>Additional commits viewable in <a href="https://github.com/colinhacks/zod/compare/v3.25.76...v4.4.3">compare view</a></li> </ul> </details> <details> <summary>Maintainer changes</summary> <p>This version was pushed to npm by <a href="https://www.npmjs.com/~GitHub%20Actions">GitHub Actions</a>, a new releaser for zod since your current version.</p> </details> <br /> --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Priya Raman <priya@paperclip.ing> Co-authored-by: Paperclip <noreply@paperclip.ing>
427 lines
16 KiB
TypeScript
427 lines
16 KiB
TypeScript
import { z } from "zod";
|
|
import {
|
|
SECRET_BINDING_TARGET_TYPES,
|
|
SECRET_MANAGED_MODES,
|
|
SECRET_PROJECTION_CLASSES,
|
|
SECRET_PROVIDER_CONFIG_STATUSES,
|
|
SECRET_PROVIDERS,
|
|
SECRET_STATUSES,
|
|
} from "../constants.js";
|
|
|
|
const secretKeySchema = z.string().trim().min(1).max(120).regex(/^[a-zA-Z0-9_.-]+$/);
|
|
const secretVersionSelectorSchema = z.union([z.literal("latest"), z.number().int().positive()]);
|
|
const creatableSecretStatusSchema = z.enum(["active", "disabled", "archived"]);
|
|
|
|
export const envBindingPlainSchema = z.object({
|
|
type: z.literal("plain"),
|
|
value: z.string(),
|
|
});
|
|
|
|
export const envBindingSecretRefSchema = z.object({
|
|
type: z.literal("secret_ref"),
|
|
secretId: z.string().guid(),
|
|
version: secretVersionSelectorSchema.optional(),
|
|
projectionClass: z.enum(SECRET_PROJECTION_CLASSES).optional(),
|
|
projectionAllowlistKey: z.string().trim().min(1).max(160).optional().nullable(),
|
|
});
|
|
|
|
export const envBindingUserSecretRefSchema = z.object({
|
|
type: z.literal("user_secret_ref"),
|
|
key: secretKeySchema,
|
|
version: secretVersionSelectorSchema.optional(),
|
|
required: z.boolean().optional().default(true),
|
|
allowMissingOverride: z.boolean().optional().default(false),
|
|
});
|
|
|
|
// Backward-compatible union that accepts legacy inline values.
|
|
export const envBindingSchema = z.union([
|
|
z.string(),
|
|
envBindingPlainSchema,
|
|
envBindingSecretRefSchema,
|
|
envBindingUserSecretRefSchema,
|
|
]);
|
|
|
|
export const envConfigSchema = z.record(z.string(), envBindingSchema);
|
|
|
|
export const createSecretSchema = z.object({
|
|
name: z.string().min(1),
|
|
key: secretKeySchema.optional(),
|
|
provider: z.enum(SECRET_PROVIDERS).optional(),
|
|
providerConfigId: z.string().guid().optional().nullable(),
|
|
managedMode: z.enum(SECRET_MANAGED_MODES).optional(),
|
|
value: z.string().min(1).optional().nullable(),
|
|
description: z.string().optional().nullable(),
|
|
externalRef: z.string().optional().nullable(),
|
|
providerMetadata: z.record(z.string(), z.unknown()).optional().nullable(),
|
|
providerVersionRef: z.string().optional().nullable(),
|
|
}).superRefine((value, ctx) => {
|
|
if ((value.managedMode ?? "paperclip_managed") === "external_reference") {
|
|
if (!value.externalRef?.trim()) {
|
|
ctx.addIssue({
|
|
code: z.ZodIssueCode.custom,
|
|
path: ["externalRef"],
|
|
message: "External reference secrets require externalRef",
|
|
});
|
|
}
|
|
return;
|
|
}
|
|
if (value.externalRef?.trim()) {
|
|
ctx.addIssue({
|
|
code: z.ZodIssueCode.custom,
|
|
path: ["externalRef"],
|
|
message: "Managed secrets cannot set externalRef",
|
|
});
|
|
}
|
|
if (!value.value?.trim()) {
|
|
ctx.addIssue({
|
|
code: z.ZodIssueCode.custom,
|
|
path: ["value"],
|
|
message: "Managed secrets require value",
|
|
});
|
|
}
|
|
});
|
|
|
|
export type CreateSecret = z.infer<typeof createSecretSchema>;
|
|
|
|
function requireSecretRotationInput(
|
|
value: {
|
|
value?: string | null;
|
|
externalRef?: string | null;
|
|
providerVersionRef?: string | null;
|
|
providerConfigId?: string | null;
|
|
},
|
|
ctx: z.RefinementCtx,
|
|
) {
|
|
if (
|
|
!value.value?.trim() &&
|
|
!value.externalRef?.trim() &&
|
|
value.providerVersionRef == null &&
|
|
value.providerConfigId == null
|
|
) {
|
|
ctx.addIssue({
|
|
code: z.ZodIssueCode.custom,
|
|
path: ["value"],
|
|
message: "Secret rotation requires value, externalRef, providerVersionRef, or providerConfigId",
|
|
});
|
|
}
|
|
}
|
|
|
|
export const rotateSecretSchema = z.object({
|
|
value: z.string().min(1).optional().nullable(),
|
|
externalRef: z.string().optional().nullable(),
|
|
providerVersionRef: z.string().optional().nullable(),
|
|
providerConfigId: z.string().guid().optional().nullable(),
|
|
}).superRefine(requireSecretRotationInput);
|
|
|
|
export type RotateSecret = z.infer<typeof rotateSecretSchema>;
|
|
|
|
export const updateSecretSchema = z.object({
|
|
name: z.string().min(1).optional(),
|
|
key: secretKeySchema.optional(),
|
|
status: z.enum(SECRET_STATUSES).optional(),
|
|
providerConfigId: z.string().guid().optional().nullable(),
|
|
description: z.string().optional().nullable(),
|
|
externalRef: z.string().optional().nullable(),
|
|
providerMetadata: z.record(z.string(), z.unknown()).optional().nullable(),
|
|
});
|
|
|
|
export type UpdateSecret = z.infer<typeof updateSecretSchema>;
|
|
|
|
export const secretBindingTargetSchema = z.object({
|
|
targetType: z.enum(SECRET_BINDING_TARGET_TYPES),
|
|
targetId: z.string().min(1),
|
|
configPath: z.string().min(1),
|
|
});
|
|
|
|
export const createSecretBindingSchema = secretBindingTargetSchema.extend({
|
|
secretId: z.string().guid(),
|
|
versionSelector: secretVersionSelectorSchema.default("latest"),
|
|
required: z.boolean().default(true),
|
|
label: z.string().optional().nullable(),
|
|
projectionClass: z.enum(SECRET_PROJECTION_CLASSES).optional(),
|
|
projectionAllowlistKey: z.string().trim().min(1).max(160).optional().nullable(),
|
|
});
|
|
|
|
export type CreateSecretBinding = z.infer<typeof createSecretBindingSchema>;
|
|
|
|
export const createUserSecretDefinitionSchema = z.object({
|
|
key: secretKeySchema,
|
|
name: z.string().trim().min(1).max(160),
|
|
description: z.string().trim().max(500).optional().nullable(),
|
|
status: creatableSecretStatusSchema.optional(),
|
|
provider: z.enum(SECRET_PROVIDERS).optional(),
|
|
providerConfigId: z.string().guid().optional().nullable(),
|
|
managedMode: z.enum(SECRET_MANAGED_MODES).optional(),
|
|
providerMetadata: z.record(z.string(), z.unknown()).optional().nullable(),
|
|
usageGuidance: z.string().trim().max(1000).optional().nullable(),
|
|
});
|
|
|
|
export type CreateUserSecretDefinition = z.infer<typeof createUserSecretDefinitionSchema>;
|
|
|
|
export const updateUserSecretDefinitionSchema = z.object({
|
|
name: z.string().trim().min(1).max(160).optional(),
|
|
description: z.string().trim().max(500).optional().nullable(),
|
|
status: z.enum(SECRET_STATUSES).optional(),
|
|
providerConfigId: z.string().guid().optional().nullable(),
|
|
providerMetadata: z.record(z.string(), z.unknown()).optional().nullable(),
|
|
usageGuidance: z.string().trim().max(1000).optional().nullable(),
|
|
});
|
|
|
|
export type UpdateUserSecretDefinition = z.infer<typeof updateUserSecretDefinitionSchema>;
|
|
|
|
export const createUserSecretValueSchema = z.object({
|
|
definitionKey: secretKeySchema.optional(),
|
|
definitionId: z.string().guid().optional(),
|
|
value: z.string().min(1).optional().nullable(),
|
|
externalRef: z.string().optional().nullable(),
|
|
providerVersionRef: z.string().optional().nullable(),
|
|
providerConfigId: z.string().guid().optional().nullable(),
|
|
}).superRefine((value, ctx) => {
|
|
if (!value.definitionKey && !value.definitionId) {
|
|
ctx.addIssue({
|
|
code: z.ZodIssueCode.custom,
|
|
path: ["definitionId"],
|
|
message: "User secret value requires definitionId or definitionKey",
|
|
});
|
|
}
|
|
if (!value.value?.trim() && !value.externalRef?.trim()) {
|
|
ctx.addIssue({
|
|
code: z.ZodIssueCode.custom,
|
|
path: ["value"],
|
|
message: "User secret value requires value or externalRef",
|
|
});
|
|
}
|
|
});
|
|
|
|
export type CreateUserSecretValue = z.infer<typeof createUserSecretValueSchema>;
|
|
|
|
export const updateUserSecretValueSchema = z.object({
|
|
status: z.enum(SECRET_STATUSES).optional(),
|
|
value: z.string().min(1).optional().nullable(),
|
|
externalRef: z.string().min(1).optional().nullable(),
|
|
providerVersionRef: z.string().min(1).optional().nullable(),
|
|
providerConfigId: z.string().guid().optional().nullable(),
|
|
});
|
|
|
|
export type UpdateUserSecretValue = z.infer<typeof updateUserSecretValueSchema>;
|
|
|
|
export const rotateUserSecretValueSchema = z.object({
|
|
value: z.string().min(1).optional().nullable(),
|
|
externalRef: z.string().min(1).optional().nullable(),
|
|
providerVersionRef: z.string().min(1).optional().nullable(),
|
|
providerConfigId: z.string().guid().optional().nullable(),
|
|
}).superRefine(requireSecretRotationInput);
|
|
|
|
export type RotateUserSecretValue = z.infer<typeof rotateUserSecretValueSchema>;
|
|
|
|
export const createUserSecretDeclarationSchema = secretBindingTargetSchema.extend({
|
|
definitionKey: secretKeySchema,
|
|
envKey: z.string().trim().min(1),
|
|
versionSelector: secretVersionSelectorSchema.default("latest"),
|
|
required: z.boolean().default(true),
|
|
allowMissingOverride: z.boolean().default(false),
|
|
label: z.string().optional().nullable(),
|
|
});
|
|
|
|
export type CreateUserSecretDeclaration = z.infer<typeof createUserSecretDeclarationSchema>;
|
|
|
|
const safeShortText = z.string().trim().min(1).max(160);
|
|
const optionalSafeShortText = safeShortText.optional().nullable();
|
|
|
|
const deniedProviderConfigKeyPattern =
|
|
/^(access[-_]?key([-_]?id)?|secret[-_]?access[-_]?key|secret[-_]?key|token|password|passwd|credential|credentials|private[-_]?key|pem|jwt|session[-_]?token|service[-_]?account([-_]?json)?|client[-_]?secret|secret[-_]?id|unseal[-_]?key|recovery[-_]?key|key[-_]?file([-_]?path)?|token[-_]?file([-_]?path)?)$/i;
|
|
|
|
function rejectSensitiveProviderConfigKeys(value: unknown, ctx: z.RefinementCtx) {
|
|
if (!value || typeof value !== "object" || Array.isArray(value)) return;
|
|
for (const key of Object.keys(value)) {
|
|
if (!deniedProviderConfigKeyPattern.test(key)) continue;
|
|
ctx.addIssue({
|
|
code: z.ZodIssueCode.custom,
|
|
path: ["config", key],
|
|
message: `Provider vault config cannot persist sensitive field: ${key}`,
|
|
});
|
|
}
|
|
}
|
|
|
|
export const localEncryptedProviderConfigSchema = z.object({
|
|
backupReminderAcknowledged: z.boolean().optional(),
|
|
}).strict();
|
|
|
|
export const awsSecretsManagerProviderConfigSchema = z.object({
|
|
region: z.string().trim().regex(/^[a-z]{2}(?:-gov)?-[a-z]+-\d+$/, "Invalid AWS region"),
|
|
namespace: optionalSafeShortText,
|
|
secretNamePrefix: optionalSafeShortText,
|
|
kmsKeyId: z.string().trim().min(1).max(512).optional().nullable(),
|
|
ownerTag: optionalSafeShortText,
|
|
environmentTag: optionalSafeShortText,
|
|
}).strict();
|
|
|
|
export const gcpSecretManagerProviderConfigSchema = z.object({
|
|
projectId: z.string().trim().min(1).max(128).regex(/^[a-z][a-z0-9-]{4,127}$/).optional().nullable(),
|
|
location: optionalSafeShortText,
|
|
namespace: optionalSafeShortText,
|
|
secretNamePrefix: optionalSafeShortText,
|
|
}).strict();
|
|
|
|
const vaultAddressSchema = z.preprocess(
|
|
(value) => typeof value === "string" ? value.trim() : value,
|
|
z.string().url().superRefine((value, ctx) => {
|
|
let url: URL;
|
|
try {
|
|
url = new URL(value);
|
|
} catch {
|
|
return;
|
|
}
|
|
const hasPath = url.pathname !== "" && url.pathname !== "/";
|
|
if (
|
|
(url.protocol !== "http:" && url.protocol !== "https:") ||
|
|
url.username ||
|
|
url.password ||
|
|
url.search ||
|
|
url.hash ||
|
|
hasPath
|
|
) {
|
|
ctx.addIssue({
|
|
code: z.ZodIssueCode.custom,
|
|
message: "Vault address must be an origin-only HTTP(S) URL without credentials, path, query, or fragment",
|
|
});
|
|
}
|
|
}).transform((value) => new URL(value).origin),
|
|
);
|
|
|
|
function rejectUnsafeVaultAddress(value: unknown, ctx: z.RefinementCtx) {
|
|
if (value === undefined || value === null) return;
|
|
const parsed = vaultAddressSchema.safeParse(value);
|
|
if (parsed.success) return;
|
|
for (const issue of parsed.error.issues) {
|
|
ctx.addIssue({
|
|
...issue,
|
|
path: ["config", "address", ...issue.path],
|
|
});
|
|
}
|
|
}
|
|
|
|
export const vaultProviderConfigSchema = z.object({
|
|
address: vaultAddressSchema.optional().nullable(),
|
|
namespace: optionalSafeShortText,
|
|
mountPath: optionalSafeShortText,
|
|
secretPathPrefix: optionalSafeShortText,
|
|
}).strict();
|
|
|
|
export const secretProviderConfigPayloadSchema = z.discriminatedUnion("provider", [
|
|
z.object({ provider: z.literal("local_encrypted"), config: localEncryptedProviderConfigSchema }),
|
|
z.object({ provider: z.literal("aws_secrets_manager"), config: awsSecretsManagerProviderConfigSchema }),
|
|
z.object({ provider: z.literal("gcp_secret_manager"), config: gcpSecretManagerProviderConfigSchema }),
|
|
z.object({ provider: z.literal("vault"), config: vaultProviderConfigSchema }),
|
|
]);
|
|
|
|
export const createSecretProviderConfigSchema = z.object({
|
|
provider: z.enum(SECRET_PROVIDERS),
|
|
displayName: z.string().trim().min(1).max(120),
|
|
status: z.enum(SECRET_PROVIDER_CONFIG_STATUSES).optional(),
|
|
isDefault: z.boolean().optional(),
|
|
config: z.record(z.string(), z.unknown()).default({}),
|
|
}).superRefine((value, ctx) => {
|
|
rejectSensitiveProviderConfigKeys(value.config, ctx);
|
|
const parsed = secretProviderConfigPayloadSchema.safeParse({
|
|
provider: value.provider,
|
|
config: value.config,
|
|
});
|
|
if (!parsed.success) {
|
|
for (const issue of parsed.error.issues) {
|
|
ctx.addIssue({
|
|
...issue,
|
|
path: issue.path[0] === "config" ? issue.path : ["config", ...issue.path],
|
|
});
|
|
}
|
|
}
|
|
const status = value.status ?? (["gcp_secret_manager", "vault"].includes(value.provider) ? "coming_soon" : "ready");
|
|
if ((value.provider === "gcp_secret_manager" || value.provider === "vault") && status !== "coming_soon" && status !== "disabled") {
|
|
ctx.addIssue({
|
|
code: z.ZodIssueCode.custom,
|
|
path: ["status"],
|
|
message: `${value.provider} provider vaults are locked while coming soon`,
|
|
});
|
|
}
|
|
if ((status === "coming_soon" || status === "disabled") && value.isDefault) {
|
|
ctx.addIssue({
|
|
code: z.ZodIssueCode.custom,
|
|
path: ["isDefault"],
|
|
message: "Only ready or warning provider vaults can be default",
|
|
});
|
|
}
|
|
});
|
|
|
|
export type CreateSecretProviderConfig = z.infer<typeof createSecretProviderConfigSchema>;
|
|
|
|
export const updateSecretProviderConfigSchema = z.object({
|
|
displayName: z.string().trim().min(1).max(120).optional(),
|
|
status: z.enum(SECRET_PROVIDER_CONFIG_STATUSES).optional(),
|
|
isDefault: z.boolean().optional(),
|
|
config: z.record(z.string(), z.unknown()).optional(),
|
|
}).superRefine((value, ctx) => {
|
|
if (value.config !== undefined) {
|
|
rejectSensitiveProviderConfigKeys(value.config, ctx);
|
|
rejectUnsafeVaultAddress(value.config.address, ctx);
|
|
}
|
|
if ((value.status === "coming_soon" || value.status === "disabled") && value.isDefault) {
|
|
ctx.addIssue({
|
|
code: z.ZodIssueCode.custom,
|
|
path: ["isDefault"],
|
|
message: "Only ready or warning provider vaults can be default",
|
|
});
|
|
}
|
|
});
|
|
|
|
export type UpdateSecretProviderConfig = z.infer<typeof updateSecretProviderConfigSchema>;
|
|
|
|
export const remoteSecretImportPreviewSchema = z.object({
|
|
providerConfigId: z.string().guid(),
|
|
query: z.string().trim().max(200).optional().nullable(),
|
|
nextToken: z.string().trim().min(1).max(4096).optional().nullable(),
|
|
pageSize: z.number().int().min(1).max(100).optional(),
|
|
});
|
|
|
|
export type RemoteSecretImportPreview = z.infer<typeof remoteSecretImportPreviewSchema>;
|
|
|
|
export const secretProviderConfigDiscoveryPreviewSchema = z.object({
|
|
provider: z.enum(SECRET_PROVIDERS),
|
|
config: z.record(z.string(), z.unknown()).default({}),
|
|
query: z.string().trim().max(200).optional().nullable(),
|
|
nextToken: z.string().trim().min(1).max(4096).optional().nullable(),
|
|
pageSize: z.number().int().min(1).max(100).optional(),
|
|
}).superRefine((value, ctx) => {
|
|
rejectSensitiveProviderConfigKeys(value.config, ctx);
|
|
const parsed = secretProviderConfigPayloadSchema.safeParse({
|
|
provider: value.provider,
|
|
config: value.config,
|
|
});
|
|
if (!parsed.success) {
|
|
for (const issue of parsed.error.issues) {
|
|
ctx.addIssue({
|
|
...issue,
|
|
path: issue.path[0] === "config" ? issue.path : ["config", ...issue.path],
|
|
});
|
|
}
|
|
}
|
|
});
|
|
|
|
export type SecretProviderConfigDiscoveryPreview = z.infer<typeof secretProviderConfigDiscoveryPreviewSchema>;
|
|
|
|
export const remoteSecretImportSelectionSchema = z.object({
|
|
externalRef: z.string().trim().min(1).max(2048),
|
|
name: z.string().trim().min(1).max(160).optional().nullable(),
|
|
key: z.string().trim().min(1).max(120).regex(/^[a-zA-Z0-9_.-]+$/).optional().nullable(),
|
|
description: z.string().trim().max(500).optional().nullable(),
|
|
providerVersionRef: z.string().trim().min(1).max(512).optional().nullable(),
|
|
providerMetadata: z.record(z.string(), z.unknown()).optional().nullable(),
|
|
});
|
|
|
|
export const remoteSecretImportSchema = z.object({
|
|
providerConfigId: z.string().guid(),
|
|
secrets: z.array(remoteSecretImportSelectionSchema).min(1).max(100),
|
|
});
|
|
|
|
export type RemoteSecretImportSelection = z.infer<typeof remoteSecretImportSelectionSchema>;
|
|
export type RemoteSecretImport = z.infer<typeof remoteSecretImportSchema>;
|