Audit logs

In an environment where human team members, transactional agents, automation scripts, Sati, and external AI agents via Remote MCP operate simultaneously on business tables, immutable traceability is a core governance pillar.


1. The platform_audit_logs Table (Single Source of Truth for Auditing)

Whenever a record is created (CREATE), updated (UPDATE), deleted (DELETE), or restored (RESTORE) in the workspace, database triggers automatically record an immutable entry in platform_audit_logs.

Strict Permissions on platform_audit_logs:

  • Read-Only (SELECT) & Immutable: Neither Sati nor the MCP server (nor any user or automation script) has insert, update, or delete permissions on platform_audit_logs.
  • RBAC Scope: Queryable by users with role Owner, Admin, or Staff members granted read permission on the 'settings' module.

Exact Column Schema of platform_audit_logs:

ColumnTypeDescription
iduuidUnique audit event ID.
actor_typetextActor type that executed the action: 'human' (user in Web/Mobile UI), 'agent' (Sati, MCP, or transactional agent), 'automation' (script in automation_scripts), or 'system'.
actor_iduuidUUID of the actor that executed the operation (user_id when 'human', agent_id when 'agent', script_id when 'automation').
prompted_byuuid (nullable)UUID of the authenticated human user who instructed the action when executed by Sati or via Remote MCP (Human + AI co-authorship).
batch_iduuid (nullable)Unique batch identifier grouping all rows created or modified within a single tool execution.
actiontextExecuted operation: 'CREATE', 'UPDATE', 'DELETE', or 'RESTORE'.
entity_slugtextAffected table or entity slug (e.g., 'pedidos', 'clientes', 'productos', 'satia_docs', 'agent', 'channel'). (Note: the column name is entity_slug; there is NO entity_type column).
record_iduuidUUID of the specific record that was created, modified, deleted, or restored. (Note: the column name is record_id; there is NO entity_id column).
reasontext (nullable)Human instruction or reason that originated the change (e.g., "[MCP: Cursor MacBook] Update order status to confirmed").
changesjsonbExact before-and-after diff of the operation: {"old": {...}, "new": {...}}. On 'CREATE', contains {"new": {...}}; on 'DELETE', contains {"old": {...}}. (Note: the column name is changes; there is NO metadata column).
created_attimestamptzExact UTC timestamp of the event.

Key entity_slug Values:

  • Business tables: Use the business table's slug directly (e.g., 'clientes', 'pedidos', 'productos', 'citas').
  • Knowledge documents (Satia Docs): Logged under entity_slug = 'satia_docs'.
  • Agents and Channels: Logged under entity_slug = 'agent' and entity_slug = 'channel'.

2. Co-Authorship (prompted_by), Batch Correlation (batch_id), and user_prompt

  1. Human + AI Co-Authorship (actor_id + prompted_by):
    • When a team member asks Sati or an MCP client to create or modify records (in business tables, agents, or knowledge_docs), the row in platform_audit_logs records actor_type = 'agent', actor_id = <Agent UUID>, and prompted_by = <Human User UUID>.
    • Furthermore, knowledge_docs tracks both the human creator and the AI co-pilot, displaying the co-authorship badge in the /knowledge UI.
  2. Batch Correlation (batch_id):
    • When an operation modifies multiple rows in a single call (for example, a batch database__insert of 30 products or a database__update affecting multiple orders), the engine generates a shared batch_id across all platform_audit_logs events produced by that operation.
  3. Mandatory Human Attribution in MCP (user_prompt → reason):
    • All mutation and delegation tools on the Remote MCP server require the user_prompt parameter.
    • The MCP server automatically prefixes the Personal Access Token name ([MCP: <KeyName>] <user_prompt>) into the reason column of all platform_audit_logs rows under that batch_id, and logs a trace entry in Sati's conversation history so the workspace owner has full visibility into actions performed from external MCP clients.

3. How to Revert or Restore Changes (RESTORE)

When a user wants to undo an accidental change (an unintended edit, creation, or deletion of a record):

  1. One-Click Restore from the Web UI (Native RESTORE):
    • In the audit timeline (available inside the detail view of any business record or Satia Doc as well as in the global Audit panel), every event has a "Restore" (Restaurar) button.
    • Clicking it automatically reverses the operation (UPDATE reverts to changes.old, DELETE re-inserts the record preserving its original id and all relationships, and CREATE deletes the newly created record) and writes a new entry in platform_audit_logs with action = 'RESTORE'.
  2. Assisted Restore via Sati or MCP (Using changes->'old'):
    • If the user asks in chat "Revert the price or fields of record X back to what they were before the last change", you can:
      1. Run SELECT id, action, changes, created_at FROM platform_audit_logs WHERE record_id = 'RECORD-UUID' ORDER BY created_at DESC LIMIT 5.
      2. Inspect the changes->'old' object to identify the exact previous values.
      3. If the record exists and was an UPDATE, call database__update on the business table with the previous values extracted from changes->'old'. If it was a complex DELETE or the user wants a full RESTORE preserving the original UUID, also let them know they can click "Restore" on that event in the web audit history.

4. Forensic Audit SQL Recipes (database__query)

Use these queries with database__query to answer questions like "Who changed the price of this product?", "What did the automation do today?", or "What changes were made via MCP?":

-- 1. Complete change history of a specific record (with actor, human co-author, and diff)
SELECT id, actor_type, actor_id, prompted_by, batch_id, action, reason, changes, created_at
FROM platform_audit_logs
WHERE record_id = 'RECORD-UUID'
ORDER BY created_at DESC
LIMIT 20

-- 2. Audit the latest modifications on a specific business table (e.g., 'pedidos')
SELECT id, actor_type, actor_id, prompted_by, action, record_id, reason, changes, created_at
FROM platform_audit_logs
WHERE entity_slug = 'pedidos'
ORDER BY created_at DESC
LIMIT 30

-- 3. Inspect all records affected within a single batch operation (batch_id)
SELECT id, entity_slug, action, record_id, reason, changes, created_at
FROM platform_audit_logs
WHERE batch_id = 'BATCH-UUID'
ORDER BY created_at ASC
LIMIT 100

-- 4. Audit changes executed by Python automation scripts
SELECT id, actor_id AS script_id, entity_slug, action, record_id, changes, created_at
FROM platform_audit_logs
WHERE actor_type = 'automation'
ORDER BY created_at DESC
LIMIT 30

-- 5. Audit all recent actions executed via Remote MCP
SELECT id, actor_id, prompted_by, batch_id, entity_slug, action, record_id, reason, created_at
FROM platform_audit_logs
WHERE reason ILIKE '[MCP:%'
ORDER BY created_at DESC
LIMIT 30

5. Audit Retention Windows

By default, all workspaces include 30 days of free audit retention in platform_audit_logs. Workspaces with extended compliance or forensic auditing requirements can configure retention windows of 60, 90, 180, or 365 days at Settings > Billing (/settings/billing) (see the billing manual for retention add-on pricing).