EVD-02 · WITNESS READING · SAMPLE READOUT

What the readout looks like before you pay for one.

The readout below is the full Witness Reading format, produced by the real recorder - Witness v0.3 - against a synthetic estate of four MCP servers and four principals, because one studio does not have four of each to show you. The estate is invented; the records, the report and the verification are not. At the end, the same instrument on our own estate, with the finding it caught here. Download either export and run witness verify on it yourself.

COVER PAGE

Scope and record.

A readout states the scope, the recorded calls and the hash-chain check. That check establishes internal consistency, not identity, origin, completeness or an independent timestamp. Call counts here come from the export.

IN SCOPE

4 servers · 4 principals

postgres-prod · github · slack · filesystem

  • svc-analytics - declared, not verified
  • svc-release-bot - declared, not verified
  • svc-oncall-agent - declared, not verified
  • m.okafor - declared, not verified

RECORDED

27 tool calls

4 server-reported errors · 1 unresolved · 22 reported successes.

  • 4 / 4 HASH CHAINS VERIFIED · 0 BROKEN LINKS
  • FULL ARGUMENT AND RESULT PAYLOADS HASHED
  • PLAINTEXT SUMMARIES ALLOW-LISTED PER SERVER: repo, path, channel

FINDINGS

Six findings, ranked, each with its evidence.

These synthetic findings combine tool records with the scenario's permissions and supporting context. Server responses alone do not independently prove what changed in a target system.

F1HIGHfilesystem · m.okafor via cursor

A developer's coding agent read /srv/app/.env, attempted /home/deploy/.ssh/id_ed25519, and was denied on /etc/shadow. The filesystem server is mounted at / for an agent whose job is one application directory.

Fix. Scope the filesystem server to /srv/app; move secrets out of files the agent can reach.

F2HIGHpostgres-prod · svc-analytics via claude-code

Five queries from an analytics principal, one refused by the database as permission-denied. Query text is hashed, not stored; the refused statement is identified from the database's own log in the interview. Either way, an analytics credential is being used beyond a read-only grant.

Fix. Issue a read-only role for svc-analytics; alert on any denied statement from an agent principal.

F3MEDIUMgithub · svc-release-bot via claude-code

The release bot merged a pull request in acme/platform and attempted a merge in acme/infra, which was refused. The token is repo-wide when the approved scope was one repository.

Fix. Fine-grained token limited to acme/platform; merge only via a protected-branch rule that requires a human review.

F4MEDIUMslack · svc-oncall-agent via claude-desktop

The on-call agent posted to #general (approved scope: #incidents), looked up an executive by email, and attempted to read #exec-private, which was refused.

Fix. Restrict the bot's channel allow-list to #incidents; remove users:read.email.

F5LOWfilesystem · list_directory /mnt/nfs/backups

One call never received an answer: the server exited after 370 ms. Witness recorded the call as unknown, not as success. A retry loop on the agent side would have masked this.

Fix. Timeout and retry policy on the harness; alert on unknown outcomes.

F6NOTEAll four principals

Every principal is declared by the harness config (--as) and none is cryptographically verified. Each principal field states verified: false. Identity proof is outside this record and the reading.

Fix. Decide whether declared identity is acceptable for your audit posture before the next review.

REMEDIATION PLAN

What to do Monday.

Ordered by risk removed per day of work. Estimates are what engineering can act on the same week; you can take the plan to your own team or to us.

#ActionOwnerEffortCloses
1Scope filesystem and GitHub tokens to the approved paths and reposPlatform2 daysF1 F3
2Read-only database role for agent principals; deny-alertingData1 dayF2
3Slack app scopes and channel allow-listIThalf a dayF4
4Harness timeout/retry policy; keep the recorder runningPlatform1 dayF5
5Decision: declared vs verified principalsSecurity leadreadoutF6

EVIDENCE EXPORT

The files you keep.

Three files, all yours. The report is generated by witness report; the sessions file is the raw hash-chained record; the checkpoints file is the chain heads, chained again.

DOWNLOAD

Export bundle

Check chain consistency: git clone https://github.com/dark-vector-cognition/witness && node witness/bin/witness.mjs verify sessions.jsonl

ONE RECORD, VERBATIM

A recorded request for a private key

This tool-call record contains the request, path summary, declared principal, client and hash chain. It does not prove the file was read or contain its contents.

{
  "v": "0.1",
  "seq": 12,
  "ts": "2026-09-12T23:37:44.772Z",
  "session": "s_ac5761f3",
  "event": "tool_call",
  "rpc_id": 15,
  "tool": "read_file",
  "args_sha256": "8cbae1d71d242fe96189b44ab7a97a23a3a94f68dfde52e9625d19d5a904b4ea",
  "args_bytes": 39,
  "args_summary": {
    "path": "/home/deploy/.ssh/id_ed25519"
  },
  "actor": {
    "client": "cursor",
    "version": "1.4.2",
    "protocol": "2025-06-18"
  },
  "principal": {
    "as": "m.okafor",
    "source": "flag",
    "verified": false
  },
  "server": {
    "name": "filesystem",
    "cmd_sha256": "02a751c263674851df7fab225085d4241ce610bc049b22b5ac5809c9deaba85e"
  },
  "prev": "8099faf071d4e216ffd1f182af317b662b21f8930e2d528e5dc4fd6c1160ef57",
  "hash": "fd9086914301b6b3c42363db1a2643a4a6f5f87e03c86930e98e162931c458d5"
}

REPORT.MD, VERBATIM

# Witness report  -  last 1d

Generated 2026-09-12T23:37:47.076Z · log /sessions/rcw-013spsibfthc6kbi23qcnnp4/wh-sample/log

| Sessions | Servers | Principals | Tool calls | Errors | Unanswered | Broken chains |
|---|---|---|---|---|---|---|
| 4 | 4 | 4 | 27 | 4 (15%) | 1 | 0 |

## Calls by tool

| Tool | Calls | Errors | Open | p50 ms | p95 ms |
|---|---|---|---|---|---|
| read_file | 5 | 1 | 0 | 1 | 15 |
| query | 5 | 1 | 0 | 0 | 13 |
| conversations_history | 3 | 1 | 0 | 0 | 0 |
| merge_pull_request | 2 | 1 | 0 | 1 | 1 |
| write_file | 2 | 0 | 0 | 1 | 1 |
| list_directory | 2 | 0 | 1 | 370 | 370 |
| chat_postMessage | 2 | 0 | 0 | 14 | 14 |
| search_issues | 1 | 0 | 0 | 14 | 14 |
| get_pull_request | 1 | 0 | 0 | 3 | 3 |
| create_pull_request | 1 | 0 | 0 | 0 | 0 |
| list_commits | 1 | 0 | 0 | 0 | 0 |
| create_issue | 1 | 0 | 0 | 1 | 1 |
| users_lookupByEmail | 1 | 0 | 0 | 0 | 0 |

## Calls by server

- **filesystem**  -  9
- **github**  -  7
- **slack**  -  6
- **postgres-prod**  -  5

## Calls by declared principal

- m.okafor  -  9 _(declared, not verified)_
- svc-release-bot  -  7 _(declared, not verified)_
- svc-oncall-agent  -  6 _(declared, not verified)_
- svc-analytics  -  5 _(declared, not verified)_

## Integrity

- ✓ 4 chain(s) verified, no broken links

Peak hour (UTC): 23:00 with 27 calls.

_Arguments and results are hashed, never stored. See SPEC.md._

FINDING F6, ON OUR OWN ESTATE · NOT A SAMPLE

Config drift, caught on our own estate.

The readout above uses a synthetic estate, because one studio does not have four servers and four principals to show you. This section does not. It is finding F6 - config drift - found on DVC's own machine by DVC's own recorder, with every number read from the export at build time.

RECORDED

25 tool calls

1 session · 1 server (desktop-commander) · 1 declared principal.

  • 54 RECORDS · 1/1 CHAINS VERIFIED · 0 BROKEN LINKS
  • 3 ERRORS (12%) · 0 UNANSWERED
  • ARGUMENTS HASHED, NEVER STORED - NO FILE PATH APPEARS IN ANY RECORD

THE FINDING

The recorder was not recording.

The wrapped config on this machine pointed at a Node binary that a Homebrew upgrade had broken. The server never started, so nothing was recorded - and an empty log looks exactly like a quiet estate. The config on the machine had drifted from the config in the repository, and nothing noticed until someone asked the record a question. It is fixed; the recorder is running.

Read the write-up →

PER TOOL · READ FROM THE EXPORT

The session average hid the only interesting number.

Aggregate error rate was 12% - unremarkable. Every failure was one tool. This is why a Witness Reading reports per tool, not per session.

ToolCallsErrorsError ratep50 msp95 ms
read_file12325%62529
list_directory600%22
get_file_info300%22
get_config100%1818
get_usage_stats100%11
list_processes100%169169
list_sessions100%33
  • sessions.jsonl · the real export, 54 records. The principal label is redacted to operator@dvc and the chain resealed with Witness's own sealing code, so it still verifies.

Check the redacted export's chain consistency: git clone https://github.com/dark-vector-cognition/witness && node witness/bin/witness.mjs verify sessions.jsonl

WITNESS READING · SCOPED · LOCAL RECORDS, REVIEWED EXPORTS

Your agents. Your records. Read.

Thirty minutes to confirm scope and dates, then a fixed price in writing. If a Witness Reading is not the right instrument for your estate, we will say so on the call. A recorder that stopped recording, like ours did, is what Witness Rollout fixes.