Files
shannon/apps/worker/src/paths.ts
T

105 lines
4.2 KiB
TypeScript

/** Centralized path constants for the worker package */
import fs from 'node:fs';
import path from 'node:path';
/** Worker package root (apps/worker/) resolved from compiled dist/ files */
const WORKER_ROOT = path.resolve(import.meta.dirname, '..');
export const PROMPTS_DIR = path.join(WORKER_ROOT, 'prompts');
export const CONFIGS_DIR = path.join(WORKER_ROOT, 'configs');
/** Bundled Typst template that renders report.json into the PDF report. */
export const TYPST_TEMPLATE = path.join(WORKER_ROOT, 'templates', 'typst', 'report.typ');
/** Compiled pi extension dir that enforces bounded `bash` timeouts (resolved from dist/) */
export const BASH_TIMEOUT_EXTENSION_DIR = path.join(import.meta.dirname, 'ai', 'extensions', 'bash-timeout');
/**
* Where the CLI mounts a pi model config passed with `--models-config`; its presence is
* what enables models.json. Must match MODELS_CONFIG_CONTAINER_PATH in the CLI package.
*/
export const MODELS_CONFIG_PATH = '/app/models.json';
/** Default deliverables subdirectory relative to repoPath */
export const DEFAULT_DELIVERABLES_SUBDIR = '.shannon/deliverables';
/** Default audit log directory */
export const DEFAULT_AUDIT_DIR = './workspaces';
/**
* Hidden subdirectory inside each run directory that holds all internals
* (logs, prompts, session state, deliverables, browser artifacts). Keeps the
* run folder's top level clean so only the final report is visible.
*/
export const INTERNAL_DIR = '.shannon';
/** Filename of the assembled report inside the deliverables dir (internal, source of the surfaced copy) */
export const ASSEMBLED_REPORT_FILENAME = 'comprehensive_security_assessment_report.md';
/** Filename of the compiled PDF report inside the deliverables dir (internal, source of the surfaced copy) */
export const ASSEMBLED_REPORT_PDF_FILENAME = 'comprehensive_security_assessment_report.pdf';
/** Filename of the human-facing PDF report surfaced at the run directory root */
export const FINAL_REPORT_PDF_FILENAME = 'Security-Assessment-Report.pdf';
/** Filename of the human-facing markdown report surfaced at the run directory root, alongside the PDF */
export const FINAL_REPORT_MD_FILENAME = 'Security-Assessment-Report.md';
/** Structured findings the report agent emits; the markdown report is rendered from it. */
export const REPORT_JSON_FILENAME = 'report.json';
/** SARIF 2.1.0 log, written for exploit=true runs unless report.sarif is set to false. */
export const SARIF_FILENAME = 'report.sarif';
/** Deterministic receipt for the canonical report finalization commit. */
export const REPORT_FINALIZATION_MANIFEST_FILENAME = 'report_finalization_manifest.json';
/**
* Resolve the session.json path for a run directory, preferring the current
* `.shannon/` location and falling back to the legacy run-root location so
* pre-restructure workspaces remain listable and resumable.
*/
export function resolveSessionJsonPath(runDir: string): string {
const current = path.join(runDir, INTERNAL_DIR, 'session.json');
if (fs.existsSync(current)) {
return current;
}
const legacy = path.join(runDir, 'session.json');
if (fs.existsSync(legacy)) {
return legacy;
}
return current;
}
/**
* Resolve the deliverables directory for a given repoPath and optional subdir override.
* @param repoPath - Absolute path to the target repository
* @param subdir - Subdirectory relative to repoPath (default: '.shannon/deliverables')
*/
export function deliverablesDir(repoPath: string, subdir: string = DEFAULT_DELIVERABLES_SUBDIR): string {
return path.join(repoPath, ...subdir.split('/'));
}
/**
* Repository root — walk up from WORKER_ROOT looking for pnpm-workspace.yaml.
* Falls back to two levels up (apps/worker/ → repo root) if not found.
*/
function findRepoRoot(): string {
let dir = WORKER_ROOT;
for (let i = 0; i < 5; i++) {
if (fs.existsSync(path.join(dir, 'pnpm-workspace.yaml'))) {
return dir;
}
const parent = path.dirname(dir);
if (parent === dir) break;
dir = parent;
}
return path.resolve(WORKER_ROOT, '..', '..');
}
const REPO_ROOT = findRepoRoot();
/** Default root for named scan workspaces; each session's audit directory nests under here. */
export const WORKSPACES_DIR = path.join(REPO_ROOT, 'workspaces');