/** * Stable references for plugin secret settings. * * A settings response never carries a secret's value. Every secret leaf is a * marker instead: * * - `{ "$secret": "sec_…", "set": true }` — a stored secret, referenced by a * stable opaque id. Send the marker back unchanged to keep the stored value. * - `null` — nothing stored at that position. * - `{ "$secret": null, "locked": true }` — the effective value comes from the * environment and is never written back. * * On save each secret leaf accepts the reference, a plain string (a new value), * or `null` (clear). Payloads carry `secret_format: "ref"` so a `null` reads as * a deliberate clear rather than the deprecated "unchanged" placeholder. */ /** Reserved marker key that references a stored secret. */ export const PLUGIN_SECRET_REF_KEY = '$secret' /** Reserved payload key declaring which secret wire format a client speaks. */ export const PLUGIN_SECRET_FORMAT_KEY = 'secret_format' /** Wire format published and understood by this SDK. */ export const PLUGIN_SECRET_FORMAT_REF = 'ref' /** One `$secret` marker as published by a settings response. */ export interface PluginSecretRef { $secret: string | null set?: boolean locked?: boolean } /** What a settings form should tell the user about one secret field. */ export type PluginSecretState = 'set' | 'unset' | 'environment' const MARKER_KEYS = new Set([PLUGIN_SECRET_REF_KEY, 'set', 'locked']) /** Return whether one settings value is a `$secret` reference marker. */ export function isPluginSecretRef(value: unknown): value is PluginSecretRef { if (!value || typeof value !== 'object' || Array.isArray(value)) return false const record = value as Record if (!(PLUGIN_SECRET_REF_KEY in record)) return false return Object.keys(record).every(key => MARKER_KEYS.has(key)) } /** Return the stored secret id behind a marker, or `null` when nothing is stored. */ export function pluginSecretId(value: unknown): string | null { if (!isPluginSecretRef(value)) return null return typeof value.$secret === 'string' ? value.$secret : null } /** Classify one secret field for display: stored, unset, or environment-provided. */ export function pluginSecretState(value: unknown): PluginSecretState { if (isPluginSecretRef(value)) { if (value.locked) return 'environment' return typeof value.$secret === 'string' ? 'set' : 'unset' } return typeof value === 'string' && value.length > 0 ? 'set' : 'unset' } /** Human label for one secret field's state. */ export function pluginSecretLabel(value: unknown): string { const state = pluginSecretState(value) if (state === 'environment') return 'Provided by environment' return state === 'set' ? 'Set' : 'Not set' } /** Whether a secret field is read-only because the environment supplies it. */ export function isPluginSecretLocked(value: unknown): boolean { return isPluginSecretRef(value) && value.locked === true } /** * Value to submit for an untouched secret field: the reference, unchanged. * * A locked marker round-trips too, which is how the platform keeps a stored * value that an environment variable currently hides. */ export function keepPluginSecret(current: unknown): PluginSecretRef | null { if (isPluginSecretRef(current)) return { ...current } return null } /** Value to submit when the user typed a new secret. */ export function setPluginSecret(value: string): string { return value } /** Value to submit when the user cleared a secret. */ export function clearPluginSecret(): null { return null } /** Whether a settings response declares the `$secret` reference wire format. */ export function usesPluginSecretReferences(response: unknown): boolean { if (!response || typeof response !== 'object') return false return ( (response as Record)[PLUGIN_SECRET_FORMAT_KEY] === PLUGIN_SECRET_FORMAT_REF ) }