fix(augment): protect orphaned wrappers
This commit is contained in:
1 parent
323757e43d
commit
65b60b1eba
2 files changed
+40
-3
No files matched your search
@@ -67,6 +67,11 @@ export interface PreparedManagedInstallation {
|
|||||||
readonly transaction: PreparedManagedTransaction;
|
readonly transaction: PreparedManagedTransaction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface RuntimeArtifactLocation {
|
||||||
|
readonly filePath: string;
|
||||||
|
readonly label: string;
|
||||||
|
}
|
||||||
|
|
||||||
export type { RenameFile };
|
export type { RenameFile };
|
||||||
|
|
||||||
export function samePath(left: string, right: string): boolean {
|
export function samePath(left: string, right: string): boolean {
|
||||||
@@ -145,6 +150,7 @@ function sameAgentId(left: unknown, right: string): boolean {
|
|||||||
async function validateRuntimeIdentity(
|
async function validateRuntimeIdentity(
|
||||||
paths: ManagedRuntimePaths,
|
paths: ManagedRuntimePaths,
|
||||||
agentKey: string,
|
agentKey: string,
|
||||||
|
additionalArtifacts: readonly RuntimeArtifactLocation[] = [],
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
if (!await inspectPhysicalDirectory(paths.runtimeRoot, 'Elydora runtime directory')) return;
|
if (!await inspectPhysicalDirectory(paths.runtimeRoot, 'Elydora runtime directory')) return;
|
||||||
if (!await inspectPhysicalDirectory(paths.agentDirectory, 'Elydora agent runtime directory')) return;
|
if (!await inspectPhysicalDirectory(paths.agentDirectory, 'Elydora agent runtime directory')) return;
|
||||||
@@ -156,6 +162,10 @@ async function validateRuntimeIdentity(
|
|||||||
readPhysicalFile(path.join(paths.agentDirectory, 'chain-state.json'), 'Elydora chain state'),
|
readPhysicalFile(path.join(paths.agentDirectory, 'chain-state.json'), 'Elydora chain state'),
|
||||||
readPhysicalFile(path.join(paths.agentDirectory, 'status-cache.json'), 'Elydora status cache'),
|
readPhysicalFile(path.join(paths.agentDirectory, 'status-cache.json'), 'Elydora status cache'),
|
||||||
readPhysicalFile(path.join(paths.agentDirectory, 'error.log'), 'Elydora error log'),
|
readPhysicalFile(path.join(paths.agentDirectory, 'error.log'), 'Elydora error log'),
|
||||||
|
...additionalArtifacts.map((artifact) => readPhysicalFile(
|
||||||
|
artifact.filePath,
|
||||||
|
artifact.label,
|
||||||
|
)),
|
||||||
]);
|
]);
|
||||||
if (!config) {
|
if (!config) {
|
||||||
if (artifacts.some(Boolean)) {
|
if (artifacts.some(Boolean)) {
|
||||||
@@ -233,6 +243,15 @@ export async function prepareManagedInstallation(
|
|||||||
hookLocations: spec.hookSources,
|
hookLocations: spec.hookSources,
|
||||||
config: spec.config,
|
config: spec.config,
|
||||||
}, guardScript, auditScript);
|
}, guardScript, auditScript);
|
||||||
|
const runtimeFiles = (spec.runtimeFiles ?? []).map((runtimeFile) => ({
|
||||||
|
runtimeFile,
|
||||||
|
filePath: runtimeFilePath(paths, runtimeFile.fileName),
|
||||||
|
}));
|
||||||
|
const runtimeArtifacts = runtimeFiles.map(({ runtimeFile, filePath }) => ({
|
||||||
|
filePath,
|
||||||
|
label: runtimeFile.label,
|
||||||
|
}));
|
||||||
|
await validateRuntimeIdentity(paths, spec.agentKey, runtimeArtifacts);
|
||||||
const changes = await Promise.all([
|
const changes = await Promise.all([
|
||||||
prepareManagedFileChange({
|
prepareManagedFileChange({
|
||||||
filePath: paths.guardPath,
|
filePath: paths.guardPath,
|
||||||
@@ -260,8 +279,8 @@ export async function prepareManagedInstallation(
|
|||||||
next: generateHookScript(spec.agentKey, spec.config.agentId, spec.auditOptions),
|
next: generateHookScript(spec.agentKey, spec.config.agentId, spec.auditOptions),
|
||||||
mode: 0o700,
|
mode: 0o700,
|
||||||
}),
|
}),
|
||||||
...(spec.runtimeFiles ?? []).map((runtimeFile) => prepareManagedFileChange({
|
...runtimeFiles.map(({ runtimeFile, filePath }) => prepareManagedFileChange({
|
||||||
filePath: runtimeFilePath(paths, runtimeFile.fileName),
|
filePath,
|
||||||
label: runtimeFile.label,
|
label: runtimeFile.label,
|
||||||
next: runtimeFile.source,
|
next: runtimeFile.source,
|
||||||
mode: runtimeFile.mode,
|
mode: runtimeFile.mode,
|
||||||
@@ -276,7 +295,7 @@ export async function prepareManagedInstallation(
|
|||||||
verifyExpectedSource: true,
|
verifyExpectedSource: true,
|
||||||
})),
|
})),
|
||||||
]);
|
]);
|
||||||
await validateRuntimeIdentity(paths, spec.agentKey);
|
await validateRuntimeIdentity(paths, spec.agentKey, runtimeArtifacts);
|
||||||
return {
|
return {
|
||||||
paths,
|
paths,
|
||||||
transaction: {
|
transaction: {
|
||||||
|
|||||||
@@ -197,6 +197,24 @@ test('Auggie rejects orphaned and mismatched runtime identities before writes',
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
await t.test('orphaned wrapper', async () => {
|
||||||
|
const fixture = await createFixture();
|
||||||
|
try {
|
||||||
|
await mkdir(fixture.agentDir, { recursive: true });
|
||||||
|
await writeFile(fixture.guardWrapperPath, 'orphaned wrapper\n');
|
||||||
|
const result = await fixture.install();
|
||||||
|
assert.equal(result.code, 1);
|
||||||
|
assert.match(result.stderr, /identity cannot be verified/i);
|
||||||
|
assert.equal(
|
||||||
|
await readFile(fixture.guardWrapperPath, 'utf-8'),
|
||||||
|
'orphaned wrapper\n',
|
||||||
|
);
|
||||||
|
await assertMissing(fixture.settingsPath);
|
||||||
|
} finally {
|
||||||
|
await fixture.close();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
await t.test('mismatched identity', async () => {
|
await t.test('mismatched identity', async () => {
|
||||||
const fixture = await createFixture();
|
const fixture = await createFixture();
|
||||||
try {
|
try {
|
||||||
|
|||||||
Reference in new issue
Block a user