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
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- **Source-scanner negative guards** (`tests/unit/source-scanner-guards.test.ts`): hard gate (no baseline, no allowlist) that fails any test variable holding project source read as text whose usages are _all_ negative guards (`assert.doesNotMatch` / `.includes(…) === false`). Those assertions pass against an empty string, so extracting the guarded code into a new file keeps them green while they protect nothing — silently deleting regression coverage during the file-splitting campaign. Classification runs on logical statements with strings, regexes, and comments blanked out, so a guard wrapped across lines cannot slip past. Fixes the 7 existing violations across 6 files with one positive anchor each; two are security scope guards that were held only by multi-line negative assertions — the SSRF guards on `/api/sync/initialize` (`providers-autosync-ssrf-323`) and the proxy-bypass guards on `chatHelpers.ts` / `chatCore.ts` (`proxy-bypass-scope-guard-3226`), the latter pinned to `handleChatCore` precisely because that file is a decomposition target. Adds `tests/_helpers/readSrc.ts`, a repo-root-relative reader that throws on a missing or empty file instead of returning `""`. Regression guards: two synthetic multi-line cases in the gate's own suite. First step of the god-file decomposition campaign tracked in #8617.
9 changes: 0 additions & 9 deletions skills/cli-backup-sync/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,15 +75,6 @@ omniroute backup disable

### `backup status`

**Flags:**

- `--name <name>`
- `--cloud`
- `--encrypt`
- `--key-file <path>`
- `--exclude <pattern>`
- `--retention <n>`

**Example:**

```bash
Expand Down
57 changes: 57 additions & 0 deletions tests/_helpers/readSrc.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// Shared reader for tests that assert against project source read as text.
//
// Why this throws instead of returning "" on a missing/empty file:
// static source scanners frequently carry NEGATIVE guards, e.g.
// assert.equal(src.includes(">Active Endpoints<"), false)
// A negative guard passes trivially against an empty string. So if the source is
// moved, renamed, or split into a new component file, a silently-empty read keeps
// the assertion green while it guards nothing at all — the regression coverage is
// deleted without a single test turning red. Failing loudly at read time makes
// that class of silent coverage loss impossible.
//
// The companion hard gate is tests/unit/source-scanner-guards.test.ts, which
// requires every source-bound variable to carry at least one positive anchor.
import { readFileSync } from "node:fs";
import { dirname, isAbsolute, join, resolve } from "node:path";
import { fileURLToPath } from "node:url";

/**
* Repo root, derived from this file's location (tests/_helpers/) — never from cwd, so
* the reader behaves identically however the test runner was invoked.
*/
const REPO_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), "..", "..");

/**
* Read a project source file as UTF-8 text, relative to the repository root.
*
* @param relPath Repo-relative path, e.g. "open-sse/executors/claude-web.ts".
* @throws If the file does not exist or its content is empty/whitespace-only.
*/
export function readSrc(relPath: string): string {
const absPath = isAbsolute(relPath) ? relPath : join(REPO_ROOT, relPath);

let content: string;
try {
content = readFileSync(absPath, "utf8");
} catch (err) {
const reason = err instanceof Error ? err.message : String(err);
throw new Error(
`readSrc("${relPath}"): cannot read source file at ${absPath}. ` +
`The file was probably moved, renamed, or split — update the test to point at ` +
`its new location instead of letting the assertions guard nothing. (${reason})`
);
}

if (!content.trim()) {
throw new Error(
`readSrc("${relPath}"): source file at ${absPath} is empty or whitespace-only. ` +
`Negative guards (assert.doesNotMatch / .includes(...) === false) pass trivially ` +
`against empty content, so an empty read would silently disable this test.`
);
}

return content;
}

/** The repository root this helper resolves against. Exposed for tests that need it. */
export { REPO_ROOT };
3 changes: 3 additions & 0 deletions tests/unit/claude-web-transport.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,9 @@ describe("Claude Web executor transport orchestration", () => {
"utf8"
);

// Anchor: proves the read still resolved to the real executor module, so the
// negative guard below cannot pass against a moved/emptied file.
assert.match(executorSource, /export class ClaudeWebExecutor extends BaseExecutor/);
assert.doesNotMatch(executorSource, /claudeTurnstileSolver|getCfClearanceToken|tryBackedChat/);
assert.doesNotMatch(indexSource, /ClaudeWebWithAutoRefresh/);
assert.match(indexSource, /"claude-web": new ClaudeWebExecutor\(\)/);
Expand Down
3 changes: 3 additions & 0 deletions tests/unit/dashboard-localization-contract.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,9 @@ test("production audit regressions stay localized and provider icons stay bounde
}

const endpoint = readSource("src/app/(dashboard)/dashboard/endpoint/EndpointPageClient.tsx");
// Anchor: the page component itself, so the raw-copy guards below cannot pass
// against a file that was moved, renamed, or split apart.
assert.match(endpoint, /export default function APIPageClient\(/);
for (const rawText of [
'label: "Context Sources"',
">Active Endpoints<",
Expand Down
3 changes: 3 additions & 0 deletions tests/unit/gamification-display-contract.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ test("profile renders mapped icons and localized badge criteria", () => {
});

test("token page no longer contains known raw English controls", () => {
// Anchor: the page component itself, so the raw-copy guards below cannot pass
// against a file that was moved, renamed, or split apart.
assert.match(tokensSource, /export default function TokensPage\(/);
for (const rawText of [
"Send Tokens",
"Create Invite",
Expand Down
3 changes: 3 additions & 0 deletions tests/unit/providers-autosync-ssrf-323.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ test("POST /api/providers auto-sync uses the trusted internal origin (not reques
});

test("POST /api/sync/initialize never forwards the client Origin to model sync", () => {
// Anchor: the route handler itself, so the SSRF guards below cannot pass against a
// file that was moved, renamed, or split apart.
assert.match(syncInitializeRouteSrc, /export async function POST\(/);
assert.doesNotMatch(
syncInitializeRouteSrc,
/request\.headers\.get\(["']origin["']\)/,
Expand Down
6 changes: 6 additions & 0 deletions tests/unit/proxy-bypass-scope-guard-3226.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,18 @@ test("bypassProxyPatch is absent from the chat hot path (scope guard — #3226)"
// If either of these assertions starts failing, a code change has silently
// extended the NVIDIA-only exception to the chat/usage egress path.
const chatHelpers = readFileSync("src/sse/handlers/chatHelpers.ts", "utf8");
// Anchor: without it, extracting the egress code into another module would make the
// negative guard below pass against a file that no longer contains the hot path.
assert.match(chatHelpers, /export async function executeChatWithBreaker\(/);
assert.ok(
!chatHelpers.includes("bypassProxyPatch"),
"chatHelpers.ts must not bypass the proxy patch — only NVIDIA validation may do this (#3226)"
);

const chatCore = readFileSync("open-sse/handlers/chatCore.ts", "utf8");
// Anchor: chatCore.ts is actively being split, so pin the entry point the route
// imports — the negative guard is worthless if this read silently misses the file.
assert.match(chatCore, /export async function handleChatCore\(/);
assert.ok(
!chatCore.includes("bypassProxyPatch"),
"chatCore.ts must not bypass the proxy patch — only NVIDIA validation may do this (#3226)"
Expand Down
12 changes: 4 additions & 8 deletions tests/unit/settings-ui-layout-static.test.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,7 @@
import test from "node:test";
import assert from "node:assert/strict";
import { readFileSync } from "node:fs";
import { dirname, join } from "node:path";
import { fileURLToPath } from "node:url";

const ROOT = join(dirname(fileURLToPath(import.meta.url)), "..", "..");

function readSrc(path: string): string {
return readFileSync(join(ROOT, path), "utf8");
}
import { readSrc } from "../_helpers/readSrc";

function assertInOrder(source: string, labels: string[]) {
let lastIndex = -1;
Expand All @@ -34,6 +27,9 @@ test("Usage Token Buffer lives in AI settings instead of General storage", () =>
);

assert.match(aiPage, /UsageTokenBufferTab/);
// Anchor: the storage tab component itself, so the negative guard below cannot
// pass against a file that was moved, renamed, or split apart.
assert.match(generalStorage, /export default function SystemStorageTab\(/);
assert.doesNotMatch(generalStorage, /storageUsageTokenBuffer/);
});

Expand Down
Loading
Loading