All files / core audit.ts

100% Statements 15/15
100% Branches 0/0
100% Functions 1/1
100% Lines 15/15

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54      1x 1x 1x 1x                             1x 1x             1x 21x               21x 21x 19x     19x 18x 18x   18x            
// Copyright 2026 ForgeKit Contributors
// SPDX-License-Identifier: Apache-2.0
// https://github.com/SubhanshuMG/ForgeKit
import * as fs from 'fs-extra';
import * as nativeFs from 'fs';
import * as path from 'path';
import * as os from 'os';
 
export interface AuditEntry {
  timestamp: string;
  command: string;
  templateId?: string;
  projectName?: string;
  outputDir?: string;
  result: 'success' | 'failure' | 'cancelled';
  error?: string;
  forgeKitVersion: string;
  nodeVersion: string;
  platform: string;
}
 
const AUDIT_LOG_PATH = path.join(os.homedir(), '.forgekit', 'audit.log');
const VERSION = '0.4.0';
 
/**
 * Logs a CLI action to the local audit log.
 * The audit log is stored locally on the user's machine only.
 * No data is sent to external servers.
 */
export async function logAuditEntry(entry: Omit<AuditEntry, 'timestamp' | 'forgeKitVersion' | 'nodeVersion' | 'platform'>): Promise<void> {
  const fullEntry: AuditEntry = {
    ...entry,
    timestamp: new Date().toISOString(),
    forgeKitVersion: VERSION,
    nodeVersion: process.version,
    platform: os.platform(),
  };
 
  try {
    await fs.ensureDir(path.dirname(AUDIT_LOG_PATH));
    const line = JSON.stringify(fullEntry) + '\n';
    // Use owner-only permissions (0o600) to protect audit log contents
    // from other local users. Open with append mode and restrictive perms.
    const fd = nativeFs.openSync(AUDIT_LOG_PATH, 'a', 0o600);
    try {
      nativeFs.writeSync(fd, line);
    } finally {
      nativeFs.closeSync(fd);
    }
  } catch {
    // Audit log failure is non-fatal, never block the user's workflow
  }
}