Chio/Docs
LOGIN · JOIN

Investigate a Session

Reconstruct one operation from the records its owners retained, and close the incident with what is established and what stays unknown.

Guide chio@5f63e6e

On this page

An investigation ends in a bounded statement about one operation: what happened on the observed path, which signed evidence supports it, what remains unknown, and which owner repairs it.

A caller's error, a signed decision, and a resource observation describe different parts of the same attempt. Preserve all three, then join them through the original operation's identities before you call it refused, completed, or unresolved.

Start
Evidence ownersChoose a boundary.
kernel hostresource ownerrequestdispatchresultreleasereplayeventscontainaKdρgcallerkernelexecutor or providerrelease checkpointactive defensekernel hostresource ownerrequestdispatchresultreleasereplayeventscontainaKdρgcallerkernelexecutor or providerrelease checkpointactive defense

The kernel establishes what it decided and captured

Retain capability, operation key, admission operation ID, and capture. The record that establishes it is the original decision, the dispatch record, and the retained authority.

One operation's evidence owners on either side of the host boundary, and the path that joins their records. Spacing carries no duration; guards, budget holds, and the receipt store are left out.

1. Name the original operation

Record the request, authenticated caller, session, tool, destination, and approximate time. Retain the original operation key and request commitment where the execution path provides them, and locate the host that admitted the work and the resource owner that could have executed it.

Follow the operation through admission, dispatch, output, and recovery. A denied call, an evaluator failure, and a lost provider response look alike to the caller and need different repairs, so find the boundary that produced the symptom first.

2. Export the original receipts

Use the installed chio and jq, with administrative read access to the deployment's receipt database. Set the original store and the tool-server ID under investigation, and export into a new private directory, which keeps evidence already gathered intact.

Terminalbash
set -eu
umask 077
: "${CHIO_RECEIPT_DB:?Set the original deployment receipt database path}"
: "${CHIO_TOOL_SERVER:?Set the tool-server ID under investigation}"
: "${CHIO_INCIDENT:?Set a new private incident directory}"
test ! -e "$CHIO_INCIDENT"
mkdir -m 0700 "$CHIO_INCIDENT"
chio --receipt-db "$CHIO_RECEIPT_DB" receipt list \
  --admin-all --tool-server "$CHIO_TOOL_SERVER" --limit 100 \
  > "$CHIO_INCIDENT/receipts.jsonl" 2> "$CHIO_INCIDENT/selection.stderr"

You should see one receipt per line in receipts.jsonl. When selection.stderr prints next_cursor=<seq> total_count=<n>, repeat the query with --cursor set to that value under the same database, scope, filter, and limit, and save each page and its stderr separately. Continue until no next cursor remains, as receipt pagination describes: a partial export cannot show that an absent receipt never existed.

3. Verify the export under an independent key

Take the signer from trusted configuration, never from a key copied out of the suspect artifact. The host owner supplies the original kernel public-key file from independent configuration.

Terminalbash
set -eu
: "${CHIO_KERNEL_PIN:?Set the independently retained original kernel public-key file}"
chio receipt verify --json --input "$CHIO_INCIDENT/receipts.jsonl" \
  --trusted-kernel-pubkey "$CHIO_KERNEL_PIN" \
  > "$CHIO_INCIDENT/verification.json" 2> "$CHIO_INCIDENT/verification.stderr"

You should see verification.json. Keep the input and any error: a failure is incident evidence. chio receipt verify checks original signatures, the signer pin, and action hashes offline; policy re-evaluation, log inclusion, and the external provider are separate questions.

A valid signature and relevance to this operation are two checks, as verify security evidence explains. Check tenant, agent, session anchor, authentication epoch, capability, request commitment, and tool identity. For caller delivery, add the executor pin and original delivery binding; for a confined tool, compare the launch's manifest, executable, and descriptor commitments.

Once signatures and bindings pass, write a separate reading aid. The signed JSONL stays unchanged, so each projected entry traces to its envelope.

Terminalbash
jq -c '{id, tool_server, tool_name, decision, receipt_kind}' \
  "$CHIO_INCIDENT/receipts.jsonl" > "$CHIO_INCIDENT/summary.jsonl"
Group a verified export without changing its originals

A grouping shows which tool and decision combinations dominate an export. Run it only on evidence collected under authorized access, with your verified, bounded export in place of incident/receipts.jsonl. jq -s loads the whole export into memory, so group large incidents page by page.

Terminalbash
jq -s '
  group_by([.tool_server, .tool_name, .decision])
  | map({
      tool_server: .[0].tool_server,
      tool_name: .[0].tool_name,
      decision: .[0].decision,
      count: length,
      receipt_ids: map(.id)
    })
' incident/receipts.jsonl > incident/by-tool-and-decision.json

The grouping is a navigation aid. It checks no signatures, recovers no omitted pages, and establishes no completion, and its counts describe only the collected pages and selected server. Follow a receipt ID back to its original envelope, verify it under the independent pin, and correlate its operation with dispatch and outcome state before assigning a cause. Sensitive request and result bodies stay in their access-controlled location.

4. Order the observations by what each owner can establish

The kernel records admission and capture, the executor reports its own work, and the provider or resource exposes the resulting state. Keep a working timeline beside the original artifacts, one entry per observation:

  1. Operation. The original operation identity the observation belongs to.
  2. Times. When the event occurred, if authenticated; when another component learned of it; when you collected the record.
  3. Source. The producing component and the original artifact reference.
  4. Fact. What that artifact establishes.
  5. Inference. Your hypothesis, kept in its own field so it stays distinct from signed observations as the incident changes hands.

Sort by cause as well as by timestamp. A receipt that references a prior operation or effect fixes an order that wall clocks miss; a late receipt can describe an effect that completed first, and an early timeout can precede a provider response that never reached the caller. Join observations through the original request and retained identities before you treat them as one sequence.

A provider object beside an unknown kernel outcome marks a missing reconciliation step; a denied admission beside a changed resource points to another effect path or a miscorrelated record. Keep both disagreeing observations, and investigate the boundary between them.

5. Classify the outcome by the boundary it reached

The last boundary the operation crossed decides what the observation means and where to look next.

Observed stateWhat it meansInvestigate next
Denial before dispatchThe selected path refused the operationThe exact guard, scope, or authority mismatch
Evaluator failureThe host reported failure; the effect may be unknownOriginal capture and executor state
Capture without outcomeThe external effect may have startedAuthenticated downstream status and the original ledger
Guarded release checkpointThe exact response can be replayedWhether delivery was retried, without re-execution
Partial response or rollbackSome containment work is unresolvedPer-effect adapter state and the valid lease owner

An evaluator failure stays distinct from a policy denial even when no output reached the client. The signed session report binds the failure observation and retains execution_outcome=unknown.

For an active-defense finding, inspect the versioned rule, group commitment, ordered event IDs, evidence digests, source receipts, and time interval. Compare event time with ingest time, and read detector-health records for lateness, eviction, or store failure. Follow the finding to its authorized plan and each requested, applied, failed, and rolled-back effect, and verify the affected-set commitment; a session-wide status can hide one remaining contribution. A failed publication walks these boundaries in order.

6. Trace one message across a cancellation

Use the stopped host from the containment rehearsal. The trace establishes whether worker sent cancel-effect-1 before cancellation and whether later refused work changed the mailbox. The native server is chio-ipc, its tool is send_effects, and the receipt's process metadata carries the original operation key.

Run the query from the extracted rehearsal directory. Supply the kernel public-key file the host owner retained, never a pin taken from the suspect receipt's kernel_key; a verification error stops the projection and keeps the export and its stderr.

Terminalbash
set -eu
umask 077
CHIO_STATE="$PWD/.chio/cancellation/host"
CHIO_INCIDENT="$PWD/incident-cancellation"
test ! -e "$CHIO_INCIDENT"
mkdir -m 0700 "$CHIO_INCIDENT"
chio receipt list --receipt-db "$CHIO_STATE/receipts.db" \
  --admin-all --tool-server chio-ipc --limit 100 \
  > "$CHIO_INCIDENT/original-receipts.jsonl" \
  2> "$CHIO_INCIDENT/selection.stderr"
# The owner supplies the original trusted key, independently of the export.
: "${CHIO_KERNEL_PIN:?Set the path to the independently retained original kernel public-key file}"
chio receipt verify --json --input "$CHIO_INCIDENT/original-receipts.jsonl" \
  --trusted-kernel-pubkey "$CHIO_KERNEL_PIN" \
  > "$CHIO_INCIDENT/verification.json" 2> "$CHIO_INCIDENT/verification.stderr"
jq -c 'select(.metadata.chio_process.operation_key == "cancel-effect-1") |
  {tool_server, tool_name, decision: .decision.verdict,
   operation_key: .metadata.chio_process.operation_key,
   dispatch_state: .metadata.admission_operation.projected_dispatch_state,
   state: .metadata.admission_operation.projected_state}' \
  "$CHIO_INCIDENT/original-receipts.jsonl"
Output
{"tool_server":"chio-ipc","tool_name":"send_effects","decision":"allow","operation_key":"cancel-effect-1","dispatch_state":"terminal","state":"completed"}

You should see one allow receipt, dispatch_state terminal and state completed, for the operation before cancellation. The projection omits receipt IDs and timestamps, which change per run; the original NDJSON stays beside it.

The refused call left no receipt, because authentication and cancellation refusals happen before kernel evaluation. Its absence from the query therefore shows nothing about whether a request reached the host. Confirm the rest outside the receipt store: the stopped mailbox store should hold the cancel-effect-1 row alone, and the later cancelled wire response belongs with the original evidence.

7. Route the repair and close with a bounded statement

Each missing fact belongs to the owner that can establish it; a general retry cannot create it.

  • An identity mismatch goes to the authenticated host and its authority configuration.
  • A captured effect with an unknown outcome goes to the original execution path, keeping the original attempt and holds while you reconcile that operation.
  • A missing release checkpoint goes to the output and release owner.
  • A partial response goes to the adapter and worker that own the outstanding contribution. For credential access followed by egress, join the rule's ordered event IDs and evidence digests to its finding, plan, and individual effect and removal records with the correlation and action inspector.

Keep captured authority attached to the original operation until its effect is reconciled. A fresh credential attempt, a refunded captured budget, or a resend hides the incident without resolving it; repair custody, authority, or store availability first, under valid serving fences. Quarantine recovery and key transparency take over when the failing boundary is theirs.

Before repair, restrict access to provider responses, decoy records, and sensitive request bodies; routine summaries cite commitments and artifact locations. Close with the bounded statement from the opening, naming the new work it authorizes and every alternate path outside your observation, so the next operator reads an incomplete history as incomplete.

Evidence by boundary

The identities and records each boundary of an operation contributes, for lookup during an incident.

Correlation identities

BoundaryIdentity to retainAuthoritative observation
Caller
Agent, tenant, session, epoch and original request
The authenticated host's accepted context and connection history
Admission and dispatch
Capability, operation key, admission operation ID and capture
The original decision, dispatch record and retained authority
Resource effect
Bound executor or provider attempt
Resource-owned state or authenticated status for that same attempt
Response and release
Retained result and release checkpoint
The exact guarded response authorized for replay
Detection and containment
Event, finding, plan and individual effect IDs
Authenticated event history and each adapter's applied or outstanding contribution

Observations in the cancellation trace

ObservationMeaningContinue
Process operation key and request commitment
Identify the frozen requested work and authenticated process
Compare the original request, connection, and selected capability, never an incident label chosen afterward
Admission operation ID, dispatch commit and projected state
Explain retained kernel lifecycle for this operation
Inspect the original store and ledger, and its provider attempt when the outcome is unresolved
Mailbox row cancel-effect-1
The owned native message was committed
Check the stopped mailbox store independently of the receipt projection
Later cancelled wire response
The later admission was refused before a new kernel receipt
Preserve its original response and verify the mailbox still holds only the first message
Response plan or partial removal
Containment has separate finding, plan, and effect identities
Join the exact finding and plan, then inspect each outstanding contribution

Timeline entries

Timeline entryEstablished by retained evidenceStill unresolved
Admission accepted
Original request satisfied the recorded admission decision
Whether dispatch later occurred
Capture committed
Original authority crossed the durable capture boundary
Whether the provider accepted the effect
Connection closed
Caller or host lost its transport observation
Whether the effect completed
Provider status obtained
Authenticated status for the bound original effect, if supported
Any behavior outside that status contract
Guarded release checkpoint found
Exact response is authorized for replay
Whether the first client received it

Keep event time and ingest time distinct for detector findings: a late collection time leaves the original event's rule window unchanged.

A failed publication, boundary by boundary

The reviewer reports that posting its summary for issue #417 to the pull request failed. Identify the original posting request and destination, then inspect the retained flow state and any bound declassification grant. If admission refused the transfer before dispatch, investigate the incompatible clearance or missing authority; the provider has no result to show in that case.

If capture committed, look for executor and provider evidence under that operation, because a client timeout cannot classify the result as denied. If the provider returned and output release failed, inspect the retained output, classification, and release custody before considering another call. If an exact guarded checkpoint exists, recover the original response and leave the post alone.

Finally, check whether active defense applied a restriction in the same interval. That response has its own finding, authorization, effects, and rollback history: lifting it settles nothing about the post, and a completed post says nothing about whether every containment contribution was removed.

Next: act on what the investigation established