diff --git a/db/migrate/20260419023642_create_captain_contact_memories.rb b/db/migrate/20260419023642_create_captain_contact_memories.rb index 6027601d8..e13aa7f00 100644 --- a/db/migrate/20260419023642_create_captain_contact_memories.rb +++ b/db/migrate/20260419023642_create_captain_contact_memories.rb @@ -1,6 +1,12 @@ class CreateCaptainContactMemories < ActiveRecord::Migration[7.1] # rubocop:disable Metrics/AbcSize, Metrics/MethodLength def change + # NOTE: source_conversation_id, source_unit_id, source_inbox_id, and + # superseded_by_id are intentionally plain bigints WITHOUT foreign keys. + # Rationale: preserve memory history and audit trail even if the source + # conversation/unit/inbox is hard-deleted (LGPD compliance for customer + # data retention, see spec §10). Application code must tolerate + # dangling references gracefully. create_table :captain_contact_memories do |t| t.references :account, null: false, foreign_key: true t.references :contact, null: false, foreign_key: true diff --git a/docs/superpowers/specs/2026-04-18-captain-semantic-memory-design.md b/docs/superpowers/specs/2026-04-18-captain-semantic-memory-design.md index e3712d5ad..fe7ac60aa 100644 --- a/docs/superpowers/specs/2026-04-18-captain-semantic-memory-design.md +++ b/docs/superpowers/specs/2026-04-18-captain-semantic-memory-design.md @@ -107,13 +107,13 @@ CREATE TABLE captain_contact_memories ( confidence FLOAT NOT NULL, scope VARCHAR NOT NULL DEFAULT 'global', embedding vector(1536), - source_conversation_id BIGINT REFERENCES conversations(id), - source_unit_id BIGINT REFERENCES captain_units(id), - source_inbox_id BIGINT REFERENCES inboxes(id), + source_conversation_id BIGINT, + source_unit_id BIGINT, + source_inbox_id BIGINT, expires_at TIMESTAMP, last_verified_at TIMESTAMP NOT NULL, superseded_at TIMESTAMP, - superseded_by_id BIGINT REFERENCES captain_contact_memories(id), + superseded_by_id BIGINT, deleted_at TIMESTAMP, metadata JSONB NOT NULL DEFAULT '{}', created_at TIMESTAMP NOT NULL, @@ -121,6 +121,8 @@ CREATE TABLE captain_contact_memories ( ); ``` +**Observação — FKs secundárias:** `source_conversation_id`, `source_unit_id`, `source_inbox_id` e `superseded_by_id` são `BIGINT` simples sem `FOREIGN KEY`. Manter a referência mesmo após o registro de origem ser hard-deletado é essencial pra auditoria LGPD (§10) e pra relatórios históricos por unidade (§3 decisão 3). App-layer precisa tratar referências órfãs graciosamente. + ### 6.2 Índices ```sql