Skip to main content

Audit & Compliance Reporting

Cocoon's backend proxy maintains an immutable audit log of every RPC call, recording the caller identity, the method invoked, and the outcome. This log is the primary tool for compliance officers, auditors, and regulators reviewing chain activity.

What Is Logged

Every JSON-RPC request that passes through the backend proxy (port 8546) is logged to a SQLite database (audit.db). Each log entry captures:

FieldDescription
timestampISO 8601 timestamp of the request
user_idUUID of the authenticated user (from session token)
ethereum_addressEthereum address of the caller
roleRole of the caller at the time of the call
methodJSON-RPC method name (e.g. token_transfer)
paramsRequest parameters (redacted for sensitive fields)
statussuccess, error, or blocked
error_codeJSON-RPC error code if the call failed
chain_tx_hashTransaction hash if the call produced an on-chain transaction
ip_addressClient IP address
note

Calls in AUTH_MODE=advisory where the caller has no valid session are still logged — they appear with user_id: null and role unauthenticated. This makes it possible to audit calls that bypassed authentication in development mode.

What Is Redacted

To prevent the audit log from becoming a source of credential leakage, certain parameter fields are redacted:

  • Private keys (any field named key, privateKey, signingKey)
  • Passwords
  • Raw UCAN delegation tokens (replaced with their CID)

Amounts, addresses, and method-specific data are never redacted — they are essential for compliance review.

Accessing the Audit Log

Via the Admin Dashboard

The audit log is accessible at http://localhost:3000/audit in the admin dashboard. It provides:

  • A searchable, paginated table of all audit entries
  • Filter by user, Ethereum address, method, status, and time range
  • Inline drill-down to view full request parameters for any entry
  • CSV export — export filtered results to a spreadsheet for external reporting

The dashboard audit view is role-gated: only users with the Admin, Compliance, or Auditor role can access it. Regulators access a separate, read-only view scoped to their jurisdiction.

Via the REST API

The backend proxy exposes audit query endpoints directly:

GET /api/audit

Query the audit log. Supports filtering and pagination.

Query parameters:

ParameterTypeDescription
addressstringFilter by Ethereum address
user_idstringFilter by user UUID
methodstringFilter by RPC method (exact or prefix match, e.g. token_)
statusstringsuccess, error, or blocked
fromISO 8601Start of time range
toISO 8601End of time range
offsetintegerPagination offset (default: 0)
limitintegerPage size (default: 50, max: 500)

Example — all blocked transfers in the last 24 hours:

curl "http://localhost:8546/api/audit?method=token_transfer&status=blocked&from=2026-04-12T00:00:00Z"

Response:

{
"entries": [
{
"id": 12345,
"timestamp": "2026-04-12T14:32:01Z",
"user_id": "a1b2c3...",
"ethereum_address": "0x70997970...",
"role": "Trader",
"method": "token_transfer",
"params": { "token": "0xMMFToken...", "to": "0x...", "amount": "2000000000000000000000000" },
"status": "blocked",
"error_code": -32001,
"chain_tx_hash": null,
"ip_address": "192.168.1.10"
}
],
"total": 3,
"offset": 0,
"limit": 50
}

GET /api/audit/{id}

Retrieve a single audit entry by ID.

GET /api/audit/export

Export audit entries as CSV. Accepts the same filter parameters as GET /api/audit. Returns a downloadable CSV file.

# Export all audit entries for a specific address
curl "http://localhost:8546/api/audit/export?address=0x70997970..." \
-o audit_export.csv

Audit Log Storage

The audit log is stored in audit.db (SQLite) at the path configured by AUDIT_DB_PATH (default: ./data/audit.db).

warning

The audit log is append-only in practice — entries are never deleted or modified by the system. In production, mount AUDIT_DB_PATH on a volume with restricted write access, and consider periodically archiving the database to long-term storage. A high-throughput system can accumulate several gigabytes of audit data per month.

For production deployments, back up audit.db regularly and retain it per the applicable jurisdiction's data retention requirements. Many financial regulations require audit records to be preserved for 5–7 years.

Compliance Reporting Workflows

Regulatory Review (Regulator Role)

Users with the Regulator role have read-only access to:

  • The audit log (filtered to their jurisdiction's assets)
  • Selective disclosure endpoints for investor KYC documents they have been granted access to
  • On-chain token compliance state (frozen wallets, compliance rule configurations)

Regulators cannot modify any state — their access is strictly observational.

Compliance Officer Workflow

Users with the Compliance role can:

  1. Query the audit log for suspicious patterns (e.g. repeated blocked transfers suggesting authorization issues)
  2. Freeze or unfreeze investor wallets via token_freeze
  3. View and update compliance rules (country allowlists, balance limits) on each token
  4. Export audit data for external review

Auditor Workflow

Users with the Auditor role have read-only access to the audit log and all transaction history. They cannot modify chain state or user records. Auditors typically:

  1. Export audit data for a reporting period via GET /api/audit/export
  2. Cross-reference on-chain transactions (visible via block explorer at port 3002) with the audit log
  3. Verify compliance module configurations against the token contract state

Permission-Blocked Request Tracking

When a request is blocked by the PermissionRegistry (e.g. a Trader attempts a $2M transfer exceeding their $1M limit), the entry is logged with:

{
"status": "blocked",
"error_code": -32001,
"method": "token_transfer",
"params": {
"token": "0x...",
"to": "0x...",
"amount": "2000000000000000000000000"
}
}

This creates an automatic audit trail of every permission violation attempt — useful for identifying users who are consistently attempting operations beyond their authorization level.