pub struct DataSubjectService {
index: SqliteBackend,
vector: Option<Arc<dyn VectorBackend + Send + Sync>>,
}Expand description
Service for GDPR data subject rights operations.
Provides:
export_user_data(): Export all user data (Article 20)delete_user_data(): Delete all user data (Article 17)
§Storage Layers
Operations affect all three storage layers:
- Persistence (
SQLite) - Authoritative storage - Index (
SQLiteFTS5) - Full-text search index - Vector (usearch) - Embedding vectors
§Audit Logging
All operations are logged for compliance:
gdpr.export- Data export requestsgdpr.delete- Data deletion requests
Fields§
§index: SqliteBackendSQLite index backend for listing and deleting memories.
vector: Option<Arc<dyn VectorBackend + Send + Sync>>Optional vector backend for deleting embeddings.
Implementations§
Source§impl DataSubjectService
impl DataSubjectService
Sourcepub const fn new(index: SqliteBackend) -> Self
pub const fn new(index: SqliteBackend) -> Self
Creates a new data subject service with an index backend.
§Arguments
index-SQLiteindex backend for memory operations
Sourcepub fn with_vector(self, vector: Arc<dyn VectorBackend + Send + Sync>) -> Self
pub fn with_vector(self, vector: Arc<dyn VectorBackend + Send + Sync>) -> Self
Adds a vector backend for complete deletion of embeddings.
Sourcepub fn export_user_data(&self) -> Result<UserDataExport>
pub fn export_user_data(&self) -> Result<UserDataExport>
Exports all user data in a portable format.
Implements GDPR Article 20 (Right to Data Portability).
§Returns
A UserDataExport containing all memories in JSON-serializable format.
§Errors
Returns an error if:
- The index backend fails to list memories
- Memory retrieval fails
§Audit
Logs a gdpr.export event with the count of exported memories.
§Example
let service = DataSubjectService::new(index);
let export = service.export_user_data()?;
// Serialize to JSON for download
let json = serde_json::to_string_pretty(&export)?;
std::fs::write("my_data.json", json)?;Sourcepub fn delete_user_data(&self) -> Result<DeletionResult>
pub fn delete_user_data(&self) -> Result<DeletionResult>
Deletes all user data from all storage layers.
Implements GDPR Article 17 (Right to Erasure / “Right to be Forgotten”).
§Storage Layers Affected
- Index (
SQLite) - Memory metadata and FTS index - Vector (usearch) - Embedding vectors (if configured)
- Persistence (
SQLite) - Authoritative storage (if configured)
§Returns
A DeletionResult with counts and any failures.
§Errors
Returns an error if:
- The index backend fails to list memories
- Critical deletion operations fail
Note: Individual memory deletion failures are captured in the result rather than causing the entire operation to fail.
§Audit
Logs a gdpr.delete event with the count of deleted memories.
§Warning
This operation is irreversible. All user data will be permanently deleted.
§Example
let service = DataSubjectService::new(index)
.with_vector(vector_backend);
let result = service.delete_user_data()?;
if result.complete {
println!("Successfully deleted {} memories", result.deleted_count);
} else {
eprintln!("Partial deletion: {} failed", result.failed_count);
}Sourcefn delete_memory_from_all_layers(&self, id: &MemoryId) -> Result<()>
fn delete_memory_from_all_layers(&self, id: &MemoryId) -> Result<()>
Deletes a single memory from all storage layers.
§Deletion Order
- Vector backend (if configured) - Delete embedding
SQLiteIndex - Delete from search index (authoritative)
Sourcepub fn record_consent(&self, record: &ConsentRecord) -> Result<()>
pub fn record_consent(&self, record: &ConsentRecord) -> Result<()>
Records consent for a specific purpose.
Implements GDPR Article 7 (Conditions for Consent).
§Arguments
record- The consent record to store
§Audit
Logs a gdpr.consent event with the purpose and grant status.
§Example
use subcog::services::{DataSubjectService, ConsentRecord, ConsentPurpose};
let service = DataSubjectService::new(index);
let record = ConsentRecord::grant(ConsentPurpose::DataStorage, "1.0")
.with_method("cli");
service.record_consent(&record)?;§Errors
Returns an error if consent recording fails.
Sourcepub fn revoke_consent(
&self,
purpose: ConsentPurpose,
policy_version: &str,
) -> Result<()>
pub fn revoke_consent( &self, purpose: ConsentPurpose, policy_version: &str, ) -> Result<()>
Revokes consent for a specific purpose.
Creates a revocation record and logs the event for audit.
§Arguments
purpose- The purpose for which consent is being revokedpolicy_version- The current policy version
§Audit
Logs a gdpr.consent_revoked event.
§Errors
Returns an error if consent revocation fails.
Sourcepub fn has_consent(&self, purpose: ConsentPurpose) -> bool
pub fn has_consent(&self, purpose: ConsentPurpose) -> bool
Sourcepub fn consent_status(&self) -> ConsentStatus
pub fn consent_status(&self) -> ConsentStatus
Returns the current consent status for all purposes.
§Returns
A ConsentStatus with the current state of all consents.
Sourcefn log_consent_event(record: &ConsentRecord)
fn log_consent_event(record: &ConsentRecord)
Logs a consent event to the audit log.
Sourcefn log_export_event(memory_count: usize)
fn log_export_event(memory_count: usize)
Logs an export event to the audit log.
Sourcefn log_deletion_event(deleted_count: usize, failed_count: usize)
fn log_deletion_event(deleted_count: usize, failed_count: usize)
Logs a deletion event to the audit log.
Auto Trait Implementations§
impl !Freeze for DataSubjectService
impl !RefUnwindSafe for DataSubjectService
impl Send for DataSubjectService
impl Sync for DataSubjectService
impl Unpin for DataSubjectService
impl !UnwindSafe for DataSubjectService
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
§impl<T> FutureExt for T
impl<T> FutureExt for T
§fn with_context(self, otel_cx: Context) -> WithContext<Self>
fn with_context(self, otel_cx: Context) -> WithContext<Self>
§fn with_current_context(self) -> WithContext<Self>
fn with_current_context(self) -> WithContext<Self>
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more§impl<T> IntoRequest<T> for T
impl<T> IntoRequest<T> for T
§fn into_request(self) -> Request<T>
fn into_request(self) -> Request<T>
T in a tonic::Request§impl<L> LayerExt<L> for L
impl<L> LayerExt<L> for L
§fn named_layer<S>(&self, service: S) -> Layered<<L as Layer<S>>::Service, S>where
L: Layer<S>,
fn named_layer<S>(&self, service: S) -> Layered<<L as Layer<S>>::Service, S>where
L: Layer<S>,
Layered].