@objectstack/plugin-audit 7.3.0 → 7.4.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/dist/index.mjs CHANGED
@@ -1,5 +1,1358 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropNames = Object.getOwnPropertyNames;
3
+ var __esm = (fn, res) => function __init() {
4
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
5
+ };
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+
11
+ // src/translations/en.objects.generated.ts
12
+ var enObjects;
13
+ var init_en_objects_generated = __esm({
14
+ "src/translations/en.objects.generated.ts"() {
15
+ "use strict";
16
+ enObjects = {
17
+ sys_audit_log: {
18
+ label: "Audit Log",
19
+ pluralLabel: "Audit Logs",
20
+ description: "Immutable audit trail for platform events",
21
+ fields: {
22
+ created_at: {
23
+ label: "Timestamp"
24
+ },
25
+ action: {
26
+ label: "Action",
27
+ help: "Action type (snake_case)",
28
+ options: {
29
+ create: "create",
30
+ update: "update",
31
+ delete: "delete",
32
+ restore: "restore",
33
+ login: "login",
34
+ logout: "logout",
35
+ permission_change: "permission_change",
36
+ config_change: "config_change",
37
+ export: "export",
38
+ import: "import"
39
+ }
40
+ },
41
+ user_id: {
42
+ label: "Actor",
43
+ help: "User who performed the action (null for system actions)"
44
+ },
45
+ object_name: {
46
+ label: "Object",
47
+ help: "Target object (e.g. sys_user, project_task)"
48
+ },
49
+ record_id: {
50
+ label: "Record ID",
51
+ help: "ID of the affected record"
52
+ },
53
+ old_value: {
54
+ label: "Old Value",
55
+ help: "JSON-serialized previous state"
56
+ },
57
+ new_value: {
58
+ label: "New Value",
59
+ help: "JSON-serialized new state"
60
+ },
61
+ ip_address: {
62
+ label: "IP Address"
63
+ },
64
+ user_agent: {
65
+ label: "User Agent"
66
+ },
67
+ tenant_id: {
68
+ label: "Tenant",
69
+ help: "Tenant context for multi-tenant isolation"
70
+ },
71
+ metadata: {
72
+ label: "Metadata",
73
+ help: "JSON-serialized additional context"
74
+ },
75
+ id: {
76
+ label: "Audit Log ID"
77
+ }
78
+ },
79
+ _views: {
80
+ recent: {
81
+ label: "Recent"
82
+ },
83
+ writes_only: {
84
+ label: "Writes"
85
+ },
86
+ auth_events: {
87
+ label: "Auth"
88
+ },
89
+ config_changes: {
90
+ label: "Config"
91
+ },
92
+ all_events: {
93
+ label: "All"
94
+ }
95
+ }
96
+ },
97
+ sys_activity: {
98
+ label: "Activity",
99
+ pluralLabel: "Activities",
100
+ description: "Recent activity stream entries (lightweight, denormalized)",
101
+ fields: {
102
+ id: {
103
+ label: "Activity ID"
104
+ },
105
+ timestamp: {
106
+ label: "Timestamp"
107
+ },
108
+ type: {
109
+ label: "Type",
110
+ options: {
111
+ created: "created",
112
+ updated: "updated",
113
+ deleted: "deleted",
114
+ commented: "commented",
115
+ mentioned: "mentioned",
116
+ shared: "shared",
117
+ assigned: "assigned",
118
+ completed: "completed",
119
+ login: "login",
120
+ logout: "logout",
121
+ system: "system"
122
+ }
123
+ },
124
+ summary: {
125
+ label: "Summary",
126
+ help: "Human-readable one-line summary"
127
+ },
128
+ actor_id: {
129
+ label: "Actor"
130
+ },
131
+ actor_name: {
132
+ label: "Actor Name"
133
+ },
134
+ actor_avatar_url: {
135
+ label: "Actor Avatar"
136
+ },
137
+ object_name: {
138
+ label: "Object",
139
+ help: "Target object short name (e.g. account, sys_user)"
140
+ },
141
+ record_id: {
142
+ label: "Record ID"
143
+ },
144
+ record_label: {
145
+ label: "Record Label",
146
+ help: "Display label of the target record at write time"
147
+ },
148
+ url: {
149
+ label: "URL",
150
+ help: "Optional deep-link to the activity target"
151
+ },
152
+ environment_id: {
153
+ label: "Project",
154
+ help: "Environment context (multi-environment deployments)"
155
+ },
156
+ metadata: {
157
+ label: "Metadata",
158
+ help: "JSON-serialized additional context"
159
+ }
160
+ }
161
+ },
162
+ sys_comment: {
163
+ label: "Comment",
164
+ pluralLabel: "Comments",
165
+ description: "Threaded comments attached to records via thread_id",
166
+ fields: {
167
+ id: {
168
+ label: "Comment ID"
169
+ },
170
+ thread_id: {
171
+ label: "Thread",
172
+ help: "Thread identifier \u2014 conventionally `{object}:{record_id}` (e.g. `sys_user:abc123`)"
173
+ },
174
+ parent_id: {
175
+ label: "Parent Comment",
176
+ help: "Optional parent comment for nested replies"
177
+ },
178
+ reply_count: {
179
+ label: "Reply Count"
180
+ },
181
+ author_id: {
182
+ label: "Author"
183
+ },
184
+ author_name: {
185
+ label: "Author Name"
186
+ },
187
+ author_avatar_url: {
188
+ label: "Author Avatar"
189
+ },
190
+ body: {
191
+ label: "Body",
192
+ help: "Comment text (Markdown supported)"
193
+ },
194
+ mentions: {
195
+ label: "Mentions",
196
+ help: "JSON array of @mention objects"
197
+ },
198
+ reactions: {
199
+ label: "Reactions",
200
+ help: "JSON array of emoji reaction objects"
201
+ },
202
+ is_edited: {
203
+ label: "Edited"
204
+ },
205
+ edited_at: {
206
+ label: "Edited At"
207
+ },
208
+ visibility: {
209
+ label: "Visibility",
210
+ options: {
211
+ public: "public",
212
+ internal: "internal",
213
+ private: "private"
214
+ }
215
+ },
216
+ created_at: {
217
+ label: "Created At"
218
+ },
219
+ updated_at: {
220
+ label: "Updated At"
221
+ }
222
+ }
223
+ }
224
+ };
225
+ }
226
+ });
227
+
228
+ // src/translations/zh-CN.objects.generated.ts
229
+ var zhCNObjects;
230
+ var init_zh_CN_objects_generated = __esm({
231
+ "src/translations/zh-CN.objects.generated.ts"() {
232
+ "use strict";
233
+ zhCNObjects = {
234
+ sys_audit_log: {
235
+ label: "\u5BA1\u8BA1\u65E5\u5FD7",
236
+ pluralLabel: "\u5BA1\u8BA1\u65E5\u5FD7",
237
+ description: "\u5E73\u53F0\u4E8B\u4EF6\u7684\u4E0D\u53EF\u53D8\u5BA1\u8BA1\u8FFD\u8E2A",
238
+ fields: {
239
+ created_at: {
240
+ label: "\u65F6\u95F4\u6233"
241
+ },
242
+ action: {
243
+ label: "\u64CD\u4F5C",
244
+ help: "\u64CD\u4F5C\u7C7B\u578B\uFF08snake_case\uFF09",
245
+ options: {
246
+ create: "\u521B\u5EFA",
247
+ update: "\u66F4\u65B0",
248
+ delete: "\u5220\u9664",
249
+ restore: "\u6062\u590D",
250
+ login: "\u767B\u5F55",
251
+ logout: "\u767B\u51FA",
252
+ permission_change: "\u6743\u9650\u53D8\u66F4",
253
+ config_change: "\u914D\u7F6E\u53D8\u66F4",
254
+ export: "\u5BFC\u51FA",
255
+ import: "\u5BFC\u5165"
256
+ }
257
+ },
258
+ user_id: {
259
+ label: "\u6267\u884C\u4EBA",
260
+ help: "\u6267\u884C\u8BE5\u64CD\u4F5C\u7684\u7528\u6237\uFF08\u7CFB\u7EDF\u64CD\u4F5C\u65F6\u4E3A null\uFF09"
261
+ },
262
+ object_name: {
263
+ label: "\u5BF9\u8C61",
264
+ help: "\u76EE\u6807\u5BF9\u8C61\uFF08\u4F8B\u5982 sys_user\u3001project_task\uFF09"
265
+ },
266
+ record_id: {
267
+ label: "\u8BB0\u5F55 ID",
268
+ help: "\u53D7\u5F71\u54CD\u8BB0\u5F55\u7684 ID"
269
+ },
270
+ old_value: {
271
+ label: "\u65E7\u503C",
272
+ help: "\u65E7\u72B6\u6001\u7684 JSON \u5E8F\u5217\u5316\u5185\u5BB9"
273
+ },
274
+ new_value: {
275
+ label: "\u65B0\u503C",
276
+ help: "\u65B0\u72B6\u6001\u7684 JSON \u5E8F\u5217\u5316\u5185\u5BB9"
277
+ },
278
+ ip_address: {
279
+ label: "IP \u5730\u5740"
280
+ },
281
+ user_agent: {
282
+ label: "\u7528\u6237\u4EE3\u7406"
283
+ },
284
+ tenant_id: {
285
+ label: "\u79DF\u6237",
286
+ help: "\u7528\u4E8E\u591A\u79DF\u6237\u9694\u79BB\u7684\u79DF\u6237\u4E0A\u4E0B\u6587"
287
+ },
288
+ metadata: {
289
+ label: "\u5143\u6570\u636E",
290
+ help: "\u9644\u52A0\u4E0A\u4E0B\u6587\u7684 JSON \u5E8F\u5217\u5316\u5185\u5BB9"
291
+ },
292
+ id: {
293
+ label: "\u5BA1\u8BA1\u65E5\u5FD7 ID"
294
+ }
295
+ },
296
+ _views: {
297
+ recent: {
298
+ label: "\u6700\u8FD1"
299
+ },
300
+ writes_only: {
301
+ label: "\u5199\u5165"
302
+ },
303
+ auth_events: {
304
+ label: "\u8BA4\u8BC1"
305
+ },
306
+ config_changes: {
307
+ label: "\u914D\u7F6E"
308
+ },
309
+ all_events: {
310
+ label: "\u5168\u90E8"
311
+ }
312
+ }
313
+ },
314
+ sys_activity: {
315
+ label: "\u6D3B\u52A8",
316
+ pluralLabel: "\u6D3B\u52A8",
317
+ description: "\u6700\u8FD1\u6D3B\u52A8\u6D41\u6761\u76EE\uFF08\u8F7B\u91CF\u3001\u53BB\u89C4\u8303\u5316\uFF09",
318
+ fields: {
319
+ id: {
320
+ label: "\u6D3B\u52A8 ID"
321
+ },
322
+ timestamp: {
323
+ label: "\u65F6\u95F4\u6233"
324
+ },
325
+ type: {
326
+ label: "\u7C7B\u578B",
327
+ options: {
328
+ created: "\u5DF2\u521B\u5EFA",
329
+ updated: "\u5DF2\u66F4\u65B0",
330
+ deleted: "\u5DF2\u5220\u9664",
331
+ commented: "\u5DF2\u8BC4\u8BBA",
332
+ mentioned: "\u88AB\u63D0\u53CA",
333
+ shared: "\u5DF2\u5171\u4EAB",
334
+ assigned: "\u5DF2\u5206\u914D",
335
+ completed: "\u5DF2\u5B8C\u6210",
336
+ login: "\u767B\u5F55",
337
+ logout: "\u767B\u51FA",
338
+ system: "\u7CFB\u7EDF"
339
+ }
340
+ },
341
+ summary: {
342
+ label: "\u6458\u8981",
343
+ help: "\u4EBA\u7C7B\u53EF\u8BFB\u7684\u5355\u884C\u6458\u8981"
344
+ },
345
+ actor_id: {
346
+ label: "\u6267\u884C\u4EBA"
347
+ },
348
+ actor_name: {
349
+ label: "\u6267\u884C\u4EBA\u540D\u79F0"
350
+ },
351
+ actor_avatar_url: {
352
+ label: "\u6267\u884C\u4EBA\u5934\u50CF"
353
+ },
354
+ object_name: {
355
+ label: "\u5BF9\u8C61",
356
+ help: "\u76EE\u6807\u5BF9\u8C61\u77ED\u540D\u79F0\uFF08\u4F8B\u5982 account\u3001sys_user\uFF09"
357
+ },
358
+ record_id: {
359
+ label: "\u8BB0\u5F55 ID"
360
+ },
361
+ record_label: {
362
+ label: "\u8BB0\u5F55\u6807\u7B7E",
363
+ help: "\u5199\u5165\u65F6\u76EE\u6807\u8BB0\u5F55\u7684\u663E\u793A\u6807\u7B7E"
364
+ },
365
+ url: {
366
+ label: "URL",
367
+ help: "\u6307\u5411\u6D3B\u52A8\u76EE\u6807\u7684\u53EF\u9009\u6DF1\u5EA6\u94FE\u63A5"
368
+ },
369
+ environment_id: {
370
+ label: "\u9879\u76EE",
371
+ help: "\u9879\u76EE\u4E0A\u4E0B\u6587\uFF08\u591A\u9879\u76EE\u90E8\u7F72\uFF09"
372
+ },
373
+ metadata: {
374
+ label: "\u5143\u6570\u636E",
375
+ help: "\u9644\u52A0\u4E0A\u4E0B\u6587\u7684 JSON \u5E8F\u5217\u5316\u5185\u5BB9"
376
+ }
377
+ }
378
+ },
379
+ sys_comment: {
380
+ label: "\u8BC4\u8BBA",
381
+ pluralLabel: "\u8BC4\u8BBA",
382
+ description: "\u901A\u8FC7 thread_id \u9644\u52A0\u5230\u8BB0\u5F55\u7684\u7EBF\u7A0B\u5316\u8BC4\u8BBA",
383
+ fields: {
384
+ id: {
385
+ label: "\u8BC4\u8BBA ID"
386
+ },
387
+ thread_id: {
388
+ label: "\u7EBF\u7A0B",
389
+ help: "\u7EBF\u7A0B\u6807\u8BC6\u2014\u2014\u7EA6\u5B9A\u683C\u5F0F\u4E3A `{object}:{record_id}`\uFF08\u4F8B\u5982 `sys_user:abc123`\uFF09"
390
+ },
391
+ parent_id: {
392
+ label: "\u7236\u8BC4\u8BBA",
393
+ help: "\u53EF\u9009\u7684\u7236\u8BC4\u8BBA\uFF0C\u7528\u4E8E\u5D4C\u5957\u56DE\u590D"
394
+ },
395
+ reply_count: {
396
+ label: "\u56DE\u590D\u6570"
397
+ },
398
+ author_id: {
399
+ label: "\u4F5C\u8005"
400
+ },
401
+ author_name: {
402
+ label: "\u4F5C\u8005\u540D\u79F0"
403
+ },
404
+ author_avatar_url: {
405
+ label: "\u4F5C\u8005\u5934\u50CF"
406
+ },
407
+ body: {
408
+ label: "\u6B63\u6587",
409
+ help: "\u8BC4\u8BBA\u6587\u672C\uFF08\u652F\u6301 Markdown\uFF09"
410
+ },
411
+ mentions: {
412
+ label: "\u63D0\u53CA",
413
+ help: "@mention \u5BF9\u8C61\u7684 JSON \u6570\u7EC4"
414
+ },
415
+ reactions: {
416
+ label: "\u56DE\u5E94",
417
+ help: "\u8868\u60C5\u56DE\u5E94\u5BF9\u8C61\u7684 JSON \u6570\u7EC4"
418
+ },
419
+ is_edited: {
420
+ label: "\u5DF2\u7F16\u8F91"
421
+ },
422
+ edited_at: {
423
+ label: "\u7F16\u8F91\u65F6\u95F4"
424
+ },
425
+ visibility: {
426
+ label: "\u53EF\u89C1\u6027",
427
+ options: {
428
+ public: "\u516C\u5F00",
429
+ internal: "\u5185\u90E8",
430
+ private: "\u79C1\u6709"
431
+ }
432
+ },
433
+ created_at: {
434
+ label: "\u521B\u5EFA\u65F6\u95F4"
435
+ },
436
+ updated_at: {
437
+ label: "\u66F4\u65B0\u65F6\u95F4"
438
+ }
439
+ }
440
+ }
441
+ };
442
+ }
443
+ });
444
+
445
+ // src/translations/ja-JP.objects.generated.ts
446
+ var jaJPObjects;
447
+ var init_ja_JP_objects_generated = __esm({
448
+ "src/translations/ja-JP.objects.generated.ts"() {
449
+ "use strict";
450
+ jaJPObjects = {
451
+ sys_audit_log: {
452
+ label: "\u76E3\u67FB\u30ED\u30B0",
453
+ pluralLabel: "\u76E3\u67FB\u30ED\u30B0",
454
+ description: "\u30D7\u30E9\u30C3\u30C8\u30D5\u30A9\u30FC\u30E0\u30A4\u30D9\u30F3\u30C8\u306E\u4E0D\u5909\u306E\u76E3\u67FB\u8A3C\u8DE1",
455
+ fields: {
456
+ created_at: {
457
+ label: "\u30BF\u30A4\u30E0\u30B9\u30BF\u30F3\u30D7"
458
+ },
459
+ action: {
460
+ label: "\u30A2\u30AF\u30B7\u30E7\u30F3",
461
+ help: "\u30A2\u30AF\u30B7\u30E7\u30F3\u30BF\u30A4\u30D7\uFF08snake_case\uFF09",
462
+ options: {
463
+ create: "\u4F5C\u6210",
464
+ update: "\u66F4\u65B0",
465
+ delete: "\u524A\u9664",
466
+ restore: "\u5FA9\u5143",
467
+ login: "\u30ED\u30B0\u30A4\u30F3",
468
+ logout: "\u30ED\u30B0\u30A2\u30A6\u30C8",
469
+ permission_change: "\u6A29\u9650\u5909\u66F4",
470
+ config_change: "\u69CB\u6210\u5909\u66F4",
471
+ export: "\u30A8\u30AF\u30B9\u30DD\u30FC\u30C8",
472
+ import: "\u30A4\u30F3\u30DD\u30FC\u30C8"
473
+ }
474
+ },
475
+ user_id: {
476
+ label: "\u64CD\u4F5C\u8005",
477
+ help: "\u30A2\u30AF\u30B7\u30E7\u30F3\u3092\u5B9F\u884C\u3057\u305F\u30E6\u30FC\u30B6\u30FC\uFF08\u30B7\u30B9\u30C6\u30E0\u64CD\u4F5C\u306E\u5834\u5408\u306F null\uFF09"
478
+ },
479
+ object_name: {
480
+ label: "\u30AA\u30D6\u30B8\u30A7\u30AF\u30C8",
481
+ help: "\u5BFE\u8C61\u30AA\u30D6\u30B8\u30A7\u30AF\u30C8\uFF08\u4F8B: sys_user\u3001project_task\uFF09"
482
+ },
483
+ record_id: {
484
+ label: "\u30EC\u30B3\u30FC\u30C9 ID",
485
+ help: "\u5F71\u97FF\u3092\u53D7\u3051\u305F\u30EC\u30B3\u30FC\u30C9\u306E ID"
486
+ },
487
+ old_value: {
488
+ label: "\u5909\u66F4\u524D\u306E\u5024",
489
+ help: "JSON \u30B7\u30EA\u30A2\u30E9\u30A4\u30BA\u3055\u308C\u305F\u4EE5\u524D\u306E\u72B6\u614B"
490
+ },
491
+ new_value: {
492
+ label: "\u5909\u66F4\u5F8C\u306E\u5024",
493
+ help: "JSON \u30B7\u30EA\u30A2\u30E9\u30A4\u30BA\u3055\u308C\u305F\u65B0\u3057\u3044\u72B6\u614B"
494
+ },
495
+ ip_address: {
496
+ label: "IP \u30A2\u30C9\u30EC\u30B9"
497
+ },
498
+ user_agent: {
499
+ label: "\u30E6\u30FC\u30B6\u30FC\u30A8\u30FC\u30B8\u30A7\u30F3\u30C8"
500
+ },
501
+ tenant_id: {
502
+ label: "\u30C6\u30CA\u30F3\u30C8",
503
+ help: "\u30DE\u30EB\u30C1\u30C6\u30CA\u30F3\u30C8\u5206\u96E2\u306E\u305F\u3081\u306E\u30C6\u30CA\u30F3\u30C8\u30B3\u30F3\u30C6\u30AD\u30B9\u30C8"
504
+ },
505
+ metadata: {
506
+ label: "\u30E1\u30BF\u30C7\u30FC\u30BF",
507
+ help: "JSON \u30B7\u30EA\u30A2\u30E9\u30A4\u30BA\u3055\u308C\u305F\u8FFD\u52A0\u30B3\u30F3\u30C6\u30AD\u30B9\u30C8"
508
+ },
509
+ id: {
510
+ label: "\u76E3\u67FB\u30ED\u30B0 ID"
511
+ }
512
+ },
513
+ _views: {
514
+ recent: {
515
+ label: "\u6700\u8FD1"
516
+ },
517
+ writes_only: {
518
+ label: "\u66F8\u304D\u8FBC\u307F"
519
+ },
520
+ auth_events: {
521
+ label: "\u8A8D\u8A3C"
522
+ },
523
+ config_changes: {
524
+ label: "\u69CB\u6210\u5909\u66F4"
525
+ },
526
+ all_events: {
527
+ label: "\u3059\u3079\u3066"
528
+ }
529
+ }
530
+ },
531
+ sys_activity: {
532
+ label: "\u30A2\u30AF\u30C6\u30A3\u30D3\u30C6\u30A3",
533
+ pluralLabel: "\u30A2\u30AF\u30C6\u30A3\u30D3\u30C6\u30A3",
534
+ description: "\u6700\u8FD1\u306E\u30A2\u30AF\u30C6\u30A3\u30D3\u30C6\u30A3\u30B9\u30C8\u30EA\u30FC\u30E0\u30A8\u30F3\u30C8\u30EA\uFF08\u8EFD\u91CF\u3001\u975E\u6B63\u898F\u5316\uFF09",
535
+ fields: {
536
+ id: {
537
+ label: "\u30A2\u30AF\u30C6\u30A3\u30D3\u30C6\u30A3 ID"
538
+ },
539
+ timestamp: {
540
+ label: "\u30BF\u30A4\u30E0\u30B9\u30BF\u30F3\u30D7"
541
+ },
542
+ type: {
543
+ label: "\u30BF\u30A4\u30D7",
544
+ options: {
545
+ created: "\u4F5C\u6210",
546
+ updated: "\u66F4\u65B0",
547
+ deleted: "\u524A\u9664",
548
+ commented: "\u30B3\u30E1\u30F3\u30C8",
549
+ mentioned: "\u30E1\u30F3\u30B7\u30E7\u30F3",
550
+ shared: "\u5171\u6709",
551
+ assigned: "\u5272\u308A\u5F53\u3066",
552
+ completed: "\u5B8C\u4E86",
553
+ login: "\u30ED\u30B0\u30A4\u30F3",
554
+ logout: "\u30ED\u30B0\u30A2\u30A6\u30C8",
555
+ system: "\u30B7\u30B9\u30C6\u30E0"
556
+ }
557
+ },
558
+ summary: {
559
+ label: "\u30B5\u30DE\u30EA\u30FC",
560
+ help: "\u5224\u5225\u3057\u3084\u3059\u3044 1 \u884C\u30B5\u30DE\u30EA\u30FC"
561
+ },
562
+ actor_id: {
563
+ label: "\u64CD\u4F5C\u8005"
564
+ },
565
+ actor_name: {
566
+ label: "\u64CD\u4F5C\u8005\u540D"
567
+ },
568
+ actor_avatar_url: {
569
+ label: "\u64CD\u4F5C\u8005\u30A2\u30D0\u30BF\u30FC"
570
+ },
571
+ object_name: {
572
+ label: "\u30AA\u30D6\u30B8\u30A7\u30AF\u30C8",
573
+ help: "\u5BFE\u8C61\u30AA\u30D6\u30B8\u30A7\u30AF\u30C8\u306E\u77ED\u3044\u540D\u524D\uFF08\u4F8B: account\u3001sys_user\uFF09"
574
+ },
575
+ record_id: {
576
+ label: "\u30EC\u30B3\u30FC\u30C9 ID"
577
+ },
578
+ record_label: {
579
+ label: "\u30EC\u30B3\u30FC\u30C9\u8868\u793A\u540D",
580
+ help: "\u66F8\u304D\u8FBC\u307F\u6642\u70B9\u306E\u5BFE\u8C61\u30EC\u30B3\u30FC\u30C9\u306E\u8868\u793A\u540D"
581
+ },
582
+ url: {
583
+ label: "URL",
584
+ help: "\u30A2\u30AF\u30C6\u30A3\u30D3\u30C6\u30A3\u30BF\u30FC\u30B2\u30C3\u30C8\u3078\u306E\u30AA\u30D7\u30B7\u30E7\u30F3\u306E\u30C7\u30A3\u30FC\u30D7\u30EA\u30F3\u30AF"
585
+ },
586
+ environment_id: {
587
+ label: "\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8",
588
+ help: "\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u30B3\u30F3\u30C6\u30AD\u30B9\u30C8\uFF08\u30DE\u30EB\u30C1\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u30C7\u30D7\u30ED\u30A4\u30E1\u30F3\u30C8\uFF09"
589
+ },
590
+ metadata: {
591
+ label: "\u30E1\u30BF\u30C7\u30FC\u30BF",
592
+ help: "JSON \u30B7\u30EA\u30A2\u30E9\u30A4\u30BA\u3055\u308C\u305F\u8FFD\u52A0\u30B3\u30F3\u30C6\u30AD\u30B9\u30C8"
593
+ }
594
+ }
595
+ },
596
+ sys_comment: {
597
+ label: "\u30B3\u30E1\u30F3\u30C8",
598
+ pluralLabel: "\u30B3\u30E1\u30F3\u30C8",
599
+ description: "thread_id \u3092\u4ECB\u3057\u3066\u30EC\u30B3\u30FC\u30C9\u306B\u6DFB\u4ED8\u3055\u308C\u305F\u30B9\u30EC\u30C3\u30C9\u30B3\u30E1\u30F3\u30C8",
600
+ fields: {
601
+ id: {
602
+ label: "\u30B3\u30E1\u30F3\u30C8 ID"
603
+ },
604
+ thread_id: {
605
+ label: "\u30B9\u30EC\u30C3\u30C9",
606
+ help: "\u30B9\u30EC\u30C3\u30C9\u8B58\u5225\u5B50 \u2014 \u901A\u5E38\u306F `{object}:{record_id}`\uFF08\u4F8B: `sys_user:abc123`\uFF09"
607
+ },
608
+ parent_id: {
609
+ label: "\u89AA\u30B3\u30E1\u30F3\u30C8",
610
+ help: "\u30CD\u30B9\u30C8\u3057\u305F\u8FD4\u4FE1\u7528\u306E\u30AA\u30D7\u30B7\u30E7\u30F3\u306E\u89AA\u30B3\u30E1\u30F3\u30C8"
611
+ },
612
+ reply_count: {
613
+ label: "\u8FD4\u4FE1\u6570"
614
+ },
615
+ author_id: {
616
+ label: "\u6295\u7A3F\u8005"
617
+ },
618
+ author_name: {
619
+ label: "\u6295\u7A3F\u8005\u540D"
620
+ },
621
+ author_avatar_url: {
622
+ label: "\u6295\u7A3F\u8005\u30A2\u30D0\u30BF\u30FC"
623
+ },
624
+ body: {
625
+ label: "\u672C\u6587",
626
+ help: "\u30B3\u30E1\u30F3\u30C8\u30C6\u30AD\u30B9\u30C8\uFF08Markdown \u5BFE\u5FDC\uFF09"
627
+ },
628
+ mentions: {
629
+ label: "\u30E1\u30F3\u30B7\u30E7\u30F3",
630
+ help: "@\u30E1\u30F3\u30B7\u30E7\u30F3\u30AA\u30D6\u30B8\u30A7\u30AF\u30C8\u306E JSON \u914D\u5217"
631
+ },
632
+ reactions: {
633
+ label: "\u30EA\u30A2\u30AF\u30B7\u30E7\u30F3",
634
+ help: "\u7D75\u6587\u5B57\u30EA\u30A2\u30AF\u30B7\u30E7\u30F3\u30AA\u30D6\u30B8\u30A7\u30AF\u30C8\u306E JSON \u914D\u5217"
635
+ },
636
+ is_edited: {
637
+ label: "\u7DE8\u96C6\u6E08\u307F"
638
+ },
639
+ edited_at: {
640
+ label: "\u7DE8\u96C6\u65E5\u6642"
641
+ },
642
+ visibility: {
643
+ label: "\u516C\u958B\u7BC4\u56F2",
644
+ options: {
645
+ public: "\u516C\u958B",
646
+ internal: "\u5185\u90E8",
647
+ private: "\u975E\u516C\u958B"
648
+ }
649
+ },
650
+ created_at: {
651
+ label: "\u4F5C\u6210\u65E5\u6642"
652
+ },
653
+ updated_at: {
654
+ label: "\u66F4\u65B0\u65E5\u6642"
655
+ }
656
+ }
657
+ }
658
+ };
659
+ }
660
+ });
661
+
662
+ // src/translations/es-ES.objects.generated.ts
663
+ var esESObjects;
664
+ var init_es_ES_objects_generated = __esm({
665
+ "src/translations/es-ES.objects.generated.ts"() {
666
+ "use strict";
667
+ esESObjects = {
668
+ sys_audit_log: {
669
+ label: "Registro de auditor\xEDa",
670
+ pluralLabel: "Registros de auditor\xEDa",
671
+ description: "Registro de auditor\xEDa inmutable para eventos de la plataforma",
672
+ fields: {
673
+ created_at: {
674
+ label: "Marca temporal"
675
+ },
676
+ action: {
677
+ label: "Acci\xF3n",
678
+ help: "Tipo de acci\xF3n (snake_case).",
679
+ options: {
680
+ create: "Crear",
681
+ update: "Actualizar",
682
+ delete: "Eliminar",
683
+ restore: "Restaurar",
684
+ login: "Inicio de sesi\xF3n",
685
+ logout: "Cierre de sesi\xF3n",
686
+ permission_change: "Cambio de permisos",
687
+ config_change: "Cambio de configuraci\xF3n",
688
+ export: "Exportar",
689
+ import: "Importar"
690
+ }
691
+ },
692
+ user_id: {
693
+ label: "Actor",
694
+ help: "Usuario que realiz\xF3 la acci\xF3n (null para acciones del sistema)."
695
+ },
696
+ object_name: {
697
+ label: "Objeto",
698
+ help: "Objeto de destino (p. ej. sys_user, project_task)."
699
+ },
700
+ record_id: {
701
+ label: "ID de registro",
702
+ help: "ID del registro afectado."
703
+ },
704
+ old_value: {
705
+ label: "Valor anterior",
706
+ help: "Estado anterior serializado en JSON."
707
+ },
708
+ new_value: {
709
+ label: "Valor nuevo",
710
+ help: "Estado nuevo serializado en JSON."
711
+ },
712
+ ip_address: {
713
+ label: "Direcci\xF3n IP"
714
+ },
715
+ user_agent: {
716
+ label: "Agente de usuario"
717
+ },
718
+ tenant_id: {
719
+ label: "Inquilino",
720
+ help: "Contexto del tenant para el aislamiento multi-tenant."
721
+ },
722
+ metadata: {
723
+ label: "Metadatos",
724
+ help: "Contexto adicional serializado en JSON."
725
+ },
726
+ id: {
727
+ label: "ID de registro de auditor\xEDa"
728
+ }
729
+ },
730
+ _views: {
731
+ recent: {
732
+ label: "Recientes"
733
+ },
734
+ writes_only: {
735
+ label: "Escrituras"
736
+ },
737
+ auth_events: {
738
+ label: "Autenticaci\xF3n"
739
+ },
740
+ config_changes: {
741
+ label: "Configuraci\xF3n"
742
+ },
743
+ all_events: {
744
+ label: "Todos"
745
+ }
746
+ }
747
+ },
748
+ sys_activity: {
749
+ label: "Actividad",
750
+ pluralLabel: "Actividades",
751
+ description: "Entradas recientes del flujo de actividad (ligeras y desnormalizadas).",
752
+ fields: {
753
+ id: {
754
+ label: "ID de actividad"
755
+ },
756
+ timestamp: {
757
+ label: "Marca temporal"
758
+ },
759
+ type: {
760
+ label: "Tipo",
761
+ options: {
762
+ created: "Creado",
763
+ updated: "Actualizado",
764
+ deleted: "Eliminado",
765
+ commented: "Comentado",
766
+ mentioned: "Mencionado",
767
+ shared: "Compartido",
768
+ assigned: "Asignado",
769
+ completed: "Completado",
770
+ login: "Inicio de sesi\xF3n",
771
+ logout: "Cierre de sesi\xF3n",
772
+ system: "Sistema"
773
+ }
774
+ },
775
+ summary: {
776
+ label: "Resumen",
777
+ help: "Resumen legible de una l\xEDnea."
778
+ },
779
+ actor_id: {
780
+ label: "Actor"
781
+ },
782
+ actor_name: {
783
+ label: "Nombre del actor"
784
+ },
785
+ actor_avatar_url: {
786
+ label: "Avatar del actor"
787
+ },
788
+ object_name: {
789
+ label: "Objeto",
790
+ help: "Nombre corto del objeto de destino (p. ej. account, sys_user)."
791
+ },
792
+ record_id: {
793
+ label: "ID de registro"
794
+ },
795
+ record_label: {
796
+ label: "Nombre visible del registro",
797
+ help: "Nombre visible del registro de destino en el momento de escritura."
798
+ },
799
+ url: {
800
+ label: "URL",
801
+ help: "Enlace profundo opcional al destino de la actividad."
802
+ },
803
+ environment_id: {
804
+ label: "Proyecto",
805
+ help: "Contexto del proyecto (implementaciones multiproyecto)."
806
+ },
807
+ metadata: {
808
+ label: "Metadatos",
809
+ help: "Contexto adicional serializado en JSON."
810
+ }
811
+ }
812
+ },
813
+ sys_comment: {
814
+ label: "Comentario",
815
+ pluralLabel: "Comentarios",
816
+ description: "Comentarios en hilo adjuntos a registros mediante thread_id.",
817
+ fields: {
818
+ id: {
819
+ label: "ID de comentario"
820
+ },
821
+ thread_id: {
822
+ label: "Hilo",
823
+ help: "Identificador del hilo; por convenci\xF3n `{object}:{record_id}` (p. ej. `sys_user:abc123`)."
824
+ },
825
+ parent_id: {
826
+ label: "Comentario principal",
827
+ help: "Comentario principal opcional para respuestas anidadas."
828
+ },
829
+ reply_count: {
830
+ label: "N\xFAmero de respuestas"
831
+ },
832
+ author_id: {
833
+ label: "Autor"
834
+ },
835
+ author_name: {
836
+ label: "Nombre del autor"
837
+ },
838
+ author_avatar_url: {
839
+ label: "Avatar del autor"
840
+ },
841
+ body: {
842
+ label: "Contenido",
843
+ help: "Texto del comentario (compatible con Markdown)."
844
+ },
845
+ mentions: {
846
+ label: "Menciones",
847
+ help: "Matriz JSON de objetos @mention."
848
+ },
849
+ reactions: {
850
+ label: "Reacciones",
851
+ help: "Matriz JSON de objetos de reacci\xF3n emoji."
852
+ },
853
+ is_edited: {
854
+ label: "Editado"
855
+ },
856
+ edited_at: {
857
+ label: "Editado el"
858
+ },
859
+ visibility: {
860
+ label: "Visibilidad",
861
+ options: {
862
+ public: "P\xFAblico",
863
+ internal: "Interno",
864
+ private: "Privado"
865
+ }
866
+ },
867
+ created_at: {
868
+ label: "Creado el"
869
+ },
870
+ updated_at: {
871
+ label: "Actualizado el"
872
+ }
873
+ }
874
+ }
875
+ };
876
+ }
877
+ });
878
+
879
+ // src/translations/index.ts
880
+ var translations_exports = {};
881
+ __export(translations_exports, {
882
+ AuditTranslations: () => AuditTranslations
883
+ });
884
+ var AuditTranslations;
885
+ var init_translations = __esm({
886
+ "src/translations/index.ts"() {
887
+ "use strict";
888
+ init_en_objects_generated();
889
+ init_zh_CN_objects_generated();
890
+ init_ja_JP_objects_generated();
891
+ init_es_ES_objects_generated();
892
+ AuditTranslations = {
893
+ en: { objects: enObjects },
894
+ "zh-CN": { objects: zhCNObjects },
895
+ "ja-JP": { objects: jaJPObjects },
896
+ "es-ES": { objects: esESObjects }
897
+ };
898
+ }
899
+ });
900
+
901
+ // src/objects/sys-audit-log.object.ts
902
+ import { ObjectSchema, Field } from "@objectstack/spec/data";
903
+ var SysAuditLog = ObjectSchema.create({
904
+ name: "sys_audit_log",
905
+ label: "Audit Log",
906
+ pluralLabel: "Audit Logs",
907
+ icon: "scroll-text",
908
+ isSystem: true,
909
+ managedBy: "append-only",
910
+ description: "Immutable audit trail for platform events",
911
+ displayNameField: "action",
912
+ titleFormat: "{action} \xB7 {object_name}",
913
+ compactLayout: ["created_at", "action", "object_name", "record_id", "user_id"],
914
+ listViews: {
915
+ recent: {
916
+ type: "grid",
917
+ name: "recent",
918
+ label: "Recent",
919
+ data: { provider: "object", object: "sys_audit_log" },
920
+ columns: ["created_at", "action", "object_name", "record_id", "user_id"],
921
+ sort: [{ field: "created_at", order: "desc" }],
922
+ pagination: { pageSize: 50 },
923
+ emptyState: { title: "No audit events", message: "Activity will appear here as users interact with the platform." }
924
+ },
925
+ writes_only: {
926
+ type: "grid",
927
+ name: "writes_only",
928
+ label: "Writes",
929
+ data: { provider: "object", object: "sys_audit_log" },
930
+ columns: ["created_at", "action", "object_name", "record_id", "user_id"],
931
+ filter: [{ field: "action", operator: "in", value: ["create", "update", "delete", "restore"] }],
932
+ sort: [{ field: "created_at", order: "desc" }],
933
+ pagination: { pageSize: 50 }
934
+ },
935
+ auth_events: {
936
+ type: "grid",
937
+ name: "auth_events",
938
+ label: "Auth",
939
+ data: { provider: "object", object: "sys_audit_log" },
940
+ columns: ["created_at", "action", "user_id"],
941
+ filter: [{ field: "action", operator: "in", value: ["login", "logout", "permission_change"] }],
942
+ sort: [{ field: "created_at", order: "desc" }],
943
+ pagination: { pageSize: 50 }
944
+ },
945
+ config_changes: {
946
+ type: "grid",
947
+ name: "config_changes",
948
+ label: "Config",
949
+ data: { provider: "object", object: "sys_audit_log" },
950
+ columns: ["created_at", "action", "object_name", "user_id"],
951
+ filter: [{ field: "action", operator: "in", value: ["config_change", "export", "import"] }],
952
+ sort: [{ field: "created_at", order: "desc" }],
953
+ pagination: { pageSize: 50 }
954
+ },
955
+ all_events: {
956
+ type: "grid",
957
+ name: "all_events",
958
+ label: "All",
959
+ data: { provider: "object", object: "sys_audit_log" },
960
+ columns: ["created_at", "action", "object_name", "record_id", "user_id"],
961
+ sort: [{ field: "created_at", order: "desc" }],
962
+ pagination: { pageSize: 100 }
963
+ }
964
+ },
965
+ fields: {
966
+ // ── Event ────────────────────────────────────────────────────
967
+ created_at: Field.datetime({
968
+ label: "Timestamp",
969
+ required: true,
970
+ defaultValue: "NOW()",
971
+ readonly: true,
972
+ group: "Event"
973
+ }),
974
+ action: Field.select(
975
+ ["create", "update", "delete", "restore", "login", "logout", "permission_change", "config_change", "export", "import"],
976
+ {
977
+ label: "Action",
978
+ required: true,
979
+ readonly: true,
980
+ searchable: true,
981
+ description: "Action type (snake_case)",
982
+ group: "Event"
983
+ }
984
+ ),
985
+ user_id: Field.lookup("sys_user", {
986
+ label: "Actor",
987
+ required: false,
988
+ readonly: true,
989
+ searchable: true,
990
+ description: "User who performed the action (null for system actions)",
991
+ group: "Event"
992
+ }),
993
+ // ── Target record ────────────────────────────────────────────
994
+ object_name: Field.text({
995
+ label: "Object",
996
+ required: false,
997
+ readonly: true,
998
+ searchable: true,
999
+ maxLength: 255,
1000
+ description: "Target object (e.g. sys_user, project_task)",
1001
+ group: "Target"
1002
+ }),
1003
+ record_id: Field.text({
1004
+ label: "Record ID",
1005
+ required: false,
1006
+ readonly: true,
1007
+ searchable: true,
1008
+ description: "ID of the affected record",
1009
+ group: "Target"
1010
+ }),
1011
+ // ── Change payload ───────────────────────────────────────────
1012
+ old_value: Field.textarea({
1013
+ label: "Old Value",
1014
+ required: false,
1015
+ readonly: true,
1016
+ description: "JSON-serialized previous state",
1017
+ group: "Changes"
1018
+ }),
1019
+ new_value: Field.textarea({
1020
+ label: "New Value",
1021
+ required: false,
1022
+ readonly: true,
1023
+ description: "JSON-serialized new state",
1024
+ group: "Changes"
1025
+ }),
1026
+ // ── Client fingerprint ───────────────────────────────────────
1027
+ ip_address: Field.text({
1028
+ label: "IP Address",
1029
+ required: false,
1030
+ readonly: true,
1031
+ maxLength: 45,
1032
+ group: "Client"
1033
+ }),
1034
+ user_agent: Field.textarea({
1035
+ label: "User Agent",
1036
+ required: false,
1037
+ readonly: true,
1038
+ group: "Client"
1039
+ }),
1040
+ // ── Context ──────────────────────────────────────────────────
1041
+ tenant_id: Field.lookup("sys_organization", {
1042
+ label: "Tenant",
1043
+ required: false,
1044
+ readonly: true,
1045
+ description: "Tenant context for multi-tenant isolation",
1046
+ group: "Context"
1047
+ }),
1048
+ metadata: Field.textarea({
1049
+ label: "Metadata",
1050
+ required: false,
1051
+ readonly: true,
1052
+ description: "JSON-serialized additional context",
1053
+ group: "Context"
1054
+ }),
1055
+ // ── System ───────────────────────────────────────────────────
1056
+ id: Field.text({
1057
+ label: "Audit Log ID",
1058
+ required: true,
1059
+ readonly: true,
1060
+ group: "System"
1061
+ })
1062
+ },
1063
+ indexes: [
1064
+ { fields: ["created_at"] },
1065
+ { fields: ["user_id"] },
1066
+ { fields: ["object_name", "record_id"] },
1067
+ { fields: ["action"] },
1068
+ { fields: ["tenant_id"] }
1069
+ ],
1070
+ enable: {
1071
+ trackHistory: false,
1072
+ // Audit logs are themselves the audit trail
1073
+ searchable: true,
1074
+ apiEnabled: true,
1075
+ apiMethods: ["get", "list"],
1076
+ // Read-only — creation happens via internal system hooks only
1077
+ trash: false,
1078
+ // Never soft-delete audit logs
1079
+ mru: false,
1080
+ clone: false
1081
+ }
1082
+ });
1083
+
1084
+ // src/objects/sys-activity.object.ts
1085
+ import { ObjectSchema as ObjectSchema2, Field as Field2 } from "@objectstack/spec/data";
1086
+ var SysActivity = ObjectSchema2.create({
1087
+ name: "sys_activity",
1088
+ label: "Activity",
1089
+ pluralLabel: "Activities",
1090
+ icon: "activity",
1091
+ isSystem: true,
1092
+ managedBy: "append-only",
1093
+ description: "Recent activity stream entries (lightweight, denormalized)",
1094
+ displayNameField: "summary",
1095
+ titleFormat: "{type} \xB7 {summary}",
1096
+ compactLayout: ["timestamp", "type", "actor_name", "summary"],
1097
+ fields: {
1098
+ id: Field2.text({
1099
+ label: "Activity ID",
1100
+ required: true,
1101
+ readonly: true,
1102
+ group: "System"
1103
+ }),
1104
+ timestamp: Field2.datetime({
1105
+ label: "Timestamp",
1106
+ required: true,
1107
+ defaultValue: "NOW()",
1108
+ readonly: true,
1109
+ group: "Event"
1110
+ }),
1111
+ type: Field2.select(
1112
+ [
1113
+ "created",
1114
+ "updated",
1115
+ "deleted",
1116
+ "commented",
1117
+ "mentioned",
1118
+ "shared",
1119
+ "assigned",
1120
+ "completed",
1121
+ "login",
1122
+ "logout",
1123
+ "system"
1124
+ ],
1125
+ {
1126
+ label: "Type",
1127
+ required: true,
1128
+ readonly: true,
1129
+ searchable: true,
1130
+ group: "Event"
1131
+ }
1132
+ ),
1133
+ summary: Field2.text({
1134
+ label: "Summary",
1135
+ required: true,
1136
+ readonly: true,
1137
+ maxLength: 500,
1138
+ searchable: true,
1139
+ description: "Human-readable one-line summary",
1140
+ group: "Event"
1141
+ }),
1142
+ // ── Actor ───────────────────────────────────────────────────
1143
+ actor_id: Field2.lookup("sys_user", {
1144
+ label: "Actor",
1145
+ required: false,
1146
+ readonly: true,
1147
+ searchable: true,
1148
+ group: "Actor"
1149
+ }),
1150
+ actor_name: Field2.text({
1151
+ label: "Actor Name",
1152
+ required: false,
1153
+ readonly: true,
1154
+ group: "Actor"
1155
+ }),
1156
+ actor_avatar_url: Field2.url({
1157
+ label: "Actor Avatar",
1158
+ required: false,
1159
+ readonly: true,
1160
+ group: "Actor"
1161
+ }),
1162
+ // ── Target ───────────────────────────────────────────────────
1163
+ object_name: Field2.text({
1164
+ label: "Object",
1165
+ required: false,
1166
+ readonly: true,
1167
+ searchable: true,
1168
+ maxLength: 255,
1169
+ description: "Target object short name (e.g. account, sys_user)",
1170
+ group: "Target"
1171
+ }),
1172
+ record_id: Field2.text({
1173
+ label: "Record ID",
1174
+ required: false,
1175
+ readonly: true,
1176
+ searchable: true,
1177
+ group: "Target"
1178
+ }),
1179
+ record_label: Field2.text({
1180
+ label: "Record Label",
1181
+ required: false,
1182
+ readonly: true,
1183
+ maxLength: 255,
1184
+ description: "Display label of the target record at write time",
1185
+ group: "Target"
1186
+ }),
1187
+ url: Field2.url({
1188
+ label: "URL",
1189
+ required: false,
1190
+ readonly: true,
1191
+ description: "Optional deep-link to the activity target",
1192
+ group: "Target"
1193
+ }),
1194
+ // ── Context ──────────────────────────────────────────────────
1195
+ environment_id: Field2.lookup("sys_environment", {
1196
+ label: "Environment",
1197
+ required: false,
1198
+ readonly: true,
1199
+ searchable: true,
1200
+ description: "Environment context (multi-environment deployments)",
1201
+ group: "Context"
1202
+ }),
1203
+ metadata: Field2.textarea({
1204
+ label: "Metadata",
1205
+ required: false,
1206
+ readonly: true,
1207
+ description: "JSON-serialized additional context",
1208
+ group: "Context"
1209
+ })
1210
+ },
1211
+ indexes: [
1212
+ { fields: ["timestamp"] },
1213
+ { fields: ["actor_id"] },
1214
+ { fields: ["object_name", "record_id"] },
1215
+ { fields: ["type"] },
1216
+ { fields: ["environment_id"] }
1217
+ ],
1218
+ enable: {
1219
+ trackHistory: false,
1220
+ searchable: true,
1221
+ apiEnabled: true,
1222
+ apiMethods: ["get", "list"],
1223
+ trash: false,
1224
+ mru: false,
1225
+ clone: false
1226
+ }
1227
+ });
1228
+
1229
+ // src/objects/sys-comment.object.ts
1230
+ import { ObjectSchema as ObjectSchema3, Field as Field3 } from "@objectstack/spec/data";
1231
+ var SysComment = ObjectSchema3.create({
1232
+ name: "sys_comment",
1233
+ label: "Comment",
1234
+ pluralLabel: "Comments",
1235
+ icon: "message-square",
1236
+ isSystem: true,
1237
+ managedBy: "platform",
1238
+ description: "Threaded comments attached to records via thread_id",
1239
+ displayNameField: "body",
1240
+ titleFormat: "{author_name}: {body}",
1241
+ compactLayout: ["created_at", "author_name", "body"],
1242
+ fields: {
1243
+ id: Field3.text({
1244
+ label: "Comment ID",
1245
+ required: true,
1246
+ readonly: true,
1247
+ group: "System"
1248
+ }),
1249
+ // ── Thread ───────────────────────────────────────────────────
1250
+ thread_id: Field3.text({
1251
+ label: "Thread",
1252
+ required: true,
1253
+ searchable: true,
1254
+ maxLength: 255,
1255
+ description: "Thread identifier \u2014 conventionally `{object}:{record_id}` (e.g. `sys_user:abc123`)",
1256
+ group: "Thread"
1257
+ }),
1258
+ parent_id: Field3.lookup("sys_comment", {
1259
+ label: "Parent Comment",
1260
+ required: false,
1261
+ description: "Optional parent comment for nested replies",
1262
+ group: "Thread"
1263
+ }),
1264
+ reply_count: Field3.number({
1265
+ label: "Reply Count",
1266
+ defaultValue: 0,
1267
+ readonly: true,
1268
+ group: "Thread"
1269
+ }),
1270
+ // ── Author ───────────────────────────────────────────────────
1271
+ author_id: Field3.lookup("sys_user", {
1272
+ label: "Author",
1273
+ required: true,
1274
+ searchable: true,
1275
+ group: "Author"
1276
+ }),
1277
+ author_name: Field3.text({
1278
+ label: "Author Name",
1279
+ required: false,
1280
+ group: "Author"
1281
+ }),
1282
+ author_avatar_url: Field3.url({
1283
+ label: "Author Avatar",
1284
+ required: false,
1285
+ group: "Author"
1286
+ }),
1287
+ // ── Body ─────────────────────────────────────────────────────
1288
+ body: Field3.textarea({
1289
+ label: "Body",
1290
+ required: true,
1291
+ searchable: true,
1292
+ description: "Comment text (Markdown supported)",
1293
+ group: "Body"
1294
+ }),
1295
+ mentions: Field3.textarea({
1296
+ label: "Mentions",
1297
+ required: false,
1298
+ description: "JSON array of @mention objects",
1299
+ group: "Body"
1300
+ }),
1301
+ reactions: Field3.textarea({
1302
+ label: "Reactions",
1303
+ required: false,
1304
+ description: "JSON array of emoji reaction objects",
1305
+ group: "Body"
1306
+ }),
1307
+ // ── Lifecycle ────────────────────────────────────────────────
1308
+ is_edited: Field3.boolean({
1309
+ label: "Edited",
1310
+ defaultValue: false,
1311
+ group: "Lifecycle"
1312
+ }),
1313
+ edited_at: Field3.datetime({
1314
+ label: "Edited At",
1315
+ required: false,
1316
+ group: "Lifecycle"
1317
+ }),
1318
+ visibility: Field3.select(
1319
+ ["public", "internal", "private"],
1320
+ {
1321
+ label: "Visibility",
1322
+ defaultValue: "public",
1323
+ group: "Lifecycle"
1324
+ }
1325
+ ),
1326
+ created_at: Field3.datetime({
1327
+ label: "Created At",
1328
+ required: true,
1329
+ defaultValue: "NOW()",
1330
+ readonly: true,
1331
+ group: "System"
1332
+ }),
1333
+ updated_at: Field3.datetime({
1334
+ label: "Updated At",
1335
+ required: false,
1336
+ group: "System"
1337
+ })
1338
+ },
1339
+ indexes: [
1340
+ { fields: ["thread_id", "created_at"] },
1341
+ { fields: ["parent_id"] },
1342
+ { fields: ["author_id"] }
1343
+ ],
1344
+ enable: {
1345
+ trackHistory: true,
1346
+ searchable: true,
1347
+ apiEnabled: true,
1348
+ trash: true,
1349
+ mru: false,
1350
+ clone: false
1351
+ }
1352
+ });
1353
+
1
1354
  // src/audit-plugin.ts
2
- import { SysAuditLog, SysActivity, SysComment, SysAttachment, SysNotification } from "@objectstack/platform-objects/audit";
1355
+ import { SysNotification, SysAttachment } from "@objectstack/platform-objects/audit";
3
1356
 
4
1357
  // src/audit-writers.ts
5
1358
  var SKIP_OBJECTS = /* @__PURE__ */ new Set([
@@ -59,8 +1412,9 @@ function safeStringify(v) {
59
1412
  return String(v);
60
1413
  }
61
1414
  }
62
- function installAuditWriters(engine, packageId = "com.objectstack.audit") {
1415
+ function installAuditWriters(engine, packageId = "com.objectstack.audit", opts = {}) {
63
1416
  if (!engine || typeof engine.registerHook !== "function") return;
1417
+ const getMessaging = opts.getMessaging ?? (() => void 0);
64
1418
  if (typeof engine.unregisterHooksByPackage === "function") {
65
1419
  engine.unregisterHooksByPackage(packageId);
66
1420
  }
@@ -154,7 +1508,7 @@ function installAuditWriters(engine, packageId = "com.objectstack.audit") {
154
1508
  const sys = api.sudo();
155
1509
  await sys.object("sys_audit_log").create(auditRow);
156
1510
  await sys.object("sys_activity").create(activityRow);
157
- await writeAssignmentNotifications(sys, {
1511
+ await writeAssignmentNotifications(getMessaging(), {
158
1512
  object: ctx.object,
159
1513
  recordId: recordId ?? null,
160
1514
  label,
@@ -177,8 +1531,8 @@ function installAuditWriters(engine, packageId = "com.objectstack.audit") {
177
1531
  const writeCommentMentions = async (ctx) => {
178
1532
  if (ctx.object !== "sys_comment") return;
179
1533
  if (ctx.event !== "afterInsert") return;
180
- const api = ctx.api;
181
- if (!api?.sudo) return;
1534
+ const messaging = getMessaging();
1535
+ if (!messaging) return;
182
1536
  const row = ctx.result;
183
1537
  if (!row || typeof row !== "object") return;
184
1538
  let mentions = row.mentions;
@@ -198,26 +1552,27 @@ function installAuditWriters(engine, packageId = "com.objectstack.audit") {
198
1552
  const bodyPreview = String(row.body ?? "").slice(0, 240);
199
1553
  const sess = ctx.session ?? {};
200
1554
  const tenantId = sess.tenantId ?? row.organization_id ?? null;
201
- const sys = api.sudo();
1555
+ const commentId = row.id != null ? String(row.id) : null;
202
1556
  for (const uid of userIds) {
203
1557
  if (uid === actorId) continue;
204
1558
  try {
205
- await sys.object("sys_notification").create({
206
- recipient_id: uid,
207
- type: "mention",
208
- title: actorName ? `${actorName} mentioned you` : "You were mentioned",
209
- body: bodyPreview,
210
- source_object: source_object || null,
211
- source_id: source_id || null,
212
- actor_id: actorId,
213
- actor_name: actorName,
214
- is_read: false,
215
- // Stamp tenant so the recipient's RLS sees it (see writeAssignmentNotifications).
216
- organization_id: tenantId
1559
+ await messaging.emit({
1560
+ topic: "collab.mention",
1561
+ audience: [uid],
1562
+ severity: "info",
1563
+ source: source_object ? { object: source_object, id: source_id ?? "" } : void 0,
1564
+ actorId: actorId ?? void 0,
1565
+ organizationId: tenantId ?? void 0,
1566
+ dedupKey: commentId ? `collab.mention:${commentId}:${uid}` : void 0,
1567
+ payload: {
1568
+ title: actorName ? `${actorName} mentioned you` : "You were mentioned",
1569
+ body: bodyPreview,
1570
+ actorName
1571
+ }
217
1572
  });
218
1573
  } catch (err) {
219
1574
  try {
220
- engine.logger?.warn?.("Mention notification write failed", { uid, err: String(err?.message ?? err) });
1575
+ engine.logger?.warn?.("Mention notification emit failed", { uid, err: String(err?.message ?? err) });
221
1576
  } catch {
222
1577
  }
223
1578
  }
@@ -234,7 +1589,8 @@ function pickOwner(rec) {
234
1589
  }
235
1590
  return null;
236
1591
  }
237
- async function writeAssignmentNotifications(sys, params) {
1592
+ async function writeAssignmentNotifications(messaging, params) {
1593
+ if (!messaging) return;
238
1594
  if (params.action === "delete") return;
239
1595
  if (!params.recordId) return;
240
1596
  const newOwner = pickOwner(params.after);
@@ -243,21 +1599,18 @@ async function writeAssignmentNotifications(sys, params) {
243
1599
  if (params.action === "update" && newOwner === oldOwner) return;
244
1600
  if (newOwner === params.actorId) return;
245
1601
  try {
246
- await sys.object("sys_notification").create({
247
- recipient_id: newOwner,
248
- type: "assignment",
249
- title: `${params.object} "${params.label}" assigned to you`,
250
- body: null,
251
- source_object: params.object,
252
- source_id: params.recordId,
253
- actor_id: params.actorId,
254
- actor_name: null,
255
- is_read: false,
256
- // Stamp organization_id so the recipient (who lives in the same
257
- // tenant as the action) sees the notification through RLS. Without
258
- // this, sys_notification rows insert with NULL organization_id and
259
- // the recipient's `tenant_isolation` policy denies them.
260
- organization_id: params.tenantId
1602
+ const writeVersion = (params.after && typeof params.after === "object" ? params.after.updated_at ?? params.after.modified_at ?? params.after.updated_date : null) ?? null;
1603
+ await messaging.emit({
1604
+ topic: "collab.assignment",
1605
+ audience: [newOwner],
1606
+ severity: "info",
1607
+ source: { object: params.object, id: params.recordId },
1608
+ actorId: params.actorId ?? void 0,
1609
+ organizationId: params.tenantId ?? void 0,
1610
+ dedupKey: writeVersion ? `collab.assignment:${params.object}:${params.recordId}:${newOwner}:${writeVersion}` : void 0,
1611
+ payload: {
1612
+ title: `${params.object} "${params.label}" assigned to you`
1613
+ }
261
1614
  });
262
1615
  } catch {
263
1616
  }
@@ -281,8 +1634,34 @@ var AuditPlugin = class {
281
1634
  scope: "system",
282
1635
  defaultDatasource: "cloud",
283
1636
  namespace: "sys",
284
- objects: [SysAuditLog, SysActivity, SysComment, SysAttachment, SysNotification]
1637
+ objects: [SysAuditLog, SysActivity, SysComment, SysAttachment, SysNotification],
1638
+ // ADR-0029 D7 — contribute the Audit Logs entry into the Setup app's
1639
+ // `group_diagnostics` slot. The plugin owns sys_audit_log (K2).
1640
+ navigationContributions: [
1641
+ {
1642
+ app: "setup",
1643
+ group: "group_diagnostics",
1644
+ priority: 100,
1645
+ items: [
1646
+ { id: "nav_audit_logs", type: "object", label: "Audit Logs", objectName: "sys_audit_log", icon: "scroll-text" }
1647
+ ]
1648
+ }
1649
+ ]
285
1650
  });
1651
+ if (typeof ctx.hook === "function") {
1652
+ ctx.hook("kernel:ready", async () => {
1653
+ try {
1654
+ const i18n = ctx.getService("i18n");
1655
+ if (i18n && typeof i18n.loadTranslations === "function") {
1656
+ const { AuditTranslations: AuditTranslations2 } = await Promise.resolve().then(() => (init_translations(), translations_exports));
1657
+ for (const [locale, data] of Object.entries(AuditTranslations2)) {
1658
+ i18n.loadTranslations(locale, data);
1659
+ }
1660
+ }
1661
+ } catch {
1662
+ }
1663
+ });
1664
+ }
286
1665
  ctx.logger.info("Audit Plugin initialized");
287
1666
  }
288
1667
  async start(ctx) {
@@ -309,7 +1688,14 @@ var AuditPlugin = class {
309
1688
  ctx.logger.warn("AuditPlugin: ObjectQL engine not available \u2014 audit writers NOT installed");
310
1689
  return;
311
1690
  }
312
- installAuditWriters(engine, this.name);
1691
+ const getMessaging = () => {
1692
+ try {
1693
+ return ctx.getService("messaging");
1694
+ } catch {
1695
+ return void 0;
1696
+ }
1697
+ };
1698
+ installAuditWriters(engine, this.name, { getMessaging });
313
1699
  process.stderr.write("[AuditPlugin] writers installed\n");
314
1700
  ctx.logger.info("AuditPlugin: audit + activity writers installed");
315
1701
  });