import fs from 'fs-extra'; import path from 'node:path'; import { createHash, randomUUID } from 'node:crypto'; import type { AxiosInstance } from 'axios'; import { getCustomerProfile } from '../api.js'; export const EVIDENCE_SCHEMA_VERSION = 'newo.evidence/v1' as const; export type EvidenceState = | 'PASS' | 'FAIL' | 'INCONCLUSIVE' | 'SUCCEEDED' | 'FAILED' | 'PARTIAL'; export type FaultOwner = 'client' | 'platform' | 'harness' | 'product' | 'unknown'; export interface EvidenceLocator { kind: string; path?: string; sha256?: string; media_type?: string; row_count?: number; identifiers?: Record; } export interface SideEffectRecord { kind: string; locator: Record; state: 'created' | 'updated' | 'completed' | 'residual' | 'unknown'; cleanup: { owner: 'caller' | 'platform' | 'harness' | 'unsupported' | 'none'; supported: boolean; state: 'not_required' | 'pending' | 'completed' | 'unsupported' | 'unknown'; }; } export interface EvidenceEnvelope> { schema_version: typeof EVIDENCE_SCHEMA_VERSION; result_kind: string; run_id: string; execution_id?: string; account?: Record; environment?: Record; phase: string; state: EvidenceState; fault_owner: FaultOwner | null; retryable: boolean | null; fault_message?: string; evidence: EvidenceLocator[]; side_effects: SideEffectRecord[]; cleanup_owner: 'caller' | 'platform' | 'harness' | 'unsupported' | 'none'; timestamps: { started_at: string; completed_at: string; }; limitations: string[]; details: TDetails; } export function createRunId(): string { return randomUUID(); } export function sha256Bytes(value: string | Buffer): string { return createHash('sha256').update(value).digest('hex'); } export interface ManifestAccountIdentity { account: Record; limitations: string[]; } /** Resolve the authenticated customer only when a manifest is requested. */ export async function resolveManifestAccount( client: AxiosInstance, customerAlias: string ): Promise { try { const profile = await getCustomerProfile(client); const customerIdn = typeof profile.idn === 'string' ? profile.idn.trim() : ''; if (customerIdn) { return { account: { customer_idn: customerIdn, ...(customerAlias !== customerIdn ? { customer_alias: customerAlias } : {}) }, limitations: [] }; } } catch { // A manifest remains useful when profile readback is unavailable, but the // configured selector must not be mislabeled as a platform customer IDN. } return { account: { customer_alias: customerAlias }, limitations: [ 'The authenticated customer profile could not be resolved; account.customer_alias is the local selector, not an attested platform customer IDN.' ] }; } export async function writeJsonFile(filePath: string, value: unknown): Promise { const absolutePath = path.resolve(filePath); await fs.ensureDir(path.dirname(absolutePath)); await fs.writeFile(absolutePath, `${JSON.stringify(value, null, 2)}\n`, 'utf8'); }