Selaa lähdekoodia

docs: 记录 lj 多用户准入未打通(平台 s6 注入限制)

## 问题
agent-lj 的同事(@pnfapmsbhs)发消息不回复,已试 5 种方案全部失败。

## 根因(已彻底定位)
平台在容器启动时把 MATRIX_ALLOWED_USERS 注入到
/run/s6/container_environment/(root:root),容器内改不掉。
而 authz_mixin 的判定逻辑是:
  有非空白名单 → 只认名单,GATEWAY_ALLOW_ALL_USERS 永远轮不到

.lenv 里无论「追加」「置空」「整行删除」都压不过它。

## 差异
- agent-node-lj-test(10-17 建,containerRef 空):s6 无此文件 → ALLOW_ALL 天然生效
- agent-lj(10-21 建,containerRef=agent-lj):s6 有此文件 → 被拦

## 待办(明日,需平台侧)
删除 lj 容器的 /run/s6/container_environment/MATRIX_ALLOWED_USERS 后重启。

## 文档更新
- 新增遗留问题文档(含 5 种失败方案 + 验证方法)
- 多用户规范新增 §3.7「s6 注入 vs .env」
- 提示词踩坑表 8 → 9 条
- 文档索引补充第 7 项

Co-Authored-By: Claude Code <noreply@anthropic.com>
Huccct 13 tuntia sitten
vanhempi
commit
735f3b3396

+ 127 - 0
docs/00-tracking/2026-11-12-遗留问题-多用户准入未打通.md

@@ -0,0 +1,127 @@
+# 遗留问题:lj 容器多用户准入未打通(2026-11-12 夜)
+
+| 字段 | 值 |
+|---|---|
+| 状态 | 🔴 **未解决**,明日继续 |
+| 影响 | 同公司同事**无法使用 `agent-lj`**(能进会话、能发消息,但容器不回复) |
+| 对照 | `agent-node-lj-test` **正常**,同事已验证可用 |
+| 容器内能否解决 | ❌ **不能**,需平台侧操作 |
+
+---
+
+## 一、问题现象
+
+同事(`@pnfapmsbhs:fmode.cn`)在 App 里给 `lj` 发消息:
+
+```
+17:05:17Z  同事「你好」   → 无回复
+17:23:29Z  同事「你好」   → 无回复(重启后)
+17:23:48Z  同事「你好」   → 无回复(重启后)
+```
+
+App 侧表现:一直显示「已送达,等待回复…」直到超时。
+
+---
+
+## 二、根因(已彻底定位)
+
+### 2.1 判定代码顺序
+
+`gateway/authz_mixin.py` 的 `_principal_authorized()`:
+
+```python
+platform_allowlist = _auth_env("MATRIX_ALLOWED_USERS")
+
+if not (platform_allowlist or group_user_allowlist or group_chat_allowlist or global_allowlist):
+    return _env_truthy("GATEWAY_ALLOW_ALL_USERS")   # ← 兜底分支
+# 否则 → 走 allowlist 精确匹配 → 不在名单 → 拒绝
+```
+
+**`GATEWAY_ALLOW_ALL_USERS` 是「兜底」,只有所有 allowlist 都为空时才轮得到它。**
+
+### 2.2 lj 卡在哪
+
+| 层 | 值 | 来源 |
+|---|---|---|
+| `/run/s6/container_environment/MATRIX_ALLOWED_USERS` | `@xhvrjtmwqh:fmode.cn` | **平台在容器启动时注入**(root:root,10-21 14:35) |
+| `/opt/data/.env` | 已改为含 `@pnfapmsbhs` | 容器内可写 |
+| **进程实际生效** | **仍是 `@xhvrjtmwqh`** | `.env` **压不过** s6 注入 |
+
+**实测证据**:日志持续出现
+```
+WARNING gateway.run: Unauthorized user (ignored): Dropped a message
+from unrecognized matrix user (@pnfapmsbhs:fmode.cn)
+```
+
+### 2.3 为什么 lj-test 没这个问题
+
+| 容器 | 创建时间 | `containerRef` | s6 里有 `MATRIX_ALLOWED_USERS` 吗 |
+|---|---|---|---|
+| `agent-node-lj-test` | 2026-10-17 | **空** | ❌ **没有** |
+| `agent-lj` | 2026-10-21 | `agent-lj` | ✅ **有**(10-21 14:35 注入) |
+
+**推测**:10-21 之后容器创建流程变更,开始注入 `MATRIX_ALLOWED_USERS`。
+lj-test 是旧流程创建的,没有这个注入,所以 `ALLOW_ALL=true` 天然生效。
+
+---
+
+## 三、已尝试且**失败**的方案
+
+| # | 方案 | 结果 |
+|---|---|---|
+| 1 | 往 `.env` 追加 `@pnfapmsbhs` 到 `MATRIX_ALLOWED_USERS` | ❌ 重启后仍被拒 |
+| 2 | 设置 `GATEWAY_ALLOW_ALL_USERS=true` | ❌ 被非空白名单短路,不生效 |
+| 3 | `.env` 里把 `MATRIX_ALLOWED_USERS` 置空 | ❌ `_clear_known_keys_missing_from_dotenv` 只清「缺失的键」,空串不算缺失 |
+| 4 | **整行删除** `.env` 的 `MATRIX_ALLOWED_USERS` | ❌ s6 注入仍在,重启后恢复 |
+| 5 | 删除/清空 s6 里的文件 | ❌ **root:root,容器用户无权限** |
+
+---
+
+## 四、明日待做(按优先级)
+
+### P0:让同事能用 `lj`
+
+| 方案 | 做什么 | 代价 |
+|---|---|---|
+| **A(推荐)** | **平台/运维删除** lj 容器的 `/run/s6/container_environment/MATRIX_ALLOWED_USERS`,然后重启 | ✅ 不动数据,根治 |
+| B | 重建 lj 容器(按 lj-test 的方式) | ❌ 现有会话数据会丢 |
+| C | 暂用 lj-test | 同事能用,但 lj 空置 |
+
+**验证方法**(平台侧操作后):
+```bash
+# 1. 进程环境应无 MATRIX_ALLOWED_USERS
+PID=$(pgrep -f "gateway run" | tail -1)
+tr '\0' '\n' < /proc/$PID/environ | grep -E "MATRIX_ALLOWED|ALLOW_ALL"
+
+# 2. 日志无 Unauthorized
+tail -50 /opt/data/logs/gateway.log | grep -i unauthoriz
+
+# 3. 让同事发一条消息,App 里应收到回复
+```
+
+### P1:确认平台注入的边界
+
+需要平台侧回答:
+- 为什么 10-21 之后的容器会注入 `MATRIX_ALLOWED_USERS`?
+- 能不能改成不注入(或注入为空)?
+- 如果必须注入,App 侧该怎么做才能让同公司共用?
+
+---
+
+## 五、对文档的影响(已更新)
+
+| 文档 | 更新内容 |
+|---|---|
+| `多用户共用容器-完整规范` | 新增 §3.7「s6 注入 vs `.env` 的优先级」 |
+| `提示词-容器自我优化-v2` | 踩坑表新增第 9 条 |
+
+---
+
+## 六、当前可用状态
+
+| 容器 | 主人能用 | 同事能用 |
+|---|---|---|
+| `agent-node-lj-test` | ✅ | ✅ **已验证** |
+| `agent-lj` | ✅ | ❌ **待平台侧处理** |
+
+**结论:多人共用功能在 lj-test 上已跑通,lj 受平台注入限制暂不可用。**

+ 11 - 0
docs/03-interface/README-容器接入文档索引.md

@@ -69,6 +69,17 @@
 | 4 | **白名单 vs ALLOW_ALL 行为不确定** | ⚠️ `.env` 有白名单但没加载进进程 | 见多用户规范 §3.4 |
 | 5 | **`usageSessions` 残留数据** | ⚠️ agent-lj 曾误用该字段,遗留 2 条 | 可忽略(App 不读) |
 | 6 | 群聊 NULL thread | 已评估:**不改**(风险大于收益) | 已闭环 |
+| 7 | 🔴 **lj 多用户准入未打通** | **未解决**(`agent-lj` 同事不可用) | **平台侧**:删 s6 注入 |
+
+### 7 的详情
+
+`agent-lj` 的 `/run/s6/container_environment/MATRIX_ALLOWED_USERS` 是**平台注入**(root:root),
+导致 `.env` 的任何修改都压不过它,同事永远被拒。
+
+- **受影响的容器**:10-21 之后创建的(如 `agent-lj`)
+- **不受影响**:10-17 创建的 `agent-node-lj-test`(s6 里没这个文件)
+- **解决**:平台侧删掉该文件 → 重启
+- **详见**:`docs/00-tracking/2026-11-12-遗留问题-多用户准入未打通.md`
 
 ---
 

+ 68 - 0
docs/03-interface/多用户共用容器-完整规范-20261112.md

@@ -219,6 +219,74 @@ MATRIX_ALLOWED_USERS=          ← 空
 
 ---
 
+### 3.7 🔴 s6 注入 vs `.env`:谁说了算(2026-11-12 实测)
+
+**这一步决定「永远全放开」能不能做成。**
+
+#### 现象
+
+有的容器改 `.env` 生效,有的**完全无效**——同样改法,结果不同。
+
+#### 根因:两个容器的配置来源不同
+
+| 容器 | 创建时间 | `containerRef` | s6 里有 `MATRIX_ALLOWED_USERS` 吗 | 改 `.env` 有效吗 |
+|---|---|---|---|---|
+| `agent-node-lj-test` | 2026-10-17 | **空** | ❌ **没有** | ✅ 有效 |
+| `agent-lj` | 2026-10-21 | `agent-lj` | ✅ **有**(root:root,10-21 14:35) | ❌ **无效** |
+
+**推测**:10-21 之后容器创建流程变更,开始往 s6 环境目录注入 `MATRIX_ALLOWED_USERS`。
+
+#### 为什么 `.env` 压不过它
+
+容器的授权判定(`authz_mixin.py`):
+
+```python
+platform_allowlist = _auth_env("MATRIX_ALLOWED_USERS")
+
+if not (platform_allowlist or ...):
+    return _env_truthy("GATEWAY_ALLOW_ALL_USERS")   # ← 兜底
+# 否则 → 精确匹配,不在名单就拒绝
+```
+
+**只要 `MATRIX_ALLOWED_USERS` 有值(哪怕来自 s6 注入),`ALLOW_ALL` 就永远轮不到。**
+
+而且:
+- `.env` 写 `MATRIX_ALLOWED_USERS=`(**空串**)→ 无效(`_clear_known_keys_missing_from_dotenv` 只清「缺失的键」,空串不算)
+- `.env` **整行删除** → s6 注入仍在,重启后恢复
+- 直接删 s6 文件 → **root:root,容器用户无权限**
+
+#### 已尝试且全部失败的方案
+
+| # | 方案 | 结果 |
+|---|---|---|
+| 1 | `.env` 追加用户到 `MATRIX_ALLOWED_USERS` | ❌ 重启后仍被拒 |
+| 2 | `GATEWAY_ALLOW_ALL_USERS=true` | ❌ 被非空白名单短路 |
+| 3 | `.env` 把该键置空 | ❌ 空串不算缺失 |
+| 4 | `.env` 整行删除该键 | ❌ s6 注入仍在 |
+| 5 | 删除/清空 s6 文件 | ❌ 无权限 |
+
+#### 结论与对策
+
+**这是平台侧的容器创建差异,容器内解决不了。**
+
+| 对策 | 说明 |
+|---|---|
+| **A. 平台删除 s6 注入** | 删 `/run/s6/container_environment/MATRIX_ALLOWED_USERS`,不动数据,根治 |
+| B. 重建容器 | 按 lj-test 的方式建,但会话数据会丢 |
+| C. 暂用可用的容器 | — |
+
+**验证方法**:
+```bash
+PID=$(pgrep -f "gateway run" | tail -1)
+tr '\0' '\n' < /proc/$PID/environ | grep -E "MATRIX_ALLOWED|ALLOW_ALL"
+```
+
+**期望**:`MATRIX_ALLOWED_USERS` 不存在 或 `ALLOW_ALL=true` 且白名单为空。
+
+> 详见 `docs/00-tracking/2026-11-12-遗留问题-多用户准入未打通.md`
+
+---
+
 ## 四、容器侧:多房间监听
 
 ### 4.1 事实

+ 1 - 0
docs/03-interface/提示词-容器自我优化-v2-20261111.md

@@ -299,6 +299,7 @@ test -w /opt/data/plugins && echo "plugins 可写" || echo "不可写"
 | 6 | **以为配了 `ALLOW_ALL` 就放开了** | 错。**非空白名单优先于 ALLOW_ALL**。必须把 `MATRIX_ALLOWED_USERS` **清空**,否则全放开等于没开 |
 | 7 | **以为改了 `.env` 就生效** | 错。`os.environ` **启动时读一次**,且某些行可能根本没被加载。必须重启 + **回读 `/proc/<pid>/environ`** |
 | 8 | **以为 reaction 的 sender 是容器** | 错。App 用容器身份登录,**用户点的 emoji 也显示成容器发的**。要看 target 和时机 |
+| 9 | **以为改 `.env` 一定能覆盖** | 错。若 `/run/s6/container_environment/MATRIX_ALLOWED_USERS` 存在(**平台注入,root:root**),`.env` **压不过它**,改多少次都没用 |
 
 ---