fix(plist): own dictionary decoding across Apple workflows

Preserve XML, OpenStep and binary dictionary keys at their format owners. Share validated binary reference facts with materialization while retaining scalar precision, UID identity and bounded expansion. Migrate archive, Interface Builder, native and app-bundle consumers, then remove obsolete key-omission accounting and schema copies.

Validated source regressions and compiled CLI/MCP workflows, including native plist fidelity and archive identity. Typecheck, lint, docs and test discovery pass. No performance benchmarks were required.
This commit is contained in:
morluto committed 2026-10-26 22:20:00 +08:00
1 parent 3b26d7f80b
commit eb06e263cb
35 files changed
+1006 -785

No files matched your search

+3 -13
View File
@@ -1,17 +1,13 @@
import { lstat, opendir, readFile, realpath, stat } from "node:fs/promises";
import { join } from "node:path";
import { parseBinary } from "plist";
import { z } from "zod";
import { preflightPropertyListDecode } from "../artifacts/apple/PropertyListDecodeBudget.js";
import { decodeBinaryPlistUids } from "../artifacts/apple/PlistScalars.js";
import { decodeBinaryPlistValue } from "../artifacts/apple/BinaryPlistMaterializer.js";
import { BinaryTargetError } from "../domain/configurationErrors.js";
import { isPathWithinRoot } from "../domain/localPath.js";
import {
omitPrototypeKeys,
parseXmlPropertyList,
} from "../domain/propertyListKeys.js";
import { parseXmlPropertyList } from "../domain/propertyListKeys.js";
import { decodeXmlPlistText } from "../domain/propertyListXmlText.js";
import { hasBinaryPlistSignature } from "../domain/apple/appleArchiveFormat.js";
import { err, ok, type Result } from "../domain/result.js";
@@ -355,13 +351,7 @@ const executableEntrySchema = z.looseObject({ CFBundleExecutable: z.string() });
/** Decode a binary plist in-process, so no host plist tool is required. */
const parseBinaryPlistExecutable = (plist: Buffer): string => {
const plan = preflightPropertyListDecode(plist, BINARY_PLIST_DECODE_BYTES);
// `plist` assigns a `__proto__` key as the prototype; copying drops it, as
// the XML path does.
return executableName(
omitPrototypeKeys(
parseBinary(decodeBinaryPlistUids(plist, plan.uidOffsetsToNormalize)),
).value,
);
return executableName(decodeBinaryPlistValue(plist, plan));
};
const isSafeExecutableName = (name: string): boolean =>