Consolidate Reader source ownership and pinned application instances
Add exact recursive source checkout, independent Git/jj developer workbenches and source-only backup/recovery commands, with Workspace instance binding outside source. Qualify two empty Reader Graphs, packaged source commands, Agent VM compilation, exact Gitea read grants and reconciled Reader settings/annotation stability. Publish checked Reader Package/root revisions to canonical review branches and retention tags, retain all 57 repositories independently in private versioned storage, verify downloaded-backup recovery and advance the example pin. Add bounded Central pin acquisition and selection-specific read-only identities, qualified against all 57 canonical repositories without write authority. Replace regex fork dependency discovery with compiler-parsed lock imports and rewrite proposals; preserve source identities and unrelated files, passing instance binding through packed and ordinary host checks. Hosted run-pin versus authoring preparation and maintained duplicate removal remain pending. Live source selections, Template defaults and default source branches are unchanged.
This commit is contained in:
@@ -90,6 +90,28 @@ package Runtime id "package:runtime" revision "package:runtime@1" {
|
||||
);
|
||||
assert.equal(result.directResources.size, 1);
|
||||
|
||||
const resolveResource = async (source: { repository: string; commit: string }, kind: string) => ({
|
||||
directory: directories.get(`${kind}\0${source.repository}\0${source.commit}`)!,
|
||||
});
|
||||
const bound = await Promise.all(
|
||||
["workspace:first", "workspace:second"].map((workspaceId) =>
|
||||
compileWorkspaceRepository({
|
||||
rootDirectory: root,
|
||||
resolveResource,
|
||||
workspaceId,
|
||||
sourceRootCommit: "5".repeat(40),
|
||||
}),
|
||||
),
|
||||
);
|
||||
assert.notEqual(bound[0]!.workspace.workspaceId, bound[1]!.workspace.workspaceId);
|
||||
assert.notEqual(bound[0]!.workspace.id, bound[1]!.workspace.id);
|
||||
for (const instance of bound) {
|
||||
assert.equal(instance.workspace.sourceRootCommit, "5".repeat(40));
|
||||
assert.deepEqual(instance.workspace.packageImports, result.workspace.packageImports);
|
||||
assert.deepEqual(instance.workspace.interfaceImports, result.workspace.interfaceImports);
|
||||
assert.deepEqual(instance.resources, result.resources, "binding does not fork resource identities");
|
||||
}
|
||||
|
||||
const resource = await compileCapabilityResourceRepository({
|
||||
rootDirectory: runtime,
|
||||
kind: "package",
|
||||
|
||||
@@ -0,0 +1,215 @@
|
||||
import assert from "node:assert/strict";
|
||||
import { execFile as callback } from "node:child_process";
|
||||
import { promisify } from "node:util";
|
||||
import { mkdtemp, mkdir, writeFile, readFile, rm, symlink } from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
import os from "node:os";
|
||||
import test from "node:test";
|
||||
import { pathToFileURL } from "node:url";
|
||||
import { materializeWorkspaceSources, workspaceSourcePin } from "../src/capability-language/source-closure.js";
|
||||
import { prepareDevelopmentSources } from "../src/capability-language/development-sources.js";
|
||||
import { backupWorkspaceSources, restoreWorkspaceSources } from "../src/capability-language/source-backup.js";
|
||||
|
||||
const exec = promisify(callback);
|
||||
const lock = (resources: string) => `quixos-lock version 1 {
|
||||
quixos source { repository "https://unavailable.test/toolchain.git"; commit "${"a".repeat(40)}"; }
|
||||
${resources}
|
||||
}`;
|
||||
test("exact source closure recovers through explicitly selected bundles, preserves history and rejects edits", async (context) => {
|
||||
const temporary = await mkdtemp(path.join(os.tmpdir(), "qx-closure-"));
|
||||
context.after(() => rm(temporary, { recursive: true, force: true }));
|
||||
const locations: Record<string, string> = {};
|
||||
const repository = async (name: string, resources: string) => {
|
||||
const directory = path.join(temporary, name);
|
||||
await mkdir(directory);
|
||||
const git = async (...args: string[]) => (await exec("git", args, { cwd: directory })).stdout.trim();
|
||||
await git("init");
|
||||
await writeFile(path.join(directory, "quixos.lock"), lock(""));
|
||||
await git("add", ".");
|
||||
const commit = async () => {
|
||||
await git("-c", "user.name=Test", "-c", "user.email=test@example.test", "commit", "-am", "Source");
|
||||
return await git("rev-parse", "HEAD");
|
||||
};
|
||||
const parent = await commit();
|
||||
await writeFile(path.join(directory, "quixos.lock"), lock(resources));
|
||||
await writeFile(path.join(directory, "marker"), name);
|
||||
await git("add", ".");
|
||||
const rev = await commit();
|
||||
await git("tag", `quixos-reachability/${rev}`);
|
||||
const bundle = path.join(temporary, `${name}.bundle`);
|
||||
await git("bundle", "create", bundle, `refs/tags/quixos-reachability/${rev}`);
|
||||
const source = { repository: `https://unavailable.test/${name}.git`, commit: rev };
|
||||
locations[source.repository] = pathToFileURL(bundle).href;
|
||||
return { ...source, parent };
|
||||
};
|
||||
const common = await repository("common", "");
|
||||
const dependency = `interface Common source { repository "${common.repository}"; commit "${common.commit}"; }`;
|
||||
const left = await repository("left", dependency),
|
||||
right = await repository("right", dependency);
|
||||
const root = await repository(
|
||||
"root",
|
||||
`
|
||||
package Left source { repository "${left.repository}"; commit "${left.commit}"; }
|
||||
package Right source { repository "${right.repository}"; commit "${right.commit}"; }`,
|
||||
);
|
||||
const directory = path.join(temporary, "checkout");
|
||||
const closure = await materializeWorkspaceSources({ source: root, directory, locations, concurrency: 2 });
|
||||
assert.deepEqual(
|
||||
await materializeWorkspaceSources({ source: root, directory, repositoryPrefix: "https://unavailable.test/" }),
|
||||
closure,
|
||||
);
|
||||
// Allow this root but not its dependencies: reject them before Git acquisition.
|
||||
const scopedRoot = { ...root, repository: "https://unavailable.test/selected/root.git" };
|
||||
await assert.rejects(
|
||||
materializeWorkspaceSources({
|
||||
source: scopedRoot,
|
||||
directory: path.join(temporary, "scoped"),
|
||||
locations: { ...locations, [scopedRoot.repository]: locations[root.repository] },
|
||||
repositoryPrefix: "https://unavailable.test/selected/",
|
||||
}),
|
||||
/outside the acquisition boundary/,
|
||||
);
|
||||
await assert.rejects(
|
||||
materializeWorkspaceSources({ source: root, directory, repositoryPrefix: "https://unavailable.test/root.git/" }),
|
||||
/outside the acquisition boundary/,
|
||||
);
|
||||
assert.equal(closure.resources.length, 4, "diamond dependency is materialized once");
|
||||
assert.deepEqual(JSON.parse(await readFile(path.join(directory, "sources.json"), "utf8")), closure);
|
||||
const rootEntry = closure.resources.find((entry) => entry.kind === "workspace")!;
|
||||
const rootDirectory = path.join(directory, rootEntry.directory);
|
||||
const rootLock = path.join(rootDirectory, "quixos.lock");
|
||||
const rootBody = await readFile(rootLock, "utf8");
|
||||
const outsideLock = path.join(temporary, "outside.lock");
|
||||
await writeFile(outsideLock, rootBody);
|
||||
// Exercise the shared loader directly: committed root symlinks must not let
|
||||
// privileged source inspection read outside the acquired repository.
|
||||
const { loadQuixosLock } = await import("../src/resource-lock/index.js");
|
||||
const linkedLock = path.join(temporary, "linked.lock");
|
||||
await symlink(outsideLock, linkedLock);
|
||||
await assert.rejects(loadQuixosLock(linkedLock), /root locks must be ordinary/);
|
||||
const backup = path.join(temporary, "retained");
|
||||
const manifest = await backupWorkspaceSources({ source: root, directory, output: backup });
|
||||
assert.equal(manifest.repositories.length, 4);
|
||||
const restored = await restoreWorkspaceSources({ backup, directory: path.join(temporary, "restored") });
|
||||
assert.deepEqual(restored, closure, "Source-only recovery retains canonical identity without an available forge");
|
||||
await assert.rejects(backupWorkspaceSources({ source: root, directory, output: backup }), /must not exist/);
|
||||
const missing = {
|
||||
...manifest,
|
||||
repositories: manifest.repositories.filter((entry) => entry.repository !== common.repository),
|
||||
};
|
||||
await writeFile(path.join(backup, "backup.json"), JSON.stringify(missing));
|
||||
await assert.rejects(
|
||||
restoreWorkspaceSources({ backup, directory: path.join(temporary, "incomplete") }),
|
||||
/omits required repository/,
|
||||
);
|
||||
await writeFile(path.join(backup, "backup.json"), JSON.stringify(manifest));
|
||||
await writeFile(path.join(backup, manifest.repositories[0].bundle), "damaged backup");
|
||||
await assert.rejects(
|
||||
restoreWorkspaceSources({ backup, directory: path.join(temporary, "damaged") }),
|
||||
/integrity mismatch/,
|
||||
);
|
||||
assert.equal((await exec("git", ["rev-parse", "HEAD^"], { cwd: rootDirectory })).stdout.trim(), root.parent);
|
||||
assert.equal(
|
||||
(await exec("git", ["remote", "get-url", "origin"], { cwd: rootDirectory })).stdout.trim(),
|
||||
root.repository,
|
||||
);
|
||||
// Cached recovery does not need the primary or the backup.
|
||||
assert.deepEqual(await materializeWorkspaceSources({ source: root, directory }), closure);
|
||||
const pinFile = path.join(temporary, "source.json");
|
||||
await writeFile(pinFile, JSON.stringify(root));
|
||||
const cli = path.resolve(import.meta.dirname, "../src/capability-language/tool-cli.js");
|
||||
const command = await exec(process.execPath, [cli, "source-checkout", pinFile, "--dir", directory]);
|
||||
assert.deepEqual(JSON.parse(command.stdout), closure, "Protocol CLI preserves exact cached source identity");
|
||||
const scoped = await exec(process.execPath, [
|
||||
cli,
|
||||
"source-checkout",
|
||||
pinFile,
|
||||
"--dir",
|
||||
directory,
|
||||
"--repository-prefix",
|
||||
"https://unavailable.test/",
|
||||
]);
|
||||
assert.deepEqual(JSON.parse(scoped.stdout), closure);
|
||||
const cliBackup = path.join(temporary, "cli-backup");
|
||||
const backupCommand = await exec(process.execPath, [
|
||||
cli,
|
||||
"source-backup",
|
||||
pinFile,
|
||||
"--dir",
|
||||
directory,
|
||||
"--output",
|
||||
cliBackup,
|
||||
]);
|
||||
assert.equal(JSON.parse(backupCommand.stdout).repositories.length, 4);
|
||||
const restoreCommand = await exec(process.execPath, [
|
||||
cli,
|
||||
"source-restore",
|
||||
cliBackup,
|
||||
"--dir",
|
||||
path.join(temporary, "cli-restore"),
|
||||
]);
|
||||
assert.deepEqual(JSON.parse(restoreCommand.stdout), closure);
|
||||
const developmentCommand = await exec(process.execPath, [
|
||||
cli,
|
||||
"source-develop",
|
||||
pinFile,
|
||||
"--dir",
|
||||
path.join(temporary, "cli-developer"),
|
||||
"--cache",
|
||||
directory,
|
||||
]);
|
||||
const developmentResult = JSON.parse(developmentCommand.stdout);
|
||||
assert.equal(developmentResult.repositories, 4);
|
||||
assert.deepEqual(developmentResult.source, closure.root);
|
||||
const a = await prepareDevelopmentSources({
|
||||
source: root,
|
||||
cacheDirectory: directory,
|
||||
directory: path.join(temporary, "a"),
|
||||
});
|
||||
const b = await prepareDevelopmentSources({
|
||||
source: root,
|
||||
cacheDirectory: directory,
|
||||
directory: path.join(temporary, "b"),
|
||||
});
|
||||
assert.notEqual(a.workspaceId, b.workspaceId);
|
||||
const aRoot = path.join(a.directory, "root"),
|
||||
bRoot = path.join(b.directory, "root");
|
||||
assert.equal((await exec("git", ["remote", "get-url", "origin"], { cwd: aRoot })).stdout.trim(), root.repository);
|
||||
assert.equal(
|
||||
await readFile(path.join(aRoot, "quixos.lock"), "utf8"),
|
||||
await readFile(path.join(rootDirectory, "quixos.lock"), "utf8"),
|
||||
);
|
||||
await exec("git", ["cat-file", "-e", root.parent], { cwd: aRoot });
|
||||
await writeFile(path.join(aRoot, "marker"), "Independent developer change");
|
||||
assert.equal(await readFile(path.join(bRoot, "marker"), "utf8"), "root");
|
||||
assert.equal(await readFile(path.join(rootDirectory, "marker"), "utf8"), "root");
|
||||
await assert.rejects(
|
||||
prepareDevelopmentSources({ source: root, cacheDirectory: directory, directory: a.directory }),
|
||||
/never overwritten/,
|
||||
);
|
||||
await writeFile(path.join(rootDirectory, "marker"), "edited");
|
||||
await assert.rejects(materializeWorkspaceSources({ source: root, directory, locations }), /modified/);
|
||||
await assert.rejects(
|
||||
materializeWorkspaceSources({
|
||||
source: root,
|
||||
directory: path.join(temporary, "bounded"),
|
||||
locations,
|
||||
maxRepositories: 2,
|
||||
}),
|
||||
/repository limit/,
|
||||
);
|
||||
await assert.rejects(
|
||||
materializeWorkspaceSources({
|
||||
source: root,
|
||||
directory,
|
||||
locations: { [root.repository]: "https://secret:password@example.test/root.git" },
|
||||
}),
|
||||
/transport substitution/,
|
||||
);
|
||||
});
|
||||
test("Workspace pins reject floating revisions and embedded credentials", () => {
|
||||
assert.throws(() => workspaceSourcePin({ repository: "https://example.test/root.git", commit: "main" }));
|
||||
assert.throws(() =>
|
||||
workspaceSourcePin({ repository: "https://user:password@example.test/root.git", commit: "a".repeat(40) }),
|
||||
);
|
||||
});
|
||||
@@ -0,0 +1,46 @@
|
||||
import assert from "node:assert/strict";
|
||||
import test from "node:test";
|
||||
import { mkdtemp, writeFile, readFile, rm } from "node:fs/promises";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { workspaceSourceLocks } from "../src/capability-language/source-locks.js";
|
||||
|
||||
test("fork lock proposals follow declared fragments and ignore comments and unrelated lock files", async (context) => {
|
||||
const directory = await mkdtemp(path.join(os.tmpdir(), "qx-lock-fork-"));
|
||||
context.after(() => rm(directory, { recursive: true, force: true }));
|
||||
const from = { repository: "https://source.test/app/runtime.git", commit: "b".repeat(40) };
|
||||
const to = { repository: "https://source.test/fork/runtime.git", commit: "c".repeat(40) };
|
||||
const root = `quixos-lock version 1 {
|
||||
quixos source { repository "https://source.test/quixos.git"; commit "${"a".repeat(40)}"; }
|
||||
import "resources.lock";
|
||||
// package Fake source { repository "https://unrelated.test/secret.git"; commit "${"d".repeat(40)}"; }
|
||||
}`;
|
||||
const fragment = `quixos-lock fragment version 1 {
|
||||
// Preserve this note: 雨 📚
|
||||
package Runtime source { repository "${from.repository}"; commit "${from.commit}"; }
|
||||
}`;
|
||||
await writeFile(path.join(directory, "quixos.lock"), root);
|
||||
await writeFile(path.join(directory, "resources.lock"), fragment);
|
||||
await writeFile(path.join(directory, "unrelated.lock"), "This is not a Quixos lock.");
|
||||
const result = await workspaceSourceLocks(directory, [{ from, to }]);
|
||||
assert.equal(result.lock.resources.length, 1);
|
||||
assert.deepEqual(result.lock.resources[0].source, { resolver: "git", ...to });
|
||||
assert.equal(result.files.find((file) => file.path === "quixos.lock")!.source, root);
|
||||
assert.match(result.files.find((file) => file.path === "resources.lock")!.source, /Preserve this note: 雨 📚/);
|
||||
assert.deepEqual(result.files.map((file) => file.path).sort(), ["quixos.lock", "resources.lock"]);
|
||||
assert.equal(
|
||||
await readFile(path.join(directory, "resources.lock"), "utf8"),
|
||||
fragment,
|
||||
"Proposing a fork does not edit selected source",
|
||||
);
|
||||
await assert.rejects(
|
||||
workspaceSourceLocks(directory, [
|
||||
{ from, to },
|
||||
{ from, to },
|
||||
]),
|
||||
/Duplicate/,
|
||||
);
|
||||
await assert.rejects(workspaceSourceLocks(directory, [{ from, to: { ...to, commit: "main" } }]), /exact commit/);
|
||||
await writeFile(path.join(directory, "quixos.lock"), root.replace('"resources.lock"', '"../outside.lock"'));
|
||||
await assert.rejects(workspaceSourceLocks(directory), /Invalid source lock/);
|
||||
});
|
||||
Reference in New Issue
Block a user