Class: Insika::Commands::ForgetCustomer
- Inherits:
-
Object
- Object
- Insika::Commands::ForgetCustomer
- Includes:
- SessionPurge
- Defined in:
- lib/insika/commands/forget_customer.rb
Overview
Control command (WS8, phase 2 — LGPD): purges what the engine holds about
ONE customer — the customer's memory cell, their sessions (found through
the customer var the Executor stamps on a tagged conversation) and
everything those sessions left behind (traces, tasks, checkpoints, outbox
deliveries — see SessionPurge). The scope string IS the isolation
boundary, so zeroing it cannot touch another customer's or another
tenant's data. Operator-only BY CONSTRUCTION: the generic command ingress
is operator-grade (a tenant principal never reaches it).
WHICH TENANT is the whole correctness of the purge: the memory cell is
"memory:{ customer:, tenant: } — the operator naming it over
HTTP, where the principal has no tenant of its own). Absent from both, the
purge is deployment-wide: the untagged memory cell plus that customer's
sessions in EVERY tenant — right for a single-tenant deployment, and never
what a multi-tenant operator means, so they must name the tenant.
Instance Method Summary collapse
-
#call(command) ⇒ Object
-> { customer:, tenant:, memory_records:, sessions: [], tasks:, checkpoints:, deliveries:, followups:, contacts: }.
-
#initialize(memory_store:, session_store:, tool_trace_store: nil, context_trace_store: nil, model_visible_trace_store: nil, task_store: nil, checkpoint_store: nil, outbox_store: nil, shadow_pairs: nil, audit_store: nil, event_stream:, followup_store: nil, contact_store: nil, proposal_store: nil) ⇒ ForgetCustomer
constructor
A new instance of ForgetCustomer.
Methods included from SessionPurge
Constructor Details
#initialize(memory_store:, session_store:, tool_trace_store: nil, context_trace_store: nil, model_visible_trace_store: nil, task_store: nil, checkpoint_store: nil, outbox_store: nil, shadow_pairs: nil, audit_store: nil, event_stream:, followup_store: nil, contact_store: nil, proposal_store: nil) ⇒ ForgetCustomer
Returns a new instance of ForgetCustomer.
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
# File 'lib/insika/commands/forget_customer.rb', line 27 def initialize(memory_store:, session_store:, tool_trace_store: nil, context_trace_store: nil, model_visible_trace_store: nil, task_store: nil, checkpoint_store: nil, outbox_store: nil, shadow_pairs: nil, audit_store: nil, event_stream:, followup_store: nil, contact_store: nil, proposal_store: nil) @memory_store = memory_store @session_store = session_store @tool_trace_store = tool_trace_store @context_trace_store = context_trace_store @model_visible_trace_store = model_visible_trace_store # ; nil = parity @task_store = task_store @checkpoint_store = checkpoint_store @outbox_store = outbox_store @shadow_pairs = shadow_pairs @audit_store = audit_store @event_stream = event_stream @followup_store = followup_store # ; nil = nothing to sweep @contact_store = contact_store # ; nil = nothing to sweep @proposal_store = proposal_store # ; nil = nothing to sweep end |
Instance Method Details
#call(command) ⇒ Object
-> { customer:, tenant:, memory_records:, sessions: [], tasks:, checkpoints:, deliveries:, followups:, contacts: }.
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 |
# File 'lib/insika/commands/forget_customer.rb', line 50 def call(command) customer = Coercion.presence(command.payload[:customer] || command.payload["customer"]) raise ValidationError, "customer is required" if customer.nil? tenant = command.[:tenant] || Coercion.presence(command.payload[:tenant] || command.payload["tenant"]) memory_scope = [tenant, customer].compact.join(":") memory_records = @memory_store.purge(tenant: memory_scope) # the follow-up footprint dies with the person — the # schedule records and the contact cell (LGPD). followups = @followup_store&.purge_customer(tenant: tenant, customer: customer) || 0 contacts = @contact_store&.delete(tenant: tenant, customer: customer) ? 1 : 0 # the distilled PROPOSALS die with the person — a proposal # is born inside a customer cell (D6), so forget_customer reaches it. proposals = @proposal_store&.purge_customer(tenant: tenant, customer: customer) || 0 sessions = session_ids_for(customer, tenant) purged = purge_sessions(sessions) # the audit records the thing that happened, content-free — # a digest-free line with the counts (the deleted VALUES never enter # the audit store). Written AFTER the purge, so the line describes a # deletion that actually happened. nil audit_store = no-op. @audit_store&.record( cell: @memory_store.cell_for(tenant, customer), action: "purge", actor: operator(command), tenant: tenant, customer: customer, note: "memory_records: #{memory_records}, sessions: #{sessions.size}" ) @event_stream.emit(Insika::Event.new( type: :customer_forgotten, data: { customer: customer, tenant: tenant, memory_records: memory_records, sessions: sessions, followups: followups, contacts: contacts, proposals: proposals }.merge(purged), meta: { at: Time.now.utc.iso8601 } )) { customer: customer, tenant: tenant, memory_records: memory_records, sessions: sessions, followups: followups, contacts: contacts, proposals: proposals }.merge(purged) end |