mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-10-19 05:20:05 +00:00
Some checks are pending
CI / Change Classification (push) Waiting to run
CI / Lint (push) Blocked by required conditions
CI / i18n Glossary (zh-CN, ko) (push) Blocked by required conditions
CI / Docs Sync (Strict) (push) Blocked by required conditions
CI / PR Test Policy (push) Waiting to run
CI / Quality Ratchet (push) Blocked by required conditions
CI / Quality Gates (Extended) (push) Blocked by required conditions
CI / Docs Lint (prose — advisory) (push) Blocked by required conditions
CI / i18n UI Coverage (push) Blocked by required conditions
CI / i18n Validation (all languages) (push) Blocked by required conditions
CI / Build (push) Blocked by required conditions
CI / Package Artifact (push) Blocked by required conditions
CI / Electron Package Smoke (ubuntu-latest) (push) Blocked by required conditions
CI / Electron Package Smoke (windows-latest) (push) Blocked by required conditions
CI / Unit Tests (1/8) (push) Blocked by required conditions
CI / Unit Tests (2/8) (push) Blocked by required conditions
CI / Unit Tests (3/8) (push) Blocked by required conditions
CI / Unit Tests (4/8) (push) Blocked by required conditions
CI / Unit Tests (5/8) (push) Blocked by required conditions
CI / Unit Tests (6/8) (push) Blocked by required conditions
CI / Unit Tests (7/8) (push) Blocked by required conditions
CI / Unit Tests (8/8) (push) Blocked by required conditions
CI / Bun SQLite Compatibility (push) Blocked by required conditions
CI / Vitest (MCP / autoCombo / UI components) (push) Blocked by required conditions
CI / Coverage (push) Blocked by required conditions
CI / SonarQube (push) Blocked by required conditions
CI / PR Coverage Comment (push) Blocked by required conditions
CI / E2E Tests (4/9) (push) Blocked by required conditions
CI / E2E Tests (5/9) (push) Blocked by required conditions
CI / E2E Tests (6/9) (push) Blocked by required conditions
CI / E2E Tests (7/9) (push) Blocked by required conditions
CI / E2E Tests (8/9) (push) Blocked by required conditions
CI / Bun SQLite Compatibility-1 (push) Blocked by required conditions
CI / E2E Tests (1/9) (push) Blocked by required conditions
CI / E2E Tests (2/9) (push) Blocked by required conditions
CI / E2E Tests (3/9) (push) Blocked by required conditions
CI / Security Tests (push) Blocked by required conditions
CI / Ecosystem E2E (live server) (push) Blocked by required conditions
Publish to Docker Hub / Resolve Docker release metadata (push) Waiting to run
Publish to Docker Hub / Build Docker (linux/amd64) (push) Blocked by required conditions
Publish to Docker Hub / Build Docker (linux/arm64) (push) Blocked by required conditions
Publish to Docker Hub / Publish multi-arch manifests (push) Blocked by required conditions
Lock released branch / lock-branch (push) Waiting to run
Lock released branch / guard-no-push-after-release (push) Waiting to run
Release-Green (continuous) / Validate active release branch (push) Waiting to run
Release-Green (continuous) / Validate main branch (push) Waiting to run
Quality Gates / Vitest (fast-path) (push) Blocked by required conditions
Quality Gates / Change Classification (push) Waiting to run
Quality Gates / Docs Gates (fast-path) (push) Blocked by required conditions
Quality Gates / Fast Quality Gates (push) Blocked by required conditions
Quality Gates / Merge integrity (changelog + generated skills) (push) Waiting to run
Quality Gates / Gate / Quality (push) Blocked by required conditions
Radar Export / publish-export (push) Waiting to run
CI / E2E Tests (9/9) (push) Blocked by required conditions
CI / Integration Tests (1/2) (push) Blocked by required conditions
CI / Integration Tests (2/2) (push) Blocked by required conditions
CI / Protocol Clients E2E (live server, advisory) (push) Blocked by required conditions
CI / Gate / CI (push) Blocked by required conditions
CI / CI Dashboard (push) Blocked by required conditions
Release-Green (continuous) / Bank ratchet shrinks (push) Waiting to run
Release-Green (continuous) / Baseline headroom (push) Waiting to run
Quality Gates / Unit Tests fast-path (1/4) (push) Blocked by required conditions
Quality Gates / Unit Tests fast-path (2/4) (push) Blocked by required conditions
Quality Gates / Unit Tests fast-path (3/4) (push) Blocked by required conditions
Quality Gates / Unit Tests fast-path (4/4) (push) Blocked by required conditions
Quality Gates / No new ESLint warnings (push) Blocked by required conditions
Release acceptance / Release acceptance (push) Waiting to run
OpenSSF Scorecard / Scorecard analysis (push) Waiting to run
Adds the opt-in 'omniroute models test-add' operation and POST /api/provider-models/validate-and-add: a model is registered only after bounded generation, streamed synthetic tool-call and continuation proofs on the selected connection. Protected surface (9 generated skills/**/SKILL.md + endpoints.md, flag documentation only): explicit owner approval given in chat; diff reviewed for external execution (none beyond a localhost curl example). Tip merged cleanly. Independent validation: 126/126 tests across 16 files, typecheck:core, open-sse typecheck, eslint on touched files, check:cycles, check:docs-all, file-size, changelog-integrity and complexity green. Route reviewed: strict Zod schema with allowInference literal true, management auth always required, errors via buildErrorBody, no client-supplied base URL. Not validated: live provider run on the VPS.
89 lines
2.6 KiB
TypeScript
89 lines
2.6 KiB
TypeScript
import "./_helpers/modelValidationEnvironment.ts";
|
|
import assert from "node:assert/strict";
|
|
import test from "node:test";
|
|
import { withPluginExecutionGuard } from "../../src/lib/plugins/executionGuard.ts";
|
|
import { createValidationPluginFence } from "../../src/lib/modelValidation/pluginFence.ts";
|
|
import {
|
|
emitHook,
|
|
emitHookBlocking,
|
|
registerHook,
|
|
runOnResponse,
|
|
unregisterHooks,
|
|
} from "../../src/lib/plugins/hooks.ts";
|
|
|
|
test("request guard blocks every plugin handler without altering unguarded traffic", async () => {
|
|
let calls = 0;
|
|
let violations = 0;
|
|
registerHook("onResponse", "validation-guard", () => {
|
|
calls++;
|
|
});
|
|
const guard = {
|
|
assertIdle() {},
|
|
reject(): never {
|
|
violations++;
|
|
throw new Error("strict plugin fence");
|
|
},
|
|
};
|
|
const context = { requestId: "test", provider: "openai", model: "test", body: {}, metadata: {} };
|
|
try {
|
|
for (const run of [
|
|
() => emitHook("onResponse", {}),
|
|
() => emitHookBlocking("onResponse", {}),
|
|
() => runOnResponse(context, {}),
|
|
]) {
|
|
await assert.rejects(() => withPluginExecutionGuard(guard, run), /strict plugin fence/);
|
|
}
|
|
assert.equal(calls, 0);
|
|
assert.equal(violations, 3);
|
|
await emitHook("onResponse", {});
|
|
await emitHookBlocking("onResponse", {});
|
|
await runOnResponse(context, {});
|
|
assert.equal(calls, 3);
|
|
} finally {
|
|
unregisterHooks("validation-guard");
|
|
}
|
|
});
|
|
|
|
test("delayed request work retains its guard after the operation returns", async () => {
|
|
let calls = 0;
|
|
let release: () => void;
|
|
const pending = new Promise<void>((resolve) => {
|
|
release = resolve;
|
|
});
|
|
let late: Promise<void>;
|
|
const guard = {
|
|
assertIdle() {},
|
|
reject(): never {
|
|
throw new Error("late strict plugin fence");
|
|
},
|
|
};
|
|
withPluginExecutionGuard(guard, () => {
|
|
late = pending.then(() => emitHook("onResponse", {}));
|
|
});
|
|
registerHook("onResponse", "validation-late-guard", () => {
|
|
calls++;
|
|
});
|
|
try {
|
|
release();
|
|
await assert.rejects(() => late, /late strict plugin fence/);
|
|
assert.equal(calls, 0);
|
|
} finally {
|
|
unregisterHooks("validation-late-guard");
|
|
}
|
|
});
|
|
|
|
test("a swallowed hook rejection stays latched after the plugin is unregistered", async () => {
|
|
const fence = createValidationPluginFence();
|
|
fence.assertIdle();
|
|
let calls = 0;
|
|
registerHook("onError", "validation-swallowed", () => {
|
|
calls++;
|
|
});
|
|
try {
|
|
await withPluginExecutionGuard(fence, () => emitHook("onError", {})).catch(() => {});
|
|
} finally {
|
|
unregisterHooks("validation-swallowed");
|
|
}
|
|
assert.equal(calls, 0);
|
|
assert.throws(() => fence.assertIdle(), { code: "VALIDATION_PLUGINS_UNSUPPORTED" });
|
|
});
|