RECEIPTS PACK — STEP 8
Security & Privacy Contract
Tenant isolation model, capability gates, audit log coverage, right-to-delete proof, retention policy, DR procedure.
1 — Tenant Isolation Model
How tenant_id is setDerived server-side from the authenticated Bearer token. Never read from the request body. Cannot be overridden by the caller.
Read isolationAll entity queries include app_id = tenant_id filter. A tenant cannot read another tenant's bottles, catalog entries, or job status.
Write isolationWrites always stamp the caller's tenant_id. Passing a different tenant_id in the body is ignored — the server overwrites it.
Cross-tenant 403 vs 404If you request a resource belonging to another tenant, you receive 403 — not 404. This prevents enumeration attacks.
Stage 12 proofTests Q + R: Cross-tenant read and write isolation. Both PASS. Verified across 3 simulated tenants.
Explicitly forbidden: Any code path that reads tenant_id from the request body for security decisions. The only permitted source is
base44.auth.me().2 — Capability Model
Admin operationsmwIssueApiKey, mwRevokeApiKey, DR export/import, deletion sweeps. All gated by mwRequireCapability.
Capability checkCapabilityGrant entity checked before any admin action. Missing grant → 403 Forbidden. AuditLog entry created regardless.
Blocked action logForbidden requests are still logged in AuditLog with action_type='capability_denied'. Proof: Stage 12 Test S.
Role inheritanceadmin role in Base44 maps to full capability. 'user' role maps to tenant-scoped operations only.
3 — Audit Log Coverage
What gets loggedEvery API call: store, recall, search, list, key operations, capability denials, auth failures, DR operations.
Log fieldsuser_email, action_type, entity_type, entity_id, tenant_id, timestamp, outcome (success/fail), risk_level.
ImmutabilityAuditLog entity has no update/delete path. Entries are append-only via service role writes.
Coverage100% of SDK function calls emit at least one AuditLog entry. No silent paths.
Where to find itBase44 entity browser → AuditLog. Filter by user_email or action_type.
4 — Right-to-Delete Proof
Request pathUser submits deletion request → DeletionRequest entity created → mwTenantDeleteSweep scheduled.
Sweep scopeRemoves all MemoryBottle, BottleMetadata, BottleCatalog, JobStatus, SoulBottleChunk records scoped to the tenant.
Audit trailDeletionRequest entity + AuditLog entry created before sweep begins. Chain of custody maintained throughout.
IdempotencySweep is safe to re-run. Already-deleted records are silently skipped. No double-processing errors.
Stage 12 proofTest W: Right-to-delete sweep. PASS. Verified across full tenant record set.
Policy window: deletion sweep completes within 72h of request. AuditLog entry remains (contains no personal content — only action + timestamp).
5 — Retention Policy & Sweep
Default retentionMemories retained until explicit deletion request or account closure.
SecurityCapsule backupsAuto backup: 30 days. Manual backup: 90 days. Emergency backup: 365 days. Configurable per tenant.
Expired sweepmwRetentionSweep removes SecurityCapsule records past expires_at. Runs daily via scheduled automation.
JobStatus recordsCompleted/dead-letter jobs swept after 30 days. Queue does not accumulate indefinitely.
6 — DR Export/Import Procedure + Evidence
1
Trigger export
Admin calls mwExportSnapshot. Returns ExportSnapshot entity with full tenant data + SHA-256 content_hash.
2
Verify integrity
content_hash verified client-side or on re-import. Corruption detected immediately.
3
Store snapshot
ExportSnapshot entity persists in Base44. Can be downloaded or transferred.
4
Restore (mwImportSnapshot)
Import uses idempotency keys — safe to re-run. Existing data is not overwritten. New records created cleanly.
5
Verify post-restore
Query BottleCatalog + MemoryBottle counts match pre-export snapshot. Chain of custody confirmed.
Stage 12 Tests U + V: DR export integrity and restore integrity. Both PASS. Verified with hash check on re-import.