@objectstack/plugin-audit 3.2.5
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 +22 -0
- package/LICENSE +202 -0
- package/dist/index.d.mts +2313 -0
- package/dist/index.d.ts +2313 -0
- package/dist/index.js +126 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +99 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +27 -0
- package/src/index.ts +11 -0
- package/src/objects/index.ts +9 -0
- package/src/objects/sys-audit-log.object.ts +116 -0
- package/tsconfig.json +9 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
SysAuditLog: () => SysAuditLog
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(index_exports);
|
|
26
|
+
|
|
27
|
+
// src/objects/sys-audit-log.object.ts
|
|
28
|
+
var import_data = require("@objectstack/spec/data");
|
|
29
|
+
var SysAuditLog = import_data.ObjectSchema.create({
|
|
30
|
+
namespace: "sys",
|
|
31
|
+
name: "audit_log",
|
|
32
|
+
label: "Audit Log",
|
|
33
|
+
pluralLabel: "Audit Logs",
|
|
34
|
+
icon: "scroll-text",
|
|
35
|
+
isSystem: true,
|
|
36
|
+
description: "Immutable audit trail for platform events",
|
|
37
|
+
titleFormat: "{action} on {object_name} by {user_id}",
|
|
38
|
+
compactLayout: ["action", "object_name", "user_id", "created_at"],
|
|
39
|
+
fields: {
|
|
40
|
+
id: import_data.Field.text({
|
|
41
|
+
label: "Audit Log ID",
|
|
42
|
+
required: true,
|
|
43
|
+
readonly: true
|
|
44
|
+
}),
|
|
45
|
+
created_at: import_data.Field.datetime({
|
|
46
|
+
label: "Timestamp",
|
|
47
|
+
required: true,
|
|
48
|
+
defaultValue: "NOW()",
|
|
49
|
+
readonly: true
|
|
50
|
+
}),
|
|
51
|
+
user_id: import_data.Field.text({
|
|
52
|
+
label: "User ID",
|
|
53
|
+
required: false,
|
|
54
|
+
description: "User who performed the action (null for system actions)"
|
|
55
|
+
}),
|
|
56
|
+
action: import_data.Field.select(["create", "update", "delete", "restore", "login", "logout", "permission_change", "config_change", "export", "import"], {
|
|
57
|
+
label: "Action",
|
|
58
|
+
required: true,
|
|
59
|
+
description: "Action type (snake_case). Values: create, update, delete, restore, login, logout, permission_change, config_change, export, import"
|
|
60
|
+
}),
|
|
61
|
+
object_name: import_data.Field.text({
|
|
62
|
+
label: "Object Name",
|
|
63
|
+
required: false,
|
|
64
|
+
maxLength: 255,
|
|
65
|
+
description: "Target object (e.g. sys_user, project_task)"
|
|
66
|
+
}),
|
|
67
|
+
record_id: import_data.Field.text({
|
|
68
|
+
label: "Record ID",
|
|
69
|
+
required: false,
|
|
70
|
+
description: "ID of the affected record"
|
|
71
|
+
}),
|
|
72
|
+
old_value: import_data.Field.textarea({
|
|
73
|
+
label: "Old Value",
|
|
74
|
+
required: false,
|
|
75
|
+
description: "JSON-serialized previous state"
|
|
76
|
+
}),
|
|
77
|
+
new_value: import_data.Field.textarea({
|
|
78
|
+
label: "New Value",
|
|
79
|
+
required: false,
|
|
80
|
+
description: "JSON-serialized new state"
|
|
81
|
+
}),
|
|
82
|
+
ip_address: import_data.Field.text({
|
|
83
|
+
label: "IP Address",
|
|
84
|
+
required: false,
|
|
85
|
+
maxLength: 45
|
|
86
|
+
}),
|
|
87
|
+
user_agent: import_data.Field.textarea({
|
|
88
|
+
label: "User Agent",
|
|
89
|
+
required: false
|
|
90
|
+
}),
|
|
91
|
+
tenant_id: import_data.Field.text({
|
|
92
|
+
label: "Tenant ID",
|
|
93
|
+
required: false,
|
|
94
|
+
description: "Tenant context for multi-tenant isolation"
|
|
95
|
+
}),
|
|
96
|
+
metadata: import_data.Field.textarea({
|
|
97
|
+
label: "Metadata",
|
|
98
|
+
required: false,
|
|
99
|
+
description: "JSON-serialized additional context"
|
|
100
|
+
})
|
|
101
|
+
},
|
|
102
|
+
indexes: [
|
|
103
|
+
{ fields: ["created_at"] },
|
|
104
|
+
{ fields: ["user_id"] },
|
|
105
|
+
{ fields: ["object_name", "record_id"] },
|
|
106
|
+
{ fields: ["action"] },
|
|
107
|
+
{ fields: ["tenant_id"] }
|
|
108
|
+
],
|
|
109
|
+
enable: {
|
|
110
|
+
trackHistory: false,
|
|
111
|
+
// Audit logs are themselves the audit trail
|
|
112
|
+
searchable: true,
|
|
113
|
+
apiEnabled: true,
|
|
114
|
+
apiMethods: ["get", "list"],
|
|
115
|
+
// Read-only — audit logs are immutable; creation happens via internal system hooks only
|
|
116
|
+
trash: false,
|
|
117
|
+
// Never soft-delete audit logs
|
|
118
|
+
mru: false,
|
|
119
|
+
clone: false
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
123
|
+
0 && (module.exports = {
|
|
124
|
+
SysAuditLog
|
|
125
|
+
});
|
|
126
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/objects/sys-audit-log.object.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\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"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACEA,kBAAoC;AAU7B,IAAM,cAAc,yBAAa,OAAO;AAAA,EAC7C,WAAW;AAAA,EACX,MAAM;AAAA,EACN,OAAO;AAAA,EACP,aAAa;AAAA,EACb,MAAM;AAAA,EACN,UAAU;AAAA,EACV,aAAa;AAAA,EACb,aAAa;AAAA,EACb,eAAe,CAAC,UAAU,eAAe,WAAW,YAAY;AAAA,EAEhE,QAAQ;AAAA,IACN,IAAI,kBAAM,KAAK;AAAA,MACb,OAAO;AAAA,MACP,UAAU;AAAA,MACV,UAAU;AAAA,IACZ,CAAC;AAAA,IAED,YAAY,kBAAM,SAAS;AAAA,MACzB,OAAO;AAAA,MACP,UAAU;AAAA,MACV,cAAc;AAAA,MACd,UAAU;AAAA,IACZ,CAAC;AAAA,IAED,SAAS,kBAAM,KAAK;AAAA,MAClB,OAAO;AAAA,MACP,UAAU;AAAA,MACV,aAAa;AAAA,IACf,CAAC;AAAA,IAED,QAAQ,kBAAM,OAAO,CAAC,UAAU,UAAU,UAAU,WAAW,SAAS,UAAU,qBAAqB,iBAAiB,UAAU,QAAQ,GAAG;AAAA,MAC3I,OAAO;AAAA,MACP,UAAU;AAAA,MACV,aAAa;AAAA,IACf,CAAC;AAAA,IAED,aAAa,kBAAM,KAAK;AAAA,MACtB,OAAO;AAAA,MACP,UAAU;AAAA,MACV,WAAW;AAAA,MACX,aAAa;AAAA,IACf,CAAC;AAAA,IAED,WAAW,kBAAM,KAAK;AAAA,MACpB,OAAO;AAAA,MACP,UAAU;AAAA,MACV,aAAa;AAAA,IACf,CAAC;AAAA,IAED,WAAW,kBAAM,SAAS;AAAA,MACxB,OAAO;AAAA,MACP,UAAU;AAAA,MACV,aAAa;AAAA,IACf,CAAC;AAAA,IAED,WAAW,kBAAM,SAAS;AAAA,MACxB,OAAO;AAAA,MACP,UAAU;AAAA,MACV,aAAa;AAAA,IACf,CAAC;AAAA,IAED,YAAY,kBAAM,KAAK;AAAA,MACrB,OAAO;AAAA,MACP,UAAU;AAAA,MACV,WAAW;AAAA,IACb,CAAC;AAAA,IAED,YAAY,kBAAM,SAAS;AAAA,MACzB,OAAO;AAAA,MACP,UAAU;AAAA,IACZ,CAAC;AAAA,IAED,WAAW,kBAAM,KAAK;AAAA,MACpB,OAAO;AAAA,MACP,UAAU;AAAA,MACV,aAAa;AAAA,IACf,CAAC;AAAA,IAED,UAAU,kBAAM,SAAS;AAAA,MACvB,OAAO;AAAA,MACP,UAAU;AAAA,MACV,aAAa;AAAA,IACf,CAAC;AAAA,EACH;AAAA,EAEA,SAAS;AAAA,IACP,EAAE,QAAQ,CAAC,YAAY,EAAE;AAAA,IACzB,EAAE,QAAQ,CAAC,SAAS,EAAE;AAAA,IACtB,EAAE,QAAQ,CAAC,eAAe,WAAW,EAAE;AAAA,IACvC,EAAE,QAAQ,CAAC,QAAQ,EAAE;AAAA,IACrB,EAAE,QAAQ,CAAC,WAAW,EAAE;AAAA,EAC1B;AAAA,EAEA,QAAQ;AAAA,IACN,cAAc;AAAA;AAAA,IACd,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,YAAY,CAAC,OAAO,MAAM;AAAA;AAAA,IAC1B,OAAO;AAAA;AAAA,IACP,KAAK;AAAA,IACL,OAAO;AAAA,EACT;AACF,CAAC;","names":[]}
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
// src/objects/sys-audit-log.object.ts
|
|
2
|
+
import { ObjectSchema, Field } from "@objectstack/spec/data";
|
|
3
|
+
var SysAuditLog = ObjectSchema.create({
|
|
4
|
+
namespace: "sys",
|
|
5
|
+
name: "audit_log",
|
|
6
|
+
label: "Audit Log",
|
|
7
|
+
pluralLabel: "Audit Logs",
|
|
8
|
+
icon: "scroll-text",
|
|
9
|
+
isSystem: true,
|
|
10
|
+
description: "Immutable audit trail for platform events",
|
|
11
|
+
titleFormat: "{action} on {object_name} by {user_id}",
|
|
12
|
+
compactLayout: ["action", "object_name", "user_id", "created_at"],
|
|
13
|
+
fields: {
|
|
14
|
+
id: Field.text({
|
|
15
|
+
label: "Audit Log ID",
|
|
16
|
+
required: true,
|
|
17
|
+
readonly: true
|
|
18
|
+
}),
|
|
19
|
+
created_at: Field.datetime({
|
|
20
|
+
label: "Timestamp",
|
|
21
|
+
required: true,
|
|
22
|
+
defaultValue: "NOW()",
|
|
23
|
+
readonly: true
|
|
24
|
+
}),
|
|
25
|
+
user_id: Field.text({
|
|
26
|
+
label: "User ID",
|
|
27
|
+
required: false,
|
|
28
|
+
description: "User who performed the action (null for system actions)"
|
|
29
|
+
}),
|
|
30
|
+
action: Field.select(["create", "update", "delete", "restore", "login", "logout", "permission_change", "config_change", "export", "import"], {
|
|
31
|
+
label: "Action",
|
|
32
|
+
required: true,
|
|
33
|
+
description: "Action type (snake_case). Values: create, update, delete, restore, login, logout, permission_change, config_change, export, import"
|
|
34
|
+
}),
|
|
35
|
+
object_name: Field.text({
|
|
36
|
+
label: "Object Name",
|
|
37
|
+
required: false,
|
|
38
|
+
maxLength: 255,
|
|
39
|
+
description: "Target object (e.g. sys_user, project_task)"
|
|
40
|
+
}),
|
|
41
|
+
record_id: Field.text({
|
|
42
|
+
label: "Record ID",
|
|
43
|
+
required: false,
|
|
44
|
+
description: "ID of the affected record"
|
|
45
|
+
}),
|
|
46
|
+
old_value: Field.textarea({
|
|
47
|
+
label: "Old Value",
|
|
48
|
+
required: false,
|
|
49
|
+
description: "JSON-serialized previous state"
|
|
50
|
+
}),
|
|
51
|
+
new_value: Field.textarea({
|
|
52
|
+
label: "New Value",
|
|
53
|
+
required: false,
|
|
54
|
+
description: "JSON-serialized new state"
|
|
55
|
+
}),
|
|
56
|
+
ip_address: Field.text({
|
|
57
|
+
label: "IP Address",
|
|
58
|
+
required: false,
|
|
59
|
+
maxLength: 45
|
|
60
|
+
}),
|
|
61
|
+
user_agent: Field.textarea({
|
|
62
|
+
label: "User Agent",
|
|
63
|
+
required: false
|
|
64
|
+
}),
|
|
65
|
+
tenant_id: Field.text({
|
|
66
|
+
label: "Tenant ID",
|
|
67
|
+
required: false,
|
|
68
|
+
description: "Tenant context for multi-tenant isolation"
|
|
69
|
+
}),
|
|
70
|
+
metadata: Field.textarea({
|
|
71
|
+
label: "Metadata",
|
|
72
|
+
required: false,
|
|
73
|
+
description: "JSON-serialized additional context"
|
|
74
|
+
})
|
|
75
|
+
},
|
|
76
|
+
indexes: [
|
|
77
|
+
{ fields: ["created_at"] },
|
|
78
|
+
{ fields: ["user_id"] },
|
|
79
|
+
{ fields: ["object_name", "record_id"] },
|
|
80
|
+
{ fields: ["action"] },
|
|
81
|
+
{ fields: ["tenant_id"] }
|
|
82
|
+
],
|
|
83
|
+
enable: {
|
|
84
|
+
trackHistory: false,
|
|
85
|
+
// Audit logs are themselves the audit trail
|
|
86
|
+
searchable: true,
|
|
87
|
+
apiEnabled: true,
|
|
88
|
+
apiMethods: ["get", "list"],
|
|
89
|
+
// Read-only — audit logs are immutable; creation happens via internal system hooks only
|
|
90
|
+
trash: false,
|
|
91
|
+
// Never soft-delete audit logs
|
|
92
|
+
mru: false,
|
|
93
|
+
clone: false
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
export {
|
|
97
|
+
SysAuditLog
|
|
98
|
+
};
|
|
99
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/objects/sys-audit-log.object.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"],"mappings":";AAEA,SAAS,cAAc,aAAa;AAU7B,IAAM,cAAc,aAAa,OAAO;AAAA,EAC7C,WAAW;AAAA,EACX,MAAM;AAAA,EACN,OAAO;AAAA,EACP,aAAa;AAAA,EACb,MAAM;AAAA,EACN,UAAU;AAAA,EACV,aAAa;AAAA,EACb,aAAa;AAAA,EACb,eAAe,CAAC,UAAU,eAAe,WAAW,YAAY;AAAA,EAEhE,QAAQ;AAAA,IACN,IAAI,MAAM,KAAK;AAAA,MACb,OAAO;AAAA,MACP,UAAU;AAAA,MACV,UAAU;AAAA,IACZ,CAAC;AAAA,IAED,YAAY,MAAM,SAAS;AAAA,MACzB,OAAO;AAAA,MACP,UAAU;AAAA,MACV,cAAc;AAAA,MACd,UAAU;AAAA,IACZ,CAAC;AAAA,IAED,SAAS,MAAM,KAAK;AAAA,MAClB,OAAO;AAAA,MACP,UAAU;AAAA,MACV,aAAa;AAAA,IACf,CAAC;AAAA,IAED,QAAQ,MAAM,OAAO,CAAC,UAAU,UAAU,UAAU,WAAW,SAAS,UAAU,qBAAqB,iBAAiB,UAAU,QAAQ,GAAG;AAAA,MAC3I,OAAO;AAAA,MACP,UAAU;AAAA,MACV,aAAa;AAAA,IACf,CAAC;AAAA,IAED,aAAa,MAAM,KAAK;AAAA,MACtB,OAAO;AAAA,MACP,UAAU;AAAA,MACV,WAAW;AAAA,MACX,aAAa;AAAA,IACf,CAAC;AAAA,IAED,WAAW,MAAM,KAAK;AAAA,MACpB,OAAO;AAAA,MACP,UAAU;AAAA,MACV,aAAa;AAAA,IACf,CAAC;AAAA,IAED,WAAW,MAAM,SAAS;AAAA,MACxB,OAAO;AAAA,MACP,UAAU;AAAA,MACV,aAAa;AAAA,IACf,CAAC;AAAA,IAED,WAAW,MAAM,SAAS;AAAA,MACxB,OAAO;AAAA,MACP,UAAU;AAAA,MACV,aAAa;AAAA,IACf,CAAC;AAAA,IAED,YAAY,MAAM,KAAK;AAAA,MACrB,OAAO;AAAA,MACP,UAAU;AAAA,MACV,WAAW;AAAA,IACb,CAAC;AAAA,IAED,YAAY,MAAM,SAAS;AAAA,MACzB,OAAO;AAAA,MACP,UAAU;AAAA,IACZ,CAAC;AAAA,IAED,WAAW,MAAM,KAAK;AAAA,MACpB,OAAO;AAAA,MACP,UAAU;AAAA,MACV,aAAa;AAAA,IACf,CAAC;AAAA,IAED,UAAU,MAAM,SAAS;AAAA,MACvB,OAAO;AAAA,MACP,UAAU;AAAA,MACV,aAAa;AAAA,IACf,CAAC;AAAA,EACH;AAAA,EAEA,SAAS;AAAA,IACP,EAAE,QAAQ,CAAC,YAAY,EAAE;AAAA,IACzB,EAAE,QAAQ,CAAC,SAAS,EAAE;AAAA,IACtB,EAAE,QAAQ,CAAC,eAAe,WAAW,EAAE;AAAA,IACvC,EAAE,QAAQ,CAAC,QAAQ,EAAE;AAAA,IACrB,EAAE,QAAQ,CAAC,WAAW,EAAE;AAAA,EAC1B;AAAA,EAEA,QAAQ;AAAA,IACN,cAAc;AAAA;AAAA,IACd,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,YAAY,CAAC,OAAO,MAAM;AAAA;AAAA,IAC1B,OAAO;AAAA;AAAA,IACP,KAAK;AAAA,IACL,OAAO;AAAA,EACT;AACF,CAAC;","names":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@objectstack/plugin-audit",
|
|
3
|
+
"version": "3.2.5",
|
|
4
|
+
"license": "Apache-2.0",
|
|
5
|
+
"description": "Audit Plugin for ObjectStack — System audit log object and audit trail",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.mjs",
|
|
12
|
+
"require": "./dist/index.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"dependencies": {
|
|
16
|
+
"@objectstack/spec": "3.2.5"
|
|
17
|
+
},
|
|
18
|
+
"devDependencies": {
|
|
19
|
+
"@types/node": "^25.3.5",
|
|
20
|
+
"typescript": "^5.0.0",
|
|
21
|
+
"vitest": "^4.0.18"
|
|
22
|
+
},
|
|
23
|
+
"scripts": {
|
|
24
|
+
"build": "tsup --config ../../../tsup.config.ts",
|
|
25
|
+
"test": "vitest run"
|
|
26
|
+
}
|
|
27
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @objectstack/plugin-audit
|
|
5
|
+
*
|
|
6
|
+
* Audit Plugin for ObjectStack
|
|
7
|
+
* Provides the sys_audit_log system object definition for immutable audit trails.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
// System Object Definitions (sys namespace)
|
|
11
|
+
export { SysAuditLog } from './objects/index.js';
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Audit Plugin — System Object Definitions (sys namespace)
|
|
5
|
+
*
|
|
6
|
+
* Canonical ObjectSchema definitions for audit-related system objects.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
export { SysAuditLog } from './sys-audit-log.object.js';
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
|
|
2
|
+
|
|
3
|
+
import { ObjectSchema, Field } from '@objectstack/spec/data';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* sys_audit_log — System Audit Log Object
|
|
7
|
+
*
|
|
8
|
+
* Immutable audit trail for all significant platform events.
|
|
9
|
+
* Records who did what, when, and the before/after state.
|
|
10
|
+
*
|
|
11
|
+
* @namespace sys
|
|
12
|
+
*/
|
|
13
|
+
export const SysAuditLog = ObjectSchema.create({
|
|
14
|
+
namespace: 'sys',
|
|
15
|
+
name: 'audit_log',
|
|
16
|
+
label: 'Audit Log',
|
|
17
|
+
pluralLabel: 'Audit Logs',
|
|
18
|
+
icon: 'scroll-text',
|
|
19
|
+
isSystem: true,
|
|
20
|
+
description: 'Immutable audit trail for platform events',
|
|
21
|
+
titleFormat: '{action} on {object_name} by {user_id}',
|
|
22
|
+
compactLayout: ['action', 'object_name', 'user_id', 'created_at'],
|
|
23
|
+
|
|
24
|
+
fields: {
|
|
25
|
+
id: Field.text({
|
|
26
|
+
label: 'Audit Log ID',
|
|
27
|
+
required: true,
|
|
28
|
+
readonly: true,
|
|
29
|
+
}),
|
|
30
|
+
|
|
31
|
+
created_at: Field.datetime({
|
|
32
|
+
label: 'Timestamp',
|
|
33
|
+
required: true,
|
|
34
|
+
defaultValue: 'NOW()',
|
|
35
|
+
readonly: true,
|
|
36
|
+
}),
|
|
37
|
+
|
|
38
|
+
user_id: Field.text({
|
|
39
|
+
label: 'User ID',
|
|
40
|
+
required: false,
|
|
41
|
+
description: 'User who performed the action (null for system actions)',
|
|
42
|
+
}),
|
|
43
|
+
|
|
44
|
+
action: Field.select(['create', 'update', 'delete', 'restore', 'login', 'logout', 'permission_change', 'config_change', 'export', 'import'], {
|
|
45
|
+
label: 'Action',
|
|
46
|
+
required: true,
|
|
47
|
+
description: 'Action type (snake_case). Values: create, update, delete, restore, login, logout, permission_change, config_change, export, import',
|
|
48
|
+
}),
|
|
49
|
+
|
|
50
|
+
object_name: Field.text({
|
|
51
|
+
label: 'Object Name',
|
|
52
|
+
required: false,
|
|
53
|
+
maxLength: 255,
|
|
54
|
+
description: 'Target object (e.g. sys_user, project_task)',
|
|
55
|
+
}),
|
|
56
|
+
|
|
57
|
+
record_id: Field.text({
|
|
58
|
+
label: 'Record ID',
|
|
59
|
+
required: false,
|
|
60
|
+
description: 'ID of the affected record',
|
|
61
|
+
}),
|
|
62
|
+
|
|
63
|
+
old_value: Field.textarea({
|
|
64
|
+
label: 'Old Value',
|
|
65
|
+
required: false,
|
|
66
|
+
description: 'JSON-serialized previous state',
|
|
67
|
+
}),
|
|
68
|
+
|
|
69
|
+
new_value: Field.textarea({
|
|
70
|
+
label: 'New Value',
|
|
71
|
+
required: false,
|
|
72
|
+
description: 'JSON-serialized new state',
|
|
73
|
+
}),
|
|
74
|
+
|
|
75
|
+
ip_address: Field.text({
|
|
76
|
+
label: 'IP Address',
|
|
77
|
+
required: false,
|
|
78
|
+
maxLength: 45,
|
|
79
|
+
}),
|
|
80
|
+
|
|
81
|
+
user_agent: Field.textarea({
|
|
82
|
+
label: 'User Agent',
|
|
83
|
+
required: false,
|
|
84
|
+
}),
|
|
85
|
+
|
|
86
|
+
tenant_id: Field.text({
|
|
87
|
+
label: 'Tenant ID',
|
|
88
|
+
required: false,
|
|
89
|
+
description: 'Tenant context for multi-tenant isolation',
|
|
90
|
+
}),
|
|
91
|
+
|
|
92
|
+
metadata: Field.textarea({
|
|
93
|
+
label: 'Metadata',
|
|
94
|
+
required: false,
|
|
95
|
+
description: 'JSON-serialized additional context',
|
|
96
|
+
}),
|
|
97
|
+
},
|
|
98
|
+
|
|
99
|
+
indexes: [
|
|
100
|
+
{ fields: ['created_at'] },
|
|
101
|
+
{ fields: ['user_id'] },
|
|
102
|
+
{ fields: ['object_name', 'record_id'] },
|
|
103
|
+
{ fields: ['action'] },
|
|
104
|
+
{ fields: ['tenant_id'] },
|
|
105
|
+
],
|
|
106
|
+
|
|
107
|
+
enable: {
|
|
108
|
+
trackHistory: false, // Audit logs are themselves the audit trail
|
|
109
|
+
searchable: true,
|
|
110
|
+
apiEnabled: true,
|
|
111
|
+
apiMethods: ['get', 'list'], // Read-only — audit logs are immutable; creation happens via internal system hooks only
|
|
112
|
+
trash: false, // Never soft-delete audit logs
|
|
113
|
+
mru: false,
|
|
114
|
+
clone: false,
|
|
115
|
+
},
|
|
116
|
+
});
|