ci / verify (push) Canceled after 0s
Add customer and operator login, BLE provisioning, device fleet controls, call memory, memoir generation, and refreshed family and maintenance portals. Include API contracts, migrations, firmware sources, tests, assets, and deployment documentation.
68 lines
3.9 KiB
Go
68 lines
3.9 KiB
Go
package callmemory
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/jackc/pgx/v5"
|
|
)
|
|
|
|
// Story references and direct-call references must resolve to the same source
|
|
// graph. A direct source deletion invalidates every story that quotes it, but
|
|
// must not erase unrelated utterances that happen to appear in those stories.
|
|
const storySourceCleanupCTE = `WITH refs AS (
|
|
SELECT r FROM memory_source_suppression s JOIN curated_memory cm ON cm.id=s.memory_id
|
|
CROSS JOIN LATERAL jsonb_array_elements(s.source_refs) r
|
|
WHERE cm.subject_id=$1::uuid AND s.subject_id=cm.subject_id AND s.scope='SOURCE_AND_DERIVED'
|
|
AND cm.public_id IN(SELECT value::uuid FROM jsonb_array_elements_text($2::jsonb))
|
|
), named_stories AS (
|
|
SELECT DISTINCT sd.id FROM story_draft sd JOIN refs ON sd.public_id::text=r->>'story_id'
|
|
WHERE sd.subject_id=$1::uuid
|
|
), call_sources AS (
|
|
SELECT c.id AS session_id,r->>'utterance_id' AS utterance_id FROM call_session c
|
|
JOIN refs ON c.id::text=r->>'session_id'
|
|
WHERE c.subject_id=$1::uuid
|
|
UNION
|
|
SELECT ss.call_session_id,ss.call_utterance_id FROM story_source ss
|
|
JOIN story_revision sr ON sr.id=ss.story_revision_id JOIN named_stories ns ON ns.id=sr.story_id
|
|
WHERE ss.call_session_id IS NOT NULL
|
|
), import_sources AS (
|
|
SELECT ss.import_turn_id AS turn_id FROM story_source ss
|
|
JOIN story_revision sr ON sr.id=ss.story_revision_id JOIN named_stories ns ON ns.id=sr.story_id
|
|
WHERE ss.import_turn_id IS NOT NULL
|
|
UNION
|
|
SELECT it.id FROM memoir_import_turn it JOIN memoir_chat_import ci ON ci.id=it.import_id
|
|
JOIN refs ON ci.id::text=r->>'import_id' AND (r->>'turn_id' IS NULL OR it.id::text=r->>'turn_id')
|
|
WHERE ci.subject_id=$1::uuid
|
|
), stories AS (
|
|
SELECT id FROM named_stories
|
|
UNION
|
|
SELECT sr.story_id FROM story_source ss JOIN story_revision sr ON sr.id=ss.story_revision_id
|
|
JOIN story_draft sd ON sd.id=sr.story_id
|
|
JOIN call_sources cs ON cs.session_id=ss.call_session_id AND (cs.utterance_id IS NULL OR cs.utterance_id=ss.call_utterance_id)
|
|
WHERE sd.subject_id=$1::uuid
|
|
UNION
|
|
SELECT sr.story_id FROM story_source ss JOIN story_revision sr ON sr.id=ss.story_revision_id
|
|
JOIN story_draft sd ON sd.id=sr.story_id JOIN import_sources i ON i.turn_id=ss.import_turn_id
|
|
WHERE sd.subject_id=$1::uuid
|
|
) `
|
|
|
|
func (s *Service) cleanStorySources(ctx context.Context, tx pgx.Tx, subject string, targets []byte) error {
|
|
statements := []string{
|
|
`UPDATE call_utterance u SET text_content='[deleted]' FROM call_sources cs WHERE u.session_id=cs.session_id AND (cs.utterance_id IS NULL OR u.utterance_id=cs.utterance_id)`,
|
|
`UPDATE call_text_fragment f SET text_content='[deleted]' FROM call_sources cs WHERE f.session_id=cs.session_id AND (cs.utterance_id IS NULL OR f.utterance_id=cs.utterance_id)`,
|
|
`UPDATE call_event ev SET payload='{"redacted":true}'::jsonb FROM call_sources cs WHERE ev.session_id=cs.session_id AND (cs.utterance_id IS NULL OR ev.payload->'payload'->>'utterance_id'=cs.utterance_id)`,
|
|
`UPDATE conversation_turn ct SET final_text='[deleted]' WHERE ct.id IN(SELECT ss.conversation_turn_id FROM story_source ss JOIN story_revision sr ON sr.id=ss.story_revision_id JOIN named_stories ns ON ns.id=sr.story_id)`,
|
|
`UPDATE memoir_import_turn SET content='[deleted]' WHERE id IN(SELECT turn_id FROM import_sources)`,
|
|
`UPDATE story_revision SET content='[deleted]',edit_reason=NULL WHERE story_id IN(SELECT id FROM stories)`,
|
|
`UPDATE fact_candidate_revision fcr SET content='[deleted]',edit_reason=NULL FROM fact_candidate fc WHERE fcr.fact_candidate_id=fc.id AND fc.story_id IN(SELECT id FROM stories)`,
|
|
`UPDATE fact_candidate SET content='[deleted]',status='SUPERSEDED',review_reason=NULL WHERE story_id IN(SELECT id FROM stories)`,
|
|
`UPDATE story_draft SET title='[deleted]',status='SUPERSEDED',review_reason='source deleted' WHERE id IN(SELECT id FROM stories)`,
|
|
}
|
|
for _, statement := range statements {
|
|
if _, err := tx.Exec(ctx, storySourceCleanupCTE+statement, subject, targets); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|