spec.md 2.0 KB

ADDED Requirements

Requirement: 租户识别

mjava-pro SHALL 在请求入口识别租户上下文。Controller 入口 MUST 通过 TenantInterceptor 读 HTTP Header X-Tenant-Id

Scenario: Header 缺失

  • WHEN 请求缺少 X-Tenant-Id
  • THEN 返回 401 { code: "TENANT_REQUIRED" }

Scenario: 租户不存在

  • WHEN Header 存在但租户不在注册表
  • THEN 返回 403 { code: "TENANT_NOT_FOUND" }

Scenario: 识别成功

  • WHEN tenantId 匹配注册表记录且启用
  • THEN TenantContext.set(profile) 写入 ThreadLocal
  • AND 请求结束时在 finally 块 TenantContext.clear()

Requirement: 异步任务传递

TenantContext MUST 在 @Async 线程池与 CompletableFuture 切换时正确传递,避免子线程拿不到租户凭据。

Scenario: @Async 线程池

  • WHEN 通过 @Async 提交任务
  • THEN 线程池 TaskDecorator 必须复制 TenantContext 到子线程
  • AND 子线程开始执行时 TenantContext.current() 返回发起请求的租户

Scenario: 手动线程切换

  • WHEN 代码显式切换线程(如 CompletableFuture.supplyAsync(executor, ...)
  • THEN 必须使用 TenantContext.propagate(ctx, runnable) 包装

Requirement: Token 隔离

mjava-pro SHALL 使用带租户前缀的 UtilToken key,避免多租户间 token 互相覆盖。

Scenario: key 格式

  • WHEN 调用 UtilToken 存取
  • THEN key 格式统一为 {tenantId}:{vendor}:{appKey}
  • AND mjava-pro 代码 MUST 不使用无 tenant 前缀的 UtilToken 接口

Scenario: 无租户上下文场景

  • WHEN 定时任务或启动时发起调用
  • THEN 必须显式传 tenantId,或声明为 SYSTEM 伪租户

Requirement: 审计日志扩展

mjava-pro SHALL 在 mjava-baseline §3.5 字段基础上追加 tenantId,日志按租户分片。

Scenario: 按租户分片输出

  • WHEN 请求进入
  • THEN 日志输出到 ./log/{日期}/pro-{tenantId}.log
  • AND MDC 含 tenantId 字段