Skip to content

Commit 7b30ef9

Browse files
committed
feat(phase-14): implement TA-P14-004 direct session ACL
1 parent 0a14239 commit 7b30ef9

16 files changed

+994
-12
lines changed

docs/implementation/phase-14/README.md

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# TelAgent v1 Phase 14 执行产出(产品聚焦与缺陷收敛)
22

3-
- 文档版本:v1.1
3+
- 文档版本:v1.2
44
- 状态:Phase 14 执行中
55
- 最后更新:2026-03-03
66

@@ -18,7 +18,7 @@ Phase 14 回归 P2P 应用核心体验,聚焦“可用性、正确性、收敛
1818
| TA-P14-001 | DONE | 阶段边界重置(产品聚焦) |
1919
| TA-P14-002 | DONE | 删除 Web 运维面板,保留核心聊天流程 |
2020
| TA-P14-003 | DONE | 消息拉取稳定游标改造(替代 offset 风险) |
21-
| TA-P14-004 | TODO | direct 会话参与方与访问约束强化 |
21+
| TA-P14-004 | DONE | direct 会话参与方与访问约束强化 |
2222
| TA-P14-005 | TODO | TS/Python SDK 核心行为收敛与错误语义统一 |
2323
| TA-P14-006 | TODO | 回归验证与 Gate 收口 |
2424

@@ -27,10 +27,15 @@ Phase 14 回归 P2P 应用核心体验,聚焦“可用性、正确性、收敛
2727
- `ta-p14-001-phase14-product-focus-boundary-2026-03-03.md`
2828
- `ta-p14-002-web-ops-panel-removal-2026-03-03.md`
2929
- `ta-p14-003-stable-pull-cursor-2026-03-03.md`
30+
- `ta-p14-004-direct-session-acl-2026-03-03.md`
3031
- `logs/2026-03-03-p14-web-build.txt`
3132
- `logs/2026-03-03-p14-web-ops-removal-check.txt`
3233
- `logs/2026-03-03-p14-node-build.txt`
3334
- `logs/2026-03-03-p14-node-test.txt`
3435
- `logs/2026-03-03-p14-stable-pull-cursor-check-run.txt`
36+
- `logs/2026-03-03-p14-node-build-ta-p14-004.txt`
37+
- `logs/2026-03-03-p14-node-test-ta-p14-004.txt`
38+
- `logs/2026-03-03-p14-direct-session-acl-check-run.txt`
3539
- `manifests/2026-03-03-p14-web-ops-removal-check.json`
3640
- `manifests/2026-03-03-p14-stable-pull-cursor-check.json`
41+
- `manifests/2026-03-03-p14-direct-session-acl-check.json`
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
[TA-P14-004] firstTwoParticipantsAccepted=true
2+
[TA-P14-004] nonParticipantRejectedRfc7807=true
3+
[TA-P14-004] existingParticipantAcceptedAfterRejection=true
4+
[TA-P14-004] rejectedErrorCode=FORBIDDEN
5+
[TA-P14-004] decision=PASS
6+
[TA-P14-004] output=/Users/xiasenhai/Workspace/OpenClaw/telagent/docs/implementation/phase-14/manifests/2026-03-03-p14-direct-session-acl-check.json
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
2+
> @telagent/node@0.1.0 build /Users/xiasenhai/Workspace/OpenClaw/telagent/packages/node
3+
> tsc -p tsconfig.json
4+
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
2+
> @telagent/node@0.1.0 pretest /Users/xiasenhai/Workspace/OpenClaw/telagent/packages/node
3+
> pnpm build
4+
5+
6+
> @telagent/node@0.1.0 build /Users/xiasenhai/Workspace/OpenClaw/telagent/packages/node
7+
> tsc -p tsconfig.json
8+
9+
10+
> @telagent/node@0.1.0 test /Users/xiasenhai/Workspace/OpenClaw/telagent/packages/node
11+
> node --test dist/*.test.js dist/**/*.test.js
12+
13+
✔ created response returns data envelope and Location header (242.813184ms)
14+
✔ list response returns paginated envelope shape (39.9615ms)
15+
✔ validation errors use RFC7807 shape and problem+json content type (15.434415ms)
16+
✔ node audit snapshot exports de-sensitized envelope and links.self (105.857061ms)
17+
✔ node audit snapshot rejects invalid query with RFC7807 response (4.608889ms)
18+
✔ TA-P12-003 revoked DID event isolates session and rejects message send with RFC7807 (11.766103ms)
19+
✔ TA-P12-004 node metrics exposes federation DLQ replay burn-rate section (3.618223ms)
20+
✔ not found uses RFC7807 shape (2.940089ms)
21+
✔ identities and groups endpoints are accessible with expected status codes (99.16139ms)
22+
✔ messages, attachments and federation endpoints are accessible (86.211749ms)
23+
✔ routes only serve /api/v1/* prefix (318.562169ms)
24+
✔ identity endpoint responds with data envelope (59.790735ms)
25+
✔ mailbox store defaults to sqlite backend (5.842809ms)
26+
✔ mailbox store parses postgres backend config (1.653589ms)
27+
✔ postgres backend requires connection url (0.831064ms)
28+
✔ mailbox backend rejects unsupported value (0.340939ms)
29+
✔ federation protocol defaults to v1 and supports self version (1.003673ms)
30+
✔ federation supported protocols auto-include self version (0.419913ms)
31+
✔ federation replay protection defaults are applied (0.518466ms)
32+
✔ federation replay protection accepts custom values (0.367184ms)
33+
✔ federation replay protection requires positive integer values (0.859582ms)
34+
✔ domain proof config defaults to enforced mode (1.623461ms)
35+
✔ domain proof config accepts report-only mode and custom values (0.414138ms)
36+
✔ domain proof mode rejects unsupported value (0.343733ms)
37+
✔ domain proof numeric settings require positive integers (0.471725ms)
38+
✔ federation pinning defaults to disabled mode (0.350699ms)
39+
✔ federation pinning parses current/next keys and cutover timestamp (0.500471ms)
40+
✔ federation pinning rejects invalid mode (0.458381ms)
41+
✔ federation pinning enabled requires key mappings (0.294758ms)
42+
✔ federation pinning map requires domain=keys format (0.271174ms)
43+
✔ federation SLO automation config defaults are applied (0.295374ms)
44+
✔ federation SLO automation config accepts custom values (0.297757ms)
45+
✔ federation SLO burn-rate thresholds require positive values (0.293347ms)
46+
✔ finalityDepth only materializes finalized blocks (104.666562ms)
47+
✔ reorg rollback replays canonical events and restores deterministic view (133.846173ms)
48+
✔ TA-P4-009 E2E main path: create -> invite -> accept -> group chat (text/image/file) (425.232084ms)
49+
✔ TA-P4-010 E2E offline 24h pull keeps dedupe and per-conversation order (79.988948ms)
50+
✔ TA-P14-003 E2E pull cursor stays stable when cleanup happens between pages (16.156278ms)
51+
✔ TA-P14-004 E2E direct conversation blocks non-participant sender with RFC7807 (7.586321ms)
52+
✔ TA-P4-006 init-upload sanitizes filename and emits attachment objectKey (2.228593ms)
53+
✔ TA-P4-006 complete-upload enforces manifest and checksum integrity (0.767476ms)
54+
✔ TA-P4-006 complete-upload is idempotent and rejects checksum divergence (0.265414ms)
55+
✔ TA-P4-006 expired upload sessions are cleaned and cannot be completed (0.234747ms)
56+
✔ TA-P11-003 accepts valid domain proof challenge and canonical hash (144.154963ms)
57+
✔ TA-P11-003 rejects illegal domain challenge on malformed domain (1.091204ms)
58+
✔ TA-P11-003 rejects when canonical domainProofHash mismatches payload (2.194631ms)
59+
✔ TA-P11-003 rotates challenge nonce near expiry and accepts renewed domain proof (2.960786ms)
60+
✔ TA-P11-003 report-only mode returns warning without blocking create flow (1.025951ms)
61+
✔ TA-P4-007 federation envelopes support idempotent retries (2.08516ms)
62+
✔ TA-P4-007 federation auth token is enforced when configured (0.59134ms)
63+
✔ TA-P4-007 federation rate limit rejects burst traffic (0.317469ms)
64+
✔ TA-P4-008 group-state sync enforces domain consistency (0.852936ms)
65+
✔ TA-P8-002 group-state sync rejects stale stateVersion and records resilience counters (0.762754ms)
66+
✔ TA-P8-002 group-state sync detects split-brain on same stateVersion with different state (0.31755ms)
67+
✔ TA-P9-002 federation accepts compatible protocol versions and tracks usage stats (90.309735ms)
68+
✔ TA-P9-002 federation rejects unsupported protocol versions (0.525636ms)
69+
✔ TA-P11-004 federation pinning enforces sourceKeyId with current/next rotation (1.576277ms)
70+
✔ TA-P11-004 federation pinning report-only mode allows traffic but records warnings (0.381931ms)
71+
✔ TA-P11-005 federation DLQ captures failures and replays in sequence order (3.196861ms)
72+
✔ TA-P4-008 node-info publishes domain and federation security policy (0.310182ms)
73+
✔ TA-P13-005 federation replay applies backoff and opens circuit on repeated failures (2.019657ms)
74+
✔ TA-P13-005 federation replay protection validates backoff range (0.213324ms)
75+
✔ TA-P12-004 federation SLO runOnce auto-replays DLQ and records burn-rate metrics (7.803725ms)
76+
✔ TA-P12-004 federation SLO scheduler periodically replays DLQ (1102.311298ms)
77+
✔ assertSufficient throws INSUFFICIENT_GAS_TOKEN_BALANCE when native balance is not enough (2.029296ms)
78+
✔ TA-P11-006 rotate key keeps old key usable in grace window then expires (3.517979ms)
79+
✔ TA-P11-006 revoke and recover lifecycle is verifiable (0.491ms)
80+
✔ TA-P11-006 rejects invalid did and malformed key id (0.423718ms)
81+
✔ TA-P12-007 orchestrator supports staged key rotation with rollback recovery (2.753973ms)
82+
✔ TA-P4-002 sequence allocator keeps per-conversation monotonic order (4.888052ms)
83+
✔ TA-P4-003 dedupe keeps idempotent writes for same envelopeId (0.767725ms)
84+
✔ TA-P4-003 duplicate envelopeId with different payload is rejected (1.039166ms)
85+
✔ TA-P14-004 direct conversation rejects non-participant writer after two participants are established (1.052266ms)
86+
✔ TA-P14-004 direct conversation ACL remains effective after repository-backed restart (20.612998ms)
87+
✔ TA-P4-004 cleanupExpired removes expired envelopes and releases dedupe key (1.444885ms)
88+
✔ TA-P14-003 conversation pull cursor stays stable after cleanup between pages (1.848464ms)
89+
✔ TA-P14-003 global pull cursor is keyset token and survives cleanup drift (1.009106ms)
90+
✔ TA-P4-005 provisional envelopes are retracted when group is reorged back (1.177371ms)
91+
✔ TA-P4-005 send is rejected when group chain state is REORGED_BACK (0.535927ms)
92+
✔ TA-P12-002 buildAuditSnapshot exports hashed retraction samples (1.104457ms)
93+
✔ TA-P12-002 buildAuditSnapshot normalizes sample and scan bounds (0.24018ms)
94+
✔ TA-P12-003 revoked DID event isolates related sessions and evicts active sessions (1.988008ms)
95+
✔ TA-P12-003 buildAuditSnapshot includes revocation isolation evidence (1.072063ms)
96+
✔ TA-P6-001 mailbox persists messages and seq after service restart (22.308847ms)
97+
✔ TA-P11-006 message send validates signal/mls key lifecycle status (1.720719ms)
98+
✔ TA-P11-007 revoked DID cannot continue sending new messages (0.491ms)
99+
✔ TA-P5-002 monitoring snapshot normalizes dynamic route segments and records counters (16.900544ms)
100+
✔ TA-P5-002 monitoring emits warning/critical alerts when thresholds are exceeded (0.515895ms)
101+
✔ TA-P12-004 federation DLQ burn-rate alert is emitted and tracked (2.698996ms)
102+
ℹ tests 89
103+
ℹ suites 0
104+
ℹ pass 89
105+
ℹ fail 0
106+
ℹ cancelled 0
107+
ℹ skipped 0
108+
ℹ todo 0
109+
ℹ duration_ms 2590.368983
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
{
2+
"phase": "Phase 14",
3+
"taskId": "TA-P14-004",
4+
"generatedAt": "2026-03-03T14:59:12.417Z",
5+
"summary": {
6+
"firstTwoParticipantsAccepted": true,
7+
"nonParticipantRejectedRfc7807": true,
8+
"existingParticipantAcceptedAfterRejection": true,
9+
"rejectedErrorCode": "FORBIDDEN"
10+
},
11+
"decision": "PASS",
12+
"details": {
13+
"api": {
14+
"rejectedStatus": 403,
15+
"rejectedContentType": "application/problem+json; charset=utf-8",
16+
"rejectedErrorCode": "FORBIDDEN",
17+
"rejectedBody": {
18+
"type": "https://telagent.dev/errors/forbidden",
19+
"title": "Forbidden",
20+
"status": 403,
21+
"detail": "senderDid is not a direct conversation participant for conversation(direct:p14-acl-script)",
22+
"instance": "/api/v1/messages",
23+
"code": "FORBIDDEN"
24+
}
25+
}
26+
}
27+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# TA-P14-004 direct 会话参与方访问控制强化(2026-03-03)
2+
3+
- Task ID:TA-P14-004
4+
- 阶段:Phase 14
5+
- 状态:DONE
6+
- 负责人角色:Backend + Security + QA
7+
8+
## 1. 目标
9+
10+
`conversationType=direct` 增加参与方访问约束,确保 direct 会话仅允许已建立参与关系的 DID 写入;非参与方写入必须被拒绝并返回 RFC7807 标准错误。
11+
12+
## 2. 实现摘要
13+
14+
1. `MessageService.send` 在 direct 会话路径增加 ACL 校验:
15+
- 第一个发送方自动登记为参与方 A;
16+
- 第二个不同发送方登记为参与方 B;
17+
- 第三个不同发送方被拒绝(`FORBIDDEN`)。
18+
2. ACL 持久化落地:
19+
- SQLite/Postgres 新增 `mailbox_direct_conversations` 表;
20+
- 约束 `conversation_id` 下最多两名参与方;
21+
- 重启后约束仍生效(防止重启绕过)。
22+
3. 非参与方拒绝语义:
23+
- 返回 `TelagentError(ErrorCodes.FORBIDDEN, ...)`
24+
- API 层统一转成 `application/problem+json`(RFC7807)。
25+
26+
## 3. 变更文件
27+
28+
- `packages/node/src/services/message-service.ts`
29+
- `packages/node/src/storage/mailbox-store.ts`
30+
- `packages/node/src/storage/message-repository.ts`
31+
- `packages/node/src/storage/postgres-message-repository.ts`
32+
- `packages/node/src/services/message-service.test.ts`
33+
- `packages/node/src/phase4-e2e.test.ts`
34+
- `packages/node/scripts/run-phase14-direct-session-acl-check.ts`
35+
36+
## 4. 验证
37+
38+
1. 服务层新增测试:
39+
- `TA-P14-004 direct conversation rejects non-participant writer after two participants are established`
40+
- `TA-P14-004 direct conversation ACL remains effective after repository-backed restart`
41+
2. E2E 新增测试:
42+
- `TA-P14-004 E2E direct conversation blocks non-participant sender with RFC7807`
43+
3. 专项脚本:
44+
- `packages/node/scripts/run-phase14-direct-session-acl-check.ts`
45+
4. 构建与测试:
46+
- `corepack pnpm --filter @telagent/node build`
47+
- `corepack pnpm --filter @telagent/node test`
48+
49+
## 5. 证据
50+
51+
- 构建日志:`docs/implementation/phase-14/logs/2026-03-03-p14-node-build-ta-p14-004.txt`
52+
- 测试日志:`docs/implementation/phase-14/logs/2026-03-03-p14-node-test-ta-p14-004.txt`
53+
- 专项检查日志:`docs/implementation/phase-14/logs/2026-03-03-p14-direct-session-acl-check-run.txt`
54+
- 机读清单:`docs/implementation/phase-14/manifests/2026-03-03-p14-direct-session-acl-check.json`

docs/implementation/telagent-v1-iteration-board.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -224,8 +224,9 @@
224224
- 已完成:`TA-P14-001`(Phase 14 产品聚焦边界冻结)
225225
- 已完成:`TA-P14-002`(默认 Web 运维面板下线,回归核心聊天流程)
226226
- 已完成:`TA-P14-003`(消息拉取稳定游标改造,修复 cleanup/retraction 导致分页跳项风险)
227+
- 已完成:`TA-P14-004`(direct 会话参与方访问控制,非参与方写入返回 RFC7807)
227228
- 已规划:`TA-P15-001`(WebApp 工业级规划总纲冻结)
228-
- 下一批 Ready:执行 `TA-P14-004`(direct 会话访问控制)与 `TA-P14-005`(SDK 行为收敛)。
229+
- 下一批 Ready:执行 `TA-P14-005`(SDK 行为收敛)与 `TA-P14-006`(Phase 14 Gate 收口)。
229230

230231
## 4.2 Blockers(2026-03-03 更新)
231232

@@ -414,7 +415,7 @@
414415
- `TA-P14-001`:DONE(产品聚焦边界冻结,见 `docs/implementation/phase-14/ta-p14-001-phase14-product-focus-boundary-2026-03-03.md`)。
415416
- `TA-P14-002`:DONE(默认 Web 运维面板下线,见 `docs/implementation/phase-14/ta-p14-002-web-ops-panel-removal-2026-03-03.md`)。
416417
- `TA-P14-003`:DONE(消息拉取稳定游标改造,见 `docs/implementation/phase-14/ta-p14-003-stable-pull-cursor-2026-03-03.md`)。
417-
- `TA-P14-004`TODO(direct 会话参与方访问控制)。
418+
- `TA-P14-004`DONE(direct 会话参与方访问控制,见 `docs/implementation/phase-14/ta-p14-004-direct-session-acl-2026-03-03.md`)。
418419
- `TA-P14-005`:TODO(TS/Python SDK 行为收敛)。
419420
- `TA-P14-006`:TODO(Phase 14 Gate 收口)。
420421
- 阶段状态:Phase 14 执行中(产品核心能力与高优缺陷收敛)。

docs/implementation/telagent-v1-task-breakdown.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ flowchart LR
148148
| TA-P14-001 | Phase 14 | 冻结产品聚焦边界(回归核心 P2P 应用) | TL + BE + FE + QA | 0.5 | TA-P13-007 | boundary decision doc | Phase 14 范围与 Phase 15 分工冻结 | DONE |
149149
| TA-P14-002 | Phase 14 | 删除默认 Web 运维面板,保留核心聊天流程 | Frontend | 1 | TA-P14-001 | web app cleanup + build log | 默认界面仅保留核心链路入口,构建通过 | DONE |
150150
| TA-P14-003 | Phase 14 | 消息拉取稳定游标改造(替代 offset 风险) | Backend + QA | 1.5 | TA-P14-001 | pull cursor upgrade + tests | 清理/撤回场景下分页稳定无重复/跳项 | DONE |
151-
| TA-P14-004 | Phase 14 | direct 会话访问控制强化(参与方约束) | Backend + Security | 1.5 | TA-P14-001 | direct ACL guard + tests | 非参与方消息写入被拒绝并返回 RFC7807 | TODO |
151+
| TA-P14-004 | Phase 14 | direct 会话访问控制强化(参与方约束) | Backend + Security | 1.5 | TA-P14-001 | direct ACL guard + tests | 非参与方消息写入被拒绝并返回 RFC7807 | DONE |
152152
| TA-P14-005 | Phase 14 | TS/Python SDK 核心行为收敛 | DX + Backend + QA | 1 | TA-P14-003, TA-P14-004 | sdk parity extension + checks | 参数、错误语义、返回结构一致 | TODO |
153153
| TA-P14-006 | Phase 14 | Phase 14 Gate 评审与收口 | TL + QA | 0.5 | TA-P14-002, TA-P14-003, TA-P14-004, TA-P14-005 | gate 结论文档 | Phase 14 正式关闭 | TODO |
154154
| TA-P15-001 | Phase 15 | Web App 工业级规划总纲冻结 | TL + FE + BE + QA + DX | 1 | TA-P14-001 | industrial planning doc | 功能/架构/平台/质量主线冻结 | DONE |
@@ -357,8 +357,8 @@ flowchart LR
357357
| TA-P14-001 | DONE | `docs/implementation/phase-14/ta-p14-001-phase14-product-focus-boundary-2026-03-03.md`, `docs/implementation/phase-14/README.md` || 进入 `TA-P14-002`(删除默认 Web 运维面板) |
358358
| TA-P14-002 | DONE | `docs/implementation/phase-14/ta-p14-002-web-ops-panel-removal-2026-03-03.md`, `packages/web/src/index.html`, `packages/web/src/main.js` || 进入 `TA-P14-003`(消息拉取稳定游标改造) |
359359
| TA-P14-003 | DONE | `docs/implementation/phase-14/ta-p14-003-stable-pull-cursor-2026-03-03.md`, `packages/node/src/services/message-service.ts`, `packages/node/src/storage/message-repository.ts`, `packages/node/src/storage/postgres-message-repository.ts`, `packages/node/src/services/message-service.test.ts`, `packages/node/src/phase4-e2e.test.ts`, `packages/node/scripts/run-phase14-stable-pull-cursor-check.ts`, `docs/implementation/phase-14/logs/2026-03-03-p14-node-build.txt`, `docs/implementation/phase-14/logs/2026-03-03-p14-node-test.txt`, `docs/implementation/phase-14/logs/2026-03-03-p14-stable-pull-cursor-check-run.txt`, `docs/implementation/phase-14/manifests/2026-03-03-p14-stable-pull-cursor-check.json` || 进入 `TA-P14-004`(direct 会话参与方访问控制) |
360-
| TA-P14-004 | TODO | `docs/implementation/phase-14/README.md` || 实施 direct 会话参与方访问控制并补齐测试 |
361-
| TA-P14-005 | TODO | `docs/implementation/phase-14/README.md` || TS/Python SDK 行为与错误语义收敛 |
360+
| TA-P14-004 | DONE | `docs/implementation/phase-14/ta-p14-004-direct-session-acl-2026-03-03.md`, `packages/node/src/services/message-service.ts`, `packages/node/src/storage/message-repository.ts`, `packages/node/src/storage/postgres-message-repository.ts`, `packages/node/src/services/message-service.test.ts`, `packages/node/src/phase4-e2e.test.ts`, `packages/node/scripts/run-phase14-direct-session-acl-check.ts`, `docs/implementation/phase-14/logs/2026-03-03-p14-node-build-ta-p14-004.txt`, `docs/implementation/phase-14/logs/2026-03-03-p14-node-test-ta-p14-004.txt`, `docs/implementation/phase-14/logs/2026-03-03-p14-direct-session-acl-check-run.txt`, `docs/implementation/phase-14/manifests/2026-03-03-p14-direct-session-acl-check.json` || 进入 `TA-P14-005`(TS/Python SDK 行为收敛) |
361+
| TA-P14-005 | TODO | `docs/implementation/phase-14/README.md` || TS/Python SDK 行为与错误语义收敛并补齐专项校验 |
362362
| TA-P14-006 | TODO | `docs/implementation/phase-14/README.md` || 阶段回归与 Gate 收口 |
363363

364364
## 21. Phase 15 Web App 工业级设计与多平台建设(2026-03-03)

0 commit comments

Comments
 (0)