Initial Commit

This commit is contained in:
2026-05-27 23:47:53 +01:00
parent fbc70f96e6
commit 9b28db724f
18103 changed files with 1600554 additions and 0 deletions

View File

@@ -0,0 +1,89 @@
# Safety Checks Schemas
## Purpose
Zod schemas for the configuration types of `@suaveplan/bitpacker-validation`'s safety subsystem: `SafetyLimits` (the absolute caps applied by every `SafetyChecker`), `SafetyPerformanceOptions` (selective skip flags for hot-path code), and `SchemaSafetyLimits` (per-schema embedded `_safety` overrides). Each schema is used at the `SafetyChecker` constructor boundary so a misconfigured limits bundle is rejected at the call site rather than producing surprising allow/deny behaviour deep in a pack/unpack chain.
The schemas are deliberately strict — `.strict()` rejects unknown keys, and numeric fields are bounded to non-negative integers because every limit is either a count (`maxRecursionDepth`, `maxArrayLength`, `maxObjectKeys`) or a byte count (`maxBufferSize`). A negative limit would be either a developer mistake or an attempt to bypass safety; either way, refusing it at parse time prevents the SafetyChecker from entering an undefined state.
## Features
- `safetyLimitsSchema` — strict, all fields required, numerics non-negative integers
- `safetyPerformanceOptionsSchema` — strict, all `skip*` flags optional booleans
- `schemaSafetyLimitsSchema` — strict, every override optional, `customValidators` is `string[]`
- `as unknown as z.ZodType<T>` casts where Zod's `T | undefined` collides with `exactOptionalPropertyTypes`
- `.strict()` on every schema — unknown keys throw
## Usage: Basic Example
```ts
import { SafetyChecker } from "@suaveplan/bitpacker-validation";
import { safetyLimitsSchema } from "@suaveplan/bitpacker-validation";
const limits = safetyLimitsSchema.parse({
maxBufferSize: 1024 * 1024,
maxRecursionDepth: 32,
maxArrayLength: 5000,
maxObjectKeys: 200,
allowInfiniteFloats: false,
allowNaNFloats: false,
});
const checker = new SafetyChecker(limits);
```
## Usage: Advanced Example
```ts
import {
SafetyChecker,
SafetyError,
safetyLimitsSchema,
safetyPerformanceOptionsSchema,
schemaSafetyLimitsSchema,
} from "@suaveplan/bitpacker-validation";
function makeSafeChecker(rawLimits: unknown, rawPerf: unknown): SafetyChecker {
const limitsResult = safetyLimitsSchema.safeParse(rawLimits);
if (!limitsResult.success) {
throw new SafetyError(
`Invalid safety limits: ${limitsResult.error.message}`,
"INVALID_LIMITS"
);
}
const perfResult = safetyPerformanceOptionsSchema.safeParse(rawPerf);
if (!perfResult.success) {
throw new SafetyError(
`Invalid performance options: ${perfResult.error.message}`,
"INVALID_PERF"
);
}
return new SafetyChecker(limitsResult.data, perfResult.data);
}
// Embedded per-schema override:
const blob = schemaSafetyLimitsSchema.parse({
maxBufferSize: 64 * 1024,
customValidators: ["png-magic-bytes"],
});
```
## API Reference
### `safetyLimitsSchema: z.ZodType<SafetyLimits>`
Validates a fully-populated `SafetyLimits` bundle. Every numeric field is required and must be a non-negative integer; both boolean flags are required. Throws `ZodError` on missing fields, negative values, or unknown keys.
### `safetyPerformanceOptionsSchema: z.ZodType<SafetyPerformanceOptions>`
Validates a `SafetyPerformanceOptions` bundle of optional `skip*` boolean flags. An empty bundle is valid. Throws `ZodError` on unknown keys or non-boolean values.
### `schemaSafetyLimitsSchema: z.ZodType<SchemaSafetyLimits>`
Validates an embedded `_safety` block. Every field is optional. `customValidators` must be a `string[]` (the names of validators registered out-of-band). Throws `ZodError` on unknown keys, negative numerics, or non-string validator names.
## Implementation Notes
- **Non-negative integer bounds.** Every numeric field is bounded by `.int().nonnegative()`. A floating-point limit would be ambiguous (round half-up? half-down?) and a negative limit is meaningless. Refusing both at parse time keeps the SafetyChecker contract simple.
- **`as unknown as z.ZodType<T>` cast.** Optional boolean fields under `exactOptionalPropertyTypes: true` produce `T | undefined` from Zod's `.optional()`, which doesn't match the target's `?:` declaration. The cast is purely a TypeScript shim — runtime semantics are identical.
- **`.strict()` everywhere.** `SafetyChecker` reads only the documented fields. A typo'd key would otherwise be silently dropped, leaving the caller convinced they had configured a limit they hadn't. Strict-mode is the only safe default for safety configuration.
- **No cross-field validation.** The schema does not enforce e.g. `maxBufferSize ≥ maxArrayLength * minElementSize` — that's a SafetyChecker invariant, not a config invariant. The schemas validate shape; the checker validates semantics.