fix: verify packaged PI ownership boundaries

This commit is contained in:
2026-08-24 13:58:08 +08:00
parent 13efe84d42
commit 0d03d00ebf
4 changed files with 68 additions and 11 deletions

View File

@@ -23,7 +23,13 @@ import {
} from '../probe-pi-packaged-runtime.mjs';
const PRODUCT_NAME = 'Makelore';
const EXTENSION_MARKER = 'makelore-runtime-v3.mjs';
const EXTENSION_CONTRACT_MARKERS = Object.freeze([
'Makelore runtime bridge rejected the request',
'subagent.dispatch',
'makelore.write-lease',
'MAKELORE_PI_BRIDGE_URL',
]);
const PI_AI_PROVIDER_PREFIX = 'pi-runtime/node_modules/@earendil-works/pi-ai/dist/providers/';
async function pathExists(path) {
try {
@@ -171,6 +177,12 @@ export async function collectForbiddenResourcePaths(root, pattern = /opencode/i)
return matches.sort();
}
export function classifyOpenCodeResourcePaths(paths) {
const upstreamPiProvider = paths.filter((path) => path.startsWith(PI_AI_PROVIDER_PREFIX));
const productOwned = paths.filter((path) => !path.startsWith(PI_AI_PROVIDER_PREFIX));
return { productOwned, upstreamPiProvider };
}
async function filesContainingNeedles(root, needles) {
const matches = [];
const visit = async (path) => {
@@ -270,9 +282,13 @@ export async function verifyPiProductArtifact({ projectRoot, executable }) {
if (absoluteManifestValues.length > 0) {
throw new Error(`Pi runtime manifest contains absolute paths: ${JSON.stringify(absoluteManifestValues)}`);
}
const forbiddenResourcePaths = await collectForbiddenResourcePaths(resourcesDirectory);
if (forbiddenResourcePaths.length > 0) {
throw new Error(`Product resources contain OpenCode paths: ${forbiddenResourcePaths.join(', ')}`);
const openCodeResourcePaths = classifyOpenCodeResourcePaths(
await collectForbiddenResourcePaths(resourcesDirectory),
);
if (openCodeResourcePaths.productOwned.length > 0) {
throw new Error(
`Product-owned resources contain OpenCode paths: ${openCodeResourcePaths.productOwned.join(', ')}`,
);
}
const expectedSkills = await sourceSkillIds(root);
@@ -281,8 +297,13 @@ export async function verifyPiProductArtifact({ projectRoot, executable }) {
throw new Error(`Packaged coding skills differ: expected ${expectedSkills}, got ${actualSkills}`);
}
const appAsarContents = await readFile(appAsar);
if (!appAsarContents.includes(Buffer.from(EXTENSION_MARKER))) {
throw new Error(`Packaged app.asar does not contain ${EXTENSION_MARKER}`);
const missingExtensionMarkers = EXTENSION_CONTRACT_MARKERS.filter(
(marker) => !appAsarContents.includes(Buffer.from(marker)),
);
if (missingExtensionMarkers.length > 0) {
throw new Error(
`Packaged app.asar does not contain Pi extension contract markers: ${missingExtensionMarkers.join(', ')}`,
);
}
const sourceNeedles = [
@@ -325,9 +346,18 @@ export async function verifyPiProductArtifact({ projectRoot, executable }) {
nodeEngine: manifest.runtime.nodeEngine,
},
packagedClosure,
extension: { marker: EXTENSION_MARKER, packaged: true },
extension: {
contractMarkers: EXTENSION_CONTRACT_MARKERS,
packaged: true,
executionProof: 'smoke:pi:real final-product extension/subagent run',
},
skills: actualSkills,
openCodeResourcePaths: [],
openCodeResourcePaths: {
...openCodeResourcePaths,
upstreamDecision: openCodeResourcePaths.upstreamPiProvider.length > 0
? 'retained-required-files-from-exact-pinned-pi-production-package'
: 'none',
},
developmentPathResidue: [],
result: 'pass',
};
@@ -336,5 +366,5 @@ export async function verifyPiProductArtifact({ projectRoot, executable }) {
export const PI_PRODUCT_ARTIFACT_DEFAULTS = Object.freeze({
platform: hostPlatform(),
arch: hostArch(),
extensionMarker: EXTENSION_MARKER,
extensionContractMarkers: EXTENSION_CONTRACT_MARKERS,
});