@tailor-platform/erp-kit 0.0.1 → 0.1.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/README.md +196 -28
- package/dist/cli.js +894 -0
- package/package.json +65 -8
- package/rules/app-compose/backend/auth.md +78 -0
- package/rules/app-compose/frontend/auth.md +55 -0
- package/rules/app-compose/frontend/component.md +55 -0
- package/rules/app-compose/frontend/page.md +86 -0
- package/rules/app-compose/frontend/screen-detailview.md +112 -0
- package/rules/app-compose/frontend/screen-form.md +145 -0
- package/rules/app-compose/frontend/screen-listview.md +159 -0
- package/rules/app-compose/structure.md +32 -0
- package/rules/module-development/commands.md +54 -0
- package/rules/module-development/cross-module-type-injection.md +28 -0
- package/rules/module-development/dependency-modules.md +24 -0
- package/rules/module-development/errors.md +12 -0
- package/rules/module-development/executors.md +67 -0
- package/rules/module-development/exports.md +13 -0
- package/rules/module-development/models.md +34 -0
- package/rules/module-development/structure.md +27 -0
- package/rules/module-development/sync-vs-async-operations.md +83 -0
- package/rules/module-development/testing.md +43 -0
- package/rules/sdk-best-practices/db-relations.md +74 -0
- package/rules/sdk-best-practices/sdk-docs.md +14 -0
- package/schemas/app-compose/actors.yml +34 -0
- package/schemas/app-compose/business-flow.yml +50 -0
- package/schemas/app-compose/requirements.yml +33 -0
- package/schemas/app-compose/resolver.yml +47 -0
- package/schemas/app-compose/screen.yml +81 -0
- package/schemas/app-compose/story.yml +67 -0
- package/schemas/module/command.yml +52 -0
- package/schemas/module/feature.yml +58 -0
- package/schemas/module/model.yml +70 -0
- package/schemas/module/module.yml +50 -0
- package/skills/1-module-docs/SKILL.md +107 -0
- package/skills/2-module-feature-breakdown/SKILL.md +66 -0
- package/skills/3-module-doc-review/SKILL.md +230 -0
- package/skills/4-module-tdd-implementation/SKILL.md +56 -0
- package/skills/5-module-implementation-review/SKILL.md +400 -0
- package/skills/app-compose-1-requirement-analysis/SKILL.md +85 -0
- package/skills/app-compose-2-requirements-breakdown/SKILL.md +88 -0
- package/skills/app-compose-3-doc-review/SKILL.md +112 -0
- package/skills/app-compose-4-design-mock/SKILL.md +248 -0
- package/skills/app-compose-5-design-mock-review/SKILL.md +283 -0
- package/skills/app-compose-6-implementation-spec/SKILL.md +122 -0
- package/skills/mock-scenario/SKILL.md +118 -0
- package/src/app.ts +1 -0
- package/src/cli.ts +120 -0
- package/src/commands/check.test.ts +30 -0
- package/src/commands/check.ts +66 -0
- package/src/commands/init.test.ts +77 -0
- package/src/commands/init.ts +87 -0
- package/src/commands/mock/index.ts +53 -0
- package/src/commands/mock/start.ts +179 -0
- package/src/commands/mock/validate.test.ts +185 -0
- package/src/commands/mock/validate.ts +198 -0
- package/src/commands/scaffold.test.ts +76 -0
- package/src/commands/scaffold.ts +119 -0
- package/src/commands/sync-check.test.ts +125 -0
- package/src/commands/sync-check.ts +182 -0
- package/src/integration.test.ts +63 -0
- package/src/mdschema.ts +48 -0
- package/src/mockServer.ts +55 -0
- package/src/module.ts +86 -0
- package/src/modules/accounting/.gitkeep +0 -0
- package/src/modules/coa-management/.gitkeep +0 -0
- package/src/modules/inventory/.gitkeep +0 -0
- package/src/modules/manufacturing/.gitkeep +0 -0
- package/src/modules/primitives/README.md +39 -0
- package/src/modules/primitives/command/activateCategory.test.ts +75 -0
- package/src/modules/primitives/command/activateCategory.ts +50 -0
- package/src/modules/primitives/command/activateCurrency.test.ts +70 -0
- package/src/modules/primitives/command/activateCurrency.ts +50 -0
- package/src/modules/primitives/command/activateUnit.test.ts +53 -0
- package/src/modules/primitives/command/activateUnit.ts +50 -0
- package/src/modules/primitives/command/convertAmount.test.ts +275 -0
- package/src/modules/primitives/command/convertAmount.ts +126 -0
- package/src/modules/primitives/command/convertQuantity.test.ts +219 -0
- package/src/modules/primitives/command/convertQuantity.ts +73 -0
- package/src/modules/primitives/command/createCategory.test.ts +126 -0
- package/src/modules/primitives/command/createCategory.ts +89 -0
- package/src/modules/primitives/command/createCurrency.test.ts +191 -0
- package/src/modules/primitives/command/createCurrency.ts +77 -0
- package/src/modules/primitives/command/createExchangeRate.test.ts +216 -0
- package/src/modules/primitives/command/createExchangeRate.ts +91 -0
- package/src/modules/primitives/command/createUnit.test.ts +214 -0
- package/src/modules/primitives/command/createUnit.ts +88 -0
- package/src/modules/primitives/command/deactivateCategory.test.ts +97 -0
- package/src/modules/primitives/command/deactivateCategory.ts +62 -0
- package/src/modules/primitives/command/deactivateCurrency.test.ts +85 -0
- package/src/modules/primitives/command/deactivateCurrency.ts +55 -0
- package/src/modules/primitives/command/deactivateUnit.test.ts +78 -0
- package/src/modules/primitives/command/deactivateUnit.ts +62 -0
- package/src/modules/primitives/command/setBaseCurrency.test.ts +98 -0
- package/src/modules/primitives/command/setBaseCurrency.ts +74 -0
- package/src/modules/primitives/command/setReferenceUnit.test.ts +108 -0
- package/src/modules/primitives/command/setReferenceUnit.ts +84 -0
- package/src/modules/primitives/db/currency.ts +30 -0
- package/src/modules/primitives/db/exchangeRate.ts +28 -0
- package/src/modules/primitives/db/unit.ts +32 -0
- package/src/modules/primitives/db/uomCategory.ts +32 -0
- package/src/modules/primitives/docs/commands/ActivateCategory.md +34 -0
- package/src/modules/primitives/docs/commands/ActivateCurrency.md +33 -0
- package/src/modules/primitives/docs/commands/ActivateUnit.md +34 -0
- package/src/modules/primitives/docs/commands/ConvertAmount.md +50 -0
- package/src/modules/primitives/docs/commands/ConvertQuantity.md +43 -0
- package/src/modules/primitives/docs/commands/CreateCategory.md +44 -0
- package/src/modules/primitives/docs/commands/CreateCurrency.md +47 -0
- package/src/modules/primitives/docs/commands/CreateExchangeRate.md +48 -0
- package/src/modules/primitives/docs/commands/CreateUnit.md +48 -0
- package/src/modules/primitives/docs/commands/DeactivateCategory.md +38 -0
- package/src/modules/primitives/docs/commands/DeactivateCurrency.md +38 -0
- package/src/modules/primitives/docs/commands/DeactivateUnit.md +38 -0
- package/src/modules/primitives/docs/commands/SetBaseCurrency.md +39 -0
- package/src/modules/primitives/docs/commands/SetReferenceUnit.md +43 -0
- package/src/modules/primitives/docs/features/currency-definitions.md +55 -0
- package/src/modules/primitives/docs/features/exchange-rates.md +61 -0
- package/src/modules/primitives/docs/features/unit-conversion.md +66 -0
- package/src/modules/primitives/docs/features/uom-categories.md +52 -0
- package/src/modules/primitives/docs/models/Currency.md +45 -0
- package/src/modules/primitives/docs/models/ExchangeRate.md +33 -0
- package/src/modules/primitives/docs/models/Unit.md +46 -0
- package/src/modules/primitives/docs/models/UoMCategory.md +44 -0
- package/src/modules/primitives/generated/kysely-tailordb.ts +95 -0
- package/src/modules/primitives/index.ts +40 -0
- package/src/modules/primitives/lib/errors.ts +138 -0
- package/src/modules/primitives/lib/types.ts +20 -0
- package/src/modules/primitives/module.ts +66 -0
- package/src/modules/primitives/permissions.ts +18 -0
- package/src/modules/primitives/tailor.config.ts +11 -0
- package/src/modules/primitives/testing/fixtures.ts +161 -0
- package/src/modules/product-management/.gitkeep +0 -0
- package/src/modules/purchase/.gitkeep +0 -0
- package/src/modules/sales/.gitkeep +0 -0
- package/src/modules/shared/createContext.test.ts +39 -0
- package/src/modules/shared/createContext.ts +15 -0
- package/src/modules/shared/defineCommand.test.ts +42 -0
- package/src/modules/shared/defineCommand.ts +19 -0
- package/src/modules/shared/definePermissions.test.ts +146 -0
- package/src/modules/shared/definePermissions.ts +94 -0
- package/src/modules/shared/entityTypes.ts +15 -0
- package/src/modules/shared/errors.ts +22 -0
- package/src/modules/shared/index.ts +1 -0
- package/src/modules/shared/internal.ts +13 -0
- package/src/modules/shared/requirePermission.test.ts +47 -0
- package/src/modules/shared/requirePermission.ts +8 -0
- package/src/modules/shared/types.ts +4 -0
- package/src/modules/supplier-management/.gitkeep +0 -0
- package/src/modules/supplier-portal/.gitkeep +0 -0
- package/src/modules/testing/index.ts +120 -0
- package/src/modules/user-management/README.md +38 -0
- package/src/modules/user-management/command/activateUser.test.ts +112 -0
- package/src/modules/user-management/command/activateUser.ts +67 -0
- package/src/modules/user-management/command/assignPermissionToRole.test.ts +119 -0
- package/src/modules/user-management/command/assignPermissionToRole.ts +87 -0
- package/src/modules/user-management/command/assignRoleToUser.test.ts +162 -0
- package/src/modules/user-management/command/assignRoleToUser.ts +93 -0
- package/src/modules/user-management/command/createPermission.test.ts +143 -0
- package/src/modules/user-management/command/createPermission.ts +66 -0
- package/src/modules/user-management/command/createRole.test.ts +115 -0
- package/src/modules/user-management/command/createRole.ts +52 -0
- package/src/modules/user-management/command/createUser.test.ts +198 -0
- package/src/modules/user-management/command/createUser.ts +85 -0
- package/src/modules/user-management/command/deactivateUser.test.ts +112 -0
- package/src/modules/user-management/command/deactivateUser.ts +67 -0
- package/src/modules/user-management/command/logAuditEvent.test.ts +179 -0
- package/src/modules/user-management/command/logAuditEvent.ts +59 -0
- package/src/modules/user-management/command/reactivateUser.test.ts +115 -0
- package/src/modules/user-management/command/reactivateUser.ts +67 -0
- package/src/modules/user-management/command/revokePermissionFromRole.test.ts +112 -0
- package/src/modules/user-management/command/revokePermissionFromRole.ts +81 -0
- package/src/modules/user-management/command/revokeRoleFromUser.test.ts +112 -0
- package/src/modules/user-management/command/revokeRoleFromUser.ts +81 -0
- package/src/modules/user-management/db/auditEvent.ts +47 -0
- package/src/modules/user-management/db/permission.ts +31 -0
- package/src/modules/user-management/db/role.ts +28 -0
- package/src/modules/user-management/db/rolePermission.ts +44 -0
- package/src/modules/user-management/db/user.ts +38 -0
- package/src/modules/user-management/db/userRole.ts +44 -0
- package/src/modules/user-management/docs/commands/ActivateUser.md +36 -0
- package/src/modules/user-management/docs/commands/AssignPermissionToRole.md +39 -0
- package/src/modules/user-management/docs/commands/AssignRoleToUser.md +43 -0
- package/src/modules/user-management/docs/commands/CreatePermission.md +35 -0
- package/src/modules/user-management/docs/commands/CreateRole.md +35 -0
- package/src/modules/user-management/docs/commands/CreateUser.md +41 -0
- package/src/modules/user-management/docs/commands/DeactivateUser.md +38 -0
- package/src/modules/user-management/docs/commands/LogAuditEvent.md +37 -0
- package/src/modules/user-management/docs/commands/ReactivateUser.md +37 -0
- package/src/modules/user-management/docs/commands/RevokePermissionFromRole.md +40 -0
- package/src/modules/user-management/docs/commands/RevokeRoleFromUser.md +40 -0
- package/src/modules/user-management/docs/features/audit-trail.md +80 -0
- package/src/modules/user-management/docs/features/role-based-access-control.md +76 -0
- package/src/modules/user-management/docs/features/user-account-management.md +64 -0
- package/src/modules/user-management/docs/models/AuditEvent.md +34 -0
- package/src/modules/user-management/docs/models/Permission.md +31 -0
- package/src/modules/user-management/docs/models/Role.md +31 -0
- package/src/modules/user-management/docs/models/RolePermission.md +33 -0
- package/src/modules/user-management/docs/models/User.md +47 -0
- package/src/modules/user-management/docs/models/UserRole.md +34 -0
- package/src/modules/user-management/docs/plans/2026-01-30-flattened-permissions-design.md +52 -0
- package/src/modules/user-management/executor/recomputeOnRolePermissionChange.ts +61 -0
- package/src/modules/user-management/generated/enums.ts +24 -0
- package/src/modules/user-management/generated/kysely-tailordb.ts +112 -0
- package/src/modules/user-management/index.ts +32 -0
- package/src/modules/user-management/lib/errors.ts +81 -0
- package/src/modules/user-management/lib/recomputeUserPermissions.ts +53 -0
- package/src/modules/user-management/lib/types.ts +31 -0
- package/src/modules/user-management/module.ts +77 -0
- package/src/modules/user-management/permissions.ts +15 -0
- package/src/modules/user-management/tailor.config.ts +11 -0
- package/src/modules/user-management/testing/fixtures.ts +98 -0
- package/src/schemas.ts +25 -0
- package/src/testing.ts +10 -0
- package/src/util.ts +3 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import {
|
|
2
|
+
db,
|
|
3
|
+
unsafeAllowAllGqlPermission,
|
|
4
|
+
unsafeAllowAllTypePermission,
|
|
5
|
+
} from "@tailor-platform/sdk";
|
|
6
|
+
import { role } from "./role";
|
|
7
|
+
import { permission } from "./permission";
|
|
8
|
+
|
|
9
|
+
export interface CreateRolePermissionTypeParams {
|
|
10
|
+
fields?: Record<string, unknown>;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function createRolePermissionType(params: CreateRolePermissionTypeParams) {
|
|
14
|
+
return db
|
|
15
|
+
.type("RolePermission", {
|
|
16
|
+
roleId: db
|
|
17
|
+
.uuid()
|
|
18
|
+
.relation({
|
|
19
|
+
type: "n-1",
|
|
20
|
+
toward: { type: role },
|
|
21
|
+
backward: "rolePermissions",
|
|
22
|
+
})
|
|
23
|
+
.description("Foreign key to Role"),
|
|
24
|
+
permissionId: db
|
|
25
|
+
.uuid()
|
|
26
|
+
.relation({
|
|
27
|
+
type: "n-1",
|
|
28
|
+
toward: { type: permission },
|
|
29
|
+
backward: "rolePermissions",
|
|
30
|
+
})
|
|
31
|
+
.description("Foreign key to Permission"),
|
|
32
|
+
...params.fields,
|
|
33
|
+
...db.fields.timestamps(),
|
|
34
|
+
})
|
|
35
|
+
.indexes({
|
|
36
|
+
fields: ["roleId", "permissionId"],
|
|
37
|
+
unique: true,
|
|
38
|
+
name: "role_permission_unique_idx",
|
|
39
|
+
})
|
|
40
|
+
.permission(unsafeAllowAllTypePermission)
|
|
41
|
+
.gqlPermission(unsafeAllowAllGqlPermission);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export const rolePermission = createRolePermissionType({});
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import {
|
|
2
|
+
db,
|
|
3
|
+
type TailorAnyDBField,
|
|
4
|
+
unsafeAllowAllGqlPermission,
|
|
5
|
+
unsafeAllowAllTypePermission,
|
|
6
|
+
} from "@tailor-platform/sdk";
|
|
7
|
+
|
|
8
|
+
export interface CreateUserTypeParams<F extends Record<string, TailorAnyDBField>> {
|
|
9
|
+
fields?: F;
|
|
10
|
+
additionalStatuses?: string[];
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const BASE_STATUSES = ["PENDING", "ACTIVE", "INACTIVE"] as const;
|
|
14
|
+
|
|
15
|
+
export function createUserType<const F extends Record<string, TailorAnyDBField>>(
|
|
16
|
+
params: CreateUserTypeParams<F>,
|
|
17
|
+
) {
|
|
18
|
+
const statuses = [...BASE_STATUSES, ...(params.additionalStatuses ?? [])] as [
|
|
19
|
+
string,
|
|
20
|
+
...string[],
|
|
21
|
+
];
|
|
22
|
+
|
|
23
|
+
return db
|
|
24
|
+
.type("User", {
|
|
25
|
+
email: db.string().unique().description("User email address (unique identifier)"),
|
|
26
|
+
name: db.string().description("User display name"),
|
|
27
|
+
status: db.enum(statuses).description("User status"),
|
|
28
|
+
permissions: db
|
|
29
|
+
.string({ array: true, optional: true })
|
|
30
|
+
.description("Flattened permission keys from all assigned roles"),
|
|
31
|
+
...((params.fields ?? {}) as F),
|
|
32
|
+
...db.fields.timestamps(),
|
|
33
|
+
})
|
|
34
|
+
.permission(unsafeAllowAllTypePermission)
|
|
35
|
+
.gqlPermission(unsafeAllowAllGqlPermission);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export const user = createUserType({});
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import {
|
|
2
|
+
db,
|
|
3
|
+
unsafeAllowAllGqlPermission,
|
|
4
|
+
unsafeAllowAllTypePermission,
|
|
5
|
+
} from "@tailor-platform/sdk";
|
|
6
|
+
import { user } from "./user";
|
|
7
|
+
import { role } from "./role";
|
|
8
|
+
|
|
9
|
+
export interface CreateUserRoleTypeParams {
|
|
10
|
+
fields?: Record<string, unknown>;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function createUserRoleType(params: CreateUserRoleTypeParams) {
|
|
14
|
+
return db
|
|
15
|
+
.type("UserRole", {
|
|
16
|
+
userId: db
|
|
17
|
+
.uuid()
|
|
18
|
+
.relation({
|
|
19
|
+
type: "n-1",
|
|
20
|
+
toward: { type: user },
|
|
21
|
+
backward: "userRoles",
|
|
22
|
+
})
|
|
23
|
+
.description("Foreign key to User"),
|
|
24
|
+
roleId: db
|
|
25
|
+
.uuid()
|
|
26
|
+
.relation({
|
|
27
|
+
type: "n-1",
|
|
28
|
+
toward: { type: role },
|
|
29
|
+
backward: "userRoles",
|
|
30
|
+
})
|
|
31
|
+
.description("Foreign key to Role"),
|
|
32
|
+
...params.fields,
|
|
33
|
+
...db.fields.timestamps(),
|
|
34
|
+
})
|
|
35
|
+
.indexes({
|
|
36
|
+
fields: ["userId", "roleId"],
|
|
37
|
+
unique: true,
|
|
38
|
+
name: "user_role_unique_idx",
|
|
39
|
+
})
|
|
40
|
+
.permission(unsafeAllowAllTypePermission)
|
|
41
|
+
.gqlPermission(unsafeAllowAllGqlPermission);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export const userRole = createUserRoleType({});
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# ActivateUser
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
ActivateUser transitions a user from PENDING status to ACTIVE status, granting them full access to the system. This command is typically executed by an administrator after the user's identity has been verified and onboarding requirements are complete.
|
|
6
|
+
|
|
7
|
+
Only users in PENDING status can be activated. Attempting to activate an already active or inactive user will fail.
|
|
8
|
+
|
|
9
|
+
## Business Rules
|
|
10
|
+
|
|
11
|
+
- User must exist in the system
|
|
12
|
+
- User must be in PENDING status
|
|
13
|
+
- Transitions user status from PENDING to ACTIVE
|
|
14
|
+
- Generates USER_ACTIVATED audit event with actor ID, timestamp, and previous status
|
|
15
|
+
|
|
16
|
+
## Process Flow
|
|
17
|
+
|
|
18
|
+
```mermaid
|
|
19
|
+
flowchart TD
|
|
20
|
+
A[Receive activate request] --> B{User exists?}
|
|
21
|
+
B -->|No| C[Return error: USER_NOT_FOUND]
|
|
22
|
+
B -->|Yes| D{Status is PENDING?}
|
|
23
|
+
D -->|No| E[Return error: INVALID_STATUS_TRANSITION]
|
|
24
|
+
D -->|Yes| F[Update status to ACTIVE]
|
|
25
|
+
F --> G[Log USER_ACTIVATED audit event]
|
|
26
|
+
G --> H[Return updated user]
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## External Dependencies
|
|
30
|
+
|
|
31
|
+
- None
|
|
32
|
+
|
|
33
|
+
## Error Scenarios
|
|
34
|
+
|
|
35
|
+
- **USER_NOT_FOUND**: User ID does not exist in the system - return not found error with the provided ID
|
|
36
|
+
- **INVALID_STATUS_TRANSITION**: User is not in PENDING status (already ACTIVE or INACTIVE) - return error with current status and valid transitions
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# AssignPermissionToRole
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
AssignPermissionToRole creates an association between a permission and a role, granting that permission to all users who have the role assigned. This command enables building up role capabilities by adding permissions one at a time.
|
|
6
|
+
|
|
7
|
+
The operation is idempotent - assigning the same permission to a role twice does not create duplicate records or return an error.
|
|
8
|
+
|
|
9
|
+
## Business Rules
|
|
10
|
+
|
|
11
|
+
- Role must exist in the system
|
|
12
|
+
- Permission must exist in the system
|
|
13
|
+
- Operation is idempotent (assigning same permission twice is not an error)
|
|
14
|
+
- Creates RolePermission association record if not already present
|
|
15
|
+
- Generates PERMISSION_ASSIGNED audit event with actor ID, role ID, permission ID, and timestamp
|
|
16
|
+
|
|
17
|
+
## Process Flow
|
|
18
|
+
|
|
19
|
+
```mermaid
|
|
20
|
+
flowchart TD
|
|
21
|
+
A[Receive assign request] --> B{Role exists?}
|
|
22
|
+
B -->|No| C[Return error: ROLE_NOT_FOUND]
|
|
23
|
+
B -->|Yes| D{Permission exists?}
|
|
24
|
+
D -->|No| E[Return error: PERMISSION_NOT_FOUND]
|
|
25
|
+
D -->|Yes| F{Assignment exists?}
|
|
26
|
+
F -->|Yes| G[Return success - idempotent]
|
|
27
|
+
F -->|No| H[Create RolePermission record]
|
|
28
|
+
H --> I[Log PERMISSION_ASSIGNED audit event]
|
|
29
|
+
I --> J[Return success]
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## External Dependencies
|
|
33
|
+
|
|
34
|
+
- None
|
|
35
|
+
|
|
36
|
+
## Error Scenarios
|
|
37
|
+
|
|
38
|
+
- **ROLE_NOT_FOUND**: Role ID does not exist in the system - return not found error with the provided role ID
|
|
39
|
+
- **PERMISSION_NOT_FOUND**: Permission ID does not exist in the system - return not found error with the provided permission ID
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# AssignRoleToUser
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
AssignRoleToUser creates an association between a role and a user, granting the user all permissions associated with that role. This command enables granting access to users by assigning them roles rather than managing permissions individually.
|
|
6
|
+
|
|
7
|
+
Only ACTIVE users can receive role assignments. The operation is idempotent - assigning the same role to a user twice does not create duplicate records or return an error.
|
|
8
|
+
|
|
9
|
+
## Business Rules
|
|
10
|
+
|
|
11
|
+
- User must exist in the system
|
|
12
|
+
- Role must exist in the system
|
|
13
|
+
- User must be in ACTIVE status
|
|
14
|
+
- Operation is idempotent (assigning same role twice is not an error)
|
|
15
|
+
- Creates UserRole association record if not already present
|
|
16
|
+
- Generates ROLE_ASSIGNED audit event with actor ID, user ID, role ID, and timestamp
|
|
17
|
+
|
|
18
|
+
## Process Flow
|
|
19
|
+
|
|
20
|
+
```mermaid
|
|
21
|
+
flowchart TD
|
|
22
|
+
A[Receive assign request] --> B{User exists?}
|
|
23
|
+
B -->|No| C[Return error: USER_NOT_FOUND]
|
|
24
|
+
B -->|Yes| D{Role exists?}
|
|
25
|
+
D -->|No| E[Return error: ROLE_NOT_FOUND]
|
|
26
|
+
D -->|Yes| F{User is ACTIVE?}
|
|
27
|
+
F -->|No| G[Return error: USER_NOT_ACTIVE]
|
|
28
|
+
F -->|Yes| H{Assignment exists?}
|
|
29
|
+
H -->|Yes| I[Return success - idempotent]
|
|
30
|
+
H -->|No| J[Create UserRole record]
|
|
31
|
+
J --> K[Log ROLE_ASSIGNED audit event]
|
|
32
|
+
K --> L[Return success]
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## External Dependencies
|
|
36
|
+
|
|
37
|
+
- None
|
|
38
|
+
|
|
39
|
+
## Error Scenarios
|
|
40
|
+
|
|
41
|
+
- **USER_NOT_FOUND**: User ID does not exist in the system - return not found error with the provided user ID
|
|
42
|
+
- **ROLE_NOT_FOUND**: Role ID does not exist in the system - return not found error with the provided role ID
|
|
43
|
+
- **USER_NOT_ACTIVE**: User is in PENDING or INACTIVE status - return error indicating only ACTIVE users can receive role assignments
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# CreatePermission
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
CreatePermission defines a new permission in the system using the `resource:action` format. Permissions are the atomic unit of authorization, specifying what action can be performed on what resource. Examples include `orders:read`, `orders:write`, `users:delete`.
|
|
6
|
+
|
|
7
|
+
Permissions are assigned to roles, which are then assigned to users. This indirection simplifies access management at scale.
|
|
8
|
+
|
|
9
|
+
## Business Rules
|
|
10
|
+
|
|
11
|
+
- Permission key must follow `resource:action` format (lowercase letters, colon separator)
|
|
12
|
+
- Permission key must be unique across all permissions
|
|
13
|
+
- Description is optional but recommended for clarity
|
|
14
|
+
- Generates PERMISSION_ASSIGNED audit event when assigned to a role (via assignPermissionToRole)
|
|
15
|
+
|
|
16
|
+
## Process Flow
|
|
17
|
+
|
|
18
|
+
```mermaid
|
|
19
|
+
flowchart TD
|
|
20
|
+
A[Receive create request] --> B{Validate key format}
|
|
21
|
+
B -->|Invalid| C[Return error: INVALID_KEY_FORMAT]
|
|
22
|
+
B -->|Valid| D{Key unique?}
|
|
23
|
+
D -->|No| E[Return error: PERMISSION_ALREADY_EXISTS]
|
|
24
|
+
D -->|Yes| F[Create permission record]
|
|
25
|
+
F --> G[Return created permission]
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## External Dependencies
|
|
29
|
+
|
|
30
|
+
- None
|
|
31
|
+
|
|
32
|
+
## Error Scenarios
|
|
33
|
+
|
|
34
|
+
- **INVALID_KEY_FORMAT**: Key does not match `resource:action` pattern - return validation error with format requirements
|
|
35
|
+
- **PERMISSION_ALREADY_EXISTS**: Permission with the same key already exists - return conflict error with existing permission reference
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# CreateRole
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
CreateRole establishes a new role in the system with a unique name and optional description. Roles are containers for permissions that can be assigned to users, providing a level of abstraction that simplifies access management. Examples include "Sales Representative", "Sales Manager", "Administrator".
|
|
6
|
+
|
|
7
|
+
Roles follow the principle of least privilege, bundling only the permissions necessary for a specific job function.
|
|
8
|
+
|
|
9
|
+
## Business Rules
|
|
10
|
+
|
|
11
|
+
- Role name must be unique across all roles
|
|
12
|
+
- Role name is required and cannot be empty
|
|
13
|
+
- Description is optional but recommended for clarity
|
|
14
|
+
- New roles start with no permissions assigned
|
|
15
|
+
|
|
16
|
+
## Process Flow
|
|
17
|
+
|
|
18
|
+
```mermaid
|
|
19
|
+
flowchart TD
|
|
20
|
+
A[Receive create request] --> B{Name provided?}
|
|
21
|
+
B -->|No| C[Return error: MISSING_REQUIRED_FIELD]
|
|
22
|
+
B -->|Yes| D{Name unique?}
|
|
23
|
+
D -->|No| E[Return error: ROLE_ALREADY_EXISTS]
|
|
24
|
+
D -->|Yes| F[Create role record]
|
|
25
|
+
F --> G[Return created role]
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## External Dependencies
|
|
29
|
+
|
|
30
|
+
- None
|
|
31
|
+
|
|
32
|
+
## Error Scenarios
|
|
33
|
+
|
|
34
|
+
- **MISSING_REQUIRED_FIELD**: Role name not provided - return validation error indicating name is required
|
|
35
|
+
- **ROLE_ALREADY_EXISTS**: Role with the same name already exists - return conflict error with existing role reference
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# CreateUser
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
CreateUser establishes a new user account in the system with the provided name and email address. The user is created in PENDING status, awaiting activation by an administrator after verification is complete. This command supports the user onboarding process where new accounts must be verified before gaining system access.
|
|
6
|
+
|
|
7
|
+
This command enforces email uniqueness across all users (active and inactive) to prevent duplicate accounts.
|
|
8
|
+
|
|
9
|
+
## Business Rules
|
|
10
|
+
|
|
11
|
+
- Email must be unique across all users (active and inactive)
|
|
12
|
+
- Email must follow valid email format
|
|
13
|
+
- Name is required and cannot be empty
|
|
14
|
+
- New users are created in PENDING status
|
|
15
|
+
- Generates USER_CREATED audit event with actor ID and timestamp
|
|
16
|
+
|
|
17
|
+
## Process Flow
|
|
18
|
+
|
|
19
|
+
```mermaid
|
|
20
|
+
flowchart TD
|
|
21
|
+
A[Receive create request] --> B{Validate email format}
|
|
22
|
+
B -->|Invalid| C[Return error: INVALID_EMAIL]
|
|
23
|
+
B -->|Valid| D{Email unique?}
|
|
24
|
+
D -->|No| E[Return error: USER_ALREADY_EXISTS]
|
|
25
|
+
D -->|Yes| F{Name provided?}
|
|
26
|
+
F -->|No| G[Return error: MISSING_REQUIRED_FIELD]
|
|
27
|
+
F -->|Yes| H[Create user record]
|
|
28
|
+
H --> I[Set status: PENDING]
|
|
29
|
+
I --> J[Log USER_CREATED audit event]
|
|
30
|
+
J --> K[Return created user]
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## External Dependencies
|
|
34
|
+
|
|
35
|
+
- None
|
|
36
|
+
|
|
37
|
+
## Error Scenarios
|
|
38
|
+
|
|
39
|
+
- **USER_ALREADY_EXISTS**: Email address is already registered in the system - return conflict error with message indicating email is taken
|
|
40
|
+
- **INVALID_EMAIL**: Email does not follow valid email format - return validation error with format requirements
|
|
41
|
+
- **MISSING_REQUIRED_FIELD**: Name or email not provided - return validation error listing missing fields
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# DeactivateUser
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
DeactivateUser transitions a user from ACTIVE status to INACTIVE status, revoking their access to the system while preserving their data for audit and historical purposes. This command is used when an employee leaves the organization, is terminated, or needs temporary access suspension.
|
|
6
|
+
|
|
7
|
+
Only users in ACTIVE status can be deactivated. User data, role assignments, and historical associations are preserved.
|
|
8
|
+
|
|
9
|
+
## Business Rules
|
|
10
|
+
|
|
11
|
+
- User must exist in the system
|
|
12
|
+
- User must be in ACTIVE status
|
|
13
|
+
- Transitions user status from ACTIVE to INACTIVE
|
|
14
|
+
- User data is preserved for audit purposes
|
|
15
|
+
- Existing role assignments remain but become inactive
|
|
16
|
+
- Generates USER_DEACTIVATED audit event with actor ID, timestamp, and previous status
|
|
17
|
+
|
|
18
|
+
## Process Flow
|
|
19
|
+
|
|
20
|
+
```mermaid
|
|
21
|
+
flowchart TD
|
|
22
|
+
A[Receive deactivate request] --> B{User exists?}
|
|
23
|
+
B -->|No| C[Return error: USER_NOT_FOUND]
|
|
24
|
+
B -->|Yes| D{Status is ACTIVE?}
|
|
25
|
+
D -->|No| E[Return error: INVALID_STATUS_TRANSITION]
|
|
26
|
+
D -->|Yes| F[Update status to INACTIVE]
|
|
27
|
+
F --> G[Log USER_DEACTIVATED audit event]
|
|
28
|
+
G --> H[Return updated user]
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## External Dependencies
|
|
32
|
+
|
|
33
|
+
- None
|
|
34
|
+
|
|
35
|
+
## Error Scenarios
|
|
36
|
+
|
|
37
|
+
- **USER_NOT_FOUND**: User ID does not exist in the system - return not found error with the provided ID
|
|
38
|
+
- **INVALID_STATUS_TRANSITION**: User is not in ACTIVE status (PENDING or already INACTIVE) - return error with current status and valid transitions
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# LogAuditEvent
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
LogAuditEvent creates an immutable record of a security-relevant event in the User Management module. This command captures the actor identity, timestamp, event type, and event details for compliance and security purposes.
|
|
6
|
+
|
|
7
|
+
Typically, this command is triggered internally as a side effect of other commands (createUser, activateUser, assignRoleToUser, etc.) rather than being called directly.
|
|
8
|
+
|
|
9
|
+
## Business Rules
|
|
10
|
+
|
|
11
|
+
- Event type must be a valid event type (USER_CREATED, USER_ACTIVATED, USER_DEACTIVATED, USER_REACTIVATED, ROLE_ASSIGNED, ROLE_REVOKED, PERMISSION_ASSIGNED, PERMISSION_REVOKED)
|
|
12
|
+
- Actor ID is required (identifies who performed the action)
|
|
13
|
+
- Timestamp is auto-generated at creation
|
|
14
|
+
- Event payload contains relevant details specific to the event type
|
|
15
|
+
- Record is immutable once created (no updates or deletes allowed)
|
|
16
|
+
|
|
17
|
+
## Process Flow
|
|
18
|
+
|
|
19
|
+
```mermaid
|
|
20
|
+
flowchart TD
|
|
21
|
+
A[Receive log request] --> B{Valid event type?}
|
|
22
|
+
B -->|No| C[Return error: INVALID_EVENT_TYPE]
|
|
23
|
+
B -->|Yes| D{Actor ID provided?}
|
|
24
|
+
D -->|No| E[Return error: MISSING_REQUIRED_FIELD]
|
|
25
|
+
D -->|Yes| F[Generate timestamp]
|
|
26
|
+
F --> G[Create AuditEvent record]
|
|
27
|
+
G --> H[Return created event]
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## External Dependencies
|
|
31
|
+
|
|
32
|
+
- None
|
|
33
|
+
|
|
34
|
+
## Error Scenarios
|
|
35
|
+
|
|
36
|
+
- **INVALID_EVENT_TYPE**: Event type is not one of the recognized types - return validation error with list of valid event types
|
|
37
|
+
- **MISSING_REQUIRED_FIELD**: Actor ID not provided - return validation error indicating actor ID is required
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# ReactivateUser
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
ReactivateUser transitions a user from INACTIVE status back to ACTIVE status, restoring their access to the system. This command is used when a previously offboarded user returns, such as a contractor returning for a new engagement or a reinstated employee.
|
|
6
|
+
|
|
7
|
+
Only users in INACTIVE status can be reactivated. Historical associations and role assignments are preserved and become active again.
|
|
8
|
+
|
|
9
|
+
## Business Rules
|
|
10
|
+
|
|
11
|
+
- User must exist in the system
|
|
12
|
+
- User must be in INACTIVE status
|
|
13
|
+
- Transitions user status from INACTIVE to ACTIVE
|
|
14
|
+
- Preserves historical role assignments and associations
|
|
15
|
+
- Generates USER_REACTIVATED audit event with actor ID, timestamp, and previous status
|
|
16
|
+
|
|
17
|
+
## Process Flow
|
|
18
|
+
|
|
19
|
+
```mermaid
|
|
20
|
+
flowchart TD
|
|
21
|
+
A[Receive reactivate request] --> B{User exists?}
|
|
22
|
+
B -->|No| C[Return error: USER_NOT_FOUND]
|
|
23
|
+
B -->|Yes| D{Status is INACTIVE?}
|
|
24
|
+
D -->|No| E[Return error: INVALID_STATUS_TRANSITION]
|
|
25
|
+
D -->|Yes| F[Update status to ACTIVE]
|
|
26
|
+
F --> G[Log USER_REACTIVATED audit event]
|
|
27
|
+
G --> H[Return updated user]
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## External Dependencies
|
|
31
|
+
|
|
32
|
+
- None
|
|
33
|
+
|
|
34
|
+
## Error Scenarios
|
|
35
|
+
|
|
36
|
+
- **USER_NOT_FOUND**: User ID does not exist in the system - return not found error with the provided ID
|
|
37
|
+
- **INVALID_STATUS_TRANSITION**: User is not in INACTIVE status (PENDING or already ACTIVE) - return error with current status and valid transitions
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# RevokePermissionFromRole
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
RevokePermissionFromRole removes an association between a permission and a role, revoking that permission from all users who have the role assigned. This command is used when restructuring role capabilities or removing permissions that are no longer appropriate.
|
|
6
|
+
|
|
7
|
+
The association must exist before it can be revoked.
|
|
8
|
+
|
|
9
|
+
## Business Rules
|
|
10
|
+
|
|
11
|
+
- Role must exist in the system
|
|
12
|
+
- Permission must exist in the system
|
|
13
|
+
- RolePermission association must exist
|
|
14
|
+
- Removes the RolePermission association record
|
|
15
|
+
- Generates PERMISSION_REVOKED audit event with actor ID, role ID, permission ID, and timestamp
|
|
16
|
+
|
|
17
|
+
## Process Flow
|
|
18
|
+
|
|
19
|
+
```mermaid
|
|
20
|
+
flowchart TD
|
|
21
|
+
A[Receive revoke request] --> B{Role exists?}
|
|
22
|
+
B -->|No| C[Return error: ROLE_NOT_FOUND]
|
|
23
|
+
B -->|Yes| D{Permission exists?}
|
|
24
|
+
D -->|No| E[Return error: PERMISSION_NOT_FOUND]
|
|
25
|
+
D -->|Yes| F{Assignment exists?}
|
|
26
|
+
F -->|No| G[Return error: ASSIGNMENT_NOT_FOUND]
|
|
27
|
+
F -->|Yes| H[Delete RolePermission record]
|
|
28
|
+
H --> I[Log PERMISSION_REVOKED audit event]
|
|
29
|
+
I --> J[Return success]
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## External Dependencies
|
|
33
|
+
|
|
34
|
+
- None
|
|
35
|
+
|
|
36
|
+
## Error Scenarios
|
|
37
|
+
|
|
38
|
+
- **ROLE_NOT_FOUND**: Role ID does not exist in the system - return not found error with the provided role ID
|
|
39
|
+
- **PERMISSION_NOT_FOUND**: Permission ID does not exist in the system - return not found error with the provided permission ID
|
|
40
|
+
- **ASSIGNMENT_NOT_FOUND**: Role does not have this permission assigned - return not found error indicating the association does not exist
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# RevokeRoleFromUser
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
RevokeRoleFromUser removes an association between a role and a user, revoking all permissions that the user had through that role. This command is used when a user changes positions, leaves a project, or no longer requires the access granted by the role.
|
|
6
|
+
|
|
7
|
+
The association must exist before it can be revoked.
|
|
8
|
+
|
|
9
|
+
## Business Rules
|
|
10
|
+
|
|
11
|
+
- User must exist in the system
|
|
12
|
+
- Role must exist in the system
|
|
13
|
+
- UserRole association must exist
|
|
14
|
+
- Removes the UserRole association record
|
|
15
|
+
- Generates ROLE_REVOKED audit event with actor ID, user ID, role ID, and timestamp
|
|
16
|
+
|
|
17
|
+
## Process Flow
|
|
18
|
+
|
|
19
|
+
```mermaid
|
|
20
|
+
flowchart TD
|
|
21
|
+
A[Receive revoke request] --> B{User exists?}
|
|
22
|
+
B -->|No| C[Return error: USER_NOT_FOUND]
|
|
23
|
+
B -->|Yes| D{Role exists?}
|
|
24
|
+
D -->|No| E[Return error: ROLE_NOT_FOUND]
|
|
25
|
+
D -->|Yes| F{Assignment exists?}
|
|
26
|
+
F -->|No| G[Return error: ASSIGNMENT_NOT_FOUND]
|
|
27
|
+
F -->|Yes| H[Delete UserRole record]
|
|
28
|
+
H --> I[Log ROLE_REVOKED audit event]
|
|
29
|
+
I --> J[Return success]
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## External Dependencies
|
|
33
|
+
|
|
34
|
+
- None
|
|
35
|
+
|
|
36
|
+
## Error Scenarios
|
|
37
|
+
|
|
38
|
+
- **USER_NOT_FOUND**: User ID does not exist in the system - return not found error with the provided user ID
|
|
39
|
+
- **ROLE_NOT_FOUND**: Role ID does not exist in the system - return not found error with the provided role ID
|
|
40
|
+
- **ASSIGNMENT_NOT_FOUND**: User does not have this role assigned - return not found error indicating the association does not exist
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# Audit Trail
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
The Audit Trail captures immutable records of all security-relevant events in the User Management module. Every user lifecycle change, role assignment, and permission modification is logged with the actor identity, timestamp, and event details. These records cannot be modified or deleted, ensuring a trustworthy history for compliance and security investigations.
|
|
6
|
+
|
|
7
|
+
This feature provides the foundation for regulatory compliance and security forensics across the ERP system.
|
|
8
|
+
|
|
9
|
+
## Business Purpose
|
|
10
|
+
|
|
11
|
+
Organizations require audit trails for multiple reasons:
|
|
12
|
+
|
|
13
|
+
- **Regulatory Compliance**: SOX, GDPR, HIPAA, and other regulations mandate tracking of access and authorization changes
|
|
14
|
+
- **Security Investigations**: When incidents occur, audit logs reveal who did what and when
|
|
15
|
+
- **Access Reviews**: Periodic reviews of who has access to what rely on historical assignment data
|
|
16
|
+
- **Accountability**: Users knowing their actions are logged encourages responsible behavior
|
|
17
|
+
- **Change Tracking**: Understanding how access evolved over time supports troubleshooting and planning
|
|
18
|
+
|
|
19
|
+
## Process Flow
|
|
20
|
+
|
|
21
|
+
```mermaid
|
|
22
|
+
flowchart TD
|
|
23
|
+
A[Security Event Occurs] --> B[Capture Event Details]
|
|
24
|
+
B --> C[Record Actor Identity]
|
|
25
|
+
C --> D[Record Timestamp]
|
|
26
|
+
D --> E[Record Event Type]
|
|
27
|
+
E --> F[Record Event Payload]
|
|
28
|
+
F --> G[Store Immutable Record]
|
|
29
|
+
G --> H[Available for Query]
|
|
30
|
+
|
|
31
|
+
subgraph Event Types
|
|
32
|
+
I[USER_CREATED]
|
|
33
|
+
J[USER_ACTIVATED]
|
|
34
|
+
K[USER_DEACTIVATED]
|
|
35
|
+
L[USER_REACTIVATED]
|
|
36
|
+
M[ROLE_ASSIGNED]
|
|
37
|
+
N[ROLE_REVOKED]
|
|
38
|
+
O[PERMISSION_ASSIGNED]
|
|
39
|
+
P[PERMISSION_REVOKED]
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
subgraph Immutability
|
|
43
|
+
G --> Q[No UPDATE Allowed]
|
|
44
|
+
G --> R[No DELETE Allowed]
|
|
45
|
+
end
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Scenario Patterns
|
|
49
|
+
|
|
50
|
+
- **User Creation Audit**: When admin creates new user, system logs USER_CREATED event with admin ID, new user details, and timestamp. Provides accountability for onboarding.
|
|
51
|
+
- **Status Transition Audit**: User activation logs USER_ACTIVATED with old status (PENDING) and new status (ACTIVE). Complete state change history maintained.
|
|
52
|
+
- **Role Assignment Audit**: Assigning "Sales Manager" role to user logs ROLE_ASSIGNED with assigner ID, user ID, role ID, and timestamp. Tracks who granted elevated access.
|
|
53
|
+
- **Permission Change Audit**: Adding permission to role logs PERMISSION_ASSIGNED. Even though permission affects many users through the role, the change itself is tracked.
|
|
54
|
+
- **Compliance Query**: Auditor requests all access changes for specific user over past year. System returns chronological list of all role assignments and revocations.
|
|
55
|
+
- **Incident Investigation**: Security team investigates unauthorized data access. Audit trail reveals user's roles at time of access and who assigned those roles.
|
|
56
|
+
- **Bulk Operations**: Even bulk operations (e.g., deactivating multiple users) generate individual audit entries for each user affected.
|
|
57
|
+
|
|
58
|
+
## Test Cases
|
|
59
|
+
|
|
60
|
+
- Creating a user should generate USER_CREATED audit entry
|
|
61
|
+
- Activating a user should generate USER_ACTIVATED entry with previous status
|
|
62
|
+
- Deactivating a user should generate USER_DEACTIVATED entry with previous status
|
|
63
|
+
- Reactivating a user should generate USER_REACTIVATED entry with previous status
|
|
64
|
+
- Assigning role to user should generate ROLE_ASSIGNED entry
|
|
65
|
+
- Revoking role from user should generate ROLE_REVOKED entry
|
|
66
|
+
- Assigning permission to role should generate PERMISSION_ASSIGNED entry
|
|
67
|
+
- Revoking permission from role should generate PERMISSION_REVOKED entry
|
|
68
|
+
- Audit entries should include actor ID (who performed the action)
|
|
69
|
+
- Audit entries should include timestamp (when action occurred)
|
|
70
|
+
- Audit entries should be immutable (no update operation allowed)
|
|
71
|
+
- Audit entries should be immutable (no delete operation allowed)
|
|
72
|
+
- Querying audit by user ID should return all entries related to that user
|
|
73
|
+
- Querying audit by date range should return entries within range
|
|
74
|
+
- Querying audit by event type should filter appropriately
|
|
75
|
+
|
|
76
|
+
## Reference Links
|
|
77
|
+
|
|
78
|
+
- [OWASP Logging Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Logging_Cheat_Sheet.html)
|
|
79
|
+
- [NIST Audit and Accountability](https://csrc.nist.gov/publications/detail/sp/800-53/rev-5/final)
|
|
80
|
+
- [SOX Compliance Requirements](https://www.soxlaw.com/)
|