pi-harness-runtime 1.1.435 → 1.1.436
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/harness/key-file-audit.ts +103 -3
- package/harness/startup-report.ts +32 -1
- package/index.ts +28 -0
- package/package.json +1 -1
- package/packages/a2a-adapter/package.json +1 -1
- package/packages/agent-policy/package.json +1 -1
- package/packages/architecture-generator/package.json +1 -1
- package/packages/auth/package.json +1 -1
- package/packages/autonomous-refactor/package.json +1 -1
- package/packages/autonomous-runtime/package.json +1 -1
- package/packages/cache-strategy/package.json +1 -1
- package/packages/capability-registry/package.json +1 -1
- package/packages/checkpoint/package.json +1 -1
- package/packages/cli-plugin-sdk/package.json +1 -1
- package/packages/clipboard/package.json +1 -1
- package/packages/clipboard-plugin/package.json +1 -1
- package/packages/code-generation/package.json +1 -1
- package/packages/code-review/package.json +1 -1
- package/packages/codex-adapter/package.json +1 -1
- package/packages/codex-watcher/package.json +1 -1
- package/packages/config-capture/package.json +1 -1
- package/packages/connection-runtime/package.json +1 -1
- package/packages/context-compiler/package.json +1 -1
- package/packages/context-discovery/package.json +1 -1
- package/packages/context-manager/package.json +1 -1
- package/packages/contracts/package.json +1 -1
- package/packages/cookie-sanitizer/package.json +1 -1
- package/packages/cost-optimizer/package.json +1 -1
- package/packages/dependency-analyzer/package.json +1 -1
- package/packages/django-plugin/package.json +1 -1
- package/packages/doc-generator/package.json +1 -1
- package/packages/durable-review/package.json +1 -1
- package/packages/e2e-tester/package.json +1 -1
- package/packages/evaluation-engine/package.json +1 -1
- package/packages/evaluation-runner/package.json +1 -1
- package/packages/event-bus/package.json +1 -1
- package/packages/event-sink/package.json +1 -1
- package/packages/event-store/package.json +1 -1
- package/packages/experience-replay/package.json +1 -1
- package/packages/feedback-collector/package.json +1 -1
- package/packages/file-copy-helper/package.json +1 -1
- package/packages/framework-detector/package.json +1 -1
- package/packages/framework-plugin-sdk/package.json +1 -1
- package/packages/frappe-plugin/package.json +1 -1
- package/packages/generic-web-plugin/package.json +1 -1
- package/packages/health-monitor/package.json +1 -1
- package/packages/intent-analyzer/package.json +1 -1
- package/packages/jev-judge/package.json +1 -1
- package/packages/knowledge-graph/package.json +1 -1
- package/packages/knowledge-retrieval/package.json +1 -1
- package/packages/laravel-plugin/package.json +1 -1
- package/packages/learning-engine/package.json +1 -1
- package/packages/logging/package.json +1 -1
- package/packages/mcp-adapter/package.json +1 -1
- package/packages/memory-engine/package.json +1 -1
- package/packages/milestone-manager/package.json +1 -1
- package/packages/model-registry/package.json +1 -1
- package/packages/nextjs-plugin/package.json +1 -1
- package/packages/notification/package.json +1 -1
- package/packages/observability/package.json +1 -1
- package/packages/okf-indexer/package.json +1 -1
- package/packages/paperclip-integration/package.json +1 -1
- package/packages/performance-optimizer/package.json +1 -1
- package/packages/permission-mode/package.json +1 -1
- package/packages/privilege-broker/package.json +1 -1
- package/packages/project-analyzer/package.json +1 -1
- package/packages/project-bootstrap/package.json +1 -1
- package/packages/projection-engine/package.json +1 -1
- package/packages/prompt-compiler/package.json +1 -1
- package/packages/prompt-versioning/package.json +1 -1
- package/packages/provider-adapter-sdk/package.json +1 -1
- package/packages/provider-router/package.json +1 -1
- package/packages/provider-selector/package.json +1 -1
- package/packages/providers/package.json +1 -1
- package/packages/qdrant-skills/package.json +1 -1
- package/packages/quota-manager/package.json +1 -1
- package/packages/rate-limiter/package.json +1 -1
- package/packages/react-vite-plugin/package.json +1 -1
- package/packages/relay/package.json +1 -1
- package/packages/release-manager/package.json +1 -1
- package/packages/requirement-compiler/package.json +1 -1
- package/packages/runtime/package.json +1 -1
- package/packages/scheduler/package.json +1 -1
- package/packages/scheduler-adapter/package.json +1 -1
- package/packages/session/package.json +1 -1
- package/packages/session-api/package.json +1 -1
- package/packages/session-export/package.json +1 -1
- package/packages/shared-context/package.json +1 -1
- package/packages/skill-mcp-client/package.json +1 -1
- package/packages/skill-registry/package.json +1 -1
- package/packages/skills/package.json +1 -1
- package/packages/sprint-planner/package.json +1 -1
- package/packages/subscription-engine/package.json +1 -1
- package/packages/task-compiler/package.json +1 -1
- package/packages/tencentdb-memory/package.json +1 -1
- package/packages/tencentdb-sync/package.json +1 -1
- package/packages/test-data-generator/package.json +1 -1
- package/packages/test-generator/package.json +1 -1
- package/packages/todo-bd-sync/package.json +1 -1
- package/packages/token-estimation/package.json +1 -1
- package/packages/token-optimizer/package.json +1 -1
- package/packages/tooling-preference/package.json +1 -1
- package/packages/trajectory/package.json +1 -1
- package/packages/tui/package.json +1 -1
- package/packages/two-phase-review/package.json +1 -1
- package/packages/types/package.json +1 -1
- package/packages/voice-api/package.json +1 -1
- package/packages/webmcp-tester/package.json +1 -1
- package/packages/wiki/package.json +1 -1
- package/packages/workflow-events/package.json +1 -1
- package/packages/workspace-scanner/package.json +1 -1
- package/packages/worktree/package.json +1 -1
- package/packages/write-review/package.json +1 -1
- package/scripts/check-sensitive-terms.d.mts +116 -0
- package/scripts/check-sensitive-terms.mjs +728 -0
- package/scripts/release/adapters/node-workspace.ts +1 -3
- package/scripts/release/tsconfig.json +11 -0
- package/scripts/typecheck-packages.mjs +15 -2
- package/scripts/verify-package-contents.ts +69 -1
- package/scripts/tsconfig.json +0 -9
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
* state of a file (missing / empty).
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
|
-
import { existsSync, readFileSync } from "node:fs";
|
|
18
|
+
import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
|
|
19
19
|
import { homedir } from "node:os";
|
|
20
20
|
import { join } from "node:path";
|
|
21
21
|
|
|
@@ -303,6 +303,22 @@ function isDerivableWebhookUrl(value: string): boolean {
|
|
|
303
303
|
}
|
|
304
304
|
}
|
|
305
305
|
|
|
306
|
+
/**
|
|
307
|
+
* A key file that other users on this machine can read.
|
|
308
|
+
*
|
|
309
|
+
* A key file is a secret. A secret that the group or the others can read
|
|
310
|
+
* is not a secret - it is published to every account on the machine. The
|
|
311
|
+
* audit does not read the content of such a file; it looks at the mode.
|
|
312
|
+
*/
|
|
313
|
+
export interface ExposedKeyFile {
|
|
314
|
+
/** The name of the file, relative to the key directory. */
|
|
315
|
+
file: string;
|
|
316
|
+
/** The mode of the file, as an octal string ("644"). */
|
|
317
|
+
mode: string;
|
|
318
|
+
/** Who can read the file besides the owner. */
|
|
319
|
+
readableBy: "group" | "others" | "group and others";
|
|
320
|
+
}
|
|
321
|
+
|
|
306
322
|
export interface KeyFileAuditOptions {
|
|
307
323
|
/** The key directory to scan (e.g. ~/.pi-harness-runtime/keys). */
|
|
308
324
|
keysDir: string;
|
|
@@ -312,6 +328,10 @@ export interface KeyFileAuditOptions {
|
|
|
312
328
|
readFile?: (path: string) => string | undefined;
|
|
313
329
|
/** Existence check override (used by the tests). */
|
|
314
330
|
exists?: (path: string) => boolean;
|
|
331
|
+
/** Directory reader override (used by the tests). */
|
|
332
|
+
readdir?: (path: string) => string[];
|
|
333
|
+
/** File information override (used by the tests). */
|
|
334
|
+
stat?: (path: string) => { mode: number; isFile: boolean } | undefined;
|
|
315
335
|
}
|
|
316
336
|
|
|
317
337
|
export interface KeyFileAuditResult {
|
|
@@ -319,6 +339,61 @@ export interface KeyFileAuditResult {
|
|
|
319
339
|
missing: MissingCredential[];
|
|
320
340
|
/** The unresolved credentials grouped by their owning feature. */
|
|
321
341
|
byFeature: Map<string, MissingCredential[]>;
|
|
342
|
+
/** The key files that other users on this machine can read. */
|
|
343
|
+
exposed: ExposedKeyFile[];
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
/**
|
|
347
|
+
* The key files that other users on this machine can read.
|
|
348
|
+
*
|
|
349
|
+
* A key file with the mode 600 is a secret. Every other bit in the group
|
|
350
|
+
* or the others column publishes it to the accounts on the machine, and
|
|
351
|
+
* nothing in the harness notices - the file is read successfully by the
|
|
352
|
+
* owner, so nothing fails and nothing is reported.
|
|
353
|
+
*
|
|
354
|
+
* The whole directory is scanned, not only the files of the inventory: a
|
|
355
|
+
* key file that the inventory does not know yet is a secret too.
|
|
356
|
+
*/
|
|
357
|
+
export function scanExposedKeyFiles(options: KeyFileAuditOptions): ExposedKeyFile[] {
|
|
358
|
+
const readdir =
|
|
359
|
+
options.readdir ??
|
|
360
|
+
((path: string) => {
|
|
361
|
+
try {
|
|
362
|
+
return readdirSync(path);
|
|
363
|
+
} catch {
|
|
364
|
+
return [];
|
|
365
|
+
}
|
|
366
|
+
});
|
|
367
|
+
const stat =
|
|
368
|
+
options.stat ??
|
|
369
|
+
((path: string) => {
|
|
370
|
+
try {
|
|
371
|
+
const info = statSync(path);
|
|
372
|
+
return { mode: info.mode & 0o777, isFile: info.isFile() };
|
|
373
|
+
} catch {
|
|
374
|
+
return undefined;
|
|
375
|
+
}
|
|
376
|
+
});
|
|
377
|
+
|
|
378
|
+
const exposed: ExposedKeyFile[] = [];
|
|
379
|
+
for (const name of readdir(options.keysDir).sort()) {
|
|
380
|
+
const info = stat(join(options.keysDir, name));
|
|
381
|
+
if (!info || !info.isFile) continue;
|
|
382
|
+
const group = info.mode & 0o070;
|
|
383
|
+
const others = info.mode & 0o007;
|
|
384
|
+
if (group === 0 && others === 0) continue;
|
|
385
|
+
exposed.push({
|
|
386
|
+
file: name,
|
|
387
|
+
mode: info.mode.toString(8).padStart(3, "0"),
|
|
388
|
+
readableBy:
|
|
389
|
+
group !== 0 && others !== 0
|
|
390
|
+
? "group and others"
|
|
391
|
+
: group !== 0
|
|
392
|
+
? "group"
|
|
393
|
+
: "others",
|
|
394
|
+
});
|
|
395
|
+
}
|
|
396
|
+
return exposed;
|
|
322
397
|
}
|
|
323
398
|
|
|
324
399
|
/**
|
|
@@ -396,10 +471,35 @@ export function auditKeyFiles(options: KeyFileAuditOptions): KeyFileAuditResult
|
|
|
396
471
|
byFeature.set(entry.requirement.feature, list);
|
|
397
472
|
}
|
|
398
473
|
|
|
399
|
-
return { missing, byFeature };
|
|
474
|
+
return { missing, byFeature, exposed: scanExposedKeyFiles(options) };
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
/**
|
|
478
|
+
* The command that makes a key file private again.
|
|
479
|
+
*
|
|
480
|
+
* The file keeps its content - the command changes the mode, not the
|
|
481
|
+
* value.
|
|
482
|
+
*/
|
|
483
|
+
export function formatExposedKeyFileFix(
|
|
484
|
+
entry: ExposedKeyFile,
|
|
485
|
+
keysDir: string,
|
|
486
|
+
): string {
|
|
487
|
+
return `chmod 600 ${join(displayKeysDir(keysDir), entry.file)}`;
|
|
400
488
|
}
|
|
401
489
|
|
|
402
|
-
/**
|
|
490
|
+
/**
|
|
491
|
+
* The fix commands for every key file that other users can read.
|
|
492
|
+
*/
|
|
493
|
+
export function formatExposedKeyFileFixes(
|
|
494
|
+
entries: ExposedKeyFile[] | undefined,
|
|
495
|
+
keysDir: string,
|
|
496
|
+
): string[] {
|
|
497
|
+
if (!entries || entries.length === 0) return [];
|
|
498
|
+
return entries.map((entry) => formatExposedKeyFileFix(entry, keysDir));
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
/**
|
|
502
|
+
* The key directory as it is shown to the user (~ instead of the home path). */
|
|
403
503
|
export function displayKeysDir(keysDir: string): string {
|
|
404
504
|
const home = homedir();
|
|
405
505
|
return keysDir.startsWith(home) ? join("~", keysDir.slice(home.length)) : keysDir;
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* - LINE must not be reported as configured when the audit could not run.
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
|
-
import type { KeyFileAuditResult } from "./key-file-audit.ts";
|
|
14
|
+
import type { ExposedKeyFile, KeyFileAuditResult } from "./key-file-audit.ts";
|
|
15
15
|
|
|
16
16
|
export type StartupStatus = "wait" | "ok" | "info" | "warn" | "err";
|
|
17
17
|
|
|
@@ -141,6 +141,37 @@ export function relayEndpointReport(options: {
|
|
|
141
141
|
};
|
|
142
142
|
}
|
|
143
143
|
|
|
144
|
+
/**
|
|
145
|
+
* The line for key files that other users on this machine can read.
|
|
146
|
+
*
|
|
147
|
+
* A key file is a secret, and a secret that the group or the others can
|
|
148
|
+
* read is published to every account on the machine. Nothing else notices:
|
|
149
|
+
* the harness reads the file successfully, so no feature fails and no other
|
|
150
|
+
* line warns. This line is the only place where the fact can surface.
|
|
151
|
+
*
|
|
152
|
+
* The line names the count and the command. It never names a value.
|
|
153
|
+
*/
|
|
154
|
+
export function exposedKeyFilesReport(options: {
|
|
155
|
+
/** The key files that other users can read. */
|
|
156
|
+
exposed: ExposedKeyFile[];
|
|
157
|
+
/** The `chmod` command for each of them. */
|
|
158
|
+
fixes: string[];
|
|
159
|
+
}): StartupReport | null {
|
|
160
|
+
if (options.exposed.length === 0) return null;
|
|
161
|
+
const count = options.exposed.length;
|
|
162
|
+
const text =
|
|
163
|
+
count === 1
|
|
164
|
+
? "1 key file can be read by other users on this machine"
|
|
165
|
+
: `${count} key files can be read by other users on this machine`;
|
|
166
|
+
const details = [...options.fixes];
|
|
167
|
+
if (details.length === 0) {
|
|
168
|
+
details.push(
|
|
169
|
+
"Make the key directory private: chmod 700 ~/.pi-harness-runtime/keys",
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
return { label: "Keys", text, status: "warn", details };
|
|
173
|
+
}
|
|
174
|
+
|
|
144
175
|
/**
|
|
145
176
|
* The two steps that create a usable LINE channel.
|
|
146
177
|
*
|
package/index.ts
CHANGED
|
@@ -23,6 +23,7 @@ import { HarnessStartupStatus, harnessStatusMarker, type HarnessStatus } from ".
|
|
|
23
23
|
import {
|
|
24
24
|
auditKeyFiles,
|
|
25
25
|
fallbackKeyFileFixes,
|
|
26
|
+
formatExposedKeyFileFixes,
|
|
26
27
|
formatKeyFileFixes,
|
|
27
28
|
selectKeyFileFixes,
|
|
28
29
|
type KeyFileAuditResult,
|
|
@@ -32,6 +33,7 @@ import { describeInboundAccess, getAllowedUserIds } from "./harness/telegram-aut
|
|
|
32
33
|
import { buildTelegramCallbackUpdate, buildTelegramMessageUpdate } from "./harness/telegram-update.ts";
|
|
33
34
|
import { installConsoleGuard } from "./harness/console-guard.ts";
|
|
34
35
|
import {
|
|
36
|
+
exposedKeyFilesReport,
|
|
35
37
|
jevMissingKeyReport,
|
|
36
38
|
lineConfigurationReport,
|
|
37
39
|
oneLineError,
|
|
@@ -200,6 +202,26 @@ function getKeyFileAudit(): KeyFileAuditResult | null {
|
|
|
200
202
|
return keyFileAudit;
|
|
201
203
|
}
|
|
202
204
|
|
|
205
|
+
/**
|
|
206
|
+
* Report the key files that other users on this machine can read.
|
|
207
|
+
*
|
|
208
|
+
* A key file is a secret. The harness reads its own key files, so a file
|
|
209
|
+
* that the group or the others can read works perfectly - and is published
|
|
210
|
+
* to every account on the machine. No other line notices, so this is the
|
|
211
|
+
* only place where the fact can surface.
|
|
212
|
+
*/
|
|
213
|
+
function reportExposedKeyFiles(): void {
|
|
214
|
+
const audit = getKeyFileAudit();
|
|
215
|
+
const exposed = audit?.exposed ?? [];
|
|
216
|
+
if (exposed.length === 0) return;
|
|
217
|
+
const report = exposedKeyFilesReport({
|
|
218
|
+
exposed,
|
|
219
|
+
fixes: formatExposedKeyFileFixes(exposed, harnessKeysDir()),
|
|
220
|
+
});
|
|
221
|
+
if (!report) return;
|
|
222
|
+
addHarnessMessage(report.label, report.text, report.status, report.details);
|
|
223
|
+
}
|
|
224
|
+
|
|
203
225
|
/**
|
|
204
226
|
* The `echo` commands that create the missing key files of one feature.
|
|
205
227
|
*
|
|
@@ -4240,6 +4262,11 @@ export default async function (pi: ExtensionAPI) {
|
|
|
4240
4262
|
// Telegram is not configured at all - that is the fresh-install case.
|
|
4241
4263
|
reportRelayConfiguration();
|
|
4242
4264
|
|
|
4265
|
+
// The key files that other users can read. The audit is read by
|
|
4266
|
+
// every other line, so this is the only place where a published
|
|
4267
|
+
// secret can surface.
|
|
4268
|
+
reportExposedKeyFiles();
|
|
4269
|
+
|
|
4243
4270
|
// --- console-guard: keep the TUI prompt input field clean ----
|
|
4244
4271
|
// A library that writes to the console would put its text into the
|
|
4245
4272
|
// prompt input field. The guard sends it to the harness log instead.
|
|
@@ -6186,6 +6213,7 @@ Run \`bd ready\` to see current bd issues.
|
|
|
6186
6213
|
keyFileAuditDone = false;
|
|
6187
6214
|
reportRelayConfiguration();
|
|
6188
6215
|
reportLineConfiguration();
|
|
6216
|
+
reportExposedKeyFiles();
|
|
6189
6217
|
// Service states survive session changes; initialization runs once per extension load.
|
|
6190
6218
|
harnessWidgetRegistered = false; // Reset for new session
|
|
6191
6219
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-harness/capability-registry",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.436",
|
|
4
4
|
"description": "Capability Registry for pi-harness-runtime — tracks model capabilities and enables capability-based routing",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|