test(#1279): RED — defaultProveFailFirst real-e2e (lint + node-test, fail-closed) + load-bearing fixture
This commit is contained in:
22
tests/_ff_lint_violation.test.cjs
Normal file
22
tests/_ff_lint_violation.test.cjs
Normal file
@@ -0,0 +1,22 @@
|
||||
/* eslint-disable local/no-source-grep */
|
||||
// PERMANENT LOAD-BEARING FIXTURE for #1279 — DO NOT "simplify" or delete.
|
||||
//
|
||||
// This file is a KNOWN `local/no-source-grep` violation used by `defaultProveFailFirst`'s lint-rule
|
||||
// path to machine-prove the rule has teeth (the fail-first proof). The exact form below is the ONLY
|
||||
// shape that fires `local/no-source-grep` under the project flat config (verified empirically, #1279
|
||||
// RESEARCH): a `tests/**/*.test.cjs` file whose `readFileSync` argument is the
|
||||
// `path.join('lib','foo.cjs')` form (a STANDALONE quoted source-dir token `'lib'` + a quoted
|
||||
// `.cjs` extension) followed by a text-search method (`.includes`) on the bound variable.
|
||||
//
|
||||
// - `'src/x.cjs'` as a single string literal does NOT fire (no standalone quoted dir token).
|
||||
// - a repo-root / tmp path does NOT fire (no source-dir token).
|
||||
//
|
||||
// The leading `/* eslint-disable local/no-source-grep */` keeps the project's own `eslint .` green
|
||||
// (the violation lands in eslint's `suppressedMessages`, which the prover's `eslintJsonHasRule`
|
||||
// reads — an inline-disabled violation still proves the rule has teeth, #1259 B1). If the prover
|
||||
// ever reports `provenFailFirst:false` for the lint-rule kind, suspect THIS file's form first.
|
||||
'use strict';
|
||||
const fs = require('node:fs');
|
||||
const path = require('node:path');
|
||||
const s = fs.readFileSync(path.join('lib', 'foo.cjs'), 'utf-8');
|
||||
module.exports = s.includes('x');
|
||||
@@ -529,3 +529,134 @@ describe('prohibition-enforcement REAL runner end-to-end (#1259)', () => {
|
||||
assert.equal(result.located, true, 'the descriptor was well-formed; it just did not genuinely pass');
|
||||
});
|
||||
});
|
||||
|
||||
// ─── #1279 defaultProveFailFirst REAL prover end-to-end (FF-02 / FF-03 / FF-05 / FF-06 / FF-07) ──
|
||||
// Exercises the SHIPPING default prover against REAL subprocesses (eslint + node --test) — the gap
|
||||
// that let #1259's BL-01/SF-01 slip past injected doubles. The lint-rule path dogfoods the committed
|
||||
// `tests/_ff_lint_violation.test.cjs` fixture; the node-test path uses synthetic temp fixtures that
|
||||
// demonstrate the `GSD_PROHIB_SUBJECT` subject-injection convention. Typed-result assertions only.
|
||||
describe('prohibition-enforcement defaultProveFailFirst REAL prover (#1279)', () => {
|
||||
const fs = require('node:fs');
|
||||
// The committed load-bearing lint fixture (a real, suppressed no-source-grep violation).
|
||||
const LINT_FIXTURE = 'tests/_ff_lint_violation.test.cjs';
|
||||
|
||||
test('exports the prover surface (defaultProveFailFirst + FailFirstProof-shaped result)', () => {
|
||||
const enforce = require(ENFORCEMENT_LIB);
|
||||
assert.equal(typeof enforce.defaultProveFailFirst, 'function',
|
||||
'must export defaultProveFailFirst — the default real prover');
|
||||
});
|
||||
|
||||
test('lint-rule: proves red on the committed no-source-grep violation fixture (FF-02 red direction)', () => {
|
||||
const enforce = require(ENFORCEMENT_LIB);
|
||||
// Lint the KNOWN-violating fixture through the project flat config; the rule id MUST appear
|
||||
// (in messages or suppressedMessages) → the rule has teeth → fail-first proven.
|
||||
const proof = enforce.defaultProveFailFirst(
|
||||
{ kind: 'lint-rule', rule: 'local/no-source-grep', target: LINT_FIXTURE, violationFixture: LINT_FIXTURE },
|
||||
process.cwd(),
|
||||
);
|
||||
assert.equal(proof.provenFailFirst, true,
|
||||
'a real no-source-grep violation fixture proves the lint rule fails-on-violation');
|
||||
assert.equal(proof.method, 'violation-fixture', 'records the proof method');
|
||||
});
|
||||
|
||||
test('lint-rule: a CLEAN violationFixture (rule does not flag) is NOT proven (FF-02 toothless direction)', () => {
|
||||
const enforce = require(ENFORCEMENT_LIB);
|
||||
// src/clock.cts is a clean in-tree source with no no-source-grep violation. If a "violation
|
||||
// fixture" does not actually trigger the rule, the rule is toothless on it → not a guard → not
|
||||
// proven → must hard-gate.
|
||||
const proof = enforce.defaultProveFailFirst(
|
||||
{ kind: 'lint-rule', rule: 'local/no-source-grep', target: 'src/clock.cts', violationFixture: 'src/clock.cts' },
|
||||
process.cwd(),
|
||||
);
|
||||
assert.equal(proof.provenFailFirst, false,
|
||||
'a fixture the rule does not flag cannot prove fail-first');
|
||||
});
|
||||
|
||||
test('lint-rule: no violationFixture -> not proven (FF-05 fail-closed)', () => {
|
||||
const enforce = require(ENFORCEMENT_LIB);
|
||||
const proof = enforce.defaultProveFailFirst(
|
||||
{ kind: 'lint-rule', rule: 'local/no-source-grep', target: 'src/clock.cts' }, // no violationFixture
|
||||
process.cwd(),
|
||||
);
|
||||
assert.equal(proof.provenFailFirst, false, 'no violationFixture -> cannot prove -> hard-gate');
|
||||
});
|
||||
|
||||
test('node-test: a negative test that goes RED against a known-bad GSD_PROHIB_SUBJECT is proven (FF-03 red direction)', (t) => {
|
||||
const enforce = require(ENFORCEMENT_LIB);
|
||||
const dir = createTempDir('prohib-ff-node-red-');
|
||||
t.after(() => cleanup(dir));
|
||||
// A negative test that HONORS the GSD_PROHIB_SUBJECT convention: it reads the subject path and
|
||||
// asserts the subject is "clean" (does not contain the forbidden token). Against a KNOWN-BAD
|
||||
// fixture, the assertion fails → the run goes RED → fail-first proven.
|
||||
const negTest = path.join(dir, 'neg.test.cjs');
|
||||
fs.writeFileSync(negTest,
|
||||
"const { test } = require('node:test');\n" +
|
||||
"const assert = require('node:assert');\n" +
|
||||
"const fs = require('node:fs');\n" +
|
||||
"test('subject must not contain FORBIDDEN', () => {\n" +
|
||||
" const subject = fs.readFileSync(process.env.GSD_PROHIB_SUBJECT, 'utf-8');\n" +
|
||||
" assert.ok(!subject.includes('FORBIDDEN'), 'subject is clean');\n" +
|
||||
"});\n");
|
||||
const badFixture = path.join(dir, 'bad-subject.txt');
|
||||
fs.writeFileSync(badFixture, 'this subject contains FORBIDDEN content\n');
|
||||
const proof = enforce.defaultProveFailFirst(
|
||||
{ kind: 'node-test', target: negTest, violationFixture: badFixture },
|
||||
dir,
|
||||
);
|
||||
assert.equal(proof.provenFailFirst, true,
|
||||
'the negative test goes RED against the known-bad subject -> fail-first proven');
|
||||
assert.equal(proof.method, 'violation-fixture');
|
||||
});
|
||||
|
||||
test('node-test: a toothless negative test that PASSES even against the violation is NOT proven (FF-03 toothless direction)', (t) => {
|
||||
const enforce = require(ENFORCEMENT_LIB);
|
||||
const dir = createTempDir('prohib-ff-node-tooth-');
|
||||
t.after(() => cleanup(dir));
|
||||
// A negative test that ignores the subject and always passes — it never goes red, so it cannot
|
||||
// prove fail-first even with a violation fixture supplied.
|
||||
const negTest = path.join(dir, 'neg.test.cjs');
|
||||
fs.writeFileSync(negTest,
|
||||
"const { test } = require('node:test');\n" +
|
||||
"const assert = require('node:assert');\n" +
|
||||
"test('always passes (toothless)', () => { assert.ok(true); });\n");
|
||||
const badFixture = path.join(dir, 'bad-subject.txt');
|
||||
fs.writeFileSync(badFixture, 'FORBIDDEN\n');
|
||||
const proof = enforce.defaultProveFailFirst(
|
||||
{ kind: 'node-test', target: negTest, violationFixture: badFixture },
|
||||
dir,
|
||||
);
|
||||
assert.equal(proof.provenFailFirst, false,
|
||||
'a test that does not go red against the violation is toothless -> not proven');
|
||||
});
|
||||
|
||||
test('node-test: no violationFixture -> not proven (FF-05 fail-closed)', (t) => {
|
||||
const enforce = require(ENFORCEMENT_LIB);
|
||||
const dir = createTempDir('prohib-ff-node-nofix-');
|
||||
t.after(() => cleanup(dir));
|
||||
const negTest = path.join(dir, 'neg.test.cjs');
|
||||
fs.writeFileSync(negTest,
|
||||
"const { test } = require('node:test');\ntest('guards', () => {});\n");
|
||||
const proof = enforce.defaultProveFailFirst(
|
||||
{ kind: 'node-test', target: negTest }, // no violationFixture
|
||||
dir,
|
||||
);
|
||||
assert.equal(proof.provenFailFirst, false,
|
||||
'a node-test with no violationFixture cannot be proven -> hard-gate, never attestation');
|
||||
});
|
||||
|
||||
test('prover never throws: a non-existent fixture / unresolvable tooling -> provenFailFirst:false (FF-05/FF-06)', () => {
|
||||
const enforce = require(ENFORCEMENT_LIB);
|
||||
// Non-existent lint fixture path -> eslint lints nothing / errors -> fail-closed, no throw.
|
||||
const lintProof = enforce.defaultProveFailFirst(
|
||||
{ kind: 'lint-rule', rule: 'local/no-source-grep', target: 'no/such/file.cjs', violationFixture: 'no/such/file.cjs' },
|
||||
process.cwd(),
|
||||
);
|
||||
assert.equal(lintProof.provenFailFirst, false, 'a missing lint fixture proves nothing, never throws');
|
||||
// Non-existent node-test target -> the run is not RED in the intended way / errors -> fail-closed.
|
||||
const nodeProof = enforce.defaultProveFailFirst(
|
||||
{ kind: 'node-test', target: 'no/such/neg.test.cjs', violationFixture: 'no/such/subject.txt' },
|
||||
process.cwd(),
|
||||
);
|
||||
assert.equal(typeof nodeProof.provenFailFirst, 'boolean', 'returns a typed proof, never throws');
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user