> ## Documentation Index
> Fetch the complete documentation index at: https://docs.omegas.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Continuity security model

> How Continuity reads hostile filesystems, redacts credentials in five layers, and imports bundles as untrusted input.

This page condenses the project's threat model. The full version, including the
out-of-scope list and the private reporting channel, is
[SECURITY.md](https://github.com/OmegaAgent/continuity/blob/main/SECURITY.md)
in the repository.

## Reading is defensive

* Source files are opened read-only, with `O_NOFOLLOW`, and re-checked for
  change while being read.
* Symlinks get one of three outcomes: resolved inside a declared root, recorded
  as crossing between roots, or refused and listed. Never a silent skip.
* Never-export rules keep whole classes of data out of any artifact: account
  and billing identity, machine fingerprints, trust decisions, OAuth locks,
  transcripts, history.

## Redaction runs as five layers

The results are unioned, so a value caught by any layer is redacted:

1. Declared secret positions, per surface.
2. Key names.
3. Clean-room provider patterns.
4. Entropy at declared sinks.
5. A deep walk of every parsed leaf, with one bounded decode.

A false positive costs a span, never a file. Recall is measured rather than
claimed: the test suite seeds 212 fake credentials across every surface the
tool reads and asserts the per-tier percentage on every build.

Before any bundle reaches disk, the export gate re-scans the serialized bytes
with the full detector. A high-confidence hit aborts the write with exit code
`5` and nothing is written. There is no `--include-secrets` and no second
"complete" file.

<Note>
  **The honest limit** — shapeless high-entropy secrets with nothing naming them
  are caught only by position. Detection is defence in depth, not a guarantee;
  read a bundle before you share it. The redaction report tells you exactly what
  was found, the class assigned to each value, and the confidence.
</Note>

## Imported bundles are hostile input

Entry names are canonicalized and re-checked on read. Traversal, case-fold
collisions, duplicate entries, count and size bombs and tampered digests are
refused with distinct exit codes rather than repaired.

The import path is built so that consent is specific and revocable:

* Nothing is applied without a recorded consent against a specific rendered
  diff.
* Permission rules are additions; importing rule 3 resolves to an append and
  can never overwrite yours.
* Everything executable lands written but inert, in the runtime's own disabled
  idiom: `"disabled": true`, `enabled = false`, a `hooks_disabled` block, no
  execute bit. `enable` is a separate act that re-verifies the content hash
  recorded at import.
* Writes are staged at `0700`, snapshotted, fingerprint-re-verified immediately
  before each write, made through `O_NOFOLLOW | O_EXCL` temp files plus
  `rename`, and rolled back in full on any failure.

## What the tests hold down

The named release gates each pin one property, and a failure names the property
that broke: `gate:purity` (no I/O modules in the core), `gate:secrets` (the
seeded-credential recall floor), `gate:network` (the stubbed-network cycle),
`gate:adversarial` (hostile bundles), `gate:noop` (`diff` leaves the target
home byte-identical), `gate:compat`, and `gate:cutover`. Every test runs
against a committed fake home; nothing in the suite reads a real `~/.claude`,
`~/.codex` or `~/.claude.json`.
