@h-ai/audit 1.0.0-beta.2 → 1.0.0-beta.20
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.en.md +120 -50
- package/README.ja.md +129 -61
- package/README.md +130 -62
- package/dist/index.d.ts +2 -1
- package/dist/index.js +727 -224
- package/dist/index.js.map +1 -1
- package/package.json +15 -15
package/README.en.md
CHANGED
|
@@ -4,33 +4,14 @@
|
|
|
4
4
|
|
|
5
5
|
[Framework home](../../README.en.md) · Related modules: [@h-ai/core](../core/README.en.md) · [@h-ai/reldb](../reldb/README.en.md)
|
|
6
6
|
|
|
7
|
-
## Introduction
|
|
8
|
-
|
|
9
7
|
A unified audit logging module. The `audit` object records, queries, cleans up, and aggregates audit logs, with persistence provided by `@h-ai/reldb`.
|
|
10
8
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
## Core features
|
|
14
|
-
|
|
15
|
-
- Record user actions and security events; filter by user, date and action.
|
|
16
|
-
- Query paginated logs and statistics, and clean up by retention period.
|
|
17
|
-
- Persist through the relational database and redact credential fields before writing.
|
|
18
|
-
|
|
19
|
-
## Getting started
|
|
9
|
+
## Quick Start
|
|
20
10
|
|
|
21
11
|
### Dependencies
|
|
22
12
|
|
|
23
13
|
- `@h-ai/reldb`: database for audit log persistence; **initialize it before audit.init()**.
|
|
24
14
|
|
|
25
|
-
### Use cases
|
|
26
|
-
|
|
27
|
-
- User activity auditing (login, logout, registration, password reset, etc.)
|
|
28
|
-
- CRUD auditing (resource creation, reads, updates, and deletion)
|
|
29
|
-
- Security event tracking and compliance auditing
|
|
30
|
-
- Operational statistics (operation frequency, active users, etc.)
|
|
31
|
-
|
|
32
|
-
### Quick start
|
|
33
|
-
|
|
34
15
|
```ts
|
|
35
16
|
import { audit } from '@h-ai/audit'
|
|
36
17
|
import { reldb } from '@h-ai/reldb'
|
|
@@ -54,7 +35,13 @@ await audit.log({
|
|
|
54
35
|
|
|
55
36
|
// 4. 使用便捷方法
|
|
56
37
|
await audit.helper.login('user_1', '127.0.0.1')
|
|
57
|
-
await audit.helper.crud({
|
|
38
|
+
await audit.helper.crud({
|
|
39
|
+
userId: 'user_1',
|
|
40
|
+
action: 'create',
|
|
41
|
+
resource: 'users',
|
|
42
|
+
resourceId: 'user_2',
|
|
43
|
+
details: { name: '张三' }
|
|
44
|
+
})
|
|
58
45
|
|
|
59
46
|
// 5. 查询日志
|
|
60
47
|
const logs = await audit.list({ pageSize: 20, action: 'login' })
|
|
@@ -72,6 +59,76 @@ if (!closeResult.success) {
|
|
|
72
59
|
}
|
|
73
60
|
```
|
|
74
61
|
|
|
62
|
+
## Features
|
|
63
|
+
|
|
64
|
+
SQLite, PostgreSQL and MySQL share the same read contract: `createdAt` is a `Date`, `details` is a JSON string or `null`, and absent nullable fields return `null`. Date filters use the same driver conversion as writes. Counts are safe integers; out-of-range counts return `STATS_FAILED`.
|
|
65
|
+
|
|
66
|
+
### Operations and results
|
|
67
|
+
|
|
68
|
+
Use the complete initialization flow in this section first. The host validates and authorizes example business values; check success before reading data from asynchronous domain results. Here void means completion without data, null means absent; synchronous factories/tools return the listed type directly.
|
|
69
|
+
|
|
70
|
+
#### audit
|
|
71
|
+
|
|
72
|
+
Structured events: log takes event/optional tx and yields the record, capture yields void under read/write policy, withContext takes trusted correlation plus callback and returns its value.
|
|
73
|
+
|
|
74
|
+
| Entry | Input parameters | Successful result | Call example |
|
|
75
|
+
| ------------------- | ------------------ | ----------------- | ----------------------------------------------------------- |
|
|
76
|
+
| `audit.log` | input, tx | `AuditLog` | `await audit.log(event)` |
|
|
77
|
+
| `audit.capture` | input, options | `void` | `await audit.capture(event)` |
|
|
78
|
+
| `audit.withContext` | context, operation | `T` | `audit.withContext(trustedAuditContext, () => saveOrder())` |
|
|
79
|
+
|
|
80
|
+
#### audit
|
|
81
|
+
|
|
82
|
+
Query/retention: filters/page yield a page with users, user ID/limit recent events, days/filters statistics, cleanup retention days a deleted count.
|
|
83
|
+
|
|
84
|
+
| Entry | Input parameters | Successful result | Call example |
|
|
85
|
+
| --------------------- | ---------------- | ----------------------------------- | --------------------------------------------- |
|
|
86
|
+
| `audit.list` | options | `PaginatedResult<AuditLogWithUser>` | `await audit.list({ page: 1, pageSize: 20 })` |
|
|
87
|
+
| `audit.getUserRecent` | userId, limit | `AuditLog[]` | `await audit.getUserRecent(userId, 20)` |
|
|
88
|
+
| `audit.getStats` | days, filters | `AuditStatItem[]` | `await audit.getStats(7)` |
|
|
89
|
+
| `audit.cleanup` | olderThanDays | `number` | `await audit.cleanup(90)` |
|
|
90
|
+
|
|
91
|
+
#### audit.helper
|
|
92
|
+
|
|
93
|
+
Common events accept user ID (email for reset request), optional IP/UA or a CRUD event and yield void HaiResult; privacy filtering still applies.
|
|
94
|
+
|
|
95
|
+
| Entry | Input parameters | Successful result | Call example |
|
|
96
|
+
| ------------------------------------ | ---------------- | ----------------- | -------------------------------------------------- |
|
|
97
|
+
| `audit.helper.login` | userId, ip, ua | `void` | `await audit.helper.login(userId)` |
|
|
98
|
+
| `audit.helper.logout` | userId, ip, ua | `void` | `await audit.helper.logout(userId)` |
|
|
99
|
+
| `audit.helper.register` | userId, ip, ua | `void` | `await audit.helper.register(userId)` |
|
|
100
|
+
| `audit.helper.passwordResetRequest` | email, ip, ua | `void` | `await audit.helper.passwordResetRequest(email)` |
|
|
101
|
+
| `audit.helper.passwordResetComplete` | userId, ip, ua | `void` | `await audit.helper.passwordResetComplete(userId)` |
|
|
102
|
+
| `audit.helper.crud` | input | `void` | `await audit.helper.crud(crudEvent)` |
|
|
103
|
+
|
|
104
|
+
#### audit.backup
|
|
105
|
+
|
|
106
|
+
Private archive: run takes filters/deadline/cancellation, verify an object key; both yield verified archive information without publishing objects.
|
|
107
|
+
|
|
108
|
+
| Entry | Input parameters | Successful result | Call example |
|
|
109
|
+
| --------------------- | ---------------- | ----------------- | --------------------------------------- |
|
|
110
|
+
| `audit.backup.run` | options | `AuditBackupInfo` | `await audit.backup.run()` |
|
|
111
|
+
| `audit.backup.verify` | key, options | `AuditBackupInfo` | `await audit.backup.verify(archiveKey)` |
|
|
112
|
+
|
|
113
|
+
#### audit
|
|
114
|
+
|
|
115
|
+
Scheduled anomaly check takes optional signal and yields matched rules/notification results; orchestrate via scheduler rather than assuming a worker started.
|
|
116
|
+
|
|
117
|
+
| Entry | Input parameters | Successful result | Call example |
|
|
118
|
+
| ------------------- | ---------------- | ------------------ | --------------------------- |
|
|
119
|
+
| `audit.checkAlerts` | options | `AuditAlertReport` | `await audit.checkAlerts()` |
|
|
120
|
+
|
|
121
|
+
- Record user actions and security events; filter by user, date and action.
|
|
122
|
+
- Query paginated logs and statistics, and clean up by retention period.
|
|
123
|
+
- Persist through the relational database and redact credential fields before writing.
|
|
124
|
+
|
|
125
|
+
### Use cases
|
|
126
|
+
|
|
127
|
+
- User activity auditing (login, logout, registration, password reset, etc.)
|
|
128
|
+
- CRUD auditing (resource creation, reads, updates, and deletion)
|
|
129
|
+
- Security event tracking and compliance auditing
|
|
130
|
+
- Operational statistics (operation frequency, active users, etc.)
|
|
131
|
+
|
|
75
132
|
### Initialization options
|
|
76
133
|
|
|
77
134
|
```ts
|
|
@@ -110,31 +167,7 @@ Record common events through `audit.helper`, with the public `AuditHelper` type.
|
|
|
110
167
|
- `audit.cleanup(days)`: `days`, if provided, must be a nonnegative integer.
|
|
111
168
|
- `audit.getStats(days)`: `days`, if provided, must be a nonnegative integer.
|
|
112
169
|
|
|
113
|
-
###
|
|
114
|
-
|
|
115
|
-
Business data operations return `HaiResult<T>`. Common error codes:
|
|
116
|
-
|
|
117
|
-
| Error code | code | Description |
|
|
118
|
-
| -------------------------------- | --------------- | ------------------------------------ |
|
|
119
|
-
| `HaiAuditError.LOG_FAILED` | `hai:audit:001` | Recording failed |
|
|
120
|
-
| `HaiAuditError.QUERY_FAILED` | `hai:audit:002` | Query failed |
|
|
121
|
-
| `HaiAuditError.CLEANUP_FAILED` | `hai:audit:003` | Cleanup failed |
|
|
122
|
-
| `HaiAuditError.STATS_FAILED` | `hai:audit:004` | Aggregation failed |
|
|
123
|
-
| `HaiAuditError.INIT_IN_PROGRESS` | `hai:audit:005` | Initialization in progress |
|
|
124
|
-
| `HaiAuditError.NOT_INITIALIZED` | `hai:audit:010` | Module not initialized |
|
|
125
|
-
| `HaiAuditError.CONFIG_ERROR` | `hai:audit:012` | Invalid configuration |
|
|
126
|
-
| `HaiAuditError.BACKUP_DISABLED` | `hai:audit:020` | Backup disabled |
|
|
127
|
-
| `HaiAuditError.BACKUP_FAILED` | `hai:audit:021` | Backup or verification failed |
|
|
128
|
-
| `HaiAuditError.BACKUP_INVALID` | `hai:audit:022` | Invalid backup input |
|
|
129
|
-
| `HaiAuditError.BACKUP_CONFLICT` | `hai:audit:023` | Backup ID/export conditions conflict |
|
|
130
|
-
| `HaiAuditError.ALERTS_DISABLED` | `hai:audit:024` | Alerts disabled |
|
|
131
|
-
| `HaiAuditError.ALERTS_FAILED` | `hai:audit:025` | Alert check or notification failed |
|
|
132
|
-
|
|
133
|
-
> Note: `audit.close()` also returns `HaiResult<void>`. Email details in `audit.helper.passwordResetRequest()` are hidden by the default business privacy settings.
|
|
134
|
-
|
|
135
|
-
`audit.init()` awaits automatic table creation and repository readiness before success. DDL failures leave `isInitialized=false`; correct the database and retry. Custom joins, statistics and cleanup share the same barrier. Closing during initialization invalidates late publication. Check the init HaiResult before recording or querying. Audit does not own the shared RelDB connection; close audit before the database.
|
|
136
|
-
|
|
137
|
-
## Event context, privacy and retention
|
|
170
|
+
### Event context, privacy and retention
|
|
138
171
|
|
|
139
172
|
Audit createdAt, alert windows and archive cutoffs share the database clock rather than individual node clocks. Scheduled backup/alert tasks declare idempotency based on their persistent deduplication guarantees; failures do not incorrectly block subsequent schedules as non-idempotent unknown tasks.
|
|
140
173
|
|
|
@@ -152,7 +185,7 @@ Stop old writers and back up before upgrading. `migrateAudit({ dryRun: true })`
|
|
|
152
185
|
|
|
153
186
|
Redaction matches whole fields, including objects, arrays and sensitive values produced by custom JSON projections. capture returns not-initialized failure before initialization or after close; only an initialized module with capture disabled skips automatic events.
|
|
154
187
|
|
|
155
|
-
|
|
188
|
+
### Private backups and scheduled archives
|
|
156
189
|
|
|
157
190
|
`backup.enabled` is off by default. Inject initialized `StorageFunctions` with `audit.init({ storage, backup: { enabled: true } })`; initialize RelDB first. `backup.batchSize` controls scan batches (default200), while `maxRecordBytes` bounds each UTF-8 record (default1 MiB). Oversized records fail the archive without truncating stored evidence.
|
|
158
191
|
|
|
@@ -165,7 +198,10 @@ Version1 contains a header, `{type:'entry',record}` lines and a footer. Entries
|
|
|
165
198
|
```ts
|
|
166
199
|
const plan = audit.schedulerPlan
|
|
167
200
|
if (plan) {
|
|
168
|
-
const initialized = await scheduler.init({
|
|
201
|
+
const initialized = await scheduler.init({
|
|
202
|
+
...schedulerSettings,
|
|
203
|
+
...plan
|
|
204
|
+
})
|
|
169
205
|
if (!initialized.success)
|
|
170
206
|
throw new Error(initialized.error.message)
|
|
171
207
|
const started = scheduler.start()
|
|
@@ -176,7 +212,7 @@ if (plan) {
|
|
|
176
212
|
|
|
177
213
|
The host imports audit/scheduler and supplies validated schedulerSettings, with Audit/Storage/RelDB initialized. Use private archive storage: enabling backups rejects an S3 publicUrl setting, and deployment must restrict bucket/CDN access. Public asset endpoints should expose designated resources only. The example/fullstack runtimes expose canonical avatar paths; archives require an authorized audit download endpoint. Disabling backups preserves the private boundary of existing files.
|
|
178
214
|
|
|
179
|
-
|
|
215
|
+
### Graded anomaly alerts
|
|
180
216
|
|
|
181
217
|
`alerts.enabled` defaults to false. Inject initialized Reach when enabling it: `audit.init({ reach, alerts: { enabled: true, rules: [...] } })`. Each rule has a stable id, exact actions, optional resource, outcomes and minimumSeverity filters, threshold/windowSeconds, notification severity, and targets containing id/provider/to. Windows default to 300 seconds (60–86400); default outcomes are failure/denied, while an empty outcomes list matches all. Rule and target IDs must be unique; providers must exist in Reach. Business roles remain application choices.
|
|
182
218
|
|
|
@@ -186,7 +222,41 @@ Messages include only rule/target IDs, level, count and window, without event de
|
|
|
186
222
|
|
|
187
223
|
alerts.schedule defaults to disabled, once per minute in UTC. audit.schedulerPlan composes enabled backup and alert tasks for explicit host Scheduler initialization; it is null without automatic tasks. Scheduler callbacks fail when checking fails or report.failed>0. Close Scheduler before Audit/Reach. Audit cancels further claims and drains in-flight sends within Reach provider timeouts without closing host Reach. Query/audit failures return a failed HaiResult; notification failures appear in a successful report.failed and must be checked by callers.
|
|
188
224
|
|
|
189
|
-
##
|
|
225
|
+
## Configuration
|
|
226
|
+
|
|
227
|
+
Lifecycle: init takes backend/business configuration; use the module only after success. Await close before releasing borrowed dependencies. Follow the quick-start example and public signatures for exact return values.
|
|
228
|
+
|
|
229
|
+
The host loads and validates configuration before passing it to this module. Keep secrets in private server environment files. Select the backend, capacity, deadlines and logging for the actual use case; reinitialize and check the result after changes.
|
|
230
|
+
|
|
231
|
+
[Per-option purpose, use cases and examples](../../docs/usage/configuration/operations.md).
|
|
232
|
+
|
|
233
|
+
## Error Handling
|
|
234
|
+
|
|
235
|
+
Check result.success for domain operations. Handle failures with the module error definitions and safe messages; retain codes, correlation IDs and sanitized causes in server logs. Synchronous tools, factories, stream iteration and lifecycle calls follow their own signatures. A completed Promise alone is not business success. See each feature for recovery limits.
|
|
236
|
+
|
|
237
|
+
Business data operations return `HaiResult<T>`. Common error codes:
|
|
238
|
+
|
|
239
|
+
| Error code | code | Description |
|
|
240
|
+
| -------------------------------- | --------------- | ------------------------------------ |
|
|
241
|
+
| `HaiAuditError.LOG_FAILED` | `hai:audit:001` | Recording failed |
|
|
242
|
+
| `HaiAuditError.QUERY_FAILED` | `hai:audit:002` | Query failed |
|
|
243
|
+
| `HaiAuditError.CLEANUP_FAILED` | `hai:audit:003` | Cleanup failed |
|
|
244
|
+
| `HaiAuditError.STATS_FAILED` | `hai:audit:004` | Aggregation failed |
|
|
245
|
+
| `HaiAuditError.INIT_IN_PROGRESS` | `hai:audit:005` | Initialization in progress |
|
|
246
|
+
| `HaiAuditError.NOT_INITIALIZED` | `hai:audit:010` | Module not initialized |
|
|
247
|
+
| `HaiAuditError.CONFIG_ERROR` | `hai:audit:012` | Invalid configuration |
|
|
248
|
+
| `HaiAuditError.BACKUP_DISABLED` | `hai:audit:020` | Backup disabled |
|
|
249
|
+
| `HaiAuditError.BACKUP_FAILED` | `hai:audit:021` | Backup or verification failed |
|
|
250
|
+
| `HaiAuditError.BACKUP_INVALID` | `hai:audit:022` | Invalid backup input |
|
|
251
|
+
| `HaiAuditError.BACKUP_CONFLICT` | `hai:audit:023` | Backup ID/export conditions conflict |
|
|
252
|
+
| `HaiAuditError.ALERTS_DISABLED` | `hai:audit:024` | Alerts disabled |
|
|
253
|
+
| `HaiAuditError.ALERTS_FAILED` | `hai:audit:025` | Alert check or notification failed |
|
|
254
|
+
|
|
255
|
+
> Note: `audit.close()` also returns `HaiResult<void>`. Email details in `audit.helper.passwordResetRequest()` are hidden by the default business privacy settings.
|
|
256
|
+
|
|
257
|
+
`audit.init()` awaits automatic table creation and repository readiness before success. DDL failures leave `isInitialized=false`; correct the database and retry. Custom joins, statistics and cleanup share the same barrier. Closing during initialization invalidates late publication. Check the init HaiResult before recording or querying. Audit does not own the shared RelDB connection; close audit before the database.
|
|
258
|
+
|
|
259
|
+
## Development
|
|
190
260
|
|
|
191
261
|
```bash
|
|
192
262
|
pnpm --filter @h-ai/audit test
|
package/README.ja.md
CHANGED
|
@@ -4,33 +4,14 @@
|
|
|
4
4
|
|
|
5
5
|
[フレームワークのホーム](../../README.ja.md) · 関連モジュール:[@h-ai/core](../core/README.ja.md) · [@h-ai/reldb](../reldb/README.ja.md)
|
|
6
6
|
|
|
7
|
-
## 概要
|
|
8
|
-
|
|
9
7
|
統一された監査ログモジュールです。`audit` オブジェクトで記録、検索、削除、集計を行い、`@h-ai/reldb` で永続化します。
|
|
10
8
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
## 主な機能
|
|
14
|
-
|
|
15
|
-
- ユーザー操作やセキュリティイベントを記録し、ユーザー・日時・操作で検索。
|
|
16
|
-
- ログのページ取得、統計、保存期間に応じた削除。
|
|
17
|
-
- 関係データベースに保存し、認証情報を記録前にマスク。
|
|
18
|
-
|
|
19
|
-
## 使い始める
|
|
9
|
+
## クイックスタート
|
|
20
10
|
|
|
21
11
|
### 依存関係
|
|
22
12
|
|
|
23
13
|
- `@h-ai/reldb`:監査ログを永続化するデータベース。**audit.init() より先に初期化してください**。
|
|
24
14
|
|
|
25
|
-
### 用途
|
|
26
|
-
|
|
27
|
-
- ユーザー操作の監査(ログイン、ログアウト、登録、パスワードリセットなど)
|
|
28
|
-
- CRUD 操作の監査(リソースの作成、参照、更新、削除)
|
|
29
|
-
- セキュリティイベントの追跡とコンプライアンス監査
|
|
30
|
-
- 運用統計(操作頻度、アクティブユーザーなど)
|
|
31
|
-
|
|
32
|
-
### クイックスタート
|
|
33
|
-
|
|
34
15
|
```ts
|
|
35
16
|
import { audit } from '@h-ai/audit'
|
|
36
17
|
import { reldb } from '@h-ai/reldb'
|
|
@@ -54,7 +35,13 @@ await audit.log({
|
|
|
54
35
|
|
|
55
36
|
// 4. 使用便捷方法
|
|
56
37
|
await audit.helper.login('user_1', '127.0.0.1')
|
|
57
|
-
await audit.helper.crud({
|
|
38
|
+
await audit.helper.crud({
|
|
39
|
+
userId: 'user_1',
|
|
40
|
+
action: 'create',
|
|
41
|
+
resource: 'users',
|
|
42
|
+
resourceId: 'user_2',
|
|
43
|
+
details: { name: '张三' }
|
|
44
|
+
})
|
|
58
45
|
|
|
59
46
|
// 5. 查询日志
|
|
60
47
|
const logs = await audit.list({ pageSize: 20, action: 'login' })
|
|
@@ -72,21 +59,75 @@ if (!closeResult.success) {
|
|
|
72
59
|
}
|
|
73
60
|
```
|
|
74
61
|
|
|
75
|
-
|
|
62
|
+
## 機能
|
|
76
63
|
|
|
77
|
-
|
|
78
|
-
// 默认配置(无需传参)
|
|
79
|
-
await audit.init()
|
|
64
|
+
SQLite、PostgreSQL、MySQL で読み取り契約は共通です。`createdAt` は `Date`、`details` は JSON 文字列または `null`、値のない nullable フィールドは `null` を返します。日時フィルターは書き込みと同じドライバー変換を使用します。件数は安全な整数とし、範囲外では `STATS_FAILED` を返します。
|
|
80
65
|
|
|
81
|
-
|
|
82
|
-
await audit.init({
|
|
83
|
-
userTable: 'hai_iam_users', // 用户表名(默认 'hai_iam_users')
|
|
84
|
-
userIdColumn: 'id', // 用户表主键列名(默认 'id')
|
|
85
|
-
userNameColumn: 'username', // 用户表用户名列名(默认 'username')
|
|
86
|
-
})
|
|
87
|
-
```
|
|
66
|
+
### 操作と入出力
|
|
88
67
|
|
|
89
|
-
|
|
68
|
+
本節の完全な初期化手順を先に実行します。例の業務値はホストが検証・認可し、非同期領域結果は success を確認してから data を読みます。void はデータなし完了、null は不存在、同期ファクトリー/ツールは表の型を直接返します。
|
|
69
|
+
|
|
70
|
+
#### audit
|
|
71
|
+
|
|
72
|
+
構造化イベント。log はイベント/任意 tx から記録、capture は読書方針に従い void、withContext は信頼する関連情報とコールバックからその値を直接返す。
|
|
73
|
+
|
|
74
|
+
| 入口 | 入力引数 | 成功結果 | 呼出し例 |
|
|
75
|
+
| ------------------- | ------------------ | ---------- | ----------------------------------------------------------- |
|
|
76
|
+
| `audit.log` | input, tx | `AuditLog` | `await audit.log(event)` |
|
|
77
|
+
| `audit.capture` | input, options | `void` | `await audit.capture(event)` |
|
|
78
|
+
| `audit.withContext` | context, operation | `T` | `audit.withContext(trustedAuditContext, () => saveOrder())` |
|
|
79
|
+
|
|
80
|
+
#### audit
|
|
81
|
+
|
|
82
|
+
検索/保持。条件/ページから利用者付き一覧、ユーザー ID/limit から直近配列、days/filters から統計、cleanup は保持日数から削除数。
|
|
83
|
+
|
|
84
|
+
| 入口 | 入力引数 | 成功結果 | 呼出し例 |
|
|
85
|
+
| --------------------- | ------------- | ----------------------------------- | --------------------------------------------- |
|
|
86
|
+
| `audit.list` | options | `PaginatedResult<AuditLogWithUser>` | `await audit.list({ page: 1, pageSize: 20 })` |
|
|
87
|
+
| `audit.getUserRecent` | userId, limit | `AuditLog[]` | `await audit.getUserRecent(userId, 20)` |
|
|
88
|
+
| `audit.getStats` | days, filters | `AuditStatItem[]` | `await audit.getStats(7)` |
|
|
89
|
+
| `audit.cleanup` | olderThanDays | `number` | `await audit.cleanup(90)` |
|
|
90
|
+
|
|
91
|
+
#### audit.helper
|
|
92
|
+
|
|
93
|
+
共通イベントはユーザー ID(リセット要求は email)・任意 IP/UA または CRUD 入力から void HaiResult。機密値は引き続き秘匿。
|
|
94
|
+
|
|
95
|
+
| 入口 | 入力引数 | 成功結果 | 呼出し例 |
|
|
96
|
+
| ------------------------------------ | -------------- | -------- | -------------------------------------------------- |
|
|
97
|
+
| `audit.helper.login` | userId, ip, ua | `void` | `await audit.helper.login(userId)` |
|
|
98
|
+
| `audit.helper.logout` | userId, ip, ua | `void` | `await audit.helper.logout(userId)` |
|
|
99
|
+
| `audit.helper.register` | userId, ip, ua | `void` | `await audit.helper.register(userId)` |
|
|
100
|
+
| `audit.helper.passwordResetRequest` | email, ip, ua | `void` | `await audit.helper.passwordResetRequest(email)` |
|
|
101
|
+
| `audit.helper.passwordResetComplete` | userId, ip, ua | `void` | `await audit.helper.passwordResetComplete(userId)` |
|
|
102
|
+
| `audit.helper.crud` | input | `void` | `await audit.helper.crud(crudEvent)` |
|
|
103
|
+
|
|
104
|
+
#### audit.backup
|
|
105
|
+
|
|
106
|
+
非公開アーカイブ。run は条件/期限/取消、verify はオブジェクト key から完全性を確認した情報を返す。公開しない。
|
|
107
|
+
|
|
108
|
+
| 入口 | 入力引数 | 成功結果 | 呼出し例 |
|
|
109
|
+
| --------------------- | ------------ | ----------------- | --------------------------------------- |
|
|
110
|
+
| `audit.backup.run` | options | `AuditBackupInfo` | `await audit.backup.run()` |
|
|
111
|
+
| `audit.backup.verify` | key, options | `AuditBackupInfo` | `await audit.backup.verify(archiveKey)` |
|
|
112
|
+
|
|
113
|
+
#### audit
|
|
114
|
+
|
|
115
|
+
異常検査は任意 signal から該当規則と通知結果。暗黙ワーカーを仮定せず scheduler で調整。
|
|
116
|
+
|
|
117
|
+
| 入口 | 入力引数 | 成功結果 | 呼出し例 |
|
|
118
|
+
| ------------------- | -------- | ------------------ | --------------------------- |
|
|
119
|
+
| `audit.checkAlerts` | options | `AuditAlertReport` | `await audit.checkAlerts()` |
|
|
120
|
+
|
|
121
|
+
- ユーザー操作やセキュリティイベントを記録し、ユーザー・日時・操作で検索。
|
|
122
|
+
- ログのページ取得、統計、保存期間に応じた削除。
|
|
123
|
+
- 関係データベースに保存し、認証情報を記録前にマスク。
|
|
124
|
+
|
|
125
|
+
### 用途
|
|
126
|
+
|
|
127
|
+
- ユーザー操作の監査(ログイン、ログアウト、登録、パスワードリセットなど)
|
|
128
|
+
- CRUD 操作の監査(リソースの作成、参照、更新、削除)
|
|
129
|
+
- セキュリティイベントの追跡とコンプライアンス監査
|
|
130
|
+
- 運用統計(操作頻度、アクティブユーザーなど)
|
|
90
131
|
|
|
91
132
|
### API 一覧
|
|
92
133
|
|
|
@@ -110,31 +151,7 @@ await audit.init({
|
|
|
110
151
|
- `audit.cleanup(days)`:`days` を指定する場合は 0 以上の整数。
|
|
111
152
|
- `audit.getStats(days)`:`days` を指定する場合は 0 以上の整数。
|
|
112
153
|
|
|
113
|
-
###
|
|
114
|
-
|
|
115
|
-
業務データ操作は `HaiResult<T>` を返します。主なエラーコード:
|
|
116
|
-
|
|
117
|
-
| エラーコード | code | 説明 |
|
|
118
|
-
| -------------------------------- | --------------- | -------------------------- |
|
|
119
|
-
| `HaiAuditError.LOG_FAILED` | `hai:audit:001` | 記録に失敗 |
|
|
120
|
-
| `HaiAuditError.QUERY_FAILED` | `hai:audit:002` | 検索に失敗 |
|
|
121
|
-
| `HaiAuditError.CLEANUP_FAILED` | `hai:audit:003` | 削除に失敗 |
|
|
122
|
-
| `HaiAuditError.STATS_FAILED` | `hai:audit:004` | 集計に失敗 |
|
|
123
|
-
| `HaiAuditError.INIT_IN_PROGRESS` | `hai:audit:005` | 初期化中 |
|
|
124
|
-
| `HaiAuditError.NOT_INITIALIZED` | `hai:audit:010` | モジュールが未初期化 |
|
|
125
|
-
| `HaiAuditError.CONFIG_ERROR` | `hai:audit:012` | 設定エラー |
|
|
126
|
-
| `HaiAuditError.BACKUP_DISABLED` | `hai:audit:020` | バックアップ無効 |
|
|
127
|
-
| `HaiAuditError.BACKUP_FAILED` | `hai:audit:021` | バックアップ/検証失敗 |
|
|
128
|
-
| `HaiAuditError.BACKUP_INVALID` | `hai:audit:022` | バックアップ入力が無効 |
|
|
129
|
-
| `HaiAuditError.BACKUP_CONFLICT` | `hai:audit:023` | IDとエクスポート条件が衝突 |
|
|
130
|
-
| `HaiAuditError.ALERTS_DISABLED` | `hai:audit:024` | アラート無効 |
|
|
131
|
-
| `HaiAuditError.ALERTS_FAILED` | `hai:audit:025` | アラート検査・通知失敗 |
|
|
132
|
-
|
|
133
|
-
> 注:`audit.close()` も `HaiResult<void>` を返します。`audit.helper.passwordResetRequest()` のメール情報は既定の業務個人情報設定でマスクされます。
|
|
134
|
-
|
|
135
|
-
`audit.init()` は自動建表とリポジトリーの準備完了を待って成功します。DDL 失敗時は `isInitialized=false` のままで、DB を修正後に再試行できます。独自 JOIN・統計・削除も同じ準備完了を待ちます。初期化中の close は遅れた公開を無効化します。init の HaiResult を確認後に記録・検索し、共有 DB の接続は所有しないため audit の終了後に DB を終了します。
|
|
136
|
-
|
|
137
|
-
## イベント文脈、個人情報と保持
|
|
154
|
+
### イベント文脈、個人情報と保持
|
|
138
155
|
|
|
139
156
|
監査 createdAt、アラート窓、アーカイブ終了時刻はノード時刻ではなく DB 時刻を共用します。バックアップ/アラート定時タスクは永続的な重複排除の保証により冪等を宣言し、失敗を非冪等の不明タスクとして後続スケジュールを阻止しません。
|
|
140
157
|
|
|
@@ -152,7 +169,7 @@ await audit.init({
|
|
|
152
169
|
|
|
153
170
|
マスキングは項目全体に適用し、オブジェクト、配列、独自 JSON 変換の機密値も隠します。未初期化または close 後の capture は未初期化エラーを返し、初期化済みモジュールで capture を無効にした場合だけ自動イベントを省略します。
|
|
154
171
|
|
|
155
|
-
|
|
172
|
+
### 非公開バックアップと定時アーカイブ
|
|
156
173
|
|
|
157
174
|
`backup.enabled` は既定で無効です。RelDB を先に初期化し、初期化済み StorageFunctions を `audit.init({ storage, backup: { enabled: true } })` に渡します。batchSize は走査件数(既定200)、maxRecordBytes は UTF-8 一行の上限(既定1 MiB)です。上限超過は失敗し、元の監査証拠は切り詰めません。
|
|
158
175
|
|
|
@@ -165,7 +182,10 @@ backup.schedule は enabled、5項目 cron(既定 `0 2 * * *`)、IANA timezo
|
|
|
165
182
|
```ts
|
|
166
183
|
const plan = audit.schedulerPlan
|
|
167
184
|
if (plan) {
|
|
168
|
-
const initialized = await scheduler.init({
|
|
185
|
+
const initialized = await scheduler.init({
|
|
186
|
+
...schedulerSettings,
|
|
187
|
+
...plan
|
|
188
|
+
})
|
|
169
189
|
if (!initialized.success)
|
|
170
190
|
throw new Error(initialized.error.message)
|
|
171
191
|
const started = scheduler.start()
|
|
@@ -176,7 +196,7 @@ if (plan) {
|
|
|
176
196
|
|
|
177
197
|
ホストが audit/scheduler と検証済み schedulerSettings を提供し、Audit/Storage/RelDB を初期化済みとします。非公開ストレージを使い、バックアップ有効時は S3 publicUrl 設定を拒否します。バケット/CDN のアクセス制限も必要です。公開ファイル入口は指定資源のみを許可し、example/fullstack は正規のアバターパスだけを公開します。アーカイブの取得には監査の認可入口を使い、無効化後も既存ファイルは非公開のままです。
|
|
178
198
|
|
|
179
|
-
|
|
199
|
+
### 等級別の異常アラート
|
|
180
200
|
|
|
181
201
|
`alerts.enabled` は既定で false。有効化時は初期化済み Reach を `audit.init({ reach, alerts: { enabled: true, rules: [...] } })` に渡します。ルールは一意な id、完全一致の actions、任意の resource、outcomes、minimumSeverity、threshold/windowSeconds、通知 severity、id/provider/to を持つ targets で指定します。既定の窓は300秒(60–86400秒)、結果は failure/denied、空の outcomes は全結果です。通知 Provider は Reach に登録済みである必要があります。業務ロールはアプリ側で決定します。
|
|
182
202
|
|
|
@@ -186,6 +206,54 @@ if (plan) {
|
|
|
186
206
|
|
|
187
207
|
alerts.schedule は独立して有効化でき、既定は毎分・UTC。audit.schedulerPlan は有効なバックアップ/アラートをまとめ、ホストが Scheduler に明示的に渡します。自動タスクがなければ null。検査失敗または report.failed>0 はタスク失敗です。Scheduler を先に停止し、次に Audit/Reach を閉じます。Audit は新規取得を取消し、Reach の Provider タイムアウト内で実行中通知を待機し、ホスト Reach は閉じません。DB/監査失敗は HaiResult の失敗、通知失敗は成功レポートの failed に現れるため、呼出側で確認します。
|
|
188
208
|
|
|
209
|
+
## 設定
|
|
210
|
+
|
|
211
|
+
ライフサイクル。init にバックエンド/業務設定を渡し成功後に使用します。借用依存先の解放前に close の完了を待ち、正確な戻り値は例と公開署名に従います。
|
|
212
|
+
|
|
213
|
+
```ts
|
|
214
|
+
// 默认配置(无需传参)
|
|
215
|
+
await audit.init()
|
|
216
|
+
|
|
217
|
+
// 自定义用户表映射
|
|
218
|
+
await audit.init({
|
|
219
|
+
userTable: 'hai_iam_users', // 用户表名(默认 'hai_iam_users')
|
|
220
|
+
userIdColumn: 'id', // 用户表主键列名(默认 'id')
|
|
221
|
+
userNameColumn: 'username', // 用户表用户名列名(默认 'username')
|
|
222
|
+
})
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
監査ログは固定の `hai_audit_logs` テーブルに保存され、初期化済みの `@h-ai/reldb` が必要です。
|
|
226
|
+
|
|
227
|
+
設定はホストが読込・検証してから渡します。秘密はサーバーの非公開環境に保存し、利用場面に応じてバックエンド・容量・期限・ログを選びます。変更後は再初期化の結果を確認してください。
|
|
228
|
+
|
|
229
|
+
[項目別の用途・適用場面・例](../../docs/usage/configuration/operations.md).
|
|
230
|
+
|
|
231
|
+
## エラー処理
|
|
232
|
+
|
|
233
|
+
領域操作は result.success を確認し、失敗時はモジュールのエラー定義と安全な説明を使います。コード・関連 ID・秘匿した原因をサーバーログに残します。同期ツール・ファクトリー・ストリーム反復・ライフサイクルは各署名に従い、Promise 完了だけで成功と判断しません。回復条件は各機能を参照してください。
|
|
234
|
+
|
|
235
|
+
業務データ操作は `HaiResult<T>` を返します。主なエラーコード:
|
|
236
|
+
|
|
237
|
+
| エラーコード | code | 説明 |
|
|
238
|
+
| -------------------------------- | --------------- | -------------------------- |
|
|
239
|
+
| `HaiAuditError.LOG_FAILED` | `hai:audit:001` | 記録に失敗 |
|
|
240
|
+
| `HaiAuditError.QUERY_FAILED` | `hai:audit:002` | 検索に失敗 |
|
|
241
|
+
| `HaiAuditError.CLEANUP_FAILED` | `hai:audit:003` | 削除に失敗 |
|
|
242
|
+
| `HaiAuditError.STATS_FAILED` | `hai:audit:004` | 集計に失敗 |
|
|
243
|
+
| `HaiAuditError.INIT_IN_PROGRESS` | `hai:audit:005` | 初期化中 |
|
|
244
|
+
| `HaiAuditError.NOT_INITIALIZED` | `hai:audit:010` | モジュールが未初期化 |
|
|
245
|
+
| `HaiAuditError.CONFIG_ERROR` | `hai:audit:012` | 設定エラー |
|
|
246
|
+
| `HaiAuditError.BACKUP_DISABLED` | `hai:audit:020` | バックアップ無効 |
|
|
247
|
+
| `HaiAuditError.BACKUP_FAILED` | `hai:audit:021` | バックアップ/検証失敗 |
|
|
248
|
+
| `HaiAuditError.BACKUP_INVALID` | `hai:audit:022` | バックアップ入力が無効 |
|
|
249
|
+
| `HaiAuditError.BACKUP_CONFLICT` | `hai:audit:023` | IDとエクスポート条件が衝突 |
|
|
250
|
+
| `HaiAuditError.ALERTS_DISABLED` | `hai:audit:024` | アラート無効 |
|
|
251
|
+
| `HaiAuditError.ALERTS_FAILED` | `hai:audit:025` | アラート検査・通知失敗 |
|
|
252
|
+
|
|
253
|
+
> 注:`audit.close()` も `HaiResult<void>` を返します。`audit.helper.passwordResetRequest()` のメール情報は既定の業務個人情報設定でマスクされます。
|
|
254
|
+
|
|
255
|
+
`audit.init()` は自動建表とリポジトリーの準備完了を待って成功します。DDL 失敗時は `isInitialized=false` のままで、DB を修正後に再試行できます。独自 JOIN・統計・削除も同じ準備完了を待ちます。初期化中の close は遅れた公開を無効化します。init の HaiResult を確認後に記録・検索し、共有 DB の接続は所有しないため audit の終了後に DB を終了します。
|
|
256
|
+
|
|
189
257
|
## 開発とテスト
|
|
190
258
|
|
|
191
259
|
```bash
|