// Opt-in live acceptance observer/submission. Never starts a host, selects a mode, // approves a PRD, creates a service resource, or substitutes a scripted role. import { readFileSync, writeFileSync, mkdirSync, lstatSync } from 'node:fs'; import { dirname, isAbsolute, join, resolve, relative } from 'node:path'; import { pathToFileURL } from 'node:url'; import { createHash, randomUUID } from 'node:crypto'; import { loadSystem, bootConfig, rolesDir } from '../src/config.mjs'; import { loadBusiness } from '../../organization/src/index.mjs'; import { readHostState } from '../src/host.mjs'; import { humanTransport, refuseInsideAgent } from '../src/transport.mjs'; import { staffFor } from '../../bus/src/request-host.mjs'; const fail = message => { throw new Error(message); }; export function parseOptions(argv) { const result = {}; const flags = { '--authorize-isolated-run': 'authorized', '--submit': 'submit' }; const values = { '--instance':'instance', '--evidence':'evidence', '--config':'config', '--business':'business', '--owner':'owner', '--request-file':'requestFile', '--request':'request', '--thread':'thread', '--artifact':'artifact', '--timeout-ms':'timeout' }; for (let n = 0; n < argv.length; n++) { const key = flags[argv[n]] ?? values[argv[n]]; if (!key || key in result) fail('unknown or duplicate option'); result[key] = argv[n] in flags ? true : argv[++n]; if (result[key] === undefined) fail('missing option value'); } if (!/^[a-z][a-z0-9]{1,15}$/.test(result.instance ?? '') || ['dev','prod','production'].includes(result.instance)) fail('explicit named isolated --instance required'); if (!result.authorized) fail('explicit owner authorization --authorize-isolated-run required'); for (const key of ['config','evidence','requestFile']) if (!isAbsolute(result[key] ?? '')) fail('explicit absolute --' + key + ' required'); if (!result.business || !result.owner) fail('explicit business and expected owner required'); if (result.submit && (!result.thread || result.request)) fail('--submit requires an existing owner --thread and no --request'); result.timeout = result.timeout === undefined ? 300000 : Number(result.timeout); if (!Number.isSafeInteger(result.timeout) || result.timeout < 1000 || result.timeout > 3600000) fail('timeout must be 1000..3600000 ms'); return result; } export function checkResources({ options, system, business, marker, host, tracker }) { if (system.environment !== 'development') fail('isolated development instance required'); if (marker?.instanceVersion !== 1 || marker.name !== options.instance) fail('instance marker mismatch'); if (business.id !== options.business || business.human !== options.owner) fail('owner/business mismatch'); if (!host?.live || (host.business && host.business !== business.id)) fail('configured live host required; runner does not start one'); if (!Number.isSafeInteger(tracker?.project) || tracker.project < 1) fail('tracker-install: declared installed tracker root required'); const pms = Object.keys(business.roles).filter(r => business.roles[r].definition === 'pm'); if (pms.length !== 1 || !staffFor(business, pms[0])) fail('configured PM, independent technical arbiter, chief, coder and reviewer staff required'); if (!Object.values(business.projects).some(p => p.kind !== 'library')) fail('declared factory source project required'); } function json(file) { const stat = lstatSync(file); if (!stat.isFile() || stat.isSymbolicLink() || stat.size > 1024 * 1024) fail('bounded regular input required'); return JSON.parse(readFileSync(file, 'utf8')); } export async function main(argv, env = process.env) { const options = parseOptions(argv); refuseInsideAgent(env); // --owner is an expectation, never authentication or a capability. const selected = { ...env, MOSAIC_CONFIG: options.config }; const system = loadSystem({ env: selected }), config = bootConfig({ system, businessId: options.business, env: selected }); const business = loadBusiness(options.business, { dir: dirname(options.config), rolesDir: rolesDir(selected) }); const host = readHostState(system.dataRoot); checkResources({ options, system, business, marker: json(join(system.dataRoot, 'instance.json')), host, tracker: config.trackers?.[options.business] }); for (const [name, role] of Object.entries(business.roles)) { if (!role.vars?.harness || !role.vars?.model || !role.vars?.thinking) fail('model route missing for ' + name); } const source = json(options.requestFile); if (typeof source.text !== 'string' || !source.text || source.provenance?.raw_runtime_event_exported !== false || createHash('sha256').update(source.text).digest('hex') !== source.source_sha256) fail('verified owner-supplied original request quotation required'); const call = humanTransport({ socket: host.socket ?? join(system.dataRoot, 'bus/broker.sock'), business: business.id, env: selected }); await call('instances'); // Existing owner process proof succeeds before any submission. const credentials = await call('credentials'); if (Array.isArray(credentials) && credentials.some(c => c.service === 'vikunja' && !['valid','ready'].includes(c.state))) fail('tracker credential setup wait; inspect Console credentials'); const rel = relative(system.dataRoot, resolve(options.evidence)); if (rel === '' || (!rel.startsWith('..') && !isAbsolute(rel))) fail('evidence output must be outside the instance data root'); mkdirSync(options.evidence, { recursive: true, mode: 0o700 }); if (!lstatSync(options.evidence).isDirectory() || lstatSync(options.evidence).isSymbolicLink()) fail('plain evidence output directory required'); const record = (kind, value) => { const file = join(options.evidence, `${kind}-${randomUUID()}.json`); writeFileSync(file, JSON.stringify(value, null, 2) + '\n', { flag: 'wx', mode: 0o600 }); return file; }; record('preflight', { instance: options.instance, business: business.id, owner: business.human, source, qualification: 'Owner-supplied incident quote; new runtime submission IDs are recorded separately. Fixture success is not live model acceptance.' }); let request = options.request; if (options.submit) { const threads = await call('thread.list'); if (!threads.some(t => t.id === options.thread)) fail('the explicitly selected thread is not owned by this user'); const sent = await call('thread.send', { thread: options.thread, body: source.text }); request = sent.request; record('submission', { request, message: sent.id, original: { source_event: source.source_event, source_message: source.source_message, source_sha256: source.source_sha256 } }); process.stdout.write(`Request ${request}. Select and confirm the exact plan in the signed-in Console.\n`); } if (!request) fail('--submit or an existing --request is required'); const end = Date.now() + options.timeout; let state, revision = null; while (Date.now() < end) { try { state = await call('request.get', { request }); } catch (e) { if (e.code !== 'request-not-found') throw e; } if (state && state.revision !== revision) { record('request', state); revision = state.revision; } if (state?.phase === 'cancelled') fail('request cancelled; receipts retained'); if (state?.phase === 'complete' && state.delivery_evidence) break; await new Promise(resolve => setTimeout(resolve, 500)); } if (!state?.delivery_evidence || state.phase !== 'complete') fail('live acceptance incomplete: exact current wait is retained in request evidence'); const delivery = state.delivery_evidence; const trails = []; for (const subject of [request, state.source_message, ...state.tasks, delivery.review_request, delivery.verdict]) trails.push({ subject, rows: await call('trail', { subject }) }); record('delivery', { state, trails, verified_local_delivery_only: true }); if (!options.artifact) fail(`download required from signed-in Console /api/requests/${request}/artifact/${delivery.id}; rerun observation with --artifact PATH`); const bytes = readFileSync(options.artifact); if (bytes.length !== delivery.artifact.bytes || createHash('sha256').update(bytes).digest('hex') !== delivery.artifact.sha256) fail('download differs from reviewed artifact'); writeFileSync(join(options.evidence, 'reviewed-' + delivery.id + '.html'), bytes, { flag: 'wx', mode: 0o600 }); record('download', { request, delivery: delivery.id, artifact: delivery.artifact, qualification: 'Hash-verified live delivery; lead must run offline behavior checks and inspect real independent role/test receipts before acceptance.' }); process.stdout.write('Live delivery and downloaded bytes retained. Offline browser verification and lead acceptance remain explicit.\n'); } if (process.argv[1] && import.meta.url === pathToFileURL(resolve(process.argv[1])).href) { main(process.argv.slice(2)).catch(e => { process.stderr.write(e.message + '\n'); process.exitCode = 2; }); }