iven
8bef5e2401
feat(crm): 启用客户实体 data_scope + owner_id + data_scope_levels
...
- customer 实体新增 data_scope = true 启用行级数据权限
- customer 新增 owner_id 字段 (scope_role = "owner") 标记数据所有者
- customer.list 和 customer.manage 权限新增 data_scope_levels 声明
支持 self / department / department_tree / all 四种范围等级
2026-04-17 10:50:53 +08:00
iven
a7342f83e9
feat(plugin): 数据范围查询基础设施 — get_data_scope + get_dept_members 辅助函数
...
- 新增 get_data_scope() 查询当前用户对指定权限的 data_scope 等级
- 新增 get_dept_members() 获取部门成员 ID 列表(预留递归部门树查询)
- 在 list_plugin_data handler 中标记 data_scope 注入点 TODO
- 这些基础设施函数将在前端 Chunk 4 完成完整集成
2026-04-17 10:49:57 +08:00
iven
41a0dc8bd6
feat(plugin): 实体级 data_scope + scope_role + data_scope_levels 声明
...
- PluginEntity 新增 data_scope: Option<bool> 字段,控制是否启用行级数据权限
- PluginField 新增 scope_role: Option<String> 字段,标记数据权限的"所有者"字段
- PluginPermission 新增 data_scope_levels: Option<Vec<String>> 字段,声明支持的数据范围等级
- 更新 default_for_field() 测试辅助和 dynamic_table.rs 中的 PluginEntity 构造
- 新增 parse_entity_with_data_scope 和 parse_permission_with_data_scope_levels 测试
2026-04-17 10:45:49 +08:00
iven
89684313d9
feat(plugin): 级联删除 — relations OnDeleteStrategy 支持
...
delete 方法扩展为处理三种级联策略:Restrict(存在关联时拒绝删除)、
Nullify(置空外键字段)、Cascade(级联软删除关联记录)。
在软删除主记录之前按声明顺序处理所有关联关系。
2026-04-17 10:40:05 +08:00
iven
e24b820d80
feat(plugin): 循环引用检测 — no_cycle 字段支持
...
新增 check_no_cycle 异步函数,通过沿 parent 链上溯检测
是否存在循环引用。在 update 方法中集成,对声明 no_cycle
的字段执行检测,最多遍历 100 层防止无限循环。
2026-04-17 10:38:41 +08:00
iven
e6aaa18ceb
fix(plugin): 移除权限 fallback — 必须显式分配实体级权限
...
所有 7 个数据 handler 方法不再回退到 plugin.list/plugin.admin
粗粒度权限。现在必须为每个实体显式分配 {plugin}.{entity}.list
或 {plugin}.{entity}.manage 权限,否则返回 403。
2026-04-17 10:38:05 +08:00
iven
314580243e
feat(plugin): 字段正则校验 — validation.pattern 支持
...
Cargo.toml 新增 regex 依赖。validate_data 函数扩展支持
FieldValidation.pattern 正则校验,空值非必填字段跳过校验,
校验失败时返回自定义 message 或默认提示。
2026-04-17 10:37:37 +08:00
iven
dadb826804
feat(plugin): SQL 构建支持行级数据范围条件
...
DynamicTableManager 新增 build_data_scope_condition_with_params 方法,
支持 all/self/department/department_tree 四种数据范围过滤。
部门成员为空时自动退化为 self 范围,支持 Generated Column 路由。
附带 6 个单元测试覆盖所有场景。
2026-04-17 10:36:01 +08:00
iven
649334e862
feat(plugin): 外键校验 — ref_entity 字段验证引用记录存在性
...
新增 validate_ref_entities 异步函数,在 create/update 时检查
ref_entity 字段指向的记录是否存在于对应动态表中。自引用
场景下 create 跳过校验,update 跳过自身引用。
2026-04-17 10:35:46 +08:00
iven
f4b1a06d53
feat(auth): JWT 中间件预留 department_ids 填充位置
...
当前 department_ids 为空列表,附带 TODO 注释说明
待 user_positions 关联表建立后补充查询逻辑。
2026-04-17 10:34:06 +08:00
iven
527a57df9e
feat(plugin): PluginRelation 级联删除声明 + OnDeleteStrategy
...
新增 OnDeleteStrategy 枚举(Nullify/Cascade/Restrict)和
PluginRelation 结构体声明实体关联关系。PluginEntity 增加
relations 字段(serde(default) 向后兼容)。
2026-04-17 10:33:58 +08:00
iven
62f17d13ad
feat(core): TenantContext 新增 department_ids 字段
...
为行级数据权限做准备,TenantContext 新增 department_ids 字段
存储用户所属部门 ID 列表。当前阶段 JWT 中间件填充为空列表,
待 user_positions 关联表建立后补充查询逻辑。
2026-04-17 10:33:28 +08:00
iven
6f286acbeb
feat(db): role_permissions 添加 data_scope 列
...
行级数据权限基础设施 — role_permissions 表新增 data_scope 列,
支持 all/self/department/department_tree 四种数据范围。
2026-04-17 10:32:12 +08:00
iven
f697b5fd6d
feat(plugin): PluginField 扩展 — ref_entity / validation / no_cycle
...
新增 FieldValidation 类型支持正则校验规则,PluginField 增加
ref_entity(外键引用实体名)、validation(字段校验规则)、
no_cycle(禁止循环引用)三个可选字段。
2026-04-17 10:31:37 +08:00
iven
abc3086571
chore(crm): 验证 Generated Column 自动生成 — 无需修改 plugin.toml
...
验证所有实体的 unique/filterable/sortable 标记已正确配置,
build_create_table_sql 将自动为以下字段生成 Generated Column:
- customer: code(unique), customer_type/industry/region/level/status(filterable)
- communication: type(filterable), occurred_at(sortable)
- customer_relationship: relationship_type(filterable)
同步更新 Cargo.lock(moka 依赖引入)
2026-04-17 10:26:13 +08:00
iven
16b7a36bfb
feat(plugin): list 方法集成 Generated Column 路由
...
- list 方法新增 cache 参数,使用 resolve_entity_info_cached 替代直接查库
- 查询改用 build_filtered_query_sql_ex,自动路由到 Generated Column
- handler 传递 entity_cache 到 list 方法
2026-04-17 10:25:43 +08:00
iven
28c7126518
feat(plugin): 聚合查询 Redis 缓存骨架
...
- 新增 aggregate_cached 方法,预留 Redis 缓存接口
- 当前直接委托到 aggregate 方法,未来版本添加缓存层
2026-04-17 10:24:26 +08:00
iven
091d517af6
feat(plugin): Schema 缓存 — moka LRU Cache 消除 resolve_entity_info 重复查库
...
- 添加 moka 0.12 依赖到 erp-plugin 和 erp-server
- 重写 state.rs: 新增 EntityInfo (含 generated_fields) 和 moka Cache
- AppState 新增 plugin_entity_cache 字段
- data_service.rs: 旧 resolve_entity_info 保留兼容,新增 resolve_entity_info_cached
2026-04-17 10:23:43 +08:00
iven
3b0b78c4cb
docs: 强化闭环工作法 — 验证通过才能提交,提交后必须推送
...
§3.3 闭环工作法改为 6 步:理解→实现→验证→提交→文档同步→推送
§13 反模式新增 3 条:禁止跳过验证、禁止不推送、禁止忘记更新文档
2026-04-17 10:19:35 +08:00
iven
2616e83ec6
feat(plugin): Keyset Pagination — cursor 编解码 + 游标分页 SQL
2026-04-17 10:18:43 +08:00
iven
20734330a6
feat(plugin): SQL 查询路由 — Generated Column 字段优先使用 _f_ 前缀列
2026-04-17 10:16:35 +08:00
iven
a897cd7a87
feat(plugin): create_table 使用 Generated Column + pg_trgm + 覆盖索引
2026-04-17 10:15:05 +08:00
iven
32dd0f72c1
feat(plugin): PluginFieldType 添加 Generated Column 类型映射
2026-04-17 10:12:52 +08:00
iven
67bdf9e942
feat(db): 添加 pg_trgm 扩展 + plugin_entity_columns 元数据表
...
- 启用 pg_trgm 扩展加速 ILIKE '%keyword%' 模糊搜索
- 新增 plugin_entity_columns 表,记录插件动态表中哪些字段被提取为 Generated Column
- 添加 plugin_entity_id 外键关联 plugin_entities 表
- down 方法仅删表不卸载 pg_trgm(其他功能可能依赖)
2026-04-17 10:08:09 +08:00
iven
a7cf44cd46
docs: CRM 插件基座升级实施计划 — 4 Chunk 36 Task
...
Chunk 1: JSONB 存储优化 (Generated Column + pg_trgm + Keyset + Schema 缓存)
Chunk 2: 数据完整性框架 (ref_entity + 级联删除 + 字段校验 + 循环检测)
Chunk 3: 行级数据权限 (data_scope + TenantContext 扩展 + fallback 收紧)
Chunk 4: 前端页面能力增强 (entity_select + kanban + 批量操作 + 图表)
2026-04-17 09:57:58 +08:00
iven
d07e476898
docs(spec): 新增 CRM 插件基座升级设计规格 v1.1
...
6 专家组深度评审后的基座优先改进方案:
- JSONB 存储优化 (Generated Column + pg_trgm + Keyset Pagination)
- 数据完整性框架 (ref_entity + 级联策略 + 字段校验 + 循环引用检测)
- 行级数据权限 (self/department/department_tree/all 四级)
- 前端页面能力增强 (entity_select + kanban + 批量操作 + Dashboard 图表)
2026-04-17 03:13:07 +08:00
iven
2866ffb634
feat(crm): 新增关系图谱和统计概览页面 + UI/UX 全面优化
...
后端:
- manifest.rs 新增 Graph 和 Dashboard 页面类型到 PluginPageType 枚举
- 添加 graph 页面验证逻辑(entity/relationship_entity/source_field/target_field)
CRM 插件:
- plugin.toml 新增关系图谱页面(graph 类型,基于 customer_relationship 实体)
- plugin.toml 新增统计概览页面(dashboard 类型)
- 侧边栏菜单从 5 项扩展到 7 项
前端 — 关系图谱 (PluginGraphPage):
- 渐变节点 + 曲线箭头连线 + 关系类型色彩区分
- 鼠标悬停高亮 + Canvas Tooltip + 点击设为中心节点
- 2-hop 邻居视图 + 统计卡片(客户总数/关系总数/当前中心)
- 关系类型图例(可点击筛选)+ 暗色主题适配
- ResizeObserver 自适应 + requestAnimationFrame 动画循环
前端 — 统计概览 (PluginDashboardPage):
- 5 实体统计卡片(渐变色条 + 图标 + 数字动画)
- 可筛选字段分布卡片(Progress 进度条 + Tag 标签)
- 响应式栅格布局 + 骨架屏加载态 + 错误状态持久展示
2026-04-17 01:28:19 +08:00
iven
b08e8b5ab5
perf: 前端 API 并行化 + 后端 Redis 连接缓存 — 响应时间从 2.26s 降至 2ms
...
后端:
- rate_limit 中间件新增 RedisAvailability 缓存
- Redis 不可用时跳过限流,30 秒冷却后再重试
- 避免 get_multiplexed_async_connection 每次请求阻塞 2 秒
前端:
- plugin store schema 加载改为 Promise.allSettled 并行(原为 for...of 顺序)
- 先基于 entities 渲染回退菜单,schema 加载完成后更新
- 移除 Home useEffect 中 unreadCount 依赖,消除双重 fetch
- MainLayout 使用选择性 store selector 减少重渲染
2026-04-17 01:12:17 +08:00
iven
f4dd228a67
feat(web): 插件侧边栏改为三级菜单结构 — 按插件名分组可折叠
...
插件菜单从扁平列表改为三级结构:
插件(分组)→ 插件名(可折叠子标题)→ 页面列表
- store 新增 PluginMenuGroup 类型和 pluginMenuGroups getter
- MainLayout 新增 SidebarSubMenu 组件,支持展开/收起
- 折叠侧边栏时子菜单显示插件图标 + tooltip
- 子菜单项增加缩进样式区分层级
- CRM 插件 name 改为 "CRM" 避免与页面标题重名
2026-04-17 01:01:19 +08:00
iven
ae62e2ecb2
feat(web): 完善插件前端页面 — 数据 API、筛选、视图切换和统计展示
...
- 新增 pluginData API 层:count/aggregate/stats 端点调用
- PluginCRUDPage 支持 visible_when 条件字段、筛选器下拉、视图切换
- PluginTabsPage 支持 tabs 布局和子实体 CRUD
- PluginTreePage 实现树形数据加载和节点展开/收起
- PluginGraphPage 实现关系图谱可视化展示
- PluginDashboardPage 实现统计卡片和聚合数据展示
- PluginAdmin 状态显示优化
- plugin store 增强 schema 加载逻辑和菜单生成
2026-04-16 23:42:57 +08:00
iven
3483395f5e
fix(plugin): 修复插件 schema API、动态表 JSONB 和 SQL 注入防护
...
- get_schema 端点同时返回 entities 和 ui 页面配置,修复前端无法生成动态菜单的问题
- 动态表 INSERT/UPDATE 添加 ::jsonb 类型转换,修复 PostgreSQL 类型推断错误
- JSONB 索引创建改为非致命(warn 跳过),避免索引冲突阻断安装流程
- 权限注册/注销改用参数化查询,消除 SQL 注入风险
- DDL 语句改用 execute_unprepared,避免不必要的安全检查开销
- clear_plugin 支持已上传状态的清理
- 添加关键步骤 tracing 日志便于排查安装问题
2026-04-16 23:42:40 +08:00
iven
b482230a07
docs(crm): 更新架构快照 + 提炼插件开发 Skill
...
- CLAUDE.md §12 新增 CRM 插件完成记录和 erp-plugin-crm 模块
- §13 新增动态表 SQL 注入防护和插件权限注册反模式
- §10 scope 表补充 plugin/crm 范围
- §11 设计文档索引补充 CRM 插件设计和实施计划
- 新建 .claude/skills/plugin-development/SKILL.md 可复用插件开发流程
2026-04-16 19:23:54 +08:00
iven
9effa9f942
feat(plugin): 新增数据统计 REST API — count 和 aggregate 端点
...
- dynamic_table: 新增 build_filtered_count_sql(带过滤/搜索的 COUNT)和 build_aggregate_sql(按字段分组计数)
- data_service: 新增 count 和 aggregate 方法,支持实时统计查询
- data_handler: 新增 count_plugin_data 和 aggregate_plugin_data REST handler
- data_dto: 新增 AggregateItem、AggregateQueryParams、CountQueryParams 类型
- module: 注册 /plugins/{plugin_id}/{entity}/count 和 /aggregate 路由
- 包含 8 个新增单元测试,全部通过
2026-04-16 16:22:33 +08:00
iven
169e6d1fe5
feat(web): 新增 PluginGraphPage 关系图谱和 PluginDashboardPage 统计概览
...
- PluginGraphPage: Canvas 2D 绘制客户关系图谱,支持中心节点选择和关系类型筛选
- PluginDashboardPage: 全量数据前端聚合统计,支持按 filterable 字段分组计数
- App.tsx: 注册 /graph/:entityName 和 /dashboard 路由
2026-04-16 16:15:32 +08:00
iven
a6d3a0efcc
feat(plugin): 实现插件权限注册,install 时写入 permissions 表、uninstall 时软删除
...
跨 crate 方案:erp-plugin 使用 raw SQL 操作 permissions 表,
避免直接依赖 erp-auth entity,保持模块间松耦合。
- erp-core: 新增 PermissionDescriptor 类型和 ErpModule::permissions() 方法
- erp-plugin service.rs install(): 解析 manifest.permissions,INSERT ON CONFLICT DO NOTHING
- erp-plugin service.rs uninstall(): 软删除 role_permissions 关联 + permissions 记录
2026-04-16 12:42:13 +08:00
iven
92789e6713
feat(crm): 创建 CRM 插件 crate + 前端 tabs/tree 页面类型 + 动态菜单
...
- CRM WASM 插件:Cargo.toml + src/lib.rs + plugin.toml(5 实体 + 9 权限 + 6 页面)
- 注册 erp-plugin-crm 到 workspace members
- PluginTabsPage: 通用标签页容器,递归渲染子页面
- PluginTreePage: 通用树形页面,前端构建树结构
- App.tsx: 新增 /tabs/:pageLabel 和 /tree/:entityName 路由
- plugin store: 从 manifest pages 生成菜单(支持 tabs 聚合)
- MainLayout: 动态图标映射(team/user/message/tags/apartment)
2026-04-16 12:41:17 +08:00
iven
e68fe8c1b1
feat(web): 插件前端全面增强 — 搜索/筛选/排序/详情页/条件表单/timeline 视图
...
- pluginData API: 支持 filter/search/sort_by/sort_order 参数
- plugins API: 新增 PluginFieldSchema/PluginEntitySchema/PluginPageSchema 类型
- PluginCRUDPage: 添加搜索框、筛选栏、视图切换(表格/时间线)
- PluginCRUDPage: 添加详情 Drawer(Descriptions + 嵌套 CRUD)
- PluginCRUDPage: 支持 visible_when 条件表单字段动态显示/隐藏
- PluginCRUDPage: 支持 compact 模式用于 detail 页面内嵌
2026-04-16 12:35:24 +08:00
iven
0ad77693f4
feat(plugin): 集成过滤查询/排序/搜索到 REST API,添加数据校验和 searchable 索引
...
- data_dto: PluginDataListParams 新增 filter/sort_by/sort_order
- data_service: list 方法支持 filter/search/sort 参数,自动提取 searchable 字段
- data_service: create/update 添加 required 字段校验
- data_service: 新增 resolve_entity_fields 和 validate_data 辅助函数
- data_handler: 权限检查从硬编码改为动态计算 plugin_id.entity.action
- dynamic_table: searchable 字段自动创建 B-tree 索引
2026-04-16 12:31:53 +08:00
iven
472bf244d8
feat(plugin): 扩展 manifest schema 支持 searchable/filterable/visible_when 和 tagged enum 页面类型
...
- PluginField 新增 searchable/filterable/sortable/visible_when 字段
- PluginPage 替换为 tagged enum PluginPageType(crud/tree/detail/tabs)
- 新增 PluginSection enum(fields/crud 区段)
- 新增 validate_pages 递归验证页面配置
- 更新现有测试适配新 TOML 格式
- 新增 3 个测试覆盖新页面类型解析和验证
2026-04-16 12:28:55 +08:00
iven
52c8821ffa
fix(plugin): 修复唯一索引使用 CREATE UNIQUE INDEX 并添加过滤查询 SQL 构建器
...
- unique 字段索引从 CREATE INDEX 改为 CREATE UNIQUE INDEX
- 新增 build_unique_index_sql 辅助方法
- 新增 build_filtered_query_sql 支持 filter/search/sort 组合查询
- 新增 sanitize_identifier 防止 SQL 注入
- 添加 6 个单元测试覆盖过滤查询场景
2026-04-16 12:24:42 +08:00
iven
ff352a4c24
feat(plugin): 集成 WASM 插件系统到主服务并修复链路问题
...
- 新增 erp-plugin crate:插件管理、WASM 运行时、动态表、数据 CRUD
- 新增前端插件管理页面(PluginAdmin/PluginCRUDPage)和 API 层
- 新增插件数据迁移(plugins/plugin_entities/plugin_event_subscriptions)
- 新增权限补充迁移(为已有租户补充 plugin.admin/plugin.list 权限)
- 修复 PluginAdmin 页面 InstallOutlined 图标不存在的崩溃问题
- 修复 settings 唯一索引迁移顺序错误(先去重再建索引)
- 更新 wiki 和 CLAUDE.md 反映插件系统集成状态
- 新增 dev.ps1 一键启动脚本
2026-04-15 23:32:02 +08:00
iven
7e8fabb095
feat(auth): add change password API and frontend page
...
Backend:
- Add ChangePasswordReq DTO with validation (current + new password)
- Add AuthService::change_password() method with credential verification,
password rehash, and token revocation
- Add POST /api/v1/auth/change-password endpoint with utoipa annotation
Frontend:
- Add changePassword() API function in auth.ts
- Add ChangePassword.tsx page with form validation and confirmation
- Add "修改密码" tab in Settings page
After password change, all refresh tokens are revoked and the user
is redirected to the login page.
2026-04-15 01:32:18 +08:00
iven
d8a0ac7519
feat: implement on_tenant_created/deleted hooks and update ErpModule trait
...
- ErpModule trait hooks now accept db and event_bus parameters
- AuthModule.on_tenant_created: seeds default roles, permissions,
and admin user for new tenants using existing seed_tenant_auth()
- AuthModule.on_tenant_deleted: soft-deletes all users for the tenant
- Updated all other modules (config, workflow, message) to match
the new trait signature
2026-04-15 01:27:33 +08:00
iven
e44d6063be
feat: add utoipa path annotations to all API handlers and wire OpenAPI spec
...
- Add #[utoipa::path] annotations to all 70+ handler functions across
auth, config, workflow, and message modules
- Add IntoParams/ToSchema derives to Pagination, PaginatedResponse, ApiResponse
in erp-core, and MessageQuery/TemplateQuery in erp-message
- Collect all module paths into OpenAPI spec via AuthApiDoc, ConfigApiDoc,
WorkflowApiDoc, MessageApiDoc structs in erp-server main.rs
- Update openapi_spec handler to merge all module specs
- The /docs/openapi.json endpoint now returns complete API documentation
with all endpoints, request/response schemas, and security requirements
2026-04-15 01:23:27 +08:00
iven
ee65b6e3c9
test: add 149 unit tests across core, auth, config, message crates
...
Test coverage increased from ~34 to 183 tests (zero failures):
- erp-core (21): version check, pagination, API response, error mapping
- erp-auth (39): org tree building, DTO validation, error conversion,
password hashing, user model mapping
- erp-config (57): DTO validation, numbering reset logic, menu tree
building, error conversion. Fixed BatchSaveMenusReq nested validation
- erp-message (50): DTO validation, template rendering, query defaults,
error conversion
- erp-workflow (16): unchanged (parser + expression tests)
All tests are pure unit tests requiring no database.
2026-04-15 01:06:34 +08:00
iven
9568dd7875
chore: apply cargo fmt across workspace and update docs
...
- Run cargo fmt on all Rust crates for consistent formatting
- Update CLAUDE.md with WASM plugin commands and dev.ps1 instructions
- Update wiki: add WASM plugin architecture, rewrite dev environment docs
- Minor frontend cleanup (unused imports)
2026-04-15 00:49:20 +08:00
iven
e16c1a85d7
feat(web): comprehensive frontend performance and UI/UX optimization
...
Performance improvements:
- Vite build: manual chunks, terser minification, optimizeDeps
- API response caching with 5s TTL via axios interceptors
- React.memo for SidebarMenuItem, useCallback for handlers
- CSS classes replacing inline styles to reduce reflows
UI/UX enhancements (inspired by SAP Fiori, Linear, Feishu):
- Dashboard: trend indicators, sparkline charts, CountUp animation on stat cards
- Dashboard: pending tasks section with priority labels
- Dashboard: recent activity timeline
- Design system tokens: trend colors, line-height, dark mode refinements
- Enhanced quick actions with hover animations
Accessibility (Lighthouse 100/100):
- Skip-to-content link, ARIA landmarks, heading hierarchy
- prefers-reduced-motion support, focus-visible states
- Color contrast fixes: all text meets 4.5:1 ratio
- Keyboard navigation for stat cards and task items
SEO: meta theme-color, format-detection, robots.txt
2026-04-13 01:37:55 +08:00
iven
88f6516fa9
fix(web): fix PaletteOutlined icon import and apply theme config
...
- Replace non-existent PaletteOutlined with BgColorsOutlined
- Apply user's refined light/dark theme configuration with proper
color tokens, component overrides, and design system consistency
2026-04-12 18:57:10 +08:00
iven
9557c9ca16
fix(db): resolve migration bugs preventing fresh database initialization
...
- Fix composite primary keys in role_permissions and user_roles tables
(PostgreSQL does not allow multiple PRIMARY KEY constraints)
- Fix FK table name mismatch: tasks → tokens (was wf_tokens)
- Fix FK table name mismatch: messages → message_templates (was message_templates_ref)
- Fix tenant table name in main.rs SQL: tenant (not tenants)
- Fix React Router nested routes: add /* wildcard for child route matching
2026-04-12 16:58:47 +08:00
iven
3b41e73f82
fix: resolve E2E audit findings and add Phase C frontend pages
...
- Fix audit_log handler multi-tenant bug: use Extension<TenantContext>
instead of hardcoded default_tenant_id
- Fix sendMessage route mismatch: frontend /messages/send → /messages
- Add POST /users/{id}/roles backend route for role assignment
- Add task.completed event payload: started_by + instance_id for
notification delivery
- Add audit log viewer frontend page (AuditLogViewer.tsx)
- Add language management frontend page (LanguageManager.tsx)
- Add api/auditLogs.ts and api/languages.ts modules
2026-04-12 15:57:33 +08:00