@basein/runner 0.2.11 → 0.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.
Files changed (144) hide show
  1. package/README.md +540 -350
  2. package/dist/auth/client.d.ts +65 -3
  3. package/dist/auth/client.js +305 -53
  4. package/dist/bin/bir-hooks.d.ts +72 -31
  5. package/dist/bin/bir-hooks.js +176 -284
  6. package/dist/bin/bir-proxy.d.ts +17 -2
  7. package/dist/bin/bir-proxy.js +222 -28
  8. package/dist/bin/bir-scenario.d.ts +61 -10
  9. package/dist/bin/bir-scenario.js +704 -135
  10. package/dist/bin/bir.d.ts +14 -8
  11. package/dist/bin/bir.js +2937 -488
  12. package/dist/bin/investigate.js +41 -16
  13. package/dist/bin/scenario-edit.d.ts +43 -10
  14. package/dist/bin/scenario-edit.js +281 -80
  15. package/dist/bin/scenario-liveness.d.ts +194 -0
  16. package/dist/bin/scenario-liveness.js +459 -0
  17. package/dist/bin/scenario-stderr.d.ts +43 -0
  18. package/dist/bin/scenario-stderr.js +76 -0
  19. package/dist/bin/service-read.d.ts +88 -0
  20. package/dist/bin/service-read.js +128 -0
  21. package/dist/bin/setup.d.ts +19 -0
  22. package/dist/bin/setup.js +146 -20
  23. package/dist/config/adapters/claude-code.d.ts +92 -14
  24. package/dist/config/adapters/claude-code.js +291 -101
  25. package/dist/config/adapters/generic.d.ts +4 -1
  26. package/dist/config/adapters/generic.js +13 -14
  27. package/dist/config/generate.d.ts +392 -14
  28. package/dist/config/generate.js +666 -19
  29. package/dist/config/mcp-approval.d.ts +76 -0
  30. package/dist/config/mcp-approval.js +210 -0
  31. package/dist/config/node-path.d.ts +42 -0
  32. package/dist/config/node-path.js +102 -0
  33. package/dist/config/overrides.d.ts +62 -0
  34. package/dist/config/overrides.js +136 -0
  35. package/dist/config/resolve.d.ts +70 -8
  36. package/dist/config/resolve.js +186 -15
  37. package/dist/control/client.d.ts +22 -0
  38. package/dist/control/client.js +26 -7
  39. package/dist/control/correlation.d.ts +23 -5
  40. package/dist/control/correlation.js +0 -0
  41. package/dist/control/daemon.d.ts +400 -18
  42. package/dist/control/daemon.js +1105 -102
  43. package/dist/control/discovery.d.ts +77 -5
  44. package/dist/control/discovery.js +186 -11
  45. package/dist/control/ensure-hook.d.ts +61 -0
  46. package/dist/control/ensure-hook.js +160 -8
  47. package/dist/control/paths.d.ts +26 -0
  48. package/dist/control/paths.js +34 -0
  49. package/dist/control/pin-guard.d.ts +83 -0
  50. package/dist/control/pin-guard.js +534 -0
  51. package/dist/control/recorder-keeper.d.ts +229 -0
  52. package/dist/control/recorder-keeper.js +721 -0
  53. package/dist/control/recorder-main.d.ts +73 -0
  54. package/dist/control/recorder-main.js +778 -0
  55. package/dist/control/server.d.ts +707 -31
  56. package/dist/control/server.js +2803 -306
  57. package/dist/control/transcript.d.ts +21 -1
  58. package/dist/control/transcript.js +378 -112
  59. package/dist/index.d.ts +5 -1
  60. package/dist/index.js +5 -1
  61. package/dist/jsonrpc/framing.d.ts +76 -12
  62. package/dist/jsonrpc/framing.js +216 -59
  63. package/dist/proxy/intercept.d.ts +49 -5
  64. package/dist/proxy/intercept.js +188 -59
  65. package/dist/proxy/relay.d.ts +16 -0
  66. package/dist/proxy/relay.js +77 -5
  67. package/dist/proxy/revive.d.ts +122 -0
  68. package/dist/proxy/revive.js +251 -0
  69. package/dist/proxy/session.d.ts +222 -14
  70. package/dist/proxy/session.js +708 -99
  71. package/dist/record/housekeeping.d.ts +71 -0
  72. package/dist/record/housekeeping.js +417 -0
  73. package/dist/record/recorder.d.ts +51 -3
  74. package/dist/record/recorder.js +3 -0
  75. package/dist/record/redact.d.ts +103 -9
  76. package/dist/record/redact.js +659 -30
  77. package/dist/record/remote-recorder.d.ts +327 -32
  78. package/dist/record/remote-recorder.js +1517 -187
  79. package/dist/record/switchable-recorder.d.ts +126 -0
  80. package/dist/record/switchable-recorder.js +351 -0
  81. package/dist/record/truncate.d.ts +40 -1
  82. package/dist/record/truncate.js +111 -4
  83. package/dist/replay/bash-channel.d.ts +35 -0
  84. package/dist/replay/bash-channel.js +133 -0
  85. package/dist/replay/bundle.d.ts +10 -0
  86. package/dist/replay/bundle.js +10 -0
  87. package/dist/replay/controller.d.ts +371 -20
  88. package/dist/replay/controller.js +1185 -111
  89. package/dist/replay/derive.d.ts +1 -0
  90. package/dist/replay/derive.js +81 -24
  91. package/dist/replay/executor.d.ts +51 -16
  92. package/dist/replay/executor.js +114 -41
  93. package/dist/replay/handover.d.ts +54 -1
  94. package/dist/replay/handover.js +55 -5
  95. package/dist/replay/logic.d.ts +62 -10
  96. package/dist/replay/logic.js +140 -22
  97. package/dist/replay/plan.d.ts +201 -27
  98. package/dist/replay/plan.js +581 -141
  99. package/dist/replay/safety.d.ts +72 -0
  100. package/dist/replay/safety.js +303 -0
  101. package/dist/replay/source-run.d.ts +10 -0
  102. package/dist/replay/source-run.js +80 -35
  103. package/dist/replay/targets.d.ts +15 -1
  104. package/dist/replay/targets.js +62 -4
  105. package/dist/replay/tool-error.d.ts +15 -1
  106. package/dist/replay/tool-error.js +33 -1
  107. package/dist/replay/types.d.ts +7 -4
  108. package/dist/upstream/client.d.ts +56 -3
  109. package/dist/upstream/client.js +61 -4
  110. package/dist/upstream/headers.d.ts +43 -0
  111. package/dist/upstream/headers.js +90 -0
  112. package/dist/upstream/http-client.d.ts +213 -22
  113. package/dist/upstream/http-client.js +1034 -168
  114. package/dist/upstream/http-transport.d.ts +143 -0
  115. package/dist/upstream/http-transport.js +391 -0
  116. package/dist/upstream/lazy-client.d.ts +8 -0
  117. package/dist/upstream/lazy-client.js +29 -1
  118. package/dist/upstream/sse.d.ts +78 -0
  119. package/dist/upstream/sse.js +189 -0
  120. package/dist/upstream/stdio-client.d.ts +61 -1
  121. package/dist/upstream/stdio-client.js +356 -33
  122. package/dist/util/atomic-write.d.ts +29 -0
  123. package/dist/util/atomic-write.js +96 -0
  124. package/dist/util/journal.d.ts +15 -0
  125. package/dist/util/journal.js +48 -3
  126. package/dist/util/log.d.ts +10 -0
  127. package/dist/util/log.js +28 -1
  128. package/dist/util/off-switch.d.ts +46 -0
  129. package/dist/util/off-switch.js +91 -0
  130. package/dist/util/service-health.d.ts +133 -0
  131. package/dist/util/service-health.js +217 -0
  132. package/docs/BaseInstRunner.md +694 -621
  133. package/docs/calculatedReplay.md +1625 -1244
  134. package/docs/calculatedReplayGuide.md +1212 -879
  135. package/docs/installRun.md +1013 -772
  136. package/docs/loginWeb.md +627 -607
  137. package/docs/mcpmark.md +49 -16
  138. package/docs/my-first-sample.md +569 -545
  139. package/docs/quickstart.md +384 -271
  140. package/docs/t-bench.md +406 -394
  141. package/package.json +58 -57
  142. package/production.md +1371 -0
  143. package/scripts/install.ps1 +97 -6
  144. package/scripts/install.sh +104 -7
@@ -4,28 +4,122 @@
4
4
  * The proxy sits on the credential path for every wrapped server (§9), and every
5
5
  * argument and result it sees crosses a process boundary and then the network.
6
6
  * So redaction runs on the recording copy of both arguments *and* results,
7
- * before the step report is even queued.
7
+ * before the step report is even queued — and once more, as the last line of
8
+ * defence, on every free-text field `RemoteRecorder` sends (the prompt, the
9
+ * answer, the reasoning, error messages), because those never pass through a
10
+ * structured payload at all.
8
11
  *
9
12
  * Three rules, in the order they fire:
10
- * 1. **By key.** A value under a key matching {@link SECRET_KEY} is replaced
11
- * wholesale, whatever its type. `authorization: { scheme, token }` loses
12
- * both halves, because the object as a whole is the secret.
13
+ * 1. **By key.** A value under a key that names a secret ({@link isSecretKey})
14
+ * is replaced wholesale, whatever its type. `authorization: { scheme, token }`
15
+ * loses both halves, because the object as a whole is the secret.
13
16
  * 2. **`env` blocks.** An object under an `env` key has *every* value replaced.
14
17
  * MCP server configs put credentials there under arbitrary names, so no key
15
18
  * pattern would catch them.
16
- * 3. **By shape.** A string that looks like a bearer token, a JWT, an
17
- * `sk-`/`ghp_`-style key or an AWS access key id is replaced wherever it
18
- * appears — including inside free text, where key-matching cannot reach.
19
+ * 3. **By shape.** A string that looks like a credential — a bearer token, a
20
+ * JWT, a provider key, a PEM private key, a password in a URL, a
21
+ * `DB_PASSWORD=…` line of a `.env` file, an `X-Api-Key:` header — is
22
+ * replaced wherever it appears, including inside free text, where key
23
+ * matching cannot reach. Reading `.env` or `~/.aws/credentials` is a routine
24
+ * thing for an agent to do; its result is recorded like any other.
25
+ *
26
+ * KEYS ARE MATCHED ON WHOLE NAME SEGMENTS, not substrings. The old rule was one
27
+ * unanchored alternation, so `author`, `max_tokens`, `nextPageToken` and
28
+ * `tokenizer` were all "secrets" — the recording lost real arguments (numbers
29
+ * became the string "[redacted]") and a scenario built from it had nothing to
30
+ * replay. Names are split on camelCase, snake_case, kebab-case and dots, and a
31
+ * segment has to *be* the secret word (`token`, `accessToken`, `x-api-key`), not
32
+ * merely contain it. The names 0.2.12's substring rule caught that do hold
33
+ * credentials are still caught: plurals (`tokens`, `api_keys`), an `auth` that
34
+ * ends the name (`basic_auth`, `X-Upstream-Auth`), `oauth`, `authentication`,
35
+ * `auth_code` — and a number under the secret itself (`token: 482913`, an OTP).
36
+ *
37
+ * TEXT RULES ARE ANCHORED TO WHERE SECRETS ARE WRITTEN, not to every
38
+ * `name = value` in sight. A recorded Read of source code must survive: its
39
+ * bytes are what a scenario's output logic is authored against, and
40
+ * `const token = await getToken()` is not a secret. So assignments are only
41
+ * redacted in env/ini/YAML line form, shell `NAME=value` form, header form and
42
+ * JSON `"key": "value"` form, and never when the value is visibly code (a call,
43
+ * a member access, a `${reference}`, a type in a declaration such as
44
+ * `password: string`, or a variable named for the same thing such as
45
+ * `token: newToken`). A separator never spans a line break: an empty
46
+ * `DB_PASSWORD=` must not take the next line with it.
47
+ *
48
+ * JSON TEXT IS REDACTED AS JSON. A serialized tool payload goes through
49
+ * {@link redactJsonText}, which parses it and runs the rules on each string
50
+ * leaf — the same pass its producer's {@link redact} made — so the result is
51
+ * always valid JSON and, when nothing new was found, the producer's bytes
52
+ * exactly (live replay serializes a result the same way and compares). The
53
+ * rules still tolerate JSON-escaped text (a string leaf that holds a JSON
54
+ * document, a preview of one): they never start a match inside an escape
55
+ * sequence and never replace a quote or a backslash, so an escaped document
56
+ * stays parseable.
19
57
  *
20
58
  * Redaction never throws and never mutates its input: a cycle, a `BigInt`, a
21
59
  * getter that explodes — each degrades to a placeholder rather than losing the
22
60
  * step or, worse, taking the session down.
23
61
  */
24
62
  export declare const REDACTED = "[redacted]";
25
- /** Keys whose values are secret regardless of shape. */
63
+ /**
64
+ * The substring rule this module used before key segments. Kept exported for
65
+ * anything that imported it, and applied again under `BIR_REDACT_LEGACY_KEYS=1`.
66
+ *
67
+ * @deprecated over-matches ordinary names (`author`, `max_tokens`); use {@link isSecretKey}.
68
+ */
26
69
  export declare const SECRET_KEY: RegExp;
27
- /** Replace every secret-shaped run inside a string. */
70
+ /**
71
+ * A string leaf longer than this is cut before its shapes are scanned. Every
72
+ * consumer caps a recorded payload far below it (64 KiB), so the cut is never
73
+ * visible in what is sent — it only stops a 20 MB tool result from costing a
74
+ * few hundred milliseconds of regex work on a hook's path.
75
+ */
76
+ export declare const REDACT_SCAN_MAX_CHARS: number;
77
+ /**
78
+ * How strongly a key names a secret. `strong` redacts any value but a boolean
79
+ * — the secret itself (`password`, `token`, `api_key`, `mfa_token`) may well
80
+ * be a number: a one-time code, a PIN, a numeric key. `weak` (a session id,
81
+ * something *about* a token such as `token_id`, a list such as `tokens`)
82
+ * keeps numbers and booleans too, which are ids, counters and flags there far
83
+ * more often than they are credentials.
84
+ */
85
+ export type SecretKeyStrength = "strong" | "weak";
86
+ export declare function secretKeyStrength(name: string): SecretKeyStrength | undefined;
87
+ /** True when a value under `name` is a secret (see {@link secretKeyStrength}). */
88
+ export declare function isSecretKey(name: string): boolean;
89
+ /**
90
+ * The same question for an UPPER_SNAKE environment variable name, where the
91
+ * words run together (`PGPASSWORD`, `GITHUB_TOKEN`, `AWS_SECRET_ACCESS_KEY`)
92
+ * and substring matching is the convention rather than the mistake — minus
93
+ * the counters (`MAX_TOKENS`, `TOKENIZERS_PARALLELISM`) and file pointers
94
+ * (`PASSWORD_FILE`, the Docker secrets convention).
95
+ */
96
+ export declare function isSecretEnvName(name: string): boolean;
97
+ /**
98
+ * Replace every secret-shaped run inside a string.
99
+ *
100
+ * Idempotent: redacting the result again changes nothing. That is what lets a
101
+ * payload be redacted by its producer and again at the recorder without its
102
+ * bytes moving (live replay compares against them). One pass is not always a
103
+ * fixed point — a match one rule declined (`Authorization: Authorization: …`)
104
+ * can hide a secret that only shows once a later rule has run — so a pass that
105
+ * changed something is followed by another, until one changes nothing.
106
+ */
28
107
  export declare function redactText(text: string): string;
108
+ /**
109
+ * Redact a string that holds JSON — a serialized tool input, result or error —
110
+ * and return JSON, always.
111
+ *
112
+ * Running {@link redactText} over the serialized text could not promise that:
113
+ * a rule that met `\n` after an empty `KEY=` wrote `KEY=\[redacted]`, and the
114
+ * service stored a payload no parser accepts. So the text is parsed and every
115
+ * string leaf gets the rules as plain text, exactly as its producer's
116
+ * {@link redact} did. When that finds nothing new — the normal case, since
117
+ * producers redact first — the original bytes come back untouched: live replay
118
+ * serializes a result the same way and compares against what was recorded.
119
+ * Text that is not JSON (a truncated preview, a producer's plain error) gets
120
+ * {@link redactText}: there is no structure to keep.
121
+ */
122
+ export declare function redactJsonText(text: string): string;
29
123
  /**
30
124
  * Deep-clone `value` with secrets removed. The result is always JSON-safe, so
31
125
  * the caller can serialise it without a second failure mode.