diff --git a/.changeset/prune-dead-audit-config-cluster.md b/.changeset/prune-dead-audit-config-cluster.md
new file mode 100644
index 0000000000..3f8f790f2c
--- /dev/null
+++ b/.changeset/prune-dead-audit-config-cluster.md
@@ -0,0 +1,38 @@
+---
+"@objectstack/spec": minor
+---
+
+feat(spec)!: remove the dead `AuditConfig` cluster from `@objectstack/spec/system` (#1878 recheck loose-end)
+
+The entire `system/audit.zod.ts` module — `AuditConfigSchema`,
+`AuditStorageConfigSchema`, `AuditRetentionPolicySchema`,
+`AuditEventFilterSchema`, `SuspiciousActivityRuleSchema`,
+`DEFAULT_SUSPICIOUS_ACTIVITY_RULES`, and the `AuditEvent` /
+`AuditEventActor` / `AuditEventTarget` / `AuditEventChange` /
+`AuditEventType` / `AuditEventSeverity` shape schemas (plus all their
+type exports) — is removed. Verified zero consumers repo-wide: the live
+audit path (`plugin-audit`) imports none of it, defines its own
+`sys_audit_log` row shape, and captures **unconditionally** via engine
+hooks, so `AuditConfigSchema.enabled: false` advertised a semantic
+(turning the compliance ledger off) the platform deliberately rejects.
+Same ADR-0056 D8 family as the earlier `compliance.zod` / `masking.zod` /
+`RLSAuditConfig` / `PolicySchema` removals: security/compliance-shaped
+config must never merely look live.
+
+**Migration — every dead knob maps to a live surface (or is deliberately
+not configurable):**
+
+| Removed (never enforced) | Live replacement |
+| --- | --- |
+| `AuditConfigSchema.enabled` | none — audit capture is **always on** (compliance ledger; `object.zod` `trackHistory` contract) |
+| `eventTypes` / `excludeEventTypes` / `minimumSeverity` / `AuditEventFilterSchema` | none today — if event filtering ships it lands as an `audit` **settings** namespace (ADR-0069 pattern), not app metadata |
+| which fields/objects are summarized + History tab UI | object-level + field-level **`trackHistory`** (live, enforced by plugin-audit) |
+| `AuditRetentionPolicySchema` / `storage` | object **`lifecycle`** `audit` category (retain → archive → delete) + per-org settings overrides (ADR-0057) |
+| `SuspiciousActivityRuleSchema` / `DEFAULT_SUSPICIOUS_ACTIVITY_RULES` | none — no detection engine exists; security monitoring is org-operations tooling, not app-package metadata |
+| `AuditEvent*` shape schemas | the `sys_audit_log` object definition in `plugin-audit` is the row-shape source of truth |
+
+No first-party, example, or downstream-contract code imported any of
+these symbols; `defineStack` never accepted an `audit` key, so no stack
+config changes. Docs page `references/system/audit.mdx` is removed by
+regeneration; the security-context module doc now marks audit alongside
+the previously removed compliance/masking subsystems.
diff --git a/content/docs/references/system/audit.mdx b/content/docs/references/system/audit.mdx
deleted file mode 100644
index 05ff1003d1..0000000000
--- a/content/docs/references/system/audit.mdx
+++ /dev/null
@@ -1,269 +0,0 @@
----
-title: Audit
-description: Audit protocol schemas
----
-
-{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */}
-
-Audit Log Architecture
-
-Comprehensive audit logging system for compliance and security.
-
-Supports SOX, HIPAA, GDPR, and other regulatory requirements.
-
-Features:
-
-- Records all CRUD operations on data
-
-- Tracks authentication events (login, logout, password reset)
-
-- Monitors authorization changes (permissions, roles)
-
-- Configurable retention policies (180-day GDPR requirement)
-
-- Suspicious activity detection and alerting
-
-
-**Source:** `packages/spec/src/system/audit.zod.ts`
-
-
-## TypeScript Usage
-
-```typescript
-import { AuditConfig, AuditEvent, AuditEventActor, AuditEventChange, AuditEventFilter, AuditEventSeverity, AuditEventTarget, AuditEventType, AuditRetentionPolicy, AuditStorageConfig, SuspiciousActivityRule } from '@objectstack/spec/system';
-import type { AuditConfig, AuditEvent, AuditEventActor, AuditEventChange, AuditEventFilter, AuditEventSeverity, AuditEventTarget, AuditEventType, AuditRetentionPolicy, AuditStorageConfig, SuspiciousActivityRule } from '@objectstack/spec/system';
-
-// Validate data
-const result = AuditConfig.parse(data);
-```
-
----
-
-## AuditConfig
-
-### Properties
-
-| Property | Type | Required | Description |
-| :--- | :--- | :--- | :--- |
-| **name** | `string` | ✅ | Configuration name (snake_case, max 64 chars) |
-| **label** | `string` | ✅ | Display label |
-| **enabled** | `boolean` | optional | Enable audit logging |
-| **eventTypes** | `Enum<'data.create' \| 'data.read' \| 'data.update' \| 'data.delete' \| 'data.export' \| 'data.import' \| 'data.bulk_update' \| 'data.bulk_delete' \| 'auth.login' \| 'auth.login_failed' \| 'auth.logout' \| 'auth.session_created' \| 'auth.session_expired' \| 'auth.password_reset' \| 'auth.password_changed' \| 'auth.email_verified' \| 'auth.mfa_enabled' \| 'auth.mfa_disabled' \| 'auth.account_locked' \| 'auth.account_unlocked' \| 'authz.permission_granted' \| 'authz.permission_revoked' \| 'authz.role_assigned' \| 'authz.role_removed' \| 'authz.role_created' \| 'authz.role_updated' \| 'authz.role_deleted' \| 'authz.policy_created' \| 'authz.policy_updated' \| 'authz.policy_deleted' \| 'system.config_changed' \| 'system.plugin_installed' \| 'system.plugin_uninstalled' \| 'system.backup_created' \| 'system.backup_restored' \| 'system.integration_added' \| 'system.integration_removed' \| 'security.access_denied' \| 'security.suspicious_activity' \| 'security.data_breach' \| 'security.api_key_created' \| 'security.api_key_revoked'>[]` | optional | Event types to audit |
-| **excludeEventTypes** | `Enum<'data.create' \| 'data.read' \| 'data.update' \| 'data.delete' \| 'data.export' \| 'data.import' \| 'data.bulk_update' \| 'data.bulk_delete' \| 'auth.login' \| 'auth.login_failed' \| 'auth.logout' \| 'auth.session_created' \| 'auth.session_expired' \| 'auth.password_reset' \| 'auth.password_changed' \| 'auth.email_verified' \| 'auth.mfa_enabled' \| 'auth.mfa_disabled' \| 'auth.account_locked' \| 'auth.account_unlocked' \| 'authz.permission_granted' \| 'authz.permission_revoked' \| 'authz.role_assigned' \| 'authz.role_removed' \| 'authz.role_created' \| 'authz.role_updated' \| 'authz.role_deleted' \| 'authz.policy_created' \| 'authz.policy_updated' \| 'authz.policy_deleted' \| 'system.config_changed' \| 'system.plugin_installed' \| 'system.plugin_uninstalled' \| 'system.backup_created' \| 'system.backup_restored' \| 'system.integration_added' \| 'system.integration_removed' \| 'security.access_denied' \| 'security.suspicious_activity' \| 'security.data_breach' \| 'security.api_key_created' \| 'security.api_key_revoked'>[]` | optional | Event types to exclude |
-| **minimumSeverity** | `Enum<'debug' \| 'info' \| 'notice' \| 'warning' \| 'error' \| 'critical' \| 'alert' \| 'emergency'>` | optional | Minimum severity level |
-| **storage** | `{ type: Enum<'database' \| 'elasticsearch' \| 'mongodb' \| 'clickhouse' \| 's3' \| 'gcs' \| 'azure_blob' \| 'custom'>; connectionString?: string; config?: Record; bufferEnabled?: boolean; … }` | ✅ | Storage configuration |
-| **retentionPolicy** | `{ retentionDays?: integer; archiveAfterRetention?: boolean; archiveStorage?: object; customRetention?: Record; … }` | optional | Retention policy |
-| **suspiciousActivityRules** | `{ id: string; name: string; description?: string; enabled?: boolean; … }[]` | optional | Suspicious activity rules |
-| **includeSensitiveData** | `boolean` | optional | Include sensitive data |
-| **redactFields** | `string[]` | optional | Fields to redact |
-| **logReads** | `boolean` | optional | Log read operations |
-| **readSamplingRate** | `number` | optional | Read sampling rate |
-| **logSystemEvents** | `boolean` | optional | Log system events |
-| **customHandlers** | `{ eventType: Enum<'data.create' \| 'data.read' \| 'data.update' \| 'data.delete' \| 'data.export' \| 'data.import' \| 'data.bulk_update' \| 'data.bulk_delete' \| 'auth.login' \| 'auth.login_failed' \| 'auth.logout' \| 'auth.session_created' \| 'auth.session_expired' \| 'auth.password_reset' \| 'auth.password_changed' \| 'auth.email_verified' \| 'auth.mfa_enabled' \| 'auth.mfa_disabled' \| 'auth.account_locked' \| 'auth.account_unlocked' \| 'authz.permission_granted' \| 'authz.permission_revoked' \| 'authz.role_assigned' \| 'authz.role_removed' \| 'authz.role_created' \| 'authz.role_updated' \| 'authz.role_deleted' \| 'authz.policy_created' \| 'authz.policy_updated' \| 'authz.policy_deleted' \| 'system.config_changed' \| 'system.plugin_installed' \| 'system.plugin_uninstalled' \| 'system.backup_created' \| 'system.backup_restored' \| 'system.integration_added' \| 'system.integration_removed' \| 'security.access_denied' \| 'security.suspicious_activity' \| 'security.data_breach' \| 'security.api_key_created' \| 'security.api_key_revoked'>; handlerId: string }[]` | optional | Custom event handler references |
-| **compliance** | `{ standards?: Enum<'sox' \| 'hipaa' \| 'gdpr' \| 'pci_dss' \| 'iso_27001' \| 'fedramp'>[]; immutableLogs?: boolean; requireSigning?: boolean; signingKey?: string }` | optional | Compliance configuration |
-
-
----
-
-## AuditEvent
-
-### Properties
-
-| Property | Type | Required | Description |
-| :--- | :--- | :--- | :--- |
-| **id** | `string` | ✅ | Audit event ID |
-| **eventType** | `Enum<'data.create' \| 'data.read' \| 'data.update' \| 'data.delete' \| 'data.export' \| 'data.import' \| 'data.bulk_update' \| 'data.bulk_delete' \| 'auth.login' \| 'auth.login_failed' \| 'auth.logout' \| 'auth.session_created' \| 'auth.session_expired' \| 'auth.password_reset' \| 'auth.password_changed' \| 'auth.email_verified' \| 'auth.mfa_enabled' \| 'auth.mfa_disabled' \| 'auth.account_locked' \| 'auth.account_unlocked' \| 'authz.permission_granted' \| 'authz.permission_revoked' \| 'authz.role_assigned' \| 'authz.role_removed' \| 'authz.role_created' \| 'authz.role_updated' \| 'authz.role_deleted' \| 'authz.policy_created' \| 'authz.policy_updated' \| 'authz.policy_deleted' \| 'system.config_changed' \| 'system.plugin_installed' \| 'system.plugin_uninstalled' \| 'system.backup_created' \| 'system.backup_restored' \| 'system.integration_added' \| 'system.integration_removed' \| 'security.access_denied' \| 'security.suspicious_activity' \| 'security.data_breach' \| 'security.api_key_created' \| 'security.api_key_revoked'>` | ✅ | Event type |
-| **severity** | `Enum<'debug' \| 'info' \| 'notice' \| 'warning' \| 'error' \| 'critical' \| 'alert' \| 'emergency'>` | ✅ | Event severity |
-| **timestamp** | `string` | ✅ | Event timestamp |
-| **actor** | `{ type: Enum<'user' \| 'system' \| 'service' \| 'api_client' \| 'integration'>; id: string; name?: string; email?: string; … }` | ✅ | Event actor |
-| **target** | `{ type: string; id: string; name?: string; metadata?: Record }` | optional | Event target |
-| **description** | `string` | ✅ | Event description |
-| **changes** | `{ field: string; oldValue?: any; newValue?: any }[]` | optional | List of changes |
-| **result** | `Enum<'success' \| 'failure' \| 'partial'>` | ✅ | Action result |
-| **errorMessage** | `string` | optional | Error message |
-| **tenantId** | `string` | optional | Tenant identifier |
-| **requestId** | `string` | optional | Request ID for tracing |
-| **metadata** | `Record` | optional | Additional metadata |
-| **location** | `{ country?: string; region?: string; city?: string }` | optional | Geographic location |
-
-
----
-
-## AuditEventActor
-
-### Properties
-
-| Property | Type | Required | Description |
-| :--- | :--- | :--- | :--- |
-| **type** | `Enum<'user' \| 'system' \| 'service' \| 'api_client' \| 'integration'>` | ✅ | Actor type |
-| **id** | `string` | ✅ | Actor identifier |
-| **name** | `string` | optional | Actor display name |
-| **email** | `string` | optional | Actor email address |
-| **ipAddress** | `string` | optional | Actor IP address |
-| **userAgent** | `string` | optional | User agent string |
-
-
----
-
-## AuditEventChange
-
-### Properties
-
-| Property | Type | Required | Description |
-| :--- | :--- | :--- | :--- |
-| **field** | `string` | ✅ | Changed field name |
-| **oldValue** | `any` | optional | Previous value |
-| **newValue** | `any` | optional | New value |
-
-
----
-
-## AuditEventFilter
-
-### Properties
-
-| Property | Type | Required | Description |
-| :--- | :--- | :--- | :--- |
-| **eventTypes** | `Enum<'data.create' \| 'data.read' \| 'data.update' \| 'data.delete' \| 'data.export' \| 'data.import' \| 'data.bulk_update' \| 'data.bulk_delete' \| 'auth.login' \| 'auth.login_failed' \| 'auth.logout' \| 'auth.session_created' \| 'auth.session_expired' \| 'auth.password_reset' \| 'auth.password_changed' \| 'auth.email_verified' \| 'auth.mfa_enabled' \| 'auth.mfa_disabled' \| 'auth.account_locked' \| 'auth.account_unlocked' \| 'authz.permission_granted' \| 'authz.permission_revoked' \| 'authz.role_assigned' \| 'authz.role_removed' \| 'authz.role_created' \| 'authz.role_updated' \| 'authz.role_deleted' \| 'authz.policy_created' \| 'authz.policy_updated' \| 'authz.policy_deleted' \| 'system.config_changed' \| 'system.plugin_installed' \| 'system.plugin_uninstalled' \| 'system.backup_created' \| 'system.backup_restored' \| 'system.integration_added' \| 'system.integration_removed' \| 'security.access_denied' \| 'security.suspicious_activity' \| 'security.data_breach' \| 'security.api_key_created' \| 'security.api_key_revoked'>[]` | optional | Event types to include |
-| **severities** | `Enum<'debug' \| 'info' \| 'notice' \| 'warning' \| 'error' \| 'critical' \| 'alert' \| 'emergency'>[]` | optional | Severity levels to include |
-| **actorId** | `string` | optional | Actor identifier |
-| **tenantId** | `string` | optional | Tenant identifier |
-| **timeRange** | `{ from: string; to: string }` | optional | Time range filter |
-| **result** | `Enum<'success' \| 'failure' \| 'partial'>` | optional | Result status |
-| **searchQuery** | `string` | optional | Search query |
-| **customFilters** | `Record` | optional | Custom filters |
-
-
----
-
-## AuditEventSeverity
-
-### Allowed Values
-
-* `debug`
-* `info`
-* `notice`
-* `warning`
-* `error`
-* `critical`
-* `alert`
-* `emergency`
-
-
----
-
-## AuditEventTarget
-
-### Properties
-
-| Property | Type | Required | Description |
-| :--- | :--- | :--- | :--- |
-| **type** | `string` | ✅ | Target type |
-| **id** | `string` | ✅ | Target identifier |
-| **name** | `string` | optional | Target display name |
-| **metadata** | `Record` | optional | Target metadata |
-
-
----
-
-## AuditEventType
-
-### Allowed Values
-
-* `data.create`
-* `data.read`
-* `data.update`
-* `data.delete`
-* `data.export`
-* `data.import`
-* `data.bulk_update`
-* `data.bulk_delete`
-* `auth.login`
-* `auth.login_failed`
-* `auth.logout`
-* `auth.session_created`
-* `auth.session_expired`
-* `auth.password_reset`
-* `auth.password_changed`
-* `auth.email_verified`
-* `auth.mfa_enabled`
-* `auth.mfa_disabled`
-* `auth.account_locked`
-* `auth.account_unlocked`
-* `authz.permission_granted`
-* `authz.permission_revoked`
-* `authz.role_assigned`
-* `authz.role_removed`
-* `authz.role_created`
-* `authz.role_updated`
-* `authz.role_deleted`
-* `authz.policy_created`
-* `authz.policy_updated`
-* `authz.policy_deleted`
-* `system.config_changed`
-* `system.plugin_installed`
-* `system.plugin_uninstalled`
-* `system.backup_created`
-* `system.backup_restored`
-* `system.integration_added`
-* `system.integration_removed`
-* `security.access_denied`
-* `security.suspicious_activity`
-* `security.data_breach`
-* `security.api_key_created`
-* `security.api_key_revoked`
-
-
----
-
-## AuditRetentionPolicy
-
-### Properties
-
-| Property | Type | Required | Description |
-| :--- | :--- | :--- | :--- |
-| **retentionDays** | `integer` | ✅ | Retention period in days |
-| **archiveAfterRetention** | `boolean` | ✅ | Archive logs after retention period |
-| **archiveStorage** | `{ type: Enum<'s3' \| 'gcs' \| 'azure_blob' \| 'filesystem'>; endpoint?: string; bucket?: string; path?: string; … }` | optional | Archive storage configuration |
-| **customRetention** | `Record` | optional | Custom retention by event type |
-| **minimumRetentionDays** | `integer` | optional | Minimum retention for compliance |
-
-
----
-
-## AuditStorageConfig
-
-### Properties
-
-| Property | Type | Required | Description |
-| :--- | :--- | :--- | :--- |
-| **type** | `Enum<'database' \| 'elasticsearch' \| 'mongodb' \| 'clickhouse' \| 's3' \| 'gcs' \| 'azure_blob' \| 'custom'>` | ✅ | Storage backend type |
-| **connectionString** | `string` | optional | Connection string |
-| **config** | `Record` | optional | Storage-specific configuration |
-| **bufferEnabled** | `boolean` | ✅ | Enable buffering |
-| **bufferSize** | `integer` | ✅ | Buffer size |
-| **flushIntervalSeconds** | `integer` | ✅ | Flush interval in seconds |
-| **compression** | `boolean` | ✅ | Enable compression |
-
-
----
-
-## SuspiciousActivityRule
-
-### Properties
-
-| Property | Type | Required | Description |
-| :--- | :--- | :--- | :--- |
-| **id** | `string` | ✅ | Rule identifier |
-| **name** | `string` | ✅ | Rule name |
-| **description** | `string` | optional | Rule description |
-| **enabled** | `boolean` | optional | Rule enabled status |
-| **eventTypes** | `Enum<'data.create' \| 'data.read' \| 'data.update' \| 'data.delete' \| 'data.export' \| 'data.import' \| 'data.bulk_update' \| 'data.bulk_delete' \| 'auth.login' \| 'auth.login_failed' \| 'auth.logout' \| 'auth.session_created' \| 'auth.session_expired' \| 'auth.password_reset' \| 'auth.password_changed' \| 'auth.email_verified' \| 'auth.mfa_enabled' \| 'auth.mfa_disabled' \| 'auth.account_locked' \| 'auth.account_unlocked' \| 'authz.permission_granted' \| 'authz.permission_revoked' \| 'authz.role_assigned' \| 'authz.role_removed' \| 'authz.role_created' \| 'authz.role_updated' \| 'authz.role_deleted' \| 'authz.policy_created' \| 'authz.policy_updated' \| 'authz.policy_deleted' \| 'system.config_changed' \| 'system.plugin_installed' \| 'system.plugin_uninstalled' \| 'system.backup_created' \| 'system.backup_restored' \| 'system.integration_added' \| 'system.integration_removed' \| 'security.access_denied' \| 'security.suspicious_activity' \| 'security.data_breach' \| 'security.api_key_created' \| 'security.api_key_revoked'>[]` | ✅ | Event types to monitor |
-| **condition** | `{ threshold: integer; windowSeconds: integer; groupBy?: string[]; filters?: Record } \| string \| { dialect: Enum<'cel' \| 'cron' \| 'template'>; source?: string; ast?: any; meta?: object }` | ✅ | Detection condition — structured threshold or CEL predicate |
-| **actions** | `Enum<'alert' \| 'lock_account' \| 'block_ip' \| 'require_mfa' \| 'log_critical' \| 'webhook'>[]` | ✅ | Actions to take |
-| **alertSeverity** | `Enum<'debug' \| 'info' \| 'notice' \| 'warning' \| 'error' \| 'critical' \| 'alert' \| 'emergency'>` | optional | Alert severity |
-| **notifications** | `{ email?: string[]; slack?: string; webhook?: string }` | optional | Notification configuration |
-
-
----
-
diff --git a/content/docs/references/system/index.mdx b/content/docs/references/system/index.mdx
index d416d817d8..111ea39759 100644
--- a/content/docs/references/system/index.mdx
+++ b/content/docs/references/system/index.mdx
@@ -7,7 +7,6 @@ This section contains all protocol schemas for the system layer of ObjectStack.
-
diff --git a/content/docs/references/system/meta.json b/content/docs/references/system/meta.json
index f1484ef6f0..6f4076046b 100644
--- a/content/docs/references/system/meta.json
+++ b/content/docs/references/system/meta.json
@@ -29,7 +29,6 @@
"translation",
"worker",
"---Observability---",
- "audit",
"logging",
"metrics",
"tracing",
diff --git a/content/docs/references/system/security-context.mdx b/content/docs/references/system/security-context.mdx
index bbcac1bfd3..a071c6da0c 100644
--- a/content/docs/references/system/security-context.mdx
+++ b/content/docs/references/system/security-context.mdx
@@ -9,15 +9,21 @@ Unified Security Context Protocol
Provides a central governance layer that correlates and unifies
-the four independent security subsystems:
+the four independent security subsystems it was designed against. Three of
-- **Audit** (audit.zod.ts): Event logging and suspicious activity detection
+the four have since been REMOVED per ADR-0056 D8 (declared-but-never-enforced;
+
+see system/index.ts notes) — only encryption survives, marked experimental:
+
+- **Audit** (audit.zod.ts — REMOVED): the live audit path is plugin-audit's
+
+always-on capture + object/field `trackHistory` + lifecycle `audit` retention
- **Encryption** (encryption.zod.ts): Field-level encryption and key management
-- **Compliance** (compliance.zod.ts): Regulatory framework enforcement (GDPR/HIPAA/SOX/PCI-DSS)
+- **Compliance** (compliance.zod.ts — REMOVED): GDPR/HIPAA/SOX/PCI-DSS configs
-- **Masking** (masking.zod.ts): PII data masking and tokenization
+- **Masking** (masking.zod.ts — REMOVED): PII data masking and tokenization
This schema enforces cross-cutting security policies, ensuring compliance
diff --git a/docs/audits/2026-07-security-props-liveness-recheck.md b/docs/audits/2026-07-security-props-liveness-recheck.md
index 255ee01980..f2f4ee2250 100644
--- a/docs/audits/2026-07-security-props-liveness-recheck.md
+++ b/docs/audits/2026-07-security-props-liveness-recheck.md
@@ -53,12 +53,20 @@ enterprise/cloud-enforced (agent `access`).
## Genuine remaining loose ends (actionable)
-1. **Prune `AuditRetentionPolicySchema`** (`packages/spec/src/system/audit.zod.ts`)
- — a real parsed-only/dead spec schema with no runtime consumer; retention is
- enforced on the `lifecycle` surface. Prune (or wire-rename to `lifecycle`).
-2. **SharingRule dead recipient types** — `owner`-type rules and `group`/`guest`
- recipients are skipped by the bootstrap while criteria-type rules enforce.
- Enforce-or-prune the dead subset so authored rules don't silently no-op.
+1. ~~**Prune `AuditRetentionPolicySchema`**~~ — **✅ Done (2026-07-27)**, and the
+ verified scope was larger: the **entire `audit.zod.ts` module** (AuditConfig /
+ AuditStorageConfig / AuditRetentionPolicy / AuditEventFilter /
+ SuspiciousActivityRule + the AuditEvent* shape schemas) had zero consumers —
+ the live audit path (plugin-audit) captures unconditionally via engine hooks
+ and defines its own `sys_audit_log` row shape, and `AuditConfigSchema.enabled`
+ contradicted the always-on compliance-ledger contract. Whole module removed;
+ the enforced authoring surface is object/field `trackHistory` + the object
+ `lifecycle` `audit` category, with per-org overrides in settings.
+2. ~~**SharingRule dead recipient types**~~ — **✅ Done (#3557)**: recipients
+ reconciled against the live identity model — `group` wired as `team`,
+ `business_unit` added, and the unenforceable `guest` recipient + `owner`-type
+ rules removed from the authoring surface (authored rules no longer silently
+ no-op).
3. **Per-org / per-user IP allow-list** — global-only today; per-org
`sys_organization.allowed_ip_ranges` is unimplemented (tracked **#2571**).
4. **Doc / ledger drift** (non-code-behavior):
diff --git a/packages/spec/PROTOCOL_MAP.md b/packages/spec/PROTOCOL_MAP.md
index 1d7ed6066b..7021262422 100644
--- a/packages/spec/PROTOCOL_MAP.md
+++ b/packages/spec/PROTOCOL_MAP.md
@@ -136,7 +136,6 @@ This document serves as the **Grand Map** of the ObjectStack specification. It l
| [`auth-config.zod.ts`](src/system/auth-config.zod.ts) | | **Auth Configuration**. SSO, OIDC, SAML settings. |
| [`http-server.zod.ts`](src/system/http-server.zod.ts) | | **HTTP Server**. Server port, CORS, and middleware settings. |
| [`logging.zod.ts`](src/system/logging.zod.ts) | | **Logging**. Log levels and output formats. |
-| [`audit.zod.ts`](src/system/audit.zod.ts) | | **Audit Trail**. Audit logging configuration. |
| [`cache.zod.ts`](src/system/cache.zod.ts) | | **Caching**. Redis/Memory cache strategies. |
| [`metrics.zod.ts`](src/system/metrics.zod.ts) | | **Observability**. Prometheus/OpenTelemetry metrics. |
| [`tracing.zod.ts`](src/system/tracing.zod.ts) | | **Tracing**. Distributed tracing configuration. |
diff --git a/packages/spec/api-surface.json b/packages/spec/api-surface.json
index 41d5eb04fb..3ae5e36aa5 100644
--- a/packages/spec/api-surface.json
+++ b/packages/spec/api-surface.json
@@ -605,24 +605,6 @@
"AppTranslationBundleSchema (const)",
"AudienceBook (interface)",
"AudienceCaller (interface)",
- "AuditConfig (type)",
- "AuditConfigSchema (const)",
- "AuditEvent (type)",
- "AuditEventActor (type)",
- "AuditEventActorSchema (const)",
- "AuditEventChange (type)",
- "AuditEventChangeSchema (const)",
- "AuditEventFilter (type)",
- "AuditEventFilterSchema (const)",
- "AuditEventSchema (const)",
- "AuditEventSeverity (type)",
- "AuditEventTarget (type)",
- "AuditEventTargetSchema (const)",
- "AuditEventType (type)",
- "AuditRetentionPolicy (type)",
- "AuditRetentionPolicySchema (const)",
- "AuditStorageConfig (type)",
- "AuditStorageConfigSchema (const)",
"AuthConfig (type)",
"AuthConfigSchema (const)",
"AuthPluginConfig (type)",
@@ -727,7 +709,6 @@
"CursorStyleSchema (const)",
"CursorUpdate (type)",
"CursorUpdateSchema (const)",
- "DEFAULT_SUSPICIOUS_ACTIVITY_RULES (const)",
"DashboardLike (interface)",
"DataClassification (type)",
"DataClassificationPolicy (type)",
@@ -1169,8 +1150,6 @@
"SupplierSecurityPolicySchema (const)",
"SupplierSecurityRequirement (type)",
"SupplierSecurityRequirementSchema (const)",
- "SuspiciousActivityRule (type)",
- "SuspiciousActivityRuleSchema (const)",
"SystemFieldName (type)",
"SystemObjectName (type)",
"SystemUserId (type)",
diff --git a/packages/spec/json-schema.manifest.json b/packages/spec/json-schema.manifest.json
index f23530a31b..da865881bb 100644
--- a/packages/spec/json-schema.manifest.json
+++ b/packages/spec/json-schema.manifest.json
@@ -1262,16 +1262,6 @@
"system/AppInstallResult",
"system/AppManifest",
"system/AppTranslationBundle",
- "system/AuditConfig",
- "system/AuditEvent",
- "system/AuditEventActor",
- "system/AuditEventChange",
- "system/AuditEventFilter",
- "system/AuditEventSeverity",
- "system/AuditEventTarget",
- "system/AuditEventType",
- "system/AuditRetentionPolicy",
- "system/AuditStorageConfig",
"system/AuthConfig",
"system/AuthPluginConfig",
"system/AuthProviderConfig",
@@ -1532,7 +1522,6 @@
"system/SupplierSecurityAssessment",
"system/SupplierSecurityPolicy",
"system/SupplierSecurityRequirement",
- "system/SuspiciousActivityRule",
"system/Task",
"system/TaskExecutionResult",
"system/TaskPriority",
diff --git a/packages/spec/src/system/audit.test.ts b/packages/spec/src/system/audit.test.ts
deleted file mode 100644
index bee7a45faf..0000000000
--- a/packages/spec/src/system/audit.test.ts
+++ /dev/null
@@ -1,598 +0,0 @@
-import { describe, it, expect } from 'vitest';
-import {
- AuditEventType,
- AuditEventSeverity,
- AuditEventActorSchema,
- AuditEventTargetSchema,
- AuditEventChangeSchema,
- AuditEventSchema,
- AuditRetentionPolicySchema,
- SuspiciousActivityRuleSchema,
- AuditStorageConfigSchema,
- AuditEventFilterSchema,
- AuditConfigSchema,
- DEFAULT_SUSPICIOUS_ACTIVITY_RULES,
- type AuditEvent,
- type AuditConfig,
- type SuspiciousActivityRule,
-} from './audit.zod';
-
-describe('AuditEventType', () => {
- it('should accept valid event types', () => {
- const validTypes = [
- 'data.create',
- 'data.read',
- 'data.update',
- 'data.delete',
- 'auth.login',
- 'auth.login_failed',
- 'auth.logout',
- 'authz.permission_granted',
- 'authz.role_assigned',
- 'security.access_denied',
- ];
-
- validTypes.forEach((type) => {
- expect(() => AuditEventType.parse(type)).not.toThrow();
- });
- });
-
- it('should reject invalid event types', () => {
- expect(() => AuditEventType.parse('invalid.type')).toThrow();
- expect(() => AuditEventType.parse('dataCreate')).toThrow();
- });
-});
-
-describe('AuditEventSeverity', () => {
- it('should accept valid severity levels', () => {
- const validLevels = ['debug', 'info', 'notice', 'warning', 'error', 'critical', 'alert', 'emergency'];
-
- validLevels.forEach((level) => {
- expect(() => AuditEventSeverity.parse(level)).not.toThrow();
- });
- });
-
- it('should reject invalid severity levels', () => {
- expect(() => AuditEventSeverity.parse('invalid')).toThrow();
- expect(() => AuditEventSeverity.parse('high')).toThrow();
- });
-});
-
-describe('AuditEventActorSchema', () => {
- it('should accept valid actor configuration', () => {
- const validActor = {
- type: 'user',
- id: 'user_123',
- name: 'John Doe',
- email: 'john@example.com',
- ipAddress: '192.168.1.1',
- userAgent: 'Mozilla/5.0',
- };
-
- expect(() => AuditEventActorSchema.parse(validActor)).not.toThrow();
- });
-
- it('should accept minimal actor configuration', () => {
- const minimalActor = {
- type: 'system',
- id: 'system',
- };
-
- expect(() => AuditEventActorSchema.parse(minimalActor)).not.toThrow();
- });
-
- it('should reject invalid email', () => {
- const invalidActor = {
- type: 'user',
- id: 'user_123',
- email: 'not-an-email',
- };
-
- expect(() => AuditEventActorSchema.parse(invalidActor)).toThrow();
- });
-});
-
-describe('AuditEventTargetSchema', () => {
- it('should accept valid target configuration', () => {
- const validTarget = {
- type: 'record',
- id: 'rec_456',
- name: 'Customer Record #456',
- metadata: {
- objectName: 'customer',
- fields: ['name', 'email'],
- },
- };
-
- expect(() => AuditEventTargetSchema.parse(validTarget)).not.toThrow();
- });
-
- it('should accept minimal target configuration', () => {
- const minimalTarget = {
- type: 'object',
- id: 'obj_789',
- };
-
- expect(() => AuditEventTargetSchema.parse(minimalTarget)).not.toThrow();
- });
-});
-
-describe('AuditEventChangeSchema', () => {
- it('should accept valid change record', () => {
- const validChange = {
- field: 'email',
- oldValue: 'old@example.com',
- newValue: 'new@example.com',
- };
-
- expect(() => AuditEventChangeSchema.parse(validChange)).not.toThrow();
- });
-
- it('should accept change with only new value', () => {
- const createChange = {
- field: 'name',
- newValue: 'John Doe',
- };
-
- expect(() => AuditEventChangeSchema.parse(createChange)).not.toThrow();
- });
-});
-
-describe('AuditEventSchema', () => {
- it('should accept complete audit event', () => {
- const validEvent: AuditEvent = {
- id: 'evt_123',
- eventType: 'data.update',
- severity: 'info',
- timestamp: new Date().toISOString(),
- actor: {
- type: 'user',
- id: 'user_123',
- email: 'user@example.com',
- },
- target: {
- type: 'record',
- id: 'rec_456',
- },
- description: 'User updated customer record',
- changes: [
- {
- field: 'email',
- oldValue: 'old@example.com',
- newValue: 'new@example.com',
- },
- ],
- result: 'success',
- tenantId: 'tenant_789',
- requestId: 'req_abc',
- };
-
- expect(() => AuditEventSchema.parse(validEvent)).not.toThrow();
- });
-
- it('should accept minimal audit event', () => {
- const minimalEvent = {
- id: 'evt_456',
- eventType: 'auth.login',
- timestamp: new Date().toISOString(),
- actor: {
- type: 'user',
- id: 'user_123',
- },
- description: 'User logged in',
- };
-
- expect(() => AuditEventSchema.parse(minimalEvent)).not.toThrow();
- });
-
- it('should default severity to info', () => {
- const event = {
- id: 'evt_789',
- eventType: 'data.read',
- timestamp: new Date().toISOString(),
- actor: {
- type: 'user',
- id: 'user_123',
- },
- description: 'User viewed record',
- };
-
- const parsed = AuditEventSchema.parse(event);
- expect(parsed.severity).toBe('info');
- });
-
- it('should default result to success', () => {
- const event = {
- id: 'evt_101',
- eventType: 'data.create',
- timestamp: new Date().toISOString(),
- actor: {
- type: 'user',
- id: 'user_123',
- },
- description: 'User created record',
- };
-
- const parsed = AuditEventSchema.parse(event);
- expect(parsed.result).toBe('success');
- });
-
- it('should accept failed event with error message', () => {
- const failedEvent = {
- id: 'evt_202',
- eventType: 'auth.login',
- severity: 'warning',
- timestamp: new Date().toISOString(),
- actor: {
- type: 'user',
- id: 'user_123',
- },
- description: 'Login attempt failed',
- result: 'failure',
- errorMessage: 'Invalid password',
- };
-
- expect(() => AuditEventSchema.parse(failedEvent)).not.toThrow();
- });
-});
-
-describe('AuditRetentionPolicySchema', () => {
- it('should accept valid retention policy', () => {
- const validPolicy = {
- retentionDays: 365,
- archiveAfterRetention: true,
- archiveStorage: {
- type: 's3',
- bucket: 'audit-logs-archive',
- path: 'logs/',
- },
- customRetention: {
- 'auth.login_failed': 730, // 2 years
- 'security.data_breach': 2555, // 7 years
- },
- minimumRetentionDays: 180,
- };
-
- expect(() => AuditRetentionPolicySchema.parse(validPolicy)).not.toThrow();
- });
-
- it('should default to 180 days retention', () => {
- const policy = {};
- const parsed = AuditRetentionPolicySchema.parse(policy);
- expect(parsed.retentionDays).toBe(180);
- });
-
- it('should default to archiving enabled', () => {
- const policy = {};
- const parsed = AuditRetentionPolicySchema.parse(policy);
- expect(parsed.archiveAfterRetention).toBe(true);
- });
-
- it('should reject negative retention days', () => {
- const invalidPolicy = {
- retentionDays: -30,
- };
-
- expect(() => AuditRetentionPolicySchema.parse(invalidPolicy)).toThrow();
- });
-});
-
-describe('SuspiciousActivityRuleSchema', () => {
- it('should accept valid suspicious activity rule', () => {
- const validRule: SuspiciousActivityRule = {
- id: 'rule_123',
- name: 'Multiple Failed Logins',
- description: 'Detects brute force attacks',
- enabled: true,
- eventTypes: ['auth.login_failed'],
- condition: {
- threshold: 5,
- windowSeconds: 600,
- groupBy: ['actor.id'],
- },
- actions: ['alert', 'lock_account'],
- alertSeverity: 'critical',
- notifications: {
- email: ['security@example.com'],
- slack: 'https://hooks.slack.com/services/xxx',
- },
- };
-
- expect(() => SuspiciousActivityRuleSchema.parse(validRule)).not.toThrow();
- });
-
- it('should default enabled to true', () => {
- const rule = {
- id: 'rule_456',
- name: 'Test Rule',
- eventTypes: ['data.export'],
- condition: {
- threshold: 10,
- windowSeconds: 3600,
- },
- actions: ['alert'],
- };
-
- const parsed = SuspiciousActivityRuleSchema.parse(rule);
- expect(parsed.enabled).toBe(true);
- });
-
- it('should default alert severity to warning', () => {
- const rule = {
- id: 'rule_789',
- name: 'Test Rule',
- eventTypes: ['data.delete'],
- condition: {
- threshold: 3,
- windowSeconds: 300,
- },
- actions: ['alert'],
- };
-
- const parsed = SuspiciousActivityRuleSchema.parse(rule);
- expect(parsed.alertSeverity).toBe('warning');
- });
-});
-
-describe('AuditStorageConfigSchema', () => {
- it('should accept database storage configuration', () => {
- const dbStorage = {
- type: 'database',
- connectionString: 'postgresql://localhost:5432/audit',
- bufferEnabled: true,
- bufferSize: 100,
- flushIntervalSeconds: 5,
- compression: true,
- };
-
- expect(() => AuditStorageConfigSchema.parse(dbStorage)).not.toThrow();
- });
-
- it('should accept elasticsearch storage configuration', () => {
- const esStorage = {
- type: 'elasticsearch',
- connectionString: 'https://elasticsearch:9200',
- config: {
- index: 'audit-logs',
- shards: 5,
- },
- };
-
- expect(() => AuditStorageConfigSchema.parse(esStorage)).not.toThrow();
- });
-
- it('should default buffer settings', () => {
- const storage = {
- type: 'mongodb',
- };
-
- const parsed = AuditStorageConfigSchema.parse(storage);
- expect(parsed.bufferEnabled).toBe(true);
- expect(parsed.bufferSize).toBe(100);
- expect(parsed.flushIntervalSeconds).toBe(5);
- expect(parsed.compression).toBe(true);
- });
-});
-
-describe('AuditEventFilterSchema', () => {
- it('should accept complete filter configuration', () => {
- const validFilter = {
- eventTypes: ['data.create', 'data.update'],
- severities: ['warning', 'error', 'critical'],
- actorId: 'user_123',
- tenantId: 'tenant_456',
- timeRange: {
- from: '2024-01-01T00:00:00Z',
- to: '2024-12-31T23:59:59Z',
- },
- result: 'failure',
- searchQuery: 'password reset',
- };
-
- expect(() => AuditEventFilterSchema.parse(validFilter)).not.toThrow();
- });
-
- it('should accept minimal filter configuration', () => {
- const minimalFilter = {};
- expect(() => AuditEventFilterSchema.parse(minimalFilter)).not.toThrow();
- });
-
- it('should accept partial filters', () => {
- const partialFilter = {
- eventTypes: ['auth.login'],
- timeRange: {
- from: '2024-01-01T00:00:00Z',
- to: '2024-01-31T23:59:59Z',
- },
- };
-
- expect(() => AuditEventFilterSchema.parse(partialFilter)).not.toThrow();
- });
-});
-
-describe('AuditConfigSchema', () => {
- it('should accept complete audit configuration', () => {
- const validConfig: AuditConfig = {
- name: 'main_audit',
- label: 'Main Audit Configuration',
- enabled: true,
- eventTypes: ['data.create', 'data.update', 'auth.login'],
- minimumSeverity: 'info',
- storage: {
- type: 'database',
- connectionString: 'postgresql://localhost/audit',
- },
- retentionPolicy: {
- retentionDays: 365,
- },
- suspiciousActivityRules: [
- {
- id: 'failed_logins',
- name: 'Failed Logins',
- eventTypes: ['auth.login_failed'],
- condition: {
- threshold: 5,
- windowSeconds: 600,
- },
- actions: ['alert'],
- },
- ],
- includeSensitiveData: false,
- logReads: false,
- compliance: {
- standards: ['gdpr', 'sox'],
- immutableLogs: true,
- },
- };
-
- expect(() => AuditConfigSchema.parse(validConfig)).not.toThrow();
- });
-
- it('should accept minimal audit configuration', () => {
- const minimalConfig = {
- name: 'basic_audit',
- label: 'Basic Audit',
- storage: {
- type: 'database',
- },
- };
-
- expect(() => AuditConfigSchema.parse(minimalConfig)).not.toThrow();
- });
-
- it('should enforce snake_case naming convention', () => {
- const invalidConfig = {
- name: 'mainAudit', // camelCase, should be snake_case
- label: 'Main Audit',
- storage: {
- type: 'database',
- },
- };
-
- expect(() => AuditConfigSchema.parse(invalidConfig)).toThrow();
- });
-
- it('should accept valid snake_case names', () => {
- const validNames = ['audit_config', 'main_audit', 'security_audit_log'];
-
- validNames.forEach((name) => {
- const config = {
- name,
- label: 'Test Audit',
- storage: { type: 'database' },
- };
- expect(() => AuditConfigSchema.parse(config)).not.toThrow();
- });
- });
-
- it('should default enabled to true', () => {
- const config = {
- name: 'test_audit',
- label: 'Test Audit',
- storage: { type: 'database' },
- };
-
- const parsed = AuditConfigSchema.parse(config);
- expect(parsed.enabled).toBe(true);
- });
-
- it('should default minimumSeverity to info', () => {
- const config = {
- name: 'test_audit',
- label: 'Test Audit',
- storage: { type: 'database' },
- };
-
- const parsed = AuditConfigSchema.parse(config);
- expect(parsed.minimumSeverity).toBe('info');
- });
-
- it('should default redactFields to common sensitive fields', () => {
- const config = {
- name: 'test_audit',
- label: 'Test Audit',
- storage: { type: 'database' },
- };
-
- const parsed = AuditConfigSchema.parse(config);
- expect(parsed.redactFields).toContain('password');
- expect(parsed.redactFields).toContain('token');
- expect(parsed.redactFields).toContain('apiKey');
- });
-
- it('should default logReads to false', () => {
- const config = {
- name: 'test_audit',
- label: 'Test Audit',
- storage: { type: 'database' },
- };
-
- const parsed = AuditConfigSchema.parse(config);
- expect(parsed.logReads).toBe(false);
- });
-
- it('should default readSamplingRate to 0.1', () => {
- const config = {
- name: 'test_audit',
- label: 'Test Audit',
- storage: { type: 'database' },
- };
-
- const parsed = AuditConfigSchema.parse(config);
- expect(parsed.readSamplingRate).toBe(0.1);
- });
-
- it('should accept compliance configuration', () => {
- const config = {
- name: 'compliance_audit',
- label: 'Compliance Audit',
- storage: { type: 'database' },
- compliance: {
- standards: ['sox', 'hipaa', 'gdpr'],
- immutableLogs: true,
- requireSigning: true,
- signingKey: 'secret-key-123',
- },
- };
-
- expect(() => AuditConfigSchema.parse(config)).not.toThrow();
- });
-});
-
-describe('DEFAULT_SUSPICIOUS_ACTIVITY_RULES', () => {
- it('should have valid default rules', () => {
- expect(DEFAULT_SUSPICIOUS_ACTIVITY_RULES.length).toBeGreaterThan(0);
-
- DEFAULT_SUSPICIOUS_ACTIVITY_RULES.forEach((rule) => {
- expect(() => SuspiciousActivityRuleSchema.parse(rule)).not.toThrow();
- });
- });
-
- it('should include multiple failed logins rule', () => {
- const rule = DEFAULT_SUSPICIOUS_ACTIVITY_RULES.find(
- (r) => r.id === 'multiple_failed_logins'
- );
-
- expect(rule).toBeDefined();
- expect(rule?.eventTypes).toContain('auth.login_failed');
- expect(rule?.condition.threshold).toBe(5);
- });
-
- it('should include bulk data export rule', () => {
- const rule = DEFAULT_SUSPICIOUS_ACTIVITY_RULES.find(
- (r) => r.id === 'bulk_data_export'
- );
-
- expect(rule).toBeDefined();
- expect(rule?.eventTypes).toContain('data.export');
- });
-
- it('should include permission changes rule', () => {
- const rule = DEFAULT_SUSPICIOUS_ACTIVITY_RULES.find(
- (r) => r.id === 'suspicious_permission_changes'
- );
-
- expect(rule).toBeDefined();
- expect(rule?.actions).toContain('alert');
- });
-});
diff --git a/packages/spec/src/system/audit.zod.ts b/packages/spec/src/system/audit.zod.ts
deleted file mode 100644
index 647a31ff73..0000000000
--- a/packages/spec/src/system/audit.zod.ts
+++ /dev/null
@@ -1,696 +0,0 @@
-// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
-
-import { z } from 'zod';
-import { ExpressionInputSchema } from '../shared/expression.zod';
-
-/**
- * Audit Log Architecture
- *
- * Comprehensive audit logging system for compliance and security.
- * Supports SOX, HIPAA, GDPR, and other regulatory requirements.
- *
- * Features:
- * - Records all CRUD operations on data
- * - Tracks authentication events (login, logout, password reset)
- * - Monitors authorization changes (permissions, roles)
- * - Configurable retention policies (180-day GDPR requirement)
- * - Suspicious activity detection and alerting
- */
-
-/**
- * Audit Event Type Enum
- * Categorizes different types of auditable events in the system
- */
-import { lazySchema } from '../shared/lazy-schema';
-export const AuditEventType = z.enum([
- // Data Operations (CRUD)
- 'data.create', // Record creation
- 'data.read', // Record retrieval/viewing
- 'data.update', // Record modification
- 'data.delete', // Record deletion
- 'data.export', // Data export operations
- 'data.import', // Data import operations
- 'data.bulk_update', // Bulk update operations
- 'data.bulk_delete', // Bulk delete operations
-
- // Authentication Events
- 'auth.login', // Successful login
- 'auth.login_failed', // Failed login attempt
- 'auth.logout', // User logout
- 'auth.session_created', // New session created
- 'auth.session_expired', // Session expiration
- 'auth.password_reset', // Password reset initiated
- 'auth.password_changed', // Password successfully changed
- 'auth.email_verified', // Email verification completed
- 'auth.mfa_enabled', // Multi-factor auth enabled
- 'auth.mfa_disabled', // Multi-factor auth disabled
- 'auth.account_locked', // Account locked (too many failures)
- 'auth.account_unlocked', // Account unlocked
-
- // Authorization Events
- 'authz.permission_granted', // Permission granted to user
- 'authz.permission_revoked', // Permission revoked from user
- 'authz.role_assigned', // Role assigned to user
- 'authz.role_removed', // Role removed from user
- 'authz.role_created', // New role created
- 'authz.role_updated', // Role permissions modified
- 'authz.role_deleted', // Role deleted
- 'authz.policy_created', // Security policy created
- 'authz.policy_updated', // Security policy updated
- 'authz.policy_deleted', // Security policy deleted
-
- // System Events
- 'system.config_changed', // System configuration modified
- 'system.plugin_installed', // Plugin installed
- 'system.plugin_uninstalled', // Plugin uninstalled
- 'system.backup_created', // Backup created
- 'system.backup_restored', // Backup restored
- 'system.integration_added', // External integration added
- 'system.integration_removed',// External integration removed
-
- // Security Events
- 'security.access_denied', // Access denied (authorization failure)
- 'security.suspicious_activity', // Suspicious activity detected
- 'security.data_breach', // Potential data breach detected
- 'security.api_key_created', // API key created
- 'security.api_key_revoked', // API key revoked
-]);
-
-export type AuditEventType = z.infer;
-
-/**
- * Audit Event Severity Level
- * Indicates the importance/criticality of an audit event
- */
-export const AuditEventSeverity = z.enum([
- 'debug', // Diagnostic information
- 'info', // Informational events (normal operations)
- 'notice', // Normal but significant events
- 'warning', // Warning conditions
- 'error', // Error conditions
- 'critical', // Critical conditions requiring immediate attention
- 'alert', // Action must be taken immediately
- 'emergency', // System is unusable
-]);
-
-export type AuditEventSeverity = z.infer;
-
-/**
- * Audit Event Actor Schema
- * Identifies who/what performed the action
- */
-export const AuditEventActorSchema = lazySchema(() => z.object({
- /**
- * Actor type (user, system, service, api_client, etc.)
- */
- type: z.enum(['user', 'system', 'service', 'api_client', 'integration']).describe('Actor type'),
-
- /**
- * Unique identifier for the actor
- */
- id: z.string().describe('Actor identifier'),
-
- /**
- * Display name of the actor
- */
- name: z.string().optional().describe('Actor display name'),
-
- /**
- * Email address (for user actors)
- */
- email: z.string().email().optional().describe('Actor email address'),
-
- /**
- * IP address of the actor
- */
- ipAddress: z.string().optional().describe('Actor IP address'),
-
- /**
- * User agent string (for web/API requests)
- */
- userAgent: z.string().optional().describe('User agent string'),
-}));
-
-export type AuditEventActor = z.infer;
-
-/**
- * Audit Event Target Schema
- * Identifies what was acted upon
- */
-export const AuditEventTargetSchema = lazySchema(() => z.object({
- /**
- * Target type (e.g., 'object', 'record', 'user', 'position', 'config')
- */
- type: z.string().describe('Target type'),
-
- /**
- * Unique identifier for the target
- */
- id: z.string().describe('Target identifier'),
-
- /**
- * Display name of the target
- */
- name: z.string().optional().describe('Target display name'),
-
- /**
- * Additional metadata about the target
- */
- metadata: z.record(z.string(), z.unknown()).optional().describe('Target metadata'),
-}));
-
-export type AuditEventTarget = z.infer;
-
-/**
- * Audit Event Change Schema
- * Describes what changed (for update operations)
- */
-export const AuditEventChangeSchema = lazySchema(() => z.object({
- /**
- * Field/property that changed
- */
- field: z.string().describe('Changed field name'),
-
- /**
- * Value before the change
- */
- oldValue: z.unknown().optional().describe('Previous value'),
-
- /**
- * Value after the change
- */
- newValue: z.unknown().optional().describe('New value'),
-}));
-
-export type AuditEventChange = z.infer;
-
-/**
- * Audit Event Schema
- * Complete audit event record
- */
-export const AuditEventSchema = lazySchema(() => z.object({
- /**
- * Unique identifier for this audit event
- */
- id: z.string().describe('Audit event ID'),
-
- /**
- * Type of event being audited
- */
- eventType: AuditEventType.describe('Event type'),
-
- /**
- * Severity level of the event
- */
- severity: AuditEventSeverity.default('info').describe('Event severity'),
-
- /**
- * Timestamp when the event occurred (ISO 8601)
- */
- timestamp: z.string().datetime().describe('Event timestamp'),
-
- /**
- * Who/what performed the action
- */
- actor: AuditEventActorSchema.describe('Event actor'),
-
- /**
- * What was acted upon
- */
- target: AuditEventTargetSchema.optional().describe('Event target'),
-
- /**
- * Human-readable description of the action
- */
- description: z.string().describe('Event description'),
-
- /**
- * Detailed changes (for update operations)
- */
- changes: z.array(AuditEventChangeSchema).optional().describe('List of changes'),
-
- /**
- * Result of the action (success, failure, partial)
- */
- result: z.enum(['success', 'failure', 'partial']).default('success').describe('Action result'),
-
- /**
- * Error message (if result is failure)
- */
- errorMessage: z.string().optional().describe('Error message'),
-
- /**
- * Tenant identifier (for multi-tenant systems)
- */
- tenantId: z.string().optional().describe('Tenant identifier'),
-
- /**
- * Request/trace ID for correlation
- */
- requestId: z.string().optional().describe('Request ID for tracing'),
-
- /**
- * Additional context and metadata
- */
- metadata: z.record(z.string(), z.unknown()).optional().describe('Additional metadata'),
-
- /**
- * Geographic location (if available)
- */
- location: z.object({
- country: z.string().optional(),
- region: z.string().optional(),
- city: z.string().optional(),
- }).optional().describe('Geographic location'),
-}));
-
-export type AuditEvent = z.infer;
-
-/**
- * Audit Retention Policy Schema
- * Defines how long audit logs are retained
- */
-export const AuditRetentionPolicySchema = lazySchema(() => z.object({
- /**
- * Retention period in days
- * Default: 180 days (GDPR 6-month requirement)
- */
- retentionDays: z.number().int().min(1).default(180).describe('Retention period in days'),
-
- /**
- * Whether to archive logs after retention period
- * If true, logs are moved to cold storage; if false, they are deleted
- */
- archiveAfterRetention: z.boolean().default(true).describe('Archive logs after retention period'),
-
- /**
- * Archive storage configuration
- */
- archiveStorage: z.object({
- type: z.enum(['s3', 'gcs', 'azure_blob', 'filesystem']).describe('Archive storage type'),
- endpoint: z.string().optional().describe('Storage endpoint URL'),
- bucket: z.string().optional().describe('Storage bucket/container name'),
- path: z.string().optional().describe('Storage path prefix'),
- credentials: z.record(z.string(), z.unknown()).optional().describe('Storage credentials'),
- }).optional().describe('Archive storage configuration'),
-
- /**
- * Event types that have different retention periods
- * Overrides the default retentionDays for specific event types
- */
- customRetention: z.record(z.string(), z.number().int().positive()).optional().describe('Custom retention by event type'),
-
- /**
- * Minimum retention period for compliance
- * Prevents accidental deletion below compliance requirements
- */
- minimumRetentionDays: z.number().int().positive().optional().describe('Minimum retention for compliance'),
-}));
-
-export type AuditRetentionPolicy = z.infer;
-
-/**
- * Suspicious Activity Rule Schema
- * Defines rules for detecting suspicious activities
- */
-export const SuspiciousActivityRuleSchema = lazySchema(() => z.object({
- /**
- * Unique identifier for the rule
- */
- id: z.string().describe('Rule identifier'),
-
- /**
- * Rule name
- */
- name: z.string().describe('Rule name'),
-
- /**
- * Rule description
- */
- description: z.string().optional().describe('Rule description'),
-
- /**
- * Whether the rule is enabled
- */
- enabled: z.boolean().default(true).describe('Rule enabled status'),
-
- /**
- * Event types to monitor
- */
- eventTypes: z.array(AuditEventType).describe('Event types to monitor'),
-
- /**
- * Detection condition — accepts either a structured threshold/window object
- * or a CEL predicate (escape hatch for advanced rules).
- */
- condition: z.union([
- z.object({
- threshold: z.number().int().positive().describe('Event threshold'),
- windowSeconds: z.number().int().positive().describe('Time window in seconds'),
- groupBy: z.array(z.string()).optional().describe('Grouping criteria'),
- filters: z.record(z.string(), z.unknown()).optional().describe('Additional filters'),
- }),
- ExpressionInputSchema,
- ]).describe('Detection condition — structured threshold or CEL predicate'),
-
- /**
- * Actions to take when rule is triggered
- */
- actions: z.array(z.enum([
- 'alert', // Send alert notification
- 'lock_account', // Lock the user account
- 'block_ip', // Block the IP address
- 'require_mfa', // Require multi-factor authentication
- 'log_critical', // Log as critical event
- 'webhook', // Call webhook
- ])).describe('Actions to take'),
-
- /**
- * Severity level for triggered alerts
- */
- alertSeverity: AuditEventSeverity.default('warning').describe('Alert severity'),
-
- /**
- * Notification configuration
- */
- notifications: z.object({
- /**
- * Email addresses to notify
- */
- email: z.array(z.string().email()).optional().describe('Email recipients'),
-
- /**
- * Slack webhook URL
- */
- slack: z.string().url().optional().describe('Slack webhook URL'),
-
- /**
- * Custom webhook URL
- */
- webhook: z.string().url().optional().describe('Custom webhook URL'),
- }).optional().describe('Notification configuration'),
-}));
-
-export type SuspiciousActivityRule = z.infer;
-
-/**
- * Audit Log Storage Configuration
- * Defines where and how audit logs are stored
- */
-export const AuditStorageConfigSchema = lazySchema(() => z.object({
- /**
- * Storage backend type
- */
- type: z.enum([
- 'database', // Store in database (PostgreSQL, MySQL, etc.)
- 'elasticsearch', // Store in Elasticsearch
- 'mongodb', // Store in MongoDB
- 'clickhouse', // Store in ClickHouse (for analytics)
- 's3', // Store in S3-compatible storage
- 'gcs', // Store in Google Cloud Storage
- 'azure_blob', // Store in Azure Blob Storage
- 'custom', // Custom storage implementation
- ]).describe('Storage backend type'),
-
- /**
- * Connection string or configuration
- */
- connectionString: z.string().optional().describe('Connection string'),
-
- /**
- * Storage configuration
- */
- config: z.record(z.string(), z.unknown()).optional().describe('Storage-specific configuration'),
-
- /**
- * Whether to enable buffering/batching
- */
- bufferEnabled: z.boolean().default(true).describe('Enable buffering'),
-
- /**
- * Buffer size (number of events before flush)
- */
- bufferSize: z.number().int().positive().default(100).describe('Buffer size'),
-
- /**
- * Buffer flush interval in seconds
- */
- flushIntervalSeconds: z.number().int().positive().default(5).describe('Flush interval in seconds'),
-
- /**
- * Whether to compress stored data
- */
- compression: z.boolean().default(true).describe('Enable compression'),
-}));
-
-export type AuditStorageConfig = z.infer;
-
-/**
- * Audit Event Filter Schema
- * Defines filters for querying audit events
- */
-export const AuditEventFilterSchema = lazySchema(() => z.object({
- /**
- * Filter by event types
- */
- eventTypes: z.array(AuditEventType).optional().describe('Event types to include'),
-
- /**
- * Filter by severity levels
- */
- severities: z.array(AuditEventSeverity).optional().describe('Severity levels to include'),
-
- /**
- * Filter by actor ID
- */
- actorId: z.string().optional().describe('Actor identifier'),
-
- /**
- * Filter by tenant ID
- */
- tenantId: z.string().optional().describe('Tenant identifier'),
-
- /**
- * Filter by time range
- */
- timeRange: z.object({
- from: z.string().datetime().describe('Start time'),
- to: z.string().datetime().describe('End time'),
- }).optional().describe('Time range filter'),
-
- /**
- * Filter by result status
- */
- result: z.enum(['success', 'failure', 'partial']).optional().describe('Result status'),
-
- /**
- * Search query (full-text search)
- */
- searchQuery: z.string().optional().describe('Search query'),
-
- /**
- * Custom filters
- */
- customFilters: z.record(z.string(), z.unknown()).optional().describe('Custom filters'),
-}));
-
-export type AuditEventFilter = z.infer;
-
-/**
- * Complete Audit Configuration Schema
- * Main configuration for the audit system
- */
-export const AuditConfigSchema = lazySchema(() => z.object({
- /**
- * Unique identifier for this audit configuration
- * Must be in snake_case following ObjectStack conventions
- * Maximum length: 64 characters
- */
- name: z.string()
- .regex(/^[a-z_][a-z0-9_]*$/)
- .max(64)
- .describe('Configuration name (snake_case, max 64 chars)'),
-
- /**
- * Human-readable label
- */
- label: z.string().describe('Display label'),
-
- /**
- * Whether audit logging is enabled
- */
- enabled: z.boolean().default(true).describe('Enable audit logging'),
-
- /**
- * Event types to audit
- * If not specified, all event types are audited
- */
- eventTypes: z.array(AuditEventType).optional().describe('Event types to audit'),
-
- /**
- * Event types to exclude from auditing
- */
- excludeEventTypes: z.array(AuditEventType).optional().describe('Event types to exclude'),
-
- /**
- * Minimum severity level to log
- * Events below this level are not logged
- */
- minimumSeverity: AuditEventSeverity.default('info').describe('Minimum severity level'),
-
- /**
- * Storage configuration
- */
- storage: AuditStorageConfigSchema.describe('Storage configuration'),
-
- /**
- * Retention policy
- */
- retentionPolicy: AuditRetentionPolicySchema.optional().describe('Retention policy'),
-
- /**
- * Suspicious activity detection rules
- */
- suspiciousActivityRules: z.array(SuspiciousActivityRuleSchema).default([]).describe('Suspicious activity rules'),
-
- /**
- * Whether to include sensitive data in audit logs
- * If false, sensitive fields are redacted/masked
- */
- includeSensitiveData: z.boolean().default(false).describe('Include sensitive data'),
-
- /**
- * Fields to redact from audit logs
- */
- redactFields: z.array(z.string()).default([
- 'password',
- 'passwordHash',
- 'token',
- 'apiKey',
- 'secret',
- 'creditCard',
- 'ssn',
- ]).describe('Fields to redact'),
-
- /**
- * Whether to log successful read operations
- * Can be disabled to reduce log volume
- */
- logReads: z.boolean().default(false).describe('Log read operations'),
-
- /**
- * Sampling rate for read operations (0.0 to 1.0)
- * Only applies if logReads is true
- */
- readSamplingRate: z.number().min(0).max(1).default(0.1).describe('Read sampling rate'),
-
- /**
- * Whether to log system/internal operations
- */
- logSystemEvents: z.boolean().default(true).describe('Log system events'),
-
- /**
- * Custom audit event handlers
- * Note: Function handlers are for runtime configuration only and will not be serialized to JSON Schema
- */
- customHandlers: z.array(z.object({
- eventType: AuditEventType.describe('Event type to handle'),
- handlerId: z.string().describe('Unique identifier for the handler'),
- })).optional().describe('Custom event handler references'),
-
- /**
- * Compliance mode configuration
- */
- compliance: z.object({
- /**
- * Compliance standards to enforce
- */
- standards: z.array(z.enum([
- 'sox', // Sarbanes-Oxley Act
- 'hipaa', // Health Insurance Portability and Accountability Act
- 'gdpr', // General Data Protection Regulation
- 'pci_dss', // Payment Card Industry Data Security Standard
- 'iso_27001',// ISO/IEC 27001
- 'fedramp', // Federal Risk and Authorization Management Program
- ])).optional().describe('Compliance standards'),
-
- /**
- * Whether to enforce immutable audit logs
- */
- immutableLogs: z.boolean().default(true).describe('Enforce immutable logs'),
-
- /**
- * Whether to require cryptographic signing
- */
- requireSigning: z.boolean().default(false).describe('Require log signing'),
-
- /**
- * Signing key configuration
- */
- signingKey: z.string().optional().describe('Signing key'),
- }).optional().describe('Compliance configuration'),
-}));
-
-export type AuditConfig = z.infer;
-
-/**
- * Default suspicious activity rules
- * Common security patterns to detect
- */
-export const DEFAULT_SUSPICIOUS_ACTIVITY_RULES: SuspiciousActivityRule[] = [
- {
- id: 'multiple_failed_logins',
- name: 'Multiple Failed Login Attempts',
- description: 'Detects multiple failed login attempts from the same user or IP',
- enabled: true,
- eventTypes: ['auth.login_failed'],
- condition: {
- threshold: 5,
- windowSeconds: 600, // 10 minutes
- groupBy: ['actor.id', 'actor.ipAddress'],
- },
- actions: ['alert', 'lock_account'],
- alertSeverity: 'warning',
- },
- {
- id: 'bulk_data_export',
- name: 'Bulk Data Export',
- description: 'Detects large data export operations',
- enabled: true,
- eventTypes: ['data.export'],
- condition: {
- threshold: 3,
- windowSeconds: 3600, // 1 hour
- groupBy: ['actor.id'],
- },
- actions: ['alert', 'log_critical'],
- alertSeverity: 'warning',
- },
- {
- id: 'suspicious_permission_changes',
- name: 'Rapid Permission Changes',
- description: 'Detects rapid permission or role changes',
- enabled: true,
- eventTypes: ['authz.permission_granted', 'authz.role_assigned'],
- condition: {
- threshold: 10,
- windowSeconds: 300, // 5 minutes
- groupBy: ['actor.id'],
- },
- actions: ['alert', 'log_critical'],
- alertSeverity: 'critical',
- },
- {
- id: 'after_hours_access',
- name: 'After Hours Access',
- description: 'Detects access during non-business hours',
- enabled: false, // Disabled by default, requires time zone configuration
- eventTypes: ['auth.login'],
- condition: {
- threshold: 1,
- windowSeconds: 86400, // 24 hours
- },
- actions: ['alert'],
- alertSeverity: 'notice',
- },
-];
diff --git a/packages/spec/src/system/index.ts b/packages/spec/src/system/index.ts
index b8fdb07243..41e68f6da2 100644
--- a/packages/spec/src/system/index.ts
+++ b/packages/spec/src/system/index.ts
@@ -19,7 +19,14 @@ export * from './search-engine.zod';
export * from './http-server.zod';
// Observability & Operations
-export * from './audit.zod';
+// audit.zod (AuditConfig/AuditStorageConfig/AuditRetentionPolicy/AuditEventFilter/
+// SuspiciousActivityRule + the AuditEvent* shape schemas) was REMOVED per ADR-0056
+// D8 "design+enforce or remove": the whole module had zero consumers — the LIVE
+// audit path (plugin-audit) captures unconditionally via engine hooks and defines
+// its own sys_audit_log row shape, and `AuditConfigSchema.enabled` contradicted
+// the always-on compliance-ledger contract (object.zod `trackHistory`). The
+// enforced authoring surface is object/field `trackHistory` + the object
+// `lifecycle` `audit` category (retention), with per-org overrides in settings.
export * from './logging.zod';
export * from './metrics.zod';
export * from './tracing.zod';
diff --git a/packages/spec/src/system/security-context.zod.ts b/packages/spec/src/system/security-context.zod.ts
index 2b40e6f1e2..0e37d9296e 100644
--- a/packages/spec/src/system/security-context.zod.ts
+++ b/packages/spec/src/system/security-context.zod.ts
@@ -10,11 +10,14 @@ import { z } from 'zod';
* Unified Security Context Protocol
*
* Provides a central governance layer that correlates and unifies
- * the four independent security subsystems:
- * - **Audit** (audit.zod.ts): Event logging and suspicious activity detection
+ * the four independent security subsystems it was designed against. Three of
+ * the four have since been REMOVED per ADR-0056 D8 (declared-but-never-enforced;
+ * see system/index.ts notes) — only encryption survives, marked experimental:
+ * - **Audit** (audit.zod.ts — REMOVED): the live audit path is plugin-audit's
+ * always-on capture + object/field `trackHistory` + lifecycle `audit` retention
* - **Encryption** (encryption.zod.ts): Field-level encryption and key management
- * - **Compliance** (compliance.zod.ts): Regulatory framework enforcement (GDPR/HIPAA/SOX/PCI-DSS)
- * - **Masking** (masking.zod.ts): PII data masking and tokenization
+ * - **Compliance** (compliance.zod.ts — REMOVED): GDPR/HIPAA/SOX/PCI-DSS configs
+ * - **Masking** (masking.zod.ts — REMOVED): PII data masking and tokenization
*
* This schema enforces cross-cutting security policies, ensuring compliance
* frameworks drive encryption requirements, masking rules respect role-based