fix: align runtime with documented contract (spec-drift code fixes)#245
Merged
Conversation
…ixes)
A spec↔implementation audit surfaced places where the runtime diverged
from its documented contract. Four fail-closed / contract fixes:
- remote MCP `resource` reads now fail closed on an unresolved placeholder
(`unfilled resource placeholders`), matching the openapi path/body guard —
previously a literal `{x}` URI was sent upstream.
- `tenant_delete` requires `confirm` == `tenant_id` before the destructive
wipe (protocol.md §Admin, platform.md §Tenant lifecycle); threaded through
`escurel-types` / `escurel-client`; the `escurel` CLI echoes the operator-
typed id as the confirmation.
- `tenant_export` now returns `format_version` + a SHA-256 of the tarball
body so a consumer can verify durability before trusting it (protocol.md
§backup contract).
- telemetry reads the convention-compliant `ESCUREL_OBSERVABILITY_OTLP_ENDPOINT`
(env = TOML key path), keeping bare `ESCUREL_OTLP_ENDPOINT` as a deprecated
fallback so existing deployments don't break.
Each behaviour is covered by a real no-mock test; the resource-guard test was
verified red→green (disabling the guard sends the literal URI and the read
stops degrading). Docs are reconciled to these fields in the follow-up
doc-sync PR.
Test plan: cargo test -p escurel-server --test remote_backend_tools
(mcp_resource_read_fails_closed_on_unresolved_placeholder) --test
mcp_admin_tools (tenant_delete_requires_matching_confirm, export sha256);
full fmt/clippy/test/build gate green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
jrosskopf
added a commit
that referenced
this pull request
Jul 7, 2026
A doc↔implementation audit (6 scoped passes + codex) found the specs had
drifted from the code across the agent surface, admin surface, storage, DX,
and platform docs. This syncs the docs to what the code actually does; where
the spec described an unbuilt feature it is now clearly marked
**Not yet implemented** rather than presented as current.
protocol.md (agent + admin wire contract):
- expand/neighbours/list_instances/resolve request args + response fields
corrected to the real handlers; `scenario`/`full`/`as_of` documented;
removed never-emitted fields (`snapshot_version`, resolve `error`, session
`content`/`conflicts`/`issues`) as not-yet-implemented.
- documented `fetch_blob` (was undocumented); added `search.similarity` +
`queries`/`page_id`; `validate` returns `{ok, issues}`.
- admin tool names fixed (`admin_audit`/`admin_quota`/`admin_delete_chat_history`);
removed the non-existent `health` tool; tenant/attach_external arg+output
shapes fixed; added the ~11 previously-undocumented admin tools; documented
`tenant_delete` confirm + `tenant_export` `{format_version, sha256}` +
markdown-only tarball (matches #245).
- `tools/list` is not role-gated (admin tools listed, dispatch-gated); added
the plain-HTTP endpoints incl. `/openapi.json`; versioning corrected
(crate semver, no `escurel-ws/1`); `backend_ref` is `{kind, endpoint}`.
storage.md: removed the phantom `frontmatter_index` table (filtering is a
direct `json_extract` over `pages`); `open_writer` marked not-implemented;
`url()` → `Result<Url>`; `links` PK includes `dst_anchor`; FTS ignore regex;
`put_blob` signature; `compact_db` → `compact_lanes`.
dx.md: `Role::User` → `Role::Agent` (the example didn't compile); added the
`AuthMode::ExternalMulti` variant; TestIssuer is RSA-2048.
platform.md / README.md / deploy: the multi-tenant TenantManager model, the
sizing knobs, `log_format=text`, and the `/readyz` OTel check are marked not-
implemented; OTLP env is the convention name (`ESCUREL_OBSERVABILITY_OTLP_ENDPOINT`,
bare name a deprecated alias).
Dockerfile: base bumped rust:1.88 → 1.91 (matches rust-toolchain.toml); the
bundled-DuckDB build comments rewritten to describe download mode.
CLAUDE.md: CI is live (re-enabled at v1.0.0) — flipped the three "CI is paused"
claims; the local four-command gate remains the fast inner loop.
ADR-0002: appended a note that gRPC was retired (surface is MCP-only).
Docs-only; no code changed. Depends on #245 for the `tenant_delete`/
`tenant_export`/OTLP field names it documents.
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Part 1 of the spec↔implementation drift remediation. Four fail-closed / contract fixes where the runtime had diverged from the documented behaviour:
resourcereads fail closed on unresolved placeholders —remote_backend.rsnow runs the sameunfilled_placeholdersguard the openapi path/body paths use; an unresolved{x}in aresource:URI degrades to an issue instead of being sent literally upstream.tenant_deleterequiresconfirm == tenant_id— the destructive wipe was firing with no confirmation token, contrary toprotocol.md §Admin surface+platform.md. Threaded throughescurel-types(TenantDeleteRequest.confirm) andescurel-client; theescurelCLI echoes the operator-typed id as the confirmation (typing the id on the command line is the confirmation).tenant_exportcarriesformat_version+sha256— the backup contract (protocol.md) promises an export-format version and a SHA-256 of the body so consumers can verify durability; the result previously had only{tarball_b64, bytes}.ESCUREL_OBSERVABILITY_OTLP_ENDPOINT(env = TOML key path, as the deploy docs instruct) with the bareESCUREL_OTLP_ENDPOINTkept as a deprecated fallback.The pure doc drift (protocol.md read/admin surface, storage.md, dx.md, platform.md, Dockerfile, CLAUDE.md CI status) is reconciled in a follow-up doc-sync PR; a dead-code cleanup PR follows that. Two larger feature gaps found in the audit —
update_pageoptimistic concurrency (base_version/three-way-merge,new_versionis a stub) andtenant_updatesuspend/quota/embedding — will be filed as issues.Test plan
cargo test -p escurel-server --test remote_backend_tools—mcp_resource_read_fails_closed_on_unresolved_placeholder(verified red→green: disabling the guard sends the literal URI and the read stops degrading).cargo test -p escurel-server --test mcp_admin_tools—tenant_delete_requires_matching_confirm(missing/wrong confirm →-32602);tenant_export_then_import_round_tripsnow assertsformat_version == 1+sha256matches the body.escurel-cli/escurel-clientadmin e2e updated to passconfirm.fmt --check,clippy --workspace --all-targets -D warnings,test --workspace --all-targets,build --workspace --release.🤖 Generated with Claude Code
Need help on this PR? Tag
/codesmithwith what you need. Autofix is disabled.