Skip to content

Delete Memory API

Plan Metadata

  • Plan type: plan
  • Parent plan: N/A
  • Depends on: N/A
  • docs/plans/memory-fetch-display.md (Memory data model)
  • docs/plans/memory-enrichment-flow.md (Existing memory processing)
  • Status: documentation

Status semantics: - draft: Plan is being created or updated and is not final. - approved: Plan is approved but not yet applied in code. - documentation: Code currently exists and matches the plan contract.

System Intent

  • What is being built: A delete memory API endpoint and UI component that allows users to permanently remove a memory from their feed and delete all associated assets from S3. The UI consists of a hamburger menu button in the top-right corner of an opened memory card, which displays a dropdown menu with a delete option.

  • Primary consumer(s): Mobile app users viewing memories in the feed; frontend MemoryViewer component; backend API consumers.

  • Boundary (black-box scope only):

  • Input: User interaction (click menu button → click delete option) + memory ID
  • Processing: Delete database records, delete S3 assets, update frontend state
  • Output: Success/error response, UI state update (memory removed from feed)

Stage Gate Tracker

  • [x] Stage 1 Mermaid approved
  • [x] Stage 2 I/O contracts approved
  • [x] Stage 3 pseudocode/technical details approved or skipped

1. Mermaid Diagram

Reference: .agent/skills/create-mermaid-diagram/SKILL.md

graph TD
    MemoryViewer["memory-viewer-modal.tsx — components/memory/memory-viewer-modal.tsx"]:::unchanged
    DeleteMenu["memory-delete-menu.tsx — components/memory/memory-delete-menu.tsx"]:::unchanged
    DeleteClient["deleteMemory.ts — lib/api/memory/deleteMemory.ts"]:::unchanged
    DeleteEndpoint["delete app.py — api/memories/delete/app.py"]:::unchanged
    DynamoDB["DynamoDB — external"]:::unchanged
    S3["S3 — external"]:::unchanged

    MemoryViewer -->|"memory_id + open menu event"| DeleteMenu
    DeleteMenu -->|"confirmed delete request with memory_id"| DeleteClient
    DeleteClient -->|"DELETE /api/memories/:id with auth token"| DeleteEndpoint
    DeleteEndpoint -->|"delete record by memory_id"| DynamoDB
    DeleteEndpoint -->|"delete all assets by memory_id prefix"| S3
    DynamoDB -->|"deletion confirmation"| DeleteEndpoint
    S3 -->|"deletion confirmation"| DeleteEndpoint
    DeleteEndpoint -->|"DeleteMemoryResponse"| DeleteClient
    DeleteClient -->|"success or error result"| DeleteMenu
    DeleteMenu -->|"remove memory from feed"| MemoryViewer

classDef unchanged fill:#d3d3d3,stroke:#666,stroke-width:1px;
classDef updated fill:#ffe58a,stroke:#666,stroke-width:1px;
classDef deleted fill:#f4a6a6,stroke:#666,stroke-width:1px;
classDef created fill:#a8e6a3,stroke:#666,stroke-width:1px;

Stage 1 diagram shows the complete flow from user interaction through deletion and feedback.

2. Black-Box Inputs and Outputs

Keep this short. Define types in JSON-style blocks and capture each flow with path-level rows.

Global Types

MemoryId {
  value: string (stable unique identifier for a memory)
}

RequestMetadata {
  trace_id: string (request trace identifier)
  requested_at: timestamp (request timestamp)
}

StandardError {
  status: number (HTTP status)
  code: string (stable machine-readable code)
  message: string (human-readable summary)
}

DeleteMemoryResponse {
  success: boolean (whether deletion was successful)
  memory_id: MemoryId (the deleted memory ID)
  deleted_at: timestamp (when deletion occurred)
}

Flow: deleteMemoryFromMenu

  • Test files: app/__tests__/components/memory-viewer-delete.test.tsx, main/server/tests/integration/test_delete_memory_api.py
  • Core files: components/memory/memory-viewer-modal.tsx, api/memories/delete/app.py, lib/api/memory/deleteMemory.ts

Type Definitions

DeleteMemoryInput {
  memory_id: MemoryId (required, from URL path)
  request_metadata: RequestMetadata (trace context)
}

DeleteMemoryOutput {
  response: DeleteMemoryResponse (deletion confirmation)
}

DeleteMemoryError {
  status: number (400, 404, 500, etc.)
  code: string (invalid-id, not-found, internal-error, unauthorized)
  message: string (human-readable error)
}

Paths

path-name input output/expected state change path-type notes updated
deleteMemory.success DeleteMemoryInput DeleteMemoryResponse success=true; memory removed from feed, all S3 assets deleted (video, audio, thumbnails, transcripts, metadata), database record deleted happy path Database and S3 deletions are transactional; if S3 deletion fails, log error but respond success if DB deletion succeeded
deleteMemory.not-found DeleteMemoryInput DeleteMemoryError status=404 code=not-found message="Memory not found" error Memory ID does not exist in database; no state change
deleteMemory.unauthorized DeleteMemoryInput DeleteMemoryError status=403 code=unauthorized message="Not authorized to delete this memory" error User is not the owner of the memory; no state change
deleteMemory.invalid-id DeleteMemoryInput DeleteMemoryError status=400 code=invalid-id message="Invalid memory ID format" error Memory ID format is invalid; no state change
deleteMemory.s3-cleanup-partial DeleteMemoryInput DeleteMemoryResponse success=true (with optional warning) edge case Some S3 assets may already be deleted or inaccessible; endpoint succeeds if DB deletion succeeds regardless of S3 state

Flow: renderDeleteMenuUI

  • Test files: app/__tests__/components/memory-viewer-modal.test.tsx
  • Core files: components/memory/memory-viewer-modal.tsx, components/memory/memory-delete-menu.tsx

Type Definitions

MenuUIInput {
  memory_id: MemoryId (required)
  user_id: UserId (required, to check ownership)
  is_loading: boolean (whether deletion is in progress)
}

MenuUIState {
  menu_visible: boolean
  dropdown_open: boolean
  is_deleting: boolean
  error_message: string | null
}

Paths

path-name input output/expected state change path-type notes updated
renderMenu.default MenuUIInput Menu button visible in top-right; clicking opens dropdown happy path Menu only shown if user is owner of memory
deleteOption.click User click event API call triggered, is_deleting flag set, button disabled during request happy path UI should show loading state while request is pending
deleteMemory.success-ui Success response from API Memory card slides out/fades out, feed re-renders without deleted memory happy path Smooth transition animation; maintain scroll position if possible
deleteMemory.error-ui Error response from API Error message displayed in toast/alert, menu remains open or closes with error shown error User can retry or dismiss error

Stage 2 contracts define the API input/output types and all success/error paths with their expected behavior.

3. Pseudocode / Technical Details for Critical Flows (Optional)

Flow: deleteMemoryFromMenu

Backend (Python/FastAPI):

1. Extract memory_id from URL path
2. Authenticate request (verify JWT token)
3. Query DynamoDB for memory record with given ID
4. If not found, return 404 error
5. Check if authenticated user is owner of memory (compare user_id in memory record)
6. If not owner, return 403 unauthorized error
7. Begin transaction:
   a. Delete memory record from DynamoDB (delete main memory item)
   b. Query S3 for all objects with memory_id prefix
   c. Delete all S3 objects (video, audio, thumbnails, transcripts, metadata JSON)
   d. If S3 deletion has errors, log them but do not fail the transaction
   e. Commit database deletion
8. Return success response with deletion timestamp
9. If exception occurs: rollback transaction if possible, return 500 error

Frontend (TypeScript/React Native):

1. User clicks hamburger menu in MemoryViewer
2. Menu button opens dropdown with delete option
3. User clicks "Delete Memory" option
4. Show confirmation dialog: "Are you sure? This cannot be undone."
5. If user confirms:
   a. Send DELETE /api/memories/:id request
   b. Set is_deleting=true, disable UI interactions
   c. Show loading spinner
6. On success response:
   a. Update local state to remove memory from feed
   b. Trigger animation (fade out / slide away)
   c. Refetch feed or update cache to reflect deletion
   d. Show success toast: "Memory deleted"
7. On error response:
   a. Show error toast with message from server
   b. Reset is_deleting=false, re-enable menu
   c. Allow user to retry

  • Implementation notes:
  • Frontend confirmation dialog is critical to prevent accidental deletions
  • S3 deletion failures should not block the overall success response (user sees memory deleted, orphaned assets can be cleaned up by a separate job)
  • Consider implementing soft-delete first, with a grace period, if we want to support un-delete in the future
  • Ensure all S3 prefixes for a memory are deleted (video files, audio files, thumbnails, metadata, transcripts, etc.)
  • Track deletion in audit logs for compliance

Stage 3 pseudocode shows the detailed implementation strategy for both backend and frontend flows.

4. Plan Status

All planning stages are complete: - Stage 1: Mermaid diagram created and approved - Stage 2: Black-box input/output contracts defined - Stage 3: Pseudocode and technical implementation details specified

Ready for implementation phase.

After approval, apply .agent/skills/reconcile-plans/SKILL.md to propagate contract updates across linked plans.