Skip to content

Team audit / shared activity log — shared OR local, conflict-free

Your audit ledger records every gate decision, tool call, and durable write — who did what across the governed brain. By default that log is local. A team can optionally make it shared so everyone sees the team-wide who-did-what and why — on the team's own storage.

NO telemetry — nothing is ever phoned home

mokata sends no telemetry. Your audit log is never transmitted to mokata or Anthropic — there is no such endpoint anywhere in the code. A shared team log lives on your team's own managed Postgres (Supabase / Neon / Amazon RDS — just a connection string, the same BYO DB as team setup). The data is the team's, on the team's storage, full stop. mokata never stores the DSN secret — only the name of the environment variable that holds it.

Local is the default

Do nothing and your audit log stays local (.mokata/…/audit/ledger.jsonl), exactly as before:

mokata audit             # the local, append-only ledger
mokata audit --why       # a readable what + decision + why timeline (bounded)

Opt in to sharing

Sharing is opt-in and local-first. Turn it on in the committed config, and name the environment variable that holds your team's DSN (the same variable team setup uses, so memory, sessions, and audit resolve the same DB out of the box):

mokata config set settings.audit.shared true            # opt in (human-gated write)
mokata config set settings.audit.dsn_env MOKATA_PG_DSN  # the env-var NAME only (never the DSN)

export MOKATA_PG_DSN='postgresql://…@your-managed-host/db'   # the DSN lives in your env
pip install 'mokata[postgres]'                               # the optional driver

mokata team init      # provisions the shared schema (once, by one person) — see team setup

The shared log lives in a mokata-owned table that mokata team init provisions. Nothing else in mokata ever runs DDL, so publishing needs no CREATE rights — a DML-only role with SELECT, INSERT on mokata_audit_log is enough, and revoking UPDATE/DELETE makes the log append-only by grant. (Already ran team init for team mode? Then you're done — memory, sessions, and audit share the one schema.)

Publish your entries — mokata audit --share

mokata audit --share          # human-gated: approve publishing your new entries
mokata audit --share --yes    # scripted / non-interactive (still secret-scanned)

Publishing is the only moment data leaves your machine, so it goes through the same universal gate as every other outbound write:

  • Human-gated — you approve the publish; decline and nothing is written.
  • Secret-scanned — a secret anywhere in the payload is a hard block, even when approved.
  • Append-only + per-actor + namespaced — each entry becomes its own row tagged with who (the actor) and the repo namespace. Two teammates publishing at the same time each get their own rows and never clobber each other — conflict-free by construction.
  • Idempotent — only your new entries publish; re-running when nothing changed is a clean no-op.
  • The DSN secret is never stored — only the env-var name lives in the manifest.

Attribution (who) comes from MOKATA_ACTOR, else USER / USERNAME — mokata adds no auth system of its own; it records who, human-gates the write, and audits it.

Read the team-wide log — mokata audit --team

mokata audit --team              # who-did-what / why across ALL teammates (read-only)
mokata audit --team --tail 20    # bounded to the most recent entries

The read spans the shared log for this repo — every actor's entries, oldest first, each line prefixed with who did it. It is read-only and touches nothing local.

Inside Claude Code

Everything is reachable in-harness (no dropping to a terminal):

  • audit MCP read tool with team=true → the shared team-wide who-did-what.
  • audit_share MCP write tool → publish your entries. Propose-only: it returns a proposal_id and writes nothing until you run mokata approve <id> in your terminal, after which it commits through the WriteGate (a secret is hard-blocked even then). approve=true on the tool call commits nothing — the model cannot approve its own writes.

Degrade-clean

No driver installed, no DSN exported, or a shared schema that isn't provisioned yet? Sharing and the team read stay local with a clear message that names the failure and its fix — never a crash, and never a silent downgrade to a less-secure path (mokata doctor also reports what fell back to a floor this session, so a degrade can't pass for the real thing):

shared audit unavailable (… needs a DSN in $MOKATA_AUDIT_PG_DSN / $MOKATA_PG_DSN …) —
your log stays LOCAL (degrade-clean). Export $MOKATA_PG_DSN and `pip install 'mokata[postgres]'`
to publish.

What you get

Shared visibility into your team's own governed activity — who set which guardrail, which gates fired, what was shipped — with zero telemetry and zero trust trade-off. It's your data, on your storage, conflict-free, and reversible (turn sharing off with mokata config set settings.audit.shared false).