@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,76 @@
|
|
|
1
|
+
# Role-Based Access Control
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
Role-Based Access Control (RBAC) implements a permission-to-role-to-user authorization model. Permissions define specific allowed actions on resources, roles bundle related permissions together, and users are assigned one or more roles. This model simplifies access management by allowing administrators to manage permissions at the role level rather than per-user.
|
|
6
|
+
|
|
7
|
+
The RBAC implementation follows the principle of least privilege, ensuring users only have access to what they need for their job function.
|
|
8
|
+
|
|
9
|
+
## Business Purpose
|
|
10
|
+
|
|
11
|
+
Organizations need granular access control that scales with team size:
|
|
12
|
+
|
|
13
|
+
- **Simplified Administration**: Instead of managing permissions per user, administrators assign roles
|
|
14
|
+
- **Consistency**: All users with the same role have identical permissions
|
|
15
|
+
- **Separation of Duties**: Different roles can have non-overlapping permissions to prevent fraud
|
|
16
|
+
- **Auditability**: Clear mapping from user to roles to permissions supports compliance reviews
|
|
17
|
+
- **Scalability**: Adding new users requires only role assignment, not permission configuration
|
|
18
|
+
|
|
19
|
+
## Process Flow
|
|
20
|
+
|
|
21
|
+
```mermaid
|
|
22
|
+
flowchart TD
|
|
23
|
+
A[Define Permission] --> B[Permission Created]
|
|
24
|
+
B --> C[Assign Permission to Role]
|
|
25
|
+
C --> D[Role Has Permission]
|
|
26
|
+
|
|
27
|
+
E[Create Role] --> F[Role Created]
|
|
28
|
+
F --> C
|
|
29
|
+
|
|
30
|
+
G[Assign Role to User] --> H{User Active?}
|
|
31
|
+
H -->|No| I[Return Error: USER_NOT_ACTIVE]
|
|
32
|
+
H -->|Yes| J[User Has Role]
|
|
33
|
+
J --> K[User Inherits Role's Permissions]
|
|
34
|
+
|
|
35
|
+
subgraph Permission Check
|
|
36
|
+
L[Check User Permission] --> M[Get User's Roles]
|
|
37
|
+
M --> N[Get Roles' Permissions]
|
|
38
|
+
N --> O{Has Required Permission?}
|
|
39
|
+
O -->|Yes| P[Access Granted]
|
|
40
|
+
O -->|No| Q[Access Denied]
|
|
41
|
+
end
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Scenario Patterns
|
|
45
|
+
|
|
46
|
+
- **Permission Definition**: Administrator defines `orders:read` and `orders:write` permissions. The format `resource:action` clearly identifies what resource and operation is controlled.
|
|
47
|
+
- **Role Creation**: Administrator creates "Sales Representative" role and assigns `orders:read` permission. Creates "Sales Manager" role with both `orders:read` and `orders:write` permissions.
|
|
48
|
+
- **User Role Assignment**: New sales hire is assigned "Sales Representative" role. User immediately inherits all permissions associated with that role.
|
|
49
|
+
- **Role Promotion**: Sales rep promoted to manager. Administrator assigns "Sales Manager" role. User can retain or lose previous role based on business policy.
|
|
50
|
+
- **Role Revocation**: User transfers to different department. Administrator revokes current role and assigns appropriate role for new position.
|
|
51
|
+
- **Idempotent Assignment**: Assigning the same role to a user twice does not create duplicate assignments or return an error. The operation is idempotent.
|
|
52
|
+
- **Inactive User Restriction**: Attempt to assign role to PENDING or INACTIVE user fails. Only ACTIVE users can receive role assignments.
|
|
53
|
+
|
|
54
|
+
## Test Cases
|
|
55
|
+
|
|
56
|
+
- Creating a permission with valid key format should succeed
|
|
57
|
+
- Permission key must follow `resource:action` format
|
|
58
|
+
- Duplicate permission keys should be rejected
|
|
59
|
+
- Creating a role with valid name should succeed
|
|
60
|
+
- Assigning permission to role should succeed
|
|
61
|
+
- Assigning same permission to role twice should be idempotent (no error)
|
|
62
|
+
- Revoking permission from role should remove the association
|
|
63
|
+
- Assigning role to ACTIVE user should succeed
|
|
64
|
+
- Assigning role to PENDING user should fail with USER_NOT_ACTIVE error
|
|
65
|
+
- Assigning role to INACTIVE user should fail with USER_NOT_ACTIVE error
|
|
66
|
+
- Assigning same role to user twice should be idempotent (no error)
|
|
67
|
+
- Revoking role from user should remove the user-role association
|
|
68
|
+
- Assigning role to non-existent user should fail with USER_NOT_FOUND error
|
|
69
|
+
- Assigning non-existent role to user should fail with ROLE_NOT_FOUND error
|
|
70
|
+
- Assigning non-existent permission to role should fail with PERMISSION_NOT_FOUND error
|
|
71
|
+
|
|
72
|
+
## Reference Links
|
|
73
|
+
|
|
74
|
+
- [NIST RBAC Model](https://csrc.nist.gov/projects/role-based-access-control)
|
|
75
|
+
- [Odoo Access Rights](https://www.odoo.com/documentation/19.0/applications/general/users/access_rights.html)
|
|
76
|
+
- [OWASP Authorization Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Authorization_Cheat_Sheet.html)
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# User Account Management
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
User Account Management handles the complete user lifecycle from creation through deactivation. Each user has a status that controls their access to the system: PENDING (awaiting activation), ACTIVE (full access), or INACTIVE (access revoked). Status transitions follow defined rules to ensure security and auditability.
|
|
6
|
+
|
|
7
|
+
This feature provides the foundation for all identity-related operations in the ERP system.
|
|
8
|
+
|
|
9
|
+
## Business Purpose
|
|
10
|
+
|
|
11
|
+
Organizations need controlled user provisioning to ensure only authorized individuals can access the system. The status-based lifecycle provides:
|
|
12
|
+
|
|
13
|
+
- **Onboarding control**: New users start in PENDING status until verified
|
|
14
|
+
- **Access management**: Only ACTIVE users can perform operations
|
|
15
|
+
- **Offboarding safety**: Deactivated users retain their data for audit purposes while losing access
|
|
16
|
+
- **Compliance tracking**: Clear status transitions support regulatory requirements
|
|
17
|
+
|
|
18
|
+
## Process Flow
|
|
19
|
+
|
|
20
|
+
```mermaid
|
|
21
|
+
flowchart TD
|
|
22
|
+
A[Create User] --> B[Status: PENDING]
|
|
23
|
+
B --> C{Verification Complete?}
|
|
24
|
+
C -->|Yes| D[Activate User]
|
|
25
|
+
D --> E[Status: ACTIVE]
|
|
26
|
+
E --> F{Employee Leaves?}
|
|
27
|
+
F -->|Yes| G[Deactivate User]
|
|
28
|
+
G --> H[Status: INACTIVE]
|
|
29
|
+
H --> I{Employee Returns?}
|
|
30
|
+
I -->|Yes| J[Reactivate User]
|
|
31
|
+
J --> E
|
|
32
|
+
|
|
33
|
+
subgraph Valid Transitions
|
|
34
|
+
B -->|activateUser| E
|
|
35
|
+
E -->|deactivateUser| H
|
|
36
|
+
H -->|reactivateUser| E
|
|
37
|
+
end
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Scenario Patterns
|
|
41
|
+
|
|
42
|
+
- **New Employee Onboarding**: HR creates user account with name and email, user starts in PENDING status. After background check and IT setup complete, administrator activates the user.
|
|
43
|
+
- **Employee Departure**: When employee resigns or is terminated, administrator deactivates user account. User data is preserved for audit and historical reporting, but all access is revoked.
|
|
44
|
+
- **Contractor Return Engagement**: Previously offboarded contractor returns for new project. Administrator reactivates existing account rather than creating duplicate, preserving historical associations.
|
|
45
|
+
- **Duplicate Prevention**: Attempt to create user with existing email address is rejected with clear error, preventing duplicate accounts.
|
|
46
|
+
- **Invalid Activation**: Attempt to activate already-active user or deactivate already-inactive user returns appropriate error with current status.
|
|
47
|
+
|
|
48
|
+
## Test Cases
|
|
49
|
+
|
|
50
|
+
- Creating a user with unique email should succeed and set status to PENDING
|
|
51
|
+
- Creating a user with duplicate email should fail with USER_ALREADY_EXISTS error
|
|
52
|
+
- Activating a PENDING user should transition status to ACTIVE
|
|
53
|
+
- Activating an already ACTIVE user should fail with INVALID_STATUS_TRANSITION error
|
|
54
|
+
- Deactivating an ACTIVE user should transition status to INACTIVE
|
|
55
|
+
- Deactivating a PENDING user should fail with INVALID_STATUS_TRANSITION error
|
|
56
|
+
- Reactivating an INACTIVE user should transition status to ACTIVE
|
|
57
|
+
- Reactivating a PENDING user should fail with INVALID_STATUS_TRANSITION error
|
|
58
|
+
- User email should be validated for proper format
|
|
59
|
+
- User name should be required and non-empty
|
|
60
|
+
|
|
61
|
+
## Reference Links
|
|
62
|
+
|
|
63
|
+
- [Odoo User Management](https://www.odoo.com/documentation/19.0/applications/general/users.html)
|
|
64
|
+
- [NIST Identity Management Guidelines](https://pages.nist.gov/800-63-3/sp800-63a.html)
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# AuditEvent
|
|
2
|
+
|
|
3
|
+
## Description
|
|
4
|
+
|
|
5
|
+
AuditEvent 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
|
+
Event types include: USER_CREATED, USER_ACTIVATED, USER_DEACTIVATED, USER_REACTIVATED, ROLE_ASSIGNED, ROLE_REVOKED, PERMISSION_ASSIGNED, PERMISSION_REVOKED.
|
|
8
|
+
|
|
9
|
+
## Domain Model Definitions
|
|
10
|
+
|
|
11
|
+
### Model type
|
|
12
|
+
|
|
13
|
+
AppendOnly
|
|
14
|
+
|
|
15
|
+
### Command Definitions
|
|
16
|
+
|
|
17
|
+
- [logAuditEvent](../commands/LogAuditEvent.md)
|
|
18
|
+
|
|
19
|
+
### Models
|
|
20
|
+
|
|
21
|
+
- AuditEvent
|
|
22
|
+
|
|
23
|
+
### Invariants
|
|
24
|
+
|
|
25
|
+
- Event type must be a valid event type (USER_CREATED, USER_ACTIVATED, USER_DEACTIVATED, USER_REACTIVATED, ROLE_ASSIGNED, ROLE_REVOKED, PERMISSION_ASSIGNED, PERMISSION_REVOKED)
|
|
26
|
+
- Actor ID is required (identifies who performed the action)
|
|
27
|
+
- Timestamp is required (auto-generated at creation)
|
|
28
|
+
- Records cannot be updated after creation
|
|
29
|
+
- Records cannot be deleted
|
|
30
|
+
|
|
31
|
+
### Relationships
|
|
32
|
+
|
|
33
|
+
- **References User as Actor**: Each event records which user performed the action
|
|
34
|
+
- **References Target Entity**: Each event references the affected entity (user, role, or permission depending on event type)
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Permission
|
|
2
|
+
|
|
3
|
+
## Description
|
|
4
|
+
|
|
5
|
+
Permission defines a specific allowed action on a resource within the ERP system. Each permission uses the `resource:action` format (e.g., `orders:read`, `users:delete`) to clearly identify what resource and operation is controlled. Permissions are the atomic unit of authorization and are bundled into roles for assignment to users.
|
|
6
|
+
|
|
7
|
+
Examples: `orders:read`, `orders:write`, `users:create`, `reports:export`.
|
|
8
|
+
|
|
9
|
+
## Domain Model Definitions
|
|
10
|
+
|
|
11
|
+
### Model type
|
|
12
|
+
|
|
13
|
+
Standard
|
|
14
|
+
|
|
15
|
+
### Command Definitions
|
|
16
|
+
|
|
17
|
+
- [createPermission](../commands/CreatePermission.md)
|
|
18
|
+
|
|
19
|
+
### Models
|
|
20
|
+
|
|
21
|
+
- Permission
|
|
22
|
+
|
|
23
|
+
### Invariants
|
|
24
|
+
|
|
25
|
+
- Permission key must be unique across all permissions
|
|
26
|
+
- Permission key must follow `resource:action` format
|
|
27
|
+
- Permission key is required and cannot be empty
|
|
28
|
+
|
|
29
|
+
### Relationships
|
|
30
|
+
|
|
31
|
+
- **Referenced By RolePermission**: Permission is assigned to roles through RolePermission join records
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Role
|
|
2
|
+
|
|
3
|
+
## Description
|
|
4
|
+
|
|
5
|
+
Role represents a named collection of permissions that can be assigned to users. Roles provide a level of abstraction between permissions and users, simplifying access management by allowing administrators to manage permissions at the role level rather than per-user. Common examples include "Sales Representative", "Sales Manager", or "Administrator".
|
|
6
|
+
|
|
7
|
+
Roles follow the principle of least privilege, bundling only the permissions necessary for a specific job function.
|
|
8
|
+
|
|
9
|
+
## Domain Model Definitions
|
|
10
|
+
|
|
11
|
+
### Model type
|
|
12
|
+
|
|
13
|
+
Standard
|
|
14
|
+
|
|
15
|
+
### Command Definitions
|
|
16
|
+
|
|
17
|
+
- [createRole](../commands/CreateRole.md)
|
|
18
|
+
|
|
19
|
+
### Models
|
|
20
|
+
|
|
21
|
+
- Role
|
|
22
|
+
|
|
23
|
+
### Invariants
|
|
24
|
+
|
|
25
|
+
- Role name must be unique across all roles
|
|
26
|
+
- Role name is required and cannot be empty
|
|
27
|
+
|
|
28
|
+
### Relationships
|
|
29
|
+
|
|
30
|
+
- **Has Many RolePermissions**: Role contains permissions through RolePermission join records
|
|
31
|
+
- **Has Many UserRoles**: Role is assigned to users through UserRole join records
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# RolePermission
|
|
2
|
+
|
|
3
|
+
## Description
|
|
4
|
+
|
|
5
|
+
RolePermission is a join model that represents the assignment of a permission to a role. This many-to-many relationship enables roles to have multiple permissions and permissions to be assigned to multiple roles. When a user is assigned a role, they inherit all permissions assigned to that role.
|
|
6
|
+
|
|
7
|
+
The assignment operation is idempotent - assigning the same permission twice does not create duplicate records.
|
|
8
|
+
|
|
9
|
+
## Domain Model Definitions
|
|
10
|
+
|
|
11
|
+
### Model type
|
|
12
|
+
|
|
13
|
+
Standard
|
|
14
|
+
|
|
15
|
+
### Command Definitions
|
|
16
|
+
|
|
17
|
+
- [assignPermissionToRole](../commands/AssignPermissionToRole.md)
|
|
18
|
+
- [revokePermissionFromRole](../commands/RevokePermissionFromRole.md)
|
|
19
|
+
|
|
20
|
+
### Models
|
|
21
|
+
|
|
22
|
+
- RolePermission
|
|
23
|
+
|
|
24
|
+
### Invariants
|
|
25
|
+
|
|
26
|
+
- Role-Permission combination must be unique (no duplicate assignments)
|
|
27
|
+
- Referenced role must exist
|
|
28
|
+
- Referenced permission must exist
|
|
29
|
+
|
|
30
|
+
### Relationships
|
|
31
|
+
|
|
32
|
+
- **Belongs To Role**: Each RolePermission record references exactly one role
|
|
33
|
+
- **Belongs To Permission**: Each RolePermission record references exactly one permission
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# User
|
|
2
|
+
|
|
3
|
+
## Description
|
|
4
|
+
|
|
5
|
+
User represents an identity in the ERP system with a lifecycle managed through status transitions. Each user has an email (unique identifier), name, and status that controls system access. The status-based lifecycle ensures controlled provisioning: users start PENDING until verified, become ACTIVE for full access, and transition to INACTIVE when access should be revoked while preserving data for audit purposes.
|
|
6
|
+
|
|
7
|
+
This model provides the foundation for all identity-related operations in the ERP system.
|
|
8
|
+
|
|
9
|
+
## Domain Model Definitions
|
|
10
|
+
|
|
11
|
+
### Model type
|
|
12
|
+
|
|
13
|
+
Stateful
|
|
14
|
+
|
|
15
|
+
#### State Transitions
|
|
16
|
+
|
|
17
|
+
```mermaid
|
|
18
|
+
stateDiagram-v2
|
|
19
|
+
[*] --> Pending: createUser
|
|
20
|
+
Pending --> Active: activateUser
|
|
21
|
+
Active --> Inactive: deactivateUser
|
|
22
|
+
Inactive --> Active: reactivateUser
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
### Command Definitions
|
|
26
|
+
|
|
27
|
+
- [createUser](../commands/CreateUser.md)
|
|
28
|
+
- [activateUser](../commands/ActivateUser.md)
|
|
29
|
+
- [deactivateUser](../commands/DeactivateUser.md)
|
|
30
|
+
- [reactivateUser](../commands/ReactivateUser.md)
|
|
31
|
+
|
|
32
|
+
### Models
|
|
33
|
+
|
|
34
|
+
- User
|
|
35
|
+
|
|
36
|
+
### Invariants
|
|
37
|
+
|
|
38
|
+
- Email must be unique across all users (active and inactive)
|
|
39
|
+
- Email must follow valid email format
|
|
40
|
+
- Name is required and cannot be empty
|
|
41
|
+
- Status must be one of PENDING, ACTIVE, or INACTIVE
|
|
42
|
+
- Only ACTIVE users can receive role assignments
|
|
43
|
+
|
|
44
|
+
### Relationships
|
|
45
|
+
|
|
46
|
+
- **Has Many UserRoles**: User is assigned roles through UserRole join records
|
|
47
|
+
- **Referenced By AuditEvent**: User actions are recorded in audit events as actor or target
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# UserRole
|
|
2
|
+
|
|
3
|
+
## Description
|
|
4
|
+
|
|
5
|
+
UserRole is a join model that represents the assignment of a role to a user. This many-to-many relationship enables users to have multiple roles and roles to be assigned to multiple users. Role assignments are only valid for users in ACTIVE status, ensuring that pending or inactive users cannot accumulate permissions.
|
|
6
|
+
|
|
7
|
+
The assignment operation is idempotent - assigning the same role twice does not create duplicate records.
|
|
8
|
+
|
|
9
|
+
## Domain Model Definitions
|
|
10
|
+
|
|
11
|
+
### Model type
|
|
12
|
+
|
|
13
|
+
Standard
|
|
14
|
+
|
|
15
|
+
### Command Definitions
|
|
16
|
+
|
|
17
|
+
- [assignRoleToUser](../commands/AssignRoleToUser.md)
|
|
18
|
+
- [revokeRoleFromUser](../commands/RevokeRoleFromUser.md)
|
|
19
|
+
|
|
20
|
+
### Models
|
|
21
|
+
|
|
22
|
+
- UserRole
|
|
23
|
+
|
|
24
|
+
### Invariants
|
|
25
|
+
|
|
26
|
+
- User-Role combination must be unique (no duplicate assignments)
|
|
27
|
+
- Referenced user must exist
|
|
28
|
+
- Referenced role must exist
|
|
29
|
+
- User must be in ACTIVE status to receive role assignment
|
|
30
|
+
|
|
31
|
+
### Relationships
|
|
32
|
+
|
|
33
|
+
- **Belongs To User**: Each UserRole record references exactly one user
|
|
34
|
+
- **Belongs To Role**: Each UserRole record references exactly one role
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Flattened User Permissions Design
|
|
2
|
+
|
|
3
|
+
## Problem
|
|
4
|
+
|
|
5
|
+
Authorization checks require joining User → UserRole → Role → RolePermission → Permission. This is slow and complex. We want permissions denormalized directly on the User record for fast lookups.
|
|
6
|
+
|
|
7
|
+
## Solution
|
|
8
|
+
|
|
9
|
+
Add a `permissions` field to User that contains a flattened array of permission keys. Recompute automatically when role/permission assignments change.
|
|
10
|
+
|
|
11
|
+
## Data Model
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
// User.permissions
|
|
15
|
+
permissions: string[] | null; // e.g., ["orders:read", "orders:write", "users:read"]
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Recompute Function
|
|
19
|
+
|
|
20
|
+
`src/lib/recomputeUserPermissions.ts`:
|
|
21
|
+
|
|
22
|
+
- Query: User → UserRole → RolePermission → Permission
|
|
23
|
+
- Deduplicate permission keys
|
|
24
|
+
- Update User.permissions field
|
|
25
|
+
- Return computed array
|
|
26
|
+
|
|
27
|
+
## Trigger Points
|
|
28
|
+
|
|
29
|
+
| Command | Affected Users | Approach |
|
|
30
|
+
| ------------------------ | ------------------------ | ------------ |
|
|
31
|
+
| assignRoleToUser | Single user | Synchronous |
|
|
32
|
+
| revokeRoleFromUser | Single user | Synchronous |
|
|
33
|
+
| assignPermissionToRole | All users with that role | Asynchronous |
|
|
34
|
+
| revokePermissionFromRole | All users with that role | Asynchronous |
|
|
35
|
+
|
|
36
|
+
## Async Executors
|
|
37
|
+
|
|
38
|
+
For role-permission changes (which affect multiple users), executors handle recomputation asynchronously:
|
|
39
|
+
|
|
40
|
+
- `recomputeOnRolePermissionCreated` - Triggers on RolePermission create
|
|
41
|
+
- `recomputeOnRolePermissionDeleted` - Triggers on RolePermission delete
|
|
42
|
+
|
|
43
|
+
Located in `src/executor/recomputeOnRolePermissionChange.ts`.
|
|
44
|
+
|
|
45
|
+
## Trade-offs
|
|
46
|
+
|
|
47
|
+
- **Pro**: Fast authorization (single field read, no joins)
|
|
48
|
+
- **Pro**: Simple permission checks (`user.permissions.includes("orders:read")`)
|
|
49
|
+
- **Pro**: Single-user operations remain fast (synchronous)
|
|
50
|
+
- **Pro**: Multi-user operations don't block requests (asynchronous)
|
|
51
|
+
- **Con**: Storage overhead (denormalized data)
|
|
52
|
+
- **Con**: Eventual consistency for role-permission changes
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { createExecutor, recordCreatedTrigger, recordDeletedTrigger } from "@tailor-platform/sdk";
|
|
2
|
+
import { getDB } from "../generated/kysely-tailordb";
|
|
3
|
+
import { rolePermission } from "../db/rolePermission";
|
|
4
|
+
import { recomputePermissionsForUsersWithRole } from "../lib/recomputeUserPermissions";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Executor: recomputeOnRolePermissionCreated
|
|
8
|
+
*
|
|
9
|
+
* Triggers when a RolePermission record is created (permission assigned to role).
|
|
10
|
+
* Recomputes permissions for all users with that role asynchronously.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
export const recomputeOnRolePermissionCreated = function recomputeOnRolePermissionCreated({
|
|
14
|
+
namespace,
|
|
15
|
+
}: {
|
|
16
|
+
namespace: string;
|
|
17
|
+
}) {
|
|
18
|
+
return createExecutor({
|
|
19
|
+
name: "recompute-on-role-permission-created",
|
|
20
|
+
description: "Recompute permissions for all users when a permission is assigned to a role",
|
|
21
|
+
trigger: recordCreatedTrigger({
|
|
22
|
+
type: rolePermission,
|
|
23
|
+
}),
|
|
24
|
+
operation: {
|
|
25
|
+
kind: "jobFunction",
|
|
26
|
+
body: async ({ newRecord }) => {
|
|
27
|
+
// @ts-expect-error unsure at build time
|
|
28
|
+
const db = getDB(namespace);
|
|
29
|
+
await recomputePermissionsForUsersWithRole(db, newRecord.roleId);
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
});
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Executor: recomputeOnRolePermissionDeleted
|
|
37
|
+
*
|
|
38
|
+
* Triggers when a RolePermission record is deleted (permission revoked from role).
|
|
39
|
+
* Recomputes permissions for all users with that role asynchronously.
|
|
40
|
+
*/
|
|
41
|
+
export const recomputeOnRolePermissionDeleted = function recomputeOnRolePermissionDeleted({
|
|
42
|
+
namespace,
|
|
43
|
+
}: {
|
|
44
|
+
namespace: string;
|
|
45
|
+
}) {
|
|
46
|
+
return createExecutor({
|
|
47
|
+
name: "recompute-on-role-permission-deleted",
|
|
48
|
+
description: "Recompute permissions for all users when a permission is revoked from a role",
|
|
49
|
+
trigger: recordDeletedTrigger({
|
|
50
|
+
type: rolePermission,
|
|
51
|
+
}),
|
|
52
|
+
operation: {
|
|
53
|
+
kind: "jobFunction",
|
|
54
|
+
body: async ({ oldRecord }) => {
|
|
55
|
+
// @ts-expect-error unsure at build time
|
|
56
|
+
const db = getDB(namespace);
|
|
57
|
+
await recomputePermissionsForUsersWithRole(db, oldRecord.roleId);
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
});
|
|
61
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type of audit event
|
|
3
|
+
*/
|
|
4
|
+
export const AuditEventEventType = {
|
|
5
|
+
USER_CREATED: "USER_CREATED",
|
|
6
|
+
USER_ACTIVATED: "USER_ACTIVATED",
|
|
7
|
+
USER_DEACTIVATED: "USER_DEACTIVATED",
|
|
8
|
+
USER_REACTIVATED: "USER_REACTIVATED",
|
|
9
|
+
ROLE_ASSIGNED: "ROLE_ASSIGNED",
|
|
10
|
+
ROLE_REVOKED: "ROLE_REVOKED",
|
|
11
|
+
PERMISSION_ASSIGNED: "PERMISSION_ASSIGNED",
|
|
12
|
+
PERMISSION_REVOKED: "PERMISSION_REVOKED",
|
|
13
|
+
} as const;
|
|
14
|
+
export type AuditEventEventType = (typeof AuditEventEventType)[keyof typeof AuditEventEventType];
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* User status
|
|
18
|
+
*/
|
|
19
|
+
export const UserStatus = {
|
|
20
|
+
PENDING: "PENDING",
|
|
21
|
+
ACTIVE: "ACTIVE",
|
|
22
|
+
INACTIVE: "INACTIVE",
|
|
23
|
+
} as const;
|
|
24
|
+
export type UserStatus = (typeof UserStatus)[keyof typeof UserStatus];
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type ColumnType,
|
|
3
|
+
Kysely,
|
|
4
|
+
type KyselyConfig,
|
|
5
|
+
type Transaction as KyselyTransaction,
|
|
6
|
+
type Insertable as KyselyInsertable,
|
|
7
|
+
type Selectable as KyselySelectable,
|
|
8
|
+
type Updateable as KyselyUpdateable,
|
|
9
|
+
} from "kysely";
|
|
10
|
+
import { TailordbDialect } from "@tailor-platform/function-kysely-tailordb";
|
|
11
|
+
|
|
12
|
+
type Timestamp = ColumnType<Date, Date | string, Date | string>;
|
|
13
|
+
type Generated<T> =
|
|
14
|
+
T extends ColumnType<infer S, infer I, infer U>
|
|
15
|
+
? ColumnType<S, I | undefined, U>
|
|
16
|
+
: ColumnType<T, T | undefined, T>;
|
|
17
|
+
|
|
18
|
+
export interface Namespace {
|
|
19
|
+
"main-db": {
|
|
20
|
+
AuditEvent: {
|
|
21
|
+
id: Generated<string>;
|
|
22
|
+
eventType:
|
|
23
|
+
| "USER_CREATED"
|
|
24
|
+
| "USER_ACTIVATED"
|
|
25
|
+
| "USER_DEACTIVATED"
|
|
26
|
+
| "USER_REACTIVATED"
|
|
27
|
+
| "ROLE_ASSIGNED"
|
|
28
|
+
| "ROLE_REVOKED"
|
|
29
|
+
| "PERMISSION_ASSIGNED"
|
|
30
|
+
| "PERMISSION_REVOKED";
|
|
31
|
+
actorId: string;
|
|
32
|
+
targetId: string | null;
|
|
33
|
+
targetType: string | null;
|
|
34
|
+
payload: string | null;
|
|
35
|
+
createdAt: Generated<Timestamp>;
|
|
36
|
+
updatedAt: Timestamp | null;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
Permission: {
|
|
40
|
+
id: Generated<string>;
|
|
41
|
+
key: string;
|
|
42
|
+
description: string | null;
|
|
43
|
+
createdAt: Generated<Timestamp>;
|
|
44
|
+
updatedAt: Timestamp | null;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
Role: {
|
|
48
|
+
id: Generated<string>;
|
|
49
|
+
name: string;
|
|
50
|
+
description: string | null;
|
|
51
|
+
createdAt: Generated<Timestamp>;
|
|
52
|
+
updatedAt: Timestamp | null;
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
RolePermission: {
|
|
56
|
+
id: Generated<string>;
|
|
57
|
+
roleId: string;
|
|
58
|
+
permissionId: string;
|
|
59
|
+
createdAt: Generated<Timestamp>;
|
|
60
|
+
updatedAt: Timestamp | null;
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
User: {
|
|
64
|
+
id: Generated<string>;
|
|
65
|
+
email: string;
|
|
66
|
+
name: string;
|
|
67
|
+
status: "PENDING" | "ACTIVE" | "INACTIVE";
|
|
68
|
+
permissions: string[] | null;
|
|
69
|
+
createdAt: Generated<Timestamp>;
|
|
70
|
+
updatedAt: Timestamp | null;
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
UserRole: {
|
|
74
|
+
id: Generated<string>;
|
|
75
|
+
userId: string;
|
|
76
|
+
roleId: string;
|
|
77
|
+
createdAt: Generated<Timestamp>;
|
|
78
|
+
updatedAt: Timestamp | null;
|
|
79
|
+
};
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export function getDB<const N extends keyof Namespace>(
|
|
84
|
+
namespace: N,
|
|
85
|
+
kyselyConfig?: Omit<KyselyConfig, "dialect">,
|
|
86
|
+
): Kysely<Namespace[N]> {
|
|
87
|
+
const client = new tailordb.Client({ namespace });
|
|
88
|
+
return new Kysely<Namespace[N]>({
|
|
89
|
+
dialect: new TailordbDialect(client),
|
|
90
|
+
...kyselyConfig,
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export type DB<N extends keyof Namespace = keyof Namespace> = ReturnType<typeof getDB<N>>;
|
|
95
|
+
|
|
96
|
+
export type Transaction<K extends keyof Namespace | DB = keyof Namespace> =
|
|
97
|
+
K extends DB<infer N>
|
|
98
|
+
? KyselyTransaction<Namespace[N]>
|
|
99
|
+
: K extends keyof Namespace
|
|
100
|
+
? KyselyTransaction<Namespace[K]>
|
|
101
|
+
: never;
|
|
102
|
+
|
|
103
|
+
type TableName = {
|
|
104
|
+
[N in keyof Namespace]: keyof Namespace[N];
|
|
105
|
+
}[keyof Namespace];
|
|
106
|
+
export type Table<T extends TableName> = {
|
|
107
|
+
[N in keyof Namespace]: T extends keyof Namespace[N] ? Namespace[N][T] : never;
|
|
108
|
+
}[keyof Namespace];
|
|
109
|
+
|
|
110
|
+
export type Insertable<T extends keyof Namespace[keyof Namespace]> = KyselyInsertable<Table<T>>;
|
|
111
|
+
export type Selectable<T extends keyof Namespace[keyof Namespace]> = KyselySelectable<Table<T>>;
|
|
112
|
+
export type Updateable<T extends keyof Namespace[keyof Namespace]> = KyselyUpdateable<Table<T>>;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export { defineModule } from "./module";
|
|
2
|
+
export { permissions, own, all } from "./permissions";
|
|
3
|
+
|
|
4
|
+
// generated types
|
|
5
|
+
export { AuditEventEventType, UserStatus } from "./generated/enums";
|
|
6
|
+
|
|
7
|
+
// errors
|
|
8
|
+
export {
|
|
9
|
+
UserNotFoundError,
|
|
10
|
+
UserAlreadyExistsError,
|
|
11
|
+
UserNotActiveError,
|
|
12
|
+
InvalidEmailError,
|
|
13
|
+
MissingRequiredFieldError,
|
|
14
|
+
InvalidStatusTransitionError,
|
|
15
|
+
PermissionNotFoundError,
|
|
16
|
+
DuplicatePermissionKeyError,
|
|
17
|
+
InvalidPermissionKeyFormatError,
|
|
18
|
+
RoleNotFoundError,
|
|
19
|
+
DuplicateRoleNameError,
|
|
20
|
+
AssignmentNotFoundError,
|
|
21
|
+
InvalidEventTypeError,
|
|
22
|
+
} from "./lib/errors";
|
|
23
|
+
|
|
24
|
+
// input types
|
|
25
|
+
export { type ActivateUserInput } from "./command/activateUser";
|
|
26
|
+
export { type DeactivateUserInput } from "./command/deactivateUser";
|
|
27
|
+
export { type ReactivateUserInput } from "./command/reactivateUser";
|
|
28
|
+
export { type AssignPermissionToRoleInput } from "./command/assignPermissionToRole";
|
|
29
|
+
export { type RevokePermissionFromRoleInput } from "./command/revokePermissionFromRole";
|
|
30
|
+
export { type AssignRoleToUserInput } from "./command/assignRoleToUser";
|
|
31
|
+
export { type RevokeRoleFromUserInput } from "./command/revokeRoleFromUser";
|
|
32
|
+
export { type LogAuditEventInput } from "./command/logAuditEvent";
|