@nahisaho/katashiro-security 1.3.0 → 2.0.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/LICENSE +21 -0
- package/dist/action-logger.d.ts +114 -0
- package/dist/action-logger.d.ts.map +1 -0
- package/dist/action-logger.js +358 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +24 -0
- package/dist/security-analyzer.d.ts +71 -0
- package/dist/security-analyzer.d.ts.map +1 -0
- package/dist/security-analyzer.js +256 -0
- package/dist/types.d.ts +208 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +130 -0
- package/package.json +11 -12
- package/tsconfig.tsbuildinfo +1 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 nahisaho
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ActionLogger - 監査ログ記録クラス
|
|
3
|
+
*
|
|
4
|
+
* @requirement REQ-012-05
|
|
5
|
+
* @design すべてのアクションをタイムスタンプ付きで記録
|
|
6
|
+
*/
|
|
7
|
+
import { Action, SecurityAnalysis, Observation, AuditLogEntry, AuditLogFilter, UserConfirmation, RiskLevel } from './types';
|
|
8
|
+
/**
|
|
9
|
+
* ログストレージインターフェース
|
|
10
|
+
*/
|
|
11
|
+
export interface LogStorage {
|
|
12
|
+
/** ログエントリを追加 */
|
|
13
|
+
append(entry: AuditLogEntry): Promise<void>;
|
|
14
|
+
/** ログを検索 */
|
|
15
|
+
query(filter: AuditLogFilter): Promise<AuditLogEntry[]>;
|
|
16
|
+
/** ログをクリア */
|
|
17
|
+
clear(): Promise<void>;
|
|
18
|
+
/** ログ件数を取得 */
|
|
19
|
+
count(): Promise<number>;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* インメモリログストレージ
|
|
23
|
+
*/
|
|
24
|
+
export declare class InMemoryLogStorage implements LogStorage {
|
|
25
|
+
private logs;
|
|
26
|
+
private maxEntries;
|
|
27
|
+
constructor(maxEntries?: number);
|
|
28
|
+
append(entry: AuditLogEntry): Promise<void>;
|
|
29
|
+
query(filter: AuditLogFilter): Promise<AuditLogEntry[]>;
|
|
30
|
+
clear(): Promise<void>;
|
|
31
|
+
count(): Promise<number>;
|
|
32
|
+
/**
|
|
33
|
+
* 全ログを取得(テスト用)
|
|
34
|
+
*/
|
|
35
|
+
getAllLogs(): AuditLogEntry[];
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* ActionLoggerオプション
|
|
39
|
+
*/
|
|
40
|
+
export interface ActionLoggerOptions {
|
|
41
|
+
/** ログストレージ */
|
|
42
|
+
storage?: LogStorage;
|
|
43
|
+
/** 最小記録リスクレベル */
|
|
44
|
+
minLogLevel?: RiskLevel;
|
|
45
|
+
/** ID生成関数 */
|
|
46
|
+
generateId?: () => string;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* アクションロガー
|
|
50
|
+
*/
|
|
51
|
+
export declare class ActionLogger {
|
|
52
|
+
private readonly storage;
|
|
53
|
+
private readonly minLogLevel;
|
|
54
|
+
private readonly generateId;
|
|
55
|
+
constructor(options?: ActionLoggerOptions);
|
|
56
|
+
/**
|
|
57
|
+
* アクションと分析結果を記録(REQ-012-05)
|
|
58
|
+
*/
|
|
59
|
+
logAction(action: Action, analysis: SecurityAnalysis, observation?: Observation, userConfirmation?: UserConfirmation): Promise<string>;
|
|
60
|
+
/**
|
|
61
|
+
* アクション開始を記録
|
|
62
|
+
*/
|
|
63
|
+
logActionStart(action: Action, analysis: SecurityAnalysis): Promise<string>;
|
|
64
|
+
/**
|
|
65
|
+
* アクション完了を記録(既存エントリを更新)
|
|
66
|
+
*/
|
|
67
|
+
logActionComplete(logId: string, observation: Observation, userConfirmation?: UserConfirmation): Promise<void>;
|
|
68
|
+
/**
|
|
69
|
+
* ログを検索
|
|
70
|
+
*/
|
|
71
|
+
queryLogs(filter: AuditLogFilter): Promise<AuditLogEntry[]>;
|
|
72
|
+
/**
|
|
73
|
+
* 最近のログを取得
|
|
74
|
+
*/
|
|
75
|
+
getRecentLogs(count?: number): Promise<AuditLogEntry[]>;
|
|
76
|
+
/**
|
|
77
|
+
* 高リスクログを取得
|
|
78
|
+
*/
|
|
79
|
+
getHighRiskLogs(count?: number): Promise<AuditLogEntry[]>;
|
|
80
|
+
/**
|
|
81
|
+
* ユーザーのログを取得
|
|
82
|
+
*/
|
|
83
|
+
getUserLogs(userId: string, count?: number): Promise<AuditLogEntry[]>;
|
|
84
|
+
/**
|
|
85
|
+
* ログをクリア
|
|
86
|
+
*/
|
|
87
|
+
clearLogs(): Promise<void>;
|
|
88
|
+
/**
|
|
89
|
+
* ログ件数を取得
|
|
90
|
+
*/
|
|
91
|
+
getLogCount(): Promise<number>;
|
|
92
|
+
/**
|
|
93
|
+
* サマリーを生成
|
|
94
|
+
*/
|
|
95
|
+
generateSummary(filter?: AuditLogFilter): Promise<AuditLogSummary>;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* 監査ログサマリー
|
|
99
|
+
*/
|
|
100
|
+
export interface AuditLogSummary {
|
|
101
|
+
/** 総アクション数 */
|
|
102
|
+
totalActions: number;
|
|
103
|
+
/** リスクレベル別件数 */
|
|
104
|
+
byRiskLevel: Record<RiskLevel, number>;
|
|
105
|
+
/** アクションタイプ別件数 */
|
|
106
|
+
byActionType: Record<string, number>;
|
|
107
|
+
/** 成功率 */
|
|
108
|
+
successRate: number;
|
|
109
|
+
/** ブロック数 */
|
|
110
|
+
blockedCount: number;
|
|
111
|
+
/** 確認数 */
|
|
112
|
+
confirmedCount: number;
|
|
113
|
+
}
|
|
114
|
+
//# sourceMappingURL=action-logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"action-logger.d.ts","sourceRoot":"","sources":["../src/action-logger.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* ActionLogger - 監査ログ記録クラス
|
|
4
|
+
*
|
|
5
|
+
* @requirement REQ-012-05
|
|
6
|
+
* @design すべてのアクションをタイムスタンプ付きで記録
|
|
7
|
+
*/
|
|
8
|
+
var __assign = (this && this.__assign) || function () {
|
|
9
|
+
__assign = Object.assign || function(t) {
|
|
10
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
11
|
+
s = arguments[i];
|
|
12
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
13
|
+
t[p] = s[p];
|
|
14
|
+
}
|
|
15
|
+
return t;
|
|
16
|
+
};
|
|
17
|
+
return __assign.apply(this, arguments);
|
|
18
|
+
};
|
|
19
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
20
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
21
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
22
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
23
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
24
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
25
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
26
|
+
});
|
|
27
|
+
};
|
|
28
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
29
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
|
|
30
|
+
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
31
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
32
|
+
function step(op) {
|
|
33
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
34
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
35
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
36
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
37
|
+
switch (op[0]) {
|
|
38
|
+
case 0: case 1: t = op; break;
|
|
39
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
40
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
41
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
42
|
+
default:
|
|
43
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
44
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
45
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
46
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
47
|
+
if (t[2]) _.ops.pop();
|
|
48
|
+
_.trys.pop(); continue;
|
|
49
|
+
}
|
|
50
|
+
op = body.call(thisArg, _);
|
|
51
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
52
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
56
|
+
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
57
|
+
if (ar || !(i in from)) {
|
|
58
|
+
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
|
59
|
+
ar[i] = from[i];
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return to.concat(ar || Array.prototype.slice.call(from));
|
|
63
|
+
};
|
|
64
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
65
|
+
exports.ActionLogger = exports.InMemoryLogStorage = void 0;
|
|
66
|
+
var types_1 = require("./types");
|
|
67
|
+
/**
|
|
68
|
+
* インメモリログストレージ
|
|
69
|
+
*/
|
|
70
|
+
var InMemoryLogStorage = /** @class */ (function () {
|
|
71
|
+
function InMemoryLogStorage(maxEntries) {
|
|
72
|
+
if (maxEntries === void 0) { maxEntries = 10000; }
|
|
73
|
+
this.logs = [];
|
|
74
|
+
this.maxEntries = maxEntries;
|
|
75
|
+
}
|
|
76
|
+
InMemoryLogStorage.prototype.append = function (entry) {
|
|
77
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
78
|
+
return __generator(this, function (_a) {
|
|
79
|
+
this.logs.push(entry);
|
|
80
|
+
// 最大件数を超えたら古いログを削除
|
|
81
|
+
if (this.logs.length > this.maxEntries) {
|
|
82
|
+
this.logs = this.logs.slice(-this.maxEntries);
|
|
83
|
+
}
|
|
84
|
+
return [2 /*return*/];
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
};
|
|
88
|
+
InMemoryLogStorage.prototype.query = function (filter) {
|
|
89
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
90
|
+
var results, minOrder_1, keyword_1, offset, limit;
|
|
91
|
+
var _a, _b;
|
|
92
|
+
return __generator(this, function (_c) {
|
|
93
|
+
results = __spreadArray([], this.logs, true);
|
|
94
|
+
// 時間範囲フィルター
|
|
95
|
+
if (filter.startTime) {
|
|
96
|
+
results = results.filter(function (e) { return e.timestamp >= filter.startTime; });
|
|
97
|
+
}
|
|
98
|
+
if (filter.endTime) {
|
|
99
|
+
results = results.filter(function (e) { return e.timestamp <= filter.endTime; });
|
|
100
|
+
}
|
|
101
|
+
// アクションタイプフィルター
|
|
102
|
+
if (filter.actionTypes && filter.actionTypes.length > 0) {
|
|
103
|
+
results = results.filter(function (e) { return filter.actionTypes.includes(e.action.type); });
|
|
104
|
+
}
|
|
105
|
+
// リスクレベルフィルター
|
|
106
|
+
if (filter.minRiskLevel) {
|
|
107
|
+
minOrder_1 = types_1.RISK_LEVEL_ORDER[filter.minRiskLevel];
|
|
108
|
+
results = results.filter(function (e) { return types_1.RISK_LEVEL_ORDER[e.analysis.riskLevel] >= minOrder_1; });
|
|
109
|
+
}
|
|
110
|
+
// 成功/失敗フィルター
|
|
111
|
+
if (filter.success !== undefined) {
|
|
112
|
+
results = results.filter(function (e) { var _a; return ((_a = e.observation) === null || _a === void 0 ? void 0 : _a.success) === filter.success; });
|
|
113
|
+
}
|
|
114
|
+
// ユーザーIDフィルター
|
|
115
|
+
if (filter.userId) {
|
|
116
|
+
results = results.filter(function (e) { var _a; return ((_a = e.action.context) === null || _a === void 0 ? void 0 : _a.userId) === filter.userId; });
|
|
117
|
+
}
|
|
118
|
+
// キーワード検索
|
|
119
|
+
if (filter.keyword) {
|
|
120
|
+
keyword_1 = filter.keyword.toLowerCase();
|
|
121
|
+
results = results.filter(function (e) {
|
|
122
|
+
var _a;
|
|
123
|
+
var searchText = __spreadArray(__spreadArray([
|
|
124
|
+
e.action.name,
|
|
125
|
+
e.action.target
|
|
126
|
+
], e.analysis.reasons, true), [
|
|
127
|
+
(_a = e.observation) === null || _a === void 0 ? void 0 : _a.error,
|
|
128
|
+
], false).filter(Boolean)
|
|
129
|
+
.join(' ')
|
|
130
|
+
.toLowerCase();
|
|
131
|
+
return searchText.includes(keyword_1);
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
// ソート(新しい順)
|
|
135
|
+
results.sort(function (a, b) { return b.timestamp.localeCompare(a.timestamp); });
|
|
136
|
+
offset = (_a = filter.offset) !== null && _a !== void 0 ? _a : 0;
|
|
137
|
+
limit = (_b = filter.limit) !== null && _b !== void 0 ? _b : 100;
|
|
138
|
+
return [2 /*return*/, results.slice(offset, offset + limit)];
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
};
|
|
142
|
+
InMemoryLogStorage.prototype.clear = function () {
|
|
143
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
144
|
+
return __generator(this, function (_a) {
|
|
145
|
+
this.logs = [];
|
|
146
|
+
return [2 /*return*/];
|
|
147
|
+
});
|
|
148
|
+
});
|
|
149
|
+
};
|
|
150
|
+
InMemoryLogStorage.prototype.count = function () {
|
|
151
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
152
|
+
return __generator(this, function (_a) {
|
|
153
|
+
return [2 /*return*/, this.logs.length];
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
};
|
|
157
|
+
/**
|
|
158
|
+
* 全ログを取得(テスト用)
|
|
159
|
+
*/
|
|
160
|
+
InMemoryLogStorage.prototype.getAllLogs = function () {
|
|
161
|
+
return __spreadArray([], this.logs, true);
|
|
162
|
+
};
|
|
163
|
+
return InMemoryLogStorage;
|
|
164
|
+
}());
|
|
165
|
+
exports.InMemoryLogStorage = InMemoryLogStorage;
|
|
166
|
+
/**
|
|
167
|
+
* アクションロガー
|
|
168
|
+
*/
|
|
169
|
+
var ActionLogger = /** @class */ (function () {
|
|
170
|
+
function ActionLogger(options) {
|
|
171
|
+
if (options === void 0) { options = {}; }
|
|
172
|
+
var _a, _b, _c;
|
|
173
|
+
this.storage = (_a = options.storage) !== null && _a !== void 0 ? _a : new InMemoryLogStorage();
|
|
174
|
+
this.minLogLevel = (_b = options.minLogLevel) !== null && _b !== void 0 ? _b : 'low';
|
|
175
|
+
this.generateId =
|
|
176
|
+
(_c = options.generateId) !== null && _c !== void 0 ? _c : (function () { return "log-".concat(Date.now(), "-").concat(Math.random().toString(36).slice(2, 8)); });
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* アクションと分析結果を記録(REQ-012-05)
|
|
180
|
+
*/
|
|
181
|
+
ActionLogger.prototype.logAction = function (action, analysis, observation, userConfirmation) {
|
|
182
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
183
|
+
var entry;
|
|
184
|
+
return __generator(this, function (_a) {
|
|
185
|
+
switch (_a.label) {
|
|
186
|
+
case 0:
|
|
187
|
+
// 最小リスクレベル未満はスキップ
|
|
188
|
+
if (types_1.RISK_LEVEL_ORDER[analysis.riskLevel] < types_1.RISK_LEVEL_ORDER[this.minLogLevel]) {
|
|
189
|
+
return [2 /*return*/, ''];
|
|
190
|
+
}
|
|
191
|
+
entry = {
|
|
192
|
+
id: this.generateId(),
|
|
193
|
+
timestamp: new Date().toISOString(),
|
|
194
|
+
action: action,
|
|
195
|
+
analysis: analysis,
|
|
196
|
+
observation: observation,
|
|
197
|
+
userConfirmation: userConfirmation,
|
|
198
|
+
};
|
|
199
|
+
return [4 /*yield*/, this.storage.append(entry)];
|
|
200
|
+
case 1:
|
|
201
|
+
_a.sent();
|
|
202
|
+
return [2 /*return*/, entry.id];
|
|
203
|
+
}
|
|
204
|
+
});
|
|
205
|
+
});
|
|
206
|
+
};
|
|
207
|
+
/**
|
|
208
|
+
* アクション開始を記録
|
|
209
|
+
*/
|
|
210
|
+
ActionLogger.prototype.logActionStart = function (action, analysis) {
|
|
211
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
212
|
+
return __generator(this, function (_a) {
|
|
213
|
+
return [2 /*return*/, this.logAction(action, analysis)];
|
|
214
|
+
});
|
|
215
|
+
});
|
|
216
|
+
};
|
|
217
|
+
/**
|
|
218
|
+
* アクション完了を記録(既存エントリを更新)
|
|
219
|
+
*/
|
|
220
|
+
ActionLogger.prototype.logActionComplete = function (logId, observation, userConfirmation) {
|
|
221
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
222
|
+
var logs, entry;
|
|
223
|
+
return __generator(this, function (_a) {
|
|
224
|
+
switch (_a.label) {
|
|
225
|
+
case 0: return [4 /*yield*/, this.storage.query({ limit: 1000 })];
|
|
226
|
+
case 1:
|
|
227
|
+
logs = _a.sent();
|
|
228
|
+
entry = logs.find(function (e) { return e.id === logId; });
|
|
229
|
+
if (entry) {
|
|
230
|
+
entry.observation = observation;
|
|
231
|
+
if (userConfirmation) {
|
|
232
|
+
entry.userConfirmation = userConfirmation;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
return [2 /*return*/];
|
|
236
|
+
}
|
|
237
|
+
});
|
|
238
|
+
});
|
|
239
|
+
};
|
|
240
|
+
/**
|
|
241
|
+
* ログを検索
|
|
242
|
+
*/
|
|
243
|
+
ActionLogger.prototype.queryLogs = function (filter) {
|
|
244
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
245
|
+
return __generator(this, function (_a) {
|
|
246
|
+
return [2 /*return*/, this.storage.query(filter)];
|
|
247
|
+
});
|
|
248
|
+
});
|
|
249
|
+
};
|
|
250
|
+
/**
|
|
251
|
+
* 最近のログを取得
|
|
252
|
+
*/
|
|
253
|
+
ActionLogger.prototype.getRecentLogs = function () {
|
|
254
|
+
return __awaiter(this, arguments, void 0, function (count) {
|
|
255
|
+
if (count === void 0) { count = 10; }
|
|
256
|
+
return __generator(this, function (_a) {
|
|
257
|
+
return [2 /*return*/, this.storage.query({ limit: count })];
|
|
258
|
+
});
|
|
259
|
+
});
|
|
260
|
+
};
|
|
261
|
+
/**
|
|
262
|
+
* 高リスクログを取得
|
|
263
|
+
*/
|
|
264
|
+
ActionLogger.prototype.getHighRiskLogs = function () {
|
|
265
|
+
return __awaiter(this, arguments, void 0, function (count) {
|
|
266
|
+
if (count === void 0) { count = 10; }
|
|
267
|
+
return __generator(this, function (_a) {
|
|
268
|
+
return [2 /*return*/, this.storage.query({ minRiskLevel: 'high', limit: count })];
|
|
269
|
+
});
|
|
270
|
+
});
|
|
271
|
+
};
|
|
272
|
+
/**
|
|
273
|
+
* ユーザーのログを取得
|
|
274
|
+
*/
|
|
275
|
+
ActionLogger.prototype.getUserLogs = function (userId_1) {
|
|
276
|
+
return __awaiter(this, arguments, void 0, function (userId, count) {
|
|
277
|
+
if (count === void 0) { count = 10; }
|
|
278
|
+
return __generator(this, function (_a) {
|
|
279
|
+
return [2 /*return*/, this.storage.query({ userId: userId, limit: count })];
|
|
280
|
+
});
|
|
281
|
+
});
|
|
282
|
+
};
|
|
283
|
+
/**
|
|
284
|
+
* ログをクリア
|
|
285
|
+
*/
|
|
286
|
+
ActionLogger.prototype.clearLogs = function () {
|
|
287
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
288
|
+
return __generator(this, function (_a) {
|
|
289
|
+
return [2 /*return*/, this.storage.clear()];
|
|
290
|
+
});
|
|
291
|
+
});
|
|
292
|
+
};
|
|
293
|
+
/**
|
|
294
|
+
* ログ件数を取得
|
|
295
|
+
*/
|
|
296
|
+
ActionLogger.prototype.getLogCount = function () {
|
|
297
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
298
|
+
return __generator(this, function (_a) {
|
|
299
|
+
return [2 /*return*/, this.storage.count()];
|
|
300
|
+
});
|
|
301
|
+
});
|
|
302
|
+
};
|
|
303
|
+
/**
|
|
304
|
+
* サマリーを生成
|
|
305
|
+
*/
|
|
306
|
+
ActionLogger.prototype.generateSummary = function () {
|
|
307
|
+
return __awaiter(this, arguments, void 0, function (filter) {
|
|
308
|
+
var logs, summary, successCount, totalWithObservation, _i, logs_1, log;
|
|
309
|
+
var _a, _b;
|
|
310
|
+
if (filter === void 0) { filter = {}; }
|
|
311
|
+
return __generator(this, function (_c) {
|
|
312
|
+
switch (_c.label) {
|
|
313
|
+
case 0: return [4 /*yield*/, this.storage.query(__assign(__assign({}, filter), { limit: 10000 }))];
|
|
314
|
+
case 1:
|
|
315
|
+
logs = _c.sent();
|
|
316
|
+
summary = {
|
|
317
|
+
totalActions: logs.length,
|
|
318
|
+
byRiskLevel: { low: 0, medium: 0, high: 0, critical: 0 },
|
|
319
|
+
byActionType: {},
|
|
320
|
+
successRate: 0,
|
|
321
|
+
blockedCount: 0,
|
|
322
|
+
confirmedCount: 0,
|
|
323
|
+
};
|
|
324
|
+
successCount = 0;
|
|
325
|
+
totalWithObservation = 0;
|
|
326
|
+
for (_i = 0, logs_1 = logs; _i < logs_1.length; _i++) {
|
|
327
|
+
log = logs_1[_i];
|
|
328
|
+
// リスクレベル別
|
|
329
|
+
summary.byRiskLevel[log.analysis.riskLevel]++;
|
|
330
|
+
// アクションタイプ別
|
|
331
|
+
summary.byActionType[log.action.type] =
|
|
332
|
+
((_a = summary.byActionType[log.action.type]) !== null && _a !== void 0 ? _a : 0) + 1;
|
|
333
|
+
// 成功率計算
|
|
334
|
+
if (log.observation) {
|
|
335
|
+
totalWithObservation++;
|
|
336
|
+
if (log.observation.success) {
|
|
337
|
+
successCount++;
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
// ブロック数
|
|
341
|
+
if (!log.analysis.allowed) {
|
|
342
|
+
summary.blockedCount++;
|
|
343
|
+
}
|
|
344
|
+
// 確認数
|
|
345
|
+
if ((_b = log.userConfirmation) === null || _b === void 0 ? void 0 : _b.confirmed) {
|
|
346
|
+
summary.confirmedCount++;
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
summary.successRate =
|
|
350
|
+
totalWithObservation > 0 ? successCount / totalWithObservation : 0;
|
|
351
|
+
return [2 /*return*/, summary];
|
|
352
|
+
}
|
|
353
|
+
});
|
|
354
|
+
});
|
|
355
|
+
};
|
|
356
|
+
return ActionLogger;
|
|
357
|
+
}());
|
|
358
|
+
exports.ActionLogger = ActionLogger;
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @nahisaho/katashiro-security
|
|
3
|
+
*
|
|
4
|
+
* Security analysis and audit logging for KATASHIRO
|
|
5
|
+
* @requirement REQ-012
|
|
6
|
+
*/
|
|
7
|
+
export { RiskLevel, RISK_LEVEL_ORDER, compareRiskLevels, isRiskLevelAtLeast, ActionType, Action, ActionContext, Observation, PatternRule, SecurityPolicy, RiskRule, RiskRuleMatch, SecurityAnalysis, AuditLogEntry, UserConfirmation, AuditLogFilter, DEFAULT_SECURITY_POLICY, BUILTIN_RISK_RULES, SecurityErrorCode, SecurityError, } from './types';
|
|
8
|
+
export { SecurityAnalyzer, SecurityAnalyzerOptions } from './security-analyzer';
|
|
9
|
+
export { LogStorage, InMemoryLogStorage, ActionLogger, ActionLoggerOptions, AuditLogSummary, } from './action-logger';
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EACL,SAAS,EACT,gBAAgB,EAChB,iBAAiB,EACjB,kBAAkB,EAClB,UAAU,EACV,MAAM,EACN,aAAa,EACb,WAAW,EACX,WAAW,EACX,cAAc,EACd,QAAQ,EACR,aAAa,EACb,gBAAgB,EAChB,aAAa,EACb,gBAAgB,EAChB,cAAc,EACd,uBAAuB,EACvB,kBAAkB,EAClB,iBAAiB,EACjB,aAAa,GACd,MAAM,SAAS,CAAC;AAGjB,OAAO,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AAGhF,OAAO,EACL,UAAU,EACV,kBAAkB,EAClB,YAAY,EACZ,mBAAmB,EACnB,eAAe,GAChB,MAAM,iBAAiB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @nahisaho/katashiro-security
|
|
4
|
+
*
|
|
5
|
+
* Security analysis and audit logging for KATASHIRO
|
|
6
|
+
* @requirement REQ-012
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.ActionLogger = exports.InMemoryLogStorage = exports.SecurityAnalyzer = exports.SecurityError = exports.BUILTIN_RISK_RULES = exports.DEFAULT_SECURITY_POLICY = exports.isRiskLevelAtLeast = exports.compareRiskLevels = exports.RISK_LEVEL_ORDER = void 0;
|
|
10
|
+
// Types
|
|
11
|
+
var types_1 = require("./types");
|
|
12
|
+
Object.defineProperty(exports, "RISK_LEVEL_ORDER", { enumerable: true, get: function () { return types_1.RISK_LEVEL_ORDER; } });
|
|
13
|
+
Object.defineProperty(exports, "compareRiskLevels", { enumerable: true, get: function () { return types_1.compareRiskLevels; } });
|
|
14
|
+
Object.defineProperty(exports, "isRiskLevelAtLeast", { enumerable: true, get: function () { return types_1.isRiskLevelAtLeast; } });
|
|
15
|
+
Object.defineProperty(exports, "DEFAULT_SECURITY_POLICY", { enumerable: true, get: function () { return types_1.DEFAULT_SECURITY_POLICY; } });
|
|
16
|
+
Object.defineProperty(exports, "BUILTIN_RISK_RULES", { enumerable: true, get: function () { return types_1.BUILTIN_RISK_RULES; } });
|
|
17
|
+
Object.defineProperty(exports, "SecurityError", { enumerable: true, get: function () { return types_1.SecurityError; } });
|
|
18
|
+
// SecurityAnalyzer
|
|
19
|
+
var security_analyzer_1 = require("./security-analyzer");
|
|
20
|
+
Object.defineProperty(exports, "SecurityAnalyzer", { enumerable: true, get: function () { return security_analyzer_1.SecurityAnalyzer; } });
|
|
21
|
+
// ActionLogger
|
|
22
|
+
var action_logger_1 = require("./action-logger");
|
|
23
|
+
Object.defineProperty(exports, "InMemoryLogStorage", { enumerable: true, get: function () { return action_logger_1.InMemoryLogStorage; } });
|
|
24
|
+
Object.defineProperty(exports, "ActionLogger", { enumerable: true, get: function () { return action_logger_1.ActionLogger; } });
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SecurityAnalyzer - セキュリティ分析クラス
|
|
3
|
+
*
|
|
4
|
+
* @requirement REQ-012
|
|
5
|
+
* @design REQ-012-01 リスクレベル評価
|
|
6
|
+
* @design REQ-012-02 確認プロンプト判定
|
|
7
|
+
* @design REQ-012-03 拒否パターンブロック
|
|
8
|
+
* @design REQ-012-04 許可パターン判定
|
|
9
|
+
* @design REQ-012-06 ファイル削除=高リスク
|
|
10
|
+
*/
|
|
11
|
+
import { Action, SecurityPolicy, SecurityAnalysis, RiskRule } from './types';
|
|
12
|
+
/**
|
|
13
|
+
* SecurityAnalyzerオプション
|
|
14
|
+
*/
|
|
15
|
+
export interface SecurityAnalyzerOptions {
|
|
16
|
+
/** カスタムポリシー */
|
|
17
|
+
policy?: Partial<SecurityPolicy>;
|
|
18
|
+
/** ビルトインルールを使用するか */
|
|
19
|
+
useBuiltinRules?: boolean;
|
|
20
|
+
/** 追加のリスクルール */
|
|
21
|
+
additionalRules?: RiskRule[];
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* セキュリティ分析器
|
|
25
|
+
*/
|
|
26
|
+
export declare class SecurityAnalyzer {
|
|
27
|
+
private readonly policy;
|
|
28
|
+
private readonly riskRules;
|
|
29
|
+
constructor(options?: SecurityAnalyzerOptions);
|
|
30
|
+
/**
|
|
31
|
+
* アクションを分析(REQ-012-01)
|
|
32
|
+
*/
|
|
33
|
+
analyze(action: Action): SecurityAnalysis;
|
|
34
|
+
/**
|
|
35
|
+
* アクションの実行を検証(確認が不要な場合のみ許可)
|
|
36
|
+
*/
|
|
37
|
+
validateAction(action: Action): void;
|
|
38
|
+
/**
|
|
39
|
+
* 確認付きでアクションを検証
|
|
40
|
+
*/
|
|
41
|
+
validateActionWithConfirmation(action: Action, confirmed: boolean): void;
|
|
42
|
+
/**
|
|
43
|
+
* 拒否パターンをチェック(REQ-012-03)
|
|
44
|
+
*/
|
|
45
|
+
private checkDenyPatterns;
|
|
46
|
+
/**
|
|
47
|
+
* 許可パターンをチェック(REQ-012-04)
|
|
48
|
+
*/
|
|
49
|
+
private checkAllowPatterns;
|
|
50
|
+
/**
|
|
51
|
+
* リスクレベルを評価
|
|
52
|
+
*/
|
|
53
|
+
private evaluateRiskLevel;
|
|
54
|
+
/**
|
|
55
|
+
* ルールがアクションにマッチするかチェック
|
|
56
|
+
*/
|
|
57
|
+
private matchesRule;
|
|
58
|
+
/**
|
|
59
|
+
* 現在のポリシーを取得
|
|
60
|
+
*/
|
|
61
|
+
getPolicy(): SecurityPolicy;
|
|
62
|
+
/**
|
|
63
|
+
* リスクルールを取得
|
|
64
|
+
*/
|
|
65
|
+
getRiskRules(): RiskRule[];
|
|
66
|
+
/**
|
|
67
|
+
* ポリシーを更新
|
|
68
|
+
*/
|
|
69
|
+
updatePolicy(update: Partial<SecurityPolicy>): void;
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=security-analyzer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"security-analyzer.d.ts","sourceRoot":"","sources":["../src/security-analyzer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,EACL,MAAM,EACN,cAAc,EACd,gBAAgB,EAEhB,QAAQ,EAOT,MAAM,SAAS,CAAC;AAEjB;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,eAAe;IACf,MAAM,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC;IACjC,qBAAqB;IACrB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,gBAAgB;IAChB,eAAe,CAAC,EAAE,QAAQ,EAAE,CAAC;CAC9B;AAED;;GAEG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAiB;IACxC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAa;gBAE3B,OAAO,GAAE,uBAA4B;IA4BjD;;OAEG;IACH,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,gBAAgB;IA8DzC;;OAEG;IACH,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAgBpC;;OAEG;IACH,8BAA8B,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,GAAG,IAAI;IAgBxE;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAkBzB;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAkB1B;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAsBzB;;OAEG;IACH,OAAO,CAAC,WAAW;IA8BnB;;OAEG;IACH,SAAS,IAAI,cAAc;IAI3B;;OAEG;IACH,YAAY,IAAI,QAAQ,EAAE;IAI1B;;OAEG;IACH,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,cAAc,CAAC,GAAG,IAAI;CAiBpD"}
|