Access audit
CipherFS records logical access and actual commits in Core, and separate delivery observations at HTTP, local API, S3 and FUSE boundaries. The desktop Access panel queries by FileId or DeviceId and shows retention coverage, writer health, backlog and loss. The current entry integrations are implemented; the default mode and boundary of each entry are exposed by operational status.
Modes and boundaries
| Entry | Default | Identity and observed boundary |
|---|---|---|
| Core, Rust, CLI, C/Python/Go, desktop | off | Local process; Core operation and return/commit boundaries |
| HTTP JSON | required | Verified session public identity; Core plus response-body handoff |
| S3 | required | Registered identity after SigV4 verification; Core plus plaintext body handoff |
| Private local API | off | Verified protected endpoint credential public identity; Core plus body handoff |
| Standalone FUSE | off | Actual callback UID/GID/PID when supplied; Core plus reply handoff |
| Daemon mount | best effort | Same OS callback observations |
| Embedded background work | off | System identity and maintenance facts |
| Daemon background work | best effort | System identity and maintenance facts |
off makes no audit guarantee. best_effort attempts every event and reports loss; gap counts are lower bounds across crashes. required rejects business access when intent cannot persist and keeps commits atomic with audit facts. A failed finish can follow a proven business commit: inspect the structured known receipt before retrying a mutation. HTTP returns AUDIT_UNAVAILABLE with status 503; bindings use error class 32. A writer fault affects required readiness while operational diagnostics remain available.
A denial that races the signing owner's shutdown keeps its unauthorized response and enters the existing bounded denial summary. Required audit failures with a live owner still return unavailable; this exception admits no business access.
Actors never retain session tokens, passwords, headers, paths or body contents. Unknown authentication remains an unknown actor and does not resolve a requested file. OS observations do not authenticate a named executable. Counts at different layers must not be added. FUSE delivery remains unknown because its reply has no kernel receipt; no delivery record proves consumption by a person.
Query and configure
Use the normal password source or an already-running local owner. IDs are canonical public identities, not paths.
cipherfs audit status --vault "$VAULT_PATH"
cipherfs audit config --vault "$VAULT_PATH" > audit-config.json
cipherfs audit file "$FILE_ID" --vault "$VAULT_PATH" --limit-count 100
cipherfs audit device "$DEVICE_ID" --vault "$VAULT_PATH" --limit-count 100
cipherfs audit set-config --vault "$VAULT_PATH" --input-file-path audit-config.json
Edit the complete configuration before set-config. mode_overrides maps entry names such as http, bindings or daemon_mount to off, best_effort or required; omitted entries retain the defaults above. Positive finite budgets include event/queue/spool/segment sizes, flush/shutdown timeouts and independent audit_retention_days. Invalid budgets or a conflicting active operation reject the update.
Move observations and transaction commit facts each have a finite limit of min(4096, max(1, queue_max_bytes / 256)) per operation or transaction. Split larger required batches: exceeding the transaction fact limit rolls that transaction back. Best effort continues with visible loss and omits a single target from an incomplete summary.
Authenticated JSON routes are relative to /api/v1:
| Method and route | Operation |
|---|---|
GET /audit/status | Operational status and declared entry coverage |
GET or PUT /audit/config | Read or replace the complete local configuration |
POST /audit/query | File/device query or continuation |
POST /audit/flush | Seal pending events to local encrypted spool |
DELETE /audit/cache | Clear only the local encrypted query cache |
POST /audit/cleanup | Explicit bounded cleanup with store/device/limit selection |
A query body has {"op":"query","query":{"file_id":"<FileId>","limit_count":100}}; use device_id for a device query. Optional time filters use from_epoch_ms and through_epoch_ms; result is a finite result name. To continue, submit {"op":"page","cursor":<next>,"limit_count":100} using the returned next object. CLI audit page takes --snapshot-id, --offset-count and --limit-count.
Every source object is authenticated before filtering. Conflicting sequence objects, internal gaps, invalid signatures and exhausted budgets return errors. Coverage reports missing retained prefixes and always leaves remote_tail_confirmed false. Pages come from an encrypted local snapshot, capped at eight snapshots/64 MiB and five minutes; expiration or cache clearing requires a new query. The independent Python reader verifies the public CFSAUD01 vector using the epoch/device key domain.
Storage and retention
Audit objects use store prefix a/ and never enter the shared index or ordinary content GC. The private spool contains final encrypted, signed segments. All configured stores must positively confirm an object before the local spool is removed. Seal revokes key copies; unfinished attempts recover as interrupted/unknown, and shutdown timeout reports pending work.
After stopping admission, shutdown drains live attempts, queued events and deferred returns. Once all three are empty, it resolves orphaned durable starts in bounded batches within the existing shutdown deadline, using the same OperationRecovered events as startup recovery. These records preserve proven commitment and mark result and delivery as unknown; a lost best-effort completion never becomes a successful operation. Live attempts remain pending and can still cause shutdown to fail.
cipherfs audit cleanup --vault "$VAULT_PATH" --store-id "$STORE_ID" --device-id "$DEVICE_ID" --limit-count 128
Cleanup requires the backend's real delete permission and protects unpublished local segments. Minimum retention starts no earlier than local first observation and the latest authenticated segment/event time; a future time delays deletion. Changing file retention never deletes audit history. A successful deletion count means positive backend acknowledgment, not proof that physical provider storage was reclaimed.
The ADR records the design and FORMAT section 11 specifies the container, strict payload and local rows. Access bypassing these instrumented boundaries is outside the log.