<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Access Control on YennJ12 Engineering Blog</title><link>https://yennj12.js.org/yennj12_blog_V4/tags/access-control/</link><description>Recent content in Access Control on YennJ12 Engineering Blog</description><generator>Hugo -- gohugo.io</generator><language>en-us</language><lastBuildDate>Fri, 07 Aug 2026 15:00:00 +0800</lastBuildDate><atom:link href="https://yennj12.js.org/yennj12_blog_V4/tags/access-control/feed.xml" rel="self" type="application/rss+xml"/><item><title>QM 深度解析（二）：Scope 與 Resolution — 一次對話如何解析出身分、權限與工作區</title><link>https://yennj12.js.org/yennj12_blog_V4/posts/qm-multiplayer-agent-part2-scope-resolution-zh/</link><pubDate>Fri, 07 Aug 2026 15:00:00 +0800</pubDate><guid>https://yennj12.js.org/yennj12_blog_V4/posts/qm-multiplayer-agent-part2-scope-resolution-zh/</guid><description>多租戶最危險的地方不是資料庫查詢忘了加 WHERE tenant_id = ?。 那種 bug 會被 code review 抓到。 真正危險的是：Agent 在頻道裡回答問題時，引用了只有提問者有權讀的檔案。 沒有 SQL 出錯，沒有權限檢查失敗 —— 是模型自己把資料唸出來的。
本篇是 QM 深度解析系列 的第二篇，主角是 src/resolution/（1,593 行）、src/acl/（354 行） 與 src/sessions/（1,936 行）。
一、ScopeId：一個字串撐起整個系統 1.1 定義只有 30 行 1const SCOPE_KINDS = [&amp;#34;personal&amp;#34;, &amp;#34;channel&amp;#34;, &amp;#34;team&amp;#34;, &amp;#34;org&amp;#34;, &amp;#34;group&amp;#34;] as const; 2export type ScopeKind = (typeof SCOPE_KINDS)[number]; 3 4export type ScopeId = string; 5 6export function scopeId(kind: ScopeKind, ref: string): ScopeId { 7 return `${kind}:${ref}`; 8} 9 10export function personalScope(principalId: string): ScopeId { 11 return scopeId(&amp;#34;personal&amp;#34;, principalId); 12} 13 14export function parseScopeId(id: ScopeId): { kind: ScopeKind | null; ref: string } { 15 const sep = id.</description></item></channel></rss>