# Redis 认证授权缓存

## 请求链路

受保护请求先在本地完成 JWT 验签，再通过一次 Redis MGET 校验 Session、用户、租户、成员资格和持久化授权版本。权限快照使用 60 秒进程内缓存和 5 分钟 Redis 缓存；本地快照键包含授权版本，因此撤权后的下一请求不会继续使用旧权限。PostgreSQL 始终是事实源，Redis 读取失败时绕过本地快照并回退数据库。

缓存不保存 JWT、Refresh Token、手机号或邮箱。Redis key 使用环境隔离前缀，并区分 platform/tenant realm、tenant、user 和 session。

## 配置与故障语义

```json
{
  "Security": {
    "AuthorizationCache": {
      "Mode": "Disabled",
      "LocalSnapshotSeconds": 60,
      "DistributedStateSeconds": 60,
      "DistributedSnapshotSeconds": 300,
      "JitterPercent": 20
    }
  }
}
```

- `Disabled`：保持 PostgreSQL 权威读取，仅维护持久化授权版本。
- `Shadow`：PostgreSQL 决策仍为准，同时读取、回填和比较 Redis 结果。
- `Active`：Redis 为主要读取路径，缓存缺失或不可用时回退 PostgreSQL。
- Redis 与 PostgreSQL 同时不可用时返回 `503`，错误码为 `auth_security_unavailable`。

生产环境的 API 和 Worker 都必须配置 `ConnectionStrings:Redis` 或 `REDIS_URL`。Worker 重试 `authorization_cache_invalidations` 中未完成的失效事件；Redis 版本写入是单调的，旧事件不会覆盖新版本。

## 发布与回滚

1. 先部署迁移，保持 `Disabled`。
2. 切换 `Shadow`，观察 `Tiku.Security.AuthorizationCache` 指标中的 mismatch、fallback 和 Redis 延迟。
3. 确认无非并发不一致后，对单实例启用 `Active`，再逐步扩容。
4. 回滚时只把模式切回 `Disabled`，不回退数据库迁移。

RBAC 表和权限目录由 PostgreSQL 触发器在业务事务内推进授权版本并写入失效事件。任何新增的用户、成员、租户、Session 或角色权限写路径，也必须调用 `IAuthorizationStateInvalidator` 完成同步 Redis 失效。
