@h-ai/audit 1.0.0-beta.19 → 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 +109 -48
- package/README.ja.md +118 -59
- package/README.md +119 -60
- package/package.json +9 -9
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'
|
|
@@ -78,6 +59,76 @@ if (!closeResult.success) {
|
|
|
78
59
|
}
|
|
79
60
|
```
|
|
80
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
|
+
|
|
81
132
|
### Initialization options
|
|
82
133
|
|
|
83
134
|
```ts
|
|
@@ -116,31 +167,7 @@ Record common events through `audit.helper`, with the public `AuditHelper` type.
|
|
|
116
167
|
- `audit.cleanup(days)`: `days`, if provided, must be a nonnegative integer.
|
|
117
168
|
- `audit.getStats(days)`: `days`, if provided, must be a nonnegative integer.
|
|
118
169
|
|
|
119
|
-
###
|
|
120
|
-
|
|
121
|
-
Business data operations return `HaiResult<T>`. Common error codes:
|
|
122
|
-
|
|
123
|
-
| Error code | code | Description |
|
|
124
|
-
| -------------------------------- | --------------- | ------------------------------------ |
|
|
125
|
-
| `HaiAuditError.LOG_FAILED` | `hai:audit:001` | Recording failed |
|
|
126
|
-
| `HaiAuditError.QUERY_FAILED` | `hai:audit:002` | Query failed |
|
|
127
|
-
| `HaiAuditError.CLEANUP_FAILED` | `hai:audit:003` | Cleanup failed |
|
|
128
|
-
| `HaiAuditError.STATS_FAILED` | `hai:audit:004` | Aggregation failed |
|
|
129
|
-
| `HaiAuditError.INIT_IN_PROGRESS` | `hai:audit:005` | Initialization in progress |
|
|
130
|
-
| `HaiAuditError.NOT_INITIALIZED` | `hai:audit:010` | Module not initialized |
|
|
131
|
-
| `HaiAuditError.CONFIG_ERROR` | `hai:audit:012` | Invalid configuration |
|
|
132
|
-
| `HaiAuditError.BACKUP_DISABLED` | `hai:audit:020` | Backup disabled |
|
|
133
|
-
| `HaiAuditError.BACKUP_FAILED` | `hai:audit:021` | Backup or verification failed |
|
|
134
|
-
| `HaiAuditError.BACKUP_INVALID` | `hai:audit:022` | Invalid backup input |
|
|
135
|
-
| `HaiAuditError.BACKUP_CONFLICT` | `hai:audit:023` | Backup ID/export conditions conflict |
|
|
136
|
-
| `HaiAuditError.ALERTS_DISABLED` | `hai:audit:024` | Alerts disabled |
|
|
137
|
-
| `HaiAuditError.ALERTS_FAILED` | `hai:audit:025` | Alert check or notification failed |
|
|
138
|
-
|
|
139
|
-
> Note: `audit.close()` also returns `HaiResult<void>`. Email details in `audit.helper.passwordResetRequest()` are hidden by the default business privacy settings.
|
|
140
|
-
|
|
141
|
-
`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.
|
|
142
|
-
|
|
143
|
-
## Event context, privacy and retention
|
|
170
|
+
### Event context, privacy and retention
|
|
144
171
|
|
|
145
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.
|
|
146
173
|
|
|
@@ -158,7 +185,7 @@ Stop old writers and back up before upgrading. `migrateAudit({ dryRun: true })`
|
|
|
158
185
|
|
|
159
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.
|
|
160
187
|
|
|
161
|
-
|
|
188
|
+
### Private backups and scheduled archives
|
|
162
189
|
|
|
163
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.
|
|
164
191
|
|
|
@@ -185,7 +212,7 @@ if (plan) {
|
|
|
185
212
|
|
|
186
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.
|
|
187
214
|
|
|
188
|
-
|
|
215
|
+
### Graded anomaly alerts
|
|
189
216
|
|
|
190
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.
|
|
191
218
|
|
|
@@ -195,7 +222,41 @@ Messages include only rule/target IDs, level, count and window, without event de
|
|
|
195
222
|
|
|
196
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.
|
|
197
224
|
|
|
198
|
-
##
|
|
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
|
|
199
260
|
|
|
200
261
|
```bash
|
|
201
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'
|
|
@@ -78,21 +59,75 @@ if (!closeResult.success) {
|
|
|
78
59
|
}
|
|
79
60
|
```
|
|
80
61
|
|
|
81
|
-
|
|
62
|
+
## 機能
|
|
82
63
|
|
|
83
|
-
|
|
84
|
-
// 默认配置(无需传参)
|
|
85
|
-
await audit.init()
|
|
64
|
+
SQLite、PostgreSQL、MySQL で読み取り契約は共通です。`createdAt` は `Date`、`details` は JSON 文字列または `null`、値のない nullable フィールドは `null` を返します。日時フィルターは書き込みと同じドライバー変換を使用します。件数は安全な整数とし、範囲外では `STATS_FAILED` を返します。
|
|
86
65
|
|
|
87
|
-
|
|
88
|
-
await audit.init({
|
|
89
|
-
userTable: 'hai_iam_users', // 用户表名(默认 'hai_iam_users')
|
|
90
|
-
userIdColumn: 'id', // 用户表主键列名(默认 'id')
|
|
91
|
-
userNameColumn: 'username', // 用户表用户名列名(默认 'username')
|
|
92
|
-
})
|
|
93
|
-
```
|
|
66
|
+
### 操作と入出力
|
|
94
67
|
|
|
95
|
-
|
|
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
|
+
- 運用統計(操作頻度、アクティブユーザーなど)
|
|
96
131
|
|
|
97
132
|
### API 一覧
|
|
98
133
|
|
|
@@ -116,31 +151,7 @@ await audit.init({
|
|
|
116
151
|
- `audit.cleanup(days)`:`days` を指定する場合は 0 以上の整数。
|
|
117
152
|
- `audit.getStats(days)`:`days` を指定する場合は 0 以上の整数。
|
|
118
153
|
|
|
119
|
-
###
|
|
120
|
-
|
|
121
|
-
業務データ操作は `HaiResult<T>` を返します。主なエラーコード:
|
|
122
|
-
|
|
123
|
-
| エラーコード | code | 説明 |
|
|
124
|
-
| -------------------------------- | --------------- | -------------------------- |
|
|
125
|
-
| `HaiAuditError.LOG_FAILED` | `hai:audit:001` | 記録に失敗 |
|
|
126
|
-
| `HaiAuditError.QUERY_FAILED` | `hai:audit:002` | 検索に失敗 |
|
|
127
|
-
| `HaiAuditError.CLEANUP_FAILED` | `hai:audit:003` | 削除に失敗 |
|
|
128
|
-
| `HaiAuditError.STATS_FAILED` | `hai:audit:004` | 集計に失敗 |
|
|
129
|
-
| `HaiAuditError.INIT_IN_PROGRESS` | `hai:audit:005` | 初期化中 |
|
|
130
|
-
| `HaiAuditError.NOT_INITIALIZED` | `hai:audit:010` | モジュールが未初期化 |
|
|
131
|
-
| `HaiAuditError.CONFIG_ERROR` | `hai:audit:012` | 設定エラー |
|
|
132
|
-
| `HaiAuditError.BACKUP_DISABLED` | `hai:audit:020` | バックアップ無効 |
|
|
133
|
-
| `HaiAuditError.BACKUP_FAILED` | `hai:audit:021` | バックアップ/検証失敗 |
|
|
134
|
-
| `HaiAuditError.BACKUP_INVALID` | `hai:audit:022` | バックアップ入力が無効 |
|
|
135
|
-
| `HaiAuditError.BACKUP_CONFLICT` | `hai:audit:023` | IDとエクスポート条件が衝突 |
|
|
136
|
-
| `HaiAuditError.ALERTS_DISABLED` | `hai:audit:024` | アラート無効 |
|
|
137
|
-
| `HaiAuditError.ALERTS_FAILED` | `hai:audit:025` | アラート検査・通知失敗 |
|
|
138
|
-
|
|
139
|
-
> 注:`audit.close()` も `HaiResult<void>` を返します。`audit.helper.passwordResetRequest()` のメール情報は既定の業務個人情報設定でマスクされます。
|
|
140
|
-
|
|
141
|
-
`audit.init()` は自動建表とリポジトリーの準備完了を待って成功します。DDL 失敗時は `isInitialized=false` のままで、DB を修正後に再試行できます。独自 JOIN・統計・削除も同じ準備完了を待ちます。初期化中の close は遅れた公開を無効化します。init の HaiResult を確認後に記録・検索し、共有 DB の接続は所有しないため audit の終了後に DB を終了します。
|
|
142
|
-
|
|
143
|
-
## イベント文脈、個人情報と保持
|
|
154
|
+
### イベント文脈、個人情報と保持
|
|
144
155
|
|
|
145
156
|
監査 createdAt、アラート窓、アーカイブ終了時刻はノード時刻ではなく DB 時刻を共用します。バックアップ/アラート定時タスクは永続的な重複排除の保証により冪等を宣言し、失敗を非冪等の不明タスクとして後続スケジュールを阻止しません。
|
|
146
157
|
|
|
@@ -158,7 +169,7 @@ await audit.init({
|
|
|
158
169
|
|
|
159
170
|
マスキングは項目全体に適用し、オブジェクト、配列、独自 JSON 変換の機密値も隠します。未初期化または close 後の capture は未初期化エラーを返し、初期化済みモジュールで capture を無効にした場合だけ自動イベントを省略します。
|
|
160
171
|
|
|
161
|
-
|
|
172
|
+
### 非公開バックアップと定時アーカイブ
|
|
162
173
|
|
|
163
174
|
`backup.enabled` は既定で無効です。RelDB を先に初期化し、初期化済み StorageFunctions を `audit.init({ storage, backup: { enabled: true } })` に渡します。batchSize は走査件数(既定200)、maxRecordBytes は UTF-8 一行の上限(既定1 MiB)です。上限超過は失敗し、元の監査証拠は切り詰めません。
|
|
164
175
|
|
|
@@ -185,7 +196,7 @@ if (plan) {
|
|
|
185
196
|
|
|
186
197
|
ホストが audit/scheduler と検証済み schedulerSettings を提供し、Audit/Storage/RelDB を初期化済みとします。非公開ストレージを使い、バックアップ有効時は S3 publicUrl 設定を拒否します。バケット/CDN のアクセス制限も必要です。公開ファイル入口は指定資源のみを許可し、example/fullstack は正規のアバターパスだけを公開します。アーカイブの取得には監査の認可入口を使い、無効化後も既存ファイルは非公開のままです。
|
|
187
198
|
|
|
188
|
-
|
|
199
|
+
### 等級別の異常アラート
|
|
189
200
|
|
|
190
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 に登録済みである必要があります。業務ロールはアプリ側で決定します。
|
|
191
202
|
|
|
@@ -195,6 +206,54 @@ if (plan) {
|
|
|
195
206
|
|
|
196
207
|
alerts.schedule は独立して有効化でき、既定は毎分・UTC。audit.schedulerPlan は有効なバックアップ/アラートをまとめ、ホストが Scheduler に明示的に渡します。自動タスクがなければ null。検査失敗または report.failed>0 はタスク失敗です。Scheduler を先に停止し、次に Audit/Reach を閉じます。Audit は新規取得を取消し、Reach の Provider タイムアウト内で実行中通知を待機し、ホスト Reach は閉じません。DB/監査失敗は HaiResult の失敗、通知失敗は成功レポートの failed に現れるため、呼出側で確認します。
|
|
197
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
|
+
|
|
198
257
|
## 開発とテスト
|
|
199
258
|
|
|
200
259
|
```bash
|
package/README.md
CHANGED
|
@@ -4,33 +4,14 @@
|
|
|
4
4
|
|
|
5
5
|
[框架首页](../../README.md) · 相关模块:[@h-ai/core](../core/README.md) · [@h-ai/reldb](../reldb/README.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'
|
|
@@ -78,21 +59,75 @@ if (!closeResult.success) {
|
|
|
78
59
|
}
|
|
79
60
|
```
|
|
80
61
|
|
|
81
|
-
|
|
62
|
+
## 功能
|
|
82
63
|
|
|
83
|
-
|
|
84
|
-
// 默认配置(无需传参)
|
|
85
|
-
await audit.init()
|
|
64
|
+
SQLite、PostgreSQL、MySQL 的读取结果保持同一契约:`createdAt` 为 `Date`,`details` 为 JSON 字符串或 `null`,缺失的可空字段返回 `null`。日期筛选与写入使用相同的驱动日期转换;统计数量为安全整数,超出范围返回 `STATS_FAILED`。
|
|
86
65
|
|
|
87
|
-
|
|
88
|
-
await audit.init({
|
|
89
|
-
userTable: 'hai_iam_users', // 用户表名(默认 'hai_iam_users')
|
|
90
|
-
userIdColumn: 'id', // 用户表主键列名(默认 'id')
|
|
91
|
-
userNameColumn: 'username', // 用户表用户名列名(默认 'username')
|
|
92
|
-
})
|
|
93
|
-
```
|
|
66
|
+
### 功能输入输出
|
|
94
67
|
|
|
95
|
-
|
|
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
|
+
- 运营数据统计(操作频次、活跃用户等)
|
|
96
131
|
|
|
97
132
|
### API 概览
|
|
98
133
|
|
|
@@ -116,31 +151,7 @@ await audit.init({
|
|
|
116
151
|
- `audit.cleanup(days)`:`days`(如传入)必须为非负整数。
|
|
117
152
|
- `audit.getStats(days)`:`days`(如传入)必须为非负整数。
|
|
118
153
|
|
|
119
|
-
###
|
|
120
|
-
|
|
121
|
-
业务数据操作返回 `HaiResult<T>`,常用错误码如下:
|
|
122
|
-
|
|
123
|
-
| 错误码 | code | 说明 |
|
|
124
|
-
| -------------------------------- | --------------- | ---------------------- |
|
|
125
|
-
| `HaiAuditError.LOG_FAILED` | `hai:audit:001` | 记录失败 |
|
|
126
|
-
| `HaiAuditError.QUERY_FAILED` | `hai:audit:002` | 查询失败 |
|
|
127
|
-
| `HaiAuditError.CLEANUP_FAILED` | `hai:audit:003` | 清理失败 |
|
|
128
|
-
| `HaiAuditError.STATS_FAILED` | `hai:audit:004` | 统计失败 |
|
|
129
|
-
| `HaiAuditError.INIT_IN_PROGRESS` | `hai:audit:005` | 初始化进行中 |
|
|
130
|
-
| `HaiAuditError.NOT_INITIALIZED` | `hai:audit:010` | 模块未初始化 |
|
|
131
|
-
| `HaiAuditError.CONFIG_ERROR` | `hai:audit:012` | 配置错误 |
|
|
132
|
-
| `HaiAuditError.BACKUP_DISABLED` | `hai:audit:020` | 备份未启用 |
|
|
133
|
-
| `HaiAuditError.BACKUP_FAILED` | `hai:audit:021` | 备份或校验失败 |
|
|
134
|
-
| `HaiAuditError.BACKUP_INVALID` | `hai:audit:022` | 备份输入无效 |
|
|
135
|
-
| `HaiAuditError.BACKUP_CONFLICT` | `hai:audit:023` | 备份编号与导出条件冲突 |
|
|
136
|
-
| `HaiAuditError.ALERTS_DISABLED` | `hai:audit:024` | 告警未启用 |
|
|
137
|
-
| `HaiAuditError.ALERTS_FAILED` | `hai:audit:025` | 告警检查或通知失败 |
|
|
138
|
-
|
|
139
|
-
> 说明:`audit.close()` 也返回 `HaiResult<void>`;`audit.helper.passwordResetRequest()` 的邮箱详情默认经过业务隐私脱敏。
|
|
140
|
-
|
|
141
|
-
`audit.init()` 会等待自动建表和仓库就绪才返回成功;DDL 失败保持 `isInitialized=false`,修正数据库后可重试。自定义 JOIN、统计和清理也使用同一就绪屏障;初始化期间关闭会使迟到结果失效。先检查 init 的 HaiResult,再立即记录或查询;audit 不拥有共享 RelDB 的连接,关闭 audit 后再关闭数据库。
|
|
142
|
-
|
|
143
|
-
## 事件上下文、隐私与保留
|
|
154
|
+
### 事件上下文、隐私与保留
|
|
144
155
|
|
|
145
156
|
审计 createdAt、告警窗口与归档截止共用数据库时钟,不以各节点系统钟作为共享真值。备份与告警调度任务使用已验证的持久去重保障声明幂等;失败不会被错误地当作非幂等未知任务而阻塞后续调度。
|
|
146
157
|
|
|
@@ -158,7 +169,7 @@ await audit.init({
|
|
|
158
169
|
|
|
159
170
|
脱敏匹配整个字段:对象、数组以及自定义 JSON 投影内的敏感值同样隐藏。关闭或尚未初始化 Audit 时,capture 返回未初始化失败;只有已初始化模块的关闭采集配置才跳过自动事件。
|
|
160
171
|
|
|
161
|
-
|
|
172
|
+
### 私有备份与定时归档
|
|
162
173
|
|
|
163
174
|
`backup.enabled` 默认关闭。开启时向 `audit.init({ storage, backup: { enabled: true } })` 注入已经初始化的 `StorageFunctions`;数据库仍先初始化。`backup.batchSize` 控制扫描批量(默认200),`maxRecordBytes` 限制单条 UTF-8 记录(默认1 MiB),超限返回失败并保留原始审计,不截断证据。
|
|
164
175
|
|
|
@@ -185,7 +196,7 @@ if (plan) {
|
|
|
185
196
|
|
|
186
197
|
上例由宿主导入 `audit`、`scheduler` 并提供已校验的 schedulerSettings,Audit/Storage/RelDB 已初始化。归档使用私有存储,开启备份时拒绝配置了公开 publicUrl 的 S3;部署仍须限制桶/CDN访问。公开静态文件入口应仅开放指定资源;管理示例与 fullstack 仅公开规范头像路径,如提供归档下载,须通过审计授权接口处理,关闭备份也不改变已有文件的私有边界。
|
|
187
198
|
|
|
188
|
-
|
|
199
|
+
### 分级异常告警
|
|
189
200
|
|
|
190
201
|
`alerts.enabled` 默认关闭。开启时注入已初始化的 Reach:`audit.init({ reach, alerts: { enabled: true, rules: [...] } })`。规则通过稳定 id、actions(精确事件名)、可选 resource、outcomes、minimumSeverity 筛选事件,threshold/windowSeconds 指定固定窗口阈值,severity 指定通知等级,targets 中的 id/provider/to 指定人员或目标。默认窗口300秒,范围60–86400秒;默认仅失败/拒绝,空 outcomes 表示所有结果。规则和目标 id 必须各自唯一;provider 须已在 Reach 注册。不将具体业务角色写入框架。
|
|
191
202
|
|
|
@@ -195,13 +206,61 @@ if (plan) {
|
|
|
195
206
|
|
|
196
207
|
`alerts.schedule` 可独立启用,默认每分钟、UTC。`audit.schedulerPlan` 合并已启用的备份和告警任务,由宿主显式交给 Scheduler;计划没有自动任务时为 null。调度回调在检查失败或 failed>0 时准确失败。先关闭 Scheduler,再关闭 Audit 和 Reach;关闭 Audit 取消后续领取并等待在途通知完成(受 Reach Provider 超时约束),不关闭宿主 Reach。数据库查询/审计失败返回失败;通知业务失败在成功检查报告的 failed 字段体现,调用方必须检查。
|
|
197
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`,失败按本模块错误定义与安全提示处理,服务端保留错误码、关联编号和脱敏原因。同步工具、工厂、流迭代及生命周期按各自签名处理,不把 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` | 备份编号与导出条件冲突 |
|
|
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`,修正数据库后可重试。自定义 JOIN、统计和清理也使用同一就绪屏障;初始化期间关闭会使迟到结果失效。先检查 init 的 HaiResult,再立即记录或查询;audit 不拥有共享 RelDB 的连接,关闭 audit 后再关闭数据库。
|
|
256
|
+
|
|
198
257
|
## 开发测试
|
|
199
258
|
|
|
200
259
|
```bash
|
|
201
260
|
pnpm --filter @h-ai/audit test
|
|
202
261
|
```
|
|
203
262
|
|
|
204
|
-
审计源码示例明确先初始化 RelDB、检查审计写入结果,再按依赖反序检查关闭结果;参见[模块 JSDoc 约定](../../.agents/instructions/module-conventions.md#jsdoc-与示例验证)
|
|
263
|
+
审计源码示例明确先初始化 RelDB、检查审计写入结果,再按依赖反序检查关闭结果;参见[模块 JSDoc 约定](../../.agents/instructions/module-conventions.md#jsdoc-与示例验证).
|
|
205
264
|
|
|
206
265
|
## 许可证
|
|
207
266
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@h-ai/audit",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.0.0-beta.
|
|
4
|
+
"version": "1.0.0-beta.20",
|
|
5
5
|
"description": "Hai Framework audit logging module.",
|
|
6
6
|
"license": "Apache-2.0",
|
|
7
7
|
"exports": {
|
|
@@ -23,9 +23,9 @@
|
|
|
23
23
|
"node": "^22.23.4 || ^24.22.1 || ^26.12.1"
|
|
24
24
|
},
|
|
25
25
|
"peerDependencies": {
|
|
26
|
-
"@h-ai/reach": "1.0.0-beta.
|
|
27
|
-
"@h-ai/scheduler": "1.0.0-beta.
|
|
28
|
-
"@h-ai/storage": "1.0.0-beta.
|
|
26
|
+
"@h-ai/reach": "1.0.0-beta.20",
|
|
27
|
+
"@h-ai/scheduler": "1.0.0-beta.20",
|
|
28
|
+
"@h-ai/storage": "1.0.0-beta.20"
|
|
29
29
|
},
|
|
30
30
|
"peerDependenciesMeta": {
|
|
31
31
|
"@h-ai/reach": {
|
|
@@ -39,14 +39,14 @@
|
|
|
39
39
|
}
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@h-ai/core": "1.0.0-beta.
|
|
43
|
-
"@h-ai/reldb": "1.0.0-beta.
|
|
42
|
+
"@h-ai/core": "1.0.0-beta.20",
|
|
43
|
+
"@h-ai/reldb": "1.0.0-beta.20",
|
|
44
44
|
"zod": "^4.6.7"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
|
-
"@h-ai/reach": "1.0.0-beta.
|
|
48
|
-
"@h-ai/scheduler": "1.0.0-beta.
|
|
49
|
-
"@h-ai/storage": "1.0.0-beta.
|
|
47
|
+
"@h-ai/reach": "1.0.0-beta.20",
|
|
48
|
+
"@h-ai/scheduler": "1.0.0-beta.20",
|
|
49
|
+
"@h-ai/storage": "1.0.0-beta.20",
|
|
50
50
|
"@types/node": "^26.6.6",
|
|
51
51
|
"rimraf": "^6.1.4",
|
|
52
52
|
"testcontainers": "^12.2.1",
|