A profile accepted by libsandbox can still exceed PolicyWitness's input
capacities, exhaust an execution budget, or produce more evidence than a reply
can carry. This inventory covers specimen admission, execution, comparison
transport and retained evidence.
Counts of UTF-8 bytes are not counts of characters. Admission limits apply before
worker launch. Capture limits usually reduce evidence after work has happened.
The diagnostic sbpl-check helper has separate limits and is not the normal
worker admission path. Its import inventory does not control libsandbox's own
import resolution or compilation.
- Raising
--timeout-mschanges the client wait only. The worker and validator retain their own budgets. None of these numbers promises an end-to-end runtime: worker policy transfer precedes polling, synchronous validator work is outside the worker polling budget, and cleanup/reaping can take additional time. - The controller's runner-client budget is derived, not tuned: three times the
synthesized maximal reply (
runner_reply_maximum, the field-complete reply fixture with 256 steps and records and every string at its limit, encoded by the production encoder), rounded up to a whole 4 MiB. The sbpl-check streams keep an independent 8 MiB. These receivers report their budget incapture_limit_bytes; collection buffers the whole stream first. The synthesized number is an upper bound for the schema, since it puts fields that cannot co-occur in one run side by side; the live 256-step corpus is evidence that real replies stay inside it. A reply string key added without a size classification fails runner_unit, so the bound follows the schema. - Log collection enforces limits during reads: inner log-show stdout 1 MiB and
stderr 128 KiB, observer stdout 32 MiB and stderr 128 KiB. The outer allowance
accommodates repeated raw lines, JSON escaping and metadata from bounded
inner output; derived structures have independent guards. The runner's reply
size and step count cannot bound OS log volume. Both supervisors share one
monotonic deadline and a fixed cleanup grace.
--log-timeout-mschanges the time allowance, leaving byte limits and the padded query interval unchanged. - Service and direct orchestration share admission. Top-level metadata comes first, then plan/parameter counts, worker strings and host query fields. Each string checks its UTF-8 capacity before its native-string constraint. Refusals select one diagnostic but independently sanitize every echoed metadata field. Oversized or invalid identities are omitted or replaced by explicit placeholders, never shortened into apparent submitted identities.
- Native C strings (source, parameters, step IDs, targets, exec arguments,
query operations/values and override paths) reject embedded NUL before any
process work. The admission record counts
nul_bytesagainst maximum zero. The worker's reader refuses a NUL in the policy on its own (exit 9, failure code 9, offset in detail) rather than compile a prefix; the shared-memory string slots carry no length, so for them the host rule is the only guard. Other control characters and valid Unicode survive JSON transport exactly; host-only metadata and labels may also contain escaped NUL. The validator rejects raw controls, invalid UTF-8, malformed escapes and lone surrogates, while preserving the next physical probe line. Decoder failures report a bounded category/path instead of arbitrary input-derived exception prose. - Exec attempts spend descriptors before the sandbox applies, four per step, so the worker counts free descriptor slots and raises its soft limit to fit the plan plus reserved headroom before opening any pipe. Inherited descriptors count against availability. If the hard limit prevents the plan from fitting, excess exec steps report a descriptor-budget refusal before opening pipes; compilation and other attempts keep their headroom. The refusal is per-step evidence and does not by itself fail the run.
- Exec attempts share a local active-time budget as well as a per-child deadline. The plan cutoff starts before worker setup, excludes the measured release wait, and never restarts after spawn. This is separate from the host polling budget; the nominal 5,000 ms margin is a configuration allowance, not a guarantee against blocking calls or delayed scheduling.
- Pipe EOF does not establish child exit. The worker retains the unreaped leader while observing streams so deadline cleanup can still target its process group after a leader exit. Kill/wait/clock errors remain errors; final reaping uses a separate bounded, nonblocking observation window. Group termination cannot cover descendants that leave that group. A worker dying before slot completion leaves exec details unpublished, not proof that no child spawned or that cleanup succeeded.
- Deny-log capture has no fixed lookback limit. The requested interval is the
runner client's wall-clock span:
floor(start) - 2 sthroughceil(end) + 2 s. Whole-second rounding accommodateslog showprecision; the additional pad allows for client/archive clock differences.window.pad_secondsrecords 2. Raw client milliseconds are unchanged. Reversed endpoints prevent the scan; ordered endpoints do not establish clock continuity or complete log delivery. Archive access has been observed to cost seconds even for short spans; scan cost is not guaranteed to be independent of span or log volume.
Values are maxima unless labelled as defaults or fixed allowances.
| Limit | Value | Counting and consequence | Control |
|---|---|---|---|
Policy source (policy_source) |
262,143 UTF-8 bytes | Final SBPL source after augments; excludes terminating NUL. Imported file contents are not added to this count. Excess rejects the specimen after decoding and before semantic validation or process work: bad_request with host-owned admission_failure. | Fixed; no public override. |
Probe steps (probe_steps) |
256 items | Entries in probe_plan. Excess rejects the specimen after decoding and before semantic validation or process work: bad_request with host-owned admission_failure. | Fixed; no public override. |
Policy parameters (policy_parameters) |
1,024 items | Entries in the policy parameter dictionary. Excess rejects the specimen after decoding and before semantic validation or process work: bad_request with host-owned admission_failure. | Fixed; no public override. |
Step ID (step_id) |
63 UTF-8 bytes | Each step_id, excluding terminating NUL. A refused step ID is identified by step_index only, never echoed. Excess rejects the specimen after decoding and before semantic validation or process work: bad_request with host-owned admission_failure. | Fixed; no public override. |
Attempt target (attempt_target) |
511 UTF-8 bytes | Each attempt target (path, service or sysctl name), excluding terminating NUL. Also the exec argv[0]. Excess rejects the specimen after decoding and before semantic validation or process work: bad_request with host-owned admission_failure. | Fixed; no public override. |
Supplied exec arguments (exec_arguments) |
15 items | Arguments supplied in attempt.args; the target occupies the additional argv[0] slot. Excess rejects the specimen after decoding and before semantic validation or process work: bad_request with host-owned admission_failure. | Fixed; no public override. |
Each supplied exec argument (exec_argument) |
127 UTF-8 bytes | Each supplied argument, excluding terminating NUL; the target has its own larger limit. Excess rejects the specimen after decoding and before semantic validation or process work: bad_request with host-owned admission_failure. | Fixed; no public override. |
Parameter key (parameter_key) |
127 UTF-8 bytes | Each key, excluding terminating NUL. A refused key is identified by field and byte count only, never echoed. Excess rejects the specimen after decoding and before semantic validation or process work: bad_request with host-owned admission_failure. | Fixed; no public override. |
Parameter value (parameter_value) |
383 UTF-8 bytes | Each value, excluding terminating NUL. Excess rejects the specimen after decoding and before semantic validation or process work: bad_request with host-owned admission_failure. | Fixed; no public override. |
Query operation (query_operation) |
127 UTF-8 bytes | Each sandbox_check.operation, excluding terminating NUL. Host-only: the string goes to the validator line and is echoed per step in the reply; it never enters shared memory. Excess rejects the specimen after decoding and before semantic validation or process work: bad_request with host-owned admission_failure. | Fixed; no public override. |
Query filter value (query_filter_value) |
511 UTF-8 bytes | Each sandbox_check.filter.value when present, for every filter kind including none and unrecognized kinds, excluding terminating NUL. Independent of the attempt target: a step may query one path and attempt another, and each string is bounded on its own. Excess rejects the specimen after decoding and before semantic validation or process work: bad_request with host-owned admission_failure. | Fixed; no public override. |
Probe filter and attempt labels (probe_plan_label) |
127 UTF-8 bytes | Each sandbox_check.filter.kind, attempt.kind and attempt.action, excluding terminating NUL. Unknown labels within the bound retain their per-step prediction_unavailable or unsupported behavior. Excess rejects the specimen after decoding and before semantic validation or process work: bad_request with host-owned admission_failure. | Fixed; no public override. |
Specimen ID (specimen_id) |
255 UTF-8 bytes | The specimen_id string, excluding terminating NUL. Echoed once per reply; a refused ID is replaced by the placeholder <admission_refused>. Excess rejects the specimen after decoding and before semantic validation or process work: bad_request with host-owned admission_failure. | Fixed; no public override. |
Request labels (request_label) |
63 UTF-8 bytes | Each of run_kind and policy.format, excluding terminating NUL. Echoed once per reply; a refused run_kind is omitted and a refused format reads unknown. Excess rejects the specimen after decoding and before semantic validation or process work: bad_request with host-owned admission_failure. | Fixed; no public override. |
Test-seam executable paths (test_override_path) |
1,023 UTF-8 bytes | Each of _test_overrides.libsandbox_path, worker_executable_path and validator_executable_path, excluding terminating NUL. Mirrored back in test_overrides and named in dlopen and spawn diagnostics; every invalid path is independently dropped from a refusal mirror, even if another field is reported first. Excess rejects the specimen after decoding and before semantic validation or process work: bad_request with host-owned admission_failure. | Fixed; no public override. |
| Limit | Value | Counting and consequence | Control |
|---|---|---|---|
Worker readiness hint wait (worker_ready_wait) |
1,000 milliseconds | Initial ready-byte polling budget. Expiry alone does not abort: the host still checks shared-memory publication. | Production default; test-only controls are not a public tuning interface. |
Worker publication wait (worker_sentinel_wait) |
120,000 milliseconds | Nominal host polling budget from the end of the ready-byte wait until done. Synchronous validator work is outside this count; policy transfer before polling and scheduler delays are separate. The worker uses a separate local active-time budget for exec attempts. Expiry can trigger worker cleanup and runner_timeout with partial evidence. The exec budget is configured below this window but does not guarantee an end-to-end deadline. | Production default; test-only controls are not a public tuning interface. |
Worker exit grace (worker_exit_grace) |
1,000 milliseconds | Polling grace after the host requests exit. Expiry triggers a SIGKILL attempt, then reaping. Kill/reap failures remain reported. | Production default; test-only controls are not a public tuning interface. |
Worker release wait (worker_proceed_wait) |
60,000 milliseconds | Elapsed CLOCK_MONOTONIC time after successful apply, before host release acknowledgement. Expiry or clock failure publishes a proceed failure and done with no attempts. The existing exit-request spin can outlive a dead host. | Production default and internal test equipment; not a public CLI tuning interface. |
Nominal release margin (validator_release_margin) |
5,000 milliseconds | Configuration allowance for host observation, setup, decoding and scheduling, not a separately enforced timer. Production defaults satisfy 60000 > 30000 + 1000 + 5000. This guard does not cover test overrides or bound final blocking reap, host descheduling, prompt replies or eventual orphan cleanup. | Production default and internal test equipment; not a public CLI tuning interface. |
Validator I/O test override floor (validator_io_override_floor) |
50 milliseconds | Minimum effective _test_overrides.validator_io_timeout_ms. Changes only the real validator I/O deadline, with no ceiling. Over-budget values may intentionally outlast the worker release wait; expiry cannot revive attempts. The supplied value is mirrored in every reply. | Production default and internal test equipment; not a public CLI tuning interface. |
Validator I/O deadline (validator_io_wait) |
30,000 milliseconds | Elapsed CLOCK_MONOTONIC deadline for nonblocking probe writes and verdict reads; wall-clock changes cannot extend it. Retains received verdicts and records an I/O timeout; cleanup follows. | Production default; _test_overrides.validator_io_timeout_ms replaces this deadline, floored at 50 ms without a ceiling and mirrored in results. |
Validator exit grace (validator_exit_grace) |
1,000 milliseconds | Polling grace after closing validator pipes. Expiry triggers a SIGKILL attempt, then reaping; failures remain reported. | Production default; test-only controls are not a public tuning interface. |
Exec child deadline (exec_child_wait) |
10,000 milliseconds | Child observation time after successful spawn, limited by the earlier of its absolute deadline and the local exec plan deadline. Time spent spawning cannot restart the plan budget. EOF and child exit are observed separately. Deadline or observation failure requests process-group termination while the leader is still owned, even if that leader already exited. A deadline makes the attempt fail while preserving any observed natural exit code. A successful leader reap does not prove every descendant stopped. | Production default; test-only controls are not a public tuning interface. |
Exec attempt budget (exec_attempt_budget) |
115,000 milliseconds | Local CLOCK_MONOTONIC active time starting before worker setup. Only the interval returned by the release barrier is excluded. An absolute cutoff is passed to exec attempts; this is not a reconstruction of the host polling clock. An exhausted budget refuses spawn with exec_failed and ETIMEDOUT, no child identity and no sandbox attribution. Clock failure before spawn refuses the attempt; clock failure after spawn triggers cleanup and is retained as an observation error. Blocking spawn and non-exec operations are not preemptible here. | Production default leaves a nominal 5,000 ms margin below worker_sentinel_wait. Internal test equipment may shorten it independently; the specimen worker_timeout_ms override does not move it. |
Exec child reap grace (exec_reap_grace) |
1,000 milliseconds | Local monotonic observation window for nonblocking waitpid after exec observation stops. Expiry, clock failure or native wait failure retains an unconfirmed reap without inventing exit status. Failed group termination permits only an immediate nonblocking reap. This does not bound a native syscall or host descheduling. | Fixed; no public override. |
Exec attempt descriptors (exec_step_descriptors) |
4 items | Descriptors opened before sandbox application per exec step: both ends of stdout and stderr pipes. Before opening any, the worker scans for free descriptor numbers, accounting for inherited descriptors, and raises its soft limit to fit the plan plus the descriptor reserve. Raises are capped at the hard limit and OPEN_MAX (10,240); an already higher soft limit is preserved. Only exec slots that fit without spending the reserve get pipes. Excess slots report exec_failed with errno 24 and an exec descriptor budget diagnostic naming the limit; no pipe syscall or child spawn is claimed. Actual pipe failures report their own syscall and errno. Budget refusal is per-step evidence, with sandbox attribution unestablished; imports and other attempts retain descriptor headroom. | Host-derived hard ceiling; no public override. The worker raises the soft limit and never lowers it. |
Exec descriptor reserve (exec_descriptor_reserve) |
64 items | Free descriptor slots withheld from exec pipe setup, in addition to descriptors already open. The worker scans with fcntl(F_GETFD) to find room for this reserve plus four descriptors per exec step. Preserves headroom for policy compilation/imports, file probes, and spawn file actions. If the inherited/hard limit already leaves fewer free slots than the reserve, exec setup opens no pipes. This bounds exec pipe consumption; it does not guarantee that arbitrary imports or other resource users fit. | Fixed; no public override. |
Runner RPC wait (client_rpc_wait) |
240,000 milliseconds | Client wait for the runner reply. An expired wait yields runner_timeout; it does not expand the inner worker or validator budgets. | Default; --timeout-ms changes only this wait and floors its value at 1 ms. |
| Limit | Value | Counting and consequence | Control |
|---|---|---|---|
Validator query payload (validator_query_payload) |
65,534 bytes | Serialized JSON bytes for one probe, before the LF delimiter. Escaping counts. The fixed 65536-byte buffer retains the 65534-byte payload allowance; the reader counts physical bytes, including raw NUL, and drains the rest of an overlong line. An overlong line produces one parse_error with no step ID; that prediction is unavailable. Later lines can still be processed. Admitted specimens cannot reach it: with the operation and filter value admission-bounded, a fully escaped probe line stays a few KiB. | Fixed; no public override. |
Synthesized maximal reply (runner_reply_maximum) |
24,869,018 bytes | Encoded size, through the production encoder, of the field-complete reply fixture with 256 steps, 256 validator records and disposition entries, every request- or host-derived string at its documented limit and made of U+0001 (six JSON bytes per byte), the largest worker diagnostic, and the largest slash-heavy compiled-profile receipt. An upper bound for the current response schema: fields that cannot co-occur in one run are all present. Composed host path strings allow 1,535 bytes for a resolved parent plus literal leaf and 1,043 bytes for a realpath plus the supported system firmlink prefix; runner_unit checks both expansions. Not enforced anywhere; it derives the runner client budget. A reply string key added to the fixture without a size classification fails runner_unit, so the number cannot silently fall behind the schema. | Recomputed by runner_unit; edit the manifest when the synthesizer's number moves. |
Runner client output (controller_output) |
75,497,472 bytes | Per stdout or stderr stream captured from the runner client. Byte prefix before lossy text decoding; not an envelope-wide cap. Output beyond the prefix is marked truncated. Truncated JSON stdout is not parsed as a complete reply. | Derived: three times runner_reply_maximum, rounded up to a whole 4 MiB. runner_unit asserts the relation against the compiled Rust constant's documented value; no public override. |
Log observer stdout (log_observer_output) |
33,554,432 bytes | Raw observer stdout bytes, enforced while reading; includes the JSON report and final newline. Independent stderr has its own cap. One extra byte witnesses overflow; retain only the bounded raw prefix without JSON fragment recovery and withhold correlation. | Fixed. Sized for bounded inner text, duplicated deny lines and parsed raw lines, six-byte JSON escaping, event metadata and reply metadata. |
Log show stdout (log_show_stdout) |
1,048,576 bytes | Raw bytes read from log show stdout, already selected by the OS predicate, before PW decoding, parsing or PID filtering; enforced while reading. One extra byte witnesses overflow; retain only the budgeted prefix, stop collection, clean up and withhold correlation. | Fixed; no public override. |
Log show stderr (log_show_stderr) |
131,072 bytes | Raw bytes read from log show stderr, before decoding or parsing; enforced while reading. One extra byte witnesses overflow; retain only the budgeted prefix, stop collection, clean up and withhold correlation. | Fixed; no public override. |
Log observer stderr (log_observer_stderr) |
131,072 bytes | Raw bytes read from observer stderr, before decoding or parsing; enforced while reading. One extra byte witnesses overflow; retain only the budgeted prefix, stop collection, clean up and withhold correlation. | Fixed; no public override. |
Observer JSON structure (log_reply_structure) |
262,144 items | Opening object/array delimiters, commas and colons outside quoted strings, counted before allocating a JSON tree. Excess retains bounded raw diagnostic text and withholds parsing and correlation. | Fixed; no public override. |
Observer echoed metadata (log_observer_metadata) |
4,096 UTF-8 bytes | Each echoed show argument: predicate, process name, start, end, last, plan, row and correlation ID. Observer rejects excess before launching log show; controller also rejects oversized reply metadata. | Fixed; no public override. |
Policy helper output (policy_helper_output) |
8,388,608 bytes | Per stdout or stderr stream captured from sbpl-check. Byte prefix before lossy text decoding; independent of the runner reply budget. Output beyond the prefix is marked truncated. Truncated JSON stdout is not parsed as a complete reply. | Fixed; no public override. |
Rejected validator frame context (validator_fault_context) |
256 bytes | Raw prefix of the first rejected frame, before base64 encoding. The remaining frame is not retained as context; frame_bytes, retained_bytes and context_truncated describe the loss. | Fixed; no public override. |
| Limit | Value | Counting and consequence | Control |
|---|---|---|---|
Deny-log scan padding per endpoint (log_window_pad) |
2 seconds | Symmetric padding after flooring the runner client's start and ceiling its end to whole seconds. Allows for differences between the client's wall clock and the archive's displayed event timestamps; does not guarantee delivery or coverage under every clock condition. Queries floor(start) - 2 seconds through ceil(end) + 2 seconds; records in either pad remain eligible for correlation. Raw client milliseconds are unchanged; reversed endpoints still prevent collection. | Fixed; no public override. window.pad_seconds records the pad. |
Default log collection timeout (log_collection_timeout) |
10,000 milliseconds | Shared CLOCK_MONOTONIC allowance starting before observer launch; includes startup, inner log show capture and processing. The log child receives the allowance minus the report reserve. Standalone show uses the same finite default. Expiry stops collection and starts the fixed cleanup grace; available diagnostics survive without associations. | Override with --log-timeout-ms: positive integer milliseconds representable as a monotonic deadline plus cleanup grace. Validated before runner invocation even with --no-log-capture. |
Log cleanup grace (log_cleanup_grace) |
1,000 milliseconds | Cleanup ends no later than the original collection deadline plus this grace; early failures start the grace immediately. Unconfirmed reaping or group absence is reported; retries never restart the allowance. | Fixed; no public override. |
Log report reserve (log_report_reserve) |
1,000 milliseconds | Withheld from the shared deadline at the log show boundary: the observer stops its log child this long before the controller's deadline so it can reap the child and deliver its report. The controller's own deadline is unchanged. Leaves time for an intact observer reply containing the inner cutoff and retained diagnostics. Cleanup and scheduling can consume this reserve; an interrupted report retains only bounded transport diagnostics. An allowance at or below the reserve leaves no time for the query itself. | Fixed; no public override. supervision.reserve_ms records 0 at the observer boundary and this value under observer.data.collection. |
Parsed deny events (log_deny_events) |
8,192 records | Parsed deny events in show output and the derived controller array. An additional event makes capture incomplete and correlation unavailable; bounded raw output and available diagnostic events survive. | Fixed; no public override. |
Candidate associations (log_candidate_count) |
4,096 items | Total event-to-step candidates, including ambiguous matches. Excess discards the whole derived association result and withholds correlation; retained events remain diagnostic. | Fixed; no public override. |
Candidate allocation allowance (log_candidate_bytes) |
8,388,608 bytes | Conservative encoded/allocation charge per candidate: six times the sum of twice the step-ID length plus path, operation, kind and action lengths, plus 1,024 bytes of structure. Excess discards all associations and withholds correlation. | Fixed; no public override. |
Steps admitted to correlation (log_correlation_steps) |
256 items | Each of the submitted plan and returned step arrays. Excess withholds log correlation; execution evidence is unchanged. | Fixed; no public override. |
Exec child output per stream (exec_stream) |
1,023 bytes | Retained bytes in each stdout/stderr text buffer, excluding NUL. A truncation marker occupies part of this space on overflow. Additional output is drained but not retained. | Fixed; no public override. |
Primary worker diagnostic (worker_diagnostic) |
4,095 bytes | Diagnostic payload bytes, excluding NUL. The primary diagnostic is bounded and reports retained length and truncation state; it is not a transcript. | Fixed; no public override. |
Optional compiled-object capture (applied_profile) |
1,048,576 bytes | Raw bytecode bytes for a nonempty supported single-profile (type 0) object, before base64 encoding. Oversize or unsupported objects leave capture unavailable without preventing policy application. | Fixed; no public override. |
Worker observed path (observed_path) |
1,023 bytes | Per-step C path-buffer payload bytes, excluding NUL. Path observation can be absent or bounded; a host-side path diagnostic is a separate observation. | Fixed; no public override. |
Worker attempt error text (attempt_error) |
255 bytes | Per-step error-buffer payload bytes, excluding NUL. Error prose is bounded; structured result/status fields remain separate. | Fixed; no public override. |
| Limit | Value | Counting and consequence | Control |
|---|---|---|---|
sbpl-check source admission (helper_source) |
4,194,304 bytes | Top-level source bytes read by the diagnostic helper; not the runner policy cap. policy_too_large without a compile verdict. | Fixed; no public override. |
sbpl-check import inventory depth (helper_import_depth) |
8 levels | Top-level imports start at depth 0. At depth 8 the helper records a depth-limit diagnostic instead of reading/expanding that file. Stops inventory expansion on that branch and marks imports_truncated. Does not impose this depth on libsandbox compilation. | Fixed; no public override. |
sbpl-check import inventory count (helper_import_count) |
64 records | Maximum records accumulated by the helper traversal, including unresolved/error records; visited files/names are deduplicated. Stops further inventory traversal and marks imports_truncated. Does not impose this count on libsandbox compilation. | Fixed; no public override. |
Log observer stream text (observer_stream_text) |
1,048,576 bytes | Streaming helper mode only (--duration or --follow): retained nonempty, non-prelude log lines with one LF per line. Only whole lines that fit are retained. The first overflowing line sets log_truncated and stops text accumulation. Deny-event arrays and JSONL emission continue separately; this is not a memory or total-report cap. The normal CLI log-show path does not use this inner cap. | Fixed byte cap; --no-log-capture disables normal CLI log collection, not this helper capability. |
See the user guide for the request and response contracts. Tables are generated from limits.json.
Value checks compare the inventory with compiled constants, constructed defaults or actual returned bytes. Boundary checks exercise a limit and its consequence; path checks cover related behavior without proving the exact boundary. A source reference alone is not a value check. Coverage notes below identify where behavior remains source-inspected.
| Limit ID | Implementation | Permanent checks | Behavioral coverage |
|---|---|---|---|
policy_source |
PW_SHM_POLICY_BYTES; workerAdmissionFailure |
value: ABI_LIMITS; value: runLimitsContractTests; boundary: admission |
At-limit, over-limit and multibyte admission controls through the CLI. |
probe_steps |
PW_SHM_MAX_STEPS; workerAdmissionFailure |
value: ABI_LIMITS; value: runLimitsContractTests; boundary: admission |
At-limit, over-limit and multibyte admission controls through the CLI. |
policy_parameters |
PW_SHM_MAX_PARAMS; workerAdmissionFailure |
value: ABI_LIMITS; value: runLimitsContractTests; boundary: admission |
At-limit, over-limit and multibyte admission controls through the CLI. |
step_id |
PW_SHM_STEP_ID_MAX; workerAdmissionFailure |
value: ABI_LIMITS; value: runLimitsContractTests; boundary: admission |
At-limit, over-limit and multibyte admission controls through the CLI. |
attempt_target |
PW_SHM_TARGET_MAX; workerAdmissionFailure |
value: ABI_LIMITS; value: runLimitsContractTests; boundary: admission |
At-limit, over-limit and multibyte admission controls through the CLI. |
exec_arguments |
PW_SHM_MAX_ARGV; workerAdmissionFailure |
value: ABI_LIMITS; value: runLimitsContractTests; boundary: admission |
At-limit, over-limit and multibyte admission controls through the CLI. |
exec_argument |
PW_SHM_ARGV_BYTES; workerAdmissionFailure |
value: ABI_LIMITS; value: runLimitsContractTests; boundary: admission |
At-limit, over-limit and multibyte admission controls through the CLI. |
parameter_key |
PW_SHM_PARAM_KEY_MAX; workerAdmissionFailure |
value: ABI_LIMITS; value: runLimitsContractTests; boundary: admission |
At-limit, over-limit and multibyte admission controls through the CLI. |
parameter_value |
PW_SHM_PARAM_VALUE_MAX; workerAdmissionFailure |
value: ABI_LIMITS; value: runLimitsContractTests; boundary: admission |
At-limit, over-limit and multibyte admission controls through the CLI. |
query_operation |
sandboxCheckOperationMaxBytes; queryAdmissionFailure |
value: runLimitsContractTests; boundary: admission; boundary: runQueryAdmissionTests |
At-limit, over-limit and multibyte admission controls through the CLI; constructed orchestrator controls refuse before any process work and cover every filter kind. |
query_filter_value |
sandboxCheckFilterValueMaxBytes; queryAdmissionFailure |
value: runLimitsContractTests; boundary: admission; boundary: runQueryAdmissionTests |
At-limit, over-limit and multibyte admission controls through the CLI; constructed orchestrator controls refuse before any process work and cover every filter kind. |
probe_plan_label |
probePlanLabelMaxBytes; queryAdmissionFailure |
value: runLimitsContractTests; boundary: admission; boundary: runQueryAdmissionTests |
Exact, over-limit and multibyte boundaries through the CLI; 256-step oversized-label regressions require a small refusal and unchanged write targets. |
specimen_id |
specimenIdMaxBytes; requestAdmissionFailure |
value: runLimitsContractTests; boundary: admission; boundary: runQueryAdmissionTests |
Exact, over-limit and multibyte boundaries through the CLI and in constructed controls; the refusal reply never contains the refused string. |
request_label |
requestLabelMaxBytes; requestAdmissionFailure |
value: runLimitsContractTests; boundary: admission; boundary: runQueryAdmissionTests |
Exact, over-limit and multibyte boundaries through the CLI and in constructed controls; an at-limit format passes admission and fails as bad_policy. |
test_override_path |
testOverridePathMaxBytes; requestAdmissionFailure |
value: runLimitsContractTests; boundary: admission; boundary: runQueryAdmissionTests |
Exact, over-limit and multibyte boundaries through the CLI and in constructed controls; at-limit nonexistent paths pass admission and reach their own seam failures. |
worker_ready_wait |
CWorkerInput |
value: runLimitsContractTests; path: runCWorkerTests |
Normal readiness is tested; expiry without aborting is source-inspected. |
worker_sentinel_wait |
timeoutMsForCWorker |
value: runLimitsContractTests; path: runCWorkerTests |
Deadline and partial-publication paths use shortened test budgets; the production duration is source-inspected. |
worker_exit_grace |
CWorkerInput |
value: runLimitsContractTests; path: runCWorkerLifecycleTests |
Deadline/cleanup paths use controlled children; the production duration is source-inspected. |
worker_proceed_wait |
PW_PROCEED_WAIT_MS_DEFAULT |
value: runLimitsContractTests; value: NATIVE_LIMITS; path: proceed_wait_budget_short; path: runOrderingTests |
Short-budget, delayed-release, clock-failure and delayed-cleanup controls establish fail-closed behavior; production duration is value-checked. |
validator_release_margin |
validatorReleaseMarginMs |
value: runLimitsContractTests |
Short-budget, delayed-release, clock-failure and delayed-cleanup controls establish fail-closed behavior; production duration is value-checked. |
validator_io_override_floor |
timeoutMsForValidator |
value: runLimitsContractTests |
Short-budget, delayed-release, clock-failure and delayed-cleanup controls establish fail-closed behavior; production duration is value-checked. |
validator_io_wait |
ValidatorClientInput |
value: runLimitsContractTests; path: runValidatorEvidenceTests |
I/O deadline and partial-evidence paths use shortened budgets; the production duration is source-inspected. |
validator_exit_grace |
ValidatorClientInput |
value: runLimitsContractTests; path: runValidatorEvidenceTests |
Cleanup paths use controlled children; the production duration is source-inspected. |
exec_child_wait |
PW_EXEC_CHILD_DEADLINE_MS_DEFAULT |
value: NATIVE_LIMITS; path: runCWorkerTests |
Live controls close streams while both processes remain alive and exit the leader while a descendant retains streams. Independent socket credentials, OS exit events and file effects establish the behavior. |
exec_attempt_budget |
PW_EXEC_ATTEMPT_BUDGET_MS_DEFAULT; attempt_budget_start |
value: NATIVE_LIMITS; value: runLimitsContractTests; boundary: run_exec_attempt_budget |
Compiled values agree with the host configuration. Deterministic native controls vary spawn latency, release exclusion, intervening work, exact exhaustion, clock failures and cleanup. Real short-budget plans preserve completed prefix and trailing file effects through host assembly and serialization. |
exec_reap_grace |
PW_EXEC_REAP_GRACE_MS |
value: NATIVE_LIMITS; boundary: main |
Controlled pending/EINTR waits exhaust the grace; kill, wait and clock failures retain missing status. Every wait is required to be nonblocking. |
exec_step_descriptors |
PW_EXEC_DESCRIPTORS_PER_STEP; setup_exec_resources |
value: NATIVE_LIMITS; boundary: main; path: run_exec_descriptor_limit; path: EXEC_STEPS |
The per-step count is value-checked against the compiled worker. A 256-exec plan is pinned live through the CLI. Native harness cases cover a raised soft limit, 80 extra inherited descriptors, and hard caps 64 and 126 through 129 with policy imports and reads before/after execs. Every prepared child must exit cleanly and excess slots must report budget refusal. The OPEN_MAX clamp is source-inspected. |
exec_descriptor_reserve |
PW_EXEC_DESCRIPTOR_RESERVE; prepare_exec_descriptor_budget |
value: NATIVE_LIMITS; path: run_exec_descriptor_limit |
Value-checked against the compiled worker. Capped mixed plans require successful policy imports and file reads even when all exec slots are refused, and clean exits for every prepared exec. The inherited-descriptor case requires all 32 execs with ample hard-limit capacity. |
client_rpc_wait |
DEFAULT_TIMEOUT_MS; defaultClientTimeoutMs; defaultClientTimeoutMs |
value: runLimitsContractTests; value: documented_controller_limits |
The production wait and timeout response are source-inspected; compiled default agreement is tested. |
validator_query_payload |
LINE_MAX_BYTES; runValidator |
value: NATIVE_LIMITS; boundary: query_boundary; path: validator_overlong_request |
Exact payload boundary, over-limit drain/recovery, valid raw and escaped Unicode, malformed escapes/UTF-8/raw controls and raw-NUL physical framing. Every rejected probe is followed by a valid recovery probe. |
runner_reply_maximum |
maximalReplyEncodedSize; pwRunnerEncodeJSON |
value: runLimitsContractTests; boundary: runReplyMaximumTests; path: main |
The synthesizer's value is compared with the manifest; the budget relation is asserted; an injected unclassified key is detected. Live 256-step workloads are measured against this bound. |
controller_output |
RUNNER_CAPTURE_BYTES |
value: documented_controller_limits; path: mod tests; path: main |
Exact prefix and truncation-boundary controls, including small arbitrary budgets and every cut within multibyte scalars. Collection buffers the entire stream first; this is not a memory limit. Five admitted 256-step CLI workloads at the admitted maxima, including the control-character exec workload with 511-byte targets and queries, 63-byte step IDs, maximal metadata and live profile capture, must each stay under runner_reply_maximum; the budget then holds a complete reply with a threefold margin by construction. |
log_observer_output |
OBSERVER_STDOUT_BYTES |
value: documented_controller_limits; boundary: both_raw_streams_are_bounded_at_exact_edges; boundary: inner_byte_limit_with_maximal_json_escaping_fits_outer_serialization_limit; boundary: controlled_256_step_capture_keeps_every_long_target_candidate |
Streaming cap controls cover both pipes. A 256-record corpus with 511-byte targets preserves all records and candidate references through parser, supervised receiver, assembly and consumer recovery under the production default allowance. Exact inner stdout/stderr caps with maximum escaping fit the bounded serializer. Interrupted or failed capture changes log evidence only; live volume has no bound derived from step count. |
log_show_stdout |
LOG_STDOUT_BYTES |
value: documented_collection_limits; boundary: both_raw_streams_are_bounded_at_exact_edges |
Both stream boundaries are tested at, below and above a substituted small cap, including concurrent stdout/stderr. Counts describe bytes actually read, never the unavailable remainder. |
log_show_stderr |
LOG_STDERR_BYTES |
value: documented_collection_limits; boundary: both_raw_streams_are_bounded_at_exact_edges |
Both stream boundaries are tested at, below and above a substituted small cap, including concurrent stdout/stderr. Counts describe bytes actually read, never the unavailable remainder. |
log_observer_stderr |
OBSERVER_STDERR_BYTES |
value: documented_collection_limits; boundary: both_raw_streams_are_bounded_at_exact_edges |
Both stream boundaries are tested at, below and above a substituted small cap, including concurrent stdout/stderr. Counts describe bytes actually read, never the unavailable remainder. |
log_window_pad |
LOG_WINDOW_PAD_SECONDS |
value: documented_controller_limits; boundary: run_span_window_floors_start_ceils_end_and_never_collapses; boundary: requested_intervals_select_independently_timed_events; boundary: padded_records_survive_assembly_and_consumer_recovery |
Independent timestamp fixtures cover both padding regions, exact and exterior bounds, equal spans and rollback. Complete full, early-only, late-only and empty replies preserve eligible candidates and missing-record diagnostics through assembly, serialization and consumer recovery. |
log_collection_timeout |
DEFAULT_LOG_TIMEOUT_MS |
value: documented_collection_limits; boundary: larger_allowance_buys_time_only_and_still_bounds_hangs |
Independent slow-success and permanent-hang fixtures prove that a larger finite allowance buys waiting time only; shared absolute deadlines are not restarted by the observer. |
log_cleanup_grace |
CLEANUP_GRACE_MS |
value: documented_collection_limits; path: cleanup_failures_and_lost_ownership_remain_unconfirmed |
Owned orphan controls cover leader death before reply, pipes open or closed, group absence, failed signalling/probing and lost ownership. The bound concerns supervised waiting, not OS scheduling. |
log_report_reserve |
LOG_REPORT_RESERVE_MS |
value: documented_collection_limits; boundary: inner_timeout_preserves_available_record_and_actual_child_wait; boundary: timeout_override_changes_waiting_only_across_both_boundaries |
A short inner allowance cuts off the log child while the observer's report, including its inner cutoff, still reaches the controller; a stalled query exhausts the reserved inner allowance and is reported the same way. |
log_deny_events |
MAX_DENY_EVENTS |
value: documented_collection_limits; boundary: event_limit_withholds_completion_without_discarding_retained_diagnostics; boundary: maximum_event_volume_correlates_within_the_default_allowance |
Exact and over-limit fixtures retain diagnostics and distinguish complete capture from overflow. The maximum event volume correlates against a 256-step plan inside the default collection allowance. |
log_candidate_count |
MAX_ASSOCIATIONS |
value: documented_collection_limits; boundary: derived_json_and_candidate_allocations_are_bounded |
A 256-record unique-path control preserves all associations; repeated matching attempts exhaust the candidate budget. |
log_candidate_bytes |
MAX_ASSOCIATION_BYTES |
value: documented_collection_limits; boundary: derived_json_and_candidate_allocations_are_bounded |
Long repeated paths exercise the allocation allowance independently of the candidate count. This is a derived-data bound, not a peak-process-memory claim. |
log_correlation_steps |
MAX_CORRELATION_STEPS |
value: documented_collection_limits; boundary: derived_json_and_candidate_allocations_are_bounded |
A 256-step control preserves unique candidates; over-limit arrays reject correlation. |
log_reply_structure |
MAX_OBSERVER_JSON_TOKENS |
value: documented_collection_limits; boundary: derived_json_and_candidate_allocations_are_bounded |
Independent oversized JSON array trips the structural guard before Value allocation. |
log_observer_metadata |
MAX_OBSERVER_METADATA_BYTES |
value: documented_collection_limits; path: supervised_receiver_retains_failed_inner_evidence_and_rejects_bad_shapes |
Receiver malformed-shape controls cover excess metadata; direct argument admission is source-inspected. |
policy_helper_output |
HELPER_CAPTURE_BYTES |
value: documented_controller_limits; boundary: arbitrary_budgets_preserve_counts_at_every_unicode_cut |
The shared receiver accepts an explicit per-stream retention budget for this producer; exact byte counts, truncation and JSON parse suppression are tested independently of the runner budget. |
validator_fault_context |
decodeValidatorFrames |
value: runLimitsContractTests; boundary: runLimitsContractTests |
Exact and over-limit invalid-frame context controls; no rejected bytes become verdicts. |
exec_stream |
PW_SHM_CHILD_OUTPUT_BYTES |
value: ABI_LIMITS; value: runLimitsContractTests; path: runCWorkerTests |
Small stdout/stderr capture is tested. Overflow truncation and the exact retained-prefix/marker split are source-inspected. |
worker_diagnostic |
PW_SHM_DIAGNOSTIC_BYTES |
value: ABI_LIMITS; value: runLimitsContractTests; path: runWorkerEvidenceTests |
Bounded diagnostic/truncation controls in the Swift worker evidence tests. |
applied_profile |
PW_SHM_CAPTURE_BYTES |
value: ABI_LIMITS; value: runLimitsContractTests; boundary: main |
Independently constructed object controls cover exact, excessive and unsupported captures. |
observed_path |
PW_SHM_OBSERVED_PATH_MAX |
value: ABI_LIMITS; value: runLimitsContractTests |
Source-inspected buffer use; no exact path-length behavior claim is tested. |
attempt_error |
PW_SHM_ERROR_MAX |
value: ABI_LIMITS; value: runLimitsContractTests |
Source-inspected bounded formatting; no exact error-text boundary claim is tested. |
helper_source |
MAX_SBPL_SOURCE_BYTES |
value: documented_helper_limits; path: mod tests |
Oversized input is tested through the shipped helper and fallback CLI; exact boundary behavior is source-inspected. |
helper_import_depth |
IMPORT_MAX_DEPTH |
value: documented_helper_limits; path: mod tests |
Deep import-chain control in the helper unit tests. |
helper_import_count |
IMPORT_MAX_COUNT |
value: documented_helper_limits; path: mod tests |
Import-count exhaustion control in the helper unit tests. |
observer_stream_text |
MAX_CAPTURE_BYTES |
value: documented_observer_limits |
Compiled value agreement is tested. Streaming accumulation and overflow behavior are source-inspected. |
Edit limits.json, then run python3 docs/generate_limits.py from
the repository root. The same command copies the marked shared section into
PolicyWitness.md; edit its explanations here. Review the
handwritten explanations as well as the tables. The same command also copies the
shared questions from QUESTIONS.md into the guide's Questions
section; edit the questions there, writing links into the guide as
PolicyWitness.md#anchor.
The JSON is a reviewed description; production code does not load it.
python3 docs/generate_limits.py --check verifies the manifest's shape, source
and check references, generated text in both documents, the copied questions,
and the guide's internal links. The copied sections must contain every limit and
every shared question and require no companion files or web pages. --stage-guide PATH performs the same checks before copying
the guide; it refuses stale documents without regenerating them. The build
checks freshness before compilation and stages the guide before packaging.
These checks cannot establish implementation agreement by themselves.
source_drift exercises invalid and stale inputs, copying and staging, a
standalone guide, and refusal to build with stale documentation.
runner_abi_layout compares
compiled C values and exercises native query boundaries; runner_unit checks
compiled Swift values/defaults and rejected-frame capture. Rust unit tests check
controller and helper constants. Existing behavioral suites remain independent
of the manifest, so changing a documented number cannot change their oracles.
For a limit change, run cargo test --manifest-path controller/Cargo.toml and
tests/run.sh --suite source_drift --suite runner_abi_layout --suite runner_unit --suite runner_c_worker_harness --suite failure_boundaries against a normal
signed build, plus the affected behavior owners named above. New entries need
an implementation-value check and an honest coverage note; a link to source is
not enough. Do not label a shortened timeout control as a test of the production
duration, or a constant comparison as proof of its operational consequences.