Skip to content

feat(lex-apollo): identity persistence, access_scope enforcement (global/team/private), erasure compliance#23

Merged
Esity merged 5 commits into
mainfrom
worktree-phase3a-lex-apollo-identity-persistence
May 15, 2026
Merged

feat(lex-apollo): identity persistence, access_scope enforcement (global/team/private), erasure compliance#23
Esity merged 5 commits into
mainfrom
worktree-phase3a-lex-apollo-identity-persistence

Conversation

@Esity

@Esity Esity commented May 15, 2026

Copy link
Copy Markdown
Contributor

Summary

  • handle_ingest now accepts and persists access_scope, identity_principal_id, identity_id, identity_canonical_name to apollo_entries — populated automatically by legion-apollo's identity injection; defaults to access_scope: 'global' for backward compatibility
  • build_semantic_search_sql adds optional access-scope SQL filter when requesting_principal_id: is provided: global always visible, private owner-only (dual-path for multi-provider auth via both identity_principal_id FK and identities subquery), team via group membership join
  • handle_query and retrieve_relevant both accept and forward requesting_principal_id: — covers the GAIA path (via handle_query) and the direct-call path (via retrieve_relevant); browse-mode fallback (list_entries_chronologically) filtered too
  • Private-entry dedup guard: when access_scope: 'private', the content-hash dedup check is scoped per-principal so two different principals writing identical content each get their own row
  • handle_erasure_request now clears identity_principal_id, identity_id, identity_canonical_name on confirmed entries — GDPR right-to-erasure compliance gap closed

Prerequisites

  • Phase 1 (legion-data migrations 100–124) merged and deployed — apollo_entries needs access_scope, identity_principal_id, identity_id, identity_canonical_name columns
  • Phase 0 (legion-apollo identity injection) merged — Legion::Apollo.ingest already injects these kwargs

Test plan

  • handle_ingest forwards identity kwargs and access_scope to create_candidate_entry
  • handle_ingest defaults access_scope to 'global' when not provided
  • handle_ingest persists identity_id and identity_canonical_name
  • Private entries from different principals are not deduplicated (per-principal hash check)
  • build_semantic_search_sql without requesting_principal_id has no access_scope clause (backwards compatible)
  • build_semantic_search_sql with requesting_principal_id generates correct global/team/private SQL
  • handle_query forwards requesting_principal_id to build_semantic_search_sql
  • retrieve_relevant forwards requesting_principal_id to build_semantic_search_sql
  • handle_erasure_request clears identity FK columns on confirmed (redacted) entries
  • All 335 existing examples pass, 0 failures, rubocop clean

@Esity Esity requested a review from a team as a code owner May 15, 2026 23:51
@Esity Esity merged commit 7aa4360 into main May 15, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant