@hivemagnus/magnus-agent 1.1.12 → 1.1.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -33,7 +33,7 @@ async function main() {
|
|
|
33
33
|
throw new Error('Offline Linux root controller required');
|
|
34
34
|
const [mode, ...args] = process.argv.slice(2);
|
|
35
35
|
if (!['inspect', 'apply'].includes(mode ?? '') || args.length % 2)
|
|
36
|
-
throw new Error('Usage: inspect --output FILE | apply --before FILE --records UUID,UUID --approval-ref REF --output FILE');
|
|
36
|
+
throw new Error('Usage: inspect --output FILE [--records UUID,UUID] | apply --before FILE --records UUID,UUID --approval-ref REF --output FILE');
|
|
37
37
|
const options = {};
|
|
38
38
|
for (let i = 0; i < args.length; i += 2) {
|
|
39
39
|
const key = args[i];
|
|
@@ -41,7 +41,7 @@ async function main() {
|
|
|
41
41
|
throw new Error('Invalid or duplicate option');
|
|
42
42
|
options[key] = args[i + 1];
|
|
43
43
|
}
|
|
44
|
-
if (!options['--output'] || (mode === 'inspect' && Object.keys(options).
|
|
44
|
+
if (!options['--output'] || (mode === 'inspect' && Object.keys(options).some(key => !['--output', '--records'].includes(key))) ||
|
|
45
45
|
(mode === 'apply' && Object.keys(options).length !== 4))
|
|
46
46
|
throw new Error('Exact mode options required');
|
|
47
47
|
const install = await lstat('/opt/magnus-agent');
|
|
@@ -54,7 +54,7 @@ async function main() {
|
|
|
54
54
|
const { MutationBarrier } = await import('./mutation-barrier.js');
|
|
55
55
|
const barrier = new MutationBarrier('/opt/magnus-agent/.magnus/mutation-barrier');
|
|
56
56
|
if (mode === 'inspect') {
|
|
57
|
-
const observation = await barrier.historicalObservation();
|
|
57
|
+
const observation = await barrier.historicalObservation(options['--records']?.split(','));
|
|
58
58
|
await writePrivate(options['--output'], observation);
|
|
59
59
|
console.log(JSON.stringify({ mode, records: observation.records.length, boot: observation.boot,
|
|
60
60
|
output: options['--output'], originalOutcomes: 'unknown' }));
|
|
@@ -30,7 +30,7 @@ export declare class MutationBarrier {
|
|
|
30
30
|
private recordDigest;
|
|
31
31
|
private historicalSettlement;
|
|
32
32
|
/** Before-maintenance owner evidence; read-only and signed with the result key. */
|
|
33
|
-
historicalObservation(): Promise<{
|
|
33
|
+
historicalObservation(recordIds?: readonly string[]): Promise<{
|
|
34
34
|
version: 1;
|
|
35
35
|
drain: {
|
|
36
36
|
nodeId: string;
|
|
@@ -171,7 +171,11 @@ export class MutationBarrier {
|
|
|
171
171
|
return receipt;
|
|
172
172
|
}
|
|
173
173
|
/** Before-maintenance owner evidence; read-only and signed with the result key. */
|
|
174
|
-
async historicalObservation() {
|
|
174
|
+
async historicalObservation(recordIds) {
|
|
175
|
+
const selected = recordIds === undefined ? undefined
|
|
176
|
+
: z.array(z.string().guid()).min(1).max(16).parse(recordIds);
|
|
177
|
+
if (selected && new Set(selected).size !== selected.length)
|
|
178
|
+
throw new Error('Exact distinct historical record IDs required');
|
|
175
179
|
return this.lockedRead(async () => {
|
|
176
180
|
const drain = await this.identity();
|
|
177
181
|
if (!drain)
|
|
@@ -184,12 +188,16 @@ export class MutationBarrier {
|
|
|
184
188
|
const row = recordSchema.parse(await this.read(name));
|
|
185
189
|
if (name !== 'request-' + row.id + '.json')
|
|
186
190
|
throw new Error('Mutation record identity differs');
|
|
191
|
+
if (selected && !selected.includes(row.id))
|
|
192
|
+
continue;
|
|
187
193
|
if (row.state === 'completed' || await this.historicalSettlement(row, drain))
|
|
188
194
|
continue;
|
|
189
195
|
if (this.active.has(row.id))
|
|
190
196
|
throw new Error('Active operation cannot be retired');
|
|
191
197
|
records.push({ id: row.id, recordSha256: await this.recordDigest(row.id), acceptedAt: row.acceptedAt, routeSha256: row.routeSha256 });
|
|
192
198
|
}
|
|
199
|
+
if (selected && records.length !== selected.length)
|
|
200
|
+
throw new Error('Selected historical records must all remain unsettled');
|
|
193
201
|
return signHistoricalObservation({ version: 1, drain, boot: await this.bootReader(), observedAt: Date.now(), records }, this.historicalKeys.result);
|
|
194
202
|
});
|
|
195
203
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hivemagnus/magnus-agent",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.13",
|
|
4
4
|
"description": "Magnus node agent: a small daemon that enrolls a Linux host with a magnus-server and runs authenticated health, command, cron, file and skill management, with optional Hermes Agent, Codex and Ardent management.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"magnus",
|
|
@@ -60,7 +60,7 @@
|
|
|
60
60
|
"clean": "node -e \"const fs=require('node:fs');fs.rmSync('dist',{recursive:true,force:true});fs.rmSync('tsconfig.tsbuildinfo',{force:true})\""
|
|
61
61
|
},
|
|
62
62
|
"dependencies": {
|
|
63
|
-
"@hivemagnus/magnus-contracts": "1.1.
|
|
63
|
+
"@hivemagnus/magnus-contracts": "1.1.13",
|
|
64
64
|
"@hono/node-server": "^2.1.5",
|
|
65
65
|
"dotenv": "^18.0.9",
|
|
66
66
|
"hono": "^4.13.16",
|