@attest-it/core 0.0.2 → 0.4.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.
- package/dist/{chunk-CEE7ONNG.js → chunk-VC3BBBBO.js} +39 -20
- package/dist/chunk-VC3BBBBO.js.map +1 -0
- package/dist/core-alpha.d.ts +1109 -19
- package/dist/core-beta.d.ts +1109 -19
- package/dist/core-public.d.ts +1109 -19
- package/dist/core-unstripped.d.ts +1109 -19
- package/dist/{crypto-VAXWUGKL.js → crypto-CE2YISRD.js} +3 -3
- package/dist/{crypto-VAXWUGKL.js.map → crypto-CE2YISRD.js.map} +1 -1
- package/dist/index.cjs +1324 -56
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1163 -20
- package/dist/index.d.ts +1159 -20
- package/dist/index.js +1267 -54
- package/dist/index.js.map +1 -1
- package/package.json +3 -1
- package/dist/chunk-CEE7ONNG.js.map +0 -1
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/crypto.ts","../src/config.ts","../src/fingerprint.ts","../src/attestation.ts","../src/index.ts","../src/verify.ts"],"names":["resolve","spawn","os","path2","fs2","z","parseYaml","join","readFileSync","readFile","path","crypto","hash","fs","glob","globSync","canonicalizeNamespace","fs3","path3","os2","sign","verify","fs4","path4"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Cryptographic utilities for key generation, signing, and verification.\n *\n * @remarks\n * This module provides cryptographic operations using OpenSSL for key management\n * and signature verification. It uses RSA-2048 with SHA-256 for signatures,\n * which is universally supported across all OpenSSL and LibreSSL versions.\n *\n * @packageDocumentation\n */\n\nimport { spawn } from 'node:child_process'\nimport * as fs from 'node:fs/promises'\nimport * as path from 'node:path'\nimport * as os from 'node:os'\n\n/**\n * Paths to a generated keypair.\n * @public\n */\nexport interface KeyPaths {\n /** Path to the private key file */\n privatePath: string\n /** Path to the public key file */\n publicPath: string\n}\n\n/**\n * Options for key generation.\n * @public\n */\nexport interface KeygenOptions {\n /** Path for private key (default: OS-specific config dir) */\n privatePath?: string\n /** Path for public key (default: repo root) */\n publicPath?: string\n /** Overwrite existing keys (default: false) */\n force?: boolean\n}\n\n/**\n * Options for signing data.\n * @public\n */\nexport interface SignOptions {\n /** Path to the private key file */\n privateKeyPath: string\n /** Data to sign (string or Buffer) */\n data: string | Buffer\n}\n\n/**\n * Options for verifying signatures.\n * @public\n */\nexport interface VerifyOptions {\n /** Path to the public key file */\n publicKeyPath: string\n /** Original data that was signed */\n data: string | Buffer\n /** Base64-encoded signature to verify */\n signature: string\n}\n\n/**\n * Result from spawning an OpenSSL process.\n * @internal\n */\ninterface SpawnResult {\n /** Process exit code */\n exitCode: number\n /** Standard output as Buffer */\n stdout: Buffer\n /** Standard error as string */\n stderr: string\n}\n\n/**\n * Run OpenSSL with the given arguments.\n * @param args - Command-line arguments for OpenSSL\n * @param stdin - Optional data to write to stdin\n * @returns Process result with exit code and outputs\n * @internal\n */\nasync function runOpenSSL(args: string[], stdin?: Buffer): Promise<SpawnResult> {\n return new Promise((resolve, reject) => {\n const child = spawn('openssl', args, {\n stdio: ['pipe', 'pipe', 'pipe'],\n })\n\n const stdoutChunks: Buffer[] = []\n let stderr = ''\n\n child.stdout.on('data', (chunk: Buffer) => {\n stdoutChunks.push(chunk)\n })\n\n child.stderr.on('data', (chunk: Buffer) => {\n stderr += chunk.toString()\n })\n\n child.on('error', (err) => {\n reject(new Error(`Failed to spawn OpenSSL: ${err.message}`))\n })\n\n child.on('close', (code) => {\n resolve({\n exitCode: code ?? 1,\n stdout: Buffer.concat(stdoutChunks),\n stderr,\n })\n })\n\n if (stdin) {\n child.stdin.write(stdin)\n }\n child.stdin.end()\n })\n}\n\n/**\n * Check if OpenSSL is available and get version info.\n * @returns OpenSSL version string\n * @throws Error if OpenSSL is not available\n * @public\n */\nexport async function checkOpenSSL(): Promise<string> {\n const result = await runOpenSSL(['version'])\n\n if (result.exitCode !== 0) {\n throw new Error(`OpenSSL check failed: ${result.stderr}`)\n }\n\n return result.stdout.toString().trim()\n}\n\n/**\n * Cached result of OpenSSL availability check.\n * @internal\n */\nlet openSSLChecked = false\n\n/**\n * Ensure OpenSSL is available before performing cryptographic operations.\n * @throws Error with installation instructions if OpenSSL is not available\n * @internal\n */\nasync function ensureOpenSSLAvailable(): Promise<void> {\n if (openSSLChecked) {\n return\n }\n\n try {\n await checkOpenSSL()\n openSSLChecked = true\n } catch {\n throw new Error(\n 'OpenSSL is not installed or not in PATH. ' +\n 'Please install OpenSSL to use attest-it. ' +\n 'On macOS: brew install openssl. ' +\n 'On Ubuntu: apt-get install openssl',\n )\n }\n}\n\n/**\n * Get the default private key path based on OS.\n * - macOS/Linux: ~/.config/attest-it/private.pem\n * - Windows: %APPDATA%\\attest-it\\private.pem\n * @public\n */\nexport function getDefaultPrivateKeyPath(): string {\n const homeDir = os.homedir()\n\n if (process.platform === 'win32') {\n const appData = process.env.APPDATA ?? path.join(homeDir, 'AppData', 'Roaming')\n return path.join(appData, 'attest-it', 'private.pem')\n }\n\n return path.join(homeDir, '.config', 'attest-it', 'private.pem')\n}\n\n/**\n * Get the default public key path (in repo).\n * @public\n */\nexport function getDefaultPublicKeyPath(): string {\n return path.join(process.cwd(), 'attest-it-public.pem')\n}\n\n/**\n * Ensure a directory exists, creating it and parent directories if needed.\n * @param dirPath - Directory path to create\n * @internal\n */\nasync function ensureDir(dirPath: string): Promise<void> {\n try {\n await fs.mkdir(dirPath, { recursive: true })\n } catch (err) {\n if (err instanceof Error && 'code' in err && err.code !== 'EEXIST') {\n throw err\n }\n }\n}\n\n/**\n * Check if a file exists.\n * @param filePath - File path to check\n * @returns true if file exists\n * @internal\n */\nasync function fileExists(filePath: string): Promise<boolean> {\n try {\n await fs.access(filePath)\n return true\n } catch {\n return false\n }\n}\n\n/**\n * Clean up one or more files, ignoring errors if files don't exist.\n * @param paths - File paths to delete\n * @internal\n */\nasync function cleanupFiles(...paths: string[]): Promise<void> {\n for (const filePath of paths) {\n try {\n await fs.unlink(filePath)\n } catch {\n // Ignore cleanup errors - file may not exist\n }\n }\n}\n\n/**\n * Generate a new RSA-2048 keypair using OpenSSL.\n *\n * RSA-2048 with SHA-256 is used because it's universally supported across\n * all OpenSSL and LibreSSL versions, including older macOS systems.\n *\n * @param options - Generation options\n * @returns Paths to generated keys\n * @throws Error if OpenSSL fails or keys exist without force\n * @public\n */\nexport async function generateKeyPair(options: KeygenOptions = {}): Promise<KeyPaths> {\n // Ensure OpenSSL is available before proceeding\n await ensureOpenSSLAvailable()\n\n const {\n privatePath = getDefaultPrivateKeyPath(),\n publicPath = getDefaultPublicKeyPath(),\n force = false,\n } = options\n\n // Check if keys already exist\n const privateExists = await fileExists(privatePath)\n const publicExists = await fileExists(publicPath)\n\n if ((privateExists || publicExists) && !force) {\n const existing = [privateExists ? privatePath : null, publicExists ? publicPath : null].filter(\n Boolean,\n )\n throw new Error(\n `Key files already exist: ${existing.join(', ')}. Use force: true to overwrite.`,\n )\n }\n\n // Ensure parent directories exist\n await ensureDir(path.dirname(privatePath))\n await ensureDir(path.dirname(publicPath))\n\n try {\n // Generate RSA-2048 private key\n const genArgs = [\n 'genpkey',\n '-algorithm',\n 'RSA',\n '-pkeyopt',\n 'rsa_keygen_bits:2048',\n '-out',\n privatePath,\n ]\n\n const genResult = await runOpenSSL(genArgs)\n if (genResult.exitCode !== 0) {\n throw new Error(`Failed to generate private key: ${genResult.stderr}`)\n }\n\n // Set restrictive permissions on private key\n await setKeyPermissions(privatePath)\n\n // Extract public key\n const pubResult = await runOpenSSL(['pkey', '-in', privatePath, '-pubout', '-out', publicPath])\n\n if (pubResult.exitCode !== 0) {\n throw new Error(`Failed to extract public key: ${pubResult.stderr}`)\n }\n\n return {\n privatePath,\n publicPath,\n }\n } catch (err) {\n // Clean up both key files on any failure\n await cleanupFiles(privatePath, publicPath)\n throw err\n }\n}\n\n/**\n * Sign data using an RSA private key with SHA-256.\n *\n * Uses `openssl dgst -sha256 -sign` which is universally supported across\n * all OpenSSL and LibreSSL versions.\n *\n * @param options - Signing options\n * @returns Base64-encoded signature\n * @throws Error if signing fails\n * @public\n */\nexport async function sign(options: SignOptions): Promise<string> {\n // Ensure OpenSSL is available before proceeding\n await ensureOpenSSLAvailable()\n\n const { privateKeyPath, data } = options\n\n // Check if private key exists\n if (!(await fileExists(privateKeyPath))) {\n throw new Error(`Private key not found: ${privateKeyPath}`)\n }\n\n // Convert data to Buffer\n const dataBuffer = typeof data === 'string' ? Buffer.from(data, 'utf8') : data\n\n // OpenSSL dgst cannot handle empty files, so we need to add a single byte\n // for empty data and document this limitation\n const processBuffer = dataBuffer.length === 0 ? Buffer.from([0x00]) : dataBuffer\n\n // Create temporary directory with OS-level uniqueness guarantees\n // This prevents TOCTOU race conditions that Math.random() would allow\n const tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), 'attest-it-'))\n const dataFile = path.join(tmpDir, 'data.bin')\n const sigFile = path.join(tmpDir, 'sig.bin')\n\n try {\n // Write data to temp file\n await fs.writeFile(dataFile, processBuffer)\n\n // Sign using openssl dgst -sha256 (cross-platform compatible)\n const signArgs = ['dgst', '-sha256', '-sign', privateKeyPath, '-out', sigFile, dataFile]\n const result = await runOpenSSL(signArgs)\n\n if (result.exitCode !== 0) {\n throw new Error(`Failed to sign data: ${result.stderr}`)\n }\n\n // Read the signature\n const sigBuffer = await fs.readFile(sigFile)\n return sigBuffer.toString('base64')\n } finally {\n // Clean up temp directory and all files within it\n try {\n await fs.rm(tmpDir, { recursive: true, force: true })\n } catch {\n // Ignore cleanup errors - OS will eventually clean tmpdir\n }\n }\n}\n\n/**\n * Verify a signature using an RSA public key with SHA-256.\n *\n * Uses `openssl dgst -sha256 -verify` which is universally supported across\n * all OpenSSL and LibreSSL versions.\n *\n * @param options - Verification options\n * @returns true if signature is valid\n * @throws Error if verification fails (not just invalid signature)\n * @public\n */\nexport async function verify(options: VerifyOptions): Promise<boolean> {\n // Ensure OpenSSL is available before proceeding\n await ensureOpenSSLAvailable()\n\n const { publicKeyPath, data, signature } = options\n\n // Check if public key exists\n if (!(await fileExists(publicKeyPath))) {\n throw new Error(`Public key not found: ${publicKeyPath}`)\n }\n\n // Convert data to Buffer\n const dataBuffer = typeof data === 'string' ? Buffer.from(data, 'utf8') : data\n\n // OpenSSL dgst cannot handle empty files, so we use the same workaround\n // as in sign() - add a single byte for empty data\n const processBuffer = dataBuffer.length === 0 ? Buffer.from([0x00]) : dataBuffer\n\n // Decode signature from base64\n const sigBuffer = Buffer.from(signature, 'base64')\n\n // Create temporary directory with OS-level uniqueness guarantees\n // This prevents TOCTOU race conditions that Math.random() would allow\n const tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), 'attest-it-'))\n const dataFile = path.join(tmpDir, 'data.bin')\n const sigFile = path.join(tmpDir, 'sig.bin')\n\n try {\n // Write data and signature to temp files\n await fs.writeFile(dataFile, processBuffer)\n await fs.writeFile(sigFile, sigBuffer)\n\n // Verify using openssl dgst -sha256 (cross-platform compatible)\n const verifyArgs = [\n 'dgst',\n '-sha256',\n '-verify',\n publicKeyPath,\n '-signature',\n sigFile,\n dataFile,\n ]\n const result = await runOpenSSL(verifyArgs)\n\n // dgst -verify: Exit code 0 means valid, non-0 means invalid\n // Output contains \"Verified OK\" on success\n return result.exitCode === 0 && result.stdout.toString().includes('Verified OK')\n } finally {\n // Clean up temp directory and all files within it\n try {\n await fs.rm(tmpDir, { recursive: true, force: true })\n } catch {\n // Ignore cleanup errors - OS will eventually clean tmpdir\n }\n }\n}\n\n/**\n * Set restrictive permissions on a private key file.\n * @param keyPath - Path to the private key\n * @public\n */\nexport async function setKeyPermissions(keyPath: string): Promise<void> {\n // On Windows, use fs.chmod which has limited effect\n // On Unix, set to 0o600 (read/write for owner only)\n if (process.platform === 'win32') {\n // Windows doesn't support Unix-style permissions in the same way\n // But we still call chmod for consistency\n await fs.chmod(keyPath, 0o600)\n } else {\n await fs.chmod(keyPath, 0o600)\n }\n}\n","/**\n * Configuration loading and validation for attest-it.\n */\n\nimport { readFileSync } from 'node:fs'\nimport { readFile } from 'node:fs/promises'\nimport { join, resolve } from 'node:path'\nimport { parse as parseYaml } from 'yaml'\nimport { z } from 'zod'\n\n/**\n * Zod schema for settings with defaults applied.\n */\nconst settingsSchema = z\n .object({\n maxAgeDays: z.number().int().positive().default(30),\n publicKeyPath: z.string().default('.attest-it/pubkey.pem'),\n attestationsPath: z.string().default('.attest-it/attestations.json'),\n defaultCommand: z.string().optional(),\n // Note: algorithm field was removed - RSA is the only supported algorithm\n })\n .passthrough()\n\n/**\n * Zod schema for a suite configuration.\n */\nconst suiteSchema = z\n .object({\n description: z.string().optional(),\n packages: z\n .array(z.string().min(1, 'Package path cannot be empty'))\n .min(1, 'At least one package pattern is required'),\n files: z.array(z.string().min(1, 'File path cannot be empty')).optional(),\n ignore: z.array(z.string().min(1, 'Ignore pattern cannot be empty')).optional(),\n command: z.string().optional(),\n invalidates: z.array(z.string().min(1, 'Invalidated suite name cannot be empty')).optional(),\n })\n .strict()\n\n/**\n * Zod schema for the full configuration file.\n */\nconst configSchema = z\n .object({\n version: z.literal(1),\n settings: settingsSchema.default({}),\n suites: z.record(z.string(), suiteSchema).refine((suites) => Object.keys(suites).length >= 1, {\n message: 'At least one suite must be defined',\n }),\n })\n .strict()\n\n/**\n * Type inference from Zod schema (should match AttestItConfig).\n * This is the same as AttestItConfig but with defaults applied.\n * @public\n */\nexport type Config = z.infer<typeof configSchema>\n\n/**\n * Error thrown when configuration is invalid.\n * @public\n */\nexport class ConfigValidationError extends Error {\n constructor(\n message: string,\n public readonly issues: z.ZodIssue[],\n ) {\n super(message)\n this.name = 'ConfigValidationError'\n }\n}\n\n/**\n * Error thrown when configuration file cannot be found.\n * @public\n */\nexport class ConfigNotFoundError extends Error {\n constructor(message: string) {\n super(message)\n this.name = 'ConfigNotFoundError'\n }\n}\n\n/**\n * Parse configuration content from a string.\n *\n * @param content - The configuration file content\n * @param format - The format of the content ('yaml' or 'json')\n * @returns Parsed and validated configuration\n * @throws {ConfigValidationError} If validation fails\n */\nfunction parseConfigContent(content: string, format: 'yaml' | 'json'): Config {\n let rawConfig: unknown\n\n try {\n if (format === 'yaml') {\n rawConfig = parseYaml(content)\n } else {\n rawConfig = JSON.parse(content)\n }\n } catch (error) {\n throw new ConfigValidationError(\n `Failed to parse ${format.toUpperCase()}: ${error instanceof Error ? error.message : String(error)}`,\n [],\n )\n }\n\n const result = configSchema.safeParse(rawConfig)\n\n if (!result.success) {\n throw new ConfigValidationError(\n 'Configuration validation failed:\\n' +\n result.error.issues\n .map((issue) => ` - ${issue.path.join('.')}: ${issue.message}`)\n .join('\\n'),\n result.error.issues,\n )\n }\n\n return result.data\n}\n\n/**\n * Determine the format of a config file from its extension.\n *\n * @param filePath - Path to the config file\n * @returns 'yaml' or 'json'\n */\nfunction getConfigFormat(filePath: string): 'yaml' | 'json' {\n const ext = filePath.toLowerCase()\n if (ext.endsWith('.yaml') || ext.endsWith('.yml')) {\n return 'yaml'\n }\n if (ext.endsWith('.json')) {\n return 'json'\n }\n // Default to yaml for extensionless files\n return 'yaml'\n}\n\n/**\n * Find the configuration file in default locations.\n *\n * Searches in this order:\n * 1. .attest-it/config.yaml\n * 2. .attest-it/config.yml\n * 3. .attest-it/config.json\n *\n * @param startDir - Directory to start searching from (defaults to cwd)\n * @returns Absolute path to the config file, or null if not found\n * @public\n */\nexport function findConfigPath(startDir: string = process.cwd()): string | null {\n const configDir = join(startDir, '.attest-it')\n const candidates = ['config.yaml', 'config.yml', 'config.json']\n\n for (const candidate of candidates) {\n const configPath = join(configDir, candidate)\n try {\n readFileSync(configPath, 'utf8')\n return configPath\n } catch {\n // File doesn't exist or can't be read, try next candidate\n continue\n }\n }\n\n return null\n}\n\n/**\n * Load and validate configuration from a file (async).\n *\n * @param configPath - Optional path to config file. If not provided, searches default locations.\n * @returns Validated configuration object\n * @throws {@link ConfigNotFoundError} If config file cannot be found\n * @throws {@link ConfigValidationError} If validation fails\n * @public\n */\nexport async function loadConfig(configPath?: string): Promise<Config> {\n const resolvedPath = configPath ?? findConfigPath()\n\n if (!resolvedPath) {\n throw new ConfigNotFoundError(\n 'Configuration file not found. Expected .attest-it/config.yaml, .attest-it/config.yml, or .attest-it/config.json',\n )\n }\n\n try {\n const content = await readFile(resolvedPath, 'utf8')\n const format = getConfigFormat(resolvedPath)\n return parseConfigContent(content, format)\n } catch (error) {\n if (error instanceof ConfigValidationError) {\n throw error\n }\n throw new ConfigNotFoundError(\n `Failed to read configuration file at ${resolvedPath}: ${String(error)}`,\n )\n }\n}\n\n/**\n * Load and validate configuration from a file (sync).\n *\n * @param configPath - Optional path to config file. If not provided, searches default locations.\n * @returns Validated configuration object\n * @throws {@link ConfigNotFoundError} If config file cannot be found\n * @throws {@link ConfigValidationError} If validation fails\n * @public\n */\nexport function loadConfigSync(configPath?: string): Config {\n const resolvedPath = configPath ?? findConfigPath()\n\n if (!resolvedPath) {\n throw new ConfigNotFoundError(\n 'Configuration file not found. Expected .attest-it/config.yaml, .attest-it/config.yml, or .attest-it/config.json',\n )\n }\n\n try {\n const content = readFileSync(resolvedPath, 'utf8')\n const format = getConfigFormat(resolvedPath)\n return parseConfigContent(content, format)\n } catch (error) {\n if (error instanceof ConfigValidationError) {\n throw error\n }\n throw new ConfigNotFoundError(\n `Failed to read configuration file at ${resolvedPath}: ${String(error)}`,\n )\n }\n}\n\n/**\n * Resolve relative paths in the configuration against the repository root.\n *\n * This converts relative paths in settings.publicKeyPath and settings.attestationsPath\n * to absolute paths relative to the repository root.\n *\n * @param config - The configuration object\n * @param repoRoot - Absolute path to the repository root\n * @returns Configuration with resolved absolute paths\n * @public\n */\nexport function resolveConfigPaths(config: Config, repoRoot: string): Config {\n return {\n ...config,\n settings: {\n ...config.settings,\n publicKeyPath: resolve(repoRoot, config.settings.publicKeyPath),\n attestationsPath: resolve(repoRoot, config.settings.attestationsPath),\n },\n }\n}\n\n/**\n * Convert Zod-validated Config to AttestItConfig by removing undefined values.\n *\n * The Config type (from Zod) has optional fields as `T | undefined`,\n * while AttestItConfig has optional fields as `T?` (can be absent, not undefined).\n *\n * This adapter removes any undefined values to match the AttestItConfig interface\n * that the core functions expect.\n *\n * @param config - The Zod-validated configuration from loadConfig()\n * @returns Configuration compatible with AttestItConfig\n * @public\n */\nexport function toAttestItConfig(config: Config): import('./types.js').AttestItConfig {\n return {\n version: config.version,\n settings: {\n maxAgeDays: config.settings.maxAgeDays,\n publicKeyPath: config.settings.publicKeyPath,\n attestationsPath: config.settings.attestationsPath,\n ...(config.settings.defaultCommand !== undefined && {\n defaultCommand: config.settings.defaultCommand,\n }),\n },\n suites: Object.fromEntries(\n Object.entries(config.suites).map(([name, suite]) => [\n name,\n {\n packages: suite.packages,\n ...(suite.description !== undefined && { description: suite.description }),\n ...(suite.files !== undefined && { files: suite.files }),\n ...(suite.ignore !== undefined && { ignore: suite.ignore }),\n ...(suite.command !== undefined && { command: suite.command }),\n ...(suite.invalidates !== undefined && { invalidates: suite.invalidates }),\n },\n ]),\n ),\n }\n}\n","import * as crypto from 'node:crypto'\nimport * as fs from 'node:fs'\nimport * as path from 'node:path'\nimport { glob, globSync } from 'tinyglobby'\n\n/**\n * Threshold for streaming large files instead of reading into memory.\n * Files larger than this will be hashed via streaming to avoid memory issues.\n */\nconst LARGE_FILE_THRESHOLD = 50 * 1024 * 1024 // 50MB\n\n/**\n * Options for computing a package fingerprint.\n * @public\n */\nexport interface FingerprintOptions {\n /** Package directories to include */\n packages: string[]\n /** Glob patterns to exclude from fingerprint */\n ignore?: string[]\n /** Base directory for resolving paths */\n baseDir?: string\n}\n\n/**\n * Result of computing a package fingerprint.\n * @public\n */\nexport interface FingerprintResult {\n /** The fingerprint in \"sha256:...\" format */\n fingerprint: string\n /** List of files included in fingerprint calculation */\n files: string[]\n /** Number of files processed */\n fileCount: number\n}\n\n/**\n * Internal representation of a file hash for fingerprint computation.\n */\ninterface FileHashInput {\n /** The normalized relative path of the file */\n relativePath: string\n /** The computed hash of the file content */\n hash: Buffer\n}\n\n/**\n * Sort files lexicographically (locale-independent).\n */\nfunction sortFiles(files: string[]): string[] {\n return [...files].sort((a, b) => {\n if (a < b) return -1\n if (a > b) return 1\n return 0\n })\n}\n\n/**\n * Normalize path separators to forward slashes.\n */\nfunction normalizePath(filePath: string): string {\n return filePath.split(path.sep).join('/')\n}\n\n/**\n * Compute final fingerprint from file hashes.\n */\nfunction computeFinalFingerprint(fileHashes: FileHashInput[]): string {\n // Sort by relative path\n const sorted = [...fileHashes].sort((a, b) => {\n if (a.relativePath < b.relativePath) return -1\n if (a.relativePath > b.relativePath) return 1\n return 0\n })\n\n // Concatenate all file hashes\n const hashes = sorted.map((input) => input.hash)\n const concatenated = Buffer.concat(hashes)\n\n // Compute final hash\n const finalHash = crypto.createHash('sha256').update(concatenated).digest()\n return `sha256:${finalHash.toString('hex')}`\n}\n\n/**\n * Hash a file's content using streaming for large files (async).\n * For files larger than LARGE_FILE_THRESHOLD, uses streaming to avoid memory issues.\n */\nasync function hashFileAsync(\n realPath: string,\n normalizedPath: string,\n stats: fs.Stats,\n): Promise<Buffer> {\n if (stats.size > LARGE_FILE_THRESHOLD) {\n // Stream large files to avoid memory issues\n return new Promise((resolve, reject) => {\n const hash = crypto.createHash('sha256')\n hash.update(normalizedPath)\n hash.update('\\0')\n\n const stream = fs.createReadStream(realPath)\n stream.on('data', (chunk: string | Buffer) => {\n hash.update(chunk)\n })\n stream.on('end', () => {\n resolve(hash.digest())\n })\n stream.on('error', reject)\n })\n }\n\n // Read small files into memory (faster than streaming)\n const content = await fs.promises.readFile(realPath)\n const hash = crypto.createHash('sha256')\n hash.update(normalizedPath)\n hash.update('\\0')\n hash.update(content)\n return hash.digest()\n}\n\n/**\n * Hash a file's content synchronously.\n * Note: Cannot stream synchronously, so large files are read into memory.\n */\nfunction hashFileSync(realPath: string, normalizedPath: string): Buffer {\n const content = fs.readFileSync(realPath)\n const hash = crypto.createHash('sha256')\n hash.update(normalizedPath)\n hash.update('\\0')\n hash.update(content)\n return hash.digest()\n}\n\n/**\n * Validate fingerprint options and return base directory.\n */\nfunction validateOptions(options: FingerprintOptions): string {\n if (options.packages.length === 0) {\n throw new Error('packages array must not be empty')\n }\n\n const baseDir = options.baseDir ?? process.cwd()\n\n // Verify all package paths exist\n for (const pkg of options.packages) {\n const pkgPath = path.resolve(baseDir, pkg)\n if (!fs.existsSync(pkgPath)) {\n throw new Error(`Package path does not exist: ${pkgPath}`)\n }\n }\n\n return baseDir\n}\n\n/**\n * Compute a deterministic fingerprint for a set of packages (async).\n *\n * Algorithm:\n * 1. List all files in packages (respecting ignore globs)\n * 2. Sort files lexicographically by relative path\n * 3. For each file: compute SHA256(relativePath + \"\\0\" + content)\n * 4. Concatenate all file hashes in sorted order\n * 5. Compute final SHA256 of concatenated hashes\n * 6. Return \"sha256:\" + hex(fingerprint)\n *\n * @param options - Configuration for fingerprint computation\n * @returns Result containing the fingerprint hash and list of files processed\n * @throws Error if packages array is empty or if package paths don't exist\n * @public\n */\nexport async function computeFingerprint(options: FingerprintOptions): Promise<FingerprintResult> {\n const baseDir = validateOptions(options)\n\n // List all files in packages\n const files = await listPackageFiles(options.packages, options.ignore, baseDir)\n\n // Sort files lexicographically\n const sortedFiles = sortFiles(files)\n\n // Track visited files to handle multiple symlinks pointing to the same file\n // Key: realpath, Value: file hash\n const fileHashCache = new Map<string, Buffer>()\n\n // Compute individual file hashes\n const fileHashInputs: FileHashInput[] = []\n for (const file of sortedFiles) {\n const filePath = path.resolve(baseDir, file)\n\n // Handle symlinks\n let realPath = filePath\n let stats = await fs.promises.lstat(filePath)\n\n if (stats.isSymbolicLink()) {\n try {\n realPath = await fs.promises.realpath(filePath)\n } catch {\n // Skip broken symlinks\n continue\n }\n\n // Get stats of the target\n try {\n stats = await fs.promises.stat(realPath)\n } catch {\n // Skip broken symlinks\n continue\n }\n }\n\n // Skip if not a file (e.g., directories)\n if (!stats.isFile()) {\n continue\n }\n\n // Normalize path separators to forward slashes\n const normalizedPath = normalizePath(file)\n\n // Check if we've already hashed this file (via symlinks)\n let hash: Buffer\n const cachedHash = fileHashCache.get(realPath)\n if (cachedHash !== undefined) {\n // Reuse cached hash for files we've already seen (via symlinks)\n hash = cachedHash\n } else {\n // Hash the file content\n hash = await hashFileAsync(realPath, normalizedPath, stats)\n fileHashCache.set(realPath, hash)\n }\n\n fileHashInputs.push({ relativePath: normalizedPath, hash })\n }\n\n // Compute final fingerprint\n const fingerprint = computeFinalFingerprint(fileHashInputs)\n\n return {\n fingerprint,\n files: sortedFiles,\n fileCount: sortedFiles.length,\n }\n}\n\n/**\n * Compute a deterministic fingerprint for a set of packages (sync).\n *\n * @param options - Configuration for fingerprint computation\n * @returns Result containing the fingerprint hash and list of files processed\n * @throws Error if packages array is empty or if package paths don't exist\n * @public\n * @see {@link computeFingerprint} for the async version\n */\nexport function computeFingerprintSync(options: FingerprintOptions): FingerprintResult {\n const baseDir = validateOptions(options)\n\n // List all files in packages (sync version)\n const files = listPackageFilesSync(options.packages, options.ignore, baseDir)\n\n // Sort files lexicographically\n const sortedFiles = sortFiles(files)\n\n // Track visited files to handle multiple symlinks pointing to the same file\n // Key: realpath, Value: file hash\n const fileHashCache = new Map<string, Buffer>()\n\n // Compute individual file hashes\n const fileHashInputs: FileHashInput[] = []\n for (const file of sortedFiles) {\n const filePath = path.resolve(baseDir, file)\n\n // Handle symlinks\n let realPath = filePath\n let stats = fs.lstatSync(filePath)\n\n if (stats.isSymbolicLink()) {\n try {\n realPath = fs.realpathSync(filePath)\n } catch {\n // Skip broken symlinks\n continue\n }\n\n // Get stats of the target\n try {\n stats = fs.statSync(realPath)\n } catch {\n // Skip broken symlinks\n continue\n }\n }\n\n // Skip if not a file (e.g., directories)\n if (!stats.isFile()) {\n continue\n }\n\n // Normalize path separators to forward slashes\n const normalizedPath = normalizePath(file)\n\n // Check if we've already hashed this file (via symlinks)\n let hash: Buffer\n const cachedHash = fileHashCache.get(realPath)\n if (cachedHash !== undefined) {\n // Reuse cached hash for files we've already seen (via symlinks)\n hash = cachedHash\n } else {\n // Hash the file content (sync version cannot stream)\n hash = hashFileSync(realPath, normalizedPath)\n fileHashCache.set(realPath, hash)\n }\n\n fileHashInputs.push({ relativePath: normalizedPath, hash })\n }\n\n // Compute final fingerprint\n const fingerprint = computeFinalFingerprint(fileHashInputs)\n\n return {\n fingerprint,\n files: sortedFiles,\n fileCount: sortedFiles.length,\n }\n}\n\n/**\n * List files in packages, respecting ignore patterns (async).\n *\n * @param packages - Array of package directory paths\n * @param ignore - Optional glob patterns to exclude\n * @param baseDir - Base directory for resolving paths (defaults to cwd)\n * @returns Array of relative file paths\n * @public\n */\nexport async function listPackageFiles(\n packages: string[],\n ignore: string[] = [],\n baseDir: string = process.cwd(),\n): Promise<string[]> {\n const allFiles: string[] = []\n\n for (const pkg of packages) {\n // Build glob patterns for this package\n const patterns = [`${pkg}/**/*`]\n\n // Use tinyglobby to find files\n const files = await glob(patterns, {\n cwd: baseDir,\n ignore,\n onlyFiles: true,\n dot: true, // Include dotfiles\n absolute: false, // Return relative paths\n })\n\n allFiles.push(...files)\n }\n\n return allFiles\n}\n\n/**\n * Synchronous version of listPackageFiles\n */\nfunction listPackageFilesSync(\n packages: string[],\n ignore: string[] = [],\n baseDir: string = process.cwd(),\n): string[] {\n const allFiles: string[] = []\n\n for (const pkg of packages) {\n // Build glob patterns for this package\n const patterns = [`${pkg}/**/*`]\n\n // Use tinyglobby to find files (sync version)\n const files = globSync(patterns, {\n cwd: baseDir,\n ignore,\n onlyFiles: true,\n dot: true, // Include dotfiles\n absolute: false, // Return relative paths\n })\n\n allFiles.push(...files)\n }\n\n return allFiles\n}\n","/**\n * Attestation file I/O module with JSON canonicalization.\n */\n\nimport * as fs from 'node:fs'\nimport * as os from 'node:os'\nimport * as path from 'node:path'\nimport * as canonicalizeNamespace from 'canonicalize'\nimport { z } from 'zod'\nimport type { Attestation, AttestationsFile } from './types.js'\n\n/**\n * Extract the serialize function from the canonicalize CommonJS module.\n *\n * Context: The canonicalize package uses `module.exports = function(...)`, which is\n * a CommonJS pattern. With `esModuleInterop: false` (required for library code to\n * avoid leaking tsconfig options to consumers), TypeScript treats the namespace import\n * as the module object itself, not as an object with a default export.\n *\n * The package's type definitions declare `export default function serialize(...)`,\n * which TypeScript interprets as `{ default: function }` when esModuleInterop is off.\n * However, at runtime with NodeNext module resolution, the actual value is just the\n * function itself.\n *\n * This type assertion is safe because:\n * 1. We verified the runtime export structure of the canonicalize module\n * 2. The type matches the published @types signature\n * 3. This is the standard pattern for importing CommonJS modules in strict ESM\n */\n// eslint-disable-next-line @typescript-eslint/consistent-type-assertions\nconst canonicalize = canonicalizeNamespace as unknown as {\n default: (input: unknown) => string | undefined\n}\nconst serialize = canonicalize.default\n\n// Zod schema for attestation validation\nconst attestationSchema = z.object({\n suite: z.string().min(1),\n fingerprint: z.string().regex(/^sha256:[a-f0-9]{64}$/),\n attestedAt: z.string().datetime(),\n attestedBy: z.string().min(1),\n command: z.string().min(1),\n exitCode: z.literal(0),\n})\n\nconst attestationsFileSchema = z.object({\n schemaVersion: z.literal('1'),\n attestations: z.array(attestationSchema),\n signature: z.string(), // Will be validated by crypto module\n})\n\n/**\n * Type guard to check if an error is a Node.js file system error with code.\n * We need to disable the type assertion rule here because TypeScript doesn't\n * provide a way to narrow an object type after checking for a property without\n * using type assertions or indexed access. This is a safe assertion because we\n * check for the property existence and type before using it.\n */\nfunction isNodeError(error: unknown): error is NodeJS.ErrnoException {\n if (error === null || typeof error !== 'object') {\n return false\n }\n if (!('code' in error)) {\n return false\n }\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n const errorObj = error as Record<string, unknown>\n return typeof errorObj.code === 'string'\n}\n\n/**\n * Read attestations file from disk (async).\n *\n * @param filePath - Absolute path to the attestations JSON file\n * @returns Parsed attestations file, or null if the file doesn't exist\n * @throws Error on parse or validation errors\n * @public\n */\nexport async function readAttestations(filePath: string): Promise<AttestationsFile | null> {\n try {\n const content = await fs.promises.readFile(filePath, 'utf-8')\n const parsed: unknown = JSON.parse(content)\n // Zod validates and returns the correct type\n return attestationsFileSchema.parse(parsed)\n } catch (error) {\n if (isNodeError(error) && error.code === 'ENOENT') {\n return null\n }\n throw error\n }\n}\n\n/**\n * Read attestations file from disk (sync).\n *\n * @param filePath - Absolute path to the attestations JSON file\n * @returns Parsed attestations file, or null if the file doesn't exist\n * @throws Error on parse or validation errors\n * @public\n */\nexport function readAttestationsSync(filePath: string): AttestationsFile | null {\n try {\n const content = fs.readFileSync(filePath, 'utf-8')\n const parsed: unknown = JSON.parse(content)\n // Zod validates and returns the correct type\n return attestationsFileSchema.parse(parsed)\n } catch (error) {\n if (isNodeError(error) && error.code === 'ENOENT') {\n return null\n }\n throw error\n }\n}\n\n/**\n * Write attestations file to disk (async).\n *\n * Creates parent directories if needed. The signature should be computed\n * separately and passed in.\n *\n * @param filePath - Absolute path to write the attestations file\n * @param attestations - Array of attestation entries\n * @param signature - Cryptographic signature of the attestations\n * @throws Error on validation or write errors\n * @public\n */\nexport async function writeAttestations(\n filePath: string,\n attestations: Attestation[],\n signature: string,\n): Promise<void> {\n const fileContent: AttestationsFile = {\n schemaVersion: '1',\n attestations,\n signature,\n }\n\n // Validate before writing\n attestationsFileSchema.parse(fileContent)\n\n // Create parent directories if needed\n const dir = path.dirname(filePath)\n await fs.promises.mkdir(dir, { recursive: true })\n\n // Write with pretty formatting for readability\n const json = JSON.stringify(fileContent, null, 2)\n await fs.promises.writeFile(filePath, json, 'utf-8')\n}\n\n/**\n * Write attestations file to disk (sync).\n *\n * Creates parent directories if needed. The signature should be computed\n * separately and passed in.\n *\n * @param filePath - Absolute path to write the attestations file\n * @param attestations - Array of attestation entries\n * @param signature - Cryptographic signature of the attestations\n * @throws Error on validation or write errors\n * @public\n */\nexport function writeAttestationsSync(\n filePath: string,\n attestations: Attestation[],\n signature: string,\n): void {\n const fileContent: AttestationsFile = {\n schemaVersion: '1',\n attestations,\n signature,\n }\n\n // Validate before writing\n attestationsFileSchema.parse(fileContent)\n\n // Create parent directories if needed\n const dir = path.dirname(filePath)\n fs.mkdirSync(dir, { recursive: true })\n\n // Write with pretty formatting for readability\n const json = JSON.stringify(fileContent, null, 2)\n fs.writeFileSync(filePath, json, 'utf-8')\n}\n\n/**\n * Find an attestation for a specific suite.\n *\n * @param attestations - Attestations file containing all attestations\n * @param suite - Name of the suite to find\n * @returns The attestation if found, undefined otherwise\n * @public\n */\nexport function findAttestation(\n attestations: AttestationsFile,\n suite: string,\n): Attestation | undefined {\n return attestations.attestations.find((a) => a.suite === suite)\n}\n\n/**\n * Add or update an attestation for a suite.\n *\n * This is an immutable operation that returns a new array.\n *\n * @param attestations - Current array of attestations\n * @param newAttestation - Attestation to add or update\n * @returns New attestations array with the upserted attestation\n * @throws Error if the new attestation fails validation\n * @public\n */\nexport function upsertAttestation(\n attestations: Attestation[],\n newAttestation: Attestation,\n): Attestation[] {\n // Validate the new attestation\n attestationSchema.parse(newAttestation)\n\n const existingIndex = attestations.findIndex((a) => a.suite === newAttestation.suite)\n\n if (existingIndex === -1) {\n // Add new attestation\n return [...attestations, newAttestation]\n } else {\n // Update existing attestation\n const updated = [...attestations]\n // eslint-disable-next-line security/detect-object-injection -- False positive: existingIndex is a safe number from findIndex\n updated[existingIndex] = newAttestation\n return updated\n }\n}\n\n/**\n * Remove attestations for a suite.\n *\n * This is an immutable operation that returns a new array.\n *\n * @param attestations - Current array of attestations\n * @param suite - Name of the suite to remove\n * @returns New attestations array without the specified suite\n * @public\n */\nexport function removeAttestation(attestations: Attestation[], suite: string): Attestation[] {\n return attestations.filter((a) => a.suite !== suite)\n}\n\n/**\n * Compute canonical JSON representation for signing.\n *\n * Implements RFC 8785 JSON Canonicalization Scheme. The canonicalize package provides:\n * 1. Keys sorted lexicographically (Unicode code point order)\n * 2. No whitespace between tokens\n * 3. No trailing commas\n * 4. Strings escaped using \\uXXXX for control characters\n * 5. Numbers: no leading zeros, no +, use lowercase 'e' for exponent\n * 6. UTF-8 encoding\n *\n * @param attestations - Array of attestations to canonicalize\n * @returns Canonical JSON string representation\n * @throws Error if canonicalization fails\n * @public\n */\nexport function canonicalizeAttestations(attestations: Attestation[]): string {\n const canonical = serialize(attestations)\n if (canonical === undefined) {\n throw new Error('Failed to canonicalize attestations')\n }\n return canonical\n}\n\n/**\n * Create a new attestation entry.\n *\n * @param params - Parameters for creating the attestation\n * @param params.suite - Name of the test suite\n * @param params.fingerprint - Fingerprint of the packages in sha256 format\n * @param params.command - Command that was executed\n * @param params.attestedBy - Optional username (defaults to current OS user)\n * @returns Validated attestation object\n * @throws Error if attestation validation fails\n * @public\n */\nexport function createAttestation(params: {\n suite: string\n fingerprint: string\n command: string\n attestedBy?: string\n}): Attestation {\n const attestation: Attestation = {\n suite: params.suite,\n fingerprint: params.fingerprint,\n attestedAt: new Date().toISOString(),\n attestedBy: params.attestedBy ?? os.userInfo().username,\n command: params.command,\n exitCode: 0,\n }\n\n // Validate before returning\n attestationSchema.parse(attestation)\n\n return attestation\n}\n\n/**\n * Options for writing signed attestations.\n * @public\n */\nexport interface WriteSignedAttestationsOptions {\n /** Path to write the attestations file */\n filePath: string\n /** Array of attestations to write */\n attestations: Attestation[]\n /** Path to the private key for signing */\n privateKeyPath: string\n}\n\n/**\n * Options for reading and verifying signed attestations.\n * @public\n */\nexport interface ReadSignedAttestationsOptions {\n /** Path to read the attestations file from */\n filePath: string\n /** Path to the public key for verification */\n publicKeyPath: string\n}\n\n/**\n * Write attestations with a cryptographic signature.\n *\n * This function canonicalizes the attestations, signs them with the private key,\n * and writes the attestations file with the signature.\n *\n * @param options - Options for writing signed attestations\n * @throws Error if signing or writing fails\n * @public\n */\nexport async function writeSignedAttestations(\n options: WriteSignedAttestationsOptions,\n): Promise<void> {\n // Import sign function here to avoid circular dependency\n const { sign } = await import('./crypto.js')\n\n const canonical = canonicalizeAttestations(options.attestations)\n const signature = await sign({\n privateKeyPath: options.privateKeyPath,\n data: canonical,\n })\n await writeAttestations(options.filePath, options.attestations, signature)\n}\n\n/**\n * Read attestations and verify the signature.\n *\n * This function reads the attestations file, canonicalizes the attestations,\n * and verifies the signature using the public key. It throws an error if the\n * file doesn't exist or if signature verification fails.\n *\n * @param options - Options for reading and verifying attestations\n * @returns The attestations file if signature is valid\n * @throws Error if attestations file not found\n * @throws SignatureInvalidError if signature verification fails\n * @public\n */\nexport async function readAndVerifyAttestations(\n options: ReadSignedAttestationsOptions,\n): Promise<AttestationsFile> {\n // Import verify function here to avoid circular dependency\n const { verify } = await import('./crypto.js')\n\n const file = await readAttestations(options.filePath)\n if (!file) {\n throw new Error(`Attestations file not found: ${options.filePath}`)\n }\n\n const canonical = canonicalizeAttestations(file.attestations)\n const isValid = await verify({\n publicKeyPath: options.publicKeyPath,\n data: canonical,\n signature: file.signature,\n })\n\n if (!isValid) {\n throw new SignatureInvalidError(options.filePath)\n }\n\n return file\n}\n\n/**\n * Error thrown when signature verification fails.\n * @public\n */\nexport class SignatureInvalidError extends Error {\n /**\n * Create a new SignatureInvalidError.\n * @param filePath - Path to the file that failed verification\n */\n constructor(filePath: string) {\n super(`Signature verification failed for: ${filePath}`)\n this.name = 'SignatureInvalidError'\n }\n}\n","/**\n * @attest-it/core\n *\n * Core functionality for the attest-it testing framework.\n * @packageDocumentation\n */\n\n/**\n * Package version\n * @public\n */\nexport const version = '0.0.0'\n\n// Types\nexport type {\n AttestItSettings,\n SuiteConfig,\n AttestItConfig,\n Attestation,\n AttestationsFile,\n VerificationStatus,\n SuiteVerificationResult,\n} from './types.js'\n\n// Config\nexport {\n loadConfig,\n loadConfigSync,\n findConfigPath,\n resolveConfigPaths,\n toAttestItConfig,\n ConfigValidationError,\n ConfigNotFoundError,\n type Config,\n} from './config.js'\n\n// Fingerprinting\nexport { computeFingerprint, computeFingerprintSync, listPackageFiles } from './fingerprint.js'\nexport type { FingerprintOptions, FingerprintResult } from './fingerprint.js'\n\n// Attestations\nexport {\n readAttestations,\n readAttestationsSync,\n writeAttestations,\n writeAttestationsSync,\n findAttestation,\n upsertAttestation,\n removeAttestation,\n canonicalizeAttestations,\n createAttestation,\n writeSignedAttestations,\n readAndVerifyAttestations,\n SignatureInvalidError,\n} from './attestation.js'\nexport type {\n WriteSignedAttestationsOptions,\n ReadSignedAttestationsOptions,\n} from './attestation.js'\n\n// Cryptography\nexport {\n checkOpenSSL,\n getDefaultPrivateKeyPath,\n getDefaultPublicKeyPath,\n generateKeyPair,\n sign,\n verify,\n setKeyPermissions,\n} from './crypto.js'\nexport type {\n KeyPaths,\n KeygenOptions,\n SignOptions,\n VerifyOptions as CryptoVerifyOptions,\n} from './crypto.js'\n\n// Verification\nexport { verifyAttestations } from './verify.js'\nexport type { VerifyOptions, VerifyResult } from './verify.js'\n","/**\n * Verification logic for attestations.\n * @packageDocumentation\n */\n\nimport * as fs from 'node:fs'\nimport * as path from 'node:path'\nimport type {\n AttestItConfig,\n Attestation,\n AttestationsFile,\n SuiteVerificationResult,\n} from './types.js'\nimport { computeFingerprint } from './fingerprint.js'\nimport { readAndVerifyAttestations, SignatureInvalidError } from './attestation.js'\n\n/**\n * Options for verifying attestations.\n * @public\n */\nexport interface VerifyOptions {\n /** Configuration object */\n config: AttestItConfig\n /** Repository root directory (defaults to process.cwd()) */\n repoRoot?: string\n}\n\n/**\n * Result of verifying all attestations.\n * @public\n */\nexport interface VerifyResult {\n /** Overall success - true if all attestations are valid */\n success: boolean\n /** Whether the attestations file signature is valid */\n signatureValid: boolean\n /** Verification results for each suite */\n suites: SuiteVerificationResult[]\n /** Error messages encountered during verification */\n errors: string[]\n}\n\n/**\n * Verify all attestations against current code state.\n *\n * Verification algorithm:\n * 1. Load and verify attestations file signature\n * 2. For each suite in config:\n * a. Compute current fingerprint\n * b. Find matching attestation\n * c. Compare fingerprints\n * d. Check age\n * 3. Check invalidation chains\n * 4. Return aggregated results\n *\n * @param options - Verification options\n * @returns Verification result with status for each suite\n * @public\n */\nexport async function verifyAttestations(options: VerifyOptions): Promise<VerifyResult> {\n const { config, repoRoot = process.cwd() } = options\n const errors: string[] = []\n const suiteResults: SuiteVerificationResult[] = []\n let signatureValid = true\n let attestationsFile: AttestationsFile | null = null\n\n // Resolve paths\n const attestationsPath = resolvePath(config.settings.attestationsPath, repoRoot)\n const publicKeyPath = resolvePath(config.settings.publicKeyPath, repoRoot)\n\n // Step 1: Load and verify attestations\n try {\n if (!fs.existsSync(attestationsPath)) {\n // No attestations file - all suites need attestation\n attestationsFile = null\n } else if (!fs.existsSync(publicKeyPath)) {\n errors.push(`Public key not found: ${publicKeyPath}`)\n signatureValid = false\n } else {\n attestationsFile = await readAndVerifyAttestations({\n filePath: attestationsPath,\n publicKeyPath,\n })\n }\n } catch (err) {\n if (err instanceof SignatureInvalidError) {\n signatureValid = false\n errors.push(err.message)\n } else if (err instanceof Error) {\n errors.push(err.message)\n }\n }\n\n const attestations = attestationsFile?.attestations ?? []\n\n // Step 2: Check each suite\n for (const [suiteName, suiteConfig] of Object.entries(config.suites)) {\n const result = await verifySuite({\n suiteName,\n suiteConfig,\n attestations,\n maxAgeDays: config.settings.maxAgeDays,\n repoRoot,\n })\n suiteResults.push(result)\n }\n\n // Step 3: Check invalidation chains\n checkInvalidationChains(config, suiteResults)\n\n // Step 4: Aggregate results\n const allValid =\n signatureValid && suiteResults.every((r) => r.status === 'VALID') && errors.length === 0\n\n return {\n success: allValid,\n signatureValid,\n suites: suiteResults,\n errors,\n }\n}\n\n/**\n * Options for verifying a single suite.\n * @internal\n */\ninterface VerifySuiteOptions {\n /** Name of the suite */\n suiteName: string\n /** Suite configuration */\n suiteConfig: { packages: string[]; ignore?: string[] }\n /** All attestations from the attestations file */\n attestations: Attestation[]\n /** Maximum age in days before attestation expires */\n maxAgeDays: number\n /** Repository root directory */\n repoRoot: string\n}\n\n/**\n * Verify a single suite's attestation.\n * @internal\n */\nasync function verifySuite(options: VerifySuiteOptions): Promise<SuiteVerificationResult> {\n const { suiteName, suiteConfig, attestations, maxAgeDays, repoRoot } = options\n\n // Compute current fingerprint\n const fingerprintOptions = {\n packages: suiteConfig.packages.map((p) => resolvePath(p, repoRoot)),\n baseDir: repoRoot,\n ...(suiteConfig.ignore && { ignore: suiteConfig.ignore }),\n }\n const fingerprintResult = await computeFingerprint(fingerprintOptions)\n\n // Find attestation for this suite\n const attestation = attestations.find((a) => a.suite === suiteName)\n\n // No attestation found\n if (!attestation) {\n return {\n suite: suiteName,\n status: 'NEEDS_ATTESTATION',\n fingerprint: fingerprintResult.fingerprint,\n message: 'No attestation found for this suite',\n }\n }\n\n // Check fingerprint\n if (attestation.fingerprint !== fingerprintResult.fingerprint) {\n return {\n suite: suiteName,\n status: 'FINGERPRINT_CHANGED',\n fingerprint: fingerprintResult.fingerprint,\n attestation,\n message: `Fingerprint changed from ${attestation.fingerprint.slice(0, 20)}... to ${fingerprintResult.fingerprint.slice(0, 20)}...`,\n }\n }\n\n // Check age\n const attestedAt = new Date(attestation.attestedAt)\n const ageMs = Date.now() - attestedAt.getTime()\n const ageDays = Math.floor(ageMs / (1000 * 60 * 60 * 24))\n\n if (ageDays > maxAgeDays) {\n return {\n suite: suiteName,\n status: 'EXPIRED',\n fingerprint: fingerprintResult.fingerprint,\n attestation,\n age: ageDays,\n message: `Attestation expired (${String(ageDays)} days old, max ${String(maxAgeDays)} days)`,\n }\n }\n\n // All checks passed\n return {\n suite: suiteName,\n status: 'VALID',\n fingerprint: fingerprintResult.fingerprint,\n attestation,\n age: ageDays,\n }\n}\n\n/**\n * Check invalidation chains.\n *\n * If suite A invalidates suite B, and A's attestation is newer than B's,\n * then B should be marked as INVALIDATED_BY_PARENT.\n *\n * @param config - Full configuration\n * @param results - Array of suite verification results to mutate\n * @internal\n */\nfunction checkInvalidationChains(config: AttestItConfig, results: SuiteVerificationResult[]): void {\n for (const [parentName, parentConfig] of Object.entries(config.suites)) {\n const invalidates = parentConfig.invalidates ?? []\n const parentResult = results.find((r) => r.suite === parentName)\n\n if (!parentResult?.attestation) continue\n\n const parentTime = new Date(parentResult.attestation.attestedAt).getTime()\n\n for (const childName of invalidates) {\n const childResult = results.find((r) => r.suite === childName)\n if (!childResult?.attestation) continue\n\n const childTime = new Date(childResult.attestation.attestedAt).getTime()\n\n // If parent was attested AFTER child, child is invalidated\n if (parentTime > childTime && childResult.status === 'VALID') {\n childResult.status = 'INVALIDATED_BY_PARENT'\n childResult.message = `Invalidated by ${parentName} (attested later)`\n }\n }\n }\n}\n\n/**\n * Resolve a path relative to a base directory.\n * @param relativePath - Path that may be relative or absolute\n * @param baseDir - Base directory for resolving relative paths\n * @returns Absolute path\n * @internal\n */\nfunction resolvePath(relativePath: string, baseDir: string): string {\n if (path.isAbsolute(relativePath)) {\n return relativePath\n }\n return path.join(baseDir, relativePath)\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/crypto.ts","../src/config.ts","../src/fingerprint.ts","../src/attestation.ts","../src/index.ts","../src/crypto/ed25519.ts","../src/verify.ts","../src/key-provider/filesystem-provider.ts","../src/key-provider/one-password-provider.ts","../src/key-provider/macos-keychain-provider.ts","../src/key-provider/registry.ts","../src/identity/config.ts","../src/authorization.ts","../src/seal/operations.ts","../src/seal/verification.ts"],"names":["resolve","spawn","os","path2","fs2","z","ms","parseYaml","join","readFileSync","readFile","path","crypto","hash","fs","glob","globSync","canonicalizeNamespace","fs3","path3","os2","sign","verify","generateKeyPair","crypto2","fs4","path4","fs5","fs6","path5","os3","execCommand","fs7","path6","os4","homedir","stringifyYaml","dirname","mkdirAsync","writeFile","mkdirSync","writeFileSync","path7","fs8"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Cryptographic utilities for key generation, signing, and verification.\n *\n * @remarks\n * This module provides cryptographic operations using OpenSSL for key management\n * and signature verification. It uses RSA-2048 with SHA-256 for signatures,\n * which is universally supported across all OpenSSL and LibreSSL versions.\n *\n * @packageDocumentation\n */\n\nimport { spawn } from 'node:child_process'\nimport * as fs from 'node:fs/promises'\nimport * as path from 'node:path'\nimport * as os from 'node:os'\n\n/**\n * Paths to a generated keypair.\n * @public\n */\nexport interface KeyPaths {\n /** Path to the private key file */\n privatePath: string\n /** Path to the public key file */\n publicPath: string\n}\n\n/**\n * Options for key generation.\n * @public\n */\nexport interface KeygenOptions {\n /** Path for private key (default: OS-specific config dir) */\n privatePath?: string\n /** Path for public key (default: repo root) */\n publicPath?: string\n /** Overwrite existing keys (default: false) */\n force?: boolean\n}\n\n/**\n * Options for signing data.\n * @public\n */\nexport interface SignOptions {\n /** Path to the private key file (legacy) */\n privateKeyPath?: string\n /** Key provider to use for retrieving the private key */\n keyProvider?: import('./key-provider/types.js').KeyProvider\n /** Key reference for the provider */\n keyRef?: string\n /** Data to sign (string or Buffer) */\n data: string | Buffer\n}\n\n/**\n * Options for verifying signatures.\n * @public\n */\nexport interface VerifyOptions {\n /** Path to the public key file */\n publicKeyPath: string\n /** Original data that was signed */\n data: string | Buffer\n /** Base64-encoded signature to verify */\n signature: string\n}\n\n/**\n * Result from spawning an OpenSSL process.\n * @internal\n */\ninterface SpawnResult {\n /** Process exit code */\n exitCode: number\n /** Standard output as Buffer */\n stdout: Buffer\n /** Standard error as string */\n stderr: string\n}\n\n/**\n * Run OpenSSL with the given arguments.\n * @param args - Command-line arguments for OpenSSL\n * @param stdin - Optional data to write to stdin\n * @returns Process result with exit code and outputs\n * @internal\n */\nasync function runOpenSSL(args: string[], stdin?: Buffer): Promise<SpawnResult> {\n return new Promise((resolve, reject) => {\n const child = spawn('openssl', args, {\n stdio: ['pipe', 'pipe', 'pipe'],\n })\n\n const stdoutChunks: Buffer[] = []\n let stderr = ''\n\n child.stdout.on('data', (chunk: Buffer) => {\n stdoutChunks.push(chunk)\n })\n\n child.stderr.on('data', (chunk: Buffer) => {\n stderr += chunk.toString()\n })\n\n child.on('error', (err) => {\n reject(new Error(`Failed to spawn OpenSSL: ${err.message}`))\n })\n\n child.on('close', (code) => {\n resolve({\n exitCode: code ?? 1,\n stdout: Buffer.concat(stdoutChunks),\n stderr,\n })\n })\n\n if (stdin) {\n child.stdin.write(stdin)\n }\n child.stdin.end()\n })\n}\n\n/**\n * Check if OpenSSL is available and get version info.\n * @returns OpenSSL version string\n * @throws Error if OpenSSL is not available\n * @public\n */\nexport async function checkOpenSSL(): Promise<string> {\n const result = await runOpenSSL(['version'])\n\n if (result.exitCode !== 0) {\n throw new Error(`OpenSSL check failed: ${result.stderr}`)\n }\n\n return result.stdout.toString().trim()\n}\n\n/**\n * Cached result of OpenSSL availability check.\n * @internal\n */\nlet openSSLChecked = false\n\n/**\n * Ensure OpenSSL is available before performing cryptographic operations.\n * @throws Error with installation instructions if OpenSSL is not available\n * @internal\n */\nasync function ensureOpenSSLAvailable(): Promise<void> {\n if (openSSLChecked) {\n return\n }\n\n try {\n await checkOpenSSL()\n openSSLChecked = true\n } catch {\n throw new Error(\n 'OpenSSL is not installed or not in PATH. ' +\n 'Please install OpenSSL to use attest-it. ' +\n 'On macOS: brew install openssl. ' +\n 'On Ubuntu: apt-get install openssl',\n )\n }\n}\n\n/**\n * Get the default private key path based on OS.\n * - macOS/Linux: ~/.config/attest-it/private.pem\n * - Windows: %APPDATA%\\attest-it\\private.pem\n * @public\n */\nexport function getDefaultPrivateKeyPath(): string {\n const homeDir = os.homedir()\n\n if (process.platform === 'win32') {\n const appData = process.env.APPDATA ?? path.join(homeDir, 'AppData', 'Roaming')\n return path.join(appData, 'attest-it', 'private.pem')\n }\n\n return path.join(homeDir, '.config', 'attest-it', 'private.pem')\n}\n\n/**\n * Get the default public key path (in repo).\n * @public\n */\nexport function getDefaultPublicKeyPath(): string {\n return path.join(process.cwd(), 'attest-it-public.pem')\n}\n\n/**\n * Ensure a directory exists, creating it and parent directories if needed.\n * @param dirPath - Directory path to create\n * @internal\n */\nasync function ensureDir(dirPath: string): Promise<void> {\n try {\n await fs.mkdir(dirPath, { recursive: true })\n } catch (err) {\n if (err instanceof Error && 'code' in err && err.code !== 'EEXIST') {\n throw err\n }\n }\n}\n\n/**\n * Check if a file exists.\n * @param filePath - File path to check\n * @returns true if file exists\n * @internal\n */\nasync function fileExists(filePath: string): Promise<boolean> {\n try {\n await fs.access(filePath)\n return true\n } catch {\n return false\n }\n}\n\n/**\n * Clean up one or more files, ignoring errors if files don't exist.\n * @param paths - File paths to delete\n * @internal\n */\nasync function cleanupFiles(...paths: string[]): Promise<void> {\n for (const filePath of paths) {\n try {\n await fs.unlink(filePath)\n } catch {\n // Ignore cleanup errors - file may not exist\n }\n }\n}\n\n/**\n * Generate a new RSA-2048 keypair using OpenSSL.\n *\n * RSA-2048 with SHA-256 is used because it's universally supported across\n * all OpenSSL and LibreSSL versions, including older macOS systems.\n *\n * @param options - Generation options\n * @returns Paths to generated keys\n * @throws Error if OpenSSL fails or keys exist without force\n * @public\n */\nexport async function generateKeyPair(options: KeygenOptions = {}): Promise<KeyPaths> {\n // Ensure OpenSSL is available before proceeding\n await ensureOpenSSLAvailable()\n\n const {\n privatePath = getDefaultPrivateKeyPath(),\n publicPath = getDefaultPublicKeyPath(),\n force = false,\n } = options\n\n // Check if keys already exist\n const privateExists = await fileExists(privatePath)\n const publicExists = await fileExists(publicPath)\n\n if ((privateExists || publicExists) && !force) {\n const existing = [privateExists ? privatePath : null, publicExists ? publicPath : null].filter(\n Boolean,\n )\n throw new Error(\n `Key files already exist: ${existing.join(', ')}. Use force: true to overwrite.`,\n )\n }\n\n // Ensure parent directories exist\n await ensureDir(path.dirname(privatePath))\n await ensureDir(path.dirname(publicPath))\n\n try {\n // Generate RSA-2048 private key\n const genArgs = [\n 'genpkey',\n '-algorithm',\n 'RSA',\n '-pkeyopt',\n 'rsa_keygen_bits:2048',\n '-out',\n privatePath,\n ]\n\n const genResult = await runOpenSSL(genArgs)\n if (genResult.exitCode !== 0) {\n throw new Error(`Failed to generate private key: ${genResult.stderr}`)\n }\n\n // Set restrictive permissions on private key\n await setKeyPermissions(privatePath)\n\n // Extract public key\n const pubResult = await runOpenSSL(['pkey', '-in', privatePath, '-pubout', '-out', publicPath])\n\n if (pubResult.exitCode !== 0) {\n throw new Error(`Failed to extract public key: ${pubResult.stderr}`)\n }\n\n return {\n privatePath,\n publicPath,\n }\n } catch (err) {\n // Clean up both key files on any failure\n await cleanupFiles(privatePath, publicPath)\n throw err\n }\n}\n\n/**\n * Sign data using an RSA private key with SHA-256.\n *\n * Uses `openssl dgst -sha256 -sign` which is universally supported across\n * all OpenSSL and LibreSSL versions.\n *\n * @param options - Signing options\n * @returns Base64-encoded signature\n * @throws Error if signing fails\n * @public\n */\nexport async function sign(options: SignOptions): Promise<string> {\n // Ensure OpenSSL is available before proceeding\n await ensureOpenSSLAvailable()\n\n const { privateKeyPath, keyProvider, keyRef, data } = options\n\n // Determine which key path to use\n let effectiveKeyPath: string\n let cleanup: (() => Promise<void>) | undefined\n\n if (keyProvider && keyRef) {\n // Use key provider to retrieve the key\n const result = await keyProvider.getPrivateKey(keyRef)\n effectiveKeyPath = result.keyPath\n cleanup = result.cleanup\n } else if (privateKeyPath) {\n // Legacy path: use privateKeyPath directly\n effectiveKeyPath = privateKeyPath\n } else {\n throw new Error(\n 'Either privateKeyPath or both keyProvider and keyRef must be provided for signing',\n )\n }\n\n try {\n // Check if private key exists\n if (!(await fileExists(effectiveKeyPath))) {\n throw new Error(`Private key not found: ${effectiveKeyPath}`)\n }\n\n // Convert data to Buffer\n const dataBuffer = typeof data === 'string' ? Buffer.from(data, 'utf8') : data\n\n // OpenSSL dgst cannot handle empty files, so we need to add a single byte\n // for empty data and document this limitation\n const processBuffer = dataBuffer.length === 0 ? Buffer.from([0x00]) : dataBuffer\n\n // Create temporary directory with OS-level uniqueness guarantees\n // This prevents TOCTOU race conditions that Math.random() would allow\n const tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), 'attest-it-'))\n const dataFile = path.join(tmpDir, 'data.bin')\n const sigFile = path.join(tmpDir, 'sig.bin')\n\n try {\n // Write data to temp file\n await fs.writeFile(dataFile, processBuffer)\n\n // Sign using openssl dgst -sha256 (cross-platform compatible)\n const signArgs = ['dgst', '-sha256', '-sign', effectiveKeyPath, '-out', sigFile, dataFile]\n const result = await runOpenSSL(signArgs)\n\n if (result.exitCode !== 0) {\n throw new Error(`Failed to sign data: ${result.stderr}`)\n }\n\n // Read the signature\n const sigBuffer = await fs.readFile(sigFile)\n return sigBuffer.toString('base64')\n } finally {\n // Clean up temp directory and all files within it\n try {\n await fs.rm(tmpDir, { recursive: true, force: true })\n } catch {\n // Ignore cleanup errors - OS will eventually clean tmpdir\n }\n }\n } finally {\n // Always call cleanup function if provided\n if (cleanup) {\n await cleanup()\n }\n }\n}\n\n/**\n * Verify a signature using an RSA public key with SHA-256.\n *\n * Uses `openssl dgst -sha256 -verify` which is universally supported across\n * all OpenSSL and LibreSSL versions.\n *\n * @param options - Verification options\n * @returns true if signature is valid\n * @throws Error if verification fails (not just invalid signature)\n * @public\n */\nexport async function verify(options: VerifyOptions): Promise<boolean> {\n // Ensure OpenSSL is available before proceeding\n await ensureOpenSSLAvailable()\n\n const { publicKeyPath, data, signature } = options\n\n // Check if public key exists\n if (!(await fileExists(publicKeyPath))) {\n throw new Error(`Public key not found: ${publicKeyPath}`)\n }\n\n // Convert data to Buffer\n const dataBuffer = typeof data === 'string' ? Buffer.from(data, 'utf8') : data\n\n // OpenSSL dgst cannot handle empty files, so we use the same workaround\n // as in sign() - add a single byte for empty data\n const processBuffer = dataBuffer.length === 0 ? Buffer.from([0x00]) : dataBuffer\n\n // Decode signature from base64\n const sigBuffer = Buffer.from(signature, 'base64')\n\n // Create temporary directory with OS-level uniqueness guarantees\n // This prevents TOCTOU race conditions that Math.random() would allow\n const tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), 'attest-it-'))\n const dataFile = path.join(tmpDir, 'data.bin')\n const sigFile = path.join(tmpDir, 'sig.bin')\n\n try {\n // Write data and signature to temp files\n await fs.writeFile(dataFile, processBuffer)\n await fs.writeFile(sigFile, sigBuffer)\n\n // Verify using openssl dgst -sha256 (cross-platform compatible)\n const verifyArgs = [\n 'dgst',\n '-sha256',\n '-verify',\n publicKeyPath,\n '-signature',\n sigFile,\n dataFile,\n ]\n const result = await runOpenSSL(verifyArgs)\n\n // dgst -verify: Exit code 0 means valid, non-0 means invalid\n // Output contains \"Verified OK\" on success\n return result.exitCode === 0 && result.stdout.toString().includes('Verified OK')\n } finally {\n // Clean up temp directory and all files within it\n try {\n await fs.rm(tmpDir, { recursive: true, force: true })\n } catch {\n // Ignore cleanup errors - OS will eventually clean tmpdir\n }\n }\n}\n\n/**\n * Set restrictive permissions on a private key file.\n * @param keyPath - Path to the private key\n * @public\n */\nexport async function setKeyPermissions(keyPath: string): Promise<void> {\n // On Windows, use fs.chmod which has limited effect\n // On Unix, set to 0o600 (read/write for owner only)\n if (process.platform === 'win32') {\n // Windows doesn't support Unix-style permissions in the same way\n // But we still call chmod for consistency\n await fs.chmod(keyPath, 0o600)\n } else {\n await fs.chmod(keyPath, 0o600)\n }\n}\n","/**\n * Configuration loading and validation for attest-it.\n */\n\nimport { readFileSync } from 'node:fs'\nimport { readFile } from 'node:fs/promises'\nimport { join, resolve } from 'node:path'\nimport ms from 'ms'\nimport { parse as parseYaml } from 'yaml'\nimport { z } from 'zod'\n\n/**\n * Zod schema for key provider configuration.\n */\nconst keyProviderOptionsSchema = z\n .object({\n privateKeyPath: z.string().optional(),\n account: z.string().optional(),\n vault: z.string().optional(),\n itemName: z.string().optional(),\n })\n .strict()\n\nconst keyProviderSchema = z\n .object({\n type: z.enum(['filesystem', '1password']).or(z.string()),\n options: keyProviderOptionsSchema.optional(),\n })\n .strict()\n\n/**\n * Zod schema for a team member configuration.\n */\nconst teamMemberSchema = z\n .object({\n name: z.string().min(1, 'Team member name cannot be empty'),\n email: z.string().email().optional(),\n github: z.string().min(1).optional(),\n publicKey: z.string().min(1, 'Public key is required'),\n })\n .strict()\n\n/**\n * Zod schema for fingerprint configuration.\n */\nconst fingerprintConfigSchema = z\n .object({\n paths: z\n .array(z.string().min(1, 'Path cannot be empty'))\n .min(1, 'At least one path is required'),\n exclude: z.array(z.string().min(1, 'Exclude pattern cannot be empty')).optional(),\n })\n .strict()\n\n/**\n * Zod schema for duration strings.\n * Validates and parses duration strings like \"30d\", \"7d\", \"24h\".\n */\nconst durationSchema = z.string().refine(\n (val) => {\n try {\n // Type assertion needed because ms has strict StringValue type\n // We validate the result is a positive number below\n // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-argument, @typescript-eslint/consistent-type-assertions\n const parsed = ms(val as any)\n return typeof parsed === 'number' && parsed > 0\n } catch {\n return false\n }\n },\n {\n message: 'Duration must be a valid duration string (e.g., \"30d\", \"7d\", \"24h\")',\n },\n)\n\n/**\n * Zod schema for a gate configuration.\n */\nconst gateSchema = z\n .object({\n name: z.string().min(1, 'Gate name cannot be empty'),\n description: z.string().min(1, 'Gate description cannot be empty'),\n authorizedSigners: z\n .array(z.string().min(1, 'Authorized signer slug cannot be empty'))\n .min(1, 'At least one authorized signer is required'),\n fingerprint: fingerprintConfigSchema,\n maxAge: durationSchema,\n })\n .strict()\n\n/**\n * Zod schema for settings with defaults applied.\n */\nconst settingsSchema = z\n .object({\n maxAgeDays: z.number().int().positive().default(30),\n publicKeyPath: z.string().default('.attest-it/pubkey.pem'),\n attestationsPath: z.string().default('.attest-it/attestations.json'),\n defaultCommand: z.string().optional(),\n keyProvider: keyProviderSchema.optional(),\n // Note: algorithm field was removed - RSA is the only supported algorithm\n })\n .passthrough()\n\n/**\n * Zod schema for a suite configuration.\n * Suites are CLI-layer extensions of gates with command execution capabilities.\n * For backward compatibility, suites can define their own fingerprint via packages/files/ignore.\n */\nconst suiteSchema = z\n .object({\n // Gate fields (if present, this suite references a gate)\n gate: z.string().optional(),\n // Legacy fingerprint definition (for backward compatibility)\n description: z.string().optional(),\n packages: z.array(z.string().min(1, 'Package path cannot be empty')).optional(),\n files: z.array(z.string().min(1, 'File path cannot be empty')).optional(),\n ignore: z.array(z.string().min(1, 'Ignore pattern cannot be empty')).optional(),\n // CLI-specific fields\n command: z.string().optional(),\n timeout: z.string().optional(),\n interactive: z.boolean().optional(),\n // Relationship fields\n invalidates: z.array(z.string().min(1, 'Invalidated suite name cannot be empty')).optional(),\n depends_on: z.array(z.string().min(1, 'Dependency suite name cannot be empty')).optional(),\n })\n .strict()\n .refine(\n (suite) => {\n // Either gate is specified, or packages is specified (for legacy compatibility)\n return suite.gate !== undefined || (suite.packages !== undefined && suite.packages.length > 0)\n },\n {\n message: 'Suite must either reference a gate or define packages for fingerprinting',\n },\n )\n\n/**\n * Zod schema for the full configuration file.\n */\nconst configSchema = z\n .object({\n version: z.literal(1),\n settings: settingsSchema.default({}),\n team: z.record(z.string(), teamMemberSchema).optional(),\n gates: z.record(z.string(), gateSchema).optional(),\n suites: z.record(z.string(), suiteSchema).refine((suites) => Object.keys(suites).length >= 1, {\n message: 'At least one suite must be defined',\n }),\n groups: z\n .record(z.string(), z.array(z.string().min(1, 'Suite name in group cannot be empty')))\n .optional(),\n })\n .strict()\n\n/**\n * Type inference from Zod schema (should match AttestItConfig).\n * This is the same as AttestItConfig but with defaults applied.\n * @public\n */\nexport type Config = z.infer<typeof configSchema>\n\n/**\n * Error thrown when configuration is invalid.\n * @public\n */\nexport class ConfigValidationError extends Error {\n constructor(\n message: string,\n public readonly issues: z.ZodIssue[],\n ) {\n super(message)\n this.name = 'ConfigValidationError'\n }\n}\n\n/**\n * Error thrown when configuration file cannot be found.\n * @public\n */\nexport class ConfigNotFoundError extends Error {\n constructor(message: string) {\n super(message)\n this.name = 'ConfigNotFoundError'\n }\n}\n\n/**\n * Parse configuration content from a string.\n *\n * @param content - The configuration file content\n * @param format - The format of the content ('yaml' or 'json')\n * @returns Parsed and validated configuration\n * @throws {ConfigValidationError} If validation fails\n */\nfunction parseConfigContent(content: string, format: 'yaml' | 'json'): Config {\n let rawConfig: unknown\n\n try {\n if (format === 'yaml') {\n rawConfig = parseYaml(content)\n } else {\n rawConfig = JSON.parse(content)\n }\n } catch (error) {\n throw new ConfigValidationError(\n `Failed to parse ${format.toUpperCase()}: ${error instanceof Error ? error.message : String(error)}`,\n [],\n )\n }\n\n const result = configSchema.safeParse(rawConfig)\n\n if (!result.success) {\n throw new ConfigValidationError(\n 'Configuration validation failed:\\n' +\n result.error.issues\n .map((issue) => ` - ${issue.path.join('.')}: ${issue.message}`)\n .join('\\n'),\n result.error.issues,\n )\n }\n\n return result.data\n}\n\n/**\n * Determine the format of a config file from its extension.\n *\n * @param filePath - Path to the config file\n * @returns 'yaml' or 'json'\n */\nfunction getConfigFormat(filePath: string): 'yaml' | 'json' {\n const ext = filePath.toLowerCase()\n if (ext.endsWith('.yaml') || ext.endsWith('.yml')) {\n return 'yaml'\n }\n if (ext.endsWith('.json')) {\n return 'json'\n }\n // Default to yaml for extensionless files\n return 'yaml'\n}\n\n/**\n * Find the configuration file in default locations.\n *\n * Searches in this order:\n * 1. .attest-it/config.yaml\n * 2. .attest-it/config.yml\n * 3. .attest-it/config.json\n *\n * @param startDir - Directory to start searching from (defaults to cwd)\n * @returns Absolute path to the config file, or null if not found\n * @public\n */\nexport function findConfigPath(startDir: string = process.cwd()): string | null {\n const configDir = join(startDir, '.attest-it')\n const candidates = ['config.yaml', 'config.yml', 'config.json']\n\n for (const candidate of candidates) {\n const configPath = join(configDir, candidate)\n try {\n readFileSync(configPath, 'utf8')\n return configPath\n } catch {\n // File doesn't exist or can't be read, try next candidate\n continue\n }\n }\n\n return null\n}\n\n/**\n * Load and validate configuration from a file (async).\n *\n * @param configPath - Optional path to config file. If not provided, searches default locations.\n * @returns Validated configuration object\n * @throws {@link ConfigNotFoundError} If config file cannot be found\n * @throws {@link ConfigValidationError} If validation fails\n * @public\n */\nexport async function loadConfig(configPath?: string): Promise<Config> {\n const resolvedPath = configPath ?? findConfigPath()\n\n if (!resolvedPath) {\n throw new ConfigNotFoundError(\n 'Configuration file not found. Expected .attest-it/config.yaml, .attest-it/config.yml, or .attest-it/config.json',\n )\n }\n\n try {\n const content = await readFile(resolvedPath, 'utf8')\n const format = getConfigFormat(resolvedPath)\n return parseConfigContent(content, format)\n } catch (error) {\n if (error instanceof ConfigValidationError) {\n throw error\n }\n throw new ConfigNotFoundError(\n `Failed to read configuration file at ${resolvedPath}: ${String(error)}`,\n )\n }\n}\n\n/**\n * Load and validate configuration from a file (sync).\n *\n * @param configPath - Optional path to config file. If not provided, searches default locations.\n * @returns Validated configuration object\n * @throws {@link ConfigNotFoundError} If config file cannot be found\n * @throws {@link ConfigValidationError} If validation fails\n * @public\n */\nexport function loadConfigSync(configPath?: string): Config {\n const resolvedPath = configPath ?? findConfigPath()\n\n if (!resolvedPath) {\n throw new ConfigNotFoundError(\n 'Configuration file not found. Expected .attest-it/config.yaml, .attest-it/config.yml, or .attest-it/config.json',\n )\n }\n\n try {\n const content = readFileSync(resolvedPath, 'utf8')\n const format = getConfigFormat(resolvedPath)\n return parseConfigContent(content, format)\n } catch (error) {\n if (error instanceof ConfigValidationError) {\n throw error\n }\n throw new ConfigNotFoundError(\n `Failed to read configuration file at ${resolvedPath}: ${String(error)}`,\n )\n }\n}\n\n/**\n * Resolve relative paths in the configuration against the repository root.\n *\n * This converts relative paths in settings.publicKeyPath and settings.attestationsPath\n * to absolute paths relative to the repository root.\n *\n * @param config - The configuration object\n * @param repoRoot - Absolute path to the repository root\n * @returns Configuration with resolved absolute paths\n * @public\n */\nexport function resolveConfigPaths(config: Config, repoRoot: string): Config {\n return {\n ...config,\n settings: {\n ...config.settings,\n publicKeyPath: resolve(repoRoot, config.settings.publicKeyPath),\n attestationsPath: resolve(repoRoot, config.settings.attestationsPath),\n },\n }\n}\n\n/**\n * Convert Zod-validated Config to AttestItConfig by removing undefined values.\n *\n * The Config type (from Zod) has optional fields as `T | undefined`,\n * while AttestItConfig has optional fields as `T?` (can be absent, not undefined).\n *\n * This adapter removes any undefined values to match the AttestItConfig interface\n * that the core functions expect.\n *\n * @param config - The Zod-validated configuration from loadConfig()\n * @returns Configuration compatible with AttestItConfig\n * @public\n */\nexport function toAttestItConfig(config: Config): import('./types.js').AttestItConfig {\n const result: import('./types.js').AttestItConfig = {\n version: config.version,\n settings: {\n maxAgeDays: config.settings.maxAgeDays,\n publicKeyPath: config.settings.publicKeyPath,\n attestationsPath: config.settings.attestationsPath,\n },\n suites: {},\n }\n\n // Add optional settings fields\n if (config.settings.defaultCommand !== undefined) {\n result.settings.defaultCommand = config.settings.defaultCommand\n }\n if (config.settings.keyProvider !== undefined) {\n result.settings.keyProvider = {\n type: config.settings.keyProvider.type,\n ...(config.settings.keyProvider.options !== undefined && {\n options: config.settings.keyProvider.options,\n }),\n }\n }\n\n // Add optional top-level fields\n if (config.team !== undefined) {\n result.team = config.team\n }\n if (config.gates !== undefined) {\n result.gates = config.gates\n }\n if (config.groups !== undefined) {\n result.groups = config.groups\n }\n\n // Map suites\n result.suites = Object.fromEntries(\n Object.entries(config.suites).map(([name, suite]) => {\n const mappedSuite: import('./types.js').SuiteConfig = {}\n\n if (suite.gate !== undefined) mappedSuite.gate = suite.gate\n if (suite.packages !== undefined) mappedSuite.packages = suite.packages\n if (suite.description !== undefined) mappedSuite.description = suite.description\n if (suite.files !== undefined) mappedSuite.files = suite.files\n if (suite.ignore !== undefined) mappedSuite.ignore = suite.ignore\n if (suite.command !== undefined) mappedSuite.command = suite.command\n if (suite.timeout !== undefined) mappedSuite.timeout = suite.timeout\n if (suite.interactive !== undefined) mappedSuite.interactive = suite.interactive\n if (suite.invalidates !== undefined) mappedSuite.invalidates = suite.invalidates\n if (suite.depends_on !== undefined) mappedSuite.depends_on = suite.depends_on\n\n return [name, mappedSuite]\n }),\n )\n\n return result\n}\n","import * as crypto from 'node:crypto'\nimport * as fs from 'node:fs'\nimport * as path from 'node:path'\nimport { glob, globSync } from 'tinyglobby'\n\n/**\n * Threshold for streaming large files instead of reading into memory.\n * Files larger than this will be hashed via streaming to avoid memory issues.\n */\nconst LARGE_FILE_THRESHOLD = 50 * 1024 * 1024 // 50MB\n\n/**\n * Options for computing a package fingerprint.\n * @public\n */\nexport interface FingerprintOptions {\n /** Package directories to include */\n packages: string[]\n /** Glob patterns to exclude from fingerprint */\n ignore?: string[]\n /** Base directory for resolving paths */\n baseDir?: string\n}\n\n/**\n * Result of computing a package fingerprint.\n * @public\n */\nexport interface FingerprintResult {\n /** The fingerprint in \"sha256:...\" format */\n fingerprint: string\n /** List of files included in fingerprint calculation */\n files: string[]\n /** Number of files processed */\n fileCount: number\n}\n\n/**\n * Internal representation of a file hash for fingerprint computation.\n */\ninterface FileHashInput {\n /** The normalized relative path of the file */\n relativePath: string\n /** The computed hash of the file content */\n hash: Buffer\n}\n\n/**\n * Sort files lexicographically (locale-independent).\n */\nfunction sortFiles(files: string[]): string[] {\n return [...files].sort((a, b) => {\n if (a < b) return -1\n if (a > b) return 1\n return 0\n })\n}\n\n/**\n * Normalize path separators to forward slashes.\n */\nfunction normalizePath(filePath: string): string {\n return filePath.split(path.sep).join('/')\n}\n\n/**\n * Compute final fingerprint from file hashes.\n */\nfunction computeFinalFingerprint(fileHashes: FileHashInput[]): string {\n // Sort by relative path\n const sorted = [...fileHashes].sort((a, b) => {\n if (a.relativePath < b.relativePath) return -1\n if (a.relativePath > b.relativePath) return 1\n return 0\n })\n\n // Concatenate all file hashes\n const hashes = sorted.map((input) => input.hash)\n const concatenated = Buffer.concat(hashes)\n\n // Compute final hash\n const finalHash = crypto.createHash('sha256').update(concatenated).digest()\n return `sha256:${finalHash.toString('hex')}`\n}\n\n/**\n * Hash a file's content using streaming for large files (async).\n * For files larger than LARGE_FILE_THRESHOLD, uses streaming to avoid memory issues.\n */\nasync function hashFileAsync(\n realPath: string,\n normalizedPath: string,\n stats: fs.Stats,\n): Promise<Buffer> {\n if (stats.size > LARGE_FILE_THRESHOLD) {\n // Stream large files to avoid memory issues\n return new Promise((resolve, reject) => {\n const hash = crypto.createHash('sha256')\n hash.update(normalizedPath)\n hash.update(':')\n\n const stream = fs.createReadStream(realPath)\n stream.on('data', (chunk: string | Buffer) => {\n hash.update(chunk)\n })\n stream.on('end', () => {\n resolve(hash.digest())\n })\n stream.on('error', reject)\n })\n }\n\n // Read small files into memory (faster than streaming)\n const content = await fs.promises.readFile(realPath)\n const hash = crypto.createHash('sha256')\n hash.update(normalizedPath)\n hash.update(':')\n hash.update(content)\n return hash.digest()\n}\n\n/**\n * Hash a file's content synchronously.\n * Note: Cannot stream synchronously, so large files are read into memory.\n */\nfunction hashFileSync(realPath: string, normalizedPath: string): Buffer {\n const content = fs.readFileSync(realPath)\n const hash = crypto.createHash('sha256')\n hash.update(normalizedPath)\n hash.update(':')\n hash.update(content)\n return hash.digest()\n}\n\n/**\n * Validate fingerprint options and return base directory.\n */\nfunction validateOptions(options: FingerprintOptions): string {\n if (options.packages.length === 0) {\n throw new Error('packages array must not be empty')\n }\n\n const baseDir = options.baseDir ?? process.cwd()\n\n // Verify all package paths exist\n for (const pkg of options.packages) {\n const pkgPath = path.resolve(baseDir, pkg)\n if (!fs.existsSync(pkgPath)) {\n throw new Error(`Package path does not exist: ${pkgPath}`)\n }\n }\n\n return baseDir\n}\n\n/**\n * Compute a deterministic fingerprint for a set of packages (async).\n *\n * Algorithm:\n * 1. List all files in packages (respecting ignore globs)\n * 2. Sort files lexicographically by relative path\n * 3. For each file: compute SHA256(relativePath + \":\" + content)\n * 4. Concatenate all file hashes in sorted order\n * 5. Compute final SHA256 of concatenated hashes\n * 6. Return \"sha256:\" + hex(fingerprint)\n *\n * @param options - Configuration for fingerprint computation\n * @returns Result containing the fingerprint hash and list of files processed\n * @throws Error if packages array is empty or if package paths don't exist\n * @public\n */\nexport async function computeFingerprint(options: FingerprintOptions): Promise<FingerprintResult> {\n const baseDir = validateOptions(options)\n\n // List all files in packages\n const files = await listPackageFiles(options.packages, options.ignore, baseDir)\n\n // Sort files lexicographically\n const sortedFiles = sortFiles(files)\n\n // Track visited files to handle multiple symlinks pointing to the same file\n // Key: realpath, Value: file hash\n const fileHashCache = new Map<string, Buffer>()\n\n // Compute individual file hashes\n const fileHashInputs: FileHashInput[] = []\n for (const file of sortedFiles) {\n const filePath = path.resolve(baseDir, file)\n\n // Handle symlinks\n let realPath = filePath\n let stats = await fs.promises.lstat(filePath)\n\n if (stats.isSymbolicLink()) {\n try {\n realPath = await fs.promises.realpath(filePath)\n } catch {\n // Skip broken symlinks\n continue\n }\n\n // Get stats of the target\n try {\n stats = await fs.promises.stat(realPath)\n } catch {\n // Skip broken symlinks\n continue\n }\n }\n\n // Skip if not a file (e.g., directories)\n if (!stats.isFile()) {\n continue\n }\n\n // Normalize path separators to forward slashes\n const normalizedPath = normalizePath(file)\n\n // Check if we've already hashed this file (via symlinks)\n let hash: Buffer\n const cachedHash = fileHashCache.get(realPath)\n if (cachedHash !== undefined) {\n // Reuse cached hash for files we've already seen (via symlinks)\n hash = cachedHash\n } else {\n // Hash the file content\n hash = await hashFileAsync(realPath, normalizedPath, stats)\n fileHashCache.set(realPath, hash)\n }\n\n fileHashInputs.push({ relativePath: normalizedPath, hash })\n }\n\n // Compute final fingerprint\n const fingerprint = computeFinalFingerprint(fileHashInputs)\n\n return {\n fingerprint,\n files: sortedFiles,\n fileCount: sortedFiles.length,\n }\n}\n\n/**\n * Compute a deterministic fingerprint for a set of packages (sync).\n *\n * @param options - Configuration for fingerprint computation\n * @returns Result containing the fingerprint hash and list of files processed\n * @throws Error if packages array is empty or if package paths don't exist\n * @public\n * @see {@link computeFingerprint} for the async version\n */\nexport function computeFingerprintSync(options: FingerprintOptions): FingerprintResult {\n const baseDir = validateOptions(options)\n\n // List all files in packages (sync version)\n const files = listPackageFilesSync(options.packages, options.ignore, baseDir)\n\n // Sort files lexicographically\n const sortedFiles = sortFiles(files)\n\n // Track visited files to handle multiple symlinks pointing to the same file\n // Key: realpath, Value: file hash\n const fileHashCache = new Map<string, Buffer>()\n\n // Compute individual file hashes\n const fileHashInputs: FileHashInput[] = []\n for (const file of sortedFiles) {\n const filePath = path.resolve(baseDir, file)\n\n // Handle symlinks\n let realPath = filePath\n let stats = fs.lstatSync(filePath)\n\n if (stats.isSymbolicLink()) {\n try {\n realPath = fs.realpathSync(filePath)\n } catch {\n // Skip broken symlinks\n continue\n }\n\n // Get stats of the target\n try {\n stats = fs.statSync(realPath)\n } catch {\n // Skip broken symlinks\n continue\n }\n }\n\n // Skip if not a file (e.g., directories)\n if (!stats.isFile()) {\n continue\n }\n\n // Normalize path separators to forward slashes\n const normalizedPath = normalizePath(file)\n\n // Check if we've already hashed this file (via symlinks)\n let hash: Buffer\n const cachedHash = fileHashCache.get(realPath)\n if (cachedHash !== undefined) {\n // Reuse cached hash for files we've already seen (via symlinks)\n hash = cachedHash\n } else {\n // Hash the file content (sync version cannot stream)\n hash = hashFileSync(realPath, normalizedPath)\n fileHashCache.set(realPath, hash)\n }\n\n fileHashInputs.push({ relativePath: normalizedPath, hash })\n }\n\n // Compute final fingerprint\n const fingerprint = computeFinalFingerprint(fileHashInputs)\n\n return {\n fingerprint,\n files: sortedFiles,\n fileCount: sortedFiles.length,\n }\n}\n\n/**\n * List files in packages, respecting ignore patterns (async).\n *\n * @param packages - Array of package directory paths\n * @param ignore - Optional glob patterns to exclude\n * @param baseDir - Base directory for resolving paths (defaults to cwd)\n * @returns Array of relative file paths\n * @public\n */\nexport async function listPackageFiles(\n packages: string[],\n ignore: string[] = [],\n baseDir: string = process.cwd(),\n): Promise<string[]> {\n const allFiles: string[] = []\n\n for (const pkg of packages) {\n // Build glob patterns for this package\n const patterns = [`${pkg}/**/*`]\n\n // Use tinyglobby to find files\n const files = await glob(patterns, {\n cwd: baseDir,\n ignore,\n onlyFiles: true,\n dot: true, // Include dotfiles\n absolute: false, // Return relative paths\n })\n\n allFiles.push(...files)\n }\n\n return allFiles\n}\n\n/**\n * Synchronous version of listPackageFiles\n */\nfunction listPackageFilesSync(\n packages: string[],\n ignore: string[] = [],\n baseDir: string = process.cwd(),\n): string[] {\n const allFiles: string[] = []\n\n for (const pkg of packages) {\n // Build glob patterns for this package\n const patterns = [`${pkg}/**/*`]\n\n // Use tinyglobby to find files (sync version)\n const files = globSync(patterns, {\n cwd: baseDir,\n ignore,\n onlyFiles: true,\n dot: true, // Include dotfiles\n absolute: false, // Return relative paths\n })\n\n allFiles.push(...files)\n }\n\n return allFiles\n}\n","/**\n * Attestation file I/O module with JSON canonicalization.\n */\n\nimport * as fs from 'node:fs'\nimport * as os from 'node:os'\nimport * as path from 'node:path'\nimport * as canonicalizeNamespace from 'canonicalize'\nimport { z } from 'zod'\nimport type { Attestation, AttestationsFile } from './types.js'\n\n/**\n * Extract the serialize function from the canonicalize CommonJS module.\n *\n * Context: The canonicalize package uses `module.exports = function(...)`, which is\n * a CommonJS pattern. With `esModuleInterop: false` (required for library code to\n * avoid leaking tsconfig options to consumers), TypeScript treats the namespace import\n * as the module object itself, not as an object with a default export.\n *\n * The package's type definitions declare `export default function serialize(...)`,\n * which TypeScript interprets as `{ default: function }` when esModuleInterop is off.\n * However, at runtime with NodeNext module resolution, the actual value is just the\n * function itself.\n *\n * This type assertion is safe because:\n * 1. We verified the runtime export structure of the canonicalize module\n * 2. The type matches the published @types signature\n * 3. This is the standard pattern for importing CommonJS modules in strict ESM\n */\n// eslint-disable-next-line @typescript-eslint/consistent-type-assertions\nconst canonicalize = canonicalizeNamespace as unknown as {\n default: (input: unknown) => string | undefined\n}\nconst serialize = canonicalize.default\n\n// Zod schema for attestation validation\nconst attestationSchema = z.object({\n suite: z.string().min(1),\n fingerprint: z.string().regex(/^sha256:[a-f0-9]{64}$/),\n attestedAt: z.string().datetime(),\n attestedBy: z.string().min(1),\n command: z.string().min(1),\n exitCode: z.literal(0),\n})\n\nconst attestationsFileSchema = z.object({\n schemaVersion: z.literal('1'),\n attestations: z.array(attestationSchema),\n signature: z.string(), // Will be validated by crypto module\n})\n\n/**\n * Type guard to check if an error is a Node.js file system error with code.\n * We need to disable the type assertion rule here because TypeScript doesn't\n * provide a way to narrow an object type after checking for a property without\n * using type assertions or indexed access. This is a safe assertion because we\n * check for the property existence and type before using it.\n */\nfunction isNodeError(error: unknown): error is NodeJS.ErrnoException {\n if (error === null || typeof error !== 'object') {\n return false\n }\n if (!('code' in error)) {\n return false\n }\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n const errorObj = error as Record<string, unknown>\n return typeof errorObj.code === 'string'\n}\n\n/**\n * Read attestations file from disk (async).\n *\n * @param filePath - Absolute path to the attestations JSON file\n * @returns Parsed attestations file, or null if the file doesn't exist\n * @throws Error on parse or validation errors\n * @public\n */\nexport async function readAttestations(filePath: string): Promise<AttestationsFile | null> {\n try {\n const content = await fs.promises.readFile(filePath, 'utf-8')\n const parsed: unknown = JSON.parse(content)\n // Zod validates and returns the correct type\n return attestationsFileSchema.parse(parsed)\n } catch (error) {\n if (isNodeError(error) && error.code === 'ENOENT') {\n return null\n }\n throw error\n }\n}\n\n/**\n * Read attestations file from disk (sync).\n *\n * @param filePath - Absolute path to the attestations JSON file\n * @returns Parsed attestations file, or null if the file doesn't exist\n * @throws Error on parse or validation errors\n * @public\n */\nexport function readAttestationsSync(filePath: string): AttestationsFile | null {\n try {\n const content = fs.readFileSync(filePath, 'utf-8')\n const parsed: unknown = JSON.parse(content)\n // Zod validates and returns the correct type\n return attestationsFileSchema.parse(parsed)\n } catch (error) {\n if (isNodeError(error) && error.code === 'ENOENT') {\n return null\n }\n throw error\n }\n}\n\n/**\n * Write attestations file to disk (async).\n *\n * Creates parent directories if needed. The signature should be computed\n * separately and passed in.\n *\n * @param filePath - Absolute path to write the attestations file\n * @param attestations - Array of attestation entries\n * @param signature - Cryptographic signature of the attestations\n * @throws Error on validation or write errors\n * @public\n */\nexport async function writeAttestations(\n filePath: string,\n attestations: Attestation[],\n signature: string,\n): Promise<void> {\n const fileContent: AttestationsFile = {\n schemaVersion: '1',\n attestations,\n signature,\n }\n\n // Validate before writing\n attestationsFileSchema.parse(fileContent)\n\n // Create parent directories if needed\n const dir = path.dirname(filePath)\n await fs.promises.mkdir(dir, { recursive: true })\n\n // Write with pretty formatting for readability\n const json = JSON.stringify(fileContent, null, 2)\n await fs.promises.writeFile(filePath, json, 'utf-8')\n}\n\n/**\n * Write attestations file to disk (sync).\n *\n * Creates parent directories if needed. The signature should be computed\n * separately and passed in.\n *\n * @param filePath - Absolute path to write the attestations file\n * @param attestations - Array of attestation entries\n * @param signature - Cryptographic signature of the attestations\n * @throws Error on validation or write errors\n * @public\n */\nexport function writeAttestationsSync(\n filePath: string,\n attestations: Attestation[],\n signature: string,\n): void {\n const fileContent: AttestationsFile = {\n schemaVersion: '1',\n attestations,\n signature,\n }\n\n // Validate before writing\n attestationsFileSchema.parse(fileContent)\n\n // Create parent directories if needed\n const dir = path.dirname(filePath)\n fs.mkdirSync(dir, { recursive: true })\n\n // Write with pretty formatting for readability\n const json = JSON.stringify(fileContent, null, 2)\n fs.writeFileSync(filePath, json, 'utf-8')\n}\n\n/**\n * Find an attestation for a specific suite.\n *\n * @param attestations - Attestations file containing all attestations\n * @param suite - Name of the suite to find\n * @returns The attestation if found, undefined otherwise\n * @public\n */\nexport function findAttestation(\n attestations: AttestationsFile,\n suite: string,\n): Attestation | undefined {\n return attestations.attestations.find((a) => a.suite === suite)\n}\n\n/**\n * Add or update an attestation for a suite.\n *\n * This is an immutable operation that returns a new array.\n *\n * @param attestations - Current array of attestations\n * @param newAttestation - Attestation to add or update\n * @returns New attestations array with the upserted attestation\n * @throws Error if the new attestation fails validation\n * @public\n */\nexport function upsertAttestation(\n attestations: Attestation[],\n newAttestation: Attestation,\n): Attestation[] {\n // Validate the new attestation\n attestationSchema.parse(newAttestation)\n\n const existingIndex = attestations.findIndex((a) => a.suite === newAttestation.suite)\n\n if (existingIndex === -1) {\n // Add new attestation\n return [...attestations, newAttestation]\n } else {\n // Update existing attestation\n const updated = [...attestations]\n // eslint-disable-next-line security/detect-object-injection -- False positive: existingIndex is a safe number from findIndex\n updated[existingIndex] = newAttestation\n return updated\n }\n}\n\n/**\n * Remove attestations for a suite.\n *\n * This is an immutable operation that returns a new array.\n *\n * @param attestations - Current array of attestations\n * @param suite - Name of the suite to remove\n * @returns New attestations array without the specified suite\n * @public\n */\nexport function removeAttestation(attestations: Attestation[], suite: string): Attestation[] {\n return attestations.filter((a) => a.suite !== suite)\n}\n\n/**\n * Compute canonical JSON representation for signing.\n *\n * Implements RFC 8785 JSON Canonicalization Scheme. The canonicalize package provides:\n * 1. Keys sorted lexicographically (Unicode code point order)\n * 2. No whitespace between tokens\n * 3. No trailing commas\n * 4. Strings escaped using \\uXXXX for control characters\n * 5. Numbers: no leading zeros, no +, use lowercase 'e' for exponent\n * 6. UTF-8 encoding\n *\n * @param attestations - Array of attestations to canonicalize\n * @returns Canonical JSON string representation\n * @throws Error if canonicalization fails\n * @public\n */\nexport function canonicalizeAttestations(attestations: Attestation[]): string {\n const canonical = serialize(attestations)\n if (canonical === undefined) {\n throw new Error('Failed to canonicalize attestations')\n }\n return canonical\n}\n\n/**\n * Create a new attestation entry.\n *\n * @param params - Parameters for creating the attestation\n * @param params.suite - Name of the test suite\n * @param params.fingerprint - Fingerprint of the packages in sha256 format\n * @param params.command - Command that was executed\n * @param params.attestedBy - Optional username (defaults to current OS user)\n * @returns Validated attestation object\n * @throws Error if attestation validation fails\n * @public\n */\nexport function createAttestation(params: {\n suite: string\n fingerprint: string\n command: string\n attestedBy?: string\n}): Attestation {\n const attestation: Attestation = {\n suite: params.suite,\n fingerprint: params.fingerprint,\n attestedAt: new Date().toISOString(),\n attestedBy: params.attestedBy ?? os.userInfo().username,\n command: params.command,\n exitCode: 0,\n }\n\n // Validate before returning\n attestationSchema.parse(attestation)\n\n return attestation\n}\n\n/**\n * Options for writing signed attestations.\n * @public\n */\nexport interface WriteSignedAttestationsOptions {\n /** Path to write the attestations file */\n filePath: string\n /** Array of attestations to write */\n attestations: Attestation[]\n /** Path to the private key for signing (legacy) */\n privateKeyPath?: string\n /** Key provider for signing */\n keyProvider?: import('./key-provider/types.js').KeyProvider\n /** Key reference for the provider */\n keyRef?: string\n}\n\n/**\n * Options for reading and verifying signed attestations.\n * @public\n */\nexport interface ReadSignedAttestationsOptions {\n /** Path to read the attestations file from */\n filePath: string\n /** Path to the public key for verification */\n publicKeyPath: string\n}\n\n/**\n * Write attestations with a cryptographic signature.\n *\n * This function canonicalizes the attestations, signs them with the private key,\n * and writes the attestations file with the signature.\n *\n * @param options - Options for writing signed attestations\n * @throws Error if signing or writing fails\n * @public\n */\nexport async function writeSignedAttestations(\n options: WriteSignedAttestationsOptions,\n): Promise<void> {\n // Import sign function here to avoid circular dependency\n const { sign } = await import('./crypto.js')\n\n const { privateKeyPath, keyProvider, keyRef } = options\n\n // Validate that we have either legacy path or provider + ref\n if (!privateKeyPath && (!keyProvider || !keyRef)) {\n throw new Error(\n 'Either privateKeyPath or both keyProvider and keyRef must be provided for signing',\n )\n }\n\n const canonical = canonicalizeAttestations(options.attestations)\n\n // Build sign options, only including defined properties\n const signOptions: Parameters<typeof sign>[0] = {\n data: canonical,\n }\n\n if (privateKeyPath !== undefined) {\n signOptions.privateKeyPath = privateKeyPath\n }\n if (keyProvider !== undefined) {\n signOptions.keyProvider = keyProvider\n }\n if (keyRef !== undefined) {\n signOptions.keyRef = keyRef\n }\n\n const signature = await sign(signOptions)\n await writeAttestations(options.filePath, options.attestations, signature)\n}\n\n/**\n * Read attestations and verify the signature.\n *\n * This function reads the attestations file, canonicalizes the attestations,\n * and verifies the signature using the public key. It throws an error if the\n * file doesn't exist or if signature verification fails.\n *\n * @param options - Options for reading and verifying attestations\n * @returns The attestations file if signature is valid\n * @throws Error if attestations file not found\n * @throws SignatureInvalidError if signature verification fails\n * @public\n */\nexport async function readAndVerifyAttestations(\n options: ReadSignedAttestationsOptions,\n): Promise<AttestationsFile> {\n // Import verify function here to avoid circular dependency\n const { verify } = await import('./crypto.js')\n\n const file = await readAttestations(options.filePath)\n if (!file) {\n throw new Error(`Attestations file not found: ${options.filePath}`)\n }\n\n const canonical = canonicalizeAttestations(file.attestations)\n const isValid = await verify({\n publicKeyPath: options.publicKeyPath,\n data: canonical,\n signature: file.signature,\n })\n\n if (!isValid) {\n throw new SignatureInvalidError(options.filePath)\n }\n\n return file\n}\n\n/**\n * Error thrown when signature verification fails.\n * @public\n */\nexport class SignatureInvalidError extends Error {\n /**\n * Create a new SignatureInvalidError.\n * @param filePath - Path to the file that failed verification\n */\n constructor(filePath: string) {\n super(`Signature verification failed for: ${filePath}`)\n this.name = 'SignatureInvalidError'\n }\n}\n","/**\n * @attest-it/core\n *\n * Core functionality for the attest-it testing framework.\n * @packageDocumentation\n */\n\n/**\n * Package version\n * @public\n */\nexport const version = '0.0.0'\n\n// Types\nexport type {\n AttestItSettings,\n KeyProviderSettings,\n TeamMember,\n FingerprintConfig,\n GateConfig,\n SuiteConfig,\n AttestItConfig,\n Attestation,\n AttestationsFile,\n VerificationStatus,\n SuiteVerificationResult,\n} from './types.js'\n\n// Config\nexport {\n loadConfig,\n loadConfigSync,\n findConfigPath,\n resolveConfigPaths,\n toAttestItConfig,\n ConfigValidationError,\n ConfigNotFoundError,\n type Config,\n} from './config.js'\n\n// Fingerprinting\nexport { computeFingerprint, computeFingerprintSync, listPackageFiles } from './fingerprint.js'\nexport type { FingerprintOptions, FingerprintResult } from './fingerprint.js'\n\n// Attestations\nexport {\n readAttestations,\n readAttestationsSync,\n writeAttestations,\n writeAttestationsSync,\n findAttestation,\n upsertAttestation,\n removeAttestation,\n canonicalizeAttestations,\n createAttestation,\n writeSignedAttestations,\n readAndVerifyAttestations,\n SignatureInvalidError,\n} from './attestation.js'\nexport type {\n WriteSignedAttestationsOptions,\n ReadSignedAttestationsOptions,\n} from './attestation.js'\n\n// Cryptography\nexport {\n checkOpenSSL,\n getDefaultPrivateKeyPath,\n getDefaultPublicKeyPath,\n generateKeyPair,\n sign,\n verify,\n setKeyPermissions,\n} from './crypto.js'\nexport type {\n KeyPaths,\n KeygenOptions,\n SignOptions,\n VerifyOptions as CryptoVerifyOptions,\n} from './crypto.js'\n\n// Ed25519 Cryptography\nexport {\n generateKeyPair as generateEd25519KeyPair,\n sign as signEd25519,\n verify as verifyEd25519,\n getPublicKeyFromPrivate,\n} from './crypto/ed25519.js'\nexport type { KeyPair as Ed25519KeyPair } from './crypto/ed25519.js'\n\n// Verification\nexport { verifyAttestations } from './verify.js'\nexport type { VerifyOptions, VerifyResult } from './verify.js'\n\n// Key Providers\nexport {\n FilesystemKeyProvider,\n OnePasswordKeyProvider,\n MacOSKeychainKeyProvider,\n KeyProviderRegistry,\n type KeyProvider,\n type KeyProviderConfig,\n type KeyRetrievalResult,\n type KeyGenerationResult,\n type KeygenProviderOptions,\n type FilesystemKeyProviderOptions,\n type OnePasswordKeyProviderOptions,\n type OnePasswordAccount,\n type OnePasswordVault,\n type MacOSKeychainKeyProviderOptions,\n type KeyProviderFactory,\n} from './key-provider/index.js'\n\n// Identity System\nexport {\n getLocalConfigPath,\n loadLocalConfig,\n loadLocalConfigSync,\n saveLocalConfig,\n saveLocalConfigSync,\n getActiveIdentity,\n LocalConfigValidationError,\n type PrivateKeyRef,\n type Identity,\n type LocalConfig,\n} from './identity/index.js'\n\n// Authorization\nexport {\n isAuthorizedSigner,\n getAuthorizedSignersForGate,\n findTeamMemberByPublicKey,\n getGate,\n parseDuration,\n} from './authorization.js'\n\n// Seal System\nexport {\n createSeal,\n verifySeal,\n readSeals,\n readSealsSync,\n writeSeals,\n writeSealsSync,\n verifyGateSeal,\n verifyAllSeals,\n type Seal,\n type SealsFile,\n type CreateSealOptions,\n type SignatureVerificationResult,\n type VerificationState,\n type SealVerificationResult,\n} from './seal/index.js'\n","/**\n * Ed25519 cryptographic operations using Node.js native crypto module.\n *\n * @remarks\n * This module provides Ed25519 digital signature operations using Node.js\n * native crypto support (available in Node 18+). Ed25519 offers better security\n * and performance than RSA-2048 with much smaller key and signature sizes.\n *\n * @packageDocumentation\n */\n\nimport * as crypto from 'node:crypto'\n\n/**\n * An Ed25519 keypair with base64-encoded public key and PEM-encoded private key.\n * @public\n */\nexport interface KeyPair {\n /** Base64-encoded public key (raw 32 bytes, ~44 characters) */\n publicKey: string\n /** PEM-encoded private key */\n privateKey: string\n}\n\n/**\n * Type guard to check if a value is a Buffer.\n * @param value - Value to check\n * @returns true if value is a Buffer\n * @internal\n */\nfunction isBuffer(value: unknown): value is Buffer {\n return Buffer.isBuffer(value)\n}\n\n/**\n * Generate a new Ed25519 keypair.\n *\n * @returns A keypair with base64-encoded public key and PEM-encoded private key\n * @throws Error if key generation fails\n * @public\n */\nexport function generateKeyPair(): KeyPair {\n try {\n // Generate Ed25519 keypair using Node.js native crypto\n // When format is 'pem', the keys are returned as strings\n const keyPair = crypto.generateKeyPairSync('ed25519', {\n publicKeyEncoding: {\n type: 'spki',\n format: 'pem',\n },\n privateKeyEncoding: {\n type: 'pkcs8',\n format: 'pem',\n },\n })\n\n const { publicKey, privateKey } = keyPair\n if (typeof publicKey !== 'string' || typeof privateKey !== 'string') {\n throw new Error('Expected keypair to have string keys')\n }\n\n // Extract raw public key bytes and encode as base64\n const publicKeyObj = crypto.createPublicKey(publicKey)\n const publicKeyExport = publicKeyObj.export({\n type: 'spki',\n format: 'der',\n })\n\n if (!isBuffer(publicKeyExport)) {\n throw new Error('Expected public key export to be a Buffer')\n }\n\n // Ed25519 SPKI format: 12-byte header + 32-byte key\n // We extract just the 32-byte raw key for compact storage\n const rawPublicKey = publicKeyExport.subarray(12)\n const publicKeyBase64 = rawPublicKey.toString('base64')\n\n return {\n publicKey: publicKeyBase64,\n privateKey,\n }\n } catch (err) {\n throw new Error(\n `Failed to generate Ed25519 keypair: ${err instanceof Error ? err.message : String(err)}`,\n )\n }\n}\n\n/**\n * Sign data with an Ed25519 private key.\n *\n * @param data - Data to sign (Buffer or UTF-8 string)\n * @param privateKeyPem - PEM-encoded private key\n * @returns Base64-encoded signature\n * @throws Error if signing fails\n * @public\n */\nexport function sign(data: Buffer | string, privateKeyPem: string): string {\n try {\n // Convert string data to Buffer\n const dataBuffer = typeof data === 'string' ? Buffer.from(data, 'utf8') : data\n\n // Create private key object\n const privateKeyObj = crypto.createPrivateKey(privateKeyPem)\n\n // Sign the data (null algorithm parameter for Ed25519)\n const signatureResult = crypto.sign(null, dataBuffer, privateKeyObj)\n\n if (!isBuffer(signatureResult)) {\n throw new Error('Expected signature to be a Buffer')\n }\n\n return signatureResult.toString('base64')\n } catch (err) {\n throw new Error(\n `Failed to sign data with Ed25519: ${err instanceof Error ? err.message : String(err)}`,\n )\n }\n}\n\n/**\n * Verify an Ed25519 signature.\n *\n * @param data - Original data that was signed\n * @param signature - Base64-encoded signature to verify\n * @param publicKeyBase64 - Base64-encoded public key (raw 32 bytes)\n * @returns true if signature is valid, false otherwise\n * @throws Error if verification fails (not just invalid signature)\n * @public\n */\nexport function verify(data: Buffer | string, signature: string, publicKeyBase64: string): boolean {\n try {\n // Convert string data to Buffer\n const dataBuffer = typeof data === 'string' ? Buffer.from(data, 'utf8') : data\n\n // Decode signature from base64\n const signatureBuffer = Buffer.from(signature, 'base64')\n\n // Reconstruct SPKI format from raw public key\n // Ed25519 SPKI: 12-byte header + 32-byte key\n const rawPublicKey = Buffer.from(publicKeyBase64, 'base64')\n\n if (rawPublicKey.length !== 32) {\n throw new Error(\n `Invalid Ed25519 public key length: expected 32 bytes, got ${rawPublicKey.length.toString()}`,\n )\n }\n\n // SPKI header for Ed25519 (algorithm OID)\n const spkiHeader = Buffer.from([\n 0x30,\n 0x2a, // SEQUENCE, 42 bytes\n 0x30,\n 0x05, // SEQUENCE, 5 bytes\n 0x06,\n 0x03,\n 0x2b,\n 0x65,\n 0x70, // OID 1.3.101.112 (Ed25519)\n 0x03,\n 0x21,\n 0x00, // BIT STRING, 33 bytes (32 key + 1 padding)\n ])\n\n const spkiBuffer = Buffer.concat([spkiHeader, rawPublicKey])\n\n // Create public key object from SPKI\n const publicKeyObj = crypto.createPublicKey({\n key: spkiBuffer,\n format: 'der',\n type: 'spki',\n })\n\n // Verify the signature (null algorithm parameter for Ed25519)\n return crypto.verify(null, dataBuffer, publicKeyObj, signatureBuffer)\n } catch (err) {\n // If it's a verification failure (wrong signature), return false\n // If it's any other error, throw it\n if (err instanceof Error && err.message.includes('verification failed')) {\n return false\n }\n throw new Error(\n `Failed to verify Ed25519 signature: ${err instanceof Error ? err.message : String(err)}`,\n )\n }\n}\n\n/**\n * Extract the public key from an Ed25519 private key.\n *\n * @param privateKeyPem - PEM-encoded private key\n * @returns Base64-encoded public key (raw 32 bytes)\n * @throws Error if extraction fails\n * @public\n */\nexport function getPublicKeyFromPrivate(privateKeyPem: string): string {\n try {\n // Create private key object\n const privateKeyObj = crypto.createPrivateKey(privateKeyPem)\n\n // Export the corresponding public key\n const publicKeyObj = crypto.createPublicKey(privateKeyObj)\n const publicKeyExport = publicKeyObj.export({\n type: 'spki',\n format: 'der',\n })\n\n if (!isBuffer(publicKeyExport)) {\n throw new Error('Expected public key export to be a Buffer')\n }\n\n // Extract raw 32-byte public key from SPKI format\n const rawPublicKey = publicKeyExport.subarray(12)\n return rawPublicKey.toString('base64')\n } catch (err) {\n throw new Error(\n `Failed to extract public key from Ed25519 private key: ${err instanceof Error ? err.message : String(err)}`,\n )\n }\n}\n","/**\n * Verification logic for attestations.\n * @packageDocumentation\n */\n\nimport * as fs from 'node:fs'\nimport * as path from 'node:path'\nimport type {\n AttestItConfig,\n Attestation,\n AttestationsFile,\n SuiteVerificationResult,\n} from './types.js'\nimport { computeFingerprint } from './fingerprint.js'\nimport { readAndVerifyAttestations, SignatureInvalidError } from './attestation.js'\n\n/**\n * Options for verifying attestations.\n * @public\n */\nexport interface VerifyOptions {\n /** Configuration object */\n config: AttestItConfig\n /** Repository root directory (defaults to process.cwd()) */\n repoRoot?: string\n}\n\n/**\n * Result of verifying all attestations.\n * @public\n */\nexport interface VerifyResult {\n /** Overall success - true if all attestations are valid */\n success: boolean\n /** Whether the attestations file signature is valid */\n signatureValid: boolean\n /** Verification results for each suite */\n suites: SuiteVerificationResult[]\n /** Error messages encountered during verification */\n errors: string[]\n}\n\n/**\n * Verify all attestations against current code state.\n *\n * Verification algorithm:\n * 1. Load and verify attestations file signature\n * 2. For each suite in config:\n * a. Compute current fingerprint\n * b. Find matching attestation\n * c. Compare fingerprints\n * d. Check age\n * 3. Check invalidation chains\n * 4. Return aggregated results\n *\n * @param options - Verification options\n * @returns Verification result with status for each suite\n * @public\n */\nexport async function verifyAttestations(options: VerifyOptions): Promise<VerifyResult> {\n const { config, repoRoot = process.cwd() } = options\n const errors: string[] = []\n const suiteResults: SuiteVerificationResult[] = []\n let signatureValid = true\n let attestationsFile: AttestationsFile | null = null\n\n // Resolve paths\n const attestationsPath = resolvePath(config.settings.attestationsPath, repoRoot)\n const publicKeyPath = resolvePath(config.settings.publicKeyPath, repoRoot)\n\n // Step 1: Load and verify attestations\n try {\n if (!fs.existsSync(attestationsPath)) {\n // No attestations file - all suites need attestation\n attestationsFile = null\n } else if (!fs.existsSync(publicKeyPath)) {\n errors.push(`Public key not found: ${publicKeyPath}`)\n signatureValid = false\n } else {\n attestationsFile = await readAndVerifyAttestations({\n filePath: attestationsPath,\n publicKeyPath,\n })\n }\n } catch (err) {\n if (err instanceof SignatureInvalidError) {\n signatureValid = false\n errors.push(err.message)\n } else if (err instanceof Error) {\n errors.push(err.message)\n }\n }\n\n const attestations = attestationsFile?.attestations ?? []\n\n // Step 2: Check each suite\n for (const [suiteName, suiteConfig] of Object.entries(config.suites)) {\n const result = await verifySuite({\n suiteName,\n suiteConfig,\n attestations,\n maxAgeDays: config.settings.maxAgeDays,\n repoRoot,\n })\n suiteResults.push(result)\n }\n\n // Step 3: Check invalidation chains\n checkInvalidationChains(config, suiteResults)\n\n // Step 4: Aggregate results\n const allValid =\n signatureValid && suiteResults.every((r) => r.status === 'VALID') && errors.length === 0\n\n return {\n success: allValid,\n signatureValid,\n suites: suiteResults,\n errors,\n }\n}\n\n/**\n * Options for verifying a single suite.\n * @internal\n */\ninterface VerifySuiteOptions {\n /** Name of the suite */\n suiteName: string\n /** Suite configuration */\n suiteConfig: { packages?: string[]; ignore?: string[] }\n /** All attestations from the attestations file */\n attestations: Attestation[]\n /** Maximum age in days before attestation expires */\n maxAgeDays: number\n /** Repository root directory */\n repoRoot: string\n}\n\n/**\n * Verify a single suite's attestation.\n * @internal\n */\nasync function verifySuite(options: VerifySuiteOptions): Promise<SuiteVerificationResult> {\n const { suiteName, suiteConfig, attestations, maxAgeDays, repoRoot } = options\n\n // Validate that packages is defined (required for legacy verification)\n // Note: For gate-based verification, use the seal system functions instead\n if (!suiteConfig.packages || suiteConfig.packages.length === 0) {\n return {\n suite: suiteName,\n status: 'NEEDS_ATTESTATION',\n fingerprint: '',\n message: 'Suite configuration missing packages field',\n }\n }\n\n // Compute current fingerprint\n const fingerprintOptions = {\n packages: suiteConfig.packages.map((p) => resolvePath(p, repoRoot)),\n baseDir: repoRoot,\n ...(suiteConfig.ignore && { ignore: suiteConfig.ignore }),\n }\n const fingerprintResult = await computeFingerprint(fingerprintOptions)\n\n // Find attestation for this suite\n const attestation = attestations.find((a) => a.suite === suiteName)\n\n // No attestation found\n if (!attestation) {\n return {\n suite: suiteName,\n status: 'NEEDS_ATTESTATION',\n fingerprint: fingerprintResult.fingerprint,\n message: 'No attestation found for this suite',\n }\n }\n\n // Check fingerprint\n if (attestation.fingerprint !== fingerprintResult.fingerprint) {\n return {\n suite: suiteName,\n status: 'FINGERPRINT_CHANGED',\n fingerprint: fingerprintResult.fingerprint,\n attestation,\n message: `Fingerprint changed from ${attestation.fingerprint.slice(0, 20)}... to ${fingerprintResult.fingerprint.slice(0, 20)}...`,\n }\n }\n\n // Check age\n const attestedAt = new Date(attestation.attestedAt)\n const ageMs = Date.now() - attestedAt.getTime()\n const ageDays = Math.floor(ageMs / (1000 * 60 * 60 * 24))\n\n if (ageDays > maxAgeDays) {\n return {\n suite: suiteName,\n status: 'EXPIRED',\n fingerprint: fingerprintResult.fingerprint,\n attestation,\n age: ageDays,\n message: `Attestation expired (${String(ageDays)} days old, max ${String(maxAgeDays)} days)`,\n }\n }\n\n // All checks passed\n return {\n suite: suiteName,\n status: 'VALID',\n fingerprint: fingerprintResult.fingerprint,\n attestation,\n age: ageDays,\n }\n}\n\n/**\n * Check invalidation chains.\n *\n * If suite A invalidates suite B, and A's attestation is newer than B's,\n * then B should be marked as INVALIDATED_BY_PARENT.\n *\n * @param config - Full configuration\n * @param results - Array of suite verification results to mutate\n * @internal\n */\nfunction checkInvalidationChains(config: AttestItConfig, results: SuiteVerificationResult[]): void {\n for (const [parentName, parentConfig] of Object.entries(config.suites)) {\n const invalidates = parentConfig.invalidates ?? []\n const parentResult = results.find((r) => r.suite === parentName)\n\n if (!parentResult?.attestation) continue\n\n const parentTime = new Date(parentResult.attestation.attestedAt).getTime()\n\n for (const childName of invalidates) {\n const childResult = results.find((r) => r.suite === childName)\n if (!childResult?.attestation) continue\n\n const childTime = new Date(childResult.attestation.attestedAt).getTime()\n\n // If parent was attested AFTER child, child is invalidated\n if (parentTime > childTime && childResult.status === 'VALID') {\n childResult.status = 'INVALIDATED_BY_PARENT'\n childResult.message = `Invalidated by ${parentName} (attested later)`\n }\n }\n }\n}\n\n/**\n * Resolve a path relative to a base directory.\n * @param relativePath - Path that may be relative or absolute\n * @param baseDir - Base directory for resolving relative paths\n * @returns Absolute path\n * @internal\n */\nfunction resolvePath(relativePath: string, baseDir: string): string {\n if (path.isAbsolute(relativePath)) {\n return relativePath\n }\n return path.join(baseDir, relativePath)\n}\n","/**\n * Filesystem-based key provider implementation.\n *\n * @remarks\n * This provider stores private keys on the local filesystem, maintaining\n * backward compatibility with the existing attest-it key storage behavior.\n *\n * @packageDocumentation\n */\n\nimport * as fs from 'node:fs/promises'\nimport { generateKeyPair as cryptoGenerateKeyPair, getDefaultPrivateKeyPath } from '../crypto.js'\nimport type {\n KeyProvider,\n KeyProviderConfig,\n KeyRetrievalResult,\n KeyGenerationResult,\n KeygenProviderOptions,\n} from './types.js'\n\n/**\n * Options for creating a FilesystemKeyProvider.\n * @public\n */\nexport interface FilesystemKeyProviderOptions {\n /** Path to the private key file (defaults to OS-specific config dir) */\n privateKeyPath?: string\n}\n\n/**\n * Key provider that stores private keys on the filesystem.\n *\n * @remarks\n * This is the default provider and maintains backward compatibility with\n * existing attest-it installations. Private keys are stored at:\n * - macOS/Linux: ~/.config/attest-it/private.pem\n * - Windows: %APPDATA%\\attest-it\\private.pem\n *\n * @public\n */\nexport class FilesystemKeyProvider implements KeyProvider {\n readonly type = 'filesystem'\n readonly displayName = 'Filesystem'\n\n private readonly privateKeyPath: string\n\n /**\n * Create a new FilesystemKeyProvider.\n * @param options - Provider options\n */\n constructor(options: FilesystemKeyProviderOptions = {}) {\n this.privateKeyPath = options.privateKeyPath ?? getDefaultPrivateKeyPath()\n }\n\n /**\n * Check if this provider is available.\n * Filesystem provider is always available.\n */\n async isAvailable(): Promise<boolean> {\n // Filesystem provider is always available\n return Promise.resolve(true)\n }\n\n /**\n * Check if a key exists at the given path.\n * @param keyRef - Path to the private key file\n */\n async keyExists(keyRef: string): Promise<boolean> {\n try {\n await fs.access(keyRef)\n return true\n } catch {\n return false\n }\n }\n\n /**\n * Get the private key path for signing.\n * Returns the path directly with a no-op cleanup function.\n * @param keyRef - Path to the private key file\n */\n async getPrivateKey(keyRef: string): Promise<KeyRetrievalResult> {\n // Verify the key exists\n if (!(await this.keyExists(keyRef))) {\n throw new Error(`Private key not found: ${keyRef}`)\n }\n\n return {\n keyPath: keyRef,\n // No-op cleanup for filesystem provider\n cleanup: async () => {\n // Nothing to clean up - key stays on filesystem\n },\n }\n }\n\n /**\n * Generate a new keypair and store on filesystem.\n * @param options - Key generation options\n */\n async generateKeyPair(options: KeygenProviderOptions): Promise<KeyGenerationResult> {\n const { publicKeyPath, force = false } = options\n\n // Delegate to existing crypto module function\n const result = await cryptoGenerateKeyPair({\n privatePath: this.privateKeyPath,\n publicPath: publicKeyPath,\n force,\n })\n\n return {\n privateKeyRef: result.privatePath,\n publicKeyPath: result.publicPath,\n storageDescription: `Filesystem: ${result.privatePath}`,\n }\n }\n\n /**\n * Get the configuration for this provider.\n */\n getConfig(): KeyProviderConfig {\n return {\n type: this.type,\n options: {\n privateKeyPath: this.privateKeyPath,\n },\n }\n }\n}\n","/**\n * 1Password-based key provider implementation.\n *\n * @remarks\n * This provider stores private keys in 1Password and retrieves them via the\n * `op` CLI tool. Keys are downloaded to a temporary file for signing and\n * securely deleted after use.\n *\n * @packageDocumentation\n */\n\nimport * as fs from 'node:fs/promises'\nimport * as os from 'node:os'\nimport * as path from 'node:path'\nimport { spawn } from 'node:child_process'\nimport { generateKeyPair as cryptoGenerateKeyPair, setKeyPermissions } from '../crypto.js'\nimport type {\n KeyProvider,\n KeyProviderConfig,\n KeyRetrievalResult,\n KeyGenerationResult,\n KeygenProviderOptions,\n} from './types.js'\n\n/**\n * Options for creating a OnePasswordKeyProvider.\n * @public\n */\nexport interface OnePasswordKeyProviderOptions {\n /** 1Password account email (optional if only one account) */\n account?: string\n /** Vault name or ID where the key is stored */\n vault: string\n /** Item name in 1Password */\n itemName: string\n}\n\n/**\n * Information about a 1Password account.\n * @public\n */\nexport interface OnePasswordAccount {\n /** Account UUID */\n account_uuid: string\n /** User email address */\n email: string\n /** Account URL */\n url: string\n /** User UUID */\n user_uuid: string\n}\n\n/**\n * Information about a 1Password vault.\n * @public\n */\nexport interface OnePasswordVault {\n /** Vault UUID */\n id: string\n /** Vault name */\n name: string\n}\n\n/**\n * Key provider that stores private keys in 1Password.\n *\n * @remarks\n * This provider requires the `op` CLI tool to be installed and authenticated.\n * Private keys are stored as documents in 1Password and downloaded to\n * temporary files for signing operations.\n *\n * @public\n */\nexport class OnePasswordKeyProvider implements KeyProvider {\n readonly type = '1password'\n readonly displayName = '1Password'\n\n private readonly account?: string\n private readonly vault: string\n private readonly itemName: string\n\n /**\n * Create a new OnePasswordKeyProvider.\n * @param options - Provider options\n */\n constructor(options: OnePasswordKeyProviderOptions) {\n // Only assign account if it's defined (to satisfy exactOptionalPropertyTypes)\n if (options.account !== undefined) {\n this.account = options.account\n }\n this.vault = options.vault\n this.itemName = options.itemName\n }\n\n /**\n * Check if the 1Password CLI is installed.\n * @returns True if `op` command is available\n */\n static async isInstalled(): Promise<boolean> {\n try {\n await execCommand('op', ['--version'])\n return true\n } catch {\n return false\n }\n }\n\n /**\n * List all 1Password accounts.\n * @returns Array of account information\n */\n static async listAccounts(): Promise<OnePasswordAccount[]> {\n try {\n const output = await execCommand('op', ['account', 'list', '--format=json'])\n const parsed: unknown = JSON.parse(output)\n if (!Array.isArray(parsed)) {\n return []\n }\n // Type assertion needed: We validate it's an array, but can't validate structure\n // at runtime without a full validation library. The op CLI output format is trusted.\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n return parsed as OnePasswordAccount[]\n } catch (error) {\n // Log in development for debugging, but don't fail\n if (process.env.NODE_ENV !== 'production') {\n console.error('Failed to list 1Password accounts:', error)\n }\n return []\n }\n }\n\n /**\n * List vaults in a specific account.\n * @param account - Account email (optional if only one account)\n * @returns Array of vault information\n */\n static async listVaults(account?: string): Promise<OnePasswordVault[]> {\n try {\n const args = ['vault', 'list', '--format=json']\n if (account) {\n args.push('--account', account)\n }\n const output = await execCommand('op', args)\n const parsed: unknown = JSON.parse(output)\n if (!Array.isArray(parsed)) {\n return []\n }\n // Type assertion needed: We validate it's an array, but can't validate structure\n // at runtime without a full validation library. The op CLI output format is trusted.\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n return parsed as OnePasswordVault[]\n } catch (error) {\n // Log in development for debugging, but don't fail\n if (process.env.NODE_ENV !== 'production') {\n console.error('Failed to list 1Password vaults:', error)\n }\n return []\n }\n }\n\n /**\n * Check if this provider is available.\n * Requires `op` CLI to be installed and authenticated.\n */\n async isAvailable(): Promise<boolean> {\n return OnePasswordKeyProvider.isInstalled()\n }\n\n /**\n * Check if a key exists in 1Password.\n * @param keyRef - Item name in 1Password\n */\n async keyExists(keyRef: string): Promise<boolean> {\n try {\n const args = ['item', 'get', keyRef, '--vault', this.vault, '--format=json']\n if (this.account) {\n args.push('--account', this.account)\n }\n await execCommand('op', args)\n return true\n } catch {\n return false\n }\n }\n\n /**\n * Get the private key from 1Password for signing.\n * Downloads to a temporary file and returns a cleanup function.\n * @param keyRef - Item name in 1Password\n * @throws Error if the key does not exist in 1Password\n */\n async getPrivateKey(keyRef: string): Promise<KeyRetrievalResult> {\n // Check if key exists first for better error messages\n if (!(await this.keyExists(keyRef))) {\n throw new Error(\n `Key not found in 1Password: \"${keyRef}\" (vault: ${this.vault})` +\n (this.account ? ` (account: ${this.account})` : ''),\n )\n }\n\n // Create a temporary file\n const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), 'attest-it-'))\n const tempKeyPath = path.join(tempDir, 'private.pem')\n\n try {\n // Download the key from 1Password\n const args = ['document', 'get', keyRef, '--vault', this.vault, '--out-file', tempKeyPath]\n if (this.account) {\n args.push('--account', this.account)\n }\n\n await execCommand('op', args)\n\n // Set proper permissions\n await setKeyPermissions(tempKeyPath)\n\n return {\n keyPath: tempKeyPath,\n cleanup: async () => {\n // Securely delete the temporary file and directory\n try {\n await fs.unlink(tempKeyPath)\n await fs.rmdir(tempDir)\n } catch (cleanupError) {\n // Log warning for security audit - temporary keys may not have been cleaned up\n console.warn(\n `Warning: Failed to clean up temporary key file at ${tempKeyPath}: ${cleanupError instanceof Error ? cleanupError.message : String(cleanupError)}`,\n )\n }\n },\n }\n } catch (error) {\n // Clean up temp directory on error\n try {\n await fs.rm(tempDir, { recursive: true, force: true })\n } catch (cleanupError) {\n // Log warning for security audit - temporary keys may not have been cleaned up\n console.warn(\n `Warning: Failed to clean up temporary key directory at ${tempDir}: ${cleanupError instanceof Error ? cleanupError.message : String(cleanupError)}`,\n )\n }\n throw error\n }\n }\n\n /**\n * Generate a new keypair and store private key in 1Password.\n * Public key is written to filesystem for repository commit.\n * @param options - Key generation options\n */\n async generateKeyPair(options: KeygenProviderOptions): Promise<KeyGenerationResult> {\n const { publicKeyPath, force = false } = options\n\n // Create a temporary directory for key generation\n const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), 'attest-it-keygen-'))\n const tempPrivateKeyPath = path.join(tempDir, 'private.pem')\n\n try {\n // Generate the keypair to temporary location\n await cryptoGenerateKeyPair({\n privatePath: tempPrivateKeyPath,\n publicPath: publicKeyPath,\n force,\n })\n\n // Upload the private key to 1Password as a document\n const args = [\n 'document',\n 'create',\n tempPrivateKeyPath,\n '--title',\n this.itemName,\n '--vault',\n this.vault,\n ]\n if (this.account) {\n args.push('--account', this.account)\n }\n\n await execCommand('op', args)\n\n // Clean up temporary private key\n await fs.unlink(tempPrivateKeyPath)\n await fs.rmdir(tempDir)\n\n return {\n privateKeyRef: this.itemName,\n publicKeyPath,\n storageDescription: `1Password: ${this.vault}/${this.itemName}`,\n }\n } catch (error) {\n // Clean up on error\n try {\n await fs.rm(tempDir, { recursive: true, force: true })\n } catch (cleanupError) {\n // Log warning for security audit - temporary keys may not have been cleaned up\n console.warn(\n `Warning: Failed to clean up temporary key directory at ${tempDir}: ${cleanupError instanceof Error ? cleanupError.message : String(cleanupError)}`,\n )\n }\n throw error\n }\n }\n\n /**\n * Get the configuration for this provider.\n */\n getConfig(): KeyProviderConfig {\n return {\n type: this.type,\n options: {\n ...(this.account && { account: this.account }),\n vault: this.vault,\n itemName: this.itemName,\n },\n }\n }\n}\n\n/**\n * Execute a command and return stdout.\n * @internal\n */\nasync function execCommand(command: string, args: string[]): Promise<string> {\n return new Promise((resolve, reject) => {\n const proc = spawn(command, args, { stdio: ['ignore', 'pipe', 'pipe'] })\n let stdout = ''\n let stderr = ''\n\n proc.stdout.on('data', (data: Buffer) => {\n stdout += data.toString()\n })\n\n proc.stderr.on('data', (data: Buffer) => {\n stderr += data.toString()\n })\n\n proc.on('close', (code) => {\n if (code === 0) {\n resolve(stdout.trim())\n } else {\n reject(new Error(`Command failed with exit code ${String(code)}: ${stderr}`))\n }\n })\n\n proc.on('error', (error) => {\n reject(error)\n })\n })\n}\n","/**\n * macOS Keychain-based key provider implementation.\n *\n * @remarks\n * This provider stores private keys in the macOS Keychain and retrieves them via the\n * `security` CLI tool. Keys are stored as base64-encoded strings and downloaded to\n * temporary files for signing operations, then securely deleted after use.\n *\n * @packageDocumentation\n */\n\nimport * as fs from 'node:fs/promises'\nimport * as os from 'node:os'\nimport * as path from 'node:path'\nimport { spawn } from 'node:child_process'\nimport { generateKeyPair as cryptoGenerateKeyPair, setKeyPermissions } from '../crypto.js'\nimport type {\n KeyProvider,\n KeyProviderConfig,\n KeyRetrievalResult,\n KeyGenerationResult,\n KeygenProviderOptions,\n} from './types.js'\n\n/**\n * Options for creating a MacOSKeychainKeyProvider.\n * @public\n */\nexport interface MacOSKeychainKeyProviderOptions {\n /** Item name in keychain (e.g., \"attest-it-private-key\") */\n itemName: string\n}\n\n/**\n * Key provider that stores private keys in macOS Keychain.\n *\n * @remarks\n * This provider requires macOS and uses the `security` CLI tool.\n * Private keys are stored as base64-encoded strings in the keychain and decoded\n * to temporary files for signing operations.\n *\n * @public\n */\nexport class MacOSKeychainKeyProvider implements KeyProvider {\n readonly type = 'macos-keychain'\n readonly displayName = 'macOS Keychain'\n\n private readonly itemName: string\n private static readonly ACCOUNT = 'attest-it'\n\n /**\n * Create a new MacOSKeychainKeyProvider.\n * @param options - Provider options\n */\n constructor(options: MacOSKeychainKeyProviderOptions) {\n this.itemName = options.itemName\n }\n\n /**\n * Check if this provider is available.\n * Only available on macOS platforms.\n */\n static isAvailable(): boolean {\n return process.platform === 'darwin'\n }\n\n /**\n * Check if this provider is available on the current system.\n */\n isAvailable(): Promise<boolean> {\n return Promise.resolve(MacOSKeychainKeyProvider.isAvailable())\n }\n\n /**\n * Check if a key exists in the keychain.\n * @param keyRef - Item name in keychain\n */\n async keyExists(keyRef: string): Promise<boolean> {\n try {\n await execCommand('security', [\n 'find-generic-password',\n '-a',\n MacOSKeychainKeyProvider.ACCOUNT,\n '-s',\n keyRef,\n ])\n return true\n } catch {\n return false\n }\n }\n\n /**\n * Get the private key from keychain for signing.\n * Downloads to a temporary file and returns a cleanup function.\n * @param keyRef - Item name in keychain\n * @throws Error if the key does not exist in keychain\n */\n async getPrivateKey(keyRef: string): Promise<KeyRetrievalResult> {\n // Check if key exists first for better error messages\n if (!(await this.keyExists(keyRef))) {\n throw new Error(\n `Key not found in macOS Keychain: \"${keyRef}\" (account: ${MacOSKeychainKeyProvider.ACCOUNT})`,\n )\n }\n\n // Create a temporary file\n const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), 'attest-it-'))\n const tempKeyPath = path.join(tempDir, 'private.pem')\n\n try {\n // Retrieve the base64-encoded key from keychain\n const base64Key = await execCommand('security', [\n 'find-generic-password',\n '-a',\n MacOSKeychainKeyProvider.ACCOUNT,\n '-s',\n keyRef,\n '-w',\n ])\n\n // Decode from base64 and write to temp file\n const keyContent = Buffer.from(base64Key, 'base64').toString('utf8')\n await fs.writeFile(tempKeyPath, keyContent, { mode: 0o600 })\n\n // Set proper permissions\n await setKeyPermissions(tempKeyPath)\n\n return {\n keyPath: tempKeyPath,\n cleanup: async () => {\n // Securely delete the temporary file and directory\n try {\n await fs.unlink(tempKeyPath)\n await fs.rmdir(tempDir)\n } catch (cleanupError) {\n // Log warning for security audit - temporary keys may not have been cleaned up\n console.warn(\n `Warning: Failed to clean up temporary key file at ${tempKeyPath}: ${cleanupError instanceof Error ? cleanupError.message : String(cleanupError)}`,\n )\n }\n },\n }\n } catch (error) {\n // Clean up temp directory on error\n try {\n await fs.rm(tempDir, { recursive: true, force: true })\n } catch (cleanupError) {\n // Log warning for security audit - temporary keys may not have been cleaned up\n console.warn(\n `Warning: Failed to clean up temporary key directory at ${tempDir}: ${cleanupError instanceof Error ? cleanupError.message : String(cleanupError)}`,\n )\n }\n throw error\n }\n }\n\n /**\n * Generate a new keypair and store private key in keychain.\n * Public key is written to filesystem for repository commit.\n * @param options - Key generation options\n */\n async generateKeyPair(options: KeygenProviderOptions): Promise<KeyGenerationResult> {\n const { publicKeyPath, force = false } = options\n\n // Create a temporary directory for key generation\n const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), 'attest-it-keygen-'))\n const tempPrivateKeyPath = path.join(tempDir, 'private.pem')\n\n try {\n // Generate the keypair to temporary location\n await cryptoGenerateKeyPair({\n privatePath: tempPrivateKeyPath,\n publicPath: publicKeyPath,\n force,\n })\n\n // Read the private key and encode as base64\n const privateKeyContent = await fs.readFile(tempPrivateKeyPath, 'utf8')\n const base64Key = Buffer.from(privateKeyContent, 'utf8').toString('base64')\n\n // Store in keychain\n // The -T \"\" flag allows all applications to access the key\n // The -U flag updates if the item already exists\n await execCommand('security', [\n 'add-generic-password',\n '-a',\n MacOSKeychainKeyProvider.ACCOUNT,\n '-s',\n this.itemName,\n '-w',\n base64Key,\n '-T',\n '',\n '-U',\n ])\n\n // Clean up temporary private key\n await fs.unlink(tempPrivateKeyPath)\n await fs.rmdir(tempDir)\n\n return {\n privateKeyRef: this.itemName,\n publicKeyPath,\n storageDescription: `macOS Keychain: ${this.itemName}`,\n }\n } catch (error) {\n // Clean up on error\n try {\n await fs.rm(tempDir, { recursive: true, force: true })\n } catch (cleanupError) {\n // Log warning for security audit - temporary keys may not have been cleaned up\n console.warn(\n `Warning: Failed to clean up temporary key directory at ${tempDir}: ${cleanupError instanceof Error ? cleanupError.message : String(cleanupError)}`,\n )\n }\n throw error\n }\n }\n\n /**\n * Get the configuration for this provider.\n */\n getConfig(): KeyProviderConfig {\n return {\n type: this.type,\n options: {\n itemName: this.itemName,\n },\n }\n }\n}\n\n/**\n * Execute a command and return stdout.\n * @internal\n */\nasync function execCommand(command: string, args: string[]): Promise<string> {\n return new Promise((resolve, reject) => {\n const proc = spawn(command, args, { stdio: ['ignore', 'pipe', 'pipe'] })\n let stdout = ''\n let stderr = ''\n\n proc.stdout.on('data', (data: Buffer) => {\n stdout += data.toString()\n })\n\n proc.stderr.on('data', (data: Buffer) => {\n stderr += data.toString()\n })\n\n proc.on('close', (code) => {\n if (code === 0) {\n resolve(stdout.trim())\n } else {\n reject(new Error(`Command failed with exit code ${String(code)}: ${stderr}`))\n }\n })\n\n proc.on('error', (error) => {\n reject(error)\n })\n })\n}\n","/**\n * Registry for key provider implementations.\n *\n * @remarks\n * The registry maintains a mapping of provider types to factory functions,\n * allowing dynamic creation of key providers based on configuration.\n *\n * @packageDocumentation\n */\n\nimport type { KeyProvider, KeyProviderConfig } from './types.js'\nimport { FilesystemKeyProvider } from './filesystem-provider.js'\nimport { OnePasswordKeyProvider } from './one-password-provider.js'\nimport { MacOSKeychainKeyProvider } from './macos-keychain-provider.js'\n\n/**\n * Type for a key provider factory function.\n * @public\n */\nexport type KeyProviderFactory = (config: KeyProviderConfig) => KeyProvider\n\n/**\n * Registry for key provider implementations.\n *\n * @remarks\n * The registry allows registration of custom key providers and provides\n * a factory method to create provider instances from configuration.\n *\n * Note: This class is used as a namespace for static methods.\n * @public\n */\n// eslint-disable-next-line @typescript-eslint/no-extraneous-class\nexport class KeyProviderRegistry {\n private static providers = new Map<string, KeyProviderFactory>()\n\n /**\n * Register a key provider factory.\n * @param type - Provider type identifier\n * @param factory - Factory function to create provider instances\n */\n static register(type: string, factory: KeyProviderFactory): void {\n this.providers.set(type, factory)\n }\n\n /**\n * Create a key provider from configuration.\n * @param config - Provider configuration\n * @returns A key provider instance\n * @throws Error if the provider type is not registered\n */\n static create(config: KeyProviderConfig): KeyProvider {\n const factory = this.providers.get(config.type)\n if (!factory) {\n throw new Error(\n `Unknown key provider type: ${config.type}. ` +\n `Available types: ${Array.from(this.providers.keys()).join(', ')}`,\n )\n }\n return factory(config)\n }\n\n /**\n * Get all registered provider types.\n * @returns Array of provider type identifiers\n */\n static getProviderTypes(): string[] {\n return Array.from(this.providers.keys())\n }\n}\n\n// Register the filesystem provider by default\nKeyProviderRegistry.register('filesystem', (config) => {\n const privateKeyPath =\n typeof config.options.privateKeyPath === 'string' ? config.options.privateKeyPath : undefined\n\n // Only pass privateKeyPath if it's defined (to satisfy exactOptionalPropertyTypes)\n if (privateKeyPath !== undefined) {\n return new FilesystemKeyProvider({ privateKeyPath })\n }\n return new FilesystemKeyProvider()\n})\n\n// Register the 1Password provider\nKeyProviderRegistry.register('1password', (config) => {\n const { options } = config\n const account = typeof options.account === 'string' ? options.account : undefined\n const vault = typeof options.vault === 'string' ? options.vault : ''\n const itemName = typeof options.itemName === 'string' ? options.itemName : ''\n\n if (!vault || !itemName) {\n throw new Error('1Password provider requires vault and itemName options')\n }\n\n // Only pass account if it's defined (to satisfy exactOptionalPropertyTypes)\n if (account !== undefined) {\n return new OnePasswordKeyProvider({ account, vault, itemName })\n }\n return new OnePasswordKeyProvider({ vault, itemName })\n})\n\n// Register the macOS Keychain provider\nKeyProviderRegistry.register('macos-keychain', (config) => {\n const { options } = config\n const itemName = typeof options.itemName === 'string' ? options.itemName : ''\n\n if (!itemName) {\n throw new Error('macOS Keychain provider requires itemName option')\n }\n\n return new MacOSKeychainKeyProvider({ itemName })\n})\n","/**\n * Configuration loading for local identity system.\n * @packageDocumentation\n */\n\nimport { mkdirSync, readFileSync, writeFileSync } from 'node:fs'\nimport { mkdir as mkdirAsync, readFile, writeFile } from 'node:fs/promises'\nimport { homedir } from 'node:os'\nimport { dirname, join } from 'node:path'\nimport { parse as parseYaml, stringify as stringifyYaml } from 'yaml'\nimport { z } from 'zod'\nimport type { Identity, LocalConfig, PrivateKeyRef } from './types.js'\n\n/**\n * Zod schema for private key references.\n */\nconst privateKeyRefSchema = z.discriminatedUnion('type', [\n z.object({\n type: z.literal('file'),\n path: z.string().min(1, 'File path cannot be empty'),\n }),\n z.object({\n type: z.literal('keychain'),\n service: z.string().min(1, 'Service name cannot be empty'),\n account: z.string().min(1, 'Account name cannot be empty'),\n }),\n z.object({\n type: z.literal('1password'),\n account: z.string().optional(),\n vault: z.string().min(1, 'Vault name cannot be empty'),\n item: z.string().min(1, 'Item name cannot be empty'),\n field: z.string().optional(),\n }),\n])\n\n/**\n * Zod schema for a single identity.\n */\nconst identitySchema = z\n .object({\n name: z.string().min(1, 'Identity name cannot be empty'),\n email: z.string().optional(),\n github: z.string().optional(),\n publicKey: z.string().min(1, 'Public key cannot be empty'),\n privateKey: privateKeyRefSchema,\n })\n .strict()\n\n/**\n * Zod schema for the local config file.\n */\nconst localConfigSchema = z\n .object({\n activeIdentity: z.string().min(1, 'Active identity name cannot be empty'),\n identities: z\n .record(z.string(), identitySchema)\n .refine((identities) => Object.keys(identities).length >= 1, {\n message: 'At least one identity must be defined',\n }),\n })\n .strict()\n\n/**\n * Error thrown when local config validation fails.\n * @public\n */\nexport class LocalConfigValidationError extends Error {\n constructor(\n message: string,\n public readonly issues: z.ZodIssue[],\n ) {\n super(message)\n this.name = 'LocalConfigValidationError'\n }\n}\n\n/**\n * Get the path to the local config file.\n *\n * @returns Path to ~/.config/attest-it/config.yaml\n * @public\n */\nexport function getLocalConfigPath(): string {\n const home = homedir()\n return join(home, '.config', 'attest-it', 'config.yaml')\n}\n\n/**\n * Parse and validate local config content.\n *\n * @param content - YAML content to parse\n * @returns Validated LocalConfig object\n * @throws {LocalConfigValidationError} If validation fails\n */\nfunction parseLocalConfigContent(content: string): LocalConfig {\n let rawConfig: unknown\n\n try {\n rawConfig = parseYaml(content)\n } catch (error) {\n throw new LocalConfigValidationError(\n `Failed to parse YAML: ${error instanceof Error ? error.message : String(error)}`,\n [],\n )\n }\n\n const result = localConfigSchema.safeParse(rawConfig)\n\n if (!result.success) {\n throw new LocalConfigValidationError(\n 'Local configuration validation failed:\\n' +\n result.error.issues\n .map((issue) => ` - ${issue.path.join('.')}: ${issue.message}`)\n .join('\\n'),\n result.error.issues,\n )\n }\n\n // Transform Zod output to match LocalConfig interface by removing undefined values\n const identities: Record<string, Identity> = Object.fromEntries(\n Object.entries(result.data.identities).map(([key, identity]) => {\n // Transform private key ref to remove undefined optional fields\n let privateKey: PrivateKeyRef\n if (identity.privateKey.type === '1password') {\n privateKey = {\n type: '1password',\n vault: identity.privateKey.vault,\n item: identity.privateKey.item,\n ...(identity.privateKey.account !== undefined && {\n account: identity.privateKey.account,\n }),\n ...(identity.privateKey.field !== undefined && { field: identity.privateKey.field }),\n }\n } else {\n privateKey = identity.privateKey\n }\n\n return [\n key,\n {\n name: identity.name,\n publicKey: identity.publicKey,\n privateKey,\n ...(identity.email !== undefined && { email: identity.email }),\n ...(identity.github !== undefined && { github: identity.github }),\n },\n ]\n }),\n )\n\n return {\n activeIdentity: result.data.activeIdentity,\n identities,\n }\n}\n\n/**\n * Load and validate local config from file (async).\n *\n * @param configPath - Optional path to config file. If not provided, uses default location.\n * @returns Validated LocalConfig object, or null if file does not exist\n * @throws {LocalConfigValidationError} If validation fails\n * @public\n */\nexport async function loadLocalConfig(configPath?: string): Promise<LocalConfig | null> {\n const resolvedPath = configPath ?? getLocalConfigPath()\n\n try {\n const content = await readFile(resolvedPath, 'utf8')\n return parseLocalConfigContent(content)\n } catch (error) {\n if (error instanceof LocalConfigValidationError) {\n throw error\n }\n // Check if it's a file not found error\n if (\n error &&\n typeof error === 'object' &&\n 'code' in error &&\n (error.code === 'ENOENT' || error.code === 'ENOTDIR')\n ) {\n return null\n }\n // Re-throw other errors\n throw error\n }\n}\n\n/**\n * Load and validate local config from file (sync).\n *\n * @param configPath - Optional path to config file. If not provided, uses default location.\n * @returns Validated LocalConfig object, or null if file does not exist\n * @throws {LocalConfigValidationError} If validation fails\n * @public\n */\nexport function loadLocalConfigSync(configPath?: string): LocalConfig | null {\n const resolvedPath = configPath ?? getLocalConfigPath()\n\n try {\n const content = readFileSync(resolvedPath, 'utf8')\n return parseLocalConfigContent(content)\n } catch (error) {\n if (error instanceof LocalConfigValidationError) {\n throw error\n }\n // Check if it's a file not found error\n if (\n error &&\n typeof error === 'object' &&\n 'code' in error &&\n (error.code === 'ENOENT' || error.code === 'ENOTDIR')\n ) {\n return null\n }\n // Re-throw other errors\n throw error\n }\n}\n\n/**\n * Save local config to file (async).\n *\n * @param config - LocalConfig object to save\n * @param configPath - Optional path to config file. If not provided, uses default location.\n * @throws {Error} If write fails\n * @public\n */\nexport async function saveLocalConfig(config: LocalConfig, configPath?: string): Promise<void> {\n const resolvedPath = configPath ?? getLocalConfigPath()\n const content = stringifyYaml(config)\n\n // Ensure parent directory exists\n const dir = dirname(resolvedPath)\n await mkdirAsync(dir, { recursive: true })\n\n await writeFile(resolvedPath, content, 'utf8')\n}\n\n/**\n * Save local config to file (sync).\n *\n * @param config - LocalConfig object to save\n * @param configPath - Optional path to config file. If not provided, uses default location.\n * @throws {Error} If write fails\n * @public\n */\nexport function saveLocalConfigSync(config: LocalConfig, configPath?: string): void {\n const resolvedPath = configPath ?? getLocalConfigPath()\n const content = stringifyYaml(config)\n\n // Ensure parent directory exists\n const dir = dirname(resolvedPath)\n mkdirSync(dir, { recursive: true })\n\n writeFileSync(resolvedPath, content, 'utf8')\n}\n\n/**\n * Get the active identity from a config.\n *\n * @param config - LocalConfig object\n * @returns The active Identity, or undefined if not found\n * @public\n */\nexport function getActiveIdentity(config: LocalConfig): Identity | undefined {\n return config.identities[config.activeIdentity]\n}\n","/**\n * Authorization logic for attest-it v2.0.\n * @packageDocumentation\n */\n\nimport ms from 'ms'\n\nimport type { AttestItConfig, GateConfig, TeamMember } from './types.js'\n\n/**\n * Check if a public key belongs to an authorized signer for a gate.\n *\n * @param config - The attest-it configuration\n * @param gateId - The gate identifier (slug)\n * @param publicKey - Base64-encoded Ed25519 public key to check\n * @returns true if the public key belongs to an authorized signer for the gate\n * @public\n */\nexport function isAuthorizedSigner(\n config: AttestItConfig,\n gateId: string,\n publicKey: string,\n): boolean {\n // eslint-disable-next-line security/detect-object-injection\n const gate = config.gates?.[gateId]\n if (!gate) {\n return false\n }\n\n const teamMember = findTeamMemberByPublicKey(config, publicKey)\n if (!teamMember) {\n return false\n }\n\n // Find the slug for this team member\n const teamMemberSlug = findTeamMemberSlug(config, teamMember)\n if (!teamMemberSlug) {\n return false\n }\n\n return gate.authorizedSigners.includes(teamMemberSlug)\n}\n\n/**\n * Get all team members authorized to sign for a gate.\n *\n * @param config - The attest-it configuration\n * @param gateId - The gate identifier (slug)\n * @returns Array of authorized team members, or empty array if gate not found\n * @public\n */\nexport function getAuthorizedSignersForGate(config: AttestItConfig, gateId: string): TeamMember[] {\n // eslint-disable-next-line security/detect-object-injection\n const gate = config.gates?.[gateId]\n if (!gate || !config.team) {\n return []\n }\n\n const authorizedMembers: TeamMember[] = []\n for (const signerSlug of gate.authorizedSigners) {\n // eslint-disable-next-line security/detect-object-injection\n const member = config.team[signerSlug]\n if (member) {\n authorizedMembers.push(member)\n }\n }\n\n return authorizedMembers\n}\n\n/**\n * Find a team member by their public key.\n *\n * @param config - The attest-it configuration\n * @param publicKey - Base64-encoded Ed25519 public key\n * @returns The team member with matching public key, or undefined if not found\n * @public\n */\nexport function findTeamMemberByPublicKey(\n config: AttestItConfig,\n publicKey: string,\n): TeamMember | undefined {\n if (!config.team) {\n return undefined\n }\n\n for (const member of Object.values(config.team)) {\n if (member.publicKey === publicKey) {\n return member\n }\n }\n\n return undefined\n}\n\n/**\n * Find the slug for a team member.\n *\n * @param config - The attest-it configuration\n * @param teamMember - The team member to find the slug for\n * @returns The team member slug, or undefined if not found\n */\nfunction findTeamMemberSlug(config: AttestItConfig, teamMember: TeamMember): string | undefined {\n if (!config.team) {\n return undefined\n }\n\n for (const [slug, member] of Object.entries(config.team)) {\n if (member === teamMember || member.publicKey === teamMember.publicKey) {\n return slug\n }\n }\n\n return undefined\n}\n\n/**\n * Get the gate configuration for a given gate ID.\n *\n * @param config - The attest-it configuration\n * @param gateId - The gate identifier (slug)\n * @returns The gate configuration, or undefined if not found\n * @public\n */\nexport function getGate(config: AttestItConfig, gateId: string): GateConfig | undefined {\n // eslint-disable-next-line security/detect-object-injection\n return config.gates?.[gateId]\n}\n\n/**\n * Regular expression pattern for valid duration strings.\n * Matches formats like \"30d\", \"7d\", \"24h\", \"1w\", \"2y\", \"100ms\", etc.\n * Negative durations are not supported.\n * @internal\n */\nconst DURATION_PATTERN = /^\\d+(\\.\\d+)?\\s*(ms|s|m|h|d|w|y)$/i\n\n/**\n * Type guard to check if a string is a valid duration format.\n *\n * @param value - String to check\n * @returns true if the string matches the duration pattern\n * @internal\n */\nfunction isValidDurationFormat(value: string): boolean {\n return DURATION_PATTERN.test(value.trim())\n}\n\n/**\n * Parse a duration string to milliseconds.\n * Uses the ms library to parse strings like \"30d\", \"7d\", \"24h\".\n *\n * @param duration - Duration string (e.g., \"30d\", \"7d\", \"24h\")\n * @returns Duration in milliseconds\n * @throws {Error} If duration string is invalid\n * @public\n */\nexport function parseDuration(duration: string): number {\n // Validate format before calling ms to avoid type assertion issues\n if (!isValidDurationFormat(duration)) {\n throw new Error(`Invalid duration string: ${duration}`)\n }\n\n // The ms function accepts the StringValue type which is a union of specific string patterns\n // After validating the format, we can safely call ms\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- safe after format validation\n const result = ms(duration as Parameters<typeof ms>[0])\n if (typeof result !== 'number' || result <= 0) {\n throw new Error(`Invalid duration string: ${duration}`)\n }\n return result\n}\n","/**\n * Seal operations for creating, verifying, and managing seals.\n * @packageDocumentation\n */\n\nimport * as fs from 'node:fs'\nimport * as path from 'node:path'\nimport { z } from 'zod'\n\nimport * as ed25519 from '../crypto/ed25519.js'\nimport type { AttestItConfig } from '../types.js'\nimport type { Seal, SealsFile } from './types.js'\n\n/**\n * Zod schema for a single seal.\n * @internal\n */\nconst sealSchema = z.object({\n gateId: z.string().min(1, 'Gate ID cannot be empty'),\n // Fingerprint format: sha256:<hex> where hex is at least 1 character\n // Full fingerprints are 64 hex chars, but tests may use shorter values\n fingerprint: z\n .string()\n .regex(/^sha256:[a-f0-9]+$/i, 'Invalid fingerprint format (expected sha256:<hex>)'),\n timestamp: z.string().datetime({ message: 'Invalid ISO 8601 timestamp' }),\n sealedBy: z.string().min(1, 'Signer slug cannot be empty'),\n signature: z.string().min(1, 'Signature cannot be empty'),\n})\n\n/**\n * Zod schema for the seals file.\n * @internal\n */\nconst sealsFileSchema = z.object({\n version: z.literal(1, { errorMap: () => ({ message: 'Unsupported seals file version' }) }),\n seals: z.record(z.string(), sealSchema),\n})\n\n/**\n * Options for creating a seal.\n * @public\n */\nexport interface CreateSealOptions {\n /** Gate identifier (slug) */\n gateId: string\n /** SHA-256 fingerprint of the gate's content */\n fingerprint: string\n /** Team member slug creating the seal */\n sealedBy: string\n /** PEM-encoded Ed25519 private key for signing */\n privateKey: string\n}\n\n/**\n * Result of seal signature verification.\n * @public\n */\nexport interface SignatureVerificationResult {\n /** Whether the seal signature is valid */\n valid: boolean\n /** Error message if verification failed */\n error?: string\n}\n\n/**\n * Create a seal by signing the canonical string: gateId:fingerprint:timestamp\n *\n * @param options - Seal creation options\n * @returns The created seal\n * @throws Error if signing fails\n * @public\n */\nexport function createSeal(options: CreateSealOptions): Seal {\n const { gateId, fingerprint, sealedBy, privateKey } = options\n\n // Create ISO 8601 timestamp\n const timestamp = new Date().toISOString()\n\n // Create canonical string to sign\n const canonicalString = `${gateId}:${fingerprint}:${timestamp}`\n\n // Sign the canonical string\n const signature = ed25519.sign(canonicalString, privateKey)\n\n return {\n gateId,\n fingerprint,\n timestamp,\n sealedBy,\n signature,\n }\n}\n\n/**\n * Verify a seal's signature against the team member's public key.\n *\n * @param seal - The seal to verify\n * @param config - The attest-it configuration containing team members\n * @returns Verification result with success status and optional error message\n * @public\n */\nexport function verifySeal(seal: Seal, config: AttestItConfig): SignatureVerificationResult {\n const { gateId, fingerprint, timestamp, sealedBy, signature } = seal\n\n // Look up team member by slug\n if (!config.team) {\n return {\n valid: false,\n error: `No team configuration found`,\n }\n }\n\n // eslint-disable-next-line security/detect-object-injection\n const teamMember = config.team[sealedBy]\n if (!teamMember) {\n return {\n valid: false,\n error: `Team member '${sealedBy}' not found in configuration`,\n }\n }\n\n // Reconstruct canonical string\n const canonicalString = `${gateId}:${fingerprint}:${timestamp}`\n\n // Verify signature\n try {\n const isValid = ed25519.verify(canonicalString, signature, teamMember.publicKey)\n if (!isValid) {\n return {\n valid: false,\n error: 'Signature verification failed',\n }\n }\n\n return { valid: true }\n } catch (error) {\n return {\n valid: false,\n error: `Signature verification error: ${error instanceof Error ? error.message : String(error)}`,\n }\n }\n}\n\n/**\n * Parse and validate seals file content.\n *\n * @param content - JSON content to parse\n * @returns Validated SealsFile\n * @throws Error if validation fails\n * @internal\n */\nfunction parseSealsContent(content: string): SealsFile {\n let rawData: unknown\n try {\n rawData = JSON.parse(content)\n } catch (error) {\n throw new Error(`Invalid JSON: ${error instanceof Error ? error.message : String(error)}`)\n }\n\n const result = sealsFileSchema.safeParse(rawData)\n if (!result.success) {\n const issues = result.error.issues\n .map((issue) => ` - ${issue.path.join('.')}: ${issue.message}`)\n .join('\\n')\n throw new Error(`Invalid seals file:\\n${issues}`)\n }\n\n return result.data\n}\n\n/**\n * Read seals from the seals.json file (async).\n *\n * @param dir - Directory containing .attest-it/seals.json\n * @returns The seals file contents, or an empty seals file if the file doesn't exist\n * @throws Error if file exists but cannot be read or parsed\n * @public\n */\nexport async function readSeals(dir: string): Promise<SealsFile> {\n const sealsPath = path.join(dir, '.attest-it', 'seals.json')\n\n try {\n const content = await fs.promises.readFile(sealsPath, 'utf8')\n return parseSealsContent(content)\n } catch (error) {\n // If file doesn't exist, return empty seals file\n if (error instanceof Error && 'code' in error && error.code === 'ENOENT') {\n return {\n version: 1,\n seals: {},\n }\n }\n\n // Re-throw other errors (permission denied, parse errors, etc.)\n throw new Error(\n `Failed to read seals file: ${error instanceof Error ? error.message : String(error)}`,\n )\n }\n}\n\n/**\n * Read seals from the seals.json file (sync).\n *\n * @param dir - Directory containing .attest-it/seals.json\n * @returns The seals file contents, or an empty seals file if the file doesn't exist\n * @throws Error if file exists but cannot be read or parsed\n * @public\n */\nexport function readSealsSync(dir: string): SealsFile {\n const sealsPath = path.join(dir, '.attest-it', 'seals.json')\n\n try {\n const content = fs.readFileSync(sealsPath, 'utf8')\n return parseSealsContent(content)\n } catch (error) {\n // If file doesn't exist, return empty seals file\n if (error instanceof Error && 'code' in error && error.code === 'ENOENT') {\n return {\n version: 1,\n seals: {},\n }\n }\n\n // Re-throw other errors (permission denied, parse errors, etc.)\n throw new Error(\n `Failed to read seals file: ${error instanceof Error ? error.message : String(error)}`,\n )\n }\n}\n\n/**\n * Write seals to the seals.json file (async).\n *\n * @param dir - Directory containing .attest-it/seals.json\n * @param sealsFile - The seals file to write\n * @throws Error if file cannot be written\n * @public\n */\nexport async function writeSeals(dir: string, sealsFile: SealsFile): Promise<void> {\n const attestItDir = path.join(dir, '.attest-it')\n const sealsPath = path.join(attestItDir, 'seals.json')\n\n try {\n // Ensure .attest-it directory exists\n await fs.promises.mkdir(attestItDir, { recursive: true })\n\n // Write seals file with pretty formatting\n const content = JSON.stringify(sealsFile, null, 2) + '\\n'\n await fs.promises.writeFile(sealsPath, content, 'utf8')\n } catch (error) {\n throw new Error(\n `Failed to write seals file: ${error instanceof Error ? error.message : String(error)}`,\n )\n }\n}\n\n/**\n * Write seals to the seals.json file (sync).\n *\n * @param dir - Directory containing .attest-it/seals.json\n * @param sealsFile - The seals file to write\n * @throws Error if file cannot be written\n * @public\n */\nexport function writeSealsSync(dir: string, sealsFile: SealsFile): void {\n const attestItDir = path.join(dir, '.attest-it')\n const sealsPath = path.join(attestItDir, 'seals.json')\n\n try {\n // Ensure .attest-it directory exists\n fs.mkdirSync(attestItDir, { recursive: true })\n\n // Write seals file with pretty formatting\n const content = JSON.stringify(sealsFile, null, 2) + '\\n'\n fs.writeFileSync(sealsPath, content, 'utf8')\n } catch (error) {\n throw new Error(\n `Failed to write seals file: ${error instanceof Error ? error.message : String(error)}`,\n )\n }\n}\n","/**\n * Seal verification logic and states.\n * @packageDocumentation\n */\n\nimport { parseDuration, getGate, isAuthorizedSigner } from '../authorization.js'\nimport type { AttestItConfig } from '../types.js'\nimport type { Seal, SealsFile } from './types.js'\nimport { verifySeal } from './operations.js'\n\n/**\n * Verification state for a gate's seal.\n * @public\n */\nexport type VerificationState =\n | 'VALID' // Seal exists, signature valid, not stale, fingerprint matches\n | 'MISSING' // No seal for this gate\n | 'STALE' // Seal exists but exceeds maxAge\n | 'FINGERPRINT_MISMATCH' // Seal fingerprint doesn't match current fingerprint\n | 'INVALID_SIGNATURE' // Signature doesn't verify\n | 'UNKNOWN_SIGNER' // sealedBy not in team or not authorized for this gate\n\n/**\n * Result of verifying a single gate's seal.\n * @public\n */\nexport interface SealVerificationResult {\n /** Gate identifier */\n gateId: string\n /** Verification state */\n state: VerificationState\n /** The seal, if one exists */\n seal?: Seal\n /** Human-readable message explaining the state */\n message?: string\n}\n\n/**\n * Verify a single gate's seal.\n *\n * @param config - The attest-it configuration\n * @param gateId - Gate identifier to verify\n * @param seals - The seals file containing all seals\n * @param currentFingerprint - Current computed fingerprint for the gate\n * @returns Verification result for the gate\n * @public\n */\nexport function verifyGateSeal(\n config: AttestItConfig,\n gateId: string,\n seals: SealsFile,\n currentFingerprint: string,\n): SealVerificationResult {\n // Get the gate configuration\n const gate = getGate(config, gateId)\n if (!gate) {\n return {\n gateId,\n state: 'MISSING',\n message: `Gate '${gateId}' not found in configuration`,\n }\n }\n\n // Check if a seal exists for this gate\n // eslint-disable-next-line security/detect-object-injection\n const seal = seals.seals[gateId]\n if (!seal) {\n return {\n gateId,\n state: 'MISSING',\n message: `No seal found for gate '${gateId}'`,\n }\n }\n\n // Check if fingerprint matches\n if (seal.fingerprint !== currentFingerprint) {\n return {\n gateId,\n state: 'FINGERPRINT_MISMATCH',\n seal,\n message: `Fingerprint changed since seal was created`,\n }\n }\n\n // Check if signer is in team and authorized\n if (!config.team) {\n return {\n gateId,\n state: 'UNKNOWN_SIGNER',\n seal,\n message: `No team configuration found`,\n }\n }\n\n const teamMember = config.team[seal.sealedBy]\n if (!teamMember) {\n return {\n gateId,\n state: 'UNKNOWN_SIGNER',\n seal,\n message: `Signer '${seal.sealedBy}' not found in team`,\n }\n }\n\n // Check if signer is authorized for this gate\n const authorized = isAuthorizedSigner(config, gateId, teamMember.publicKey)\n if (!authorized) {\n return {\n gateId,\n state: 'UNKNOWN_SIGNER',\n seal,\n message: `Signer '${seal.sealedBy}' is not authorized for gate '${gateId}'`,\n }\n }\n\n // Verify signature\n const verificationResult = verifySeal(seal, config)\n if (!verificationResult.valid) {\n return {\n gateId,\n state: 'INVALID_SIGNATURE',\n seal,\n message: verificationResult.error ?? 'Signature verification failed',\n }\n }\n\n // Check if seal is stale (exceeds maxAge)\n try {\n const maxAgeMs = parseDuration(gate.maxAge)\n const sealTimestamp = new Date(seal.timestamp).getTime()\n const now = Date.now()\n const ageMs = now - sealTimestamp\n\n if (ageMs > maxAgeMs) {\n const ageDays = Math.floor(ageMs / (1000 * 60 * 60 * 24))\n const maxAgeDays = Math.floor(maxAgeMs / (1000 * 60 * 60 * 24))\n return {\n gateId,\n state: 'STALE',\n seal,\n message: `Seal is ${ageDays.toString()} days old, exceeds maxAge of ${maxAgeDays.toString()} days`,\n }\n }\n } catch (error) {\n // If we can't parse maxAge, fail closed - treat as stale to enforce freshness\n // This prevents bypassing staleness checks with invalid maxAge values\n return {\n gateId,\n state: 'STALE',\n seal,\n message: `Cannot verify freshness: invalid maxAge format: ${error instanceof Error ? error.message : String(error)}`,\n }\n }\n\n // All checks passed\n return {\n gateId,\n state: 'VALID',\n seal,\n }\n}\n\n/**\n * Verify all gates' seals.\n *\n * @param config - The attest-it configuration\n * @param seals - The seals file containing all seals\n * @param fingerprints - Map of gate IDs to their current fingerprints\n * @returns Array of verification results for all gates\n * @public\n */\nexport function verifyAllSeals(\n config: AttestItConfig,\n seals: SealsFile,\n fingerprints: Record<string, string>,\n): SealVerificationResult[] {\n if (!config.gates) {\n return []\n }\n\n const results: SealVerificationResult[] = []\n\n for (const gateId of Object.keys(config.gates)) {\n // eslint-disable-next-line security/detect-object-injection\n const fingerprint = fingerprints[gateId]\n if (!fingerprint) {\n results.push({\n gateId,\n state: 'MISSING',\n message: `No fingerprint computed for gate '${gateId}'`,\n })\n continue\n }\n\n const result = verifyGateSeal(config, gateId, seals, fingerprint)\n results.push(result)\n }\n\n return results\n}\n"]}
|