Qualify restricted SDK syntax independently of build architecture

This commit is contained in:
Timothy J. Aveni
2026-10-08 12:32:06 -07:00
parent 165510341d
commit 0a7bdf7657
2 changed files with 93 additions and 3 deletions
+39 -3
View File
@@ -26,13 +26,41 @@ export interface ImportFinding {
export const restrictedSDKSpecifier = "quixos:restricted-sdk/v1";
export const restrictedSDKPath = "share/quixos/restricted/core.mjs";
/** Compare trusted SDK syntax without build-machine paths in source comments.
* Keep literal/directive spelling and every executable AST node. This is SDK
* compatibility only: artifact files and the executed host SDK still have exact
* byte digests, and authored SDK bytes are never loaded by the restricted host.
*/
export function restrictedSDKIdentity(source: string): string {
if (Buffer.byteLength(source) > 2 * 1024 * 1024) throw Error("RESTRICTED_SDK_ANALYSIS_LIMIT");
const syntax = parse(source, { sourceType: "module", attachComment: false });
const metadata = new Set([
"start",
"end",
"loc",
"comments",
"leadingComments",
"innerComments",
"trailingComments",
"parenStart",
]);
let nodes = 0;
const encoded = JSON.stringify(syntax, (key, value) => {
if (metadata.has(key)) return undefined;
if (value && typeof value === "object" && typeof value.type === "string" && ++nodes > 100000)
throw Error("RESTRICTED_SDK_ANALYSIS_LIMIT");
return value;
});
return hexDigest({ codec: "quixos-restricted-sdk-syntax-v1", syntax: JSON.parse(encoded) });
}
/** Mechanical candidate checks, not authorization or an engine-safety proof.
* The caller must first verify the manifest and all declared file digests. */
export async function inspectRestrictedImplementation(
revision: string,
implementation: ArtifactImplementation,
read: ArtifactReader,
qualifiedSDKDigest?: string,
qualifiedSDKIdentity?: string,
): Promise<ImportFinding[]> {
const entry = implementation.files.find((file) => file.path === implementation.path);
const sdk = implementation.files.find((file) => file.path === restrictedSDKPath);
@@ -48,10 +76,18 @@ export async function inspectRestrictedImplementation(
!/^[$A-Z_a-z][$\w]*$/.test(implementation.registryExport ?? "")
)
return [{ code: "RESTRICTED_CLOSURE", detail: "Expected one closed module and the restricted SDK", line: null }];
if (qualifiedSDKDigest && sdk.digest !== qualifiedSDKDigest)
return [{ code: "RESTRICTED_SDK_UNSUPPORTED", detail: "SDK differs from the qualified host profile", line: null }];
if (entry.bytes > 1024 * 1024 || sdk.bytes > 2 * 1024 * 1024)
return [{ code: "ANALYSIS_LIMIT", detail: "Restricted closure exceeds the source budget", line: null }];
if (qualifiedSDKIdentity) {
const source = Buffer.from(await read(revision, sdk.path, sdk.bytes)).toString("utf8");
try {
if (restrictedSDKIdentity(source) !== qualifiedSDKIdentity) throw Error("SDK syntax differs");
} catch {
return [
{ code: "RESTRICTED_SDK_UNSUPPORTED", detail: "SDK differs from the qualified host profile", line: null },
];
}
}
return inspectJavaScriptSurface(Buffer.from(await read(revision, entry.path, entry.bytes)).toString("utf8"), [
restrictedSDKSpecifier,
]);