From cf759428b6e2709ae0ed8dbe9397e7a77fe3e01f Mon Sep 17 00:00:00 2001 From: Riverbraid Date: Mon, 27 Jul 2026 13:21:35 -0400 Subject: [PATCH 1/2] Add isolated fail-closed verifier test --- tests/verify-fail-closed.mjs | 45 ++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 tests/verify-fail-closed.mjs diff --git a/tests/verify-fail-closed.mjs b/tests/verify-fail-closed.mjs new file mode 100644 index 0000000..bf7f0f6 --- /dev/null +++ b/tests/verify-fail-closed.mjs @@ -0,0 +1,45 @@ +import assert from "node:assert/strict"; +import fs from "node:fs"; +import os from "node:os"; +import path from "node:path"; +import { spawnSync } from "node:child_process"; + +const repoRoot = process.cwd(); +const requiredFiles = [ + "verify.mjs", + "index.js", + "protocol.steps", + "package.json", + "AUTHORITY.md", + "RING.md" +]; + +const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), "riverbraid-refusal-fail-closed-")); + +try { + for (const file of requiredFiles) { + fs.copyFileSync(path.join(repoRoot, file), path.join(tempRoot, file)); + } + + fs.rmSync(path.join(tempRoot, "AUTHORITY.md")); + + const result = spawnSync(process.execPath, ["verify.mjs"], { + cwd: tempRoot, + encoding: "utf8" + }); + + assert.equal(result.status, 1, `expected exit code 1, received ${result.status}`); + + const outputPath = path.join(tempRoot, "verify-output.json"); + assert.equal(fs.existsSync(outputPath), true, "verify-output.json must be written on failure"); + + const output = JSON.parse(fs.readFileSync(outputPath, "utf8")); + assert.equal(output.status, "FILES_PRESENT_UNVERIFIED"); + assert.equal(output.missing_files.includes("AUTHORITY.md"), true); + assert.equal(output.failure_codes.includes("REQUIRED_FILES_MISSING"), true); + assert.equal(output.claim_boundary, "declared-conditions-only"); + + console.log("REFUSAL_GOLD_FAIL_CLOSED_NEGATIVE_PASS"); +} finally { + fs.rmSync(tempRoot, { recursive: true, force: true }); +} From a05c341af05fe9b5663c5dc8d6e85084e0118cdc Mon Sep 17 00:00:00 2001 From: Riverbraid Date: Mon, 27 Jul 2026 13:21:56 -0400 Subject: [PATCH 2/2] Execute positive and negative verifier evidence --- .github/workflows/verify.yml | 39 +++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/.github/workflows/verify.yml b/.github/workflows/verify.yml index e315521..66a232b 100644 --- a/.github/workflows/verify.yml +++ b/.github/workflows/verify.yml @@ -1,38 +1,41 @@ name: Riverbraid Verification Gate + on: push: - branches: [ main ] + branches: [main] pull_request: - branches: [ main ] + branches: [main] workflow_dispatch: + permissions: contents: read + jobs: verify: - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 steps: - name: Checkout Repository - uses: actions/checkout@v4 + uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 + - name: Setup Node.js - uses: actions/setup-node@v4 + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 with: - node-version: '20.11.0' + node-version: '24.11.1' + - name: Install Dependencies run: | + set -euo pipefail if [ -f package-lock.json ]; then - npm ci + npm ci --ignore-scripts else echo "No package-lock.json found. Skipping dependency install." fi - - name: Execute Riverbraid Verifier + + - name: Execute positive verifier path run: | - if [ -f verify.mjs ]; then - node verify.mjs - elif [ -f package.json ] && grep -q '"verify":' package.json 2>/dev/null; then - npm run verify - elif [ -f package.json ] && grep -q '"test":' package.json 2>/dev/null; then - npm test - else - echo "Error: No standard verifier found." - exit 1 - fi + set -euo pipefail + node verify.mjs + node -e "const fs=require('fs'); const r=JSON.parse(fs.readFileSync('verify-output.json','utf8')); if(r.status!=='VERIFIED'||r.failure_codes.length!==0) process.exit(1); console.log('REFUSAL_GOLD_POSITIVE_PASS')" + + - name: Execute isolated fail-closed negative path + run: node tests/verify-fail-closed.mjs