KB-3000

S177 Cowork Gateway Protection — README (post-2500x SEAL, 2026-05-24)

11 min read Revision 1
s177coworklarkgatewayprotectionreadme2500x5000xdieu-30dieu-31runbook2026-05-24

Lark MCP Launchers — Protection Package

Covers the SINGLE remaining Lark MCP launcher used by Claude Desktop:

  1. lark-crud-gateway — S177 Cowork Gateway via mcp-remote (22 tools as of 5000x).

The official @larksuiteoapi/lark-mcp was RETIRED in S177-5000x — its wrapper is archived under ./archive/ for forensic reference and is never re-installed by restore.sh.

Total expected after Claude Desktop restart: 22 tools (S177 Gateway only).

Active missions:

  • S177-COWORK-GATEWAY-CONSTITUTION-PROTECTION-3500X (2026-05-23) — initial protection package for the lark-crud-gateway connection.
  • S177-OFFICIAL-LARK-MCP-CONSTITUTION-HARDENING-3000X (2026-05-23) — removed raw LARK_APP_ID / LARK_APP_SECRET from claude_desktop_config.json and routed the official launcher through a GSM-backed wrapper.
  • S177-SECRET-ROTATION-AND-BYPASS-CONTAINMENT-4000X (2026-05-23) — rotated S177_LARK_MCP_REMOTE_TOKEN v1→v2 and DISABLED the official lark-mcp entry in claude_desktop_config.json (moved under _disabled_mcpServers).
  • S177-COWORK-BYPASS-CLEANUP-AND-FINAL-VERIFY-4500X (2026-05-24) — removed the remaining Claude Code CLI bypass in ~/.claude.json. Checker grew to 17 checks; required 5 record-CRUD tool names asserted.
  • S177-ELIMINATE-OFFICIAL-LARK-MCP-BYPASS-5000X (2026-05-24) — added the 7 replacement tools to S177 Gateway (lark_records_search, lark_records_batch_create, lark_records_batch_update, lark_fields_list, lark_tables_list, lark_tables_create, lark_app_create) so the official bypass is no longer needed. RETIRED the official lark-mcp from claude_desktop_config.json AND ~/.claude.json (moved under _retired_mcpServers with _retired_at + _reason); removed ~/bin/s177-official-lark-mcp (archived). Checker grew to 22 checks enforcing the Điều 30/31 protection gate (regression + system integrity). Tool count: 15 → 22.
  • S177-COWORK-FINAL-READY-SEAL-AND-RUNBOOK-2500X (2026-05-24) — sealed the current working state. Verification-only macro: no code/config mutation, no Lark write, no VPS mutation. Cowork independently reported COWORK_READY_WITH_S177_GATEWAY (22 tools visible, official lark-mcp invisible, lark_healthcheck PASS, lark_records_get recvkdFceNdpcz PASS, production write blocked at adapter boundary). Checker re-run from Mac: PASS=26 FAIL=0 NOTE=0 across 22 checks. VPS re-verified: lark-mcp-remote.service active, nginx -t OK, public healthz=200. Accepted residual risks remain: LARK_APP_SECRET_ROTATION_PENDING, production live write not enabled, schema/app/table live ops governed/dry-run.

Constitution

  • One Lark bot: For Gem
  • One Lark credential source: GSM (LARK_APP_ID, LARK_APP_SECRET)
  • One S177 bearer source: GSM (S177_LARK_MCP_REMOTE_TOKEN)
  • Base URL: https://open.larksuite.com only — never open.feishu.cn
  • No hardcoded Lark creds, no hardcoded bearer token in Claude Desktop config
  • No secret printed to terminal, chat, or report
  • S177 Gateway is the SINGLE controlled write path (post-5000x)

Files

  • claude_desktop_config.good-5000x-<ts>.json — current known-good Claude Desktop config. Only lark-crud-gateway is active. The old lark-mcp entry lives in _retired_mcpServers for audit only.
  • claude_desktop_config.good-<ts>.json (pre-5000x) — historical snapshots kept for forensics. restore.sh ignores them — they would re-introduce the retired official lark-mcp bypass.
  • s177-lark-crud-gateway-mcp.good-5000x-<ts>.sh — current known-good S177 wrapper (unchanged from pre-5000x; restore.sh picks the newest 5000x snapshot).
  • archive/s177-official-lark-mcp.retired-5000x-<date> — forensic archive of the retired official wrapper. NOT restored by restore.sh.
  • s177-cowork-gateway-check.sh — read-only 22-check Điều 30/31 gate (regression protection + system integrity). Tool-count assertion is 22; asserts no active or _disabled lark-mcp anywhere; live MCP probe for tools/list + production write rejection + Base đệm records_search.
  • s177-cowork-gateway-restore.sh — restores S177 wrapper + config only from the newest 5000x good snapshots; explicitly NEVER restores the official lark-mcp bypass. Refuses to fall back to pre-5000x snapshots.
  • s177-cowork-gateway-manifest.json — file inventory with SHA-256s, retired components, open follow-ups.
  • restore-backups/ — auto-created by the restore script; pre-restore copies of the live config and S177 wrapper.

How the connection works (post-5000x)

Claude Desktop
  └─ launches: /Users/nmhuyen/bin/s177-lark-crud-gateway-mcp
       └─ reads GSM: github-chatgpt-ggcloud / S177_LARK_MCP_REMOTE_TOKEN
       └─ exec: npx -y mcp-remote@latest \
                  https://vps.incomexsaigoncorp.vn/mcp/s177/ocER6C1zErepgpAe/mcp \
                  --transport http-only \
                  --header "Authorization:Bearer <token>"

VPS (vmi3080463)
  └─ lark-mcp-remote.service
       └─ python -m lark_client.mcp_adapter.remote_server
            └─ exposes 22 tools (the surface that replaced both the old
               S177 set AND the retired official lark-mcp set)
            └─ writes route: LarkMcpAdapter → LarkWriteService → SafetyLayer
                            → BaseDemOnlyApiCaller → LarkCore (whitelist + audit)

The S177 bearer lives only in GSM at rest; it is interpolated into the child mcp-remote argv at launch. The wrapper does not echo it.

Residual risk (post-5000x)

RESIDUAL_RISK_TOKEN_IN_CHILD_PROCESS_ARGVmcp-remote only accepts the bearer via --header. Consequence: the S177 token appears in the npx/ mcp-remote child argv at runtime, observable to local processes able to read this user's process table.

Mitigations:

  • Wrapper does not export the token as an env var.
  • Wrapper execs the child, so no parent shell keeps a copy.
  • Wrapper file is mode 700 (owner-only).
  • Token is NOT at rest in Claude Desktop config or ~/.claude.json.

The previous RESIDUAL_RISK_LARK_CREDS_IN_CHILD_PROCESS_ARGV (from the official lark-mcp wrapper) is eliminated in 5000x because that wrapper is no longer launched. LARK_APP_SECRET_ROTATION_PENDING remains a recommended follow-up from 4500x — see INCIDENT_SECRET_DISCLOSURE_VIA_JQ_REDACTION_2026_05_24.

Closed gaps

  • CONSTITUTION_GAP_OFFICIAL_LARK_MCP (from 3500x manifest) — CLOSED by 3000x.
  • CLAUDE_CODE_CLI_LARK_MCP_BYPASS (4000x → 4500x → 5000x) — CLOSED by 5000x.
  • OFFICIAL_LARK_MCP_BYPASS_BLOCKER_FOR_FULL_RETIREMENT (4500x) — CLOSED by 5000x.

Usage

Check current state:

bash "/Users/nmhuyen/Documents/Manual Deploy/web-test/knowledge/current-state/s177-cowork-gateway-protection/s177-cowork-gateway-check.sh"

Restore known-good state (then restart Claude Desktop):

bash "/Users/nmhuyen/Documents/Manual Deploy/web-test/knowledge/current-state/s177-cowork-gateway-protection/s177-cowork-gateway-restore.sh"

Neither script touches Lark data, the VPS, nginx, systemd, or removes any MCP server entry.

After applying changes

Restart Claude Desktop manually so both wrappers are picked up. Do not let any automation kill Claude Desktop on the user's behalf.

Runbook — sealed state for real work (post-2500x)

Authoritative facts for any agent (Claude, Cowork, GPT, etc.) connecting to this Mac:

  • The only active Lark path is the S177 lark-crud-gateway.

  • The official @larksuiteoapi/lark-mcp is RETIRED. It must not be re-enabled in claude_desktop_config.json, ~/.claude.json, or anywhere else. It is preserved in ./archive/ for forensic reference only; the restore script refuses to reinstall it.

  • Expected lark-crud-gateway tools/list count is 22. If a future agent sees a different number (especially 15, 9, or 24), the protection has regressed.

  • If tools disappear or look wrong, run the read-only checker first — never poke at the config blind:

    ~/bin/s177-cowork-gateway-check
    
  • restore.sh only ever restores S177 wrapper + config from the newest 5000x snapshots. It refuses pre-5000x snapshots because they would re-introduce the retired official bypass.

  • LARK_APP_SECRET_ROTATION_PENDING is an accepted risk, not a blocker. Sealing the current state does not require rotation. Rotation, when performed, is an operator action against GSM (github-chatgpt-ggcloud / LARK_APP_SECRET).

  • Production live write is not enabled. The S177 adapter rejects writes outside the Base đệm whitelist with safety_violation. Enabling production writes requires a future governance macro — do not bypass.

  • lark_tables_create and lark_app_create are dry-run / governed. The api_caller refuses non-record operations by design until the production-governed-tools macro lands.

What Cowork (and any agent) may do now

  • Read operations on Base đệm via S177 Gateway: lark_healthcheck, lark_records_get, lark_records_search, lark_fields_list, lark_tables_list, lark_views_list.
  • Dry-run validation of writes for design/test purposes.
  • Single-record CRUD on Base đệm: lark_records_create, lark_records_update, lark_records_delete (whitelist-checked).
  • Batched record writes on Base đệm: lark_records_batch_create, lark_records_batch_update (BATCH_MAX=100).

What Cowork (and any agent) must NOT do yet

  • Any write to a Lark production base / table / app outside Base đệm.
  • Calling lark_tables_create, lark_app_create, lark_fields_create, lark_fields_update, lark_fields_delete, lark_views_create, lark_views_delete against production Lark — these remain governed / dry-run until the production-governed-tools macro authorizes them.
  • Re-enabling the official lark-mcp (in any config).
  • Restoring from a pre-5000x snapshot.
  • Printing the S177 bearer or LARK_APP_SECRET to terminal/chat/report.

Sealing reference

The sealed state is recorded in:

../reports/s177-cowork-final-ready-seal-2026-05-24.md

Also mirrored in KB at:

knowledge/dev/lark/s177-controlled-crud-gateway/s177-cowork-final-ready-seal-2026-05-24.md
Back to Knowledge Hub knowledge/dev/lark/s177-controlled-crud-gateway/s177-cowork-gateway-protection-README-2500x.md