import type { AssurancePolicy } from "../assurance.js"; /** * How much a {@link securityBaseline} demands. Each level is a superset of the one before it, so * raising the level only ever adds findings. * * - `"essential"` - the invariants that hold for ANY app and never false-positive on a reasonable * one: a body read must be bounded, an unlimited body may never claim to be bounded, an agent tool * ingress must be bounded, and an authenticated state change must prove CSRF. Every required piece * of evidence here is either published by the core from the route schema or only demanded when the * route already opted into the risk (CSRF is required only where authentication is present). Safe to * adopt on day one. * - `"standard"` (default) - essential, plus: a route the app itself classified as `pii` or higher * must be authenticated, whether it reads or writes. High signal, low noise - it fires only on * routes the application already labelled sensitive. * - `"strict"` - standard, plus the opinionated, higher-friction requirements: every route must carry * a response contract, every read must carry security headers, and every mutation must be rate * limited. These need middleware the app has to install, so they are opt-in rather than default. */ export type SecurityBaselineLevel = "essential" | "standard" | "strict"; /** Tuning for {@link securityBaseline}. Every knob only ever tightens the policy. */ export interface SecurityBaselineOptions { /** How much the baseline demands. Default `"standard"`. See {@link SecurityBaselineLevel}. */ readonly level?: SecurityBaselineLevel; /** * How to treat a route no rule matched. Default `"ignore"` so the baseline is purely additive - it * asserts the invariants below and stays silent on everything else, which lets a project adopt it * without first classifying its whole route table. Set `"error"` to make an unclassified route a * finding, turning the baseline into a closed allow-list (recommended once the table is covered). */ readonly unmatched?: "error" | "ignore"; /** * Require that a matched route's evidence was installed by runtime enforcement (middleware/plugin * or framework policy) rather than asserted inline on `schema.assurance`. Default `true`: an author * label is not proof, and a security baseline that accepts labels is theater. Set `false` only to * stage adoption before guards emit runtime evidence. */ readonly requireRuntimeProvenance?: boolean; } /** * A first-match-wins security policy that turns the recurring audit finding classes into machine * checked route invariants. Composed only from the public assurance engine, so it inherits its * fail-closed evaluation, provenance checks, and selector validation - no bespoke evaluator. * * The rules are ordered most-specific-first because assurance evaluation is first-match-wins: each * route is owned by exactly one rule, so that rule carries the FULL requirement bundle for its class * (a body-carrying mutation proves bounded-body AND CSRF in one rule, not two). Raising the `level` * widens those bundles; it never reorders them. * * Coverage by level (see {@link SecurityBaselineLevel} for the rationale): * * | invariant | essential | standard | strict | * | --- | :-: | :-: | :-: | * | unlimited body can never be "bounded" (F-001) | ✓ | ✓ | ✓ | * | every body read is bounded | ✓ | ✓ | ✓ | * | agent tool ingress is bounded | ✓ | ✓ | ✓ | * | authenticated mutation proves CSRF | ✓ | ✓ | ✓ | * | pii+ route is authenticated | | ✓ | ✓ | * | every route carries a response contract | | | ✓ | * | every read carries security headers | | | ✓ | * | every mutation is rate limited | | | ✓ | * * The baseline deliberately does not select on `access`/`zone` capabilities: those selectors require * capability definitions and would make the preset refuse an app that declares none. Extend the * returned policy's `rules` for capability- or path-specific requirements; put more specific rules * before these so they own their routes first. */ export declare function securityBaseline(options?: SecurityBaselineOptions): AssurancePolicy; //# sourceMappingURL=baseline.d.ts.map