// Synthetic-only publication simulator. No caller-selected filesystem root, // production credential adapter, real Pi runner, service or live activation. import { mkdtemp, mkdir, open, rename, rm, lstat } from 'node:fs/promises'; import { constants } from 'node:fs'; import { randomUUID } from 'node:crypto'; import { FixtureError, exact, refuse, resolveFixtureExecution, validateFixtureCredential } from './execution.mjs'; import { isFixtureStore } from './fixture-store.mjs'; import { refreshFixtureCredential, validateRefreshOptions } from './refresh-fixture.mjs'; const anchor = h => `/proc/self/fd/${h.fd}`; async function openDir(path) { return open(path, constants.O_RDONLY | constants.O_DIRECTORY | constants.O_NOFOLLOW); } async function verifyJson(dir, name, value) { const expected = Buffer.from(JSON.stringify(value, null, 2) + '\n'); const h = await open(`${anchor(dir)}/${name}`, constants.O_RDONLY | constants.O_NOFOLLOW | constants.O_NONBLOCK); try { const s = await h.stat(); if (!s.isFile() || s.uid !== process.getuid() || (s.mode & 0o777) !== 0o600 || s.size !== expected.length) refuse('generation-validation-failed'); const actual = Buffer.alloc(expected.length + 1); let size = 0; while (size < actual.length) { const { bytesRead } = await h.read(actual, size, actual.length - size, null); if (!bytesRead) break; size += bytesRead; } if (size !== expected.length || !actual.subarray(0, size).equals(expected)) refuse('generation-validation-failed'); } finally { await h.close(); } } async function writeJson(dir, name, value) { const content = JSON.stringify(value, null, 2) + '\n'; if (Buffer.byteLength(content) > 1024 * 1024) refuse('generation-too-large'); const h = await open(`${anchor(dir)}/${name}`, constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL | constants.O_NOFOLLOW, 0o600); try { await h.writeFile(content); await h.sync(); } finally { await h.close(); } } export async function createFixtureWorkspace() { if (process.platform !== 'linux') refuse('unsupported-platform'); const path = await mkdtemp('/tmp/mosaic-materialization-fixture-'); const root = await openDir(path), identity = await root.stat(); let closed = false, active = 0; const handles = {}; try { for (const name of ['claims', 'pending', 'generations']) { await mkdir(`${anchor(root)}/${name}`, { mode: 0o700 }); handles[name] = await openDir(`${anchor(root)}/${name}`); } } catch (e) { for (const h of Object.values(handles)) await h.close(); await root.close(); await rm(path, { recursive: true, force: true }); throw e; } return Object.freeze({ fixtureOnly: true, path, async generate(registry, request, store, options = {}) { if (closed) refuse('workspace-closed'); if (!isFixtureStore(store)) refuse('fixture-store-required'); exact(options, [], ['fault', 'refresh']); if (options.fault !== undefined && !['after-auth', 'before-publish', 'after-publish'].includes(options.fault)) refuse('invalid-fixture-option'); options = { fault: options.fault, refresh: options.refresh === undefined ? undefined : validateRefreshOptions(options.refresh) }; const plan = resolveFixtureExecution(registry, request), id = plan.scope.executionId; const pending = `${anchor(handles.pending)}/${id}`, claimPath = `${anchor(handles.claims)}/${id}`; let claim, generation, claimed = false, published = false; active++; try { try { await mkdir(claimPath, { mode: 0o700 }); claimed = true; } catch { refuse('execution-already-claimed'); } claim = await openDir(claimPath); await writeJson(claim, 'started.json', { fixtureOnly: true, executionId: id, state: 'started' }); const result = await store.transaction(Object.values(plan.accounts), async draft => { const auth = Object.create(null); for (const [provider, ref] of Object.entries(plan.accounts)) { let credential = validateFixtureCredential(draft.get(ref), plan.types[provider]); if (credential !== null && (options.refresh !== undefined || (credential.type === 'oauth' && credential.expires <= Date.now() + 300000))) { credential = await refreshFixtureCredential(provider, credential, options.refresh ?? {}); draft.set(ref, credential); } if (credential !== null) auth[provider] = credential; } await mkdir(pending, { mode: 0o700 }); generation = await openDir(pending); await writeJson(generation, 'auth.json', auth); if (options.fault === 'after-auth') refuse('injected-generation-failure'); await writeJson(generation, 'models.json', plan.models); const manifest = { manifestVersion: 1, fixtureOnly: true, manifestId: randomUUID(), scope: plan.scope, profile: plan.profile, accounts: plan.accounts, fork: plan.fork, artifacts: ['auth.json', 'models.json'], state: 'ready' }; // Manifest contains no token, expiry or credential-content digest. await writeJson(generation, 'manifest.json', manifest); if (options.fault === 'before-publish') refuse('injected-generation-failure'); await verifyJson(generation, 'auth.json', auth); await verifyJson(generation, 'models.json', plan.models); await verifyJson(generation, 'manifest.json', manifest); await generation.sync(); await generation.close(); generation = undefined; const target = `${anchor(handles.generations)}/${id}`; try { await lstat(target); refuse('generation-exists'); } catch (e) { if (e.code !== 'ENOENT') throw e; } // Retained exclusive claim serializes this execution ID, including // failed attempts. Published generations are never replaced by API. await rename(pending, target); published = true; if (options.fault === 'after-publish') refuse('injected-generation-failure'); await handles.generations.sync(); await writeJson(claim, 'result.json', { fixtureOnly: true, state: 'published', manifestId: manifest.manifestId }); return { fixtureOnly: true, manifest, generationPath: `${path}/generations/${id}` }; }); return result; } catch (e) { if (generation) { await generation.close(); generation = undefined; } if (claimed && !published) await rm(pending, { recursive: true, force: true }); const code = published ? 'publication-uncertain' : e instanceof FixtureError ? e.code : 'generation-failed'; if (claim) { try { await writeJson(claim, 'failure.json', { fixtureOnly: true, state: published ? 'uncertain' : 'failed', code }); } catch { throw new FixtureError('recording-failed'); } } throw new FixtureError(code); } finally { if (claim) await claim.close(); active--; } }, async close() { if (closed) return; if (active) refuse('workspace-busy'); closed = true; for (const h of Object.values(handles)) await h.close(); await root.close(); const current = await lstat(path); if (current.dev !== identity.dev || current.ino !== identity.ino || current.isSymbolicLink()) refuse('workspace-path-changed'); await rm(path, { recursive: true, force: true }); }, }); }