Data handling

What Abhed stores, where it lives, how long it lives, what an operator can do about it, and who else touches data for the hosted console.

What Abhed stores

From internal/store/schema.sql, on the Postgres storage driver:

TableContents
sessionsOne row per agent session: tenant, user, workspace, model, the opening prompt, turn/token counts, cost, terminal reason
eventsEvery event in a session, append-only: tool calls, tool output, model responses, approvals and refusals — tagged trusted or untrusted per event
checkpointsThe content of a file immediately before the agent changed it, keyed to the event that changed it — this is what /undo reads
modelsThe registry of configured model endpoints and their capability profile
access_grants / access_eventsWho requested and holds console access, and the append-only history of how that changed

Accounts (username, email, tenant, groups, bcrypt password hash) are stored either in this same Postgres database or, without storage.driver: postgres configured, in <workspace>/.abhed/users.json mode 0600 (docs/ops/enabling-auth.md, "Where accounts live").

Uploads are files the agent reads or writes inside the session workspace — on the hosted console this is the container's workspace volume (deploy/run.sh's ABHED_VOLUME), not a host path. They are not a separate store; they are ordinary files in that workspace, and their content that passes through the agent loop is captured in events as tool output like anything else the agent reads.

Where

Self-hosted: wherever the operator points storage.dsn. Hosted console: a Postgres container on the operator's own machine (deploy/run.sh's abhed-db container, DB_VOLUME), with no published port — reachable only from the container network, never the LAN or the host (deploy/run.sh comment: "No published port").

Without the Postgres driver configured, sessions and events live in memory and do not survive a restart at all (internal/sitecheck/claims_test.go's TestDurabilityClaimsNameTheDriver pins this exact distinction: "accounts survive... transcripts survive... postgres... default... they do not").

Retention

Indefinite by default. Nothing in internal/store/schema.sql expires a row. The schema comment says retention is "handled by dropping partitions or by a privileged archival role, never by mutating rows in place" — that mechanism is not implemented in this repository today; there is no scheduled job that drops old partitions. Rows persist until an operator does something about it at the database level.

Deleting a session marks it; the rows stay. Schema version 3 in internal/store/schema.sql adds sessions.deleted_at and deleted_by. The comment is explicit about what this does and does not do: "Events are append-only by trigger, so a delete cannot remove the transcript rows and does not try. It marks the session; every read path treats a marked session as absent. The rows remain for the audit the deployment promised, reachable only by someone with the database, never through the API again." A deleted session is gone from the console and the API; it is not gone from the database.

Access grants and revocations are permanent, by design. Revoking access disables the account rather than deleting it, "so the record of what happened survives — that is the point of an audit log" (docs/access-policy.md, "How revocation works"). access_events is append-only by trigger, same as events.

What the operator can export or delete

Subprocessors — hosted console at abhed.zybuu.com

Zybuu is a one-person company (docs/vision.md), and the hosted console runs on the founder's own hardware. Stated plainly, per this folder's convention:

SubprocessorWhat it handlesWhere documented
CloudflareDNS and the zybuu.com zone; Cloudflare Pages hosts the marketing site and generated docs; the tunnel/reverse-proxy path carries traffic to abhed.zybuu.comdeploy/GO-LIVE.md (DNS record, Pages publishing, the docs Worker)
ResendTransactional mail: access-request acknowledgements, invite delivery, revocation noticesdeploy/GO-LIVE.md ("The homepage form"), internal/server/admin.go's mailRevocation
The founder's own hardwareRuns the console, the Postgres database, and the model the console's agent usesdeploy/GO-LIVE.md: "The site is up only while this Mac is awake and online"; docs/access-policy.md: "that is a model running on the same machine, so prompts do not leave it"

No other third party receives console data. There is no analytics vendor and no tracking (docs/access-policy.md: "Nothing is sold, and there is no analytics or tracking").

Self-hosted deployments

No subprocessors. A customer running Abhed on their own infrastructure — laptop, private datacenter, or air-gapped rack — sends data nowhere but the model endpoint they themselves configure (docs/vision.md: "It runs where the data is... It runs any model... Changing vendors is a line of config"). Zybuu has no access to a self-hosted deployment's data, database, or logs unless the operator explicitly shares them (for example, to report a bug).