promptkaizen-agent 0.1.0 → 0.2.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.
- package/README.md +5 -3
- package/dist/cli/init.d.ts.map +1 -1
- package/dist/cli/init.js +4 -1
- package/dist/cli/init.js.map +1 -1
- package/dist/cli/install-systemd.d.ts +17 -0
- package/dist/cli/install-systemd.d.ts.map +1 -0
- package/dist/cli/install-systemd.js +96 -0
- package/dist/cli/install-systemd.js.map +1 -0
- package/dist/cli/start.d.ts.map +1 -1
- package/dist/cli/start.js +43 -2
- package/dist/cli/start.js.map +1 -1
- package/dist/cli/status.d.ts.map +1 -1
- package/dist/cli/status.js +24 -2
- package/dist/cli/status.js.map +1 -1
- package/dist/cli/uninstall-systemd.d.ts +8 -0
- package/dist/cli/uninstall-systemd.d.ts.map +1 -0
- package/dist/cli/uninstall-systemd.js +58 -0
- package/dist/cli/uninstall-systemd.js.map +1 -0
- package/dist/config.d.ts +61 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +31 -1
- package/dist/config.js.map +1 -1
- package/dist/detection-secret.d.ts +8 -0
- package/dist/detection-secret.d.ts.map +1 -0
- package/dist/detection-secret.js +37 -0
- package/dist/detection-secret.js.map +1 -0
- package/dist/index.js +13 -5
- package/dist/index.js.map +1 -1
- package/dist/mask-rules-fetcher.d.ts +15 -0
- package/dist/mask-rules-fetcher.d.ts.map +1 -0
- package/dist/mask-rules-fetcher.js +67 -0
- package/dist/mask-rules-fetcher.js.map +1 -0
- package/dist/pii-masker.d.ts +48 -1
- package/dist/pii-masker.d.ts.map +1 -1
- package/dist/pii-masker.js +144 -41
- package/dist/pii-masker.js.map +1 -1
- package/dist/secret-detector.d.ts +82 -0
- package/dist/secret-detector.d.ts.map +1 -0
- package/dist/secret-detector.js +400 -0
- package/dist/secret-detector.js.map +1 -0
- package/dist/types.d.ts +12 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HMAC 鍵を解決する。優先順:
|
|
3
|
+
* 1. agent 設定 `detection.hmacSecret`
|
|
4
|
+
* 2. 既存の鍵ファイル (~/.promptkaizen/detection-secret)
|
|
5
|
+
* 3. 初回起動時に生成して同ファイルへ保存 (mode 600)
|
|
6
|
+
*/
|
|
7
|
+
export declare function loadOrCreateDetectionSecret(configSecret?: string, secretPath?: string): Promise<string>;
|
|
8
|
+
//# sourceMappingURL=detection-secret.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detection-secret.d.ts","sourceRoot":"","sources":["../src/detection-secret.ts"],"names":[],"mappings":"AAWA;;;;;GAKG;AACH,wBAAsB,2BAA2B,CAC/C,YAAY,CAAC,EAAE,MAAM,EACrB,UAAU,GAAE,MAA4B,GACvC,OAAO,CAAC,MAAM,CAAC,CAYjB"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.loadOrCreateDetectionSecret = loadOrCreateDetectionSecret;
|
|
7
|
+
const crypto_1 = require("crypto");
|
|
8
|
+
const promises_1 = __importDefault(require("fs/promises"));
|
|
9
|
+
const os_1 = __importDefault(require("os"));
|
|
10
|
+
const path_1 = __importDefault(require("path"));
|
|
11
|
+
// pii/pii_jp の matchHash (HMAC-SHA256) に使うローカルシークレット (Issue #42)。
|
|
12
|
+
// マイナンバー等の低エントロピー値を無塩ハッシュで送ると総当たりで復元できてしまう
|
|
13
|
+
// ため、鍵付きハッシュにする。鍵はローカルにのみ保持し、クラウドへは送らない。
|
|
14
|
+
const DEFAULT_SECRET_PATH = path_1.default.join(os_1.default.homedir(), '.promptkaizen', 'detection-secret');
|
|
15
|
+
/**
|
|
16
|
+
* HMAC 鍵を解決する。優先順:
|
|
17
|
+
* 1. agent 設定 `detection.hmacSecret`
|
|
18
|
+
* 2. 既存の鍵ファイル (~/.promptkaizen/detection-secret)
|
|
19
|
+
* 3. 初回起動時に生成して同ファイルへ保存 (mode 600)
|
|
20
|
+
*/
|
|
21
|
+
async function loadOrCreateDetectionSecret(configSecret, secretPath = DEFAULT_SECRET_PATH) {
|
|
22
|
+
if (configSecret)
|
|
23
|
+
return configSecret;
|
|
24
|
+
try {
|
|
25
|
+
const existing = (await promises_1.default.readFile(secretPath, 'utf8')).trim();
|
|
26
|
+
if (existing.length >= 32)
|
|
27
|
+
return existing;
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
// ファイルなし (初回起動) → 下で生成する
|
|
31
|
+
}
|
|
32
|
+
const secret = (0, crypto_1.randomBytes)(32).toString('hex');
|
|
33
|
+
await promises_1.default.mkdir(path_1.default.dirname(secretPath), { recursive: true });
|
|
34
|
+
await promises_1.default.writeFile(secretPath, secret + '\n', { mode: 0o600 });
|
|
35
|
+
return secret;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=detection-secret.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detection-secret.js","sourceRoot":"","sources":["../src/detection-secret.ts"],"names":[],"mappings":";;;;;AAiBA,kEAeC;AAhCD,mCAAoC;AACpC,2DAA4B;AAC5B,4CAAmB;AACnB,gDAAuB;AAEvB,kEAAkE;AAClE,2CAA2C;AAC3C,yCAAyC;AAEzC,MAAM,mBAAmB,GAAG,cAAI,CAAC,IAAI,CAAC,YAAE,CAAC,OAAO,EAAE,EAAE,eAAe,EAAE,kBAAkB,CAAC,CAAA;AAExF;;;;;GAKG;AACI,KAAK,UAAU,2BAA2B,CAC/C,YAAqB,EACrB,aAAqB,mBAAmB;IAExC,IAAI,YAAY;QAAE,OAAO,YAAY,CAAA;IACrC,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,CAAC,MAAM,kBAAE,CAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,EAAE,CAAA;QAC/D,IAAI,QAAQ,CAAC,MAAM,IAAI,EAAE;YAAE,OAAO,QAAQ,CAAA;IAC5C,CAAC;IAAC,MAAM,CAAC;QACP,yBAAyB;IAC3B,CAAC;IACD,MAAM,MAAM,GAAG,IAAA,oBAAW,EAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;IAC9C,MAAM,kBAAE,CAAC,KAAK,CAAC,cAAI,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IAC7D,MAAM,kBAAE,CAAC,SAAS,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAA;IAC9D,OAAO,MAAM,CAAA;AACf,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -3,9 +3,11 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
4
|
const init_1 = require("./cli/init");
|
|
5
5
|
const install_launchd_1 = require("./cli/install-launchd");
|
|
6
|
+
const install_systemd_1 = require("./cli/install-systemd");
|
|
6
7
|
const start_1 = require("./cli/start");
|
|
7
8
|
const status_1 = require("./cli/status");
|
|
8
9
|
const uninstall_launchd_1 = require("./cli/uninstall-launchd");
|
|
10
|
+
const uninstall_systemd_1 = require("./cli/uninstall-systemd");
|
|
9
11
|
const version_1 = require("./version");
|
|
10
12
|
const HELP = `promptkaizen-agent v${version_1.AGENT_VERSION}
|
|
11
13
|
|
|
@@ -18,17 +20,19 @@ Usage:
|
|
|
18
20
|
|
|
19
21
|
Subcommands:
|
|
20
22
|
init Interactive setup — write ~/.promptkaizen/agent.config.json
|
|
21
|
-
start Run the agent in the foreground (used by launchd too)
|
|
22
|
-
status Health check: config,
|
|
23
|
-
install-launchd Register a
|
|
24
|
-
uninstall-launchd Remove the LaunchAgent (config/offsets preserved)
|
|
23
|
+
start Run the agent in the foreground (used by launchd/systemd too)
|
|
24
|
+
status Health check: config, autostart, process, offsets, endpoint
|
|
25
|
+
install-launchd [macOS] Register a LaunchAgent — auto-start on login + auto-restart
|
|
26
|
+
uninstall-launchd [macOS] Remove the LaunchAgent (config/offsets preserved)
|
|
27
|
+
install-systemd [Linux] Register a systemd user unit — auto-start + auto-restart
|
|
28
|
+
uninstall-systemd [Linux] Remove the systemd user unit (config/offsets preserved)
|
|
25
29
|
version Print agent version
|
|
26
30
|
help Print this message
|
|
27
31
|
|
|
28
32
|
Examples:
|
|
29
33
|
npm link # one-time, from repo root after build
|
|
30
34
|
promptkaizen-agent init
|
|
31
|
-
promptkaizen-agent install-launchd
|
|
35
|
+
promptkaizen-agent install-launchd # macOS (Linux: install-systemd)
|
|
32
36
|
promptkaizen-agent status
|
|
33
37
|
`;
|
|
34
38
|
async function main() {
|
|
@@ -44,6 +48,10 @@ async function main() {
|
|
|
44
48
|
return (0, install_launchd_1.runInstallLaunchd)(rest);
|
|
45
49
|
case 'uninstall-launchd':
|
|
46
50
|
return (0, uninstall_launchd_1.runUninstallLaunchd)(rest);
|
|
51
|
+
case 'install-systemd':
|
|
52
|
+
return (0, install_systemd_1.runInstallSystemd)(rest);
|
|
53
|
+
case 'uninstall-systemd':
|
|
54
|
+
return (0, uninstall_systemd_1.runUninstallSystemd)(rest);
|
|
47
55
|
case 'version':
|
|
48
56
|
case '--version':
|
|
49
57
|
case '-v':
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AACA,qCAAoC;AACpC,2DAAyD;AACzD,uCAAsC;AACtC,yCAAwC;AACxC,+DAA6D;AAC7D,uCAAyC;AAEzC,MAAM,IAAI,GAAG,uBAAuB,uBAAa
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AACA,qCAAoC;AACpC,2DAAyD;AACzD,2DAAyD;AACzD,uCAAsC;AACtC,yCAAwC;AACxC,+DAA6D;AAC7D,+DAA6D;AAC7D,uCAAyC;AAEzC,MAAM,IAAI,GAAG,uBAAuB,uBAAa;;;;;;;;;;;;;;;;;;;;;;;;;CAyBhD,CAAA;AAED,KAAK,UAAU,IAAI;IACjB,MAAM,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;IAC5C,QAAQ,GAAG,EAAE,CAAC;QACZ,KAAK,MAAM;YACT,OAAO,IAAA,cAAO,EAAC,IAAI,CAAC,CAAA;QACtB,KAAK,OAAO;YACV,OAAO,IAAA,gBAAQ,EAAC,IAAI,CAAC,CAAA;QACvB,KAAK,QAAQ;YACX,OAAO,IAAA,kBAAS,EAAC,IAAI,CAAC,CAAA;QACxB,KAAK,iBAAiB;YACpB,OAAO,IAAA,mCAAiB,EAAC,IAAI,CAAC,CAAA;QAChC,KAAK,mBAAmB;YACtB,OAAO,IAAA,uCAAmB,EAAC,IAAI,CAAC,CAAA;QAClC,KAAK,iBAAiB;YACpB,OAAO,IAAA,mCAAiB,EAAC,IAAI,CAAC,CAAA;QAChC,KAAK,mBAAmB;YACtB,OAAO,IAAA,uCAAmB,EAAC,IAAI,CAAC,CAAA;QAClC,KAAK,SAAS,CAAC;QACf,KAAK,WAAW,CAAC;QACjB,KAAK,IAAI;YACP,OAAO,CAAC,GAAG,CAAC,uBAAa,CAAC,CAAA;YAC1B,OAAM;QACR,KAAK,SAAS,CAAC;QACf,KAAK,MAAM,CAAC;QACZ,KAAK,QAAQ,CAAC;QACd,KAAK,IAAI;YACP,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;YACjB,OAAM;QACR;YACE,OAAO,CAAC,KAAK,CAAC,uBAAuB,GAAG,IAAI,CAAC,CAAA;YAC7C,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;YACnB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACnB,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAU,EAAE,EAAE;IAC1B,OAAO,CAAC,KAAK,CAAC,UAAU,GAAG,CAAC,OAAO,EAAE,CAAC,CAAA;IACtC,IAAI,OAAO,CAAC,GAAG,CAAC,wBAAwB,KAAK,GAAG,IAAI,GAAG,CAAC,KAAK,EAAE,CAAC;QAC9D,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;IAC1B,CAAC;IACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;AACjB,CAAC,CAAC,CAAA"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { MaskRulesConfig } from './pii-masker';
|
|
2
|
+
/** receiveObservations と同じ apiKey/endpoint pattern で /getAgentMaskRules を導出。 */
|
|
3
|
+
export declare function maskRulesUrl(apiEndpoint: string): string;
|
|
4
|
+
export interface FetchMaskRulesOptions {
|
|
5
|
+
apiEndpoint: string;
|
|
6
|
+
apiKey: string;
|
|
7
|
+
fetchImpl?: typeof fetch;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* 組織/ユーザーのマスクルールを取得する。
|
|
11
|
+
* - 未設定 (cloud に doc がない) → null (ローカル設定のみで動作)
|
|
12
|
+
* - 通信エラー / 不正レスポンス → null + warn log (検知・送信は止めない)
|
|
13
|
+
*/
|
|
14
|
+
export declare function fetchMaskRules(opts: FetchMaskRulesOptions): Promise<MaskRulesConfig | null>;
|
|
15
|
+
//# sourceMappingURL=mask-rules-fetcher.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mask-rules-fetcher.d.ts","sourceRoot":"","sources":["../src/mask-rules-fetcher.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AAWnD,gFAAgF;AAChF,wBAAgB,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAExD;AAsBD,MAAM,WAAW,qBAAqB;IACpC,WAAW,EAAE,MAAM,CAAA;IACnB,MAAM,EAAE,MAAM,CAAA;IACd,SAAS,CAAC,EAAE,OAAO,KAAK,CAAA;CACzB;AAED;;;;GAIG;AACH,wBAAsB,cAAc,CAAC,IAAI,EAAE,qBAAqB,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAuBjG"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.maskRulesUrl = maskRulesUrl;
|
|
4
|
+
exports.fetchMaskRules = fetchMaskRules;
|
|
5
|
+
const zod_1 = require("zod");
|
|
6
|
+
const logger_1 = require("./logger");
|
|
7
|
+
// =============================================
|
|
8
|
+
// 組織マスクルールの取得 (Issue #43)
|
|
9
|
+
// =============================================
|
|
10
|
+
//
|
|
11
|
+
// cloud (functions/src/agent/maskRules.ts getAgentMaskRules) から組織/ユーザーの
|
|
12
|
+
// マスクルールを取得する。認証は receiveObservations / agentHeartbeat と同じ
|
|
13
|
+
// Bearer apiKey。取得できない場合は null を返し、agent はローカル設定のみで
|
|
14
|
+
// 動作する (マスキング適用自体はローカル完結を維持)。
|
|
15
|
+
/** receiveObservations と同じ apiKey/endpoint pattern で /getAgentMaskRules を導出。 */
|
|
16
|
+
function maskRulesUrl(apiEndpoint) {
|
|
17
|
+
return apiEndpoint.replace(/\/receiveObservations\/?$/, '/getAgentMaskRules');
|
|
18
|
+
}
|
|
19
|
+
// cloud 側 (functions/src/agent/maskRules.ts) の schema と整合させること。
|
|
20
|
+
const MaskRulesSchema = zod_1.z.object({
|
|
21
|
+
builtin: zod_1.z.object({
|
|
22
|
+
maskApiKeys: zod_1.z.boolean(),
|
|
23
|
+
maskFilePaths: zod_1.z.boolean(),
|
|
24
|
+
maskEmails: zod_1.z.boolean(),
|
|
25
|
+
}),
|
|
26
|
+
customRules: zod_1.z
|
|
27
|
+
.array(zod_1.z.object({
|
|
28
|
+
ruleId: zod_1.z.string().regex(/^[A-Za-z0-9_-]{1,50}$/),
|
|
29
|
+
pattern: zod_1.z.string().min(1).max(500),
|
|
30
|
+
replacement: zod_1.z.string().max(100),
|
|
31
|
+
enabled: zod_1.z.boolean(),
|
|
32
|
+
}))
|
|
33
|
+
.max(100),
|
|
34
|
+
updatedAt: zod_1.z.number().optional(),
|
|
35
|
+
});
|
|
36
|
+
/**
|
|
37
|
+
* 組織/ユーザーのマスクルールを取得する。
|
|
38
|
+
* - 未設定 (cloud に doc がない) → null (ローカル設定のみで動作)
|
|
39
|
+
* - 通信エラー / 不正レスポンス → null + warn log (検知・送信は止めない)
|
|
40
|
+
*/
|
|
41
|
+
async function fetchMaskRules(opts) {
|
|
42
|
+
const doFetch = opts.fetchImpl ?? fetch;
|
|
43
|
+
try {
|
|
44
|
+
const res = await doFetch(maskRulesUrl(opts.apiEndpoint), {
|
|
45
|
+
method: 'GET',
|
|
46
|
+
headers: { Authorization: `Bearer ${opts.apiKey}` },
|
|
47
|
+
});
|
|
48
|
+
if (!res.ok) {
|
|
49
|
+
logger_1.logger.warn('fetchMaskRules: non-OK response', { status: res.status });
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
const body = (await res.json());
|
|
53
|
+
if (!body.success || body.rules == null)
|
|
54
|
+
return null;
|
|
55
|
+
const parsed = MaskRulesSchema.safeParse(body.rules);
|
|
56
|
+
if (!parsed.success) {
|
|
57
|
+
logger_1.logger.warn('fetchMaskRules: invalid rules payload', { error: parsed.error.message });
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
return parsed.data;
|
|
61
|
+
}
|
|
62
|
+
catch (e) {
|
|
63
|
+
logger_1.logger.warn('fetchMaskRules failed', { error: e.message });
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=mask-rules-fetcher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mask-rules-fetcher.js","sourceRoot":"","sources":["../src/mask-rules-fetcher.ts"],"names":[],"mappings":";;AAcA,oCAEC;AAiCD,wCAuBC;AAxED,6BAAuB;AACvB,qCAAiC;AAGjC,gDAAgD;AAChD,0BAA0B;AAC1B,gDAAgD;AAChD,EAAE;AACF,wEAAwE;AACxE,2DAA2D;AAC3D,oDAAoD;AACpD,8BAA8B;AAE9B,gFAAgF;AAChF,SAAgB,YAAY,CAAC,WAAmB;IAC9C,OAAO,WAAW,CAAC,OAAO,CAAC,2BAA2B,EAAE,oBAAoB,CAAC,CAAA;AAC/E,CAAC;AAED,gEAAgE;AAChE,MAAM,eAAe,GAAG,OAAC,CAAC,MAAM,CAAC;IAC/B,OAAO,EAAE,OAAC,CAAC,MAAM,CAAC;QAChB,WAAW,EAAE,OAAC,CAAC,OAAO,EAAE;QACxB,aAAa,EAAE,OAAC,CAAC,OAAO,EAAE;QAC1B,UAAU,EAAE,OAAC,CAAC,OAAO,EAAE;KACxB,CAAC;IACF,WAAW,EAAE,OAAC;SACX,KAAK,CACJ,OAAC,CAAC,MAAM,CAAC;QACP,MAAM,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,uBAAuB,CAAC;QACjD,OAAO,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC;QACnC,WAAW,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC;QAChC,OAAO,EAAE,OAAC,CAAC,OAAO,EAAE;KACrB,CAAC,CACH;SACA,GAAG,CAAC,GAAG,CAAC;IACX,SAAS,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CACjC,CAAC,CAAA;AAQF;;;;GAIG;AACI,KAAK,UAAU,cAAc,CAAC,IAA2B;IAC9D,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,IAAI,KAAK,CAAA;IACvC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,YAAY,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE;YACxD,MAAM,EAAE,KAAK;YACb,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,IAAI,CAAC,MAAM,EAAE,EAAE;SACpD,CAAC,CAAA;QACF,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,eAAM,CAAC,IAAI,CAAC,iCAAiC,EAAE,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC,CAAA;YACtE,OAAO,IAAI,CAAA;QACb,CAAC;QACD,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAA2C,CAAA;QACzE,IAAI,CAAC,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,KAAK,IAAI,IAAI;YAAE,OAAO,IAAI,CAAA;QACpD,MAAM,MAAM,GAAG,eAAe,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QACpD,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,eAAM,CAAC,IAAI,CAAC,uCAAuC,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAA;YACrF,OAAO,IAAI,CAAA;QACb,CAAC;QACD,OAAO,MAAM,CAAC,IAAI,CAAA;IACpB,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,eAAM,CAAC,IAAI,CAAC,uBAAuB,EAAE,EAAE,KAAK,EAAG,CAAW,CAAC,OAAO,EAAE,CAAC,CAAA;QACrE,OAAO,IAAI,CAAA;IACb,CAAC;AACH,CAAC"}
|
package/dist/pii-masker.d.ts
CHANGED
|
@@ -1,10 +1,55 @@
|
|
|
1
1
|
import type { AgentConfig } from './config';
|
|
2
2
|
import type { ParsedEntry } from './types';
|
|
3
|
+
/** ファイルパス / 画像など、正規表現グループ外の構造的ルールの ruleId。 */
|
|
4
|
+
export declare const RULE_ID_FILE_PATH = "file_path";
|
|
5
|
+
export declare const RULE_ID_EMAIL = "email";
|
|
6
|
+
export declare const RULE_ID_IMAGE = "image_base64";
|
|
7
|
+
/** 1 entry あたりの MaskStat 上限 (detections の MAX_DETECTIONS_PER_ENTRY と同思想)。 */
|
|
8
|
+
export declare const MAX_MASK_STATS_PER_ENTRY = 50;
|
|
9
|
+
/** ルールごとのマスク実績 (生値は持たない。件数のみ)。 */
|
|
10
|
+
export interface MaskStat {
|
|
11
|
+
ruleId: string;
|
|
12
|
+
count: number;
|
|
13
|
+
}
|
|
14
|
+
export interface CustomMaskRule {
|
|
15
|
+
/** 英数字・ハイフン・アンダースコアのみ (Firestore field path 安全性のため)。 */
|
|
16
|
+
ruleId: string;
|
|
17
|
+
/** 正規表現文字列 (global flag は自動付与)。 */
|
|
18
|
+
pattern: string;
|
|
19
|
+
/** マスク後の文字列 (literal 置換。$1 等のグループ参照は使えない)。 */
|
|
20
|
+
replacement: string;
|
|
21
|
+
enabled: boolean;
|
|
22
|
+
}
|
|
23
|
+
export interface MaskRulesConfig {
|
|
24
|
+
builtin: {
|
|
25
|
+
maskApiKeys: boolean;
|
|
26
|
+
maskFilePaths: boolean;
|
|
27
|
+
maskEmails: boolean;
|
|
28
|
+
};
|
|
29
|
+
customRules: CustomMaskRule[];
|
|
30
|
+
updatedAt?: number;
|
|
31
|
+
}
|
|
32
|
+
/** 適用時の実効設定。ローカル設定と組織ルール (remote) をマージした結果。 */
|
|
33
|
+
export interface EffectiveMaskConfig {
|
|
34
|
+
maskApiKeys: boolean;
|
|
35
|
+
maskFilePaths: boolean;
|
|
36
|
+
maskEmails: boolean;
|
|
37
|
+
customRules: CustomMaskRule[];
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* ローカル設定 (agent.config.json の pii) と組織ルール (cloud 配信) をマージする。
|
|
41
|
+
* - builtin トグルは組織ルールがあればそちらを正とする (組織統制を優先)。
|
|
42
|
+
* - カスタムルールは両方の和集合 (多くマスクする方向は常に安全側)。
|
|
43
|
+
* ローカル customPatterns は ruleId を持たないため custom_local_N を自動付与する。
|
|
44
|
+
*/
|
|
45
|
+
export declare function resolveMaskConfig(local: AgentConfig['pii'], remote?: MaskRulesConfig | null): EffectiveMaskConfig;
|
|
3
46
|
export interface PiiMaskerOptions {
|
|
4
47
|
homeDir?: string;
|
|
48
|
+
/** 組織のマスクルール (cloud 配信)。null/未指定ならローカル設定のみで動作する。 */
|
|
49
|
+
remoteRules?: MaskRulesConfig | null;
|
|
5
50
|
}
|
|
6
51
|
export declare class PiiMasker {
|
|
7
|
-
private readonly
|
|
52
|
+
private readonly effective;
|
|
8
53
|
private readonly homeDir;
|
|
9
54
|
private readonly customPatterns;
|
|
10
55
|
constructor(config: AgentConfig['pii'], opts?: PiiMaskerOptions);
|
|
@@ -13,6 +58,8 @@ export declare class PiiMasker {
|
|
|
13
58
|
/** 任意の値を再帰的に処理。string は pattern 置換、object は structural な特別処理あり */
|
|
14
59
|
private maskValue;
|
|
15
60
|
private maskString;
|
|
61
|
+
/** ファイルパス内のユーザー名を匿名化 */
|
|
62
|
+
private maskFilePathsInString;
|
|
16
63
|
private isBase64ImageBlock;
|
|
17
64
|
private summarizeImage;
|
|
18
65
|
}
|
package/dist/pii-masker.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pii-masker.d.ts","sourceRoot":"","sources":["../src/pii-masker.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA;AAC3C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"pii-masker.d.ts","sourceRoot":"","sources":["../src/pii-masker.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA;AAC3C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAmE1C,8CAA8C;AAC9C,eAAO,MAAM,iBAAiB,cAAc,CAAA;AAC5C,eAAO,MAAM,aAAa,UAAU,CAAA;AACpC,eAAO,MAAM,aAAa,iBAAiB,CAAA;AAE3C,6EAA6E;AAC7E,eAAO,MAAM,wBAAwB,KAAK,CAAA;AAE1C,kCAAkC;AAClC,MAAM,WAAW,QAAQ;IACvB,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,MAAM,CAAA;CACd;AAQD,MAAM,WAAW,cAAc;IAC7B,wDAAwD;IACxD,MAAM,EAAE,MAAM,CAAA;IACd,mCAAmC;IACnC,OAAO,EAAE,MAAM,CAAA;IACf,8CAA8C;IAC9C,WAAW,EAAE,MAAM,CAAA;IACnB,OAAO,EAAE,OAAO,CAAA;CACjB;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE;QACP,WAAW,EAAE,OAAO,CAAA;QACpB,aAAa,EAAE,OAAO,CAAA;QACtB,UAAU,EAAE,OAAO,CAAA;KACpB,CAAA;IACD,WAAW,EAAE,cAAc,EAAE,CAAA;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,+CAA+C;AAC/C,MAAM,WAAW,mBAAmB;IAClC,WAAW,EAAE,OAAO,CAAA;IACpB,aAAa,EAAE,OAAO,CAAA;IACtB,UAAU,EAAE,OAAO,CAAA;IACnB,WAAW,EAAE,cAAc,EAAE,CAAA;CAC9B;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,WAAW,CAAC,KAAK,CAAC,EACzB,MAAM,CAAC,EAAE,eAAe,GAAG,IAAI,GAC9B,mBAAmB,CAqBrB;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,oDAAoD;IACpD,WAAW,CAAC,EAAE,eAAe,GAAG,IAAI,CAAA;CACrC;AAED,qBAAa,SAAS;IACpB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAqB;IAC/C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAQ;IAChC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAA+D;gBAElF,MAAM,EAAE,WAAW,CAAC,KAAK,CAAC,EAAE,IAAI,GAAE,gBAAqB;IAenE,IAAI,CAAC,KAAK,EAAE,WAAW,GAAG,WAAW;IAYrC,OAAO,CAAC,OAAO,EAAE,WAAW,EAAE,GAAG,WAAW,EAAE;IAI9C,kEAAkE;IAClE,OAAO,CAAC,SAAS;IA0BjB,OAAO,CAAC,UAAU;IAmBlB,wBAAwB;IACxB,OAAO,CAAC,qBAAqB;IAc7B,OAAO,CAAC,kBAAkB;IAQ1B,OAAO,CAAC,cAAc;CAevB"}
|
package/dist/pii-masker.js
CHANGED
|
@@ -3,110 +3,198 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.PiiMasker = void 0;
|
|
6
|
+
exports.PiiMasker = exports.MAX_MASK_STATS_PER_ENTRY = exports.RULE_ID_IMAGE = exports.RULE_ID_EMAIL = exports.RULE_ID_FILE_PATH = void 0;
|
|
7
|
+
exports.resolveMaskConfig = resolveMaskConfig;
|
|
7
8
|
const crypto_1 = require("crypto");
|
|
8
9
|
const os_1 = __importDefault(require("os"));
|
|
10
|
+
// =============================================
|
|
11
|
+
// PII マスキング (送信前に伏せる) — Issue #43 でルール駆動化
|
|
12
|
+
// =============================================
|
|
13
|
+
//
|
|
14
|
+
// secret-detector.ts (検出・記録) と同じ前処理パイプラインの別レイヤ。
|
|
15
|
+
// Issue #43 で「何がどうマスクされるか」を顧客が定義・確認・監査できるよう、
|
|
16
|
+
// 1. 既定ルールの ON/OFF とカスタムルール (正規表現 + マスク文字列) を設定可能に
|
|
17
|
+
// 2. ルールごとのマスク件数 (MaskStat) を entry に付与 → cloud が日次集計
|
|
18
|
+
// 3. 組織ルール (cloud 配信) とローカル設定をマージして適用
|
|
19
|
+
// した。マスク文字列のみが残り、元の値は entry に保持されない。
|
|
9
20
|
/**
|
|
10
21
|
* Built-in PII patterns. Phase B 観測 (`agent/docs/claude-log-structure.md` 第 7 節)
|
|
11
22
|
* で実際に conversation に出現することが確認されたものを優先実装。
|
|
12
23
|
*
|
|
13
24
|
* 注: 検出粒度は false negative より false positive を許容する方針
|
|
14
25
|
* (key 漏洩リスク > 文字列を過剰にマスクするリスク)。
|
|
26
|
+
* ruleId は secret-detector.ts の同種ルールと揃える (監査表示で対応が取れるように)。
|
|
15
27
|
*/
|
|
16
28
|
const SECRET_PATTERNS = [
|
|
17
29
|
// Anthropic API key (sk-ant-api... / sk-ant-oat... / sk-ant-ort...)
|
|
18
|
-
|
|
30
|
+
{
|
|
31
|
+
ruleId: 'anthropic_key',
|
|
32
|
+
regex: /sk-ant-(api|oat|ort)\d+-[A-Za-z0-9_-]{40,}/g,
|
|
33
|
+
replacement: '[MASKED_ANTHROPIC_KEY]',
|
|
34
|
+
},
|
|
19
35
|
// OpenAI key (sk-proj-... or legacy sk-...) — 40+ 文字に絞って誤検出抑制
|
|
20
|
-
|
|
36
|
+
{
|
|
37
|
+
ruleId: 'openai_key',
|
|
38
|
+
regex: /sk-(proj-)?[A-Za-z0-9]{40,}/g,
|
|
39
|
+
replacement: '[MASKED_OPENAI_KEY]',
|
|
40
|
+
},
|
|
21
41
|
// GitHub token (ghp_, gho_, ghu_, ghs_, ghr_)
|
|
22
|
-
|
|
42
|
+
{
|
|
43
|
+
ruleId: 'github_token',
|
|
44
|
+
regex: /gh[pousr]_[A-Za-z0-9]{36}/g,
|
|
45
|
+
replacement: '[MASKED_GITHUB_TOKEN]',
|
|
46
|
+
},
|
|
23
47
|
// Slack token (xoxb-, xoxp-, xoxa-, xoxr-, xoxs-)
|
|
24
|
-
|
|
48
|
+
{
|
|
49
|
+
ruleId: 'slack_token',
|
|
50
|
+
regex: /xox[baprs]-[A-Za-z0-9-]{10,}/g,
|
|
51
|
+
replacement: '[MASKED_SLACK_TOKEN]',
|
|
52
|
+
},
|
|
25
53
|
// AWS access key
|
|
26
|
-
|
|
54
|
+
{ ruleId: 'aws_access_key', regex: /\bAKIA[0-9A-Z]{16}\b/g, replacement: '[MASKED_AWS_KEY]' },
|
|
27
55
|
// GCP API key
|
|
28
|
-
|
|
56
|
+
{
|
|
57
|
+
ruleId: 'gcp_api_key',
|
|
58
|
+
regex: /\bAIza[0-9A-Za-z_-]{35}\b/g,
|
|
59
|
+
replacement: '[MASKED_GCP_KEY]',
|
|
60
|
+
},
|
|
29
61
|
// Generic Bearer token (短すぎる文字列は誤検出するので 20+ 文字に絞る)
|
|
30
|
-
|
|
62
|
+
{
|
|
63
|
+
ruleId: 'bearer_token',
|
|
64
|
+
regex: /Bearer\s+[A-Za-z0-9._-]{20,}/g,
|
|
65
|
+
replacement: 'Bearer [MASKED_TOKEN]',
|
|
66
|
+
},
|
|
31
67
|
];
|
|
32
68
|
// local-part を 2 文字以上にして Flask デコレータ等 (例: `t@app.context_processor`,
|
|
33
69
|
// `n@app.after_request`) の false positive をブロック。1 文字 local-part の実 email は
|
|
34
70
|
// RFC 上 valid だが実運用ではほぼ存在しない (acceptable trade-off)。
|
|
35
71
|
const EMAIL_PATTERN = /[a-zA-Z0-9._%+-]{2,}@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/g;
|
|
36
|
-
/**
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
72
|
+
/** ファイルパス / 画像など、正規表現グループ外の構造的ルールの ruleId。 */
|
|
73
|
+
exports.RULE_ID_FILE_PATH = 'file_path';
|
|
74
|
+
exports.RULE_ID_EMAIL = 'email';
|
|
75
|
+
exports.RULE_ID_IMAGE = 'image_base64';
|
|
76
|
+
/** 1 entry あたりの MaskStat 上限 (detections の MAX_DETECTIONS_PER_ENTRY と同思想)。 */
|
|
77
|
+
exports.MAX_MASK_STATS_PER_ENTRY = 50;
|
|
78
|
+
/**
|
|
79
|
+
* ローカル設定 (agent.config.json の pii) と組織ルール (cloud 配信) をマージする。
|
|
80
|
+
* - builtin トグルは組織ルールがあればそちらを正とする (組織統制を優先)。
|
|
81
|
+
* - カスタムルールは両方の和集合 (多くマスクする方向は常に安全側)。
|
|
82
|
+
* ローカル customPatterns は ruleId を持たないため custom_local_N を自動付与する。
|
|
83
|
+
*/
|
|
84
|
+
function resolveMaskConfig(local, remote) {
|
|
85
|
+
const localCustom = (local.customPatterns ?? []).map((p, i) => ({
|
|
86
|
+
ruleId: `custom_local_${i + 1}`,
|
|
87
|
+
pattern: p.pattern,
|
|
88
|
+
replacement: p.replacement,
|
|
89
|
+
enabled: true,
|
|
90
|
+
}));
|
|
91
|
+
if (!remote) {
|
|
92
|
+
return {
|
|
93
|
+
maskApiKeys: local.maskApiKeys,
|
|
94
|
+
maskFilePaths: local.maskFilePaths,
|
|
95
|
+
maskEmails: local.maskEmails,
|
|
96
|
+
customRules: localCustom,
|
|
97
|
+
};
|
|
42
98
|
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
99
|
+
return {
|
|
100
|
+
maskApiKeys: remote.builtin.maskApiKeys,
|
|
101
|
+
maskFilePaths: remote.builtin.maskFilePaths,
|
|
102
|
+
maskEmails: remote.builtin.maskEmails,
|
|
103
|
+
customRules: [...remote.customRules.filter((r) => r.enabled), ...localCustom],
|
|
104
|
+
};
|
|
47
105
|
}
|
|
48
106
|
class PiiMasker {
|
|
49
|
-
|
|
107
|
+
effective;
|
|
50
108
|
homeDir;
|
|
51
109
|
customPatterns;
|
|
52
110
|
constructor(config, opts = {}) {
|
|
53
|
-
this.
|
|
111
|
+
this.effective = resolveMaskConfig(config, opts.remoteRules);
|
|
54
112
|
this.homeDir = opts.homeDir ?? os_1.default.homedir();
|
|
55
|
-
this.customPatterns =
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
113
|
+
this.customPatterns = this.effective.customRules
|
|
114
|
+
.map((rule) => {
|
|
115
|
+
try {
|
|
116
|
+
return { ruleId: rule.ruleId, regex: new RegExp(rule.pattern, 'g'), replacement: rule.replacement };
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
// 不正な正規表現は無視 (1 ルールのせいでマスキング全体を落とさない)。
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
})
|
|
123
|
+
.filter((r) => r !== null);
|
|
60
124
|
}
|
|
61
125
|
mask(entry) {
|
|
62
|
-
|
|
126
|
+
const counts = new Map();
|
|
127
|
+
const raw = this.maskValue(entry.raw, counts);
|
|
128
|
+
if (counts.size === 0)
|
|
129
|
+
return { ...entry, raw };
|
|
130
|
+
// 件数降順で上限へ切り詰める (cloud 側 schema の上限と整合)。
|
|
131
|
+
const masks = [...counts.entries()]
|
|
132
|
+
.map(([ruleId, count]) => ({ ruleId, count }))
|
|
133
|
+
.sort((a, b) => b.count - a.count)
|
|
134
|
+
.slice(0, exports.MAX_MASK_STATS_PER_ENTRY);
|
|
135
|
+
return { ...entry, raw, masks };
|
|
63
136
|
}
|
|
64
137
|
maskAll(entries) {
|
|
65
138
|
return entries.map((e) => this.mask(e));
|
|
66
139
|
}
|
|
67
140
|
/** 任意の値を再帰的に処理。string は pattern 置換、object は structural な特別処理あり */
|
|
68
|
-
maskValue(v) {
|
|
141
|
+
maskValue(v, counts) {
|
|
69
142
|
if (typeof v === 'string') {
|
|
70
|
-
return this.maskString(v);
|
|
143
|
+
return this.maskString(v, counts);
|
|
71
144
|
}
|
|
72
145
|
if (Array.isArray(v)) {
|
|
73
|
-
return v.map((x) => this.maskValue(x));
|
|
146
|
+
return v.map((x) => this.maskValue(x, counts));
|
|
74
147
|
}
|
|
75
148
|
if (v !== null && typeof v === 'object') {
|
|
76
149
|
const obj = v;
|
|
77
150
|
// 画像 base64 は構造的に検出して省略 (帯域節約 + 二次的 PII 流出防止)
|
|
78
151
|
if (this.isBase64ImageBlock(obj)) {
|
|
152
|
+
bump(counts, exports.RULE_ID_IMAGE, 1);
|
|
79
153
|
return this.summarizeImage(obj);
|
|
80
154
|
}
|
|
81
155
|
const result = {};
|
|
82
156
|
for (const [k, val] of Object.entries(obj)) {
|
|
83
157
|
// key 自体に絶対パス等が入るケース (例: file-history-snapshot の
|
|
84
158
|
// trackedFileBackups は file path を key にする) があるので key も maskString
|
|
85
|
-
const newKey = this.maskString(k);
|
|
86
|
-
result[newKey] = this.maskValue(val);
|
|
159
|
+
const newKey = this.maskString(k, counts);
|
|
160
|
+
result[newKey] = this.maskValue(val, counts);
|
|
87
161
|
}
|
|
88
162
|
return result;
|
|
89
163
|
}
|
|
90
164
|
return v;
|
|
91
165
|
}
|
|
92
|
-
maskString(str) {
|
|
166
|
+
maskString(str, counts) {
|
|
93
167
|
let result = str;
|
|
94
|
-
if (this.
|
|
95
|
-
for (const
|
|
96
|
-
result = result
|
|
168
|
+
if (this.effective.maskApiKeys) {
|
|
169
|
+
for (const { ruleId, regex, replacement } of SECRET_PATTERNS) {
|
|
170
|
+
result = replaceCounted(result, regex, replacement, counts, ruleId);
|
|
97
171
|
}
|
|
98
172
|
}
|
|
99
|
-
if (this.
|
|
100
|
-
result = maskFilePathsInString(result,
|
|
173
|
+
if (this.effective.maskFilePaths) {
|
|
174
|
+
result = this.maskFilePathsInString(result, counts);
|
|
101
175
|
}
|
|
102
|
-
if (this.
|
|
103
|
-
result = result
|
|
176
|
+
if (this.effective.maskEmails) {
|
|
177
|
+
result = replaceCounted(result, EMAIL_PATTERN, '[MASKED_EMAIL]', counts, exports.RULE_ID_EMAIL);
|
|
104
178
|
}
|
|
105
|
-
for (const
|
|
106
|
-
result = result
|
|
179
|
+
for (const { ruleId, regex, replacement } of this.customPatterns) {
|
|
180
|
+
result = replaceCounted(result, regex, replacement, counts, ruleId);
|
|
107
181
|
}
|
|
108
182
|
return result;
|
|
109
183
|
}
|
|
184
|
+
/** ファイルパス内のユーザー名を匿名化 */
|
|
185
|
+
maskFilePathsInString(str, counts) {
|
|
186
|
+
let result = str;
|
|
187
|
+
// 自分のホーム → ~
|
|
188
|
+
if (this.homeDir && result.includes(this.homeDir)) {
|
|
189
|
+
const parts = result.split(this.homeDir);
|
|
190
|
+
bump(counts, exports.RULE_ID_FILE_PATH, parts.length - 1);
|
|
191
|
+
result = parts.join('~');
|
|
192
|
+
}
|
|
193
|
+
// 他ユーザー (チーム共有時に他のユーザー名が漏れないように)
|
|
194
|
+
result = replaceCounted(result, /\/Users\/[^/\s"'`]+/g, '/Users/[USER]', counts, exports.RULE_ID_FILE_PATH);
|
|
195
|
+
result = replaceCounted(result, /\/home\/[^/\s"'`]+/g, '/home/[USER]', counts, exports.RULE_ID_FILE_PATH);
|
|
196
|
+
return result;
|
|
197
|
+
}
|
|
110
198
|
isBase64ImageBlock(obj) {
|
|
111
199
|
if (obj.type !== 'image')
|
|
112
200
|
return false;
|
|
@@ -133,4 +221,19 @@ class PiiMasker {
|
|
|
133
221
|
}
|
|
134
222
|
}
|
|
135
223
|
exports.PiiMasker = PiiMasker;
|
|
224
|
+
function bump(counts, ruleId, n) {
|
|
225
|
+
if (n <= 0)
|
|
226
|
+
return;
|
|
227
|
+
counts.set(ruleId, (counts.get(ruleId) ?? 0) + n);
|
|
228
|
+
}
|
|
229
|
+
/** literal 置換 + 置換回数のカウント。replacement 内の $& 等は解釈しない。 */
|
|
230
|
+
function replaceCounted(str, regex, replacement, counts, ruleId) {
|
|
231
|
+
let n = 0;
|
|
232
|
+
const result = str.replace(regex, () => {
|
|
233
|
+
n++;
|
|
234
|
+
return replacement;
|
|
235
|
+
});
|
|
236
|
+
bump(counts, ruleId, n);
|
|
237
|
+
return result;
|
|
238
|
+
}
|
|
136
239
|
//# sourceMappingURL=pii-masker.js.map
|
package/dist/pii-masker.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pii-masker.js","sourceRoot":"","sources":["../src/pii-masker.ts"],"names":[],"mappings":";;;;;;
|
|
1
|
+
{"version":3,"file":"pii-masker.js","sourceRoot":"","sources":["../src/pii-masker.ts"],"names":[],"mappings":"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"}
|