S177 — Cowork Full LarkBase Tools (4000x) — Evidence (2026-05-23)
S177 — Cowork Full LarkBase Tools (4000x) — evidence — 2026-05-23
Mission: take S177 from "Remote MCP Gateway can healthcheck/get/create/update Base đệm" to "Cowork has a complete, safe LarkBase tool surface for record CRUD + schema/view management, exposed through the S177 Remote MCP Gateway, with production writes/destructive operations gated, Base đệm live operations tested, docs synced, and a final Cowork usage package ready."
Outcome: MACRO_PARTIAL_WITH_EXACT_GAP — COWORK_RECORD_CRUD_READY_SCHEMA_DEFERRED.
- record CRUD over the Base đệm is live and audited end-to-end (create, get, update, delete — including S177 marker cleanup);
- production live mutations are blocked at the adapter boundary;
- schema/view tools (fields / tables / views create / update / delete) are exposed and dry-run-previewable on any base, but live execution is deferred at the api_caller (it is the only path forward without Base đệm temporary-resource setup or production approvals, both of which the next-macro package covers).
1. Environment
| field | value |
|---|---|
| host | vmi3080463 |
| repo | /opt/incomex/lark-client |
| branch | feat/s177-sprint1-round-a |
| HEAD before | 09c30cdc3f355eafaf70a4bf333db217c268a8ed |
| config/bases.yaml sha256 (unchanged) | c063dc00c6b71a56d06435baba3019fcdd33d92999c770f8bc6d784866bdae5d |
| service | lark-mcp-remote.service — active (restarted after code change) |
| public endpoint | https://vps.incomexsaigoncorp.vn/mcp/s177/ocER6C1zErepgpAe/{mcp,healthz} |
2. Tool surface — 15 tools deployed
tools/list returns exactly the S177-4000x set (verified live via
scripts/s177_4000x_public_tools_probe.py):
| tier | tool | scope | live behaviour |
|---|---|---|---|
| A read | lark_healthcheck |
adapter | local, no Lark call |
| A read | lark_app_get |
any registered base | live |
| A read | lark_records_get |
any registered base | live |
| A read | lark_views_list |
any registered base | live |
| B write | lark_records_create |
Base đệm live; prod dry-run; prod live blocked | live (Base đệm) |
| B write | lark_records_update |
Base đệm live (single probe + field); prod blocked | live (Base đệm probe) |
| B/D destructive | lark_records_delete |
Base đệm live (non-protected); prod blocked | live (Base đệm) |
| B/D destructive | lark_records_batch_delete |
dry-run only; live deferred | dry-run preview only |
| C schema | lark_fields_create |
dry-run preview; live refused | dry-run only |
| C schema | lark_fields_update |
dry-run preview; live refused | dry-run only (destructive) |
| C schema | lark_fields_delete |
dry-run preview; live refused | dry-run only (destructive) |
| C schema | lark_tables_update |
dry-run preview; live refused | dry-run only (destructive) |
| C schema | lark_tables_delete |
dry-run preview; live refused | dry-run only (destructive) |
| C schema | lark_views_create |
dry-run preview; live refused | dry-run only |
| C schema | lark_views_delete |
dry-run preview; live refused | dry-run only (destructive) |
3. Files changed (summary)
See the canonical local evidence for the full list. Key changes:
config/allowed_endpoints.yaml— 6 → 13 write endpoints (added field / table / view paths).lark_client/reader.py—get_app,list_views.lark_client/service.py—get_app,list_views, seven schema write entry points,BaseDemOnlyApiCaller._issue_delete(with the protected-record guard forrecvkdFceNdpcz).lark_client/safety.py—_OP_ENUMand_is_destructivecover the seven schema ops; schema-mutation destructive ops require GPG backup.lark_client/mcp_adapter/adapter.py—MCP_TOOL_NAMES= 15 tools, a_SERVICE_METHOD_BY_OPdispatch table, and a relaxed base guard (production dry-run allowed; production live blocked).lark_client/mcp_adapter/server.py— 11 new@server.tool()s.tests/test_s177_4000x_surface.py— 34 new tests covering the entire 4000x surface; full suite at 310 passed, 5 skipped.scripts/s177_4000x_public_tools_probe.py,s177_4000x_public_acceptance.py,s177_4000x_cleanup.py— three new HTTPS-driven scripts.
4. Live acceptance — 14 steps, all pass
Run 2026-05-23 08:54Z. Highlights:
- Base đệm
records_createLIVE →recvkqPyVWspX5(audit9af788a7…). - Base đệm
records_updateLIVE on probe → backup…recvkdFceNdpcz…__pre.json.gpg, audit6d1c5fec…. - Base đệm
records_deleteLIVE on created → audit04aff4ae…. records_deleteof the probe — refused at api_caller (record_id_protected).records_batch_deleteLIVE — refused (op deferred).- Production
records_create/records_delete/tables_deleteLIVE — all refused at the adapter boundary (safety_violation). - Schema dry-runs (
fields_create,views_create) — succeed with fullaudit_ref+ preview.
5. Cleanup — Target F
scripts/s177_4000x_cleanup.py deleted all four S177-marked test
records on the Base đệm via the new lark_records_delete tool. Each
delete carries a GPG backup + audit ref. The probe was protected. Probe
read after cleanup is still green.
6. Structured error contract (RT-2)
All refused calls return ok=False with full RT-2: error_type,
reason, operation_id, remediation, safe_to_retry,
base_key/table_id/record_id. JSON-serialisable.
7. Token lifecycle status
- Bearer token (S177 Remote MCP): file-backed, constant-time compare, never printed.
- Lark tenant access token: cached with 5-minute safety margin under Lark expiry. Gap: a long-soak >2-hour probe is recommended in the next macro to verify the 120-minute boundary refresh.
8. Forbidden-action compliance
None of the mission's forbidden actions occurred. No production write,
no SafetyLayer bypass, no token print, no config/bases.yaml change,
no new credentials, no git push / merge / tag, no other service
restart, nginx untouched.
9. Final classification
MACRO_PARTIAL_WITH_EXACT_GAP — COWORK_RECORD_CRUD_READY_SCHEMA_DEFERRED.
Exact gaps for the next macro
(s177-production-governed-tools-readiness-macro-package.md):
- Schema live execution — dry-run-only this round; live deferred.
record.batch_deletelive execution — deferred at api_caller.- Lark tenant token long-soak refresh — single-session verified only.
- Production live writes — by design.