이 문서는 mutation 보안 경계, 프로젝트 상태, 장기 작업, 제품 tool surface를 단순화한 현재 구현 계약을 설명합니다. English summaries are included under each phase for host integrators.
Runtime Contract
| Concern | Canonical implementation | Operational rule |
|---|---|---|
| Tool catalog | crates/codelens-mcp/tools.toml plus generated metadata |
Run python3 scripts/regen-tool-defs.py --check --enforce-drift |
| Mutation identity | One UUID operation_id per invocation |
transaction_id is a deprecated response/query alias only |
| Mutation audit | SQLite intent and terminal transition rows | Audit open/write failure blocks mutation |
| RBAC | Project or user principals.toml |
Mutation-capable runtime without a valid file resolves every principal to ReadOnly |
| Project state | ProjectContext |
Request binding selects one context without copying project resources into AppState |
| Long jobs | JobService and AnalysisJobStore |
Queue, semantic indexing, cancellation, heartbeat, deadline, and stale recovery share one lifecycle |
| Product surface | readonly, review, builder |
Previous profile names remain deprecated input aliases until v2.0 |
| Experimental tools | CODELENS_EXPERIMENTAL_FEATURES |
secondary-projects, orchestration, or all must be explicitly enabled |
principals.toml mappings are cached per project audit directory. After changing the file, restart the daemon. A malformed or missing mapping cannot be repaired through a mutation call because the runtime is already fail-closed.
Phase 0: Immediate Risk Controls
- Mutation dispatch opens the audit sink and writes a
Verifyingintent before the handler runs. - Audit open or intent-write failure returns an error before any content mutation.
- A UUID
operation_idis generated once and reused by intent, denial, failure, terminal audit row, response, and orchestration event. tools/listis intersected with the authenticated principal role. Listing and execution use the same_session_principal_id.- A mutation-capable runtime requires an operator-authored
principals.toml; missing or malformed configuration resolves toReadOnly. scripts/runtime-snapshot.pygenerates source HEAD/tree, disk binary SHA, live daemon SHA, and role-filtered tool counts.
English: mutation authorization and audit durability now form one fail-closed pre-execution boundary.
Phase 1: Integrity Recovery
- Mutation classification moved from a Rust match list into the generated ToolCatalog metadata sourced from
tools.toml. - Audit records are validated in Rust and constrained by SQLite lifecycle domains.
- Audit schema v5 renames the physical
transaction_idcolumn and index tooperation_id; only the request/response compatibility alias remains. - Role denial, surface/access denial, parameter failure, preflight failure, handler failure, rollback, and success use the same operation log.
- Memory mutation responses expose both
scopeandtier; rename, archive, restore, and archived listing support project and global roots consistently. - The legacy
transaction_idquery input and response field remain compatibility aliases foroperation_id.
English: catalog, RBAC, audit, and memory ownership now use shared classifications instead of parallel string lists.
Phase 2: State And Job Simplification
ProjectContextowns project root, symbol index, graph cache, LSP pool, memory/analysis/audit directories, watcher, and watcher health.AppStateholds one default context plus request-scoped/cached context references instead of eight duplicated default project fields.JobServiceis the only background queue for report analysis and semantic indexing.- Jobs persist
heartbeat_at_ms,deadline_at_ms, andcancel_requested_at_ms. - Semantic indexing checks cancellation and deadline state at file and embedding-batch boundaries while refreshing its heartbeat.
- Startup converts stale queued/running jobs to
Errorwithworker interruptedevidence instead of leaving them permanently active. CODELENS_JOB_DEADLINE_SECSdefaults to 1800 seconds;CODELENS_JOB_STALE_SECSdefaults to 300 seconds.CODELENS_JOB_HEARTBEAT_SECSdefaults to 5 seconds for long semantic jobs.
English: project ownership is explicit and every durable background task follows one recoverable lifecycle.
Phase 3: Product Surface Reduction
- Canonical profiles are
readonly,review, andbuilder. planner-readonly,reviewer-graph,builder-minimal,refactor-full,ci-audit,workflow-first, andevaluator-compactare deprecated input aliases.- Overlay details remain internal routing calculations; only canonical profile and selected guidance are product contracts.
- Secondary-project tools require
CODELENS_EXPERIMENTAL_FEATURES=secondary-projects. - Orchestration requires
CODELENS_EXPERIMENTAL_FEATURES=orchestration. index_embeddingsqueues by default.background:falseis the explicit synchronous compatibility path.
English: the public product has three role surfaces; research and orchestration capabilities no longer enlarge the default contract.
C4 As-Is
flowchart TB
Host["Agent host"] --> Transport["MCP transport"]
Transport --> AppState["AppState with duplicated default project resources"]
AppState --> AnalysisQueue["Analysis queue"]
AppState --> EmbeddingThread["Detached embedding thread"]
AppState --> Index["Symbol and embedding indexes"]
Transport --> RoleGate["Execution-only role gate"]
RoleGate --> Mutation["Mutation handler"]
Mutation -. "best-effort audit" .-> Audit["SQLite audit sink"]
C4 To-Be
flowchart TB
Host["Agent host"] --> Transport["MCP transport"]
Transport --> Identity["Session principal and canonical surface"]
Identity --> Catalog["Generated ToolCatalog"]
Catalog --> Listing["Role-filtered tools/list"]
Catalog --> Dispatch["Dispatch access gate"]
Dispatch --> AuditIntent["Fail-closed audit intent"]
AuditIntent --> Mutation["Mutation handler"]
Mutation --> AuditTerminal["Terminal operation transition"]
Dispatch --> Context["ProjectContext"]
Context --> Index["Symbol, graph, LSP, semantic stores"]
Dispatch --> Jobs["JobService"]
Jobs --> JobStore["Durable job store with heartbeat and deadline"]
Jobs --> Reports["Analysis runners"]
Jobs --> Semantic["Semantic indexing runner"]
Dynamic Flow: Mutation
sequenceDiagram
participant H as Host
participant D as Dispatch
participant R as RBAC and Catalog
participant A as AuditSink
participant M as Mutation Handler
H->>D: tools/call
D->>D: generate UUID operation_id
D->>R: validate role, surface, project, preflight
alt denied or invalid
D->>A: append denied or failed transition
D-->>H: error with recovery hint
else allowed
D->>A: append Verifying intent
A-->>D: durable write acknowledged
D->>M: execute mutation
M-->>D: evidence or error
D->>A: append terminal transition
D-->>H: response with operation_id
end
Dynamic Flow: Semantic Job
sequenceDiagram
participant H as Host
participant J as JobService
participant S as AnalysisJobStore
participant E as Embedding Engine
H->>J: index_embeddings
J->>S: persist queued job and deadline
J-->>H: job_id and poll handle
J->>S: running heartbeat
J->>E: index project
E-->>J: index result
J->>S: completed or error
H->>S: get_analysis_job
S-->>H: status, heartbeat, deadline, error
Note over J,S: On restart, stale queued/running jobs become Error
Deployment Verification
cargo check --workspace --features http,semantic
cargo test -p codelens-engine
cargo test -p codelens-mcp --bin codelens-mcp --features http,semantic
python3 scripts/regen-tool-defs.py --check --enforce-drift
python3 scripts/surface-manifest.py --check
bash scripts/redeploy-daemons.sh --build --probe
python3 scripts/runtime-snapshot.py --write --check