@objectstack/plugin-audit 4.0.1 → 4.0.2
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/.turbo/turbo-build.log +11 -11
- package/CHANGELOG.md +8 -0
- package/dist/index.d.mts +7 -30
- package/dist/index.d.ts +7 -30
- package/dist/index.js +15 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +15 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -4
- package/src/audit-plugin.ts +19 -2
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
|
|
2
|
-
> @objectstack/plugin-audit@4.0.
|
|
2
|
+
> @objectstack/plugin-audit@4.0.2 build /home/runner/work/framework/framework/packages/plugins/plugin-audit
|
|
3
3
|
> tsup --config ../../../tsup.config.ts
|
|
4
4
|
|
|
5
5
|
[34mCLI[39m Building entry: src/index.ts
|
|
6
6
|
[34mCLI[39m Using tsconfig: tsconfig.json
|
|
7
7
|
[34mCLI[39m tsup v8.5.1
|
|
8
|
-
[34mCLI[39m Using tsup config: /home/runner/work/
|
|
8
|
+
[34mCLI[39m Using tsup config: /home/runner/work/framework/framework/tsup.config.ts
|
|
9
9
|
[34mCLI[39m Target: es2020
|
|
10
10
|
[34mCLI[39m Cleaning output folder
|
|
11
11
|
[34mESM[39m Build start
|
|
12
12
|
[34mCJS[39m Build start
|
|
13
|
-
[32mESM[39m [1mdist/index.mjs [22m[32m3.
|
|
14
|
-
[32mESM[39m [1mdist/index.mjs.map [22m[
|
|
15
|
-
[32mESM[39m ⚡️ Build success in
|
|
16
|
-
[32mCJS[39m [1mdist/index.js [22m[32m4.
|
|
17
|
-
[32mCJS[39m [1mdist/index.js.map [22m[
|
|
18
|
-
[32mCJS[39m ⚡️ Build success in
|
|
13
|
+
[32mESM[39m [1mdist/index.mjs [22m[32m3.75 KB[39m
|
|
14
|
+
[32mESM[39m [1mdist/index.mjs.map [22m[32m7.10 KB[39m
|
|
15
|
+
[32mESM[39m ⚡️ Build success in 107ms
|
|
16
|
+
[32mCJS[39m [1mdist/index.js [22m[32m4.93 KB[39m
|
|
17
|
+
[32mCJS[39m [1mdist/index.js.map [22m[32m7.55 KB[39m
|
|
18
|
+
[32mCJS[39m ⚡️ Build success in 108ms
|
|
19
19
|
[34mDTS[39m Build start
|
|
20
|
-
[32mDTS[39m ⚡️ Build success in
|
|
21
|
-
[32mDTS[39m [1mdist/index.d.mts [22m[
|
|
22
|
-
[32mDTS[39m [1mdist/index.d.ts [22m[
|
|
20
|
+
[32mDTS[39m ⚡️ Build success in 20592ms
|
|
21
|
+
[32mDTS[39m [1mdist/index.d.mts [22m[32m103.78 KB[39m
|
|
22
|
+
[32mDTS[39m [1mdist/index.d.ts [22m[32m103.78 KB[39m
|
package/CHANGELOG.md
CHANGED
package/dist/index.d.mts
CHANGED
|
@@ -12,6 +12,7 @@ declare class AuditPlugin implements Plugin {
|
|
|
12
12
|
name: string;
|
|
13
13
|
type: string;
|
|
14
14
|
version: string;
|
|
15
|
+
dependencies: string[];
|
|
15
16
|
init(ctx: PluginContext): Promise<void>;
|
|
16
17
|
}
|
|
17
18
|
|
|
@@ -337,11 +338,7 @@ declare const SysAuditLog: Omit<{
|
|
|
337
338
|
keyPrefix?: string | undefined;
|
|
338
339
|
actions?: {
|
|
339
340
|
name: string;
|
|
340
|
-
label: string
|
|
341
|
-
key: string;
|
|
342
|
-
defaultValue?: string | undefined;
|
|
343
|
-
params?: Record<string, string | number | boolean> | undefined;
|
|
344
|
-
};
|
|
341
|
+
label: string;
|
|
345
342
|
type: "url" | "script" | "modal" | "flow" | "api";
|
|
346
343
|
refreshAfter: boolean;
|
|
347
344
|
objectName?: string | undefined;
|
|
@@ -352,44 +349,24 @@ declare const SysAuditLog: Omit<{
|
|
|
352
349
|
execute?: string | undefined;
|
|
353
350
|
params?: {
|
|
354
351
|
name: string;
|
|
355
|
-
label: string
|
|
356
|
-
key: string;
|
|
357
|
-
defaultValue?: string | undefined;
|
|
358
|
-
params?: Record<string, string | number | boolean> | undefined;
|
|
359
|
-
};
|
|
352
|
+
label: string;
|
|
360
353
|
type: "number" | "boolean" | "date" | "lookup" | "file" | "url" | "json" | "text" | "textarea" | "email" | "phone" | "password" | "markdown" | "html" | "richtext" | "currency" | "percent" | "datetime" | "time" | "toggle" | "select" | "multiselect" | "radio" | "checkboxes" | "master_detail" | "tree" | "image" | "avatar" | "video" | "audio" | "formula" | "summary" | "autonumber" | "location" | "address" | "code" | "color" | "rating" | "slider" | "signature" | "qrcode" | "progress" | "tags" | "vector";
|
|
361
354
|
required: boolean;
|
|
362
355
|
options?: {
|
|
363
|
-
label: string
|
|
364
|
-
key: string;
|
|
365
|
-
defaultValue?: string | undefined;
|
|
366
|
-
params?: Record<string, string | number | boolean> | undefined;
|
|
367
|
-
};
|
|
356
|
+
label: string;
|
|
368
357
|
value: string;
|
|
369
358
|
}[] | undefined;
|
|
370
359
|
}[] | undefined;
|
|
371
360
|
variant?: "link" | "primary" | "secondary" | "danger" | "ghost" | undefined;
|
|
372
|
-
confirmText?: string |
|
|
373
|
-
|
|
374
|
-
defaultValue?: string | undefined;
|
|
375
|
-
params?: Record<string, string | number | boolean> | undefined;
|
|
376
|
-
} | undefined;
|
|
377
|
-
successMessage?: string | {
|
|
378
|
-
key: string;
|
|
379
|
-
defaultValue?: string | undefined;
|
|
380
|
-
params?: Record<string, string | number | boolean> | undefined;
|
|
381
|
-
} | undefined;
|
|
361
|
+
confirmText?: string | undefined;
|
|
362
|
+
successMessage?: string | undefined;
|
|
382
363
|
visible?: string | undefined;
|
|
383
364
|
disabled?: string | boolean | undefined;
|
|
384
365
|
shortcut?: string | undefined;
|
|
385
366
|
bulkEnabled?: boolean | undefined;
|
|
386
367
|
timeout?: number | undefined;
|
|
387
368
|
aria?: {
|
|
388
|
-
ariaLabel?: string |
|
|
389
|
-
key: string;
|
|
390
|
-
defaultValue?: string | undefined;
|
|
391
|
-
params?: Record<string, string | number | boolean> | undefined;
|
|
392
|
-
} | undefined;
|
|
369
|
+
ariaLabel?: string | undefined;
|
|
393
370
|
ariaDescribedBy?: string | undefined;
|
|
394
371
|
role?: string | undefined;
|
|
395
372
|
} | undefined;
|
package/dist/index.d.ts
CHANGED
|
@@ -12,6 +12,7 @@ declare class AuditPlugin implements Plugin {
|
|
|
12
12
|
name: string;
|
|
13
13
|
type: string;
|
|
14
14
|
version: string;
|
|
15
|
+
dependencies: string[];
|
|
15
16
|
init(ctx: PluginContext): Promise<void>;
|
|
16
17
|
}
|
|
17
18
|
|
|
@@ -337,11 +338,7 @@ declare const SysAuditLog: Omit<{
|
|
|
337
338
|
keyPrefix?: string | undefined;
|
|
338
339
|
actions?: {
|
|
339
340
|
name: string;
|
|
340
|
-
label: string
|
|
341
|
-
key: string;
|
|
342
|
-
defaultValue?: string | undefined;
|
|
343
|
-
params?: Record<string, string | number | boolean> | undefined;
|
|
344
|
-
};
|
|
341
|
+
label: string;
|
|
345
342
|
type: "url" | "script" | "modal" | "flow" | "api";
|
|
346
343
|
refreshAfter: boolean;
|
|
347
344
|
objectName?: string | undefined;
|
|
@@ -352,44 +349,24 @@ declare const SysAuditLog: Omit<{
|
|
|
352
349
|
execute?: string | undefined;
|
|
353
350
|
params?: {
|
|
354
351
|
name: string;
|
|
355
|
-
label: string
|
|
356
|
-
key: string;
|
|
357
|
-
defaultValue?: string | undefined;
|
|
358
|
-
params?: Record<string, string | number | boolean> | undefined;
|
|
359
|
-
};
|
|
352
|
+
label: string;
|
|
360
353
|
type: "number" | "boolean" | "date" | "lookup" | "file" | "url" | "json" | "text" | "textarea" | "email" | "phone" | "password" | "markdown" | "html" | "richtext" | "currency" | "percent" | "datetime" | "time" | "toggle" | "select" | "multiselect" | "radio" | "checkboxes" | "master_detail" | "tree" | "image" | "avatar" | "video" | "audio" | "formula" | "summary" | "autonumber" | "location" | "address" | "code" | "color" | "rating" | "slider" | "signature" | "qrcode" | "progress" | "tags" | "vector";
|
|
361
354
|
required: boolean;
|
|
362
355
|
options?: {
|
|
363
|
-
label: string
|
|
364
|
-
key: string;
|
|
365
|
-
defaultValue?: string | undefined;
|
|
366
|
-
params?: Record<string, string | number | boolean> | undefined;
|
|
367
|
-
};
|
|
356
|
+
label: string;
|
|
368
357
|
value: string;
|
|
369
358
|
}[] | undefined;
|
|
370
359
|
}[] | undefined;
|
|
371
360
|
variant?: "link" | "primary" | "secondary" | "danger" | "ghost" | undefined;
|
|
372
|
-
confirmText?: string |
|
|
373
|
-
|
|
374
|
-
defaultValue?: string | undefined;
|
|
375
|
-
params?: Record<string, string | number | boolean> | undefined;
|
|
376
|
-
} | undefined;
|
|
377
|
-
successMessage?: string | {
|
|
378
|
-
key: string;
|
|
379
|
-
defaultValue?: string | undefined;
|
|
380
|
-
params?: Record<string, string | number | boolean> | undefined;
|
|
381
|
-
} | undefined;
|
|
361
|
+
confirmText?: string | undefined;
|
|
362
|
+
successMessage?: string | undefined;
|
|
382
363
|
visible?: string | undefined;
|
|
383
364
|
disabled?: string | boolean | undefined;
|
|
384
365
|
shortcut?: string | undefined;
|
|
385
366
|
bulkEnabled?: boolean | undefined;
|
|
386
367
|
timeout?: number | undefined;
|
|
387
368
|
aria?: {
|
|
388
|
-
ariaLabel?: string |
|
|
389
|
-
key: string;
|
|
390
|
-
defaultValue?: string | undefined;
|
|
391
|
-
params?: Record<string, string | number | boolean> | undefined;
|
|
392
|
-
} | undefined;
|
|
369
|
+
ariaLabel?: string | undefined;
|
|
393
370
|
ariaDescribedBy?: string | undefined;
|
|
394
371
|
role?: string | undefined;
|
|
395
372
|
} | undefined;
|
package/dist/index.js
CHANGED
|
@@ -127,9 +127,10 @@ var AuditPlugin = class {
|
|
|
127
127
|
this.name = "com.objectstack.audit";
|
|
128
128
|
this.type = "standard";
|
|
129
129
|
this.version = "1.0.0";
|
|
130
|
+
this.dependencies = ["com.objectstack.engine.objectql"];
|
|
130
131
|
}
|
|
131
132
|
async init(ctx) {
|
|
132
|
-
ctx.
|
|
133
|
+
ctx.getService("manifest").register({
|
|
133
134
|
id: "com.objectstack.audit",
|
|
134
135
|
name: "Audit",
|
|
135
136
|
version: "1.0.0",
|
|
@@ -137,6 +138,19 @@ var AuditPlugin = class {
|
|
|
137
138
|
namespace: "sys",
|
|
138
139
|
objects: [SysAuditLog]
|
|
139
140
|
});
|
|
141
|
+
try {
|
|
142
|
+
const setupNav = ctx.getService("setupNav");
|
|
143
|
+
if (setupNav) {
|
|
144
|
+
setupNav.contribute({
|
|
145
|
+
areaId: "area_system",
|
|
146
|
+
items: [
|
|
147
|
+
{ id: "nav_audit_logs", type: "object", label: "Audit Logs", objectName: "audit_log", icon: "scroll-text", order: 10 }
|
|
148
|
+
]
|
|
149
|
+
});
|
|
150
|
+
ctx.logger.info("Audit navigation items contributed to Setup App");
|
|
151
|
+
}
|
|
152
|
+
} catch {
|
|
153
|
+
}
|
|
140
154
|
ctx.logger.info("Audit Plugin initialized");
|
|
141
155
|
}
|
|
142
156
|
};
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/objects/sys-audit-log.object.ts","../src/audit-plugin.ts"],"sourcesContent":["// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * @objectstack/plugin-audit\n *\n * Audit Plugin for ObjectStack\n * Provides the sys_audit_log system object definition for immutable audit trails.\n */\n\nexport { AuditPlugin } from './audit-plugin.js';\n\n// System Object Definitions (sys namespace)\nexport { SysAuditLog } from './objects/index.js';\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { ObjectSchema, Field } from '@objectstack/spec/data';\n\n/**\n * sys_audit_log — System Audit Log Object\n *\n * Immutable audit trail for all significant platform events.\n * Records who did what, when, and the before/after state.\n *\n * @namespace sys\n */\nexport const SysAuditLog = ObjectSchema.create({\n namespace: 'sys',\n name: 'audit_log',\n label: 'Audit Log',\n pluralLabel: 'Audit Logs',\n icon: 'scroll-text',\n isSystem: true,\n description: 'Immutable audit trail for platform events',\n titleFormat: '{action} on {object_name} by {user_id}',\n compactLayout: ['action', 'object_name', 'user_id', 'created_at'],\n \n fields: {\n id: Field.text({\n label: 'Audit Log ID',\n required: true,\n readonly: true,\n }),\n \n created_at: Field.datetime({\n label: 'Timestamp',\n required: true,\n defaultValue: 'NOW()',\n readonly: true,\n }),\n \n user_id: Field.text({\n label: 'User ID',\n required: false,\n description: 'User who performed the action (null for system actions)',\n }),\n \n action: Field.select(['create', 'update', 'delete', 'restore', 'login', 'logout', 'permission_change', 'config_change', 'export', 'import'], {\n label: 'Action',\n required: true,\n description: 'Action type (snake_case). Values: create, update, delete, restore, login, logout, permission_change, config_change, export, import',\n }),\n \n object_name: Field.text({\n label: 'Object Name',\n required: false,\n maxLength: 255,\n description: 'Target object (e.g. sys_user, project_task)',\n }),\n \n record_id: Field.text({\n label: 'Record ID',\n required: false,\n description: 'ID of the affected record',\n }),\n \n old_value: Field.textarea({\n label: 'Old Value',\n required: false,\n description: 'JSON-serialized previous state',\n }),\n \n new_value: Field.textarea({\n label: 'New Value',\n required: false,\n description: 'JSON-serialized new state',\n }),\n \n ip_address: Field.text({\n label: 'IP Address',\n required: false,\n maxLength: 45,\n }),\n \n user_agent: Field.textarea({\n label: 'User Agent',\n required: false,\n }),\n \n tenant_id: Field.text({\n label: 'Tenant ID',\n required: false,\n description: 'Tenant context for multi-tenant isolation',\n }),\n \n metadata: Field.textarea({\n label: 'Metadata',\n required: false,\n description: 'JSON-serialized additional context',\n }),\n },\n \n indexes: [\n { fields: ['created_at'] },\n { fields: ['user_id'] },\n { fields: ['object_name', 'record_id'] },\n { fields: ['action'] },\n { fields: ['tenant_id'] },\n ],\n \n enable: {\n trackHistory: false, // Audit logs are themselves the audit trail\n searchable: true,\n apiEnabled: true,\n apiMethods: ['get', 'list'], // Read-only — audit logs are immutable; creation happens via internal system hooks only\n trash: false, // Never soft-delete audit logs\n mru: false,\n clone: false,\n },\n});\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { Plugin, PluginContext } from '@objectstack/core';\nimport { SysAuditLog } from './objects/index.js';\n\n/**\n * AuditPlugin\n *\n * Registers the sys_audit_log system object with ObjectQL so it is\n * discoverable by the studio and available for CRUD operations.\n */\nexport class AuditPlugin implements Plugin {\n name = 'com.objectstack.audit';\n type = 'standard';\n version = '1.0.0';\n\n async init(ctx: PluginContext): Promise<void> {\n // Register audit system objects
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/objects/sys-audit-log.object.ts","../src/audit-plugin.ts"],"sourcesContent":["// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * @objectstack/plugin-audit\n *\n * Audit Plugin for ObjectStack\n * Provides the sys_audit_log system object definition for immutable audit trails.\n */\n\nexport { AuditPlugin } from './audit-plugin.js';\n\n// System Object Definitions (sys namespace)\nexport { SysAuditLog } from './objects/index.js';\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { ObjectSchema, Field } from '@objectstack/spec/data';\n\n/**\n * sys_audit_log — System Audit Log Object\n *\n * Immutable audit trail for all significant platform events.\n * Records who did what, when, and the before/after state.\n *\n * @namespace sys\n */\nexport const SysAuditLog = ObjectSchema.create({\n namespace: 'sys',\n name: 'audit_log',\n label: 'Audit Log',\n pluralLabel: 'Audit Logs',\n icon: 'scroll-text',\n isSystem: true,\n description: 'Immutable audit trail for platform events',\n titleFormat: '{action} on {object_name} by {user_id}',\n compactLayout: ['action', 'object_name', 'user_id', 'created_at'],\n \n fields: {\n id: Field.text({\n label: 'Audit Log ID',\n required: true,\n readonly: true,\n }),\n \n created_at: Field.datetime({\n label: 'Timestamp',\n required: true,\n defaultValue: 'NOW()',\n readonly: true,\n }),\n \n user_id: Field.text({\n label: 'User ID',\n required: false,\n description: 'User who performed the action (null for system actions)',\n }),\n \n action: Field.select(['create', 'update', 'delete', 'restore', 'login', 'logout', 'permission_change', 'config_change', 'export', 'import'], {\n label: 'Action',\n required: true,\n description: 'Action type (snake_case). Values: create, update, delete, restore, login, logout, permission_change, config_change, export, import',\n }),\n \n object_name: Field.text({\n label: 'Object Name',\n required: false,\n maxLength: 255,\n description: 'Target object (e.g. sys_user, project_task)',\n }),\n \n record_id: Field.text({\n label: 'Record ID',\n required: false,\n description: 'ID of the affected record',\n }),\n \n old_value: Field.textarea({\n label: 'Old Value',\n required: false,\n description: 'JSON-serialized previous state',\n }),\n \n new_value: Field.textarea({\n label: 'New Value',\n required: false,\n description: 'JSON-serialized new state',\n }),\n \n ip_address: Field.text({\n label: 'IP Address',\n required: false,\n maxLength: 45,\n }),\n \n user_agent: Field.textarea({\n label: 'User Agent',\n required: false,\n }),\n \n tenant_id: Field.text({\n label: 'Tenant ID',\n required: false,\n description: 'Tenant context for multi-tenant isolation',\n }),\n \n metadata: Field.textarea({\n label: 'Metadata',\n required: false,\n description: 'JSON-serialized additional context',\n }),\n },\n \n indexes: [\n { fields: ['created_at'] },\n { fields: ['user_id'] },\n { fields: ['object_name', 'record_id'] },\n { fields: ['action'] },\n { fields: ['tenant_id'] },\n ],\n \n enable: {\n trackHistory: false, // Audit logs are themselves the audit trail\n searchable: true,\n apiEnabled: true,\n apiMethods: ['get', 'list'], // Read-only — audit logs are immutable; creation happens via internal system hooks only\n trash: false, // Never soft-delete audit logs\n mru: false,\n clone: false,\n },\n});\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { Plugin, PluginContext } from '@objectstack/core';\nimport { SysAuditLog } from './objects/index.js';\n\n/**\n * AuditPlugin\n *\n * Registers the sys_audit_log system object with ObjectQL so it is\n * discoverable by the studio and available for CRUD operations.\n */\nexport class AuditPlugin implements Plugin {\n name = 'com.objectstack.audit';\n type = 'standard';\n version = '1.0.0';\n dependencies = ['com.objectstack.engine.objectql'];\n\n async init(ctx: PluginContext): Promise<void> {\n // Register audit system objects via the manifest service.\n ctx.getService<{ register(m: any): void }>('manifest').register({\n id: 'com.objectstack.audit',\n name: 'Audit',\n version: '1.0.0',\n type: 'plugin',\n namespace: 'sys',\n objects: [SysAuditLog],\n });\n\n // Contribute navigation items to the Setup App (if SetupPlugin is loaded).\n try {\n const setupNav = ctx.getService<{ contribute(c: any): void }>('setupNav');\n if (setupNav) {\n setupNav.contribute({\n areaId: 'area_system',\n items: [\n { id: 'nav_audit_logs', type: 'object', label: 'Audit Logs', objectName: 'audit_log', icon: 'scroll-text', order: 10 },\n ],\n });\n ctx.logger.info('Audit navigation items contributed to Setup App');\n }\n } catch {\n // SetupPlugin not loaded — skip silently\n }\n\n ctx.logger.info('Audit Plugin initialized');\n }\n}\n"],"mappings":"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","names":[]}
|
package/dist/index.mjs
CHANGED
|
@@ -100,9 +100,10 @@ var AuditPlugin = class {
|
|
|
100
100
|
this.name = "com.objectstack.audit";
|
|
101
101
|
this.type = "standard";
|
|
102
102
|
this.version = "1.0.0";
|
|
103
|
+
this.dependencies = ["com.objectstack.engine.objectql"];
|
|
103
104
|
}
|
|
104
105
|
async init(ctx) {
|
|
105
|
-
ctx.
|
|
106
|
+
ctx.getService("manifest").register({
|
|
106
107
|
id: "com.objectstack.audit",
|
|
107
108
|
name: "Audit",
|
|
108
109
|
version: "1.0.0",
|
|
@@ -110,6 +111,19 @@ var AuditPlugin = class {
|
|
|
110
111
|
namespace: "sys",
|
|
111
112
|
objects: [SysAuditLog]
|
|
112
113
|
});
|
|
114
|
+
try {
|
|
115
|
+
const setupNav = ctx.getService("setupNav");
|
|
116
|
+
if (setupNav) {
|
|
117
|
+
setupNav.contribute({
|
|
118
|
+
areaId: "area_system",
|
|
119
|
+
items: [
|
|
120
|
+
{ id: "nav_audit_logs", type: "object", label: "Audit Logs", objectName: "audit_log", icon: "scroll-text", order: 10 }
|
|
121
|
+
]
|
|
122
|
+
});
|
|
123
|
+
ctx.logger.info("Audit navigation items contributed to Setup App");
|
|
124
|
+
}
|
|
125
|
+
} catch {
|
|
126
|
+
}
|
|
113
127
|
ctx.logger.info("Audit Plugin initialized");
|
|
114
128
|
}
|
|
115
129
|
};
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/objects/sys-audit-log.object.ts","../src/audit-plugin.ts"],"sourcesContent":["// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { ObjectSchema, Field } from '@objectstack/spec/data';\n\n/**\n * sys_audit_log — System Audit Log Object\n *\n * Immutable audit trail for all significant platform events.\n * Records who did what, when, and the before/after state.\n *\n * @namespace sys\n */\nexport const SysAuditLog = ObjectSchema.create({\n namespace: 'sys',\n name: 'audit_log',\n label: 'Audit Log',\n pluralLabel: 'Audit Logs',\n icon: 'scroll-text',\n isSystem: true,\n description: 'Immutable audit trail for platform events',\n titleFormat: '{action} on {object_name} by {user_id}',\n compactLayout: ['action', 'object_name', 'user_id', 'created_at'],\n \n fields: {\n id: Field.text({\n label: 'Audit Log ID',\n required: true,\n readonly: true,\n }),\n \n created_at: Field.datetime({\n label: 'Timestamp',\n required: true,\n defaultValue: 'NOW()',\n readonly: true,\n }),\n \n user_id: Field.text({\n label: 'User ID',\n required: false,\n description: 'User who performed the action (null for system actions)',\n }),\n \n action: Field.select(['create', 'update', 'delete', 'restore', 'login', 'logout', 'permission_change', 'config_change', 'export', 'import'], {\n label: 'Action',\n required: true,\n description: 'Action type (snake_case). Values: create, update, delete, restore, login, logout, permission_change, config_change, export, import',\n }),\n \n object_name: Field.text({\n label: 'Object Name',\n required: false,\n maxLength: 255,\n description: 'Target object (e.g. sys_user, project_task)',\n }),\n \n record_id: Field.text({\n label: 'Record ID',\n required: false,\n description: 'ID of the affected record',\n }),\n \n old_value: Field.textarea({\n label: 'Old Value',\n required: false,\n description: 'JSON-serialized previous state',\n }),\n \n new_value: Field.textarea({\n label: 'New Value',\n required: false,\n description: 'JSON-serialized new state',\n }),\n \n ip_address: Field.text({\n label: 'IP Address',\n required: false,\n maxLength: 45,\n }),\n \n user_agent: Field.textarea({\n label: 'User Agent',\n required: false,\n }),\n \n tenant_id: Field.text({\n label: 'Tenant ID',\n required: false,\n description: 'Tenant context for multi-tenant isolation',\n }),\n \n metadata: Field.textarea({\n label: 'Metadata',\n required: false,\n description: 'JSON-serialized additional context',\n }),\n },\n \n indexes: [\n { fields: ['created_at'] },\n { fields: ['user_id'] },\n { fields: ['object_name', 'record_id'] },\n { fields: ['action'] },\n { fields: ['tenant_id'] },\n ],\n \n enable: {\n trackHistory: false, // Audit logs are themselves the audit trail\n searchable: true,\n apiEnabled: true,\n apiMethods: ['get', 'list'], // Read-only — audit logs are immutable; creation happens via internal system hooks only\n trash: false, // Never soft-delete audit logs\n mru: false,\n clone: false,\n },\n});\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { Plugin, PluginContext } from '@objectstack/core';\nimport { SysAuditLog } from './objects/index.js';\n\n/**\n * AuditPlugin\n *\n * Registers the sys_audit_log system object with ObjectQL so it is\n * discoverable by the studio and available for CRUD operations.\n */\nexport class AuditPlugin implements Plugin {\n name = 'com.objectstack.audit';\n type = 'standard';\n version = '1.0.0';\n\n async init(ctx: PluginContext): Promise<void> {\n // Register audit system objects
|
|
1
|
+
{"version":3,"sources":["../src/objects/sys-audit-log.object.ts","../src/audit-plugin.ts"],"sourcesContent":["// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { ObjectSchema, Field } from '@objectstack/spec/data';\n\n/**\n * sys_audit_log — System Audit Log Object\n *\n * Immutable audit trail for all significant platform events.\n * Records who did what, when, and the before/after state.\n *\n * @namespace sys\n */\nexport const SysAuditLog = ObjectSchema.create({\n namespace: 'sys',\n name: 'audit_log',\n label: 'Audit Log',\n pluralLabel: 'Audit Logs',\n icon: 'scroll-text',\n isSystem: true,\n description: 'Immutable audit trail for platform events',\n titleFormat: '{action} on {object_name} by {user_id}',\n compactLayout: ['action', 'object_name', 'user_id', 'created_at'],\n \n fields: {\n id: Field.text({\n label: 'Audit Log ID',\n required: true,\n readonly: true,\n }),\n \n created_at: Field.datetime({\n label: 'Timestamp',\n required: true,\n defaultValue: 'NOW()',\n readonly: true,\n }),\n \n user_id: Field.text({\n label: 'User ID',\n required: false,\n description: 'User who performed the action (null for system actions)',\n }),\n \n action: Field.select(['create', 'update', 'delete', 'restore', 'login', 'logout', 'permission_change', 'config_change', 'export', 'import'], {\n label: 'Action',\n required: true,\n description: 'Action type (snake_case). Values: create, update, delete, restore, login, logout, permission_change, config_change, export, import',\n }),\n \n object_name: Field.text({\n label: 'Object Name',\n required: false,\n maxLength: 255,\n description: 'Target object (e.g. sys_user, project_task)',\n }),\n \n record_id: Field.text({\n label: 'Record ID',\n required: false,\n description: 'ID of the affected record',\n }),\n \n old_value: Field.textarea({\n label: 'Old Value',\n required: false,\n description: 'JSON-serialized previous state',\n }),\n \n new_value: Field.textarea({\n label: 'New Value',\n required: false,\n description: 'JSON-serialized new state',\n }),\n \n ip_address: Field.text({\n label: 'IP Address',\n required: false,\n maxLength: 45,\n }),\n \n user_agent: Field.textarea({\n label: 'User Agent',\n required: false,\n }),\n \n tenant_id: Field.text({\n label: 'Tenant ID',\n required: false,\n description: 'Tenant context for multi-tenant isolation',\n }),\n \n metadata: Field.textarea({\n label: 'Metadata',\n required: false,\n description: 'JSON-serialized additional context',\n }),\n },\n \n indexes: [\n { fields: ['created_at'] },\n { fields: ['user_id'] },\n { fields: ['object_name', 'record_id'] },\n { fields: ['action'] },\n { fields: ['tenant_id'] },\n ],\n \n enable: {\n trackHistory: false, // Audit logs are themselves the audit trail\n searchable: true,\n apiEnabled: true,\n apiMethods: ['get', 'list'], // Read-only — audit logs are immutable; creation happens via internal system hooks only\n trash: false, // Never soft-delete audit logs\n mru: false,\n clone: false,\n },\n});\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { Plugin, PluginContext } from '@objectstack/core';\nimport { SysAuditLog } from './objects/index.js';\n\n/**\n * AuditPlugin\n *\n * Registers the sys_audit_log system object with ObjectQL so it is\n * discoverable by the studio and available for CRUD operations.\n */\nexport class AuditPlugin implements Plugin {\n name = 'com.objectstack.audit';\n type = 'standard';\n version = '1.0.0';\n dependencies = ['com.objectstack.engine.objectql'];\n\n async init(ctx: PluginContext): Promise<void> {\n // Register audit system objects via the manifest service.\n ctx.getService<{ register(m: any): void }>('manifest').register({\n id: 'com.objectstack.audit',\n name: 'Audit',\n version: '1.0.0',\n type: 'plugin',\n namespace: 'sys',\n objects: [SysAuditLog],\n });\n\n // Contribute navigation items to the Setup App (if SetupPlugin is loaded).\n try {\n const setupNav = ctx.getService<{ contribute(c: any): void }>('setupNav');\n if (setupNav) {\n setupNav.contribute({\n areaId: 'area_system',\n items: [\n { id: 'nav_audit_logs', type: 'object', label: 'Audit Logs', objectName: 'audit_log', icon: 'scroll-text', order: 10 },\n ],\n });\n ctx.logger.info('Audit navigation items contributed to Setup App');\n }\n } catch {\n // SetupPlugin not loaded — skip silently\n }\n\n ctx.logger.info('Audit Plugin initialized');\n }\n}\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@objectstack/plugin-audit",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.2",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"description": "Audit Plugin for ObjectStack — System audit log object and audit trail",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -13,11 +13,11 @@
|
|
|
13
13
|
}
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
|
-
"@objectstack/core": "4.0.
|
|
17
|
-
"@objectstack/spec": "4.0.
|
|
16
|
+
"@objectstack/core": "4.0.2",
|
|
17
|
+
"@objectstack/spec": "4.0.2"
|
|
18
18
|
},
|
|
19
19
|
"devDependencies": {
|
|
20
|
-
"@types/node": "^25.5.
|
|
20
|
+
"@types/node": "^25.5.2",
|
|
21
21
|
"typescript": "^6.0.2",
|
|
22
22
|
"vitest": "^4.1.2"
|
|
23
23
|
},
|
package/src/audit-plugin.ts
CHANGED
|
@@ -13,10 +13,11 @@ export class AuditPlugin implements Plugin {
|
|
|
13
13
|
name = 'com.objectstack.audit';
|
|
14
14
|
type = 'standard';
|
|
15
15
|
version = '1.0.0';
|
|
16
|
+
dependencies = ['com.objectstack.engine.objectql'];
|
|
16
17
|
|
|
17
18
|
async init(ctx: PluginContext): Promise<void> {
|
|
18
|
-
// Register audit system objects
|
|
19
|
-
ctx.
|
|
19
|
+
// Register audit system objects via the manifest service.
|
|
20
|
+
ctx.getService<{ register(m: any): void }>('manifest').register({
|
|
20
21
|
id: 'com.objectstack.audit',
|
|
21
22
|
name: 'Audit',
|
|
22
23
|
version: '1.0.0',
|
|
@@ -25,6 +26,22 @@ export class AuditPlugin implements Plugin {
|
|
|
25
26
|
objects: [SysAuditLog],
|
|
26
27
|
});
|
|
27
28
|
|
|
29
|
+
// Contribute navigation items to the Setup App (if SetupPlugin is loaded).
|
|
30
|
+
try {
|
|
31
|
+
const setupNav = ctx.getService<{ contribute(c: any): void }>('setupNav');
|
|
32
|
+
if (setupNav) {
|
|
33
|
+
setupNav.contribute({
|
|
34
|
+
areaId: 'area_system',
|
|
35
|
+
items: [
|
|
36
|
+
{ id: 'nav_audit_logs', type: 'object', label: 'Audit Logs', objectName: 'audit_log', icon: 'scroll-text', order: 10 },
|
|
37
|
+
],
|
|
38
|
+
});
|
|
39
|
+
ctx.logger.info('Audit navigation items contributed to Setup App');
|
|
40
|
+
}
|
|
41
|
+
} catch {
|
|
42
|
+
// SetupPlugin not loaded — skip silently
|
|
43
|
+
}
|
|
44
|
+
|
|
28
45
|
ctx.logger.info('Audit Plugin initialized');
|
|
29
46
|
}
|
|
30
47
|
}
|