用途:指导在 Rails 中把登录身份(Identity)、租户内人员(User)与成员关系(Membership)拆开,避免把某个客户的用户泄漏到另一个分片。
主要能力:Identity 全局保存 email、sessions、magic links、access tokens,负责认证;Membership 全局保存 identity_id + tenant_id + role,负责“能否进入该工作区”;User 位于租户库(Cortex/Innkeeper),保存 identity_id、name 与租户内角色。Herald 可省略租户内 User,仅用全局 AccountMembership。Fizzy 在同一数据库用 users.identity_id + account_id 表达同一思路。
使用方式:Identity 保持全局,登录只创建 Session,不选租户。Membership 是连接表,角色放在这里,唯一性约束为 identity_id 作用域 tenant_id。加入时先全局创建 Membership,再在 with_tenant 内创建 User,顺序不能反。join 方法用事务包裹,处理 RecordNotUnique 竞态。Current.identity 来自会话,Current.tenant 来自租户作用域,Current.user 由 identity_id 在租户内查找;Current.user 为空表示已登录但非该租户成员,应返回 403 而非登录循环。加入码为可分享的 XXXX-XXXX-XXXX(Base58,排除 0/O/I/l),全局表,每租户/项目一个有效码,兑换需限流,成功后才递增 usage_count。
适用场景:多租户 Rails 应用、SQLite-per-tenant、activerecord-tenanted、magic-link-auth 之上的用户与工作区体系。
限制与反模式:不要在 User 上挂 sessions;不要在租户内 find_or_create_by(email:);不要只用 Current.identity 授权;不要先建 User 后建 Membership;不要把加入码放进 magic-link 邮件;不要从会话设置 Current.user。具体测试辅助与各项目差异见 reference.md。