@xenos1996/usa 2.17.0 → 2.18.0

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.
@@ -1 +1 @@
1
- {"version":3,"file":"cli-help.d.ts","sourceRoot":"","sources":["../src/cli-help.ts"],"names":[],"mappings":"AAAA,iGAAiG;AAEjG,eAAO,MAAM,gBAAgB,QAOrB,CAAC;AAET,eAAO,MAAM,cAAc,QAcnB,CAAC;AAET,eAAO,MAAM,IAAI,QA0GT,CAAC;AAET,eAAO,MAAM,iBAAiB,mbAmB7B,CAAC"}
1
+ {"version":3,"file":"cli-help.d.ts","sourceRoot":"","sources":["../src/cli-help.ts"],"names":[],"mappings":"AAAA,iGAAiG;AAEjG,eAAO,MAAM,gBAAgB,QAOrB,CAAC;AAET,eAAO,MAAM,cAAc,QAcnB,CAAC;AAET,eAAO,MAAM,IAAI,QA2GT,CAAC;AAET,eAAO,MAAM,iBAAiB,mbAmB7B,CAAC"}
package/dist/cli-help.js CHANGED
@@ -86,6 +86,7 @@ serve options
86
86
  --port <n> Port to listen on (default 0 = ephemeral, printed at startup)
87
87
  --token <t> Bearer token for /api/* (default: generated and printed once)
88
88
  --allow-root <dir> Auditable root, repeatable (default: working directory)
89
+ --data-dir <dir> Persist finished audits here (default: memory only)
89
90
 
90
91
  audit options
91
92
  --dry-run Print the report path that would be written and exit
@@ -1 +1 @@
1
- {"version":3,"file":"cli-help.js","sourceRoot":"","sources":["../src/cli-help.ts"],"names":[],"mappings":"AAAA,iGAAiG;AAEjG,MAAM,CAAC,MAAM,gBAAgB,GAAG;;;;;;;CAO/B,CAAC,IAAI,EAAE,CAAC;AAET,MAAM,CAAC,MAAM,cAAc,GAAG;;;;;;;;;;;;;;CAc7B,CAAC,IAAI,EAAE,CAAC;AAET,MAAM,CAAC,MAAM,IAAI,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0GnB,CAAC,IAAI,EAAE,CAAC;AAET,MAAM,CAAC,MAAM,iBAAiB,GAAG;;;;;;;;;;;;;;;;;;;CAmBhC,CAAC;AAEF,6BAA6B;AAC7B,6EAA6E;AAC7E,8EAA8E;AAC9E,4EAA4E;AAC5E,6EAA6E;AAC7E,2EAA2E"}
1
+ {"version":3,"file":"cli-help.js","sourceRoot":"","sources":["../src/cli-help.ts"],"names":[],"mappings":"AAAA,iGAAiG;AAEjG,MAAM,CAAC,MAAM,gBAAgB,GAAG;;;;;;;CAO/B,CAAC,IAAI,EAAE,CAAC;AAET,MAAM,CAAC,MAAM,cAAc,GAAG;;;;;;;;;;;;;;CAc7B,CAAC,IAAI,EAAE,CAAC;AAET,MAAM,CAAC,MAAM,IAAI,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2GnB,CAAC,IAAI,EAAE,CAAC;AAET,MAAM,CAAC,MAAM,iBAAiB,GAAG;;;;;;;;;;;;;;;;;;;CAmBhC,CAAC;AAEF,6BAA6B;AAC7B,6EAA6E;AAC7E,8EAA8E;AAC9E,4EAA4E;AAC5E,6EAA6E;AAC7E,2EAA2E"}
@@ -1,8 +1,3 @@
1
1
  import { type Args } from './cli-args.js';
2
- /**
3
- * `usa serve`: loopback-only audit server (ADR-0039). Binds 127.0.0.1 —
4
- * there is deliberately no flag to change that. Targets must exist and
5
- * resolve inside --allow-root (default: the working directory).
6
- */
7
2
  export declare function cmdServe(args: Args): Promise<number>;
8
3
  //# sourceMappingURL=cli-serve.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"cli-serve.d.ts","sourceRoot":"","sources":["../src/cli-serve.ts"],"names":[],"mappings":"AAIA,OAAO,EAAa,KAAK,IAAI,EAAE,MAAM,eAAe,CAAC;AAErD;;;;GAIG;AACH,wBAAsB,QAAQ,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAkC1D"}
1
+ {"version":3,"file":"cli-serve.d.ts","sourceRoot":"","sources":["../src/cli-serve.ts"],"names":[],"mappings":"AAIA,OAAO,EAAa,KAAK,IAAI,EAAE,MAAM,eAAe,CAAC;AAqCrD,wBAAsB,QAAQ,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CA+B1D"}
package/dist/cli-serve.js CHANGED
@@ -3,37 +3,51 @@ import path from 'node:path';
3
3
  import { randomBytes } from 'node:crypto';
4
4
  import { startServer } from './serve/server.js';
5
5
  import { list, str } from './cli-args.js';
6
- /**
7
- * `usa serve`: loopback-only audit server (ADR-0039). Binds 127.0.0.1 —
8
- * there is deliberately no flag to change that. Targets must exist and
9
- * resolve inside --allow-root (default: the working directory).
10
- */
11
- export async function cmdServe(args) {
12
- const portRaw = str(args, 'port', '0') ?? '0';
13
- const port = Number(portRaw);
6
+ /** Parse and validate serve flags. Returns an error string instead of throwing. */
7
+ function resolveServeArgs(args) {
8
+ const port = Number(str(args, 'port', '0') ?? '0');
14
9
  if (!Number.isInteger(port) || port < 0 || port > 65535) {
15
- console.error('--port must be an integer 0-65535 (0 picks an ephemeral port)');
16
- return 2;
10
+ return { error: '--port must be an integer 0-65535 (0 picks an ephemeral port)' };
17
11
  }
18
12
  const roots = list(args, 'allow-root');
19
13
  const resolvedRoots = (roots.length > 0 ? roots : [process.cwd()]).map((r) => path.resolve(r));
20
14
  for (const r of resolvedRoots) {
21
- if (!fs.existsSync(r)) {
22
- console.error(`--allow-root does not exist: ${r}`);
23
- return 2;
24
- }
15
+ if (!fs.existsSync(r))
16
+ return { error: `--allow-root does not exist: ${r}` };
25
17
  }
26
18
  const given = str(args, 'token');
27
- const token = given ?? randomBytes(32).toString('hex');
19
+ const dataDirRaw = str(args, 'data-dir');
20
+ return {
21
+ port,
22
+ token: given ?? randomBytes(32).toString('hex'),
23
+ tokenGiven: given !== undefined,
24
+ roots: resolvedRoots,
25
+ dataDir: dataDirRaw === undefined ? undefined : path.resolve(dataDirRaw),
26
+ };
27
+ }
28
+ export async function cmdServe(args) {
29
+ const resolved = resolveServeArgs(args);
30
+ if ('error' in resolved) {
31
+ console.error(resolved.error);
32
+ return 2;
33
+ }
28
34
  try {
29
- const { port: bound } = await startServer({ port, token, roots: resolvedRoots });
35
+ const { port: bound } = await startServer({
36
+ port: resolved.port,
37
+ token: resolved.token,
38
+ roots: resolved.roots,
39
+ ...(resolved.dataDir === undefined ? {} : { dataDir: resolved.dataDir }),
40
+ });
30
41
  console.log(`usa serve: listening on http://127.0.0.1:${bound} (loopback only — never expose directly)`);
31
- if (given === undefined) {
32
- console.log('usa serve: generated bearer token (printed once, required on /api/*):');
33
- console.log(token);
42
+ if (resolved.tokenGiven) {
43
+ console.log('usa serve: using the provided bearer token for /api/*.');
34
44
  }
35
45
  else {
36
- console.log('usa serve: using the provided bearer token for /api/*.');
46
+ console.log('usa serve: generated bearer token (printed once, required on /api/*):');
47
+ console.log(resolved.token);
48
+ }
49
+ if (resolved.dataDir !== undefined) {
50
+ console.log(`usa serve: persisting finished audits to ${resolved.dataDir}.`);
37
51
  }
38
52
  }
39
53
  catch (err) {
@@ -1 +1 @@
1
- {"version":3,"file":"cli-serve.js","sourceRoot":"","sources":["../src/cli-serve.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,IAAI,EAAE,GAAG,EAAa,MAAM,eAAe,CAAC;AAErD;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,IAAU;IACvC,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,CAAC,IAAI,GAAG,CAAC;IAC9C,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;IAC7B,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI,IAAI,GAAG,KAAK,EAAE,CAAC;QACxD,OAAO,CAAC,KAAK,CAAC,+DAA+D,CAAC,CAAC;QAC/E,OAAO,CAAC,CAAC;IACX,CAAC;IACD,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;IACvC,MAAM,aAAa,GAAG,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/F,KAAK,MAAM,CAAC,IAAI,aAAa,EAAE,CAAC;QAC9B,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC;YACtB,OAAO,CAAC,KAAK,CAAC,gCAAgC,CAAC,EAAE,CAAC,CAAC;YACnD,OAAO,CAAC,CAAC;QACX,CAAC;IACH,CAAC;IACD,MAAM,KAAK,GAAG,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACjC,MAAM,KAAK,GAAG,KAAK,IAAI,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IACvD,IAAI,CAAC;QACH,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,WAAW,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,aAAa,EAAE,CAAC,CAAC;QACjF,OAAO,CAAC,GAAG,CACT,4CAA4C,KAAK,0CAA0C,CAC5F,CAAC;QACF,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,OAAO,CAAC,GAAG,CAAC,uEAAuE,CAAC,CAAC;YACrF,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACrB,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,wDAAwD,CAAC,CAAC;QACxE,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,6BAA8B,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC;QACrE,OAAO,CAAC,CAAC;IACX,CAAC;IACD,MAAM,IAAI,OAAO,CAAO,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IAClC,OAAO,CAAC,CAAC;AACX,CAAC"}
1
+ {"version":3,"file":"cli-serve.js","sourceRoot":"","sources":["../src/cli-serve.ts"],"names":[],"mappings":"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"}
@@ -24,6 +24,11 @@ export interface ServeJob {
24
24
  finishedAt?: string;
25
25
  report?: AuditReport;
26
26
  profile?: MaturityProfile;
27
+ /** Rendered report (set for finished jobs when persistence is on). */
28
+ rendered?: {
29
+ contentType: string;
30
+ body: string;
31
+ };
27
32
  error?: string;
28
33
  }
29
34
  /**
@@ -41,12 +46,44 @@ export interface JobRunner {
41
46
  profile: MaturityProfile;
42
47
  }>;
43
48
  }
44
- export declare function createJobManager(runner: JobRunner, historyLimit?: number): {
49
+ export interface JobHooks {
50
+ /** Fires for every finished job (done or error), after status is set. */
51
+ onDone?: (job: ServeJob) => void;
52
+ }
53
+ export declare function createJobManager(runner: JobRunner, historyLimit?: number, hooks?: JobHooks): {
45
54
  submit: (options: ServeJobOptions, target: string) => {
46
55
  id: string;
47
56
  } | {
48
57
  conflict: true;
49
58
  };
50
59
  get: (id: string) => ServeJob | undefined;
60
+ list: () => ServeJob[];
61
+ restore: (jobs: ServeJob[]) => void;
51
62
  };
63
+ /**
64
+ * File persistence for `--data-dir` (ADR-0040): one JSON file per finished
65
+ * job, pruned to the same bound as memory history. Only finished jobs are
66
+ * ever written — a crash leaves no partial record behind.
67
+ */
68
+ export interface PersistedJob {
69
+ id: string;
70
+ status: JobStatus;
71
+ options: ServeJobOptions;
72
+ createdAt: string;
73
+ finishedAt?: string;
74
+ error?: string;
75
+ rendered?: {
76
+ contentType: string;
77
+ body: string;
78
+ };
79
+ }
80
+ export declare function persistJob(dir: string, job: ServeJob): void;
81
+ /**
82
+ * Read back persisted jobs, skipping anything malformed with a loud
83
+ * warning instead of refusing to start — a corrupt file must not take
84
+ * down the server, but it must not pass silently either.
85
+ */
86
+ export declare function loadPersisted(dir: string): ServeJob[];
87
+ /** Prune persisted files past the bound, oldest first (shared rule). */
88
+ export declare function prunePersisted(dir: string, historyLimit: number): void;
52
89
  //# sourceMappingURL=jobs.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"jobs.d.ts","sourceRoot":"","sources":["../../src/serve/jobs.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAE7D;;;;;;;;GAQG;AAEH,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,MAAM,SAAS,GAAG,SAAS,GAAG,MAAM,GAAG,OAAO,CAAC;AAErD,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,SAAS,CAAC;IAClB,OAAO,EAAE,eAAe,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,OAAO,CAAC,EAAE,eAAe,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,CAelE;AAED,MAAM,WAAW,SAAS;IACxB,CACE,OAAO,EAAE,eAAe,EACxB,MAAM,EAAE,MAAM,GAEZ;QAAE,MAAM,EAAE,WAAW,CAAC;QAAC,OAAO,EAAE,eAAe,CAAA;KAAE,GACjD,OAAO,CAAC;QAAE,MAAM,EAAE,WAAW,CAAC;QAAC,OAAO,EAAE,eAAe,CAAA;KAAE,CAAC,CAAC;CAChE;AAED,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,SAAS,EACjB,YAAY,SAAK,GAChB;IACD,MAAM,EAAE,CAAC,OAAO,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,KAAK;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,GAAG;QAAE,QAAQ,EAAE,IAAI,CAAA;KAAE,CAAC;IAC1F,GAAG,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,QAAQ,GAAG,SAAS,CAAC;CAC3C,CAmDA"}
1
+ {"version":3,"file":"jobs.d.ts","sourceRoot":"","sources":["../../src/serve/jobs.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAE7D;;;;;;;;GAQG;AAEH,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,MAAM,SAAS,GAAG,SAAS,GAAG,MAAM,GAAG,OAAO,CAAC;AAErD,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,SAAS,CAAC;IAClB,OAAO,EAAE,eAAe,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,OAAO,CAAC,EAAE,eAAe,CAAC;IAC1B,sEAAsE;IACtE,QAAQ,CAAC,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IACjD,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,CAelE;AAED,MAAM,WAAW,SAAS;IACxB,CACE,OAAO,EAAE,eAAe,EACxB,MAAM,EAAE,MAAM,GAEZ;QAAE,MAAM,EAAE,WAAW,CAAC;QAAC,OAAO,EAAE,eAAe,CAAA;KAAE,GACjD,OAAO,CAAC;QAAE,MAAM,EAAE,WAAW,CAAC;QAAC,OAAO,EAAE,eAAe,CAAA;KAAE,CAAC,CAAC;CAChE;AAED,MAAM,WAAW,QAAQ;IACvB,yEAAyE;IACzE,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,QAAQ,KAAK,IAAI,CAAC;CAClC;AAED,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,SAAS,EACjB,YAAY,SAAK,EACjB,KAAK,GAAE,QAAa,GACnB;IACD,MAAM,EAAE,CAAC,OAAO,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,KAAK;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,GAAG;QAAE,QAAQ,EAAE,IAAI,CAAA;KAAE,CAAC;IAC1F,GAAG,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,QAAQ,GAAG,SAAS,CAAC;IAC1C,IAAI,EAAE,MAAM,QAAQ,EAAE,CAAC;IACvB,OAAO,EAAE,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,IAAI,CAAC;CACrC,CA+DA;AAED;;;;GAIG;AACH,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,SAAS,CAAC;IAClB,OAAO,EAAE,eAAe,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;CAClD;AAED,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,QAAQ,GAAG,IAAI,CAY3D;AAkBD;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,QAAQ,EAAE,CAmBrD;AAED,wEAAwE;AACxE,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,IAAI,CAmBtE"}
@@ -1,5 +1,5 @@
1
1
  import { randomBytes } from 'node:crypto';
2
- import { existsSync, realpathSync } from 'node:fs';
2
+ import fs, { existsSync, realpathSync } from 'node:fs';
3
3
  import path from 'node:path';
4
4
  /**
5
5
  * Resolve a requested target against allow-roots. Throws a clean Error when
@@ -23,7 +23,7 @@ export function resolveTarget(raw, roots) {
23
23
  }
24
24
  throw new Error(`target escapes the allowed roots: ${raw}`);
25
25
  }
26
- export function createJobManager(runner, historyLimit = 20) {
26
+ export function createJobManager(runner, historyLimit = 20, hooks = {}) {
27
27
  const jobs = new Map();
28
28
  let running = false;
29
29
  function prune() {
@@ -66,6 +66,7 @@ export function createJobManager(runner, historyLimit = 20) {
66
66
  job.finishedAt = new Date().toISOString();
67
67
  running = false;
68
68
  prune();
69
+ hooks.onDone?.(job);
69
70
  }
70
71
  })();
71
72
  });
@@ -74,6 +75,95 @@ export function createJobManager(runner, historyLimit = 20) {
74
75
  get(id) {
75
76
  return jobs.get(id);
76
77
  },
78
+ list() {
79
+ return [...jobs.values()].sort((a, b) => (a.createdAt < b.createdAt ? 1 : -1));
80
+ },
81
+ restore(seed) {
82
+ for (const job of seed) {
83
+ if (job.status !== 'running')
84
+ jobs.set(job.id, job);
85
+ }
86
+ prune();
87
+ },
88
+ };
89
+ }
90
+ export function persistJob(dir, job) {
91
+ if (job.status === 'running')
92
+ return;
93
+ const record = {
94
+ id: job.id,
95
+ status: job.status,
96
+ options: job.options,
97
+ createdAt: job.createdAt,
98
+ finishedAt: job.finishedAt,
99
+ error: job.error,
100
+ rendered: job.rendered,
77
101
  };
102
+ fs.writeFileSync(path.join(dir, `${job.id}.json`), `${JSON.stringify(record, null, 2)}\n`);
103
+ }
104
+ function readRecord(dir, file) {
105
+ const raw = JSON.parse(fs.readFileSync(path.join(dir, file), 'utf8'));
106
+ if (typeof raw.id !== 'string' || (raw.status !== 'done' && raw.status !== 'error')) {
107
+ throw new Error('not a job record');
108
+ }
109
+ return raw;
110
+ }
111
+ function listRecordFiles(dir) {
112
+ try {
113
+ return fs.readdirSync(dir).filter((f) => f.endsWith('.json'));
114
+ }
115
+ catch {
116
+ return [];
117
+ }
118
+ }
119
+ /**
120
+ * Read back persisted jobs, skipping anything malformed with a loud
121
+ * warning instead of refusing to start — a corrupt file must not take
122
+ * down the server, but it must not pass silently either.
123
+ */
124
+ export function loadPersisted(dir) {
125
+ const out = [];
126
+ for (const f of listRecordFiles(dir)) {
127
+ try {
128
+ const raw = readRecord(dir, f);
129
+ out.push({
130
+ id: raw.id,
131
+ status: raw.status,
132
+ options: raw.options,
133
+ createdAt: raw.createdAt,
134
+ finishedAt: raw.finishedAt,
135
+ error: raw.error,
136
+ rendered: raw.rendered,
137
+ });
138
+ }
139
+ catch (err) {
140
+ console.error(`serve: skipping unreadable job file ${f}: ${err.message}`);
141
+ }
142
+ }
143
+ return out;
144
+ }
145
+ /** Prune persisted files past the bound, oldest first (shared rule). */
146
+ export function prunePersisted(dir, historyLimit) {
147
+ const records = [];
148
+ for (const f of listRecordFiles(dir)) {
149
+ try {
150
+ const raw = readRecord(dir, f);
151
+ records.push({ id: raw.id, createdAt: raw.createdAt });
152
+ }
153
+ catch {
154
+ // Malformed files are the loader's complaint, not the pruner's.
155
+ }
156
+ }
157
+ if (records.length <= historyLimit)
158
+ return;
159
+ records.sort((a, b) => (a.createdAt < b.createdAt ? -1 : 1));
160
+ for (const victim of records.slice(0, records.length - historyLimit)) {
161
+ try {
162
+ fs.rmSync(path.join(dir, `${victim.id}.json`));
163
+ }
164
+ catch {
165
+ // Best effort: a leftover file is untidy, not a failure.
166
+ }
167
+ }
78
168
  }
79
169
  //# sourceMappingURL=jobs.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"jobs.js","sourceRoot":"","sources":["../../src/serve/jobs.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"jobs.js","sourceRoot":"","sources":["../../src/serve/jobs.ts"],"names":[],"mappings":"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"}
@@ -6,7 +6,11 @@ export interface ServeOptions {
6
6
  port: number;
7
7
  token: string;
8
8
  roots: string[];
9
- manager?: ReturnType<typeof createJobManager>;
9
+ /** Injected for tests; production runs the real audit engine. */
10
+ runner?: Parameters<typeof createJobManager>[0];
11
+ /** Persist finished jobs here (ADR-0040); unset means memory only. */
12
+ dataDir?: string;
13
+ historyLimit?: number;
10
14
  }
11
15
  export declare function startServer(opts: ServeOptions): Promise<{
12
16
  server: Server;
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/serve/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,eAAe,EAAE,KAAK,MAAM,EAAuB,MAAM,WAAW,CAAC;AAQjG,OAAO,EAAE,gBAAgB,EAAgC,MAAM,WAAW,CAAC;AAsB3E,0EAA0E;AAC1E,wBAAgB,SAAS,CAAC,GAAG,EAAE,eAAe,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAQtE;AAkCD,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,OAAO,CAAC,EAAE,UAAU,CAAC,OAAO,gBAAgB,CAAC,CAAC;CAC/C;AAED,wBAAsB,WAAW,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC;IAC7D,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf,CAAC,CA0HD"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/serve/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,eAAe,EAAE,KAAK,MAAM,EAAuB,MAAM,WAAW,CAAC;AAUjG,OAAO,EACL,gBAAgB,EAMjB,MAAM,WAAW,CAAC;AAsBnB,0EAA0E;AAC1E,wBAAgB,SAAS,CAAC,GAAG,EAAE,eAAe,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAQtE;AAkCD,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,iEAAiE;IACjE,MAAM,CAAC,EAAE,UAAU,CAAC,OAAO,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC;IAChD,sEAAsE;IACtE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,wBAAsB,WAAW,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC;IAC7D,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf,CAAC,CAiED"}
@@ -6,7 +6,9 @@ import { renderJson } from '../report/json.js';
6
6
  import { renderMarkdown } from '../report/markdown.js';
7
7
  import { renderHtml } from '../report/html.js';
8
8
  import { DEPTHS, MATURITIES, DEFAULT_RULES_DIR, VERSION } from '../cli-args.js';
9
- import { createJobManager, resolveTarget } from './jobs.js';
9
+ import fs from 'node:fs';
10
+ import path from 'node:path';
11
+ import { createJobManager, loadPersisted, persistJob, prunePersisted, resolveTarget, } from './jobs.js';
10
12
  import { uiPage } from './ui.js';
11
13
  /**
12
14
  * `usa serve` HTTP layer (ADR-0039): loopback only, bearer-token auth on
@@ -68,8 +70,31 @@ function renderJobReport(job) {
68
70
  return { contentType: 'application/json; charset=utf-8', body: renderJson(job.report) };
69
71
  }
70
72
  export async function startServer(opts) {
71
- const manager = opts.manager ??
72
- createJobManager((jobOptions, target) => {
73
+ const historyLimit = opts.historyLimit ?? 20;
74
+ const dataDir = opts.dataDir === undefined ? undefined : path.resolve(opts.dataDir);
75
+ if (dataDir !== undefined) {
76
+ try {
77
+ fs.mkdirSync(dataDir, { recursive: true });
78
+ }
79
+ catch (err) {
80
+ throw new Error(`serve: cannot create data dir ${dataDir}: ${err.message}`, {
81
+ cause: err,
82
+ });
83
+ }
84
+ }
85
+ const hooks = dataDir === undefined
86
+ ? {}
87
+ : {
88
+ onDone: (job) => {
89
+ if (job.status === 'done' && job.report && job.profile) {
90
+ job.rendered = renderJobReport(job);
91
+ }
92
+ persistJob(dataDir, job);
93
+ prunePersisted(dataDir, historyLimit);
94
+ },
95
+ };
96
+ const manager = createJobManager(opts.runner ??
97
+ ((jobOptions, target) => {
73
98
  const config = loadConfig(target);
74
99
  const { report, profile } = runAudit({
75
100
  target,
@@ -81,99 +106,16 @@ export async function startServer(opts) {
81
106
  usaVersion: VERSION,
82
107
  });
83
108
  return { report, profile };
84
- });
109
+ }), historyLimit, hooks);
110
+ if (dataDir !== undefined)
111
+ manager.restore(loadPersisted(dataDir));
112
+ const ctx = {
113
+ manager,
114
+ token: opts.token,
115
+ roots: opts.roots,
116
+ };
85
117
  const server = createServer((req, res) => {
86
- void (async () => {
87
- const url = new URL(req.url ?? '/', 'http://127.0.0.1');
88
- if (req.method === 'GET' && url.pathname === '/') {
89
- res.writeHead(200, { 'content-type': 'text/html; charset=utf-8' });
90
- res.end(uiPage());
91
- return;
92
- }
93
- if (!checkAuth(req, opts.token)) {
94
- sendJson(res, 401, { error: 'missing or invalid bearer token' });
95
- return;
96
- }
97
- if (req.method === 'POST' && url.pathname === '/api/audits') {
98
- let raw;
99
- try {
100
- raw = await readBody(req);
101
- }
102
- catch {
103
- sendJson(res, 413, { error: 'request body too large' });
104
- return;
105
- }
106
- let body;
107
- try {
108
- body = JSON.parse(raw);
109
- }
110
- catch {
111
- sendJson(res, 400, { error: 'request body must be JSON' });
112
- return;
113
- }
114
- const target = body['target'];
115
- const depth = body['depth'] ?? 'standard';
116
- const profile = body['profile'] ?? 'auto';
117
- const format = body['format'] ?? 'json';
118
- if (typeof target !== 'string' || target.length === 0) {
119
- sendJson(res, 400, { error: 'target (string) is required' });
120
- return;
121
- }
122
- if (typeof depth !== 'string' || !DEPTHS.includes(depth)) {
123
- sendJson(res, 400, { error: `depth must be one of ${DEPTHS.join('|')}` });
124
- return;
125
- }
126
- if (typeof profile !== 'string' ||
127
- (profile !== 'auto' && !MATURITIES.includes(profile))) {
128
- sendJson(res, 400, { error: 'profile must be auto or a maturity stage' });
129
- return;
130
- }
131
- if (typeof format !== 'string' || !FORMATS.includes(format)) {
132
- sendJson(res, 400, { error: `format must be one of ${FORMATS.join('|')}` });
133
- return;
134
- }
135
- let resolved;
136
- try {
137
- resolved = resolveTarget(target, opts.roots);
138
- }
139
- catch (err) {
140
- const message = err.message;
141
- // Containment failures are authorization failures; a missing
142
- // path is a bad request. Different status, same static shape.
143
- sendJson(res, message.includes('escapes') ? 403 : 400, { error: message });
144
- return;
145
- }
146
- const submitted = manager.submit({ target, depth, profile, format }, resolved);
147
- if ('conflict' in submitted) {
148
- sendJson(res, 409, { error: 'an audit is already running' });
149
- return;
150
- }
151
- sendJson(res, 202, { id: submitted.id, status: 'running' });
152
- return;
153
- }
154
- const auditMatch = /^\/api\/audits\/([0-9a-f]+)$/.exec(url.pathname);
155
- if (req.method === 'GET' && auditMatch) {
156
- const job = manager.get(auditMatch[1]);
157
- if (!job) {
158
- sendJson(res, 404, { error: 'unknown audit id' });
159
- return;
160
- }
161
- const rendered = job.status === 'done' ? renderJobReport(job) : undefined;
162
- sendJson(res, 200, {
163
- id: job.id,
164
- status: job.status,
165
- createdAt: job.createdAt,
166
- ...(job.finishedAt === undefined ? {} : { finishedAt: job.finishedAt }),
167
- options: job.options,
168
- ...(job.error === undefined ? {} : { error: job.error }),
169
- ...(rendered === undefined
170
- ? {}
171
- : { contentType: rendered.contentType, report: rendered.body }),
172
- });
173
- return;
174
- }
175
- sendJson(res, 404, { error: 'not found' });
176
- })().catch((err) => {
118
+ handleRequest(req, res, ctx).catch((err) => {
177
119
  if (!res.headersSent)
178
120
  sendJson(res, 500, { error: 'internal error' });
179
121
  console.error(`serve: request failed: ${err.message}`);
@@ -189,4 +131,145 @@ export async function startServer(opts) {
189
131
  const port = typeof address === 'object' && address !== null ? address.port : opts.port;
190
132
  return { server, port, token: opts.token };
191
133
  }
134
+ function depthError(depth) {
135
+ if (typeof depth !== 'string' || !DEPTHS.includes(depth)) {
136
+ return `depth must be one of ${DEPTHS.join('|')}`;
137
+ }
138
+ return null;
139
+ }
140
+ function profileError(profile) {
141
+ if (typeof profile !== 'string' ||
142
+ (profile !== 'auto' && !MATURITIES.includes(profile))) {
143
+ return 'profile must be auto or a maturity stage';
144
+ }
145
+ return null;
146
+ }
147
+ function formatError(format) {
148
+ if (typeof format !== 'string' || !FORMATS.includes(format)) {
149
+ return `format must be one of ${FORMATS.join('|')}`;
150
+ }
151
+ return null;
152
+ }
153
+ function validateAuditBody(body) {
154
+ const target = body['target'];
155
+ if (typeof target !== 'string' || target.length === 0) {
156
+ return { error: 'target (string) is required' };
157
+ }
158
+ const depth = body['depth'] ?? 'standard';
159
+ const profile = body['profile'] ?? 'auto';
160
+ const format = body['format'] ?? 'json';
161
+ for (const err of [depthError(depth), profileError(profile), formatError(format)]) {
162
+ if (err)
163
+ return { error: err };
164
+ }
165
+ return {
166
+ options: {
167
+ target,
168
+ depth: depth,
169
+ profile: profile,
170
+ format: format,
171
+ },
172
+ };
173
+ }
174
+ async function handlePostAudits(req, res, ctx) {
175
+ let raw;
176
+ try {
177
+ raw = await readBody(req);
178
+ }
179
+ catch {
180
+ sendJson(res, 413, { error: 'request body too large' });
181
+ return;
182
+ }
183
+ let body;
184
+ try {
185
+ body = JSON.parse(raw);
186
+ }
187
+ catch {
188
+ sendJson(res, 400, { error: 'request body must be JSON' });
189
+ return;
190
+ }
191
+ const valid = validateAuditBody(body);
192
+ if ('error' in valid) {
193
+ sendJson(res, 400, { error: valid.error });
194
+ return;
195
+ }
196
+ let resolved;
197
+ try {
198
+ resolved = resolveTarget(valid.options.target, ctx.roots);
199
+ }
200
+ catch (err) {
201
+ const message = err.message;
202
+ // Containment failures are authorization failures; a missing
203
+ // path is a bad request. Different status, same static shape.
204
+ sendJson(res, message.includes('escapes') ? 403 : 400, { error: message });
205
+ return;
206
+ }
207
+ const submitted = ctx.manager.submit({ ...valid.options }, resolved);
208
+ if ('conflict' in submitted) {
209
+ sendJson(res, 409, { error: 'an audit is already running' });
210
+ return;
211
+ }
212
+ sendJson(res, 202, { id: submitted.id, status: 'running' });
213
+ }
214
+ function jobSummary(j) {
215
+ return {
216
+ id: j.id,
217
+ status: j.status,
218
+ createdAt: j.createdAt,
219
+ ...(j.finishedAt === undefined ? {} : { finishedAt: j.finishedAt }),
220
+ options: j.options,
221
+ ...(j.error === undefined ? {} : { error: j.error }),
222
+ };
223
+ }
224
+ function handleListAudits(res, ctx) {
225
+ sendJson(res, 200, { audits: ctx.manager.list().map(jobSummary) });
226
+ }
227
+ function handleGetAudit(res, ctx, id) {
228
+ const job = ctx.manager.get(id);
229
+ if (!job) {
230
+ sendJson(res, 404, { error: 'unknown audit id' });
231
+ return;
232
+ }
233
+ // Restored jobs carry only the filed rendering; live jobs render.
234
+ const rendered = job.rendered ?? (job.status === 'done' ? renderJobReport(job) : undefined);
235
+ sendJson(res, 200, {
236
+ ...jobSummary(job),
237
+ ...(rendered === undefined ? {} : { contentType: rendered.contentType, report: rendered.body }),
238
+ });
239
+ }
240
+ /** Request URL against the loopback base (the server never sees another host). */
241
+ function requestUrl(req) {
242
+ return new URL(req.url ?? '/', 'http://127.0.0.1');
243
+ }
244
+ async function handleRequest(req, res, ctx) {
245
+ const url = requestUrl(req);
246
+ if (req.method === 'GET' && url.pathname === '/') {
247
+ res.writeHead(200, { 'content-type': 'text/html; charset=utf-8' });
248
+ res.end(uiPage());
249
+ return;
250
+ }
251
+ if (!checkAuth(req, ctx.token)) {
252
+ sendJson(res, 401, { error: 'missing or invalid bearer token' });
253
+ return;
254
+ }
255
+ if (req.method === 'POST' && url.pathname === '/api/audits') {
256
+ await handlePostAudits(req, res, ctx);
257
+ return;
258
+ }
259
+ if (req.method === 'GET' && url.pathname === '/api/audits') {
260
+ handleListAudits(res, ctx);
261
+ return;
262
+ }
263
+ const auditId = matchAuditId(url.pathname);
264
+ if (req.method === 'GET' && auditId) {
265
+ handleGetAudit(res, ctx, auditId);
266
+ return;
267
+ }
268
+ sendJson(res, 404, { error: 'not found' });
269
+ }
270
+ /** Extract a hex audit id from /api/audits/:id, or null. */
271
+ function matchAuditId(pathname) {
272
+ const match = /^\/api\/audits\/([0-9a-f]+)$/.exec(pathname);
273
+ return match?.[1] ?? null;
274
+ }
192
275
  //# sourceMappingURL=server.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/serve/server.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/serve/server.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"ui.d.ts","sourceRoot":"","sources":["../../src/serve/ui.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,wBAAgB,MAAM,IAAI,MAAM,CAiG/B"}
1
+ {"version":3,"file":"ui.d.ts","sourceRoot":"","sources":["../../src/serve/ui.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,wBAAgB,MAAM,IAAI,MAAM,CA4H/B"}
package/dist/serve/ui.js CHANGED
@@ -33,6 +33,9 @@ pre { white-space: pre-wrap; word-break: break-word; background: rgba(127,127,12
33
33
  </form>
34
34
  <div id="status"></div>
35
35
  <div id="result"></div>
36
+ <h2>History</h2>
37
+ <button id="refresh" type="button">Refresh</button>
38
+ <div id="history"></div>
36
39
  <script>
37
40
  (function () {
38
41
  var form = document.getElementById('run');
@@ -54,6 +57,29 @@ pre { white-space: pre-wrap; word-break: break-word; background: rgba(127,127,12
54
57
  return r.json().then(function (body) { return { code: r.status, body: body }; });
55
58
  });
56
59
  }
60
+ function loadHistory() {
61
+ var history = document.getElementById('history');
62
+ clear(history);
63
+ api('/api/audits').then(function (got) {
64
+ if (got.code !== 200) { line(history, 'p', 'History: ' + (got.body.error || got.code)); return; }
65
+ (got.body.audits || []).forEach(function (a) {
66
+ var row = line(history, 'div', '');
67
+ var link = document.createElement('a');
68
+ link.href = '#';
69
+ link.textContent = a.id.slice(0, 8) + ' — ' + a.status + ' — ' + a.options.target;
70
+ link.addEventListener('click', function (ev) {
71
+ ev.preventDefault();
72
+ api('/api/audits/' + a.id).then(function (one) {
73
+ if (one.code !== 200) { say('Error: ' + (one.body.error || one.code)); return; }
74
+ say(one.body.status === 'done' ? 'Done.' : one.body.status + '.');
75
+ if (one.body.status === 'done') render(one.body);
76
+ }).catch(function (err) { say('Request failed: ' + err); });
77
+ });
78
+ row.appendChild(link);
79
+ });
80
+ }).catch(function (err) { line(history, 'p', 'History failed: ' + err); });
81
+ }
82
+ document.getElementById('refresh').addEventListener('click', loadHistory);
57
83
  form.addEventListener('submit', function (ev) {
58
84
  ev.preventDefault();
59
85
  clear(result);
@@ -74,6 +100,7 @@ pre { white-space: pre-wrap; word-break: break-word; background: rgba(127,127,12
74
100
  if (got.body.status === 'error') { say('Audit failed: ' + got.body.error); return; }
75
101
  say('Done.');
76
102
  render(got.body);
103
+ loadHistory();
77
104
  }).catch(function (err) { clearInterval(timer); say('Request failed: ' + err); });
78
105
  }, 1000);
79
106
  }).catch(function (err) { say('Request failed: ' + err); });
@@ -1 +1 @@
1
- {"version":3,"file":"ui.js","sourceRoot":"","sources":["../../src/serve/ui.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,UAAU,MAAM;IACpB,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+FR,CAAC;AACF,CAAC"}
1
+ {"version":3,"file":"ui.js","sourceRoot":"","sources":["../../src/serve/ui.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,UAAU,MAAM;IACpB,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0HR,CAAC;AACF,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xenos1996/usa",
3
- "version": "2.17.0",
3
+ "version": "2.18.0",
4
4
  "description": "Universal Software Auditor — an open-source, self-adapting audit framework for any project, any stack, any stage",
5
5
  "license": "MIT",
6
6
  "type": "module",