fix(housekeeping): isolate executable command schemas

This commit is contained in:
2026-08-27 19:55:57 +02:00
parent 00618fb2a3
commit 7895188b56
5 changed files with 431 additions and 67 deletions
@@ -21,6 +21,11 @@ export interface HousekeepingCommand<I, O> {
readonly owner: HousekeepingDomainId;
readonly risk: "safe" | "sensitive";
readonly capability: CapabilityRequirement;
/**
* Registration snapshots structural/built-in Zod graphs and resolvable lazy
* edges. Stateful custom refinements, transforms, preprocessors, and other
* executable schema callbacks are rejected.
*/
readonly input: z.ZodType<I>;
readonly requiresReason: boolean;
readonly rateLimit: Readonly<{ attempts: number; windowMs: number }>;
@@ -30,6 +35,24 @@ export interface HousekeepingCommand<I, O> {
) => Promise<HousekeepingResult<O>>;
}
export type UnsupportedHousekeepingCommandSchemaKind =
| "custom"
| "transform"
| "lazy"
| "executable";
export class UnsupportedHousekeepingCommandSchemaError extends Error {
readonly name = "UnsupportedHousekeepingCommandSchemaError";
readonly code = "UNSUPPORTED_COMMAND_INPUT_SCHEMA";
constructor(
readonly commandId: string,
readonly schemaKind: UnsupportedHousekeepingCommandSchemaKind,
) {
super(`unsupported command input schema: ${commandId} (${schemaKind})`);
}
}
type RegisteredHousekeepingCommand = HousekeepingCommand<unknown, unknown>;
type ZodInternalNode = {
@@ -63,7 +86,7 @@ export function registerHousekeepingCommand<I, O>(
owner: command.owner,
risk: command.risk,
capability,
input: isolateValidationGraph(command.input),
input: isolateValidationGraph(command.input, command.id),
requiresReason: command.requiresReason,
rateLimit: Object.freeze({ ...command.rateLimit }),
execute: command.execute,
@@ -143,74 +166,183 @@ function validateCapability(
}
}
function isolateValidationGraph<T extends z.ZodType>(schema: T): T {
const seen = new WeakMap<object, unknown>();
function isolateValidationGraph<T extends z.ZodType>(
schema: T,
commandId: string,
): T {
type SchemaCell = {
current?: z.ZodType;
reference?: z.ZodType;
};
const graphValues = new WeakMap<object, unknown>();
const schemaCells = new WeakMap<z.ZodType, SchemaCell>();
function unsupported(
schemaKind: UnsupportedHousekeepingCommandSchemaKind,
): never {
throw new UnsupportedHousekeepingCommandSchemaError(commandId, schemaKind);
}
function cloneSchema<S extends z.ZodType>(value: S): S {
const existing = schemaCells.get(value);
if (existing?.current) return existing.current as S;
if (existing) {
existing.reference ??= z.lazy(() => {
if (!existing.current) {
throw new Error("housekeeping schema registration incomplete");
}
return existing.current;
});
return existing.reference as S;
}
const definition = value.def as { type?: unknown; getter?: unknown };
if (definition.type === "custom") unsupported("custom");
if (definition.type === "transform") unsupported("transform");
const cell: SchemaCell = {};
schemaCells.set(value, cell);
if (definition.type === "lazy") {
let ownedTarget: z.ZodType | undefined;
const ownedLazy = z.lazy(() => {
if (!ownedTarget) {
throw new Error("housekeeping lazy schema target unavailable");
}
return ownedTarget;
});
cell.current = ownedLazy;
if (typeof definition.getter !== "function") unsupported("lazy");
let callerTarget: unknown;
try {
callerTarget = definition.getter();
} catch {
unsupported("lazy");
}
if (!(callerTarget instanceof z.ZodType)) unsupported("lazy");
ownedTarget = cloneSchema(callerTarget);
return ownedLazy as unknown as S;
}
const clonedDefinition = cloneGraph(value.def);
const cloned = value.clone(clonedDefinition as typeof value.def);
cell.current = cloned;
return cloned;
}
function cloneBuiltInCheck(value: ZodInternalNode): unknown {
const definition = value._zod.def;
if (typeof definition !== "object" || definition === null) {
unsupported("executable");
}
const checkDefinition = definition as {
check?: unknown;
type?: unknown;
};
if (
checkDefinition.check === "custom" ||
checkDefinition.type === "custom"
) {
unsupported("custom");
}
const clonedDefinition = cloneRecord(definition, true);
const cloned = new value._zod.constr(clonedDefinition as never) as {
_zod?: { check?: unknown };
};
if (
typeof (value._zod as { check?: unknown }).check === "function" &&
typeof cloned._zod?.check !== "function"
) {
unsupported("executable");
}
return cloned;
}
function cloneRecord(value: object, omitBuiltInWhen = false): object {
const cached = graphValues.get(value);
if (cached !== undefined) return cached as object;
const prototype = Object.getPrototypeOf(value);
const cloned = Object.create(prototype) as Record<PropertyKey, unknown>;
graphValues.set(value, cloned);
for (const key of Reflect.ownKeys(value)) {
const descriptor = Object.getOwnPropertyDescriptor(value, key);
if (!descriptor) continue;
if (
omitBuiltInWhen &&
key === "when" &&
"value" in descriptor &&
typeof descriptor.value === "function"
) {
continue;
}
let resolved: unknown;
if ("value" in descriptor) {
resolved = descriptor.value;
} else if (descriptor.get) {
try {
resolved = Reflect.get(value, key);
} catch {
unsupported("executable");
}
} else {
unsupported("executable");
}
Object.defineProperty(cloned, key, {
configurable: descriptor.configurable,
enumerable: descriptor.enumerable,
value: cloneGraph(resolved),
writable: "writable" in descriptor ? descriptor.writable : false,
});
}
return cloned;
}
function cloneGraph(value: unknown): unknown {
if (typeof value === "function") unsupported("executable");
if (typeof value !== "object" || value === null) return value;
const cached = seen.get(value);
if (cached !== undefined) return cached;
if (value instanceof z.ZodType) return cloneSchema(value);
if (value instanceof z.ZodType) {
const clonedDefinition = cloneGraph(value.def);
const cloned = value.clone(clonedDefinition as typeof value.def);
seen.set(value, cloned);
return cloned;
}
if (isZodInternalNode(value)) {
const clonedDefinition = cloneGraph(value._zod.def);
const cloned = new value._zod.constr(clonedDefinition as never) as {
_zod: { check?: unknown };
};
const runtimeCheck = (value._zod as { check?: unknown }).check;
if (runtimeCheck !== undefined && cloned._zod.check === undefined) {
cloned._zod.check = runtimeCheck;
}
seen.set(value, cloned);
return cloned;
}
const cached = graphValues.get(value);
if (cached !== undefined) return cached;
if (isZodInternalNode(value)) return cloneBuiltInCheck(value);
if (Array.isArray(value)) {
const cloned: unknown[] = [];
seen.set(value, cloned);
graphValues.set(value, cloned);
for (const item of value) cloned.push(cloneGraph(item));
return cloned;
}
if (value instanceof RegExp) {
const cloned = new RegExp(value.source, value.flags);
seen.set(value, cloned);
graphValues.set(value, cloned);
return cloned;
}
if (value instanceof Date) {
const cloned = new Date(value.getTime());
seen.set(value, cloned);
graphValues.set(value, cloned);
return cloned;
}
const cloned = Object.create(Object.getPrototypeOf(value)) as Record<
PropertyKey,
unknown
>;
seen.set(value, cloned);
for (const key of Reflect.ownKeys(value)) {
const descriptor = Object.getOwnPropertyDescriptor(value, key);
if (!descriptor) continue;
const clonedDescriptor =
"value" in descriptor
? { ...descriptor, value: cloneGraph(descriptor.value) }
: descriptor.get
? {
configurable: descriptor.configurable,
enumerable: descriptor.enumerable,
writable: false,
value: cloneGraph(Reflect.get(value, key)),
}
: descriptor;
Object.defineProperty(cloned, key, clonedDescriptor);
if (value instanceof Map) {
const cloned = new Map<unknown, unknown>();
graphValues.set(value, cloned);
for (const [key, item] of value) {
cloned.set(cloneGraph(key), cloneGraph(item));
}
return cloned;
}
return cloned;
if (value instanceof Set) {
const cloned = new Set<unknown>();
graphValues.set(value, cloned);
for (const item of value) cloned.add(cloneGraph(item));
return cloned;
}
return cloneRecord(value);
}
return createReadonlyValidationFacade(cloneGraph(schema) as T);
return createReadonlyValidationFacade(cloneSchema(schema));
}
function isZodInternalNode(value: object): value is ZodInternalNode {
@@ -227,15 +359,31 @@ function createReadonlyValidationFacade<T extends z.ZodType>(schema: T): T {
const views = new WeakMap<object, unknown>();
function readonlyView(value: unknown): unknown {
if (typeof value !== "object" || value === null) return value;
if (
(typeof value !== "object" && typeof value !== "function") ||
value === null
) {
return value;
}
const cached = views.get(value);
if (cached !== undefined) return cached;
if (value instanceof z.ZodType) return schemaFacade(value);
if (typeof value === "function") {
const wrapped = (...args: unknown[]) =>
readonlyView(Reflect.apply(value, undefined, args));
views.set(value, wrapped);
return Object.freeze(wrapped);
}
const view = new Proxy(value, {
defineProperty: () => false,
deleteProperty: () => false,
get: (target, property) => readonlyView(Reflect.get(target, property)),
get: (target, property, receiver) => {
const raw = Reflect.get(target, property, receiver);
if (typeof raw !== "function") return readonlyView(raw);
return (...args: unknown[]) =>
readonlyView(Reflect.apply(raw, receiver, args));
},
set: () => false,
setPrototypeOf: () => false,
});
@@ -259,7 +407,7 @@ function createReadonlyValidationFacade<T extends z.ZodType>(schema: T): T {
? (...args: unknown[]) => {
const result = Reflect.apply(raw, target, args);
return result instanceof z.ZodType
? isolateValidationGraph(result)
? isolateValidationGraph(result, "derived-schema")
: result;
}
: readonlyView(raw);