@boardwalk-labs/runner 0.1.5 → 0.1.6

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.
@@ -299,7 +299,12 @@ export function assembleWorkerDeps(runtime) {
299
299
  // throws) so no language-server process leaks past the run.
300
300
  lsp: lspService,
301
301
  // The orchestrator emits the program's declared output onto the wire (`output` kind).
302
- activity: { output: (value) => void runEvents.emit({ kind: "output", value }) },
302
+ // Redact the declared-output EVENT (observability): a secret the program put in output()
303
+ // must not surface in the run's event stream. The FUNCTIONAL output program_runner returns
304
+ // for `workflows.call` is a separate path and stays raw, so cross-workflow data flow is intact.
305
+ activity: {
306
+ output: (value) => void runEvents.emit({ kind: "output", value: redactor.redactValue(value) }),
307
+ },
303
308
  // Filled by the runner once the artifact extracts; the leaf's `skillsDir` thunk reads it.
304
309
  setProgramDir: (dir) => {
305
310
  programDir = dir;
@@ -4,7 +4,13 @@ export type LogStream = "stdout" | "stderr";
4
4
  * Patch the global console so each call is forwarded to the original AND handed (formatted) to
5
5
  * `sink`. Returns a restore function — ALWAYS call it (the worker runs `restore()` in a finally).
6
6
  */
7
- export declare function captureConsole(sink: (stream: LogStream, text: string) => void): () => void;
7
+ export declare function captureConsole(sink: (stream: LogStream, text: string) => void,
8
+ /** Scrub known secret values from each formatted line before it reaches EITHER sink. A program
9
+ * that `console.log`s a resolved secret must not leak it — to the run's `program_output` events
10
+ * OR to container stdout (CloudWatch). We format+redact once and print the SAME redacted string
11
+ * to the original console (equivalent output; `util.format` is what console does internally).
12
+ * Defaults to identity (tests/local). */
13
+ redact?: (text: string) => string): () => void;
8
14
  export interface ProgramLogSinkOptions {
9
15
  /** The run's shared event emitter — program logs ride the one ordered stream (`log` channel). */
10
16
  sink: TurnEventSink;
@@ -24,7 +24,13 @@ const STREAM_BY_METHOD = {
24
24
  * Patch the global console so each call is forwarded to the original AND handed (formatted) to
25
25
  * `sink`. Returns a restore function — ALWAYS call it (the worker runs `restore()` in a finally).
26
26
  */
27
- export function captureConsole(sink) {
27
+ export function captureConsole(sink,
28
+ /** Scrub known secret values from each formatted line before it reaches EITHER sink. A program
29
+ * that `console.log`s a resolved secret must not leak it — to the run's `program_output` events
30
+ * OR to container stdout (CloudWatch). We format+redact once and print the SAME redacted string
31
+ * to the original console (equivalent output; `util.format` is what console does internally).
32
+ * Defaults to identity (tests/local). */
33
+ redact = (t) => t) {
28
34
  const console_ = globalThis.console;
29
35
  const originals = {};
30
36
  for (const [method, stream] of Object.entries(STREAM_BY_METHOD)) {
@@ -33,9 +39,10 @@ export function captureConsole(sink) {
33
39
  continue;
34
40
  originals[method] = original;
35
41
  console_[method] = (...args) => {
36
- original.apply(console_, args); // still print to the container stdout (CloudWatch)
42
+ const text = redact(format(...args));
43
+ original.call(console_, text); // print the REDACTED line to container stdout (CloudWatch)
37
44
  try {
38
- sink(stream, format(...args));
45
+ sink(stream, text);
39
46
  }
40
47
  catch {
41
48
  // best-effort — a telemetry hiccup must never break the program's own logging
@@ -162,7 +162,9 @@ export async function runProgramWorker(runId, deps) {
162
162
  // by `flushFinal()` after the body (on every path except a lease_lost handoff).
163
163
  const runtimeFlush = deps.startRuntimeFlush?.({ run: claimed, startedAtMs: sessionStartMs });
164
164
  // Capture the program's console.* as `log` run-events for the duration of the body (best-effort).
165
- const restoreConsole = deps.onProgramLog !== undefined ? captureConsole(deps.onProgramLog) : () => undefined;
165
+ const restoreConsole = deps.onProgramLog !== undefined
166
+ ? captureConsole(deps.onProgramLog, (text) => redactor.redactText(text))
167
+ : () => undefined;
166
168
  let result;
167
169
  try {
168
170
  result = await runWorkflowProgram({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@boardwalk-labs/runner",
3
- "version": "0.1.5",
3
+ "version": "0.1.6",
4
4
  "description": "Boardwalk self-hosted runner: execute cloud-scheduled runs on your own machines. Currently: the canonical runner contract types.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {