S177 — Lark Base Controlled CRUD Gateway — Folder Index
S177 — Lark Base Controlled CRUD Gateway — Folder Index
Folder: knowledge/dev/lark/s177-controlled-crud-gateway/
Last updated: 2026-05-20 (Sprint 1 Round D command-review-package filed)
Status: Sprint 1 Round D — first-live-write Command Review Package — PASS (planning only). Pairs with Round C baseline (commit 2307265 on feat/s177-sprint1-round-a, not pushed; cold pytest 134 passed / 5 skipped). Round D CRP proposes one records create --confirm on 88-phai-cu-base-dem :: tblaU7kxyPTNBSrR ("Đơn hàng") with one Text field; expects clean PII (detector=["none"]); leave-and-mark cleanup (Option A) because LARK_BACKUP_GPG_PUBKEY is still absent in GSM. Execution NOT authorized by this CRP — a separate source-mutation gate (D-IMPL: real api_caller) and explicit sovereign approval of the exact command are required first. A read-only --dry-run was issued during CRP authoring to verify audit-row shape; no Lark API call occurred. config/bases.yaml SHA256 unchanged. Sprint 2 (MCP adapter) remains gated.
This folder collects every authoritative document for project S177 — Lark Base Controlled CRUD Gateway. Read in the order below to follow the trail from requirements to current gate.
Reading order
1. Requirements (đề bài) — v2.2 FINAL
Path: knowledge/dev/lark/s177-controlled-crud-gateway-requirements-v2.md
(Lives one level up at knowledge/dev/lark/; do not move.)
What it is: The approved problem statement after GPT R3 (8.8/10). 8-layer SafetyLayer, 2-layer PII model, 2-phase audit, 4-sprint plan, 18 Lark Bases in scope.
2. Base architecture design (un-patched original)
Referenced by PATCH1 header: s177-architecture-design-2026-05-19.md (SHA-256 0440ef92…3639e5).
What it is: First design pass. Superseded by PATCH1, then PATCH2. Kept for revision history.
3. PATCH1 — first design patch
Path: s177-architecture-design-2026-05-19-patch1.md
What it is: Eight design corrections (atomic approval, MCP topology, configurable API limits, $LARK_AGENT nuance, S177-R0 gate, PII nuance, orphan-backup, Sprint 1 test split). Superseded by PATCH2.
4. OQ decision record
Path: s177-oq-decision-record-2026-05-19.md
What it is: Authoritative decisions on OQ-2 (GPG key), OQ-3 (PII), OQ-4 (MCP topology), OQ-5 (batch_delete), OQ-7 (orphan backup). All folded into PATCH2.
5. R0 code reconcile report
Path: s177-r0-code-reconcile-report-2026-05-19.md
What it is: Read-only verification of PATCH1 vs live /opt/incomex/lark-client/. Found 5 material + 2 partial drifts: argparse (not Click); exit-code enum 0..5; _request private + no client_token; AuditLogger post-hoc only; ungated live tests; minor exception/registry naming. STOP — PATCH2 required.
6. PATCH2 — design realignment (binding design)
Path: s177-architecture-design-2026-05-19-patch2.md
What it is: Current authoritative design. Resolves every R0 drift, folds every OQ decision. Eleven P2 sections: CLI argparse; exit-code routing; AuditLogger extension (4 methods + JSON schemas + mask-skip carve-out); LarkCore.write + client_token; test harness convention; OQ-7 orphan retention; OQ fold-ins; exception alignment; packaging freeze; allowed_endpoints.yaml write format; live-test quarantine.
7. PATCH2 summary
Path: s177-design-patch2-summary-2026-05-19.md
What it is: Short summary — PASS/sections-changed/drift-map/OQ-fold-map/blockers/recommendations.
8. Sprint 1 command-review package (this round)
Path: s177-sprint1-command-review-package-2026-05-19.md
What it is: The complete reviewable implementation package for Sprint 1 Track B (CLI record CRUD + SafetyLayer core + ApprovalProvider YAML + GPG backup + 2-phase audit + LarkCore.write + argparse + pytest gating + Base-đệm guard). 23 sections covering scope, non-scope, file inventory (DISCOVER-FIRST justified, 7 modified + 21 new), 8-phase implementation sequence, safety gates, unit + integration test plans, exit-code / exception mappings, audit / GPG / approval / LarkCore.write plans, config schemas, PII handling, orphan retention, rollback, PASS/FAIL/BLOCKED criteria, forbidden actions, post-implementation report shape.
OQ-9 RESOLVED inline via DISCOVER-FIRST: allowed_endpoints.yaml is structured-object schema {method, path, description} with {app_token} brace templates.
OQ-8 represented as Phase-1 pre-code micro-task: doc-citation step lands a citation file in this folder before any code uses client_token. Conservative defaults stand until citation flips a flag.
9. Sprint 1 implementation checklist (this round)
Path: s177-sprint1-implementation-checklist-2026-05-19.md
What it is: Linear, tick-box implementer's view of the Sprint 1 package. 10 sections × phase-aligned. Includes quick-verification matrix and common-pitfall lookup table. The implementer uses this checklist in order; the package is the reference document for details.
10. Sprint 1 Round A implementation evidence (this round)
Path: s177-sprint1-round-a-implementation-evidence-2026-05-19.md
What it is: PASS evidence for Round A — the safest foundational slice of Sprint 1. Branch feat/s177-sprint1-round-a @ 06b11c0 (not pushed). 14 files changed, +963/−18. Cold pytest: 31 passed, 5 skipped (live), 2 failed (pre-existing on main, proven independent). No live Lark API call, no production touched, no deploy, no push/merge/tag, no MCP-write enablement, no secret printed, no self-advance.
Round A covers: 5 net-new exceptions; AuditLogger 4-method extension + _write_strict + 19-key mask-skip; LarkCore.write(...) public boundary; 6 write: entries in allowed_endpoints.yaml; 3 new YAML configs (lark-api-limits, write-approvals, pii-fields); tests/conftest.py + pyproject.toml markers; @pytest.mark.integration on all 5 live tests (2 in test_core.py, 3 in test_reader.py — the latter discovered by source inspection beyond the package's enumeration); 3 new test files (test_core_write, test_audit_extension, test_configs_parse).
10b. Sprint 1 Round B Addendum (binding for Round B execution)
Path: s177-sprint1-round-b-addendum-2026-05-20.md
What it is: User-issued binding addendum supplementing the Sprint 1 package + PATCH2 for Round B specifically. Adds 7 binding rules: structured JSON output across all records … commands (success / dry-run / validation / error); structured error shape with retry_after_seconds; mandatory records get argparse + read path; approval-exempt-base test that proves all other layers still execute; WriteContext.source enum (cli|mcp|cron|api) with _MASK_SKIP_KEYS extension to 20 keys; immutability guarantee on config/bases.yaml; partial-progress rule with 4 explicit subset boundaries (B1 baseline + leak cleanup; B2 ApprovalProvider; B3 SafetyLayer skeleton; B4 service + CLI records surface). All 7 rules met by the Round B implementation (see §10c).
10c. Sprint 1 Round B implementation evidence (this round)
Path: s177-sprint1-round-b-implementation-evidence-2026-05-20.md
What it is: PASS evidence for the full Round B (B1+B2+B3+B4). 15 files changed Round-B-only, +2,530 / −12 lines. Four commits stacked: B1 60e3d80 (LarkCore.read + s179_probe refactor + argparse SUPPRESS fix + WriteContext.source plumbing + 12 tests), B2 8527154 (ApprovalProvider with fcntl-locked one-time-use consume + exempt-base passthrough + 17 tests including 4-thread race), B3 4b73375 (SafetyLayer 8-layer orchestration with injectable deps + WriteOutcome + WriteContext + 13 tests including the addendum-§4 critical exempt-base test), B4 1cf7901 (LarkWriteService + cli/records.py 7 subcommands with addendum-§1/§2 JSON shapes; records get fully impl; mutating commands refuse with structured NotAuthorizedInRoundB + 8 in-process tests). Cold pytest: 82 passed, 5 skipped (live, gated), 0 failed. config/bases.yaml SHA256 unchanged.
10d. Sprint 1 Round C implementation evidence (this round)
Path: s177-sprint1-round-c-implementation-evidence-2026-05-20.md
What it is: PASS evidence for Round C — replace stubs + pre-write readiness. Single commit 2307265 on top of Round B (1cf7901); 13 files changed, +2,584 / −101. Four new modules (lark_client/gpg_backup.py, lark_client/pii.py, lark_client/locks.py, lark_client/factory.py), safety.py extended with addendum-§C4 record-ID surface, cli/records.py delegates to the factory and emits PII + record-ID metadata, config/pii-fields.yaml seeded (29 entries for Base 88 TTS + Base đệm wildcard), config/lark-api-limits.yaml updated per OQ-8 citation. Tests: +52 net new across test_gpg_backup.py (10), test_pii.py (18), test_locks.py (16), test_round_c_scenarios.py (8, addendum-§C6). Cold pytest: 134 passed, 5 skipped (live, gated), 0 failed. Real GPG end-to-end test passes with a transient RSA-2048 key — no GSM provisioning needed for the test itself. LARK_BACKUP_GPG_PUBKEY still absent in production GSM; the factory falls back to the Round B stub when neither LARK_BACKUP_GPG_PUBKEY_PATH nor LARK_BACKUP_GPG_PUBKEY_FPR is set. config/bases.yaml SHA256 unchanged. No Lark write, no production touched, no Base đệm write, no deploy, no push/merge/tag, no MCP write enablement.
10e. Sprint 1 Round D command-review package (this round)
Path: s177-sprint1-round-d-command-review-package-2026-05-20.md
What it is: PASS — planning-only Command Review Package proposing the first live Lark write integration test on Base đệm. Proposes ONE records create --confirm against 88-phai-cu-base-dem :: tblaU7kxyPTNBSrR ("Đơn hàng") with payload {"Văn bản": "S177-RD-LIVE-PROBE <ISO8601> <uuid7>"}. Table choice (Đơn hàng, NOT TTS tblPQ6N79EeOmnTm) is justified by the config/pii-fields.yaml wildcard scope: Đơn hàng has no registry entry, so the expected PII output is the cleanest possible — pii_redacted=false, detector=["none"], field_hits=[]. Verified live in §4.1 via a non-mutating dry-run that produced the canonical two-row audit shape (phase: planned + phase: success with outcome_status: dry_run).
Live survey findings: HEAD 2307265a11241f1ecc228ff92199c1f94b9c1483; cold pytest 134 passed, 5 skipped; config/bases.yaml SHA256 unchanged c063dc00…dae5d; LARK_BACKUP_GPG_PUBKEY absent in GSM and _PATH/_FPR unset on the operator shell; LARK_AGENT unset (default fallback root@unknown is NOT acceptable for an authorized write).
D2 finding: source mutation IS required to flip the CLI from _round_b_refusing_api_caller to real LarkCore.write. There is no env var / CLI flag / config toggle today. The CRP proposes a separate authoring gate D-IMPL (estimated ~60-90 LOC; adds _real_lark_api_caller to lark_client/factory.py with a Base-đệm-only boundary guard + a new --enable-live-write CLI flag) that must be reviewed and merged BEFORE the execution command in §6.4 becomes meaningful.
GPG: NOT required for record.create (the SafetyLayer skips the backup layer for create/batch_create). GSM provisioning of LARK_BACKUP_GPG_PUBKEY IS required before any update/delete can run, and IS required before the test record can be cleaned up via the Gateway.
Cleanup policy: Option A (leave-and-mark) — leave the test record in Base đệm with the self-identifying marker string; record the created_record_id; defer cleanup to a later separately authorized gate after LARK_BACKUP_GPG_PUBKEY is provisioned.
Addendum-D1..D5 binding answers: D1 (clean PII output expected, verified live); D2 (source-mutation gate D-IMPL proposed); D3 (Option A cleanup, GPG-blocked delete acknowledged); D4 (LARK_AGENT=claude-code set inline + --agent claude-code redundancy; expected audit.agent="claude-code", audit.source="cli"); D5 (/var/log/lark-ops/<YYYYMMDD>.jsonl two-row correlation via audit_pre_id / operation_id / idempotency_key).
No Lark write executed. No production touched. No source mutation. No commit. No push. No bases.yaml edit. No secret printed.
11. Current gate status / next step
| Gate | Status |
|---|---|
| Sprint 0 (S177-R0 code reconcile) | CLOSED |
| OQ-1 / OQ-2 / OQ-3 / OQ-4 / OQ-5 / OQ-7 | CLOSED — folded in PATCH2 |
| OQ-6 (commit / repo path mechanics) | CLOSED — Round A executed on /opt/incomex (lark-client subdir of superproject); commit 06b11c0 on feature branch, not pushed |
OQ-8 (per-endpoint client_token support) |
CLOSED 2026-05-20 — authoritative Lark Open Platform doc citation; lark-api-limits.yaml updated; see §10d / Round C evidence §6 |
OQ-9 (exact shape of existing allowed_endpoints.yaml write: entries) |
CLOSED — confirmed by inspection at Round A DISCOVER-FIRST |
| Sprint 1 command-review package | ACCEPTED (Round A/B/C executed against it) |
| Sprint 1 Round A (controlled CRUD gateway scaffolding) | PASS — branch feat/s177-sprint1-round-a @ 06b11c0 not pushed |
| Round B addendum (Cowork consumption + Base safety) | FILED 2026-05-20 — binding spec for B; all 7 rules met |
| Sprint 1 Round B (B1+B2+B3+B4) | PASS — feature branch feat/s177-sprint1-round-a HEAD 1cf7901 not pushed; see §10c |
| Round C task (replace stubs + pre-write readiness) | FILED 2026-05-20 — open-goal macro task |
| Sprint 1 Round C | PASS — feature branch feat/s177-sprint1-round-a HEAD 2307265 not pushed; see §10d |
| Sprint 1 Round D command-review package (first-live-write planning) | PASS — FILED 2026-05-20 — see §10e; execution NOT authorized; D-IMPL source-mutation gate is the next macro |
D-IMPL (Round D source-mutation: wire real api_caller + --enable-live-write flag) |
OPEN — NOT YET AUTHORIZED |
D-EXEC (Round D step 1: live records create on Base đệm per §6.4 of §10e) |
NOT AUTHORIZED — gated on D-IMPL completion + separate sovereign approval |
| Sprint 1 follow-ons | GSM LARK_BACKUP_GPG_PUBKEY provisioning · then Round D step 2 (update/delete on Base đệm) · then Gateway cleanup of the leave-and-mark record |
| Sprint 2 (MCP adapter) | NOT AUTHORIZED until Round D follow-ons land and Sprint 1 sign-off granted |
Next step: GPT/User reviews the Round D CRP (§10e). On acceptance, D-IMPL can be opened as a separate authoring macro (estimated ~60-90 LOC, ~2-3 new wiring tests; no Lark write). After D-IMPL is reviewed and merged, D-EXEC can be authorized by a separate one-time sovereign approval message for the exact §6.4 command. After D-EXEC, the operator uploads s177-sprint1-round-d-live-write-evidence-2026-05-20.md per CRP §6.16. Sprint 2 remains gated.
Conventions (unchanged from PATCH2 round)
- All S177 documents live in this folder, except the requirements file which lives one level up.
- Document file names use pattern
s177-<topic>-YYYY-MM-DD[-suffix].md. Patches are dated and labelled-patchN. Sprint deliverables are labelled-sprintN. - Existing documents are not edited except via a new patch / package that supersedes them.
- No code, no source mutation, no Lark write, no deploy, no push/merge/tag, no MCP-write enablement, no production test ever happens as a side effect of work in this folder. All such actions require separate, explicit authorization.
Existing Lark connection — reuse-only stance (Sprint 1)
Sprint 1 explicitly reuses the operational Lark connection inherited from S176 + the existing MCP topology. No new bot, no new credential, no new MCP connection, no duplicate adapter is created in Sprint 1. Specifically:
- Bot "For Gem" (
cli_a785d634437a502f) — unchanged. - GSM credential path (
LARK_APP_ID/LARK_APP_SECRETin projectgithub-chatgpt-ggcloud) — unchanged. - Existing
@larksuiteoapi/lark-mcpplugin (9 bitable tools) — untouched in Sprint 1; Sprint 2 owns plugin topology decisions per OQ-4. - Existing
lark_clientfoundations (LarkCore,LarkReader,Registry,AuditLogger) — extended, not forked. - Existing
config/allowed_endpoints.yaml— appended to (6 new entries underwrite:); schema preserved. - Existing audit dir (
/var/log/lark-ops/) and rate-limit lock files (/var/lock/lark-api.{lock,state}) — reused.
New GSM secret introduced by Sprint 1 design (not net-new infrastructure): LARK_BACKUP_GPG_PUBKEY (ASCII-armored GPG public key). Fetched via the same LarkCore._gsm_get helper; private key remains offline (OQ-2).
S177 folder index — refresh after each milestone round.