# Playbook — Insider or compromised supplier: find the observation that separates them

Hold two incompatible explanations over one set of facts, identify which evidence actually discriminates between them, and test what happens to the conclusion when a decisive source is withdrawn.

## What you need

- Docker 24 or later
- Python 3.9 or later
- About 3 minutes

## 1. Start a disposable Corrobore

```bash
mkdir -p .corrobore-tls .corrobore-secrets
printf '%s\n' 'change-me' > .corrobore-secrets/http-token
openssl req -x509 -newkey rsa:2048 -sha256 -nodes \
  -keyout .corrobore-tls/server.key -out .corrobore-tls/server.crt \
  -days 30 -subj '/CN=localhost' \
  -addext 'basicConstraints=critical,CA:FALSE' \
  -addext 'keyUsage=critical,digitalSignature,keyEncipherment' \
  -addext 'extendedKeyUsage=serverAuth' \
  -addext 'subjectAltName=DNS:localhost,IP:127.0.0.1'

docker run --rm -d --name corrobore-playbook \
  -p 127.0.0.1:8080:8080 \
  -e CORROBORE_STORAGE_MODE=ephemeral \
  -v "$PWD/.corrobore-secrets/http-token:/run/secrets/corrobore-http-token:ro" \
  -v "$PWD/.corrobore-tls/server.crt:/run/secrets/tls.crt:ro" \
  -v "$PWD/.corrobore-tls/server.key:/run/secrets/tls.key:ro" \
  ghcr.io/estance-labs/corrobore:latest

curl --insecure -H 'Authorization: Bearer change-me' https://127.0.0.1:8080/health/ready
```

## 2. Install the notebook dependencies

```bash
pip install requests
```

## 3. Run the notebook

```bash
jupyter lab notebook.ipynb
```

The notebook loads `dataset.json` from the same directory. Keep the three files together.

## 4. What to observe

1. Both branches assume the same five base facts; neither holds a private copy.
2. One observation is confirmed by both branches and therefore separates nothing, even though it is true and relevant.
3. Scoring on discriminating evidence only produces a different picture from counting every confirmation.
4. The branch that is ahead cannot close the case by erasing the other: `preserve_disagreements: false` is refused.
5. Withdrawing the decisive forensic record re-scores the branches instead of requiring the analysis to be rebuilt.

## 5. Change one thing and re-run

- Add a prediction to the insider branch that the ASN observation would confirm, and watch the discrimination flip.
- Make `observation--no-badge` non-discriminating and see whether the supplier branch still leads.
- Apply the approved consolidation with `preserve_disagreements: true` and check what happens to the losing branch.
- Add a third world for an unrelated third party and see how many observations still discriminate.

## Boundaries

- The exfiltration, the supplier and the forensic records are synthetic.
- Branchable worlds, copy-on-write overlays, cross-branch scoring and the resolution ledger are `graph-core` primitives with no HTTP route in this release.
- Worlds here are records and branch membership is a relationship, which reproduces the semantics but not branch isolation: nothing stops a client writing into a branch it does not own.

## Tear down

```bash
docker rm -f corrobore-playbook
```

---

Documentation: https://docs.corrobore.org — Source: https://github.com/Estance-Labs/corrobore
