fix(housekeeping): close schema reflection escapes

This commit is contained in:
Simo committed 2026-08-27 20:31:10 +02:00
1 parent 7895188b56
commit 01dceac073
3 files changed
+539 -37

No files matched your search

@@ -5,6 +5,7 @@ import type { HousekeepingCapabilityContext } from "../contracts";
import { anyCapability, fail, ok } from "../contracts";
import { dispatchHousekeepingCommand } from "./dispatcher";
import {
getHousekeepingCommand,
type HousekeepingCommand,
registerHousekeepingCommand,
} from "./registry";
@@ -150,6 +151,129 @@ describe("dispatchHousekeepingCommand", () => {
expect(executed).toBe(false);
});
it("uses unchanged private validation after public descriptor mutation attempts", async () => {
const commandId = "system.dispatch.reflective-schema-mutation";
let executions = 0;
register(
baseCommand(commandId, {
input: z.object({
objectDescriptor: z.string().min(3),
objectDescriptors: z.string().min(3),
reflectDescriptor: z.string().min(3),
}),
execute: async (context) => {
executions += 1;
return ok(null, context.correlationId);
},
}),
);
const registered = getHousekeepingCommand(commandId);
if (!registered) throw new Error("registered command missing");
const readers = [
["objectDescriptor", Object.getOwnPropertyDescriptor],
[
"objectDescriptors",
(target: object, property: PropertyKey) =>
Reflect.get(Object.getOwnPropertyDescriptors(target), property) as
| PropertyDescriptor
| undefined,
],
["reflectDescriptor", Reflect.getOwnPropertyDescriptor],
] as const;
const descriptorValue = (
target: object,
property: PropertyKey,
readDescriptor: (
target: object,
property: PropertyKey,
) => PropertyDescriptor | undefined,
): unknown => {
const descriptor = readDescriptor(target, property);
if (!descriptor) {
throw new Error(`missing descriptor: ${String(property)}`);
}
if ("value" in descriptor) return descriptor.value;
if (descriptor.get) return Reflect.apply(descriptor.get, target, []);
return undefined;
};
for (const [field, readDescriptor] of readers) {
const definition = descriptorValue(
registered.input,
"def",
readDescriptor,
) as object;
const shape = descriptorValue(
definition,
"shape",
readDescriptor,
) as Record<string, z.ZodType>;
const child = shape[field];
if (!child) throw new Error(`public child missing: ${field}`);
const childDefinition = descriptorValue(
child,
"def",
readDescriptor,
) as object;
const checks = descriptorValue(
childDefinition,
"checks",
readDescriptor,
) as readonly object[];
const internal = descriptorValue(
checks[0] as object,
"_zod",
readDescriptor,
) as object;
const checkDefinition = descriptorValue(
internal,
"def",
readDescriptor,
) as { minimum: number };
try {
shape[field] = z.number();
} catch {
// A readonly facade may reject the assignment.
}
try {
checkDefinition.minimum = 0;
} catch {
// A readonly facade may reject the assignment.
}
}
const forged = await dispatchHousekeepingCommand(
{
commandId,
input: {
objectDescriptor: 7,
objectDescriptors: 7,
reflectDescriptor: 7,
},
},
dependencies(),
);
expect(forged).toMatchObject({
ok: false,
error: { code: "VALIDATION" },
});
expect(executions).toBe(0);
const valid = await dispatchHousekeepingCommand(
{
commandId,
input: {
objectDescriptor: "valid",
objectDescriptors: "valid",
reflectDescriptor: "valid",
},
},
dependencies(),
);
expect(valid).toMatchObject({ ok: true });
expect(executions).toBe(1);
});
it("rejects a missing required reason before the command can execute", async () => {
let executed = false;
const audit = auditRecorder();