@iris-eval/mcp-server 0.8.2 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -2
- package/dist/capabilities.d.ts +64 -0
- package/dist/capabilities.js +65 -0
- package/dist/config/defaults.js +17 -0
- package/dist/custom-rule-store.d.ts +4 -0
- package/dist/custom-rule-store.js +8 -3
- package/dist/dashboard/assets/{index-CyzO6OC7.js → index-CeJbaq6m.js} +1 -1
- package/dist/dashboard/index.html +1 -1
- package/dist/dashboard/routes/capabilities.d.ts +3 -0
- package/dist/dashboard/routes/capabilities.js +11 -0
- package/dist/dashboard/routes/health.d.ts +5 -1
- package/dist/dashboard/routes/health.js +15 -3
- package/dist/dashboard/routes/rules.js +4 -1
- package/dist/dashboard/routes/traces.d.ts +3 -0
- package/dist/dashboard/routes/traces.js +11 -30
- package/dist/dashboard/seed-demo-data.js +1 -1
- package/dist/dashboard/server.d.ts +2 -0
- package/dist/dashboard/server.js +6 -2
- package/dist/eval/accuracy.d.ts +41 -0
- package/dist/eval/accuracy.js +97 -0
- package/dist/eval/citation-verify/verifier.d.ts +16 -1
- package/dist/eval/citation-verify/verifier.js +14 -4
- package/dist/eval/compose.d.ts +57 -0
- package/dist/eval/compose.js +179 -0
- package/dist/eval/criticality.d.ts +15 -1
- package/dist/eval/criticality.js +6 -0
- package/dist/eval/decision-moment.js +33 -4
- package/dist/eval/dormant.d.ts +4 -0
- package/dist/eval/dormant.js +22 -0
- package/dist/eval/engine.d.ts +6 -2
- package/dist/eval/engine.js +126 -12
- package/dist/eval/failure-classes.d.ts +8 -0
- package/dist/eval/failure-classes.js +18 -0
- package/dist/eval/llm-judge/evaluator.d.ts +30 -0
- package/dist/eval/llm-judge/evaluator.js +26 -2
- package/dist/eval/published-accuracy.d.ts +230 -0
- package/dist/eval/published-accuracy.js +86 -0
- package/dist/eval/questions.d.ts +12 -0
- package/dist/eval/questions.js +14 -0
- package/dist/eval/response-schema.d.ts +652 -0
- package/dist/eval/response-schema.js +130 -0
- package/dist/eval/response.d.ts +12 -0
- package/dist/eval/response.js +30 -0
- package/dist/eval/risk.d.ts +60 -0
- package/dist/eval/risk.js +187 -0
- package/dist/eval/rules/completeness.js +36 -1
- package/dist/eval/rules/cost.d.ts +2 -2
- package/dist/eval/rules/cost.js +50 -6
- package/dist/eval/rules/custom.d.ts +0 -12
- package/dist/eval/rules/custom.js +22 -0
- package/dist/eval/rules/relevance.js +23 -2
- package/dist/eval/rules/safety.d.ts +6 -2
- package/dist/eval/rules/safety.js +224 -51
- package/dist/eval/seeded-random.d.ts +4 -0
- package/dist/eval/seeded-random.js +36 -0
- package/dist/eval/stamp.d.ts +14 -0
- package/dist/eval/stamp.js +89 -0
- package/dist/eval/stats.d.ts +33 -0
- package/dist/eval/stats.js +109 -0
- package/dist/eval/text/checksums.d.ts +23 -0
- package/dist/eval/text/checksums.js +97 -0
- package/dist/eval/text/normalise.d.ts +30 -0
- package/dist/eval/text/normalise.js +265 -0
- package/dist/eval/text/sentences.d.ts +15 -0
- package/dist/eval/text/sentences.js +149 -0
- package/dist/eval/verdict.d.ts +34 -0
- package/dist/eval/verdict.js +131 -0
- package/dist/index.js +5 -28
- package/dist/instructions.d.ts +17 -0
- package/dist/instructions.js +53 -0
- package/dist/judge-enablement.d.ts +34 -0
- package/dist/judge-enablement.js +78 -0
- package/dist/judge-enablement.json +10 -0
- package/dist/preferences.d.ts +1 -1
- package/dist/prompts.d.ts +3 -0
- package/dist/prompts.js +29 -0
- package/dist/resources/index.d.ts +5 -2
- package/dist/resources/index.js +65 -5
- package/dist/resources/uris.d.ts +12 -0
- package/dist/resources/uris.js +24 -0
- package/dist/retention.d.ts +20 -0
- package/dist/retention.js +44 -0
- package/dist/self-test.d.ts +1 -0
- package/dist/self-test.js +17 -3
- package/dist/server.d.ts +10 -1
- package/dist/server.js +34 -7
- package/dist/storage/index.js +1 -1
- package/dist/storage/migrations/007-eval-provenance.d.ts +3 -0
- package/dist/storage/migrations/007-eval-provenance.js +30 -0
- package/dist/storage/migrations/index.js +24 -4
- package/dist/storage/sqlite-adapter.d.ts +26 -1
- package/dist/storage/sqlite-adapter.js +149 -15
- package/dist/tools/delete-rule.d.ts +8 -0
- package/dist/tools/delete-rule.js +30 -38
- package/dist/tools/delete-trace.d.ts +5 -0
- package/dist/tools/delete-trace.js +24 -27
- package/dist/tools/deploy-rule.d.ts +13 -1
- package/dist/tools/deploy-rule.js +37 -34
- package/dist/tools/describe.d.ts +20 -0
- package/dist/tools/describe.js +36 -0
- package/dist/tools/errors.d.ts +36 -0
- package/dist/tools/errors.js +134 -0
- package/dist/tools/evaluate-output.d.ts +8 -1
- package/dist/tools/evaluate-output.js +39 -60
- package/dist/tools/evaluate-with-llm-judge.d.ts +34 -0
- package/dist/tools/evaluate-with-llm-judge.js +124 -69
- package/dist/tools/get-traces.d.ts +9 -0
- package/dist/tools/get-traces.js +29 -28
- package/dist/tools/index.d.ts +8 -0
- package/dist/tools/index.js +22 -1
- package/dist/tools/list-rules.d.ts +13 -0
- package/dist/tools/list-rules.js +43 -46
- package/dist/tools/log-trace.d.ts +4 -0
- package/dist/tools/log-trace.js +31 -29
- package/dist/tools/respond.d.ts +42 -0
- package/dist/tools/respond.js +90 -0
- package/dist/tools/strict-input.js +1 -1
- package/dist/tools/trace-link.d.ts +2 -0
- package/dist/tools/trace-link.js +13 -2
- package/dist/tools/verify-citations.d.ts +18 -2
- package/dist/tools/verify-citations.js +122 -96
- package/dist/types/config.d.ts +44 -0
- package/dist/types/eval.d.ts +309 -0
- package/dist/types/eval.js +2 -1
- package/dist/types/query.d.ts +2 -0
- package/package.json +1 -1
- package/server.json +2 -2
- package/dist/resources/dashboard-summary.d.ts +0 -3
- package/dist/resources/dashboard-summary.js +0 -16
- package/dist/resources/trace-detail.d.ts +0 -3
- package/dist/resources/trace-detail.js +0 -30
package/README.md
CHANGED
|
@@ -60,7 +60,7 @@ The trace lands on the dashboard with its scores. Prefer the MCP server headless
|
|
|
60
60
|
|
|
61
61
|
### Capture over HTTP (no model in the loop)
|
|
62
62
|
|
|
63
|
-
The ingest endpoint lives on the **dashboard port** — `6920` by default, not the MCP transport port — and it exists only while the dashboard is running. Pass `--dashboard` (or set `IRIS_DASHBOARD=true`); `--transport http` on its own does **not** start it, and a request to the transport port returns `404`. With the dashboard up, anything that can send an HTTP request can log a trace — and optionally run the deterministic evals in the same request:
|
|
63
|
+
The ingest endpoint lives on the **dashboard port** — `6920` by default, not the MCP transport port — and it exists only while the dashboard is running. Pass `--dashboard` (or set `IRIS_DASHBOARD=true`); `--transport http` on its own does **not** start it, and a request to the transport port returns `404`. With the dashboard up, anything that can send an HTTP request can log a trace — and optionally run the deterministic evals in the same request. `GET /api/v1/capabilities` on the same port says what this server can judge, what each rule needs, the judge state with the steps that enable it, and the limits — the same object the MCP resource `iris://capabilities` serves — so an HTTP caller has the frame an MCP client gets at initialize:
|
|
64
64
|
|
|
65
65
|
```bash
|
|
66
66
|
curl -s -X POST "http://127.0.0.1:6920/api/v1/traces" \
|
|
@@ -211,6 +211,13 @@ Iris registers nine tools that any MCP-compatible agent can invoke — full rule
|
|
|
211
211
|
- **`evaluate_with_llm_judge`** — Semantic eval via LLM (Anthropic or OpenAI). Five templates: accuracy, helpfulness, safety, correctness, faithfulness. Cost-capped, per-eval pricing disclosed. **Bring your own API key** (`IRIS_ANTHROPIC_API_KEY` or `IRIS_OPENAI_API_KEY`) — Iris doesn't proxy or relay LLM calls.
|
|
212
212
|
- **`verify_citations`** — Extract citations from output (numbered, author-year, URLs, DOIs), fetch sources behind an SSRF-guarded + domain-allowlisted resolver, and use an LLM judge to check whether each source actually supports the cited claim. Opt-in outbound HTTP. Same BYOK requirement as `evaluate_with_llm_judge`.
|
|
213
213
|
|
|
214
|
+
**Enable the LLM judge (optional; the deterministic rules never need it)**
|
|
215
|
+
1. Get an API key from Anthropic or OpenAI.
|
|
216
|
+
2. Put it in the environment of the process that runs Iris, not only your shell. Claude Code, Claude Desktop, Cursor and most MCP clients: the "env" block of the iris-eval entry in your MCP config — "iris-eval": { "command": "npx", "args": ["-y", "@iris-eval/mcp-server"], "env": { "IRIS_ANTHROPIC_API_KEY": "sk-ant-..." } } (IRIS_OPENAI_API_KEY for an OpenAI key). Docker: -e IRIS_ANTHROPIC_API_KEY=... on the run command. HTTP or CI: export it before starting iris-mcp.
|
|
217
|
+
3. Restart the MCP session. A running process never sees a variable set after it started.
|
|
218
|
+
4. Confirm from inside your client: read iris://capabilities — judge.enabled must be true there. A key exported in your shell is not passed to the process your client spawns unless its config lists it. On a machine, `npx @iris-eval/mcp-server --self-test` prints the judge line for that shell, and GET /api/v1/health reports judge.enabled on a running dashboard.
|
|
219
|
+
5. Spend guard: each call is capped by IRIS_LLM_JUDGE_MAX_COST_USD_PER_EVAL (default 0.25 USD) and refused before any spend if the worst case would exceed it. Iris calls the provider directly with your key and never proxies it.
|
|
220
|
+
|
|
214
221
|
When `IRIS_OTEL_ENDPOINT` is configured, `log_trace` calls also emit a best-effort OTLP/HTTP JSON export to any OpenTelemetry collector (Jaeger, Grafana Tempo, Datadog OTLP, Honeycomb, etc). See [docs/otel-integration.md](https://github.com/iris-eval/mcp-server/blob/main/docs/otel-integration.md).
|
|
215
222
|
|
|
216
223
|
### How `passed` is decided
|
|
@@ -357,7 +364,7 @@ With a key set, API clients — MCP clients, capture SDKs, `POST /api/v1/traces`
|
|
|
357
364
|
|
|
358
365
|
### Your data on disk
|
|
359
366
|
|
|
360
|
-
Everything Iris stores lives under your Iris home (`~/.iris`, or `IRIS_HOME`). `iris.db` keeps every trace's `input` and `output` **verbatim** — including any text `no_pii` goes on to flag; detection does not redact. At startup, traces and evaluations older than `retention.days` (default `30`, `0` disables, set in `config.json`) are deleted and the write-ahead log is checkpointed. To remove everything now, stop the server and run `--purge`: it deletes every stored trace, span and evaluation, compacts the database and truncates the write-ahead log so the text is gone from disk, and keeps your deployed rules, audit log and preferences.
|
|
367
|
+
Everything Iris stores lives under your Iris home (`~/.iris`, or `IRIS_HOME`). `iris.db` keeps every trace's `input` and `output` **verbatim** — including any text `no_pii` goes on to flag; detection does not redact unless you ask it to: `storage.redact: "critical_spans"` in `config.json` stores each evaluation's output with the spans a critical detector flagged replaced by `[REDACTED:<pattern>]` (off by default; the evidence offsets still index the text the caller saw). At startup, and every `retention.sweepIntervalHours` (default `24`, `0` disables the timer) after that, traces and evaluations older than `retention.days` (default `30`, `0` disables, set in `config.json`) are deleted and the write-ahead log is checkpointed. Deleting a trace — by `delete_trace` or by the sweep — erases the text of every evaluation linked to it (the output, the expected text, the suggestions and the rule messages) and stamps `erased_at`; the verdict, the scores and the evidence offsets stay. To remove everything now, stop the server and run `--purge`: it deletes every stored trace, span and evaluation, compacts the database and truncates the write-ahead log so the text is gone from disk, and keeps your deployed rules, audit log and preferences.
|
|
361
368
|
|
|
362
369
|
</details>
|
|
363
370
|
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import type { IrisConfig } from './types/config.js';
|
|
2
|
+
import type { EvalEngine } from './eval/engine.js';
|
|
3
|
+
import type { CustomRuleStore } from './custom-rule-store.js';
|
|
4
|
+
import { type BuiltInRuleMeta } from './eval/criticality.js';
|
|
5
|
+
import { type EvaluationQuestion } from './eval/questions.js';
|
|
6
|
+
import { type PublishedRuleAccuracy } from './eval/accuracy.js';
|
|
7
|
+
import { type JudgeProvider } from './judge-enablement.js';
|
|
8
|
+
/** The most inline custom rules one evaluate_output call may carry. */
|
|
9
|
+
export declare const MAX_INLINE_CUSTOM_RULES = 10;
|
|
10
|
+
/** The most citations one verify_citations call may verify. */
|
|
11
|
+
export declare const MAX_CITATIONS_PER_CALL = 50;
|
|
12
|
+
export interface RuleProof extends PublishedRuleAccuracy {
|
|
13
|
+
/** Positive predictive value at four prevalences: what a fire is worth when the failure is rare. */
|
|
14
|
+
ppvAt: Record<string, number | null>;
|
|
15
|
+
corpusVersion: string;
|
|
16
|
+
release: string;
|
|
17
|
+
labelling: 'same-model' | 'human-verified';
|
|
18
|
+
}
|
|
19
|
+
export interface Capabilities {
|
|
20
|
+
version: string;
|
|
21
|
+
transport: 'stdio' | 'http';
|
|
22
|
+
questions: readonly EvaluationQuestion[];
|
|
23
|
+
rules: Array<BuiltInRuleMeta & {
|
|
24
|
+
proof: RuleProof | null;
|
|
25
|
+
}>;
|
|
26
|
+
customRules: {
|
|
27
|
+
count: number;
|
|
28
|
+
enabled: number;
|
|
29
|
+
quarantined: unknown[];
|
|
30
|
+
};
|
|
31
|
+
judge: {
|
|
32
|
+
enabled: boolean;
|
|
33
|
+
provider: JudgeProvider | null;
|
|
34
|
+
providers: JudgeProvider[];
|
|
35
|
+
costCapUsd: number;
|
|
36
|
+
howToEnable: readonly string[];
|
|
37
|
+
};
|
|
38
|
+
citations: {
|
|
39
|
+
fetchAllowed: boolean;
|
|
40
|
+
domainsRestricted: boolean;
|
|
41
|
+
};
|
|
42
|
+
dashboard: {
|
|
43
|
+
enabled: boolean;
|
|
44
|
+
url: string | null;
|
|
45
|
+
mode: 'real' | 'demo';
|
|
46
|
+
};
|
|
47
|
+
limits: {
|
|
48
|
+
customRulesPerCall: number;
|
|
49
|
+
regexBudgetMs: number;
|
|
50
|
+
httpRateLimitPerMin: number;
|
|
51
|
+
citationsPerCall: number;
|
|
52
|
+
};
|
|
53
|
+
tools: readonly string[];
|
|
54
|
+
resources: readonly string[];
|
|
55
|
+
prompts: readonly string[];
|
|
56
|
+
}
|
|
57
|
+
export interface CapabilitiesContext {
|
|
58
|
+
config: IrisConfig;
|
|
59
|
+
evalEngine?: EvalEngine;
|
|
60
|
+
customRuleStore?: CustomRuleStore;
|
|
61
|
+
mode?: 'real' | 'demo';
|
|
62
|
+
}
|
|
63
|
+
export declare function ruleProof(name: string): RuleProof | null;
|
|
64
|
+
export declare function buildCapabilities(ctx: CapabilitiesContext): Capabilities;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { builtInRuleRoster } from './eval/criticality.js';
|
|
2
|
+
import { QUESTIONS } from './eval/questions.js';
|
|
3
|
+
import { publishedAccuracyFor, publishedProvenance, ppvAt } from './eval/accuracy.js';
|
|
4
|
+
import { REGEX_MATCH_BUDGET_MS } from './eval/rules/regex-sandbox.js';
|
|
5
|
+
import { JUDGE_ENABLE_STEPS, judgeState } from './judge-enablement.js';
|
|
6
|
+
import { LOCAL_TENANT } from './types/tenant.js';
|
|
7
|
+
import { TOOL_NAMES } from './tools/index.js';
|
|
8
|
+
import { RESOURCE_URIS } from './resources/uris.js';
|
|
9
|
+
import { EVALUATE_MY_AGENT_PROMPT } from './instructions.js';
|
|
10
|
+
/** The most inline custom rules one evaluate_output call may carry. */
|
|
11
|
+
export const MAX_INLINE_CUSTOM_RULES = 10;
|
|
12
|
+
/** The most citations one verify_citations call may verify. */
|
|
13
|
+
export const MAX_CITATIONS_PER_CALL = 50;
|
|
14
|
+
export function ruleProof(name) {
|
|
15
|
+
const acc = publishedAccuracyFor(name);
|
|
16
|
+
if (!acc)
|
|
17
|
+
return null;
|
|
18
|
+
const prov = publishedProvenance();
|
|
19
|
+
return {
|
|
20
|
+
...acc,
|
|
21
|
+
ppvAt: ppvAt(name),
|
|
22
|
+
corpusVersion: prov.corpusVersion,
|
|
23
|
+
release: prov.release,
|
|
24
|
+
labelling: prov.labelling,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
export function buildCapabilities(ctx) {
|
|
28
|
+
const { config } = ctx;
|
|
29
|
+
const roster = builtInRuleRoster(ctx.evalEngine ? (rule) => ctx.evalEngine.effectiveCriticality(rule) : undefined);
|
|
30
|
+
const custom = ctx.customRuleStore?.list(LOCAL_TENANT) ?? [];
|
|
31
|
+
const judge = judgeState();
|
|
32
|
+
const dashboardHost = config.dashboard.host === '0.0.0.0' || config.dashboard.host === '::' ? 'localhost' : config.dashboard.host;
|
|
33
|
+
return {
|
|
34
|
+
version: config.server.version,
|
|
35
|
+
transport: config.transport.type,
|
|
36
|
+
questions: QUESTIONS,
|
|
37
|
+
rules: roster.map((r) => ({ ...r, proof: ruleProof(r.name) })),
|
|
38
|
+
customRules: { count: custom.length, enabled: custom.filter((r) => r.enabled).length, quarantined: [] },
|
|
39
|
+
judge: {
|
|
40
|
+
enabled: judge.enabled,
|
|
41
|
+
provider: judge.provider,
|
|
42
|
+
providers: judge.providers,
|
|
43
|
+
costCapUsd: judge.costCapUsd,
|
|
44
|
+
howToEnable: JUDGE_ENABLE_STEPS,
|
|
45
|
+
},
|
|
46
|
+
citations: {
|
|
47
|
+
fetchAllowed: process.env.IRIS_CITATION_ALLOW_FETCH === '1',
|
|
48
|
+
domainsRestricted: Boolean(process.env.IRIS_CITATION_DOMAINS && process.env.IRIS_CITATION_DOMAINS.trim().length > 0),
|
|
49
|
+
},
|
|
50
|
+
dashboard: {
|
|
51
|
+
enabled: config.dashboard.enabled,
|
|
52
|
+
url: config.dashboard.enabled ? `http://${dashboardHost}:${config.dashboard.port}` : null,
|
|
53
|
+
mode: ctx.mode ?? 'real',
|
|
54
|
+
},
|
|
55
|
+
limits: {
|
|
56
|
+
customRulesPerCall: MAX_INLINE_CUSTOM_RULES,
|
|
57
|
+
regexBudgetMs: REGEX_MATCH_BUDGET_MS,
|
|
58
|
+
httpRateLimitPerMin: config.security.rateLimit.mcp,
|
|
59
|
+
citationsPerCall: MAX_CITATIONS_PER_CALL,
|
|
60
|
+
},
|
|
61
|
+
tools: TOOL_NAMES,
|
|
62
|
+
resources: RESOURCE_URIS,
|
|
63
|
+
prompts: [EVALUATE_MY_AGENT_PROMPT],
|
|
64
|
+
};
|
|
65
|
+
}
|
package/dist/config/defaults.js
CHANGED
|
@@ -16,6 +16,7 @@ export const PKG_VERSION = pkgVersion;
|
|
|
16
16
|
export const defaultConfig = {
|
|
17
17
|
storage: {
|
|
18
18
|
type: 'sqlite',
|
|
19
|
+
redact: 'none',
|
|
19
20
|
path: join(irisHome(), 'iris.db'),
|
|
20
21
|
},
|
|
21
22
|
server: {
|
|
@@ -58,12 +59,28 @@ export const defaultConfig = {
|
|
|
58
59
|
*/
|
|
59
60
|
criticalRules: [],
|
|
60
61
|
nonCriticalRules: [],
|
|
62
|
+
/*
|
|
63
|
+
* The verdict's six defaults (0.10.0), each a config key so a ruling is
|
|
64
|
+
* a one-line change. Measured before shipped: on the held-out split of
|
|
65
|
+
* the composite corpus the risk composer is right about shipping 57.7%
|
|
66
|
+
* of the time against the legacy 38.5%, at an IDENTICAL false-block
|
|
67
|
+
* rate, missing 55.6% of bad outputs against 83.3%. See
|
|
68
|
+
* proof/COMPOSITE.md, which regenerates on every release.
|
|
69
|
+
*/
|
|
70
|
+
composer: 'risk',
|
|
71
|
+
falsePassCost: 1,
|
|
72
|
+
onCriticalSkipped: 'unknown',
|
|
73
|
+
requiredEvidence: [],
|
|
74
|
+
defaultsGate: false,
|
|
75
|
+
prior: 0.5,
|
|
76
|
+
priorMode: 'per-output',
|
|
61
77
|
},
|
|
62
78
|
logging: {
|
|
63
79
|
level: 'info',
|
|
64
80
|
},
|
|
65
81
|
retention: {
|
|
66
82
|
days: 30,
|
|
83
|
+
sweepIntervalHours: 24,
|
|
67
84
|
},
|
|
68
85
|
security: {
|
|
69
86
|
apiKey: undefined,
|
|
@@ -9,6 +9,8 @@ export interface CustomRuleStore {
|
|
|
9
9
|
setEnabled(tenantId: TenantId, id: string, enabled: boolean, user?: string): DeployedCustomRule | undefined;
|
|
10
10
|
/** All ENABLED rules for a tenant in deploy order — what the engine should register. */
|
|
11
11
|
enabledRules(tenantId: TenantId): DeployedCustomRule[];
|
|
12
|
+
/** Entries in the store this version could not validate: kept on disk, never registered, never deleted by a deploy. */
|
|
13
|
+
quarantined(tenantId: TenantId): unknown[];
|
|
12
14
|
/** Path on disk for diagnostics. Different per tenant. */
|
|
13
15
|
pathFor(tenantId: TenantId): string;
|
|
14
16
|
auditPath: string;
|
|
@@ -21,6 +23,8 @@ export interface DeployRuleInput {
|
|
|
21
23
|
definition: CustomRuleDefinition;
|
|
22
24
|
sourceMomentId?: string;
|
|
23
25
|
user?: string;
|
|
26
|
+
/** With replace: true, the ids of the same-named rules retired first — recorded on the rule.deploy audit row. */
|
|
27
|
+
replaces?: string[];
|
|
24
28
|
}
|
|
25
29
|
export declare function createCustomRuleStore(opts?: {
|
|
26
30
|
/**
|
|
@@ -310,6 +310,9 @@ export function createCustomRuleStore(opts) {
|
|
|
310
310
|
list(tenantId) {
|
|
311
311
|
return [...load(tenantId)];
|
|
312
312
|
},
|
|
313
|
+
quarantined(tenantId) {
|
|
314
|
+
return state(tenantId).quarantined;
|
|
315
|
+
},
|
|
313
316
|
get(tenantId, id) {
|
|
314
317
|
return load(tenantId).find((r) => r.id === id);
|
|
315
318
|
},
|
|
@@ -344,9 +347,11 @@ export function createCustomRuleStore(opts) {
|
|
|
344
347
|
user: input.user ?? 'local',
|
|
345
348
|
ruleId: id,
|
|
346
349
|
ruleName: rule.name,
|
|
347
|
-
details:
|
|
348
|
-
|
|
349
|
-
|
|
350
|
+
details: {
|
|
351
|
+
severity: rule.severity,
|
|
352
|
+
...(input.sourceMomentId ? { sourceMomentId: input.sourceMomentId } : {}),
|
|
353
|
+
...(input.replaces?.length ? { replaces: input.replaces } : {}),
|
|
354
|
+
},
|
|
350
355
|
});
|
|
351
356
|
return validated;
|
|
352
357
|
},
|