What coven-github durably retains, what it never retains, how it is redacted,
and how it is deleted — for both self-hosted operators and hosted OpenCoven.
Companion to Security Model and the
Durable task store.
Retain enough to debug, bill, support, and satisfy customer trust — never raw
secrets, credentialed URLs, private repository contents, or unfiltered agent
transcripts. Everything the adapter writes to durable storage passes through
redaction first, and a test (no_raw_token_survives_in_durable_stores) scans
every adapter-generated stored field to prove no token or secret pattern
survives.
| Class | Retained? | Where | Notes |
|---|---|---|---|
task_metadata |
Yes (tenant-scoped) | tasks |
id, installation, repo, familiar, kind, state, timestamps. |
publication_metadata |
Yes | tasks |
branch, PR number, Check Run URL. |
agent_result |
Yes, after redaction | tasks.summary, task_attempts.detail |
The result envelope is sanitize_result-scrubbed before any persist/publish. |
delivery_metadata |
Yes | webhook_deliveries |
delivery id (idempotency), event/action, installation, repo, payload hash only — never the body. |
audit_events |
Yes | api_audit, table states below |
See Audit events. |
memory_activity |
Opt-in, retention-limited | memory_activity |
Per-installation; see issue #6. |
logs / transcripts |
Not persisted by the adapter | — | Streamed/redacted only; durable transcripts are out of scope until opt-in retention is designed. |
repo_checkout |
Never after task cleanup | ephemeral workspace | The per-task workspace is deleted after every task (success or failure); the container backend also removes the container (--rm). A cleanup failure that would leave a checkout on disk is surfaced and audited (workspace_cleanup_failed), never swallowed. |
container_logs |
Not persisted | — | The container backend (#5) captures no stdout/stderr into any store; only the redacted failure detail reaches task_attempts.detail. |
tokens / secrets |
Never | — | The brief is tokenless (#4); the git token travels to the runtime by environment name only (never in argv or container-inspect output); results, comments, Check Runs, and stored fields are redacted. |
sanitize_result scrubs every free-text field of the result envelope (summary,
PR body, branch, commit messages, review findings and evidence) before the
adapter stores or publishes anything; error detail written to
task_attempts.detail, Check Run summaries, and status comments passes through
redact too. Redaction replaces exact live token values and GitHub token
patterns (ghs_/ghp_/gho_/ghu_/ghr_/github_pat_) and
x-access-token: URL credentials. User-authored content (issue/comment bodies)
is deliberately not pattern-scrubbed — a maintainer may legitimately quote a
token-shaped string — so it is excluded from the durable audit-scan surface.
| Event | Recorded in |
|---|---|
| Webhook received / routed / ignored | webhook_deliveries.routing (task:<id> / ignored:<reason>) |
| Task queued / claimed / running / terminal | tasks.state + task_attempts |
| API read (task list, memory inspect, usage) | api_audit |
| Memory read/write decisions | memory_activity (with the adapter's accept/reject verdict) |
| Memory revocation | memory_revocations |
| Tenant data deletion on uninstall | api_audit (delete_on_uninstall, with counts) |
Installation-scoped tokens are minted per repository and role (#4); their permission class is deterministic from the role, and the token value is never logged or stored.
- Delete on uninstall — an
installationdeletedwebhook purges that tenant's memory (activity + revocations) and task artifacts (tasks, attempts, deliveries), and records an auditeddelete_on_uninstallentry. Idempotent: a redelivery finds nothing left. - Task-history retention —
[storage] task_retention_daysruns a periodic server sweep that deletes terminal (completed/failed/superseded) tasks and their attempts past the horizon. In-flight tasks are never expired. - Memory retention —
[memory] retention_dayssweeps memory audit rows; revocations are never expired (that would un-revoke memory). See #6. - On-demand revoke —
POST /api/github/memory/revoke(tenant-scoped).
| Self-hosted | Hosted OpenCoven | |
|---|---|---|
| Store | Local SQLite; operator owns the volume and retention | Managed, tenant-isolated |
| Task API auth | open mode allowed for local dev |
Tenant-scoped tokens, fail-closed (#3) |
| Retention | Optional (task_retention_days / retention_days) |
Set by tier/policy |
| Memory | Operator-managed, off by default | Opt-in, per-installation, revocable |
| Worker isolation | May run on host | Container-isolated per task (#5) |
The worker runs each task in a per-task workspace, then deletes it — on every
path, success or failure. In the container backend (#5) the task runs in a
fresh container removed by --rm (and killed by name on timeout), with a
read-only root, dropped capabilities, resource limits, and only the workspace
mounted; the git token is forwarded by environment name, so it never enters
argv or docker inspect. If workspace removal ever fails while the checkout is
still on disk, the worker logs it loudly and records a workspace_cleanup_failed
audit entry rather than silently leaving private code behind.
- A unified append-only audit-event log (the tables above already provide the equivalent records; a single stream is a possible future consolidation).
- Durable, opt-in agent transcripts with their own redaction/retention policy.