Skip to content

Enterprise domains ​

The Java service keeps enterprise features in vertical module/<domain>/{api,service,persistence} packages. Flyway V9__enterprise_domains.sql adds their tables and permissions; PostgreSQL stores business state, while Redis supports short-lived coordination. These routes use the shared response contract. The frontend client lives in packages/effects/api/src/modules/enterprise.ts.

Tenant and organization ​

RoutePurposePermission
GET /api/v1/tenantsList tenantsadmin role and tenant:list
POST /api/v1/tenantsCreate a tenant and its administratoradmin role and tenant:list
PUT /api/v1/tenants/{id}Update name, status, plan, or expiryadmin role and tenant:list
GET /api/v1/organizations/currentRead the current organizationdepartment:list
PUT /api/v1/organizations/{id}Update its name or statusdepartment:manage
GET /api/v1/departmentsRead the department treedepartment:list
GET /api/v1/departments/{id}/membersRead department membersdepartment:list
POST /api/v1/departmentsCreate a departmentdepartment:manage
PUT /api/v1/departments/{id}Update a departmentdepartment:manage
PUT /api/v1/departments/{id}/members/{userId}Assign a memberdepartment:manage
DELETE /api/v1/departments/{id}/members/{userId}Remove a memberdepartment:manage
DELETE /api/v1/departments/{id}Delete an eligible departmentdepartment:manage

The signed access token supplies tenantId. MyBatis adds tenant predicates for protected tables, and services check business access as well. The bootstrap system administrator has an explicit cross-tenant path; ordinary tenant administrators do not. For anonymous /api/v1/public/** requests, X-Tenant-Code selects an active tenant and defaults to default. A missing, disabled, or expired tenant returns an error.

The Java login and registration requests accept an optional tenantCode (default default). The current frontend LoginParams and login forms do not expose that field, so the shipped UI signs in to the default tenant only. To test another tenant today, call the Java authentication API directly with tenantCode; frontend tenant switching requires a contract and UI change.

Projects and tasks ​

RoutePurposePermission
GET /api/v1/projects, GET /api/v1/projects/{id}List accessible projects or read oneproject:list
GET /api/v1/projects/{id}/activitiesRead project activityproject:list
POST /api/v1/projectsCreate a project; requires Idempotency-Keyproject:create
PUT /api/v1/projects/{id}Update with a body versionproject:update
PUT /api/v1/projects/{id}/archive?version=NArchive a projectproject:update
PUT, DELETE /api/v1/projects/{id}/members/{userId}Add or remove a memberproject:update
GET, POST /api/v1/projects/{id}/tasksList or create tasksproject:list / task:create
GET, PUT /api/v1/tasks/{id}Read or update a task; update needs versionproject:list / task:update
GET, POST /api/v1/tasks/{id}/commentsRead or add commentsproject:list
GET /api/v1/tasks/{id}/activitiesRead field and status historyproject:list

The creator becomes project owner and member. Members can access their projects; an assignee must already be a project member. Archiving prevents new tasks and membership changes. A member with unfinished assigned tasks cannot be removed. Project and task writes record activity in the same transaction.

Task status follows TODO → IN_PROGRESS → BLOCKED → IN_PROGRESS, with IN_PROGRESS → DONE, and cancellation from TODO, IN_PROGRESS, or BLOCKED. DONE and CANCELLED are terminal. priority accepts LOW, MEDIUM, HIGH, or URGENT. Stale version values and illegal transitions return HTTP 409.

Approvals, notifications, audit, and files ​

RoutePurposePermission
GET, POST /api/v1/approvalsList visible requests or create a draftAuthenticated / approval:create
POST /api/v1/approvals/{id}/submitSubmit with Idempotency-Keyapproval:create
POST /api/v1/approvals/{id}/approve, /rejectAct on the pending stepapproval:action
POST /api/v1/approvals/{id}/cancelCancel an owned draft or pending requestapproval:create
GET /api/v1/notifications, /unread-countRead personal notificationsAuthenticated
PUT /api/v1/notifications/{id}/read, /read-allMark notifications readAuthenticated
GET /api/v1/audit/operationsRead operation metadataaudit:view
POST /api/v1/filesUpload multipart field filefile:upload
GET /api/v1/files/{tenantId}/{filename}Download an authorized fileAuthenticated
DELETE /api/v1/files/{tenantId}/{filename}Delete a filefile:upload

The reference approval flow is DRAFT → PENDING → APPROVED or REJECTED; the applicant can cancel a draft or pending request. Submission requires a department with a leader. The leader acts first, followed by an administrator. Notifications are created after the business transaction commits. The audit endpoint returns request metadata, separate from project and task activity; it does not expose request bodies. File storage uses tenant-specific local directories in this implementation.

Idempotency-Key is a Redis claim lasting 24 hours for project creation and approval submission. Reusing a key returns HTTP 409; it does not replay the first response. Use a new key for a distinct command. If a request may have completed before a network failure, read the resource before retrying.

Frontend and mock scope ​

The web-antd application currently exposes project/task, approval, organization, tenant, audit, file, and notification screens. Other UI applications share the API package but do not automatically gain those screens. Nitro and the in-browser static preview use the in-memory createStaticEnterpriseApi fixture. They model routes and response shapes for development, not PostgreSQL transactions, Redis coordination, durable files, or full Java permission rules. Use backend integration when validating business behavior.

Released under the MIT License.