* feat(artifacts): make ASAR header admission configurable
ASAR header/index admission was a fixed 16 MiB with no override, so
operators with large Electron indexes could only extract the archive.
REA_ASAR_MAX_HEADER_BYTES now sets it (default 16777216, maximum
268435456). One owner resolves the effective admission for the
classification probe, inventory, ASAR reader and Electron file scope,
including the Electron header cache budget. Startup and doctor validate
the setting; admission refuses an invalid value instead of falling back.
Recovery and error details name the effective value and its source.
Fixes#6176
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(artifacts): resolve ASAR header admission from the caller's environment
The admission read process.env, so composition roots that select their own
environment (createDirectAnalysis, createServer, CLI, optional observation
factories) could not raise or lower it, and an ambient value leaked into
callers that left it unset.
Nothing reads process.env now. ArtifactProvider and extraction resolve the
admission from their environment; JavaScript analysis parses it from the
environment its server or CLI caller passes and refuses an invalid value;
the Electron and V8 providers receive it from their factories. Inventory,
nested ASAR readers, classification probes and Electron page authorization
carry that one value. A header cached by Electron under a larger admission
is refused for a smaller one.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
---------
Co-authored-by: Claude Opus 5.5 <[email protected]>
Reuse the shared safe issue projection for all six CLI validation boundaries
and cover malformed inputs, credential safety, and parser diagnostics.
Fixesmorluto/rea#2180
Developed with assistance from OpenAI Codex.
Move each error family out of domain/errors.ts into its own module
(base, core, provider selection/adapter, browser observation,
artifact, evidence, unknown registry, hopper, configuration) and
relocate AnalysisErrorProjection to analysisErrorProjection.
Migrate all 162 importers to the owning modules and delete
errors.ts. No re-export shims; behavior is unchanged.
* fix(platform): accept absolute paths for any host and stop blaming the ceiling for a missing grant
Addresses #548 and #545.
#548: processScenarioSchema required a leading "/" for executable,
working_directory and filesystem_roots, so no process scenario could be
expressed on Windows at all. The report suggested node:path's isAbsolute, but
that answers for the host running the check: on Linux `C:\tools` is not
absolute, so a scenario captured on Windows would fail validation when it is
replayed, compared, or asserted in a test on another host. A boundary schema
must not vary with its evaluator, so the check accepts the POSIX form, a
Windows drive path and a UNC share everywhere. The rejection message now names
the constraint instead of leaving the caller to infer it from "invalid request".
The HTTP `path` field inside `checkpoints` is an URL path and is deliberately
left alone.
I checked whether this merely moved the failure downstream: containment is
enforced by isPathWithinRoot, which already uses host-aware path.relative, so
validation really was the only blocker.
#545: when a scope is inside the administrator ceiling but no grant was ever
issued, the denial still pointed at widening the ceiling -- advice that cannot
help, since the ceiling already permits the operation. The `missing` payload is
computed against candidate *grants*, so it describes what a grant must cover,
not a ceiling gap. `PermissionRemediation` gains a `grant` variant saying
exactly that, and PermissionAuthority selects it when the denial is not a
ceiling violation. An explicitly requested remediation is still honoured, and a
genuine ceiling violation still says "configure".
* refactor(config): take the environment as an input at every configuration read
Completes B-2. Every `parseConfig(process.env)` site now reads from an
injected environment, so configuration-driven behaviour is a function of an
argument rather than of the machine running it.
The twelve sites were not equivalent, and treating them as one number would
have hidden the difference:
- **src/application/ (3 sites) were genuine defects.** `runSessionStatus`
already injected its `logger` but hardcoded `process.env` for config, so the
MCP path's `dependencies.env` never reached it; `captureProcessScenarioFile`
and `runAnalysis` had the same problem. `runAnalysis` gained `environment` on
the options object it already had, which is where its other injected
dependencies live.
- **The CLI command layer (9 sites) is a documented boundary,** where
`process.env` is legitimate. Rather than 9 independent ambient reads, they
now share one seam: `createCli(environment)` passes it to the seven
registrars that need configuration, and the nested helpers (`electronContext`,
`runtimeContext`, `loadConfiguredAuthority`, `inspectJavaScriptReplay`) take
it explicitly.
Every new parameter defaults to `process.env`, so all existing call sites are
unchanged and production behaviour is identical. The point is that the ambient
read is now a documented default at a boundary rather than a hidden dependency
deep inside behaviour.
`process.env` now survives in `src/` only as those default parameters —
nothing reads it at the point of use.
* style(cli): apply prettier formatting to the runtime observation command