import { readFile } from 'node:fs/promises'; import { client, call, inventory, transfer, contract, verifyManifest, atomicJson, cleanupProbe } from './s3.mjs'; // Secrets enter through a root-only mounted JSON file, never through argv or logs. const [command, configPath = '/config/job.json'] = process.argv.slice(2); if (command === 'contract') process.env.AWS_REQUEST_CHECKSUM_CALCULATION = 'WHEN_REQUIRED'; let source, target; try { const config = JSON.parse(await readFile(configPath, 'utf8')); source = config.source && client(config.source); target = config.target && client(config.target); const bucket = config.bucket; let result; if (command === 'inventory') result = await inventory(source, bucket); else if (command === 'copy' || command === 'verify') { result = await transfer(source, target, bucket, config.directory || '/work', { verifyOnly: command === 'verify' }); result = { ...result, objects: undefined }; } else if (command === 'init') { try { await call(target, 'HeadBucket', { Bucket: bucket }); } catch (error) { if (error.$metadata?.httpStatusCode !== 404) throw error; await call(target, 'CreateBucket', { Bucket: bucket }); } result = { bucket, initialized: true }; } else if (command === 'contract') result = await contract(target, config.target, bucket, { ...config, probePath: '/work/probe.json' }); else if (command === 'cleanup-probe') { await cleanupProbe(target, bucket, '/work/probe.json'); result = { cleaned: true }; } else if (command === 'restore-verify') { result = await verifyManifest(target, bucket, JSON.parse(await readFile(config.manifest || '/work/verified.json', 'utf8'))); } else throw new Error('Unbekannter Befehl.'); await atomicJson(config.result || '/work/result.json', result); console.log(JSON.stringify(command === 'inventory' ? { count: result.count, bytes: result.bytes } : result)); } catch (error) { // SDK error messages/URLs may contain identifiers; keep public output bounded. const detail = { error: error.name, code: error.code, status: error.$metadata?.httpStatusCode, message: error.$metadata ? 'S3-Prüfung fehlgeschlagen; Zugriff/Konfiguration prüfen.' : error.message }; try { await atomicJson('/work/error.json', detail); } catch { /* Preserve the original error. */ } console.error(JSON.stringify(detail)); process.exitCode = 1; } finally { source?.destroy(); target?.destroy(); }