# Card Subdomain (DDD)

This document outlines the domain model for the Card feature, following Domain-Driven Design principles.

## Bounded Context

The Card context represents a system where users can save various types of content (URLs, notes, highlights, screenshots, files) to their personal libraries and collections.

## Domain Model

### Aggregates

1. **Card Aggregate**
   - Represents a saveable item (URL, note, highlight, screenshot, file)
   - Responsible for maintaining its own integrity
   - Contains references to related cards (highlights, notes, screenshots)
   - Does NOT directly manage which collections it belongs to

2. **Collection Aggregate**
   - Represents a user-defined grouping of cards
   - Manages which cards belong to it
   - Responsible for maintaining collection membership

### Entities

1. **Card** (Aggregate Root)
   - Has identity through CardId
   - Properties: type, content, metadata, creation date
   - May reference other cards (for highlights, notes, screenshots)

2. **Collection** (Aggregate Root)
   - Has identity through CollectionId
   - Properties: name, description, creation date
   - Contains references to member cards

### Value Objects

1. **CardId**
   - Unique identifier for a card

2. **CardType**
   - Enumeration of possible card types (URL, Note, Highlight)

3. **CardContent**
   - Value object representing the content of a card with type-specific validation
   - URL cards contain URL and optional UrlMetadata
   - Note cards contain text and optional title
   - Highlight cards contain highlighted text with robust anchoring using multiple selectors (TextQuote, TextPosition, Range) following Hypothes.is approach for reliable re-anchoring

4. **CollectionId**
   - Unique identifier for a collection

5. **CuratorId**
   - References the user who owns/created the card or collection

6. **URL**
   - Value object representing a valid URL

7. **UrlMetadata**
   - Value object containing metadata about a URL (title, description, author, etc.)

## Domain Services

1. **LibraryService**
   - Coordinates operations that span multiple aggregates
   - Handles adding cards to a user's library and collections
   - Provides access to a user's entire content (their "library")

## Infrastructure Services

1. **IMetadataService**
   - Interface for external metadata retrieval services
   - Abstracts the details of specific metadata providers (Citoid, etc.)

2. **IUrlMetadataRepository**
   - Repository interface for storing and retrieving URL metadata
   - Provides caching layer for metadata to avoid repeated API calls

## Relationships and Boundaries

- **Card-Collection Relationship**: This is a many-to-many relationship. A card can be in multiple collections, and a collection can contain multiple cards.
- **Aggregate Boundaries**:
  - The Card aggregate is responsible for its own data and direct relationships to other cards.
  - The Collection aggregate manages which cards are members of the collection.
  - When adding a card to a collection, the operation is handled by the Collection aggregate.

- **Card-to-Card Relationships**:
  - URL cards are standalone and do not reference other cards
  - Note cards can be standalone or reference other cards via parentCardId
  - Highlight cards must reference a parent card (the content being highlighted) via parentCardId
  - These relationships are maintained within the Card aggregate with validation rules

## Use Cases

1. **AddCardToLibrary**
   - Adds a new card to a user's library
   - May also add the card to one or more collections
   - May create related cards (notes, highlights, screenshots)

2. **AddCardToCollection**
   - Adds an existing card to a collection

3. **AnnotateCard**
   - Creates annotation cards (notes, highlights) linked to an existing card

4. **GetUrlMetadataUseCase**
   - Retrieves metadata for a given URL
   - First checks if metadata already exists in the repository
   - If not found, fetches from external metadata service (e.g., Citoid API)
   - Stores retrieved metadata for future use

## Implementation Considerations

- When a card is added to multiple collections, this should be handled as separate operations on each Collection aggregate.
- The LibraryService domain service coordinates operations that span multiple aggregates.
- Card-to-card relationships (like highlights of a URL) are maintained within the Card aggregate.
- "Library" is a conceptual grouping of a user's content rather than an aggregate with its own identity and lifecycle.
- A user's library is accessed through repository methods (e.g., `findByCuratorId()`) and coordinated through the LibraryService.

### External API Integration Patterns

- **Repository Pattern**: Use `IUrlMetadataRepository` to abstract metadata storage and provide caching
- **Service Interface**: Use `IMetadataService` to abstract external API calls (Citoid, etc.)
- **Dependency Inversion**: Domain layer depends on interfaces, infrastructure layer implements them
- **Caching Strategy**: Check repository first before making external API calls to reduce latency and API usage
- **Error Handling**: External API failures should be handled gracefully with fallback strategies
