← back to Dw Signup Fulfillment

verification/tk11185-reconcile/retired-check.cjs

107 lines

'use strict';
// Historical modules use synthetic imports; real current commands deny access.
const fs = require('node:fs'), path = require('node:path'), vm = require('node:vm');
const crypto = require('node:crypto'), assert = require('node:assert/strict');
const { execFileSync, spawnSync } = require('node:child_process');
const root = path.resolve(__dirname, '../..');
const sha = value => crypto.createHash('sha256').update(value).digest('hex');
const history = '5e609e8';
const git = (...args) => execFileSync('git', args, { cwd: root, encoding: 'utf8' });
const report = {
  intent: 'Retire obsolete theme writes and preserve the current guarded tool',
  risk: 'R1 local command; R3 external boundary tested with denied/mock APIs',
  environment: { node: process.version, platform: process.platform, root },
  timestamp: new Date().toISOString(), baselineCommit: history, buildBase: git('rev-parse', 'HEAD').trim(),
  command: 'node --experimental-vm-modules verification/tk11185-reconcile/retired-check.cjs',
  baseline: [], invocations: [], assertions: [],
  cleanup: 'No real API calls, customers, emails, or production mutations. No temporary records.',
  scope: 'Retirement only; TK11185 production smoke-record cleanup remains with the parent.',
};
async function reproduce(name, fixtureRelative) {
  const file = 'scripts/' + name, source = git('show', history + ':' + file);
  const historical = fs.readFileSync(path.join(root, fixtureRelative), 'utf8');
  const published = fs.readFileSync(path.join(root, 'theme-proposals/designer-signin-tk11283/snippets/dw-signin-modal.liquid'), 'utf8');
  assert.notEqual(sha(historical), sha(published));
  let live = published;
  const reads = [], calls = [], output = [], fakeHome = '/retirement-fixture';
  const fakeFS = { readFileSync(filename) {
    reads.push(filename);
    if (filename === fakeHome + '/Projects/secrets-manager/.env') return 'SHOPIFY_THEME_TOKEN=dummy-test-token\n';
    if (filename === fakeHome + '/Projects/dw-signup-fulfillment/' + fixtureRelative) return historical;
    throw new Error('Unallowed fixture file: ' + filename);
  } };
  const context = vm.createContext({
    console: { log: (...args) => output.push(args.join(' ')), error: (...args) => output.push(args.join(' ')) },
    process: { exit(code) { throw new Error('Unexpected process.exit ' + code); } },
    fetch: async (url, options = {}) => {
      const method = options.method || 'GET', call = { method, url };
      calls.push(call);
      if (url.endsWith('/themes.json') && method === 'GET') return { json: async () => ({ themes: [{ role: 'main', id: 145121607731, name: 'fixture-main' }] }) };
      if (url.endsWith('/assets.json') && method === 'PUT') {
        const { asset } = JSON.parse(options.body);
        assert.equal(asset.key, 'snippets/dw-signin-modal.liquid');
        call.valueSHA256 = sha(asset.value);
        live = asset.value;
        return { status: 200, json: async () => ({ asset: { key: asset.key, updated_at: 'fixture-only' } }) };
      }
      throw new Error('Unexpected mock API access');
    },
  });
  const module = new vm.SourceTextModule(source, { context, identifier: file });
  await module.link(specifier => {
    assert.ok(['fs', 'os'].includes(specifier), 'Only synthetic imports');
    const value = specifier === 'fs' ? fakeFS : { homedir: () => fakeHome };
    return new vm.SyntheticModule(['default'], function () { this.setExport('default', value); }, { context });
  });
  await module.evaluate();
  assert.equal(live, historical, 'Original overwrites the newer published body');
  assert.equal(calls.filter(x => x.method === 'PUT').length, 1);
  assert.equal(calls.filter(x => x.method === 'GET' && x.url.includes('/assets')).length, 0, 'No current-content check');
  report.baseline.push({ file, sourceSHA256: sha(source), publishedBeforeSHA256: sha(published), staleAfterSHA256: sha(live), reads, calls, output, reproduced: true });
}
async function main() {
  await reproduce('gate2-theme-put.mjs', 'theme-proposals/loggedin-trade-entry/dw-signin-modal.PATCHED-tk11185.liquid');
  await reproduce('gate2-theme-rollback.mjs', 'theme-backups/live-snapshots/snippets__dw-signin-modal.liquid.20260903T181955.bak');
  const guardPath = 'verification/tk11283/publish-theme.cjs';
  assert.equal(fs.readFileSync(path.join(root, guardPath), 'utf8'), git('show', 'HEAD:' + guardPath), 'Supported tool has no edits');
  report.guardedToolSHA256 = sha(fs.readFileSync(path.join(root, guardPath)));
  for (const name of ['gate2-theme-put.mjs', 'gate2-theme-rollback.mjs']) {
    const entry = path.join(root, 'scripts', name);
    for (const args of [[], ['--apply'], ['--rollback']]) {
      const cwd = args.length ? '/private/tmp' : root;
      const command = ['--require', path.join(__dirname, 'retired-boundaries.cjs'), entry, ...args];
      const result = spawnSync(process.execPath, command, { cwd, encoding: 'utf8', timeout: 5000,
        env: { PATH: process.env.PATH, TK_RETIRE_ALLOWED_ENTRY: entry } });
      assert.ifError(result.error);
      assert.equal(result.status, 78, name + ' must exit78');
      assert.match(result.stderr, /SUPERSEDED/);
      assert.match(result.stderr, /TK-11283/);
      assert.match(result.stderr, /publish-theme\.cjs --status/);
      assert.equal(result.stdout, '');
      const auditLine = result.stderr.split('\n').find(line => line.startsWith('RETIREMENT_BOUNDARY_AUDIT='));
      assert.ok(auditLine, 'Preload audit actually ran');
      const audit = JSON.parse(auditLine.slice('RETIREMENT_BOUNDARY_AUDIT='.length));
      assert.deepEqual(audit.appFileAttempts, [], 'No credential or application file reads');
      assert.deepEqual(audit.networkAttempts, [], 'No network attempts');
      report.invocations.push({ entry, args, cwd, exitCode: result.status, signal: result.signal,
        command: [process.execPath, ...command], stderr: result.stderr, audit, sourceSHA256: sha(fs.readFileSync(entry)), verdict: 'PASS' });
    }
    const plain = spawnSync(process.execPath, [entry], { cwd: '/private/tmp', encoding: 'utf8', timeout: 5000, env: { PATH: process.env.PATH } });
    assert.equal(plain.status, 78);
    assert.match(plain.stderr, /SUPERSEDED/);
    report.invocations.push({ entry, mode: 'plain direct Node, no preload', cwd: '/private/tmp', exitCode: plain.status, stderr: plain.stderr, verdict: 'PASS' });
  }
  report.assertions = [
    { boundary: 'Historical fs/API', verdict: 'PASS', reason: 'Actual original sources read dummy credentials then overwrite newer body without checking current hash.' },
    { boundary: 'Real CLI process', verdict: 'PASS', reason: 'Both exit78 from repository or unrelated cwd, even with apply/rollback flags.' },
    { boundary: 'Credentials/files/network', verdict: 'PASS', reason: 'Six instrumented invocations report zero app file/network attempts.' },
    { boundary: 'Supported tooling', verdict: 'PASS', reason: 'TK11283 guarded deploy/rollback tool byte-identical to HEAD.' },
    { boundary: 'UI', verdict: 'N/A', reason: 'No storefront/UI changes.' },
  ];
  report.verdict = 'PASS';
  fs.writeFileSync(path.join(__dirname, 'retired-e2e-proof.json'), JSON.stringify(report, null, 2) + '\n');
  console.log(JSON.stringify({ verdict: report.verdict, historicalReproductions: report.baseline.length, directInvocations: report.invocations.length, networkCalls: 0,
    evidence: path.join(__dirname, 'retired-e2e-proof.json') }, null, 2));
}
main().catch(error => { console.error(error); process.exitCode = 1; });