Data flow, storage, and retention
For LLMs10 sections
Trace every byte a question touches: where questions, facts, documents, drafts, and answers travel, where each copy rests, who can read it, and when it disappears.
Component law-mcp (MCP host; default profile all, default
--port 8722, default bind 127.0.0.1). Scenario: one tools/call
round trip over stdio or HTTP, plus the optional Lens publication and
neural-search legs. All case names, hashes, and hostnames below are
synthetic examples.
Applies to
Section titled “Applies to”| Branch | Coverage in this article |
|---|---|
MCP (law-mcp-server) | full data-flow trace incl. answers/neural/OTLP legs |
law serve | not covered — serve state is the world + the shared decision journal, see Deploy a private HTTP service, Backup and restore |
Prerequisites
Section titled “Prerequisites”- The server root (
--root/LAW_MCP_ROOT, real), or a checkout the server can find by its two markers — the profiles directory and the compiled-corpus directory (real root discovery). - Know which legs are enabled: HTTP (
--http), call journal (on by default,LAW_MCP_LOG=0disables), OTLP (LAW_MCP_OTLP_URL), Lens answers (LAW_ANSWERS_URL+LAW_ANSWERS_TOKEN), neural appendix (LAW_NEURAL_URL+LAW_NEURAL_TOKEN). All real (law-mcp/src/main.rs,publication.rs,reference/search.rs).
- Send the question. Over stdio the request is one JSON line on
stdin; over HTTP it is
POST /mcpwith a single JSON-RPC object (real: batches are refused,http.rs). The request carries the tool name, the predicate with arguments, and the case facts with provenance. - The server reads the corpus and the case. Reads are confined to the
root: a case package
<root>/<package>/must containlaw.toml(real,execution.rs), and a path that canonicalizes outside the root is refused (case_ask.outside_root, real). Symlink escapes are refused, not followed. - The engine evaluates in memory. Pure evaluation writes no files:
the answer document (statuses, applied rules, provenance hashes
programHash/caseHash/resultHash/codeHash) is built in the call thread and returned in the response (real). The writing tool classes —editing(case packages),drafting(author-tree files) — are the exception, listed in the effects matrix. - Optional leg A — call journal. On the HTTP transport only (stdio
never journals, real,
reqlog.rs), each call’s primary record goes to the journald native socket/run/systemd/journal/socket, or — if the socket is absent — as one JSON line to stderr (real,journal.rs). A late-finishing call adds a second record for the same call id (OVERRUN_FINISHED), so journal reads correlate by id rather than counting lines (see Logs, audit, decision journals). Bodies are capped at 64 KiB per side by default (LAW_MCP_LOG_MAX_BODY,0uncaps, real). - Optional leg B — Lens answers. The four publication tools
(
law_capture_answer,law_prepare_answer,law_publish_answer,law_revoke_answer, real,publication.rs) forward toPOST {LAW_ANSWERS_URL}/internal/mcp/callwith schemalaw.answers.mcp-call/0.1(real). WithoutLAW_ANSWERS_URLand a non-empty token the tools answerANSWERS_UNAVAILABLEand nothing leaves the host. - Optional leg C — neural appendix.
law_searchposts the query text plus the lexicaltakencandidates (kind/id/point, no case facts) to{LAW_NEURAL_URL}/v1/appendix(real,reference/search.rs). WithoutLAW_NEURAL_URLthe leg reportsactive:falseand the answer stays purely lexical. - Optional export —
--export-neural-input PATHwrites the search index input document to exactly that path (real,main.rs). Together with theediting/draftingtool writes and per-call temp workbench files, this is the complete file-write surface — see the effects matrix for the authoritative list.
Expected result
Section titled “Expected result”- The client holds the full answer document in the response. The MCP host has no separate persistent answer store and keeps no long-lived response object after the call returns (real) — but with journaling on (the HTTP default), request and response bodies, including case facts, are persisted in the log infrastructure (journald, stderr capture, or the external collector) and must be handled as case data: same access rights, retention, backup, and cleanup rules as the case directory itself. Audit the whole deployment, not just the absence of a database inside the process.
- Case inputs live where the operator put them and where the
deployment copies them: the case directory (
law.toml,law.lock,queries/*.json,.lawcasefiles), the client that sent the facts, and — when journaling is on — the journal records described below. - Journal records live in the host journal (journald) or the process stderr stream — see article 09 for fields and redaction.
- A prepared Lens document is a non-public frozen document held by
the answers service for 24 hours (reference behavior of
law_prepare_answer); publishing returns a URL plus a separate revoke secret, and revoking closes HTML, API, and download. The MCP host stores none of these.
Result check
Section titled “Result check”- With the journal on stderr, one successful call produces one
primary JSON line containing
MCP_TOOLandMCP_CALL_ID(real field names). Line count is NOT a call count: a late-finishing computation may add anOVERRUN_FINISHEDrecord for the same call, a journal-write failure can drop a record while the call itself succeeds, an oversized datagram is resent truncated (content lost, record survives), and transport failures produce no call record at all. Correlate byMCP_CALL_IDand event type; see article 09. The guarantees of the MCP call log and thelaw servedecision journal differ — do not treat either as a backup or as an audit-completeness proof on its own. - With
LAW_ANSWERS_URLunset,law_prepare_answerreturnsisError:truewith codeANSWERS_UNAVAILABLE(real). - With
LAW_NEURAL_URLunset,law_searchcarriesneural.active:false(real). GET /healthzis never journaled (real,reqlog.rs): the balancer’s polls leave no case-data trace.
Failures and diagnostics
Section titled “Failures and diagnostics”413onPOST /mcp: request body over the 1 MiB implementation limit (MAX_BODY, real). Reduce the request only in ways that preserve its meaning: use the supported references to a prepared case, remove genuinely redundant content, or split independent objects. Do NOT split one logically connected case into separate computations without established equivalence:A ∧ B → Cevaluated on{A, B}yieldsC, while two separate runs on{A}and{B}may not — and in models with exceptions and conflicts the effect of splitting is even less obvious.ANSWERS_TOO_LARGE: Lens response over 32 MiB (real,publication.rs).BODY_SIZEfrom other services: response over 4 MiB (real,service_client.rs).SERVICE_CONFIGwithhttps_required: a service URL that is not HTTPS to a non-loopback host (real). Fix the URL; there is no bypass flag.- Oversized journal datagram: resent without bodies with
MCP_TRUNCATED=oversize(real). The record survives; the content does not — do not treat the journal as a backup.
Support boundaries
Section titled “Support boundaries”- Retention of journal records is the host’s policy (journald
MaxRetentionSec, log rotation): the server sets no TTL and runs no cleanup job. Retention of prepared/published Lens documents is the answers service’s behavior (24 hours frozen, explicit revoke). - Backups cover the inputs the operator owns: case directories,
law.toml/law.lock, and the journal archive. There is no server database to dump. - The MCP host never deletes caller data: cleanup means the
operator’s retention policy plus
law_revoke_answerfor published documents. - “Secure” in this article means only: confined reads (root containment), no silent copies (stdio journals nothing; each network leg needs an explicit URL + token), and named storage places. It does not mean encryption at rest — that is the host’s disk policy.
Next step
Section titled “Next step”- Article 09 (Logs, audit trail, and decision journals) for what exactly lands in each journal record and what is redacted; article 10 (Runtime filesystem isolation) for directory rights and the Arxo-vs-external-network boundary in full.
Documentation for Arxo. Writings — blog.arxo.io.
Anonymous visit counts on stats.arxo.io, no cookies.