mirror of
https://github.com/morluto/rea.git
synced 2026-10-26 17:35:11 +00:00
refactor(config): share bounded decimal setting validation
This commit is contained in:
1 parent
2411d60b5a
commit
91bacc5c14
6 files changed
+54
-89
No files matched your search
@@ -1,4 +1,4 @@
|
||||
import { z } from "zod";
|
||||
import { positiveDecimalIntegerSchema } from "./positiveDecimalInteger.js";
|
||||
|
||||
import { AnalysisResourceConstraintError } from "../domain/analysisErrorCore.js";
|
||||
import { ConfigurationError } from "../domain/configurationErrors.js";
|
||||
@@ -64,24 +64,12 @@ export type BridgePeer = "Hopper" | "Cutter" | "Ghidra";
|
||||
|
||||
export const bridgeMaxRequestBytesConstraint = `${BRIDGE_MAX_REQUEST_BYTES_SETTING} must be a positive decimal integer from ${String(MINIMUM_BRIDGE_MAX_REQUEST_BYTES)} to ${String(MAXIMUM_BRIDGE_MAX_REQUEST_BYTES)} bytes; the default is ${String(DEFAULT_BRIDGE_MAX_REQUEST_BYTES)} bytes (16 MiB). A value below ${String(MINIMUM_BRIDGE_MAX_REQUEST_BYTES)} bytes cannot carry the largest admitted symbol-name command, and a larger value is refused so the encoded payload plus its framing LF stays one string under Node's single-string ceiling.`;
|
||||
|
||||
const decimalInteger = /^[1-9]\d*$/u;
|
||||
|
||||
const withinRequestRange = (value: string): boolean => {
|
||||
// The pattern check reports a non-decimal value. Refine only bounds integers.
|
||||
if (!decimalInteger.test(value)) return true;
|
||||
const parsed = BigInt(value);
|
||||
return (
|
||||
parsed >= BigInt(MINIMUM_BRIDGE_MAX_REQUEST_BYTES) &&
|
||||
parsed <= BigInt(MAXIMUM_BRIDGE_MAX_REQUEST_BYTES)
|
||||
);
|
||||
};
|
||||
|
||||
/** Optional decimal byte count for the Hopper and Cutter request payload ceiling. */
|
||||
export const bridgeMaxRequestBytesSchema = z
|
||||
.string()
|
||||
.regex(decimalInteger, { error: bridgeMaxRequestBytesConstraint })
|
||||
.refine(withinRequestRange, { error: bridgeMaxRequestBytesConstraint })
|
||||
.transform(Number);
|
||||
export const bridgeMaxRequestBytesSchema = positiveDecimalIntegerSchema(
|
||||
MINIMUM_BRIDGE_MAX_REQUEST_BYTES,
|
||||
MAXIMUM_BRIDGE_MAX_REQUEST_BYTES,
|
||||
bridgeMaxRequestBytesConstraint,
|
||||
);
|
||||
|
||||
/** Resolve the effective ceiling from one environment value. */
|
||||
export const parseBridgeMaxRequestBytes = (
|
||||
|
||||
@@ -3,7 +3,7 @@ import {
|
||||
CAPTURE_DECODER_SEMI_SPACE_MIB,
|
||||
MAXIMUM_CAPTURE_DECODER_OLD_GENERATION_MIB,
|
||||
} from "../domain/analysisResourceLimits.js";
|
||||
import { z } from "zod";
|
||||
import { positiveDecimalIntegerSchema } from "./positiveDecimalInteger.js";
|
||||
|
||||
import { ConfigurationError } from "../domain/configurationErrors.js";
|
||||
import { err, ok, type Result } from "../domain/result.js";
|
||||
@@ -24,24 +24,13 @@ export const DEFAULT_CAPTURE_DECODER_HEAP: CaptureDecoderHeap = {
|
||||
|
||||
export const captureDecoderHeapConstraint = `${CAPTURE_DECODER_OLD_GENERATION_SETTING} must be a decimal integer from ${String(CAPTURE_DECODER_SEMI_SPACE_MIB)} to ${String(MAXIMUM_CAPTURE_DECODER_OLD_GENERATION_MIB)} MiB; the default is ${String(DEFAULT_CAPTURE_DECODER_OLD_GENERATION_MIB)} MiB. An old generation below the decoder's ${String(CAPTURE_DECODER_SEMI_SPACE_MIB)} MiB semi-space aborts Node during startup instead of enforcing a limit, and a larger value is refused.`;
|
||||
|
||||
const decimalInteger = /^[1-9]\d*$/u;
|
||||
|
||||
const withinHeapRange = (value: string): boolean => {
|
||||
// The pattern check reports a non-decimal value. Refine only bounds integers.
|
||||
if (!decimalInteger.test(value)) return true;
|
||||
const parsed = BigInt(value);
|
||||
return (
|
||||
parsed >= BigInt(CAPTURE_DECODER_SEMI_SPACE_MIB) &&
|
||||
parsed <= BigInt(MAXIMUM_CAPTURE_DECODER_OLD_GENERATION_MIB)
|
||||
);
|
||||
};
|
||||
|
||||
/** Optional decimal mebibyte count for the HAR/SAZ/qlog old-generation heap. */
|
||||
export const captureDecoderOldGenerationMiBSchema = z
|
||||
.string()
|
||||
.regex(decimalInteger, { error: captureDecoderHeapConstraint })
|
||||
.refine(withinHeapRange, { error: captureDecoderHeapConstraint })
|
||||
.transform(Number);
|
||||
export const captureDecoderOldGenerationMiBSchema =
|
||||
positiveDecimalIntegerSchema(
|
||||
CAPTURE_DECODER_SEMI_SPACE_MIB,
|
||||
MAXIMUM_CAPTURE_DECODER_OLD_GENERATION_MIB,
|
||||
captureDecoderHeapConstraint,
|
||||
);
|
||||
|
||||
/** Resolve the effective heap from one environment value. */
|
||||
export const parseCaptureDecoderHeap = (
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { z } from "zod";
|
||||
import { positiveDecimalIntegerSchema } from "./positiveDecimalInteger.js";
|
||||
|
||||
import { ConfigurationError } from "../domain/configurationErrors.js";
|
||||
import { err, ok, type Result } from "../domain/result.js";
|
||||
@@ -69,26 +69,12 @@ const PHASES = [
|
||||
const phaseConstraint = (phase: McpPhaseBudgetDefinition): string =>
|
||||
`${phase.setting} must be a positive decimal integer from ${String(MCP_PHASE_BUDGET_FLOOR_MS)} to ${String(MCP_PHASE_BUDGET_MAXIMUM_MS)} ms; the default is ${String(phase.defaultMilliseconds)} ms. Node schedules a delay above that maximum as 1 ms, so a larger value is refused.`;
|
||||
|
||||
const decimalInteger = /^[1-9]\d*$/u;
|
||||
|
||||
const withinPhaseBudgetRange = (value: string): boolean => {
|
||||
// The pattern check reports a non-decimal value. Refine only bounds integers.
|
||||
if (!decimalInteger.test(value)) return true;
|
||||
const parsed = BigInt(value);
|
||||
return (
|
||||
parsed >= BigInt(MCP_PHASE_BUDGET_FLOOR_MS) &&
|
||||
parsed <= BigInt(MCP_PHASE_BUDGET_MAXIMUM_MS)
|
||||
const phaseBudgetSchema = (phase: McpPhaseBudgetDefinition) =>
|
||||
positiveDecimalIntegerSchema(
|
||||
MCP_PHASE_BUDGET_FLOOR_MS,
|
||||
MCP_PHASE_BUDGET_MAXIMUM_MS,
|
||||
phaseConstraint(phase),
|
||||
);
|
||||
};
|
||||
|
||||
const phaseBudgetSchema = (phase: McpPhaseBudgetDefinition) => {
|
||||
const constraint = phaseConstraint(phase);
|
||||
return z
|
||||
.string()
|
||||
.regex(decimalInteger, { error: constraint })
|
||||
.refine(withinPhaseBudgetRange, { error: constraint })
|
||||
.transform(Number);
|
||||
};
|
||||
|
||||
/** Optional decimal millisecond count for the MCP initialize phase budget. */
|
||||
export const mcpInitializeBudgetMsSchema = phaseBudgetSchema(PHASES[0]);
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
import { z } from "zod";
|
||||
|
||||
const decimalInteger = /^[1-9]\d*$/u;
|
||||
|
||||
/** Preserve exact decimal bounds before conversion to a runtime number. */
|
||||
export const positiveDecimalIntegerSchema = (
|
||||
minimum: number,
|
||||
maximum: number,
|
||||
constraint: string,
|
||||
) =>
|
||||
z
|
||||
.string()
|
||||
.regex(decimalInteger, { error: constraint })
|
||||
.refine(
|
||||
(value) => {
|
||||
// The pattern owns malformed input; range checks only interpret integers.
|
||||
if (!decimalInteger.test(value)) return true;
|
||||
const parsed = BigInt(value);
|
||||
return parsed >= BigInt(minimum) && parsed <= BigInt(maximum);
|
||||
},
|
||||
{ error: constraint },
|
||||
)
|
||||
.transform(Number);
|
||||
@@ -2,7 +2,7 @@ import {
|
||||
DEFAULT_REGEX_MATCHING_DEADLINE_MS,
|
||||
MAXIMUM_REGEX_MATCHING_DEADLINE_MS,
|
||||
} from "../domain/analysisResourceLimits.js";
|
||||
import { z } from "zod";
|
||||
import { positiveDecimalIntegerSchema } from "./positiveDecimalInteger.js";
|
||||
|
||||
import { ConfigurationError } from "../domain/configurationErrors.js";
|
||||
import { err, ok, type Result } from "../domain/result.js";
|
||||
@@ -22,21 +22,12 @@ export const DEFAULT_REGEX_MATCHING_DEADLINE: RegexMatchingDeadline = {
|
||||
|
||||
export const regexMatchingDeadlineConstraint = `${REGEX_MATCHING_DEADLINE_SETTING} must be a positive decimal integer from 1 to ${String(MAXIMUM_REGEX_MATCHING_DEADLINE_MS)} ms; the default is ${String(DEFAULT_REGEX_MATCHING_DEADLINE_MS)} ms. Node schedules a delay above that maximum as 1 ms, so a larger value is refused.`;
|
||||
|
||||
const decimalInteger = /^[1-9]\d*$/u;
|
||||
|
||||
const withinDeadlineRange = (value: string): boolean => {
|
||||
// The pattern check reports a non-decimal value. Refine only bounds integers.
|
||||
if (!decimalInteger.test(value)) return true;
|
||||
const parsed = BigInt(value);
|
||||
return parsed >= 1n && parsed <= BigInt(MAXIMUM_REGEX_MATCHING_DEADLINE_MS);
|
||||
};
|
||||
|
||||
/** Optional decimal millisecond count for the supervised regex matching deadline. */
|
||||
export const regexMatchingDeadlineMsSchema = z
|
||||
.string()
|
||||
.regex(decimalInteger, { error: regexMatchingDeadlineConstraint })
|
||||
.refine(withinDeadlineRange, { error: regexMatchingDeadlineConstraint })
|
||||
.transform(Number);
|
||||
export const regexMatchingDeadlineMsSchema = positiveDecimalIntegerSchema(
|
||||
1,
|
||||
MAXIMUM_REGEX_MATCHING_DEADLINE_MS,
|
||||
regexMatchingDeadlineConstraint,
|
||||
);
|
||||
|
||||
/** Resolve the effective deadline from one environment value. */
|
||||
export const parseRegexMatchingDeadline = (
|
||||
|
||||
@@ -3,7 +3,7 @@ import {
|
||||
MINIMUM_REGEX_WORKER_HEAP_REQUEST_MIB,
|
||||
MAXIMUM_REGEX_WORKER_HEAP_REQUEST_MIB,
|
||||
} from "../domain/analysisResourceLimits.js";
|
||||
import { z } from "zod";
|
||||
import { positiveDecimalIntegerSchema } from "./positiveDecimalInteger.js";
|
||||
|
||||
import { ConfigurationError } from "../domain/configurationErrors.js";
|
||||
import { err, ok, type Result } from "../domain/result.js";
|
||||
@@ -24,24 +24,12 @@ export const DEFAULT_REGEX_WORKER_HEAP_REQUEST: RegexWorkerHeapRequest = {
|
||||
|
||||
export const regexWorkerHeapRequestConstraint = `${REGEX_WORKER_HEAP_REQUEST_SETTING} must be a decimal integer from ${String(MINIMUM_REGEX_WORKER_HEAP_REQUEST_MIB)} to ${String(MAXIMUM_REGEX_WORKER_HEAP_REQUEST_MIB)} MiB; the default is ${String(DEFAULT_REGEX_WORKER_HEAP_REQUEST_MIB)} MiB. A request below ${String(MINIMUM_REGEX_WORKER_HEAP_REQUEST_MIB)} MiB aborts the worker during startup, and a larger value is refused.`;
|
||||
|
||||
const decimalInteger = /^[1-9]\d*$/u;
|
||||
|
||||
const withinHeapRange = (value: string): boolean => {
|
||||
// The pattern check reports a non-decimal value. Refine only bounds integers.
|
||||
if (!decimalInteger.test(value)) return true;
|
||||
const parsed = BigInt(value);
|
||||
return (
|
||||
parsed >= BigInt(MINIMUM_REGEX_WORKER_HEAP_REQUEST_MIB) &&
|
||||
parsed <= BigInt(MAXIMUM_REGEX_WORKER_HEAP_REQUEST_MIB)
|
||||
);
|
||||
};
|
||||
|
||||
/** Optional decimal mebibyte count for the regex worker old-generation request. */
|
||||
export const regexWorkerHeapRequestMiBSchema = z
|
||||
.string()
|
||||
.regex(decimalInteger, { error: regexWorkerHeapRequestConstraint })
|
||||
.refine(withinHeapRange, { error: regexWorkerHeapRequestConstraint })
|
||||
.transform(Number);
|
||||
export const regexWorkerHeapRequestMiBSchema = positiveDecimalIntegerSchema(
|
||||
MINIMUM_REGEX_WORKER_HEAP_REQUEST_MIB,
|
||||
MAXIMUM_REGEX_WORKER_HEAP_REQUEST_MIB,
|
||||
regexWorkerHeapRequestConstraint,
|
||||
);
|
||||
|
||||
/** Resolve the effective request from one environment value. */
|
||||
export const parseRegexWorkerHeapRequest = (
|
||||
|
||||
Reference in new issue
Block a user