Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions adr/0007-scope-end-to-end-coverage-to-user-reachable-states.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,25 @@ Option 3.
4. **The floors do not move.** The browser lane keeps 100% source lines, 96%
source regions and `--require-source-files`; the unit lane keeps 100% / 100%.

## Clarification: integration-boundary evidence (2026-10-21)

Decision 3 requires surviving-mutant evidence for assertion gaps in production
logic covered by the configured mutation run. It does not require inventing a
hand-constructed mutation or another mutation harness to qualify an integration
boundary the configured mutation scope or runner does not exercise.

For such boundaries, including root configuration, Actions event environments,
and dependency/compiler contracts, a finding may instead cite a reproducible
integration failure or a documented historical regression. It must identify the
production failure mode, explain why the mutation run does not exercise that
boundary, and add a regression test against the actual consumer or exported
configuration rather than only a helper or a duplicate parser.

This clarification does not relax decisions 1, 2 or 4, or ADR 0006's
restrictions on test-tree guards. It does not authorize data-shape browser
fixture builds, change coverage floors, or replace surviving-mutant evidence for
assertion gaps within mutation-covered production logic.

## Consequences

- Hive `quality` findings that do not meet decision 2 are closed as not planned
Expand Down
3 changes: 0 additions & 3 deletions knip.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,6 @@ const config = {
// Run through `npx` inside xargs pipelines in package.json scripts.
'markdown-link-check',
'markdownlint-cli',
// Type-only JSDoc import in docusaurus.config.js and sidebars.js; installed
// by @docusaurus/preset-classic.
'@docusaurus/plugin-content-docs',
],
ignoreIssues: {
// Tests load it through importSource(), a dynamic import knip cannot follow.
Expand Down
2 changes: 2 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,9 @@
"devDependencies": {
"@axe-core/playwright": "^4.14.0",
"@docusaurus/faster": "^3.10.2",
"@docusaurus/mdx-loader": "3.10.2",
"@docusaurus/module-type-aliases": "3.10.2",
"@docusaurus/plugin-content-docs": "3.10.2",
"@docusaurus/types": "3.10.2",
"@eslint/js": "^9.39.5",
"@jridgewell/trace-mapping": "^0.3.31",
Expand Down
141 changes: 141 additions & 0 deletions tests/mdx-active-content.test.mjs
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
import assert from 'node:assert/strict';
import test from 'node:test';
import { fileURLToPath } from 'node:url';
import { resolve } from 'node:path';
import { loadSiteConfig } from '@docusaurus/core/lib/server/config.js';
import { compileToJSX } from '@docusaurus/mdx-loader/lib/utils.js';
import { DEFAULT_OPTIONS } from '@docusaurus/plugin-content-docs/lib/options.js';
import { parseSync } from '@swc/core';
import { findActiveContent } from '../scripts/lib/mdx-active-content.mjs';

const reasons = (markdown) => findActiveContent(markdown).map((f) => f.reason);
Expand Down Expand Up @@ -677,3 +683,138 @@ test('leaves an ordinary admonition and a fenced copy of the payload alone', ()
].join('\n');
assert.deepEqual(reasons(body), []);
});

const siteDir = fileURLToPath(new URL('../', import.meta.url));
const { siteConfig } = await loadSiteConfig({ siteDir });
const classicPreset = siteConfig.presets.find(
(preset) => Array.isArray(preset) && preset[0] === 'classic',
);
const compilerOptions = {
...DEFAULT_OPTIONS,
...classicPreset[1].docs,
siteDir,
staticDirs: siteConfig.staticDirectories.map((dir) => resolve(siteDir, dir)),
markdownConfig: siteConfig.markdown,
};

// Inspect the real compiler's JavaScript, not the gate's parser or rewrite
// helpers. Rejected MDX is compiled but never evaluated.
async function compiledContent(body, options = compilerOptions) {
const result = await compileToJSX({
fileContent: body,
filePath: resolve(siteDir, 'docs/architectures/_security-regression.md'),
frontMatter: {},
options,
compilerName: 'server',
});
const urls = [];
const text = [];
function visit(node) {
if (!node || typeof node !== 'object') return;
if (node.type === 'StringLiteral') text.push(node.value);
if (
node.type === 'KeyValueProperty' &&
['href', 'src'].includes(node.key.value) &&
node.value.type === 'StringLiteral'
)
urls.push([node.key.value, node.value.value]);
for (const value of Object.values(node)) {
if (Array.isArray(value)) value.forEach(visit);
else visit(value);
}
}
visit(parseSync(result.content, { syntax: 'ecmascript' }));
return { urls, text };
}

const COMPILER_REJECTED = [
[
'whole-document fence pairing exposes a remote image',
'```mdx-code-block\n<img src="https://beacon.invalid/px.png" />\n````\n\n```',
['src', 'https://beacon.invalid/px.png'],
'disallowed element <img>',
],
[
'unwrapping exposes an encoded URL in an admonition below a heading',
'## Overview\n\n```mdx-code-block\n:::note[x](&#106;avascript:alert(1))\n```',
['href', 'javascript:alert(1)'],
'disallowed URL scheme javascript:',
],
[
'GFM table delimiters expose an image inside an apparent code span',
'| a | b |\n| - | - |\n| `x | <img src="https://beacon.invalid/px.png" /> ` |',
['src', 'https://beacon.invalid/px.png'],
'disallowed element <img>',
],
[
'duplicate definitions resolve to the first destination',
'[x][d]\n\n[d]: javascript:alert(1)\n[d]: https://www.cncf.io/',
['href', 'javascript:alert(1)'],
'disallowed URL scheme javascript:',
],
];

for (const [name, body, url, reason] of COMPILER_REJECTED) {
test(`the publish gate rejects what Docusaurus makes active: ${name}`, async () => {
assert.deepEqual((await compiledContent(body)).urls, [url]);
assert.ok(reasons(body).includes(reason));
});
}

const COMPILER_ACCEPTED = [
[
'headings, modern admonitions and reference links',
'## Overview\n\n:::note[Safe title]\n\n[Read more][d]\n\n:::\n\n[d]: https://www.cncf.io/',
[['href', 'https://www.cncf.io/']],
'Read more',
],
[
'ordinary fences keep a legacy admonition payload inert',
'```\n:::note x](javascript:alert(1))\n```',
[],
':::note x](javascript:alert(1))',
],
[
'inline code preserves JSX as text',
'Use `<img src="https://beacon.invalid/px.png" />` as an example.',
[],
'<img src="https://beacon.invalid/px.png" />',
],
[
'YAML fences preserve braces and angle brackets',
'```yaml\nkey: {a: 1}\nexample: <b>\n```',
[],
'key: {a: 1}\nexample: <b>',
],
];

for (const [name, body, urls, text] of COMPILER_ACCEPTED) {
test(`the publish gate and Docusaurus preserve valid content: ${name}`, async () => {
assert.deepEqual(reasons(body), []);
const compiled = await compiledContent(body);
assert.deepEqual(compiled.urls, urls);
assert.ok(compiled.text.some((value) => value.includes(text)));
});
}

test('the gate also rejects a composed bypass when legacy compatibility is enabled', async () => {
// future.v4 disables these rewrites on the current site. Exercise opt-in
// compatibility explicitly rather than claiming legacy titles are live now.
const options = {
...compilerOptions,
markdownConfig: {
...siteConfig.markdown,
mdx1Compat: {
...siteConfig.markdown.mdx1Compat,
headingIds: true,
admonitions: true,
},
},
};
const body =
'## Overview {#overview}\n\n```mdx-code-block\n:::note x](&#106;avascript:alert(1))\n````\n\n```';
assert.deepEqual((await compiledContent(body, options)).urls, [
['href', 'javascript:alert(1)'],
]);
assert.ok(reasons(body).includes('disallowed URL scheme javascript:'));
});
28 changes: 28 additions & 0 deletions tests/stryker-config.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// nothing, so a stale list would quietly stop explaining the run.

import assert from 'node:assert/strict';
import { spawnSync } from 'node:child_process';
import { existsSync, readdirSync, readFileSync } from 'node:fs';
import test from 'node:test';

Expand Down Expand Up @@ -49,3 +50,30 @@ test('breakThreshold stands down for the full-tree report lanes', () => {
assert.equal(breakThreshold('schedule'), null);
assert.equal(breakThreshold('workflow_dispatch'), null);
});

for (const [eventName, expected] of [
[undefined, 83],
['pull_request', 83],
['merge_group', null],
['schedule', null],
['workflow_dispatch', null],
]) {
test(`exported mutation config selects the threshold for ${eventName ?? 'local runs'}`, () => {
const env = { ...process.env };
delete env.GITHUB_EVENT_NAME;
if (eventName !== undefined) env.GITHUB_EVENT_NAME = eventName;
const run = spawnSync(
process.execPath,
[
'--input-type=module',
'--eval',
`import config from ${JSON.stringify(new URL('../stryker.config.mjs', import.meta.url).href)};
console.log(JSON.stringify(config.thresholds.break));`,
],
{ encoding: 'utf8', env },
);
assert.equal(run.error, undefined);
assert.equal(run.status, 0, run.stderr);
assert.equal(JSON.parse(run.stdout), expected);
});
}
Loading