S177 Cowork Gateway Protection — README (post-2500x SEAL, 2026-05-24)
Lark MCP Launchers — Protection Package
Covers the SINGLE remaining Lark MCP launcher used by Claude Desktop:
lark-crud-gateway— S177 Cowork Gateway viamcp-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-gatewayconnection. - S177-OFFICIAL-LARK-MCP-CONSTITUTION-HARDENING-3000X (2026-05-23) —
removed raw
LARK_APP_ID/LARK_APP_SECRETfromclaude_desktop_config.jsonand routed the official launcher through a GSM-backed wrapper. - S177-SECRET-ROTATION-AND-BYPASS-CONTAINMENT-4000X (2026-05-23) — rotated
S177_LARK_MCP_REMOTE_TOKENv1→v2 and DISABLED the officiallark-mcpentry inclaude_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 officiallark-mcpfromclaude_desktop_config.jsonAND~/.claude.json(moved under_retired_mcpServerswith_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, officiallark-mcpinvisible,lark_healthcheckPASS,lark_records_get recvkdFceNdpczPASS, 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 -tOK, 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.comonly — neveropen.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. Onlylark-crud-gatewayis active. The oldlark-mcpentry lives in_retired_mcpServersfor audit only.claude_desktop_config.good-<ts>.json(pre-5000x) — historical snapshots kept for forensics.restore.shignores them — they would re-introduce the retired officiallark-mcpbypass.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 byrestore.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_disabledlark-mcpanywhere; live MCP probe for tools/list + production write rejection + Base đệmrecords_search.s177-cowork-gateway-restore.sh— restores S177 wrapper + config only from the newest 5000x good snapshots; explicitly NEVER restores the officiallark-mcpbypass. 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_ARGV — mcp-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-mcpis RETIRED. It must not be re-enabled inclaude_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-gatewaytools/listcount is 22. If a future agent sees a different number (especially15,9, or24), 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.shonly 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_PENDINGis 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_createandlark_app_createare dry-run / governed. Theapi_callerrefuses 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_deleteagainst 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_SECRETto 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