Skip to content

Commit 6d4d9e3

Browse files
committed
refactor(bitrix24): rename "Path B" framing to maintainer-specified naming [B24:2794]
Per maintainer hard rule #10 (no generic "Path A/B" framing) from PR #1061 review. The Bitrix24 MCP auto-onboard flow is Bitrix-specific glue ("Bitrix24 OAuth -> existing mcp_user_credentials bridge"), NOT a generic MCP architecture pattern. Naming convention applied consistently: - First mention per file: full "Bitrix24 OAuth -> existing mcp_user_credentials bridge" (matches maintainer comment verbatim). - Subsequent mentions in same file: shortened "mcp_user_credentials bridge". - Test/log context referencing literal endpoint /api/auto-onboard: keep "auto-onboard" reference (it's the actual API endpoint name). Changes are documentation-only: - Rename in code comments + test descriptions + plan docs. - Clarify framing in mcp_client.go + provisioner.go doc comments to emphasize Bitrix-specific glue (not generic MCP infra). - Reuse existing mcp_user_credentials table + MCPServerStore methods (no schema / store / abstraction change). Files: - cmd/gateway.go (factory registration doc) - internal/channels/bitrix24/{channel,factory,mcp_client,provisioner}.go - internal/channels/bitrix24/{mcp_client,provisioner}_test.go - plan/goclaw-mcp-integration.md (21 occurrences) Verified: go build + MCP-related tests pass (TestProvision*, TestInitMCPProvisioner*, TestMCPClient*). Phase 1 of Path C execution per plans/reports/decision-log-260519-1555-bitrix24-pr-fork-decision.md.
1 parent 28bb5c8 commit 6d4d9e3

8 files changed

Lines changed: 59 additions & 44 deletions

File tree

cmd/gateway.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -481,8 +481,10 @@ func runGateway() {
481481
// lazy per-user credential provisioning (via mcp_server_name +
482482
// mcp_base_url in their instance config) can reach the partner's
483483
// MCPServerStore. The MCP server authenticates each onboard call
484-
// via the caller-supplied Bitrix access_token (Path B) — no shared
485-
// admin secret is required. Channels with none of those set operate
484+
// via the caller-supplied Bitrix access_token (the "Bitrix24
485+
// OAuth → existing mcp_user_credentials bridge" — Bitrix-specific
486+
// glue, not a generic MCP architecture pattern) — no shared admin
487+
// secret is required. Channels with none of those set operate
486488
// identically to before — the MCPStore arg is nil-safe inside the
487489
// factory.
488490
instanceLoader.RegisterFactory(channels.TypeBitrix24, bitrix24.FactoryWithPortalStoreAndMCP(pgStores.BitrixPortals, pgStores.MCP, bitrixEncKey))

internal/channels/bitrix24/channel.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,10 @@ type Channel struct {
6161
//
6262
// mcpStore comes from the MCP-aware factory variant; mcpClient is
6363
// built at Start() iff config has mcp_server_name + mcp_base_url and
64-
// the named mcp_servers row exists. Path B: the MCP server
65-
// authenticates each onboard call via the caller-supplied Bitrix
66-
// access_token — no shared admin secret is required. mcpServerID is
64+
// the named mcp_servers row exists. Bitrix24 OAuth → existing
65+
// mcp_user_credentials bridge: the MCP server authenticates each
66+
// onboard call via the caller-supplied Bitrix access_token — no
67+
// shared admin secret is required. mcpServerID is
6768
// resolved once at Start() via mcpStore.GetServerByName and then
6869
// cached — avoids looking up the server on every inbound message.
6970
mcpStore store.MCPServerStore

internal/channels/bitrix24/factory.go

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -94,9 +94,11 @@ type bitrixInstanceConfig struct {
9494
// 2. Channel looks up MCPUserCredentials(serverID, senderID). Present
9595
// → skip. Absent → POST /api/auto-onboard on MCPBaseURL forwarding
9696
// U's OAuth tokens. MCP server authenticates the call via Bitrix
97-
// `profile` against the supplied access_token (Path B — no shared
98-
// admin secret required) and responds with a per-user api_key,
99-
// which channel stores via SetUserCredentials.
97+
// `profile` against the supplied access_token — no shared admin
98+
// secret required — and responds with a per-user api_key, which
99+
// channel stores via SetUserCredentials (the "Bitrix24 OAuth →
100+
// existing mcp_user_credentials bridge" — Bitrix-specific glue,
101+
// not a generic MCP architecture pattern).
100102
// 3. Agent pipeline downstream reads those creds naturally.
101103
//
102104
// Best-effort: if any step fails, channel logs a warning and forwards
@@ -146,8 +148,10 @@ func FactoryWithPortalStore(portalStore store.BitrixPortalStore, encKey string)
146148
// provisioning: on first message from each user, it POSTs to
147149
// {mcp_base_url}/api/auto-onboard to mint per-user MCP credentials,
148150
// which downstream agent pipeline reads naturally. The MCP server
149-
// authenticates each call via the caller-supplied Bitrix access_token
150-
// (Path B) — no shared admin secret is required.
151+
// authenticates each call via the caller-supplied Bitrix access_token —
152+
// no shared admin secret is required (Bitrix24 OAuth → existing
153+
// mcp_user_credentials bridge; Bitrix-specific glue, not a generic
154+
// MCP architecture pattern).
151155
//
152156
// Pass nil mcpStore to disable provisioning even if config has the fields.
153157
// Half-config (only one of mcp_server_name / mcp_base_url set) fails fast.

internal/channels/bitrix24/mcp_client.go

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,23 @@ import (
1414

1515
// mcpClient talks to an MCP server's /api/auto-onboard endpoint.
1616
//
17+
// This is Bitrix-specific glue ("Bitrix24 OAuth → existing
18+
// mcp_user_credentials bridge"), NOT a generic MCP architecture pattern —
19+
// other channels (Telegram, Discord, …) currently require admins to set
20+
// per-user MCP credentials manually via the HTTP admin API. Bitrix
21+
// automates the same flow because Bitrix events naturally carry user
22+
// OAuth tokens.
23+
//
1724
// When a Bitrix24 user sends their first message, the bitrix24 channel
1825
// doesn't yet know which per-user MCP API key that user should use. It POSTs
1926
// to the MCP server — which is the authoritative identity provider for this
2027
// integration — with the triggering user's OAuth tokens (access_token +
2128
// refresh_token + expires_in) harvested from the Bitrix event auth block.
2229
// The MCP server verifies the access_token against Bitrix `profile` to
23-
// confirm the caller actually owns bitrix_user_id (Path B — no shared admin
24-
// secret required), then upserts its own tenants + bitrix_users tables keyed
25-
// by (domain, bitrix_user_id) and returns the per-user api_key we persist
26-
// via mcp_user_credentials.
30+
// confirm the caller actually owns bitrix_user_id — no shared admin secret
31+
// requiredthen upserts its own tenants + bitrix_users tables keyed by
32+
// (domain, bitrix_user_id) and returns the per-user api_key we persist via
33+
// mcp_user_credentials.
2734
//
2835
// The client is deliberately thin:
2936
// - No retries on 4xx (auth config wrong → operator must fix).
@@ -48,7 +55,7 @@ var ErrTenantNotInstalled = errors.New("mcp auto-onboard: tenant_not_installed")
4855

4956
// newMCPClient builds a client pointed at baseURL. The MCP server
5057
// authenticates each auto-onboard call via the caller-supplied Bitrix
51-
// access_token (Path B) — no shared admin secret is required.
58+
// access_token — no shared admin secret is required.
5259
// baseURL MUST be the MCP server root (e.g. https://mcp.example.com) — we
5360
// append /api/auto-onboard internally so channel config stays minimal.
5461
func newMCPClient(baseURL string, timeout time.Duration) *mcpClient {

internal/channels/bitrix24/mcp_client_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,10 @@ func TestMCPClient_AutoOnboard_Success(t *testing.T) {
5151
if gotPath != "/api/auto-onboard" {
5252
t.Fatalf("wrong path: %q", gotPath)
5353
}
54-
// Path B: no Authorization header — MCP server authenticates via the
55-
// caller-supplied Bitrix access_token in the body, not a bearer token.
54+
// Auto-onboard contract: no Authorization header — MCP server authenticates
55+
// via the caller-supplied Bitrix access_token in the body, not a bearer token.
5656
if gotAuth != "" {
57-
t.Fatalf("expected no Authorization header under Path B, got: %q", gotAuth)
57+
t.Fatalf("expected no Authorization header for auto-onboard, got: %q", gotAuth)
5858
}
5959
if gotCT != "application/json" {
6060
t.Fatalf("wrong content-type: %q", gotCT)

internal/channels/bitrix24/provisioner.go

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -72,12 +72,13 @@ var (
7272
// 2. Instance config has both mcp_server_name and mcp_base_url set.
7373
// 3. The mcp_servers row exists (looked up by name).
7474
//
75-
// Path B authentication (see mcp_client.go doc): the MCP server
76-
// authenticates each /api/auto-onboard call via the caller-supplied Bitrix
77-
// access_token by calling Bitrix `profile` and matching the token-owner
78-
// ID against bitrix_user_id — no shared admin secret is required, so
79-
// multi-tenant isolation holds naturally (each portal's users authenticate
80-
// with their own per-portal OAuth tokens).
75+
// Bitrix24 OAuth → existing mcp_user_credentials bridge (Bitrix-specific
76+
// glue — see mcp_client.go doc): the MCP server authenticates each
77+
// /api/auto-onboard call via the caller-supplied Bitrix access_token by
78+
// calling Bitrix `profile` and matching the token-owner ID against
79+
// bitrix_user_id — no shared admin secret is required, so multi-tenant
80+
// isolation holds naturally (each portal's users authenticate with their
81+
// own per-portal OAuth tokens).
8182
//
8283
// Any single missing piece leaves the channel usable but with
8384
// provisioning off — that's the operator's "staged rollout" path: install

internal/channels/bitrix24/provisioner_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -558,7 +558,7 @@ func TestProvisionIfMissing_MissingAuthBlock(t *testing.T) {
558558
// Each case should leave mcpClient nil + mcpServerID zero, so
559559
// provisionIfMissing returns ErrProvisionDisabled.
560560
//
561-
// Path B auth note: there is no longer an admin-token branch to test —
561+
// Auto-onboard auth note: there is no longer an admin-token branch to test —
562562
// the MCP server authenticates each /api/auto-onboard call via the
563563
// caller-supplied Bitrix access_token, not a shared bearer.
564564
func TestInitMCPProvisioner_DisabledModes(t *testing.T) {

plan/goclaw-mcp-integration.md

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22

33
> Kế hoạch tích hợp MCP `mcp-bx-syn` với GoClaw chatbot để enforce per-user ACL khi user chat với bot Bitrix24.
44
>
5-
> **Status**: ✅ Both sides implemented. Path B (access_token as auth anchor) shipped end-to-end. Remaining work is operational (backfill, marketplace rollout, Phase E shared-credential support for Open Channel).
5+
> **Status**: ✅ Both sides implemented. "Bitrix24 OAuth → existing `mcp_user_credentials` bridge" (auto-onboard via access_token as auth anchor — Bitrix-specific glue, not a generic MCP architecture pattern) shipped end-to-end. Remaining work is operational (backfill, marketplace rollout, Phase E shared-credential support for Open Channel).
66
>
77
> **Owner**: dangt
8-
> **Last updated**: 2026-04-23 (rev5: Path B shipped — ADMIN_TOKEN removed, mapping table dropped, notify + rate limit + audit log added)
8+
> **Last updated**: 2026-04-23 (rev5: mcp_user_credentials bridge shipped — ADMIN_TOKEN removed, mapping table dropped, notify + rate limit + audit log added)
99
1010
---
1111

@@ -14,7 +14,7 @@
1414
**Mục tiêu**: Mỗi user trong Bitrix chat với bot GoClaw → MCP `mcp-bx-syn` gọi Bitrix REST với token của **chính user đó** (enforce ACL tự nhiên). Triển khai an toàn ở quy mô marketplace: mỗi portal cài app độc lập, không có shared secret giữa MCP và GoClaw.
1515

1616
**Phạm vi (đã triển khai)**:
17-
- Endpoint `POST /api/auto-onboard` trên MCP (Path B — xác thực bằng Bitrix `access_token` thay vì `ADMIN_TOKEN`)
17+
- Endpoint `POST /api/auto-onboard` trên MCP (mcp_user_credentials bridge — xác thực bằng Bitrix `access_token` thay vì `ADMIN_TOKEN`)
1818
- Lazy provisioning hook trong custom Bitrix24 channel của GoClaw
1919
- Persist per-user OAuth tokens vào MCPUserCredentials để MCP proxy gọi REST API theo user
2020
- Rate limit + audit log trên endpoint
@@ -35,7 +35,7 @@
3535

3636
## 2. Quyết định đã chốt (Rev5)
3737

38-
-**Path B**: MCP xác thực mỗi call `/api/auto-onboard` bằng cách gọi Bitrix `profile` với `access_token` do caller supply, so khớp `profile.ID` với `bitrix_user_id`. Không cần `ADMIN_TOKEN` shared giữa GoClaw và MCP.
38+
-**mcp_user_credentials bridge**: MCP xác thực mỗi call `/api/auto-onboard` bằng cách gọi Bitrix `profile` với `access_token` do caller supply, so khớp `profile.ID` với `bitrix_user_id`. Không cần `ADMIN_TOKEN` shared giữa GoClaw và MCP.
3939
- Đổi so với Rev4 (dùng `ADMIN_TOKEN` Bearer) vì không scale cho marketplace: mỗi portal chạy GoClaw riêng không thể share 1 secret với MCP worker.
4040
-**Reject 404 `tenant_not_installed`** nếu portal chưa cài MCP app.
4141
-**Idempotent theo `(tenant.domain, bitrix_user_id)`** — lần 2 refresh tokens, trả cùng USR_.
@@ -115,23 +115,23 @@ Agent gọi MCP tool → Manager.resolveServerCredentials() inject
115115
| MCP `profile` (không `user.get`) vì không yêu cầu `user` scope || `src/auth/bitrix-user-verify.ts` |
116116
| `ensureFreshToken` re-verify hourly + dismiss khi fail || `src/auth/token-manager.ts` |
117117
| GoClaw KHÔNG còn phụ thuộc ADMIN_TOKEN || commit `07b48ef0` (goclaw-deploy/dev) |
118-
| GoClaw channel đã wire Path B từ commit phase C || commit `ea09c1ba` (goclaw-deploy/dev) |
118+
| GoClaw channel đã wire mcp_user_credentials bridge từ commit phase C || commit `ea09c1ba` (goclaw-deploy/dev) |
119119

120120
---
121121

122122
## 4. Data model
123123

124124
### 4.1 MCP side — schema (không migration mới)
125125

126-
Schema gốc đã đủ. Các bảng Path B dùng:
126+
Schema gốc đã đủ. Các bảng mcp_user_credentials bridge dùng:
127127

128128
| Bảng | Cột liên quan | Dùng cho |
129129
|---|---|---|
130130
| `tenants` | `domain UNIQUE` | `findTenantByDomain` — 404 gate |
131131
| `users` | `tenant_id`, `bitrix_user_id TEXT`, `UNIQUE(tenant_id, bitrix_user_id)`, `access_token`, `refresh_token`, `token_expires_at`, `token_version` | Upsert theo (tenant, bitrix_user_id); lưu OAuth tokens để proxy Bitrix REST |
132-
| `users` (Phase 04 columns, reuse) | `user_status` (`active`/`dismissed`), `last_verified_at` (unix seconds) | Đã có từ Phase 04; Path B reuse cho `ensureFreshToken` re-verify + dismiss flow |
132+
| `users` (Phase 04 columns, reuse) | `user_status` (`active`/`dismissed`), `last_verified_at` (unix seconds) | Đã có từ Phase 04; mcp_user_credentials bridge reuse cho `ensureFreshToken` re-verify + dismiss flow |
133133
| `api_keys` | `user_id`, `key`, `label`, `active` | Mint USR_ label `"goclaw-bot"`; `deactivateUserApiKeys` set `active=0` khi dismiss |
134-
| `auto_onboard_audit` (mới — Path B) | `id`, `domain`, `bitrix_user_id`, `event`, `actor`, `metadata`, `created_at` | Audit trail cho `/api/auto-onboard` — mọi call (success + fail) ghi 1 row. Event taxonomy: `success`/`rate_limited`/`invalid_bitrix_user`/`bitrix_unreachable`/`tenant_not_installed`/`bad_request` |
134+
| `auto_onboard_audit` (mới — mcp_user_credentials bridge) | `id`, `domain`, `bitrix_user_id`, `event`, `actor`, `metadata`, `created_at` | Audit trail cho `/api/auto-onboard` — mọi call (success + fail) ghi 1 row. Event taxonomy: `success`/`rate_limited`/`invalid_bitrix_user`/`bitrix_unreachable`/`tenant_not_installed`/`bad_request` |
135135

136136
### 4.2 GoClaw side — schema (KHÔNG migration mới) ✅
137137

@@ -148,7 +148,7 @@ Schema gốc đã đủ. Các bảng Path B dùng:
148148

149149
## 5. MCP side — `/api/auto-onboard` endpoint ✅ IMPLEMENTED
150150

151-
### 5.1 HTTP contract (rev5 — Path B)
151+
### 5.1 HTTP contract (rev5 — mcp_user_credentials bridge)
152152

153153
**Route**: `POST /api/auto-onboard`
154154

@@ -223,7 +223,7 @@ Content-Type: application/json
223223

224224
### 5.3 Re-verify defence-in-depth (`src/auth/token-manager.ts`)
225225

226-
Path B xác thực 1 lần lúc onboard; nhưng nếu user bị deactive trên Bitrix sau khi onboard, USR_ vẫn sống. Mitigation:
226+
mcp_user_credentials bridge xác thực 1 lần lúc onboard; nhưng nếu user bị deactive trên Bitrix sau khi onboard, USR_ vẫn sống. Mitigation:
227227

228228
- `ensureFreshToken()` chạy trên **mỗi** MCP call (via `resolveApiAuth``OAuthAuthContext`).
229229
- Nếu `last_verified_at > 1h` → gọi `verifyBitrixActive` lại:
@@ -238,11 +238,11 @@ Kết quả: user bị xoá khỏi Bitrix → trong vòng 1h MCP key của họ
238238

239239
| File | Action | Status |
240240
|---|---|---|
241-
| `src/api/auto-onboard.ts` | Rewrite — Path B (verify + rate limit + audit) ||
241+
| `src/api/auto-onboard.ts` | Rewrite — mcp_user_credentials bridge (verify + rate limit + audit) ||
242242
| `src/auth/bitrix-user-verify.ts` | Create — `verifyBitrixActive` via `profile` ||
243243
| `src/auth/token-manager.ts` | Modify — hook re-verify vào `ensureFreshToken` ||
244244
| `src/db/queries.ts` | Modify — thêm `logAutoOnboardEvent`, `updateUserVerifyStatus`, `deactivateUserApiKeys` ||
245-
| `src/db/schema.sql` | Modify — thêm bảng `auto_onboard_audit` (Path B audit). `users.user_status` + `last_verified_at` đã có từ Phase 04 ||
245+
| `src/db/schema.sql` | Modify — thêm bảng `auto_onboard_audit` (mcp_user_credentials bridge audit). `users.user_status` + `last_verified_at` đã có từ Phase 04 ||
246246
| `src/api/api-router.ts` | Modify — route `POST /auto-onboard` (no auth gate) ||
247247
| `wrangler.toml` | Modify — `RATE_LIMIT_KV` binding + drop `ADMIN_TOKEN` dependency ||
248248

@@ -405,7 +405,7 @@ Không đụng health state — channel vẫn Green vì routing vẫn work.
405405
|---|---|---|
406406
| `internal/channels/bitrix24/channel.go` | Modify — add `mcpStore/mcpClient/mcpServerID/mcpProvMu/mcpDebounce/notifyMu/notifyDebounce/nameCacheMu/nameCache` fields | `ea09c1ba` (phase C) |
407407
| `internal/channels/bitrix24/factory.go` | Modify — `FactoryWithPortalStoreAndMCP` variant + half-config validation; `bitrixCreds` empty struct | `ea09c1ba`, `07b48ef0` |
408-
| `internal/channels/bitrix24/mcp_client.go` | Create — thin HTTP client; Path B no-auth | `ea09c1ba`, `07b48ef0` |
408+
| `internal/channels/bitrix24/mcp_client.go` | Create — thin HTTP client; mcp_user_credentials bridge no-auth | `ea09c1ba`, `07b48ef0` |
409409
| `internal/channels/bitrix24/provisioner.go` | Create — `provisionIfMissing` + `notifyUserOfMCPIssueOnce` + sentinel errors | `ea09c1ba`, `07b48ef0` |
410410
| `internal/channels/bitrix24/contact_enrich.go` | Create — lazy `user.get` cache cho display_name | `ea09c1ba` |
411411
| `internal/channels/bitrix24/handle.go` | Modify — call `provisionIfMissing` trước `HandleMessage` | `ea09c1ba` |
@@ -452,7 +452,7 @@ Không đụng health state — channel vẫn Green vì routing vẫn work.
452452
| Secret | Dùng cho | Rev5 status |
453453
|---|---|---|
454454
| `BITRIX_CLIENT_ID` / `BITRIX_CLIENT_SECRET` | OAuth dance (install + refresh) | Giữ nguyên |
455-
| ~~`ADMIN_TOKEN`~~ | ~~Auth `/api/auto-onboard`~~ | **Bỏ** (Path B không cần) |
455+
| ~~`ADMIN_TOKEN`~~ | ~~Auth `/api/auto-onboard`~~ | **Bỏ** (mcp_user_credentials bridge không cần) |
456456
| `ENCRYPTION_KEY` | D1 field encryption | Giữ nguyên |
457457
| KV binding `RATE_LIMIT_KV` | Rate limit `/api/auto-onboard` | **Mới** |
458458

@@ -470,7 +470,7 @@ Không cần env var riêng cho MCP integration. Tất cả config sống trong
470470

471471
## 8. Test plan
472472

473-
### 8.1 Unit test MCP side (Path B)
473+
### 8.1 Unit test MCP side (mcp_user_credentials bridge)
474474

475475
1. Body invalid JSON → 400 `bad_request` + audit row `reason:"invalid_json"`
476476
2. Thiếu `domain` / `bitrix_user_id` / `access_token` / `refresh_token` → 400 + audit `missing:"<field>"`
@@ -531,10 +531,10 @@ Không cần env var riêng cho MCP integration. Tất cả config sống trong
531531

532532
## 9. Rollout sequence
533533

534-
### ✅ Phase A — MCP Path B shipped
534+
### ✅ Phase A — MCP mcp_user_credentials bridge shipped
535535
- [x] Schema: thêm bảng `auto_onboard_audit` (Phase 04 đã có sẵn `user_status` + `last_verified_at` — reuse, không migrate lại)
536536
- [x] `verifyBitrixActive` via `profile` (thay cơ chế `user.get?FILTER[ID]=…&ACTIVE=true` cũ)
537-
- [x] `/api/auto-onboard` rewrite Path B (bỏ Bearer ADMIN_TOKEN gate)
537+
- [x] `/api/auto-onboard` rewrite mcp_user_credentials bridge (bỏ Bearer ADMIN_TOKEN gate)
538538
- [x] Rate limit KV + audit log
539539
- [x] Hook `verifyBitrixActive` vào `ensureFreshToken` (re-verify hourly — cơ chế hourly đã có Phase 04, chỉ đổi backend verify)
540540
- [x] Deploy + smoke test (end-to-end user#62)
@@ -567,7 +567,7 @@ Không cần env var riêng cho MCP integration. Tất cả config sống trong
567567

568568
## 10. Security considerations
569569

570-
### 10.1 Path B auth anchor
570+
### 10.1 mcp_user_credentials bridge auth anchor
571571

572572
- **Trust boundary**: MCP tin `access_token` là thật vì Bitrix `profile` xác nhận nó thuộc user nào. Attacker muốn mint USR_ cho user X phải có access_token hợp lệ của user X — mà access_token chỉ leak được nếu Bitrix portal đã bị compromise (trong trường hợp đó attacker đã có quyền cao hơn nhiều so với USR_).
573573
- Không còn "master key" → không có rotate periodic; cũng không có single point of credential leak.
@@ -616,7 +616,7 @@ Không cần env var riêng cho MCP integration. Tất cả config sống trong
616616

617617
## 12. Changelog
618618

619-
- **2026-04-23 (rev5)**: Path B shipped end-to-end. Bỏ ADMIN_TOKEN.
619+
- **2026-04-23 (rev5)**: mcp_user_credentials bridge shipped end-to-end. Bỏ ADMIN_TOKEN.
620620
- MCP side: `/api/auto-onboard` rewrite dùng `verifyBitrixActive(profile)` làm auth anchor thay vì Bearer ADMIN_TOKEN. Thêm rate limit KV (600/min IP + 120/min domain), audit log `auto_onboard_audit`. Hourly re-verify trong `ensureFreshToken` để revoke USR_ của user bị dismiss khỏi Bitrix.
621621
- GoClaw side: `mcpClient` bỏ `adminToken` field + Authorization header. `provisioner.go` bỏ `resolveMCPAdminToken` + 2 env consts (`GOCLAW_BITRIX_MCP_ADMIN_TOKEN`, `BITRIX_MCP_ADMIN_TOKEN`). `bitrixCreds` chuyển về empty struct. UI form drop `mcp_admin_token` field. (commit `07b48ef0`)
622622
- Bỏ bảng mapping `bitrix_mcp_user_mapping` khỏi plan — reuse partner's `mcp_user_credentials` store. Tiết kiệm ~300 LOC: interface + 2 store impls + migration + SchemaVersion bump.

0 commit comments

Comments
 (0)