S177 Lark Base Controlled CRUD Gateway — Đề bài v2.2 FINAL
S177 Lark Base Controlled CRUD Gateway — Đề bài v2.2 FINAL
Trạng thái: APPROVED — Sẵn sàng giao Claude Code CLI thiết kế
Ngày: 2026-05-19
Vòng phản biện: GPT R1 → R2 → Opus verdict → GPT R3 (final)
Điểm tổng GPT R3: 8.8/10 | Completeness 9.0 | Safety 9.0 | Feasibility 8.5 | Clarity 8.8
CHANGELOG
| Version | Thay đổi |
|---|---|
| v1.0 | Bản đề bài ban đầu (Cowork soạn) |
| v2.0 | Sau GPT R1: thêm SafetyLayer, CLI trước MCP, approval system |
| v2.1 | Sau GPT R2: 13 mục, 15 ràng buộc, 8 lớp bảo vệ, 4 Sprint 5 Phase, 8 quyết định chốt |
| v2.2 | Sau GPT R3 final: ApprovalProvider DI, PII 2 lớp song song, audit 2-phase, approval defaults chốt, no-wildcard policy, GPG key spec requirement, Sprint label fix |
1. MỤC TIÊU
Cowork có thể thao tác đầy đủ CRUD với 18 Lark Base mà không cần mở Lark web. Claude có quyền thao tác nhưng không bypass SafetyLayer.
2. BỐI CẢNH HỆ THỐNG
- 18 Lark Base, 299 bảng, 11,854 fields — đang production hàng ngày
- Bot "For Gem" (
cli_a785d634437a502f) — 1 bot duy nhất, đã add vào 18 Base lark_clientPython v1.0.0 — read-only (list_tables, list_fields, search_records), 19/19 test PASSlark-toolCLI — schema dump, audit log, 8/8 VERIFY PASS- MCP plugin 9 tools — Create + Read + Update (KHÔNG có Delete, KHÔNG có field management)
- Base URL:
open.larksuite.com(KHÔNG phảiopen.feishu.cn)
3. GAP HIỆN TẠI CẦN BỔ SUNG
| Nhóm | Đã có | Thiếu |
|---|---|---|
| Base App | Create | Get, Update, Delete, List |
| Table | List, Create | Update (rename), Delete |
| Field | List | Create, Update, Delete |
| Record | Search, Create×2, Update×2 | Get by ID, Delete×2 |
| View | ❌ | List, Create, Delete |
| CLI write | ❌ | Toàn bộ |
4. KIẾN TRÚC ĐỀ XUẤT
Cowork / MCP Claude Code CLI / Cron
│ │
└──────────┬───────────────┘
▼
Application Service Layer
(CLI và MCP phải gọi CÙNG layer này — không duplicate write logic)
▼
SafetyLayer
(dry-run → approval → backup → audit-pre → lock → rate-limit → PII → call API → audit-post)
▼
Lark Open API (open.larksuite.com)
Nguyên tắc bất biến:
- 1 Bot duy nhất, 1 credential (GSM) — không hardcode bao giờ
- Mọi call qua
LarkCore— khôngimport requeststrực tiếp - Rate limit 10 req/s, audit JSONL, idempotency key bắt buộc cho write
$LARK_AGENT:claude-code|cowork-mcp|cron
5. SAFELAYER — 8 LỚP BẢO VỆ
--dry-runmặc định ON —--no-dry-runđể chạy thật; update/delete production khi--no-dry-runphải thêm--confirm- Approval check — human-created, xem §8 cho defaults
- Backup record cũ trước update/delete — encrypt GPG từ Sprint 1
- Idempotency key (UUID v4) bắt buộc
- Auto-generate rollback command sau mỗi write
- Lock — tránh concurrent write cùng record
- Rate limit — 10 req/s, batch 500 records max
- Audit fail-closed — xem §9
Quan trọng:
approval_exempt_baseschỉ bypass Approval Check (lớp 2). Tất cả 7 lớp còn lại vẫn áp dụng đầy đủ — bao gồm audit, dry-run, lock, backup, rate-limit.
6. PII PROTECTION — 2 LỚP SONG SONG
Hai lớp chạy song song (không phải hierarchy):
| Lớp | Cơ chế | Bắt gì |
|---|---|---|
| Field registry | Whitelist field_id đã biết có PII | Field được đặt tên rõ |
| Pattern-based regex | CMND/passport/bank account/phone | Field chưa biết / di sản |
Cả hai phải active cùng lúc vì 18 Base do nhiều người xây, không thể biết hết field chứa PII.
Backup encrypt: GPG bắt buộc từ Sprint 1.
Architecture doc phải specify: GPG key source, rotation policy, access permission, recovery procedure.
Audit log chỉ ghi metadata, KHÔNG ghi giá trị PII:
{
"pii_redacted": true,
"redaction_types": ["national_id", "bank_account"],
"redacted_fields_count": 3
}
7. APPROVAL SYSTEM
ApprovalProvider phải dependency-injected
SafetyLayer không được import trực tiếp YamlApprovalProvider.
Sprint 1–2: YAML backend. Sprint 3+: swap sang Directus mà không đụng SafetyLayer.
Wildcard scope policy
| Operation | Wildcard table? |
|---|---|
| record.create | ✅ Cho phép |
| record.update | ❌ Không |
| record.delete | ❌ Không |
| field.create/update | ❌ Không |
| field/table delete | ❌ Không (break-glass) |
First write rule
Lần đầu ghi vào bất kỳ base/table cụ thể nào → approval scope phải chỉ rõ base_key + table_id. Wildcard không được chấp nhận cho first write.
8. APPROVAL DEFAULTS (ĐÃ CHỐT)
| Operation | Mặc định |
|---|---|
| record.create | reusable trong expiry nếu scope hẹp |
| record.update | one-time-use |
| record.delete | one-time-use bắt buộc |
| field.create/update | one-time-use bắt buộc |
| field/table delete | break-glass, one-time-use bắt buộc |
Rule tổng quát: Production approval là one-time-use by default. Reusable phải explicit và không được áp cho delete/schema operations.
9. AUDIT — 2-PHASE PRE/POST EXECUTION
Phase 1: Ghi entry "planned/started" TRƯỚC khi gọi Lark API
→ Nếu Phase 1 fail: ABORT (không gọi API)
Phase 2: Gọi Lark API
Phase 3: Ghi entry "success/failed" AFTER API trả kết quả
→ Nếu Phase 3 fail SAU KHI API success:
ghi emergency fallback log + return warning status
(không thể "unwrite" — phải có emergency trail)
Không được để tình huống: write đã chạy nhưng không có audit trail.
10. SPRINT PLAN
| Sprint | Nội dung |
|---|---|
| 1 | Track B: writer.py + SafetyLayer core + backup GPG + audit 2-phase + tests |
| 2 | Track A: MCP adapter wrap Application Service Layer + record.get/delete MCP |
| 3 | Field operations: field_manager.py (simple types only) + ApprovalProvider interface + Directus prototype |
| 4 | Schema ops: table/base management + monitoring + full integration test |
Sprint 3 field operations chỉ support: Text, Number, Single choice, Checkbox. Complex types (Formula, Lookup) → Sprint 4+.
11. TRACK DETAIL
TRACK A — MCP Plugin (Cowork)
- Khảo sát
@larksuiteoapi/lark-mcp— có thể enable tools thiếu qua config không - Nếu đủ: enable theo thứ tự: record.get/delete → field ops → view ops
- Nếu không đủ: custom MCP server wrap Application Service Layer
- Cowork/MCP delete: chỉ Base đệm — KHÔNG production
- Test 12 cases trên Base đệm
TRACK B — CLI Write Module
Files cần xây:
lark_client/writer.py— LarkWriter: create/batch_create/update/batch_update/delete/batch_delete recordslark_client/field_manager.py— LarkFieldManager: create/update/delete fieldscli/commands/records.py+cli/commands/fields.pyconfig/write-approvals.yaml— approval registry
CLI interface:
# Dry-run mặc định ON:
lark-tool records create <base-key> <table-id> --data '{...}' --approval APR-001
# Chạy thật (cần --no-dry-run + --confirm cho update/delete):
lark-tool records update <base-key> <table-id> <record-id> \
--data '{...}' --approval APR-001 --no-dry-run --confirm
lark-tool records delete <base-key> <table-id> <record-id> \
--approval APR-001 --no-dry-run --confirm
lark-tool fields create <base-key> <table-id> \
--name "X" --type Text --approval APR-001 --no-dry-run
lark-tool fields delete <base-key> <table-id> <field-id> \
--approval APR-001 --no-dry-run --confirm "tôi hiểu không thể undo"
12. RÀNG BUỘC KỸ THUẬT
- Không hardcode
app_token - Không tạo Bot mới — dùng "For Gem" (
cli_a785d634437a502f) - Không đọc GSM trực tiếp — qua
LarkCore - Không gọi HTTP trực tiếp — không
import requests $LARK_AGENTbắt buộc khi chạy batch- Không sửa field
TTN tiến cửtrong TTS (fldPTsPOxl) — read-only - Field operations phải dùng
field_id, không dùng tên - CLI và MCP phải gọi cùng Application Service Layer — không duplicate write logic
- Schema operations: maintenance window bắt buộc + staging test
- Partial failure: stop and report — không auto-rollback — retry chỉ manual
- Production delete: CLI-only — Cowork/MCP delete chỉ Base đệm
- Base đệm reset: Claude Code được reset nhưng phải audit
13. FINAL DEFAULTS FOR DESIGN (Claude Code phải tuân thủ)
- Production write → CLI/SafetyLayer first. MCP write là adapter-only.
- Production approval → human-created, one-time-use by default.
approval_exempt_bases→ bypass Approval Check only. Audit/dry-run/lock/backup/rate-limit vẫn áp.- Production delete → CLI-only. Cowork/MCP delete → Base đệm only.
- Schema operations → maintenance window + staging test bắt buộc.
- Backup → GPG encrypt từ Sprint 1. Architecture doc phải có GPG key management spec.
- Audit → pre-execution entry bắt buộc trước real write. Post-execution fail → emergency fallback log.
- Delete/schema approvals → không được dùng wildcard scope.
$LARK_AGENTvalues:claude-code|cowork-mcp|cron.- First write on any base/table → explicit approval scope (base_key + table_id), no wildcard.
- ApprovalProvider → dependency-injected. SafetyLayer không import trực tiếp implementation.
14. TÀI LIỆU LIÊN QUAN
- Directus KB #3868 — lịch sử revision đầy đủ
knowledge/dev/lark/lark-base-registry.md— schema snapshot 18 Baselark_client/trên VPS — source code hiện tại (/opt/incomex/lark-client/)bases.yaml— schema snapshot 18 Base