omp-conductor 0.3.24 → 0.4.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.
@@ -5,6 +5,14 @@
5
5
  * daemon never handles a token itself: credentials stay in the user's keychain
6
6
  * or `gh` config and are never passed as argv, written to a file, or logged.
7
7
  *
8
+ * That reachability is exactly what #125 confines. The environment this adapter
9
+ * hands `gh` comes from `credentialedEnv()` — the one named construction site
10
+ * of credential material in the daemon — so "which processes can reach the
11
+ * operator's GitHub write credential" is answered by that function's call
12
+ * sites, not by auditing every spawn in the tree. Sessions get the opposite
13
+ * environment, and on a `per-run` host they are a different OS principal
14
+ * entirely and could not use this credential even if they found it.
15
+ *
8
16
  * ponytail: shelling out to `gh` is the deliberate simplification. The ceiling
9
17
  * is per-call cost (one process spawn plus one TLS handshake per operation,
10
18
  * ~200-400ms) and failure classification by matching human-readable stderr
@@ -13,9 +21,12 @@
13
21
  * `gh auth token`; the eleven Tracker methods above it stay untouched.
14
22
  */
15
23
 
24
+ import { credentialedEnv } from "../credentials.ts";
25
+ import { parsePrDiff } from "../diff-flags.ts";
16
26
  import type {
17
27
  IssueState,
18
28
  OpenCloser,
29
+ PrDiff,
19
30
  PrState,
20
31
  PrVerification,
21
32
  ProjectConfig,
@@ -129,6 +140,11 @@ async function gh(argv: string[], stdin?: string): Promise<string> {
129
140
  stdin: new Blob([stdin ?? ""]),
130
141
  stdout: "pipe",
131
142
  stderr: "pipe",
143
+ // The privileged side of the boundary (#125). Explicit rather than
144
+ // inherited so that adding a credential-scrubbing default to this process
145
+ // could never silently break the tracker, and so that the grep for
146
+ // `credentialedEnv` finds this call.
147
+ env: credentialedEnv(),
132
148
  });
133
149
 
134
150
  const [stdout, stderr, code] = await Promise.all([
@@ -208,6 +224,17 @@ export function firstOpenCloser(raw: string): OpenCloser | undefined {
208
224
  */
209
225
  const PR_URL = /^https?:\/\/[^\s/]+\/[^\s/]+\/[^\s/]+\/pull\/\d+\/?$/;
210
226
 
227
+ /**
228
+ * How much of a pull request's diff the settlement audit will hold in memory.
229
+ *
230
+ * The daemon runs every worker in its own process, so an unbounded read of a
231
+ * PR that regenerated a 90 MB lockfile would be paid for out of the same
232
+ * resident set the live workers are using. Truncation only ever loses trailing
233
+ * files, which costs findings and never invents them, and the parsed diff
234
+ * carries `truncated` so the report never presents a short read as a clean one.
235
+ */
236
+ const MAX_DIFF_BYTES = 4 * 1024 * 1024;
237
+
211
238
  type CheckVerdict = PrVerification["status"];
212
239
 
213
240
  function checkName(check: GhCheck): string {
@@ -528,5 +555,23 @@ export function makeTracker(p: ProjectConfig, runGh: typeof gh = gh): Tracker {
528
555
  return undefined;
529
556
  }
530
557
  },
558
+
559
+ async prDiff(url: string): Promise<PrDiff | undefined> {
560
+ if (!PR_URL.test(url)) return undefined;
561
+ try {
562
+ // `--color never` rather than relying on the default: `auto` is decided
563
+ // from the child's stdout, and this adapter pipes it, but a diff with
564
+ // ANSI escapes in it would silently stop matching every pattern the
565
+ // audit looks for — a failure that looks exactly like a clean PR.
566
+ const raw = await runGh(["pr", "diff", url, "--color", "never"]);
567
+ return raw.length > MAX_DIFF_BYTES
568
+ ? parsePrDiff(raw.slice(0, MAX_DIFF_BYTES), true)
569
+ : parsePrDiff(raw);
570
+ } catch {
571
+ // Advisory: an unreadable diff costs one unaudited settlement, never a
572
+ // run's state. Undefined is "could not tell", not "clean".
573
+ return undefined;
574
+ }
575
+ },
531
576
  };
532
577
  }