Micro Entity Governance Spec
Version: 1.1 Scope: Workspace + Cell entities (micro-app-api + micro-app-ui + micro-app-db) Status: Mandatory
See also:
system/registry/ENTITY-DEFINITION.MD: canonical IKARY Entity Definition JSON standard with governance extensions (scope,governance_tier,permissions, mandatory base fields, and thedatablock for declarative filtering/searching/sorting).
0. Why this exists
Micro positions itself as enterprise-grade by default. That requires that every persisted business object (an “entity”) supports:
- Traceability: who changed what and when
- Accountability: attribution (createdBy/updatedBy) and access control
- Safety: concurrency controls to prevent accidental overwrites
- Recoverability: ability to restore a previous state (where appropriate)
- Compliance: retention policies, redaction of sensitive data, exportability
This spec defines the minimum governance contract CODEX must implement for all entities in Micro.
1. Definitions
1.1 Entity
A business object persisted in Postgres (example: Account, Contact, Opportunity, OutboundSequence, InvoiceRule).
1.2 Workspace vs Cell
Micro uses two data planes:
- Workspace plane: shared domain objects across cells (high governance expectations)
- Cell plane: vertical objects inside a cell (app-specific; still governed, but may allow lighter rollback)
1.3 Committed vs Draft
- Committed: the system of record (what the system runs on)
- Draft: user in-progress edits (safe to autosave and abandon)
Drafts are governed separately (see Form pattern spec). This document focuses on governance for committed entities and their history.
2. Governance levels (per entity)
Every entity MUST declare a GovernanceTier.
export type GovernanceTier =
| 'tier-1' // full history + diff + restore enabled
| 'tier-2' // full history + diff, restore optional
| 'tier-3'; // minimal history, no restore (rare; still audit)Default mapping
- Workspace entities: tier-1
- Cell entities: tier-2
- tier-3 is only for high-volume ephemeral entities (e.g., telemetry-like objects). Even tier-3 must still log security-critical updates.
3. Base entity contract (mandatory)
All committed entities MUST include the following fields.
export interface MicroEntityBase {
id: string; // UUID
tenantId: string; // multi-tenancy boundary (required)
workspaceId: string; // workspace boundary (required)
cellId?: string | null; // optional scoping for cell-plane entities
version: number; // optimistic concurrency; increments on every commit
createdAt: string; // ISO timestamp
createdBy: string; // actor id (user/service)
updatedAt: string; // ISO timestamp
updatedBy: string; // actor id (user/service)
deletedAt?: string | null; // soft delete (recommended default)
deletedBy?: string | null;
// Optional: for human-friendly display
displayName?: string | null;
}Rules
versionMUST increment on every mutation that changes persisted state.createdBy/updatedByMUST reflect the authenticated actor (user id or service id).- Soft delete is recommended as default for enterprise (restore + audit). Hard delete must be rare and privileged.
4. Audit history (mandatory)
4.1 Principle
History must be append-only and tamper-evident in practice (restricted writes, no updates).
4.2 Audit events
Every mutation must produce an audit event of one of these types:
entity.createdentity.updatedentity.deleted(soft delete)entity.restored(undo delete)entity.rollback(restore prior version)entity.permission_changed(if entity has ACL)
4.3 Audit record schema (recommended)
Store as a separate table: audit_log.
-- Postgres
create table audit_log (
id uuid primary key,
tenant_id uuid not null,
workspace_id uuid not null,
cell_id uuid null,
actor_id uuid not null,
actor_type text not null, -- "user" | "service"
event_type text not null, -- e.g. entity.updated
resource_type text not null, -- e.g. "contact"
resource_id uuid not null,
resource_version int not null, -- version after commit
base_version int null, -- version prior to change
occurred_at timestamptz not null default now(),
request_id text null,
trace_id text null,
ip inet null,
user_agent text null,
-- change representation
change_kind text not null, -- "diff" | "snapshot"
diff jsonb null, -- JSON Patch / field diff (preferred)
snapshot jsonb null, -- full sanitized snapshot (optional)
-- governance helpers
redaction_applied boolean not null default true,
tags text[] null
);
create index on audit_log (tenant_id, workspace_id, resource_type, resource_id, occurred_at desc);
create index on audit_log (tenant_id, workspace_id, occurred_at desc);4.4 Diff format
Preferred: RFC 6902 JSON Patch (compact, deterministic).
Example diff:
[
{ "op": "replace", "path": "/status", "value": "active" },
{ "op": "add", "path": "/tags/-", "value": "vip" }
]Alternative (acceptable): field-level { path, before, after } but MUST apply redaction policy.
5. Redaction policy (mandatory)
Audit logs are powerful and dangerous. Micro MUST support field-level redaction.
5.1 Field tagging
Entities MUST tag sensitive fields in code via a schema annotation layer.
Example (Zod + metadata):
const ContactSchema = z.object({
email: z.string().email().describe('sensitive:pii'),
phone: z.string().optional().describe('sensitive:pii'),
notes: z.string().optional().describe('sensitive:free_text'),
});5.2 Redaction rules
- For
sensitive:piifields: store only the path and operation, not raw values. - For
sensitive:free_text: store path + hash length or a stable hash, not content. - For credentials/secrets: NEVER store value; only path and op.
5.3 Compliance switch
Micro must allow per-tenant policy configuration:
audit.storeSnapshots: true/falseaudit.storeDiffValues: true/false (defaults false for sensitive)
6. Versioning & rollback (recommended default)
6.1 Two approaches
Micro SHOULD implement Event Sourcing-lite:
- System of record: standard entity table
- History: append-only
audit_log - Optional snapshots for fast restore or diff visualization
Full event sourcing is not required and increases complexity significantly.
6.2 Rollback semantics
Rollback MUST be implemented as: “Revert by creating a new version”.
- Do NOT rewrite old rows
- Do NOT delete audit events
- Rollback creates:
- a new entity version
- a new audit event
entity.rollback - a diff that returns the entity to a chosen previous state
This keeps the audit trail intact and is the enterprise-friendly approach.
6.3 When rollback is enabled
- Tier-1 entities: rollback enabled by default
- Tier-2 entities: rollback optional (configurable)
- Tier-3: rollback disabled
6.4 Restore target
Rollback can target:
- a specific
resource_version - a specific
audit_log.id - a snapshot pointer (if snapshots enabled)
7. Concurrency control (mandatory)
Micro uses optimistic concurrency for committed entities.
7.1 Rule
Every update must provide expectedVersion.
If expectedVersion != current.version → reject with 409 Conflict.
7.2 API error shape
{
"error": "conflict",
"message": "Resource updated elsewhere",
"currentVersion": 12,
"expectedVersion": 11
}7.3 Client behavior
Clients must offer:
- reload latest
- re-apply draft (rebase)
- discard changes
This ties directly to the Form Pattern Spec.
8. API contract (NestJS)
8.1 Entity CRUD (governed)
GET /{resourceType}/{id}→ returns{ data, meta }POST /{resourceType}→ creates entity, writesentity.createdPATCH /{resourceType}/{id}→ requiresexpectedVersion, writesentity.updatedDELETE /{resourceType}/{id}→ soft delete (default), writesentity.deleted
Patch request example:
{
"expectedVersion": 11,
"patch": [{ "op": "replace", "path": "/status", "value": "active" }]
}8.2 History endpoints
GET /audit?resourceType=contact&resourceId=...&limit=50GET /audit/{auditId}(details)GET /{resourceType}/{id}/versions?limit=50(optional convenience)
8.3 Rollback endpoint
POST /{resourceType}/{id}/rollback
Body:
{
"targetVersion": 9,
"expectedVersion": 12,
"mode": "revert-by-new-version"
}Response:
{
"id": "uuid",
"version": 13,
"updatedAt": "ISO_DATE"
}8.4 Authorization for history & rollback
audit:readpermission required to view historyaudit:restorepermission required for rollback- For Workspace tier-1 entities, rollback may require elevated role (e.g., Admin / Owner)
9. Database patterns (Postgres)
9.1 Entity tables
Each entity table MUST include:
tenant_id,workspace_id(andcell_idwhen relevant)versioninteger- audit metadata fields
- soft delete fields
9.2 Indexes (minimum)
(tenant_id, workspace_id, id)(primary key often enough)(tenant_id, workspace_id, updated_at desc)for admin lists(tenant_id, workspace_id, cell_id)if cell-scoped
9.3 Tenant isolation
All queries must be scoped by tenant/workspace (row-level protection in app code or RLS).
10. UI patterns (micro-app-ui)
10.1 “History Drawer” (recommended default component)
For tier-1 and tier-2 entities, Micro UI should provide a standard “History” surface:
- Right-side drawer or modal
- Timeline list of audit events
- Each entry shows:
- event type
- actor
- timestamp
- summary (fields changed)
- Entry detail view:
- diff viewer (redactions applied)
- link to requestId/traceId (observability)
10.2 “Restore” flow
When rollback enabled:
- Show “Restore this version” CTA on a history entry
- Confirm modal:
- “This will create a new version reverting changes”
- After success:
- toast “Restored as version N”
- refresh entity view
10.3 “Last updated” surface
Every entity detail header should show:
- Created at/by (optional in UI)
- Last updated at/by (recommended)
- Version number (optional, helpful for support/debug)
11. Observability (mandatory)
Each write must attach:
requestId(propagate from API gateway)traceId(OpenTelemetry)
Metrics:
entity_write_total{resourceType,eventType}entity_conflict_total{resourceType}audit_write_latency_msrollback_total{resourceType}
Logs:
- include
tenantId,workspaceId,resourceType,resourceId,version
12. Retention & compliance (enterprise defaults)
Micro SHOULD support per-tenant retention policies:
audit.retentionDays(default: 365 or “infinite” depending on plan)audit.export(ability to export by time range)audit.immutability(restrict deletion; admin-only)
Soft deletes:
- default retention for soft deleted entities (e.g., 30–90 days) before purge (optional feature)
13. How this connects to Forms (important)
Micro Forms manage drafts. Entity Governance manages committed state.
Flow
- User edits form → autosave draft (Form Pattern Spec)
- User commits → server:
- checks expectedVersion
- applies patch to entity
- increments entity version
- writes audit event (diff + metadata)
- UI updates “Last updated by/at” and version
This is the “enterprise-grade default” story.
14. Implementation checklist for CODEX
For each new entity type:
- Add base fields (tenant/workspace/cell/version + metadata)
- Implement CRUD with optimistic concurrency (409 on mismatch)
- Emit audit events on every mutation
- Apply redaction rules for sensitive fields
- Expose history endpoint (audit query)
- If tier-1/tier-2 with rollback enabled:
- implement rollback endpoint (revert-by-new-version)
- implement UI history drawer + restore flow
- Add metrics + trace ids
15. Recommended defaults (opinionated)
- Workspace entities: tier-1, rollback enabled
- Cell entities: tier-2, rollback optional (default on)
- Always store audit diffs (JSON Patch)
- Snapshots off by default; enable per tenant/plan if needed
- Soft delete on by default
expectedVersionrequired for all updates- History UI enabled by default for governed entities