@forzalabs/remora 2.2.1 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -6,6 +6,24 @@ The format is based on Keep a Changelog, and this project adheres to Semantic Ve
6
6
 
7
7
  ## Unreleased
8
8
 
9
+ ## V 2.3.0 - 2026-10-15
10
+
11
+ **Upgrading from 2.2.** One change alters what an existing project produces: a `CSV` or `TXT` output now writes a header line, so every exported file of that kind gains a first line naming its columns. It is opt-out — `"header": false` on the output restores the old headerless shape — but it is on by default, so a destination that reads the first line as data needs that flag set before this version runs. Nothing else here touches an existing configuration: `remora report` is a new command, and the `.env` refusal only fires on an archive that should never have contained one.
12
+
13
+ ### Added
14
+
15
+ - **`remora report [run-id]`, which packages a run into a `.zip` someone else can read.** A bug report is worth exactly what the reproduction is worth, so the bundle is designed backwards from what a reproduction needs rather than forwards from what is easy to collect: the usage row for the run (counts, per-stage timings, the error), that run's slice of the log file, the project configuration with its secrets removed, the environment it ran in, a one-page `report.md` that states the remora version, the node and platform, the consumer and its producers with the engine behind each source, the failure and its cause chain — and the commands that run the failing pipeline again on generated input. It defaults to the last recorded run and takes a run id for any other. **The bundle contains no executable**: the reproduction is a fenced block inside `report.md`, to be pasted or saved, rather than a `repro.sh` — an archive carrying a shell script is what a mail gateway or an endpoint scanner quarantines, and a bundle that never reaches the person who needs it reproduces nothing. Those commands bootstrap the two things a config carries from the machine it came from: a placeholder `.env` for every `{ENV_VAR}` the configuration names (`compile` refuses to run while a reference is unset, and placeholders are enough because `synth` contacts no source), and the local directories the sources point at (a missing destination fails the export AFTER the run, which reads as a second bug and is not one). Unpack, paste, and the reported failure happens again on synthetic rows. **It never compiles the project first**, unlike every other command: a bug report is wanted most when the configuration does NOT load, so the project is read leniently with `Environment.inspect()` and what will not load is collected as a finding rather than as a reason to refuse. For the same reason **no section can fail the command** — no run history, no log file, no `remora` directory at all — each one is recorded absent in the manifest with the reason, and the rest is still written; a reporter that dies on a broken project is useless precisely where it is needed. The log is sliced by run id AND by time window, because only the orchestrator's own lines carry `[usageId]` and a driver or parser line can be placed by its timestamp alone; a run whose process died before recording a finish leaves the window open to the end of the file, bounded by a record cap. Where `MONGO_URI` is set there is no local history to read at all (`UsageManager.recordsLocally()` is false), so the command degrades to the configuration, the environment and the tail of the log, and says so in the bundle
16
+
17
+ - **The configuration travels as authored; the log is scrubbed of credential shapes.** The asymmetry is deliberate. A remora config is not supposed to HOLD a credential — it names one (`{PG_PASSWORD}`, resolved by `SecretManager` at the point of use) and every authentication field already accepts a reference — so `config/` is shipped byte for byte: what a dev reads there is what runs, which is the whole reason it is in the bundle, and the reproduction copies it straight into a project directory. A literal password in a source file is an authoring mistake, and rewriting it on the way out would only hide it from the one person positioned to fix it. A log is the opposite case and gets no such assumption: by the time a value reaches a log line it has been resolved, so `SecretRedactor` removes the shapes a credential has in free text — a JWT, an AWS access key id, the query string of any URL (a presigned URL carries its signature there), and `password=`/`"apiKey":`/`Authorization: Bearer` pairs — while keeping `{ENV_VAR}` placeholders verbatim, since which variable a source reads is part of the question being asked. Nothing else travels either way: only `.json` configuration files are carried, and no row of customer data is collected at any level this version can produce
18
+
19
+ ### Changed
20
+
21
+ - **A `CSV` or `TXT` export now writes a header line.** A positional file carries values and nothing that names them, so every exported `CSV`/`TXT` file now opens with its field names — the exported ones, a field's `alias` where it has one and its `key` otherwise, in column order, quoted and delimited exactly as the rows under them so the header parses with the same reader the data does. A `hidden` field is not written and so is not named, and with a `split` **every** file of the output carries the header rather than only the first: a file that cannot be read on its own is not a file anyone can be handed. **This changes the bytes every existing CSV/TXT consumer produces**, and a destination that reads the first line as data will read the header as a row — set `"header": false` on that output to keep the old shape. The flag is `CSV`/`TXT` only: on a `JSON` or `API` output, where each record already carries its own field names, it is rejected at compile rather than ignored, so a config that asks for a header always gets one. Nothing internal changed with it — the header is composed and written at export time, not held in the dataset, so the split pass, the consumer-as-input capture, lookups and `sample` all still read a dataset of records and only records. It costs no pass over the data either: the destination drivers write the line ahead of the file they were already copying or streaming
22
+
23
+ - **`remora package` and `remora deploy` now refuse an archive containing a `.env` file.** A project keeps its `.env` above `./remora` and so out of reach of the packager's walk — but that is a property of where someone put a file, and this archive is uploaded to a worker and is now also packaged into bug reports. The check makes it a property of the packager instead, with a message saying to move the file. `ConfigPackager` moved from the CLI into `packages/common` on the way, so the deployment archive and the bug report share one set of exclusions rather than two that can drift
24
+
25
+ - `EnvironmentVariables` is now derived from a runtime `ENVIRONMENT_VARIABLES` list rather than written beside one, so a reader that has to enumerate the variables — the bug report's presence map, which records which are SET and never what they hold — gets exactly the names the type allows. `REMORA_MASK_IN_DEV` joins the catalogue, which the docs already named and the type did not
26
+
9
27
  ## V 2.2.1 - 2026-10-15
10
28
 
11
29
  ### Fixed