Files

47 lines
2.0 KiB
JavaScript

import { createHash } from "node:crypto";
import manifest from "./manifest.json" with { type: "json" };
const allowedModules = new Set(Object.keys(manifest.virtual_modules));
const denied = new Set(manifest.denied_capabilities);
export function manifestHash(value = manifest) {
return `sha256:${createHash("sha256").update(JSON.stringify(value, Object.keys(value).sort())).digest("hex")}`;
}
export function runtimeCapabilities() {
return {
runtime: manifest.runtime,
version: manifest.version,
python_version: manifest.python_version,
abi_version: manifest.abi_version,
platform: manifest.platform,
worker_only: manifest.worker_only,
offline_required: manifest.offline_required,
manifest_sha256: manifestHash(),
virtual_modules: structuredClone(manifest.virtual_modules),
denied_capabilities: [...manifest.denied_capabilities],
};
}
export function validateImport(moduleName) {
if (typeof moduleName !== "string" || moduleName.length === 0) return { status: "blocked", code: "python_import_invalid", message_key: "python.import_invalid" };
if (allowedModules.has(moduleName)) return { status: "accepted", module: moduleName, symbols: [...manifest.virtual_modules[moduleName]] };
return { status: "blocked", code: "python_unsupported", message_key: "python.unsupported_module", module: moduleName, retryable: false };
}
export function validateCapability(capability) {
if (denied.has(capability)) return { status: "REAL-EXCLUDED", code: "real_hardware_excluded", message_key: "python.host_capability_denied", capability, retryable: false };
if (typeof capability !== "string" || capability.length === 0) return { status: "blocked", code: "python_capability_invalid", message_key: "python.capability_invalid" };
return { status: "accepted", capability };
}
export function createVirtualEnvironment() {
return Object.freeze({
importModule: validateImport,
checkCapability: validateCapability,
capabilities: runtimeCapabilities(),
});
}
export { manifest };