pi-harness-runtime 1.1.159 → 1.1.161
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/README.md +39 -0
- package/harness/infisical-config.ts +7 -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/context-compiler/package.json +1 -1
- package/packages/context-discovery/package.json +1 -1
- package/packages/context-manager/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/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-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/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/dist/adapters/telegram-adapter.d.ts.map +1 -1
- package/packages/notification/dist/adapters/telegram-adapter.js +8 -2
- package/packages/notification/dist/adapters/telegram-adapter.js.map +1 -1
- package/packages/notification/dist/index.d.ts +1 -0
- package/packages/notification/dist/index.d.ts.map +1 -1
- package/packages/notification/dist/index.js +1 -0
- package/packages/notification/dist/index.js.map +1 -1
- package/packages/notification/dist/mask-secrets.d.ts +31 -0
- package/packages/notification/dist/mask-secrets.d.ts.map +1 -0
- package/packages/notification/dist/mask-secrets.js +132 -0
- package/packages/notification/dist/mask-secrets.js.map +1 -0
- package/packages/notification/package.json +1 -1
- package/packages/notification/src/adapters/telegram-adapter.ts +8 -2
- package/packages/notification/src/index.ts +7 -0
- package/packages/notification/src/mask-secrets.ts +150 -0
- 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/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/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/trajectory/package.json +1 -1
- package/packages/tui/package.json +1 -1
- package/packages/types/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
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,cAAc,0BAA0B,CAAC;AACzC,cAAc,mBAAmB,CAAC;AAClC,cAAc,YAAY,CAAC;AAC3B,cAAc,+BAA+B,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,cAAc,0BAA0B,CAAC;AACzC,cAAc,mBAAmB,CAAC;AAClC,cAAc,YAAY,CAAC;AAC3B,cAAc,+BAA+B,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACjE,OAAO,EACN,UAAU,EACV,SAAS,EACT,UAAU,EACV,WAAW,EACX,gBAAgB,GAChB,MAAM,mBAAmB,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Secret Masking Utility
|
|
3
|
+
*
|
|
4
|
+
* Masks sensitive values in strings before sending to Telegram/other channels.
|
|
5
|
+
* Shows first 4 + last 4 characters for identification.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Mask a value showing first and last characters
|
|
9
|
+
*/
|
|
10
|
+
export declare function maskValue(value: string): string;
|
|
11
|
+
/**
|
|
12
|
+
* Check if a field name is sensitive
|
|
13
|
+
*/
|
|
14
|
+
export declare function isSensitiveField(fieldName: string): boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Mask sensitive patterns in a string
|
|
17
|
+
*/
|
|
18
|
+
export declare function maskString(input: string): string;
|
|
19
|
+
/**
|
|
20
|
+
* Mask JSON object fields that are sensitive
|
|
21
|
+
*/
|
|
22
|
+
export declare function maskObject(obj: unknown, depth?: number): Record<string, unknown> | unknown[] | string | number | boolean | null;
|
|
23
|
+
/**
|
|
24
|
+
* Mask a message/notification payload
|
|
25
|
+
*/
|
|
26
|
+
export declare function maskPayload(obj: unknown): Record<string, unknown> | unknown[] | string | number | boolean | null;
|
|
27
|
+
/**
|
|
28
|
+
* Format a value for display, masking if sensitive
|
|
29
|
+
*/
|
|
30
|
+
export declare function formatValue(key: string, value: unknown): string;
|
|
31
|
+
//# sourceMappingURL=mask-secrets.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mask-secrets.d.ts","sourceRoot":"","sources":["../src/mask-secrets.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAwCH;;GAEG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAK/C;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAU3D;AAuBD;;GAEG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,OAAO,EAAE,KAAK,GAAE,MAAU,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,EAAE,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,CA+BlI;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,EAAE,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,CAEhH;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,MAAM,CAK/D"}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Secret Masking Utility
|
|
3
|
+
*
|
|
4
|
+
* Masks sensitive values in strings before sending to Telegram/other channels.
|
|
5
|
+
* Shows first 4 + last 4 characters for identification.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Patterns that match sensitive values
|
|
9
|
+
*/
|
|
10
|
+
const SENSITIVE_PATTERNS = [
|
|
11
|
+
// Generic API keys, tokens, secrets
|
|
12
|
+
/[a-zA-Z0-9_-]{32,}/g, // Long alphanumeric strings (likely keys)
|
|
13
|
+
/[A-Fa-f0-9]{32,}/g, // Hex strings (likely hashes/keys)
|
|
14
|
+
/sk-[a-zA-Z0-9]{20,}/g, // OpenAI-style keys
|
|
15
|
+
/Bearer\s+[a-zA-Z0-9_-]{20,}/gi, // Bearer tokens
|
|
16
|
+
/token[=:]\s*[a-zA-Z0-9_-]{20,}/gi, // token=xxx patterns
|
|
17
|
+
/secret[=:]\s*[a-zA-Z0-9_-]{20,}/gi, // secret=xxx patterns
|
|
18
|
+
/key[=:]\s*[a-zA-Z0-9_-]{20,}/gi, // key=xxx patterns
|
|
19
|
+
/password[=:]\s*[^\s,}]+/gi, // password=xxx patterns
|
|
20
|
+
/client[_-]?secret[=:]\s*[^\s,}]+/gi, // client_secret=xxx
|
|
21
|
+
/client[_-]?id[=:]\s*[a-zA-Z0-9_-]{20,}/gi, // client_id=xxx
|
|
22
|
+
/infisical[_-]?(client[_-])?(secret|id)[=:]\s*[a-zA-Z0-9_-]{20,}/gi,
|
|
23
|
+
];
|
|
24
|
+
// Specific Infisical field names to mask
|
|
25
|
+
const INFISICAL_FIELDS = [
|
|
26
|
+
"infisical_client_secret",
|
|
27
|
+
"infisical_client_id",
|
|
28
|
+
"infisical_project_id",
|
|
29
|
+
"INFISICAL_CLIENT_SECRET",
|
|
30
|
+
"INFISICAL_CLIENT_ID",
|
|
31
|
+
"INFISICAL_PROJECT_ID",
|
|
32
|
+
];
|
|
33
|
+
// General sensitive field patterns
|
|
34
|
+
const SENSITIVE_FIELD_PATTERNS = [
|
|
35
|
+
/_api_key$/i,
|
|
36
|
+
/_secret$/i,
|
|
37
|
+
/_token$/i,
|
|
38
|
+
/_password$/i,
|
|
39
|
+
/_credential$/i,
|
|
40
|
+
/_auth$/i,
|
|
41
|
+
];
|
|
42
|
+
/**
|
|
43
|
+
* Mask a value showing first and last characters
|
|
44
|
+
*/
|
|
45
|
+
export function maskValue(value) {
|
|
46
|
+
if (!value || value.length <= 8) {
|
|
47
|
+
return "****";
|
|
48
|
+
}
|
|
49
|
+
return `${value.slice(0, 4)}...${value.slice(-4)}`;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Check if a field name is sensitive
|
|
53
|
+
*/
|
|
54
|
+
export function isSensitiveField(fieldName) {
|
|
55
|
+
const lower = fieldName.toLowerCase();
|
|
56
|
+
// Check specific Infisical fields
|
|
57
|
+
if (INFISICAL_FIELDS.some(f => lower === f.toLowerCase())) {
|
|
58
|
+
return true;
|
|
59
|
+
}
|
|
60
|
+
// Check general patterns
|
|
61
|
+
return SENSITIVE_FIELD_PATTERNS.some(pattern => pattern.test(lower));
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Mask a string value
|
|
65
|
+
*/
|
|
66
|
+
function maskStringValue(input) {
|
|
67
|
+
let result = input;
|
|
68
|
+
// First, mask any field=value patterns for sensitive fields
|
|
69
|
+
for (const field of INFISICAL_FIELDS) {
|
|
70
|
+
const escapedField = field.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
71
|
+
const pattern = new RegExp(`(${escapedField})\\s*[=:]\\s*([a-zA-Z0-9_-]+)`, "gi");
|
|
72
|
+
result = result.replace(pattern, (_match, _field, value) => `${field}: ${maskValue(value)}`);
|
|
73
|
+
}
|
|
74
|
+
// Then mask generic patterns
|
|
75
|
+
for (const pattern of SENSITIVE_PATTERNS) {
|
|
76
|
+
result = result.replace(pattern, (match) => maskValue(match));
|
|
77
|
+
}
|
|
78
|
+
return result;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Mask sensitive patterns in a string
|
|
82
|
+
*/
|
|
83
|
+
export function maskString(input) {
|
|
84
|
+
return maskStringValue(input);
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Mask JSON object fields that are sensitive
|
|
88
|
+
*/
|
|
89
|
+
export function maskObject(obj, depth = 0) {
|
|
90
|
+
// Prevent infinite recursion
|
|
91
|
+
if (depth > 10 || obj === null || obj === undefined) {
|
|
92
|
+
return obj;
|
|
93
|
+
}
|
|
94
|
+
if (typeof obj === "string") {
|
|
95
|
+
return maskStringValue(obj);
|
|
96
|
+
}
|
|
97
|
+
if (typeof obj === "number" || typeof obj === "boolean") {
|
|
98
|
+
return obj;
|
|
99
|
+
}
|
|
100
|
+
if (Array.isArray(obj)) {
|
|
101
|
+
return obj.map(item => maskObject(item, depth + 1));
|
|
102
|
+
}
|
|
103
|
+
if (typeof obj === "object") {
|
|
104
|
+
const result = {};
|
|
105
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
106
|
+
if (isSensitiveField(key)) {
|
|
107
|
+
result[key] = typeof value === "string" ? maskValue(value) : value;
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
result[key] = maskObject(value, depth + 1);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return result;
|
|
114
|
+
}
|
|
115
|
+
return obj;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Mask a message/notification payload
|
|
119
|
+
*/
|
|
120
|
+
export function maskPayload(obj) {
|
|
121
|
+
return maskObject(obj);
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Format a value for display, masking if sensitive
|
|
125
|
+
*/
|
|
126
|
+
export function formatValue(key, value) {
|
|
127
|
+
if (isSensitiveField(key) && typeof value === "string") {
|
|
128
|
+
return `${key}: ${maskValue(value)}`;
|
|
129
|
+
}
|
|
130
|
+
return `${key}: ${value}`;
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=mask-secrets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mask-secrets.js","sourceRoot":"","sources":["../src/mask-secrets.ts"],"names":[],"mappings":"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"}
|
|
@@ -18,6 +18,7 @@ import type {
|
|
|
18
18
|
TelegramConfig,
|
|
19
19
|
} from "../types.js";
|
|
20
20
|
import { BaseChannelAdapter } from "../base-adapter.js";
|
|
21
|
+
import { maskString } from "../mask-secrets.js";
|
|
21
22
|
|
|
22
23
|
export class TelegramAdapter extends BaseChannelAdapter {
|
|
23
24
|
readonly id = "telegram";
|
|
@@ -336,7 +337,9 @@ return this._botUsername;
|
|
|
336
337
|
private formatMessage(payload: NotificationPayload): string {
|
|
337
338
|
const emoji = this.getEmoji(payload.event);
|
|
338
339
|
const title = `${emoji} ${payload.title}`;
|
|
339
|
-
|
|
340
|
+
// Mask any secrets in message before sending to Telegram
|
|
341
|
+
const maskedMessage = maskString(payload.message);
|
|
342
|
+
const lines = [title, "", maskedMessage];
|
|
340
343
|
|
|
341
344
|
if (payload.details?.taskTitle) {
|
|
342
345
|
lines.push("", `Task: ${payload.details.taskTitle}`);
|
|
@@ -345,7 +348,10 @@ return this._botUsername;
|
|
|
345
348
|
lines.push(`Job: ${payload.details.jobId}`);
|
|
346
349
|
}
|
|
347
350
|
if (payload.details?.error) {
|
|
348
|
-
|
|
351
|
+
// Mask secrets in error messages too
|
|
352
|
+
const errorStr = String(payload.details.error);
|
|
353
|
+
const maskedError = maskString(errorStr);
|
|
354
|
+
lines.push("", `Error: ${maskedError}`);
|
|
349
355
|
}
|
|
350
356
|
|
|
351
357
|
return lines.filter(Boolean).join("\n");
|
|
@@ -10,3 +10,10 @@ export * from "./types.js";
|
|
|
10
10
|
export * from "./telegram-webhook-handler.js";
|
|
11
11
|
export { LineAdapter } from "./adapters/line-adapter.js";
|
|
12
12
|
export { TelegramAdapter } from "./adapters/telegram-adapter.js";
|
|
13
|
+
export {
|
|
14
|
+
maskString,
|
|
15
|
+
maskValue,
|
|
16
|
+
maskObject,
|
|
17
|
+
maskPayload,
|
|
18
|
+
isSensitiveField,
|
|
19
|
+
} from "./mask-secrets.js";
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Secret Masking Utility
|
|
3
|
+
*
|
|
4
|
+
* Masks sensitive values in strings before sending to Telegram/other channels.
|
|
5
|
+
* Shows first 4 + last 4 characters for identification.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Patterns that match sensitive values
|
|
10
|
+
*/
|
|
11
|
+
const SENSITIVE_PATTERNS: RegExp[] = [
|
|
12
|
+
// Generic API keys, tokens, secrets
|
|
13
|
+
/[a-zA-Z0-9_-]{32,}/g, // Long alphanumeric strings (likely keys)
|
|
14
|
+
/[A-Fa-f0-9]{32,}/g, // Hex strings (likely hashes/keys)
|
|
15
|
+
/sk-[a-zA-Z0-9]{20,}/g, // OpenAI-style keys
|
|
16
|
+
/Bearer\s+[a-zA-Z0-9_-]{20,}/gi, // Bearer tokens
|
|
17
|
+
/token[=:]\s*[a-zA-Z0-9_-]{20,}/gi, // token=xxx patterns
|
|
18
|
+
/secret[=:]\s*[a-zA-Z0-9_-]{20,}/gi, // secret=xxx patterns
|
|
19
|
+
/key[=:]\s*[a-zA-Z0-9_-]{20,}/gi, // key=xxx patterns
|
|
20
|
+
/password[=:]\s*[^\s,}]+/gi, // password=xxx patterns
|
|
21
|
+
/client[_-]?secret[=:]\s*[^\s,}]+/gi, // client_secret=xxx
|
|
22
|
+
/client[_-]?id[=:]\s*[a-zA-Z0-9_-]{20,}/gi, // client_id=xxx
|
|
23
|
+
/infisical[_-]?(client[_-])?(secret|id)[=:]\s*[a-zA-Z0-9_-]{20,}/gi,
|
|
24
|
+
];
|
|
25
|
+
|
|
26
|
+
// Specific Infisical field names to mask
|
|
27
|
+
const INFISICAL_FIELDS = [
|
|
28
|
+
"infisical_client_secret",
|
|
29
|
+
"infisical_client_id",
|
|
30
|
+
"infisical_project_id",
|
|
31
|
+
"INFISICAL_CLIENT_SECRET",
|
|
32
|
+
"INFISICAL_CLIENT_ID",
|
|
33
|
+
"INFISICAL_PROJECT_ID",
|
|
34
|
+
];
|
|
35
|
+
|
|
36
|
+
// General sensitive field patterns
|
|
37
|
+
const SENSITIVE_FIELD_PATTERNS = [
|
|
38
|
+
/_api_key$/i,
|
|
39
|
+
/_secret$/i,
|
|
40
|
+
/_token$/i,
|
|
41
|
+
/_password$/i,
|
|
42
|
+
/_credential$/i,
|
|
43
|
+
/_auth$/i,
|
|
44
|
+
];
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Mask a value showing first and last characters
|
|
48
|
+
*/
|
|
49
|
+
export function maskValue(value: string): string {
|
|
50
|
+
if (!value || value.length <= 8) {
|
|
51
|
+
return "****";
|
|
52
|
+
}
|
|
53
|
+
return `${value.slice(0, 4)}...${value.slice(-4)}`;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Check if a field name is sensitive
|
|
58
|
+
*/
|
|
59
|
+
export function isSensitiveField(fieldName: string): boolean {
|
|
60
|
+
const lower = fieldName.toLowerCase();
|
|
61
|
+
|
|
62
|
+
// Check specific Infisical fields
|
|
63
|
+
if (INFISICAL_FIELDS.some(f => lower === f.toLowerCase())) {
|
|
64
|
+
return true;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Check general patterns
|
|
68
|
+
return SENSITIVE_FIELD_PATTERNS.some(pattern => pattern.test(lower));
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Mask a string value
|
|
73
|
+
*/
|
|
74
|
+
function maskStringValue(input: string): string {
|
|
75
|
+
let result = input;
|
|
76
|
+
|
|
77
|
+
// First, mask any field=value patterns for sensitive fields
|
|
78
|
+
for (const field of INFISICAL_FIELDS) {
|
|
79
|
+
const escapedField = field.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
80
|
+
const pattern = new RegExp(`(${escapedField})\\s*[=:]\\s*([a-zA-Z0-9_-]+)`, "gi");
|
|
81
|
+
result = result.replace(pattern, (_match, _field, value) => `${field}: ${maskValue(value)}`);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Then mask generic patterns
|
|
85
|
+
for (const pattern of SENSITIVE_PATTERNS) {
|
|
86
|
+
result = result.replace(pattern, (match) => maskValue(match));
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return result;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Mask sensitive patterns in a string
|
|
94
|
+
*/
|
|
95
|
+
export function maskString(input: string): string {
|
|
96
|
+
return maskStringValue(input);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Mask JSON object fields that are sensitive
|
|
101
|
+
*/
|
|
102
|
+
export function maskObject(obj: unknown, depth: number = 0): Record<string, unknown> | unknown[] | string | number | boolean | null {
|
|
103
|
+
// Prevent infinite recursion
|
|
104
|
+
if (depth > 10 || obj === null || obj === undefined) {
|
|
105
|
+
return obj as null;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if (typeof obj === "string") {
|
|
109
|
+
return maskStringValue(obj);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
if (typeof obj === "number" || typeof obj === "boolean") {
|
|
113
|
+
return obj;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if (Array.isArray(obj)) {
|
|
117
|
+
return obj.map(item => maskObject(item, depth + 1));
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (typeof obj === "object") {
|
|
121
|
+
const result: Record<string, unknown> = {};
|
|
122
|
+
for (const [key, value] of Object.entries(obj as Record<string, unknown>)) {
|
|
123
|
+
if (isSensitiveField(key)) {
|
|
124
|
+
result[key] = typeof value === "string" ? maskValue(value) : value;
|
|
125
|
+
} else {
|
|
126
|
+
result[key] = maskObject(value, depth + 1);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return result as Record<string, unknown>;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
return obj;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Mask a message/notification payload
|
|
137
|
+
*/
|
|
138
|
+
export function maskPayload(obj: unknown): Record<string, unknown> | unknown[] | string | number | boolean | null {
|
|
139
|
+
return maskObject(obj);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Format a value for display, masking if sensitive
|
|
144
|
+
*/
|
|
145
|
+
export function formatValue(key: string, value: unknown): string {
|
|
146
|
+
if (isSensitiveField(key) && typeof value === "string") {
|
|
147
|
+
return `${key}: ${maskValue(value)}`;
|
|
148
|
+
}
|
|
149
|
+
return `${key}: ${value}`;
|
|
150
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-harness/provider-router",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.161",
|
|
4
4
|
"description": "Enhanced Provider Router for pi-harness-runtime — intelligent routing with capabilities, costs, and quotas",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/provider-router.js",
|