#!/usr/bin/env node const assert = require("assert"); const fs = require("fs"); const path = require("path"); const repo = path.resolve(__dirname, ".."); function read(relativePath) { return fs.readFileSync(path.join(repo, relativePath), "utf8"); } function maybeRead(relativePath) { const absolute = path.join(repo, relativePath); if (!fs.existsSync(absolute)) return null; return fs.readFileSync(absolute, "utf8"); } function expect(source, name, pattern) { assert.match(source, pattern, `missing acceptance environment evidence: ${name}`); } function expectIncludes(source, name, text) { assert(source.includes(text), `missing acceptance environment evidence: ${name}`); } const publicAcceptance = read("scripts/acceptance-public.sh"); const privateAcceptance = read("scripts/acceptance-private.sh"); const publicSplit = read("scripts/verify-public-split.sh"); const acceptanceReport = read("scripts/acceptance-report.js"); const acceptanceReportSmoke = read("scripts/acceptance-report-smoke.js"); const readme = read("README.md"); const windowsWorkflow = read(".forgejo/workflows/windows-validation.yml"); const publicDryrunServiceSmoke = maybeRead("private/hosted-policy/scripts/public-release-dryrun-service-smoke.js"); const publicDryrunDeployPrep = maybeRead("private/hosted-policy/scripts/prepare-public-release-dryrun-deployment.js"); const publicDryrunSystemd = maybeRead("private/hosted-policy/deploy/disasmer-public-release-dryrun.service"); const publicDryrunRunbook = maybeRead("private/hosted-policy/deploy/README.md"); const hostedClientCompatSmoke = maybeRead("private/hosted-policy/scripts/hosted-client-compat-smoke.js"); const hostedService = maybeRead("private/hosted-policy/src/bin/disasmer-hosted-service.rs"); const hostedStartup = maybeRead( "private/hosted-policy/src/bin/disasmer-hosted-service/startup.rs" ); const hostedOperatorAuth = maybeRead( "private/hosted-policy/src/bin/disasmer-hosted-service/operator_auth.rs" ); const publicDryrunE2e = read("scripts/public-release-dryrun-e2e.js"); const finalDryrunEvidence = read("scripts/public-release-dryrun-final-evidence.js"); for (const [name, script] of [ ["public acceptance", publicAcceptance], ["private acceptance", privateAcceptance], ]) { expect(script, `${name} writes acceptance environment report first`, /node scripts\/acceptance-report\.js (public|private)[\s\S]*node scripts\/acceptance-report-smoke\.js/); expectIncludes( script, `${name} runs acceptance environment contract`, "node scripts/acceptance-environment-contract-smoke.js" ); } for (const [name, script] of [ ["public acceptance", publicAcceptance], ["public split", publicSplit], ]) { for (const smoke of [ "scripts/wasmtime-assignment-smoke.js", "scripts/node-attach-smoke.js", "scripts/cli-local-run-smoke.js", "scripts/vscode-f5-smoke.js", "scripts/dap-smoke.js", "scripts/artifact-download-smoke.js", "scripts/artifact-export-smoke.js", "scripts/public-local-demo-matrix-smoke.js", ]) { assert(script.includes(`node ${smoke}`), `${name} must run ${smoke}`); } } expectIncludes(publicAcceptance, "public gate runs rootless Podman backend smoke", "node scripts/podman-backend-smoke.js"); expectIncludes(publicAcceptance, "public gate runs Wasmtime node smoke", "node scripts/wasmtime-node-smoke.js"); expectIncludes(privateAcceptance, "private gate runs hosted deployment smoke", "node private/hosted-policy/scripts/hosted-deployment-smoke.js"); expectIncludes(privateAcceptance, "private gate prepares public dry-run deployment bundle", "node private/hosted-policy/scripts/prepare-public-release-dryrun-deployment.js"); expectIncludes(privateAcceptance, "private gate runs hosted Client compatibility smoke", "node private/hosted-policy/scripts/hosted-client-compat-smoke.js"); expectIncludes(privateAcceptance, "private gate runs standalone Core coordinator smoke", "node scripts/self-hosted-coordinator-smoke.js"); expectIncludes(privateAcceptance, "private gate runs Postgres durable smoke", "node private/hosted-policy/scripts/postgres-durable-smoke.js"); expectIncludes(privateAcceptance, "private gate can run public release dry-run service smoke", "node private/hosted-policy/scripts/public-release-dryrun-service-smoke.js"); expectIncludes(privateAcceptance, "public release dry-run service smoke is env gated", "DISASMER_PUBLIC_RELEASE_DRYRUN_SERVICE_ADDR"); expectIncludes(privateAcceptance, "private gate runs hosted policy cargo tests", "cargo test --manifest-path private/hosted-policy/Cargo.toml"); expectIncludes(publicAcceptance, "public gate can run final dry-run evidence verifier", "node scripts/public-release-dryrun-final-evidence.js"); expectIncludes(publicAcceptance, "public gate can run public release dry-run e2e", "node scripts/public-release-dryrun-e2e.js"); expectIncludes(publicAcceptance, "public release dry-run e2e is env gated", "DISASMER_PUBLIC_RELEASE_DRYRUN_E2E"); expectIncludes(privateAcceptance, "private gate can run final dry-run evidence verifier", "node scripts/public-release-dryrun-final-evidence.js"); expectIncludes(publicAcceptance, "public final dry-run verifier is env gated", "DISASMER_PUBLIC_RELEASE_DRYRUN_FINAL"); expectIncludes(privateAcceptance, "private final dry-run verifier is env gated", "DISASMER_PUBLIC_RELEASE_DRYRUN_FINAL"); expect(publicSplit, "public split excludes private modules", /--exclude='\.\/private'/); expect(publicSplit, "public split excludes experiments", /--exclude='\.\/experiments'/); expect(publicSplit, "public split tests copied workspace", /cargo test --workspace --manifest-path "\$tmp_dir\/Cargo\.toml"/); expect(publicSplit, "public split builds copied workspace binaries", /cargo build --workspace --bins --manifest-path "\$tmp_dir\/Cargo\.toml"/); expectIncludes( publicSplit, "public split runs acceptance environment contract from copied tree", '(cd "$tmp_dir" && node scripts/acceptance-environment-contract-smoke.js)' ); for (const [name, pattern] of [ ["commit SHA fallback", /process\.env\.DISASMER_ACCEPTANCE_COMMIT \|\| commandOutput\("git", \["rev-parse", "HEAD"\]\)/], ["tree status", /tree_status: \(commandOutput\("git", \["status", "--short"\]\) \|\| ""\)[\s\S]*\.filter\(Boolean\)/], ["OS report", /platform: os\.platform\(\)[\s\S]*kernel: os\.release\(\)/], ["Rust report", /rustc: commandOutput\("rustc", \["--version"\]\)/], ["Node report", /version: process\.version/], ["Podman report", /function podmanReport\(\)/], ["Postgres report", /postgres: \{[\s\S]*commandOutput\("postgres", \["--version"\]\) \|\|[\s\S]*commandOutput\("psql", \["--version"\]\)/], ["browser harness report", /browser_harness:/], ["VS Code harness report", /vscode_harness:/], ["Windows validation report", /windows_validation: process\.env\.DISASMER_WINDOWS_VALIDATION \|\| "not-run"/], ]) { expect(acceptanceReport, name, pattern); } for (const [name, pattern] of [ ["acceptance report validates Podman incomplete state", /assertPodmanReport/], ["acceptance report validates Windows not-run", /assertReport\(runReport\(mode\), mode, "not-run"\)/], ["acceptance report validates Windows runner mode", /DISASMER_WINDOWS_VALIDATION: "forgejo-windows-runner"/], ]) { expect(acceptanceReportSmoke, name, pattern); } expect(readme, "README documents public acceptance script", /scripts\/acceptance-public\.sh/); expect(readme, "README documents private acceptance script", /scripts\/acceptance-private\.sh/); expect(readme, "README documents rootless Podman incomplete handling", /Podman backend behavior is marked `incomplete`/); expect(readme, "README documents Postgres discovery in environment report", /Podman\/Postgres discovery/); expect(readme, "README documents manual Windows validation", /manual `Windows validation`\s+workflow/); expect(windowsWorkflow, "Windows workflow is manual", /workflow_dispatch/); expect(windowsWorkflow, "Windows workflow uses intermittent Windows runner", /runs-on:\s*windows/); expect(windowsWorkflow, "Windows workflow writes acceptance report", /node scripts\/acceptance-report\.js windows/); if (publicDryrunServiceSmoke && publicDryrunDeployPrep && publicDryrunSystemd && publicDryrunRunbook) { for (const [name, pattern] of [ ["service smoke requires external service address", /DISASMER_PUBLIC_RELEASE_DRYRUN_SERVICE_ADDR is required/], ["service smoke requires browser test driver", /DISASMER_PUBLIC_RELEASE_DRYRUN_BROWSER_OPEN_COMMAND/], ["service smoke loads release manifest", /public-release-manifest\.json/], ["service smoke rejects stale release manifest", /manifest\.source_commit[\s\S]*expectedCommit/], ["service smoke records source commit", /source_commit: release\.sourceCommit/], ["service smoke records release name", /release_name: release\.releaseName/], ["service smoke connects through public domain", /addr\.host[\s\S]*serviceHost/], ["service smoke verifies DNS state", /\["not-published", "published"\]\.includes\(dnsPublicationState\)/], ["service smoke begins a server-owned OIDC login", /type: "begin_oidc_browser_login"/], ["service smoke polls with opaque credentials", /type: "poll_oidc_browser_login"[\s\S]*transaction_id[\s\S]*polling_secret/], ["service smoke rejects missing hosted callback completion", /timed out waiting for the hosted OIDC callback/], ["service smoke reads server-created project", /type: "list_projects"/], ["service smoke enrolls signed node", /type: "create_node_enrollment_grant"[\s\S]*exchange_node_enrollment_grant/], ["service smoke starts session-authorized process", /type: "start_process"/], ["service smoke reports signed node capabilities", /signedNodeRequest[\s\S]*report_node_capabilities/], ["service smoke reads authorized debug state", /type: "debug_attach"/], ["service smoke aborts its probe process", /type: "abort_process"/], ["service smoke records private hosted coordinator", /coordinator_implementation:[\s\S]*"hosted-policy-coordinator"/], ["service smoke writes evidence report", /public-release-dryrun-service\.json/], ]) { expect(publicDryrunServiceSmoke, name, pattern); } for (const [name, source, pattern] of [ ["deployment prep builds hosted service release", publicDryrunDeployPrep, /cargo"[\s\S]*"build"[\s\S]*"--release"[\s\S]*"private\/hosted-policy\/Cargo\.toml"[\s\S]*"disasmer-hosted-service"/], ["deployment prep stages systemd unit", publicDryrunDeployPrep, /disasmer-public-release-dryrun\.service/], ["deployment prep writes manifest", publicDryrunDeployPrep, /deployment-manifest\.json/], ["deployment prep records private hosted coordinator", publicDryrunDeployPrep, /coordinator_implementation:[\s\S]*"hosted-policy-coordinator"/], ["deployment prep records service address", publicDryrunDeployPrep, /service_addr:[\s\S]*`\$\{serviceHost\}:\$\{servicePort\}`/], ["deployment prep records DNS state", publicDryrunDeployPrep, /dns_publication_state: dnsPublicationState/], ["deployment prep records service smoke command", publicDryrunDeployPrep, /public-release-dryrun-service-smoke\.js/], ["systemd keeps hosted HTTP upstream on loopback", publicDryrunSystemd, /--listen 127\.0\.0\.1:9080/], ["systemd loads root-owned operator credentials", publicDryrunSystemd, /EnvironmentFile=\/etc\/disasmer-public-release-dryrun\/operator\.env/], ["systemd avoids privileged port capability", publicDryrunSystemd, /NoNewPrivileges=true/], ["systemd uses dedicated user", publicDryrunSystemd, /User=disasmer[\s\S]*Group=disasmer/], ["runbook says externally reachable", publicDryrunRunbook, /externally reachable host/], ["runbook documents DNS pending fallback", publicDryrunRunbook, /Until the `disasmer\.michelpaulissen\.com` DNS record is deployed/], ["runbook gives hosts entry", publicDryrunRunbook, / disasmer\.michelpaulissen\.com/], ["runbook separates authority vocabulary", publicDryrunRunbook, /Client and signed Node protocols[\s\S]*Identity boundary[\s\S]*Operator boundary/], ["runbook documents operator credential", publicDryrunRunbook, /DISASMER_HOSTED_OPERATOR_TOKEN/], ]) { expect(source, name, pattern); } } if (hostedClientCompatSmoke && hostedService && hostedStartup && hostedOperatorAuth) { const hostedServiceSecurity = `${hostedService}\n${hostedStartup}\n${hostedOperatorAuth}`; for (const [name, pattern] of [ ["hosted service embeds core coordinator runtime", /core_coordinator: CoordinatorService/], ["hosted service parses the unified identity, operator, and client protocol", /decode_incoming_request/], ["hosted service delegates client requests", /handle_client_request/], ["hosted service routes decoded client requests to Core", /IncomingRequest::Client\(request\)/], ["hosted service requires replay-resistant operator envelope proofs", /hosted_operator_request[\s\S]*HostedOperatorAuth[\s\S]*replay_nonces[\s\S]*verify_request[\s\S]*hosted_operator_request_proof_from_token_digest/], ["hosted service issues the authenticated Core CLI session", /core_coordinator[\s\S]*\.issue_cli_session/], ["hosted service creates the authenticated default project through Core", /AuthenticatedCoordinatorRequest::CreateProject/], ]) { expect(hostedServiceSecurity, name, pattern); } for (const [name, pattern] of [ ["compat smoke starts hosted service", /disasmer-hosted-service/], ["compat smoke creates hosted project", /type: "create_project"/], ["compat smoke creates session-authorized enrollment grant", /type: "create_node_enrollment_grant"/], ["compat smoke runs public CLI attach", /"disasmer-cli"[\s\S]*"node"[\s\S]*"attach"/], ["compat smoke verifies public enrollment exchange", /node_enrollment_exchanged/], ["compat smoke runs public CLI browser login", /"login"[\s\S]*"--browser"[\s\S]*DISASMER_BROWSER_OPEN_COMMAND/], ["compat smoke derives hosted scope", /const session = login\.coordinator_response\.session/], ["compat smoke rejects forged identity", /forged_unsigned_project/], ["compat smoke rejects an actually expired hosted session", /DISASMER_HOSTED_CLI_SESSION_TTL_SECONDS[\s\S]*expired; run disasmer login --browser again/], ["compat smoke denies cross-tenant task-event reads", /crossTenantTaskEventsDenied[\s\S]*type: "list_task_events"[\s\S]*vp-victim/], ["compat smoke writes evidence report", /hosted-client-compat\.json/], ]) { expect(hostedClientCompatSmoke, name, pattern); } } for (const [name, pattern] of [ ["e2e runner requires explicit opt-in", /DISASMER_PUBLIC_RELEASE_DRYRUN_E2E/], ["e2e runner requires the honestly reset pre-final ledger", /assertPreFinalLedger\(readPhase3Ledger\(repo\)\)/], ["e2e runner requires public domain service address", /serviceAddr[\s\S]*serviceHost/], ["e2e runner downloads release assets", /downloadReleaseAssets/], ["e2e runner verifies release checksums", /verifyChecksums/], ["e2e runner clones public repo", /git"[\s\S]*"clone"[\s\S]*publicRepositoryUrl/], ["e2e runner uses default hosted coordinator", /defaultLoginPlan\.coordinator[\s\S]*serviceEndpoint/], ["e2e runner uses server-owned browser login", /DISASMER_PUBLIC_RELEASE_DRYRUN_BROWSER_OPEN_COMMAND[\s\S]*DISASMER_BROWSER_OPEN_COMMAND/], ["e2e runner attaches user node", /node"[\s\S]*"attach"/], ["e2e runner starts public worker runtime", /workerArgs[\s\S]*"--worker"[\s\S]*cp\.spawn\(disasmerNode/], ["e2e runner launches released product through CLI", /"run"[\s\S]*"build"[\s\S]*runReport\.status[\s\S]*main_launched/], ["standalone Core proof launches a real Wasm TaskSpec", /type: "launch_task"[\s\S]*task_spec:[\s\S]*kind: "coordinator_node_wasm"[\s\S]*bundle_digest: manifest\.bundle_digest/], ["e2e runner verifies public assignment polling", /worker_assignment_poll_protocol/], ["e2e runner validates standalone Core coordinator", /validateStandaloneCoreCoordinator/], ["e2e runner records standalone Core coordinator", /core_coordinator_implementation/], ["e2e runner verifies task events", /list_task_events/], ["e2e runner creates artifact download link", /create_artifact_download_link/], ["e2e runner verifies VS Code debugger", /vscode-f5-smoke\.js/], ["e2e runner writes e2e report", /public-release-dryrun-e2e\.json/], ]) { expect(publicDryrunE2e, name, pattern); } for (const [name, pattern] of [ ["final verifier requires public release manifest", /public-release-manifest\.json/], ["final verifier requires Forgejo release evidence", /public-release-dryrun-forgejo-release\.json/], ["final verifier requires deployment manifest", /deployment-manifest\.json/], ["final verifier requires service smoke evidence", /public-release-dryrun-service\.json/], ["final verifier requires all 191 Phase 3 criteria passed", /assertFinalLedger\(readPhase3Ledger\(repo\)\)/], ["final verifier requires current service smoke source", /service\.source_commit[\s\S]*manifest\.source_commit/], ["final verifier requires current service smoke release", /service\.release_name[\s\S]*manifest\.release_name/], ["final verifier requires hosted Client compatibility evidence", /hosted-client-compat\.json/], ["final verifier requires current Client compatibility source", /compat\.source_commit[\s\S]*manifest\.source_commit/], ["final verifier requires current Client compatibility release", /compat\.release_name[\s\S]*manifest\.release_name/], ["final verifier requires Core coordinator compatibility evidence", /core-coordinator-compat\.json/], ["final verifier requires current public coordinator source", /coreCoordinator\.source_commit[\s\S]*manifest\.source_commit/], ["final verifier requires current public coordinator release", /coreCoordinator\.release_name[\s\S]*manifest\.release_name/], ["final verifier requires public e2e evidence", /public-release-dryrun-e2e\.json/], ["final verifier records both coordinator validations", /coordinator_validation/], ["final verifier writes final evidence", /public-release-dryrun-final\.json/], ]) { expect(finalDryrunEvidence, name, pattern); } console.log("Acceptance environment contract smoke passed");