@teamscala/service-boot 0.23.331 → 0.23.333
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/package.json
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
},
|
|
7
7
|
"name": "@teamscala/service-boot",
|
|
8
8
|
"type": "module",
|
|
9
|
-
"version": "0.23.
|
|
9
|
+
"version": "0.23.333",
|
|
10
10
|
"sideEffects": false,
|
|
11
11
|
"files": [
|
|
12
12
|
"src"
|
|
@@ -38,6 +38,7 @@
|
|
|
38
38
|
"@teamscala/proc-walker": "*",
|
|
39
39
|
"@teamscala/realtime-utils": "*",
|
|
40
40
|
"@teamscala/resolver-engine": "*",
|
|
41
|
+
"@teamscala/safe-fallback": "*",
|
|
41
42
|
"@teamscala/timing": "*",
|
|
42
43
|
"@teamscala/tool-executor": "*",
|
|
43
44
|
"@teamscala/watchdog": "*",
|
|
@@ -40,6 +40,7 @@
|
|
|
40
40
|
import { getAppLogger } from "@teamscala/logger/app-loggers";
|
|
41
41
|
import { recordEvent } from "@teamscala/event-log/record-event";
|
|
42
42
|
import { getPlatformOrgId } from "@teamscala/db/registry/platform";
|
|
43
|
+
import { createSafeFallback } from "@teamscala/safe-fallback/create-safe-fallback";
|
|
43
44
|
import { authed, type Context } from "./auth-router.ts";
|
|
44
45
|
import { notifyLaneOfTaskChange } from "./task-sync-dispatch.ts";
|
|
45
46
|
import { resolveLaneTask, resolveLaneWorkName } from "./task-sync-lane.ts";
|
|
@@ -173,6 +174,12 @@ export function resolveBindOrg(explicit?: string): string {
|
|
|
173
174
|
return explicit ?? getPlatformOrgId();
|
|
174
175
|
}
|
|
175
176
|
|
|
177
|
+
const laneTaskCreateFallback = createSafeFallback<WorkItem | null>({
|
|
178
|
+
name: "task-sync:lane-task-create-race",
|
|
179
|
+
onFailure: "fail-open-noisy",
|
|
180
|
+
degradedResult: null,
|
|
181
|
+
});
|
|
182
|
+
|
|
176
183
|
/**
|
|
177
184
|
* Record a task-sync hook DISCARD to event_log so it is observable + queryable,
|
|
178
185
|
* not silently swallowed by the hook command's `>/dev/null 2>&1 || true`. The
|
|
@@ -288,8 +295,8 @@ async function ensureLaneTask(
|
|
|
288
295
|
const name = pane ? await resolveLaneWorkName(prisma, pane) : null;
|
|
289
296
|
if (!name || name.trim().toLowerCase() === "lane") return null;
|
|
290
297
|
const lane: LaneIdentity = { pane: pane ?? "", session, cli_kind: "claude-code", role: "agent" };
|
|
291
|
-
|
|
292
|
-
|
|
298
|
+
const created = await laneTaskCreateFallback.call(() =>
|
|
299
|
+
prisma.work_items.create({
|
|
293
300
|
data: {
|
|
294
301
|
kind: "task",
|
|
295
302
|
parent_id: null,
|
|
@@ -301,10 +308,9 @@ async function ensureLaneTask(
|
|
|
301
308
|
assignee_id: session,
|
|
302
309
|
kind_data: { lane },
|
|
303
310
|
},
|
|
304
|
-
})
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
}
|
|
311
|
+
}),
|
|
312
|
+
);
|
|
313
|
+
return created ?? resolveLaneTask(prisma, session);
|
|
308
314
|
}
|
|
309
315
|
|
|
310
316
|
|
|
@@ -25,6 +25,13 @@
|
|
|
25
25
|
* WebSocket upgrades are returned untouched (Bun tracks upgrades by Request
|
|
26
26
|
* identity — a clone can never upgrade).
|
|
27
27
|
*/
|
|
28
|
+
/**
|
|
29
|
+
* Preserve useful process attribution without copying arbitrary argv into logs.
|
|
30
|
+
* Arguments routinely contain bearer headers, inline scripts, URLs and secret
|
|
31
|
+
* values. There is no complete flag-name redaction list, so the safe boundary
|
|
32
|
+
* is structural: retain argv[0] and state that arguments were removed.
|
|
33
|
+
*/
|
|
34
|
+
export declare function summariseLocalCommand(cmdline: readonly string[]): string | null;
|
|
28
35
|
/**
|
|
29
36
|
* Return a Request with transport-identity headers stamped, or the original
|
|
30
37
|
* `req` when no stamping is needed/possible. Never throws.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { describe, expect, test } from "bun:test";
|
|
2
|
+
import { summariseLocalCommand } from "./stamp-transport-identity.ts";
|
|
3
|
+
|
|
4
|
+
describe("local command attribution", () => {
|
|
5
|
+
test("never copies command arguments into telemetry", () => {
|
|
6
|
+
const token = "operator-token-must-not-appear";
|
|
7
|
+
const summary = summariseLocalCommand([
|
|
8
|
+
"curl",
|
|
9
|
+
"-H",
|
|
10
|
+
`x-operator-spawn-token: ${token}`,
|
|
11
|
+
"http://127.0.0.1:3021/rpc/spawn",
|
|
12
|
+
]);
|
|
13
|
+
expect(summary).toBe("curl [arguments redacted]");
|
|
14
|
+
expect(summary).not.toContain(token);
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
test("keeps a lone executable name", () => {
|
|
18
|
+
expect(summariseLocalCommand(["scala-picker"])).toBe("scala-picker");
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
test("omits an empty command line", () => {
|
|
22
|
+
expect(summariseLocalCommand([])).toBeNull();
|
|
23
|
+
});
|
|
24
|
+
});
|
|
@@ -31,6 +31,18 @@ import { resolveSocketPeer } from "@teamscala/proc-walker/socket-peer";
|
|
|
31
31
|
|
|
32
32
|
const LOOPBACK = new Set(["127.0.0.1", "::1", "::ffff:127.0.0.1"]);
|
|
33
33
|
|
|
34
|
+
/**
|
|
35
|
+
* Preserve useful process attribution without copying arbitrary argv into logs.
|
|
36
|
+
* Arguments routinely contain bearer headers, inline scripts, URLs and secret
|
|
37
|
+
* values. There is no complete flag-name redaction list, so the safe boundary
|
|
38
|
+
* is structural: retain argv[0] and state that arguments were removed.
|
|
39
|
+
*/
|
|
40
|
+
export function summariseLocalCommand(cmdline: readonly string[]): string | null {
|
|
41
|
+
const executable = cmdline[0]?.trim();
|
|
42
|
+
if (!executable) return null;
|
|
43
|
+
return cmdline.length > 1 ? `${executable} [arguments redacted]` : executable;
|
|
44
|
+
}
|
|
45
|
+
|
|
34
46
|
/**
|
|
35
47
|
* Return a Request with transport-identity headers stamped, or the original
|
|
36
48
|
* `req` when no stamping is needed/possible. Never throws.
|
|
@@ -77,8 +89,8 @@ export function stampTransportIdentity(
|
|
|
77
89
|
const owner = resolveSocketPeer(port);
|
|
78
90
|
if (owner) {
|
|
79
91
|
headers.set(CALLER_HEADERS.LOCAL_COMM, owner.comm);
|
|
80
|
-
const cmd = owner.cmdline
|
|
81
|
-
if (cmd) headers.set(CALLER_HEADERS.LOCAL_CMD, cmd
|
|
92
|
+
const cmd = summariseLocalCommand(owner.cmdline);
|
|
93
|
+
if (cmd) headers.set(CALLER_HEADERS.LOCAL_CMD, cmd);
|
|
82
94
|
}
|
|
83
95
|
}
|
|
84
96
|
return new Request(req.url, {
|