[{"data":1,"prerenderedAt":37},["ShallowReactive",2],{"doc:\u002Fcontracts\u002Foauth\u002F12-site-roles":3},{"title":4,"route":5,"toc":6,"segments":32,"source":36},"站点域角色（site-scoped roles，权威定义，Tier A）","\u002Fcontracts\u002Foauth\u002F12-site-roles",[7,11,14,17,20,23,26,29],{"id":8,"text":9,"depth":10},"1-为什么需要它","1. 为什么需要它",2,{"id":12,"text":13,"depth":10},"2-claim-形状与出现点-权威","2. claim 形状与出现点（权威）",{"id":15,"text":16,"depth":10},"3-可授予的角色名策略-权威","3. 可授予的角色名策略（权威）",{"id":18,"text":19,"depth":10},"4-时效-同-11-2","4. 时效（同 §11 §2）",{"id":21,"text":22,"depth":10},"5-下游必须遵守的规则-must","5. 下游必须遵守的规则（MUST）",{"id":24,"text":25,"depth":10},"6-授予入口-仅-oauth-后台","6. 授予入口（仅 OAuth 后台）",{"id":27,"text":28,"depth":10},"7-下游接入清单","7. 下游接入清单",{"id":30,"text":31,"depth":10},"8-关联文档","8. 关联文档",[33],{"type":34,"html":35},"html","\u003Ch1 id=\"站点域角色-site-scoped-roles-权威定义-tier-a\" tabindex=\"-1\">站点域角色（site-scoped roles，权威定义，Tier A）\u003C\u002Fh1>\n\u003Cp>返回 \u003Ca href=\"\u002Fcontracts\u002Foauth\">README\u003C\u002Fa>\u003C\u002Fp>\n\u003Chr>\n\u003Cblockquote>\n\u003Cp>\u003Cstrong>本文是「站点域角色」\u003Ccode>site_roles\u003C\u002Fcode> claim 的唯一权威来源（Tier A）。\u003C\u002Fstrong> 它是 \u003Ca href=\"\u002Fcontracts\u002Foauth\u002F11-roles\">11-roles.md\u003C\u002Fa>\n五角色契约的\u003Cstrong>加法扩展\u003C\u002Fstrong>,不改动其任何既有语义:让一个账号可以\u003Cstrong>只在某一个站点\u003C\u002Fstrong>持有职务\n(如「letmoe 的 moderator」),而不获得任何跨站权力。下游未升级前完全不受影响(未知 claim 被忽略)。\u003C\u002Fp>\n\u003C\u002Fblockquote>\n\u003Chr>\n\u003Ch2 id=\"1-为什么需要它\" tabindex=\"-1\">1. 为什么需要它\u003C\u002Fh2>\n\u003Cp>全局五角色是\u003Cstrong>全站\u003C\u002Fstrong>的:授予 \u003Ccode>moderator\u003C\u002Fcode> 意味着 kungal \u002F moyu \u002F letmoe 三站全境版主。当多站并存,\n「仅在 letmoe 任职」这一真实需求无法用五角色表达。站点域角色补上这一层:\u003Cstrong>授予中央化(仍归 OAuth\n后台),但只对被授予的那个站点生效\u003C\u002Fstrong>。\u003C\u002Fp>\n\u003Cp>与 §11 的关系:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>\u003Cstrong>全局角色(\u003Ccode>roles\u003C\u002Fcode> claim)不变\u003C\u002Fstrong>:管理轴 \u003Ccode>moderator ⊂ admin ⊂ ren\u003C\u002Fcode>、\u003Ccode>creator\u003C\u002Fcode> 正交,一切照旧。\u003C\u002Fli>\n\u003Cli>\u003Cstrong>站点角色(\u003Ccode>site_roles\u003C\u002Fcode> claim)是新增的正交层\u003C\u002Fstrong>:只在签发 token 的那个 client 的站点生效。\u003C\u002Fli>\n\u003Cli>两者在下游\u003Cstrong>取并集\u003C\u002Fstrong>后喂给同一套能力判定(见 §5)。\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch2 id=\"2-claim-形状与出现点-权威\" tabindex=\"-1\">2. claim 形状与出现点（权威）\u003C\u002Fh2>\n\u003Cp>\u003Ccode>site_roles\u003C\u002Fcode> 是一个\u003Cstrong>扁平的角色名字符串数组\u003C\u002Fstrong>,与 \u003Ccode>roles\u003C\u002Fcode> claim 同构:\u003C\u002Fp>\n\u003Cpre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\">\u003Ccode class=\"language-json\">\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E;--shiki-dark:#E1E4E8\">{ \u003C\u002Fspan>\u003Cspan style=\"color:#005CC5;--shiki-dark:#79B8FF\">\"roles\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E;--shiki-dark:#E1E4E8\">: [\u003C\u002Fspan>\u003Cspan style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"creator\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E;--shiki-dark:#E1E4E8\">], \u003C\u002Fspan>\u003Cspan style=\"color:#005CC5;--shiki-dark:#79B8FF\">\"site_roles\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E;--shiki-dark:#E1E4E8\">: [\u003C\u002Fspan>\u003Cspan style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"moderator\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E;--shiki-dark:#E1E4E8\">], \u003C\u002Fspan>\u003Cspan style=\"color:#005CC5;--shiki-dark:#79B8FF\">\"site_id\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E;--shiki-dark:#E1E4E8\">: \u003C\u002Fspan>\u003Cspan style=\"color:#005CC5;--shiki-dark:#79B8FF\">3\u003C\u002Fspan>\u003Cspan style=\"color:#24292E;--shiki-dark:#E1E4E8\">, \u003C\u002Fspan>\u003Cspan style=\"color:#005CC5;--shiki-dark:#79B8FF\">\"...\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E;--shiki-dark:#E1E4E8\">: \u003C\u002Fspan>\u003Cspan style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"...\"\u003C\u002Fspan>\u003Cspan style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cul>\n\u003Cli>\u003Cstrong>按签发 client 的站点定界\u003C\u002Fstrong>:发给 letmoe client 的 token,\u003Ccode>site_roles\u003C\u002Fcode> 只含该用户\u003Cstrong>在 letmoe\u003C\u002Fstrong>\n的授予,\u003Cstrong>绝不\u003C\u002Fstrong>含别站的。无跨站泄漏,token 不膨胀。\u003C\u002Fli>\n\u003Cli>\u003Cstrong>空则省略\u003C\u002Fstrong>:用户在该站无授予时,整个 \u003Ccode>site_roles\u003C\u002Fcode> 字段不出现(\u003Ccode>omitempty\u003C\u002Fcode>)。非站点绑定的\nclient(如 OAuth 站自身、first-party 登录 token)也不带。\u003C\u002Fli>\n\u003Cli>\u003Cstrong>只含未过期授予\u003C\u002Fstrong>:带 \u003Ccode>expires_at\u003C\u002Fcode> 且已过期的授予不出现。\u003C\u002Fli>\n\u003Cli>出现在三处,语义一致:\n\u003Col>\n\u003Cli>\u003Cstrong>access token\u003C\u002Fstrong> 的 \u003Ccode>site_roles\u003C\u002Fcode> claim(\u003Ccode>\u002Foauth\u002Ftoken\u003C\u002Fcode> 授权码\u002F刷新两条路都带)。\u003C\u002Fli>\n\u003Cli>\u003Cstrong>\u003Ccode>GET \u002Foauth\u002Fuserinfo\u003C\u002Fcode>\u003C\u002Fstrong> 响应的 \u003Ccode>site_roles\u003C\u002Fcode> 字段(按调用所用 token 的站点)。\u003C\u002Fli>\n\u003Cli>\u003Cstrong>\u003Ccode>GET \u002Fusers\u002Fbatch\u003C\u002Fcode>\u003C\u002Fstrong>(S2S,见 \u003Ca href=\"\u002Fcontracts\u002Foauth\u002F03-cross-service\">03\u003C\u002Fa>)每个 brief 的 \u003Ccode>site_roles\u003C\u002Fcode> 字段\n(按\u003Cstrong>请求方 client\u003C\u002Fstrong> 的站点)。\u003C\u002Fli>\n\u003C\u002Fol>\n\u003C\u002Fli>\n\u003Cli>\u003Cstrong>wire 模式无关\u003C\u002Fstrong>:legacy 与标准 OIDC wire(\u003Ccode>KUN_OIDC_STANDARD_WIRE\u003C\u002Fcode>)下携带方式一致——它就是\naccess token 里的一个自定义 claim。\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch2 id=\"3-可授予的角色名策略-权威\" tabindex=\"-1\">3. 可授予的角色名策略（权威）\u003C\u002Fh2>\n\u003Cp>站点角色名由 IdP 在授予时按\u003Cstrong>策略\u003C\u002Fstrong>校验(IdP 只验策略,不认识各站的具体词汇):\u003C\u002Fp>\n\u003Cul>\n\u003Cli>\u003Cstrong>禁止\u003C\u002Fstrong> \u003Ccode>user\u003C\u002Fcode> \u002F \u003Ccode>admin\u003C\u002Fcode> \u002F \u003Ccode>ren\u003C\u002Fcode>:\u003Ccode>user\u003C\u002Fcode> 是隐式基座;\u003Ccode>admin\u003C\u002Fcode> \u002F \u003Ccode>ren\u003C\u002Fcode> 是\u003Cstrong>全局专属\u003C\u002Fstrong>管理层。这条禁令\n是安全保证的核心(见 §5)——站点角色永不可能是 \u003Ccode>admin\u003C\u002Fcode>\u002F\u003Ccode>ren\u003C\u002Fcode>。\u003C\u002Fli>\n\u003Cli>\u003Cstrong>允许\u003C\u002Fstrong> \u003Ccode>moderator\u003C\u002Fcode> \u002F \u003Ccode>creator\u003C\u002Fcode>:即「该站上等同于全局同名角色的本站切片」(letmoe 的 moderator =\n只在 letmoe 有版主权)。\u003C\u002Fli>\n\u003Cli>\u003Cstrong>允许站点自定义名\u003C\u002Fstrong>:pattern \u003Ccode>^[a-z][a-z0-9_]{1,49}$\u003C\u002Fcode>(小写字母开头、2–50 位 \u003Ccode>a-z0-9_\u003C\u002Fcode>),如\n\u003Ccode>event_organizer\u003C\u002Fcode>。这些自定义名\u003Cstrong>对应站点自行定义其含义\u003C\u002Fstrong>;IdP 不解释它们。\u003C\u002Fli>\n\u003Cli>站点对\u003Cstrong>不认识\u003C\u002Fstrong>的名字天然 fail-closed:下游能力映射查无此名 = 零授予。\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch2 id=\"4-时效-同-11-2\" tabindex=\"-1\">4. 时效（同 §11 §2）\u003C\u002Fh2>\n\u003Cp>站点角色变更在\u003Cstrong>下一次 token 刷新\u003C\u002Fstrong>后生效。下游\u003Cstrong>必须\u003C\u002Fstrong>每次从最新 claim 重新解析,不得长期缓存到\n失去时效——提权\u002F降权要能在会话中途生效。\u003Ccode>expires_at\u003C\u002Fcode> 到期后,刷新出的新 token 自动不再含该角色。\u003C\u002Fp>\n\u003Ch2 id=\"5-下游必须遵守的规则-must\" tabindex=\"-1\">5. 下游必须遵守的规则（MUST）\u003C\u002Fh2>\n\u003Col>\n\u003Cli>\u003Cstrong>联合解析\u003C\u002Fstrong>:把 \u003Ccode>site_roles\u003C\u002Fcode> 并入你已有的角色集(\u003Ccode>effective = roles ∪ site_roles\u003C\u002Fcode>),再喂给你\n\u003Cstrong>既有\u003C\u002Fstrong>的能力函数\u002F权限判定。不需要为它写新的判定路径。\u003C\u002Fli>\n\u003Cli>\u003Cstrong>只对当前站生效是天然的\u003C\u002Fstrong>:claim 已由 OP 按 client 站点定界,你拿到的 \u003Ccode>site_roles\u003C\u002Fcode> 本就只属本站。\n你\u003Cstrong>不需要\u003C\u002Fstrong>、也\u003Cstrong>拿不到\u003C\u002Fstrong>别站的站点角色。\u003C\u002Fli>\n\u003Cli>\u003Cstrong>安全不变量(为什么联合是安全的)\u003C\u002Fstrong>:\u003Ccode>site_roles\u003C\u002Fcode> \u003Cstrong>永不含\u003C\u002Fstrong> \u003Ccode>admin\u003C\u002Fcode>\u002F\u003Ccode>ren\u003C\u002Fcode>(§3 禁令 + IdP 校验),\n所以把它并进角色集\u003Cstrong>只可能\u003C\u002Fstrong>新增 \u003Ccode>moderator\u003C\u002Fcode>\u002F\u003Ccode>creator\u003C\u002Fcode>\u002F自定义名,\u003Cstrong>绝不可能\u003C\u002Fstrong>让一个站点授予触达\n\u003Ccode>admin\u003C\u002Fcode>\u002F\u003Ccode>ren\u003C\u002Fcode> 专属能力。管理面(用户管理、站点\u002Fclient 配置、PII、artifact 运维)只认 \u003Ccode>admin\u003C\u002Fcode>\u002F\u003Ccode>ren\u003C\u002Fcode>,\n站点角色结构上够不着。\u003C\u002Fli>\n\u003Cli>\u003Cstrong>自定义捆名各站自治\u003C\u002Fstrong>:\u003Ccode>moderator\u003C\u002Fcode>\u002F\u003Ccode>creator\u003C\u002Fcode> 沿用 §11 的语义;站点自定义名的含义由该站自己在其\n权限映射里定义(IdP 不参与)。\u003C\u002Fli>\n\u003Cli>\u003Cstrong>不得在下游实现授予\u002F撤销\u003C\u002Fstrong>:站点角色的授予\u002F撤销只在 OAuth 后台(与 §11 §4 规则 5 一致)。\u003C\u002Fli>\n\u003C\u002Fol>\n\u003Ch2 id=\"6-授予入口-仅-oauth-后台\" tabindex=\"-1\">6. 授予入口（仅 OAuth 后台）\u003C\u002Fh2>\n\u003Cdiv class=\"kun-table-wrap\">\u003Ctable>\u003Cthead>\n\u003Ctr>\n\u003Cth>操作\u003C\u002Fth>\n\u003Cth>端点\u003C\u002Fth>\n\u003Cth>门\u003C\u002Fth>\n\u003C\u002Ftr>\n\u003C\u002Fthead>\n\u003Ctbody>\n\u003Ctr>\n\u003Ctd>授予\u003C\u002Ftd>\n\u003Ctd>\u003Ccode>POST \u002Fadmin\u002Fusers\u002F:uuid\u002Fsite-roles\u003C\u002Fcode> \u003Ccode>{site_id, role_name, note?, expires_at?}\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>\u003Ccode>admin\u003C\u002Fcode> \u002F \u003Ccode>ren\u003C\u002Fcode>\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>撤销\u003C\u002Ftd>\n\u003Ctd>\u003Ccode>DELETE \u002Fadmin\u002Fusers\u002F:uuid\u002Fsite-roles?site_id=&amp;role_name=\u003C\u002Fcode>(幂等)\u003C\u002Ftd>\n\u003Ctd>\u003Ccode>admin\u003C\u002Fcode> \u002F \u003Ccode>ren\u003C\u002Fcode>\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003C\u002Ftbody>\n\u003C\u002Ftable>\u003C\u002Fdiv>\u003Cul>\n\u003Cli>\u003Cstrong>不能给自己授予\u002F撤销\u003C\u002Fstrong>(与全局角色矩阵一致)。\u003C\u002Fli>\n\u003Cli>授予记录 \u003Ccode>granted_by\u003C\u002Fcode>(操作者)、\u003Ccode>granted_at\u003C\u002Fcode>,可选 \u003Ccode>expires_at\u003C\u002Fcode>(过期)\u002F\u003Ccode>note\u003C\u002Fcode>。\u003C\u002Fli>\n\u003Cli>\u003Ccode>admin\u003C\u002Fcode> 即可授予站点角色——站点角色的天花板(\u003Ccode>moderator\u003C\u002Fcode>)低于全局 \u003Ccode>admin\u003C\u002Fcode> 本身能授的范围。\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch2 id=\"7-下游接入清单\" tabindex=\"-1\">7. 下游接入清单\u003C\u002Fh2>\n\u003Cul>\n\u003Cli>\u003Cstrong>kungal \u002F moyu \u002F letmoe 后端\u003C\u002Fstrong>:在把 \u003Ccode>roles\u003C\u002Fcode> claim 映射进内部能力时,\u003Cstrong>并入\u003C\u002Fstrong> \u003Ccode>site_roles\u003C\u002Fcode>\n(\u003Ccode>CanModerate\u003C\u002Fcode> 之类的判定对「本站 moderator」自然放行);自定义捆名各站在本仓定义其权限。\u003C\u002Fli>\n\u003Cli>\u003Cstrong>只读展示\u003C\u002Fstrong>:\u003Ccode>GET \u002Fusers\u002Fbatch\u003C\u002Fcode> 的 brief 现带 \u003Ccode>site_roles\u003C\u002Fcode>(本站),可用于「本站版主」标记等。\u003C\u002Fli>\n\u003Cli>\u003Cstrong>无需改动\u003C\u002Fstrong>:不使用站点角色的站点\u003Cstrong>零改动\u003C\u002Fstrong>——未知\u002F缺失的 \u003Ccode>site_roles\u003C\u002Fcode> claim 被忽略。\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch2 id=\"8-关联文档\" tabindex=\"-1\">8. 关联文档\u003C\u002Fh2>\n\u003Cul>\n\u003Cli>\u003Ca href=\"\u002Fcontracts\u002Foauth\u002F11-roles\">11-roles.md\u003C\u002Fa> —— 全局五角色契约(本文是它的加法扩展)。\u003C\u002Fli>\n\u003Cli>\u003Ca href=\"\u002Fcontracts\u002Foauth\u002F04-tokens-and-errors#jwt-access-token-claims\">04-tokens-and-errors.md\u003C\u002Fa> —— access token claims 位置。\u003C\u002Fli>\n\u003Cli>\u003Ca href=\"\u002Fcontracts\u002Foauth\u002F03-cross-service\">03-cross-service.md\u003C\u002Fa> —— \u003Ccode>\u002Fusers\u002Fbatch\u003C\u002Fcode> S2S 面。\u003C\u002Fli>\n\u003Cli>infra 内部设计(引擎\u002F词汇\u002F纪律):\u003Ccode>docs\u002Fauth\u002F04-permission-first-authz.md\u003C\u002Fcode>。\u003C\u002Fli>\n\u003C\u002Ful>\n","kun-galgame-infra\u002Fdocs\u002Fintegration\u002Foauth\u002F12-site-roles.md",1783514297248]