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