specs/001-core-engine/requirements.md
Rama main · réplica de lectura del repositorio original.
# Core Engine - Requirements
## 1. Introduction
The Core Engine is the foundational feature of daybrief.ai that implements the complete content pipeline: source management, content ingestion, AI-powered processing, briefing configuration, and report generation. This MVP focuses on RSS feed support and backend API implementation.
## 2. Alignment with Product Vision
This feature implements the core value proposition from product.md:
- **Source Management** (§5.1): RSS feed subscription and management
- **Content Processing** (§5.2): Fetch, parse, summarize, score, and tag pipeline
- **Daily Briefing** (§5.3): Configurable briefings with AI-filtered content delivery
The engine enables the "reads for you, thinks like you, briefs you" workflow for knowledge professionals.
## 3. Functional Requirements
### 3.1 Source Management
**US-3.1.1: Add RSS Source**
> As a user, I want to add an RSS feed URL as a source, so that news items from that feed are ingested into the system.
Acceptance Criteria:
- User provides: URL, name (optional, auto-detected from feed), category/tags (optional)
- System validates URL is a valid RSS/Atom feed
- System stores source with status: ACTIVE, PAUSED, ERROR
- Source is linked to the user who created it
- Duplicate URL detection per user
**US-3.1.2: List Sources**
> As a user, I want to view all my sources, so that I can manage my content feeds.
Acceptance Criteria:
- Returns list of sources with: id, name, url, type, status, lastFetchedAt, itemCount, createdAt
- Support filtering by status
- Support pagination
**US-3.1.3: Update Source**
> As a user, I want to update my source settings, so that I can change name, tags, or status.
Acceptance Criteria:
- User can update: name, tags, status (ACTIVE/PAUSED)
- Cannot change URL (must delete and recreate)
**US-3.1.4: Delete Source**
> As a user, I want to delete a source, so that it stops being fetched.
Acceptance Criteria:
- Soft delete: marks source as DELETED
- News items from source remain in system but are not included in future briefings
### 3.2 News Ingestion Engine
**US-3.2.1: Fetch RSS Feeds**
> As the system, I want to periodically fetch RSS feeds, so that new items are ingested.
Acceptance Criteria:
- Scheduler runs every 15 minutes (configurable)
- Fetches only ACTIVE sources
- Respects HTTP caching headers (ETag, Last-Modified)
- Rate limiting: max 1 request per source per 5 minutes
- Updates source.lastFetchedAt and source.lastError on completion
**US-3.2.2: Parse Feed Items**
> As the system, I want to parse RSS/Atom items into normalized NewsItem entities.
Acceptance Criteria:
- Extract: title, link, publishedAt, author, content/description, guid
- Deduplicate by guid per source
- Store raw content and cleaned content (HTML stripped)
- Set status: PENDING (awaiting processing)
### 3.3 News Processing Pipeline
**US-3.3.1: Summarize News Item**
> As the system, I want to generate a summary for each news item, so that users get concise content.
Acceptance Criteria:
- Generate 2-3 sentence summary using LLM
- Store summary alongside original content
- Mark item as SUMMARIZED after completion
**US-3.3.2: Tag News Item**
> As the system, I want to auto-categorize news items, so that they can be filtered and organized.
Acceptance Criteria:
- Extract: topics (list), entities (people, companies, technologies), sentiment (positive/neutral/negative)
- Store tags as JSON structure on NewsItem
- Mark item as TAGGED after completion
**US-3.3.3: Score News Item**
> As the system, I want to score news items against user criteria, so that relevance can be determined per briefing.
Acceptance Criteria:
- Scoring is per-briefing (same news item has different scores for different briefings)
- Score range: 0-100
- Score computed using LLM with user's briefing criteria as context
- Store score in BriefingNewsScore join entity
**US-3.3.4: Process Pipeline Orchestration**
> As the system, I want to process news items through the complete pipeline.
Acceptance Criteria:
- Pipeline: PENDING → SUMMARIZED → TAGGED → PROCESSED
- Failed items marked with status ERROR and error message
- Retry logic: max 3 attempts with exponential backoff
- Processing triggered by scheduler or on-demand
### 3.4 DayBrief Configuration
**US-3.4.1: Create DayBrief**
> As a user, I want to create a DayBrief, so that I can receive personalized briefings.
Acceptance Criteria:
- User provides: title, description, sourceIds (one or more)
- User provides: briefing (text describing goals/interests for AI filtering)
- User provides: frequency (DAILY, WEEKLY)
- User provides: scheduleTime (time of day for delivery, in user's timezone)
- DayBrief linked to user
- Default status: ACTIVE
**US-3.4.2: List DayBriefs**
> As a user, I want to view all my DayBriefs, so that I can manage my briefings.
Acceptance Criteria:
- Returns list with: id, title, description, frequency, scheduleTime, status, lastExecutedAt, sourceCount
- Support filtering by status
**US-3.4.3: Update DayBrief**
> As a user, I want to update my DayBrief settings.
Acceptance Criteria:
- User can update: title, description, sourceIds, briefing, frequency, scheduleTime, status
**US-3.4.4: Delete DayBrief**
> As a user, I want to delete a DayBrief, so that it stops executing.
Acceptance Criteria:
- Soft delete: marks DayBrief as DELETED
- Past reports remain accessible
- Can be restored within 30 days
### 3.5 Briefing Execution & Report Generation
**US-3.5.1: Execute Briefing**
> As the system, I want to execute a DayBrief on schedule, so that users receive their reports.
Acceptance Criteria:
- Scheduler checks for due briefings based on frequency and scheduleTime
- Collect news items from linked sources since last execution
- Filter items where publishedAt > lastExecutedAt
- Score each item against briefing criteria using LLM
- Select top N items (configurable, default 10) by score
- Create DailyReport with selected items
- Update DayBrief.lastExecutedAt
**US-3.5.2: Generate Daily Report**
> As the system, I want to generate a DailyReport, so that users can view their briefing results.
Acceptance Criteria:
- DailyReport contains: id, dayBriefId, generatedAt, items (ordered by score)
- Each item includes: newsItemId, score, title, summary, link, publishedAt
- Report status: PENDING → GENERATED
- Store report for user access
**US-3.5.3: View Daily Report**
> As a user, I want to view a generated report, so that I can read my briefing.
Acceptance Criteria:
- Returns full report with all items and metadata
- Includes DayBrief title and description for context
**US-3.5.4: List Daily Reports**
> As a user, I want to view past reports for a DayBrief, so that I can access historical briefings.
Acceptance Criteria:
- Returns paginated list of reports for a DayBrief
- Ordered by generatedAt descending
- Include: id, generatedAt, itemCount
### 3.6 News Item Access
**US-3.6.1: View News Item**
> As a user, I want to view a full news item, so that I can read the complete content.
Acceptance Criteria:
- Returns: id, title, link, publishedAt, author, content, summary, tags, sourceId
- Only accessible if news item belongs to one of user's sources
**US-3.6.2: Search News Items**
> As a user, I want to search through ingested news items, so that I can find specific content.
Acceptance Criteria:
- Full-text search on title and content
- Filter by: sourceId, dateRange, tags
- Returns paginated results with: id, title, summary, publishedAt, sourceName
- Results limited to user's sources
## 4. Non-Functional Requirements
### 4.1 Architecture
- Follow existing package structure: model, repository, service, controller, dto
- Services must be channel-agnostic (no DTOs, only entities)
- Use JPA relationships for entity associations
- New entities: Source, NewsItem, DayBrief, DailyReport, BriefingNewsScore
- Have a proper abstraction so we can easily additional type of sources
- Processing jobs use Spring's @Scheduled or @Async with configurable thread pool
- LLM integration via abstracted provider interface (similar to existing StorageProvider pattern)
### 4.2 Performance
- RSS fetch timeout: 30 seconds max
- Database indexes on where needed
- Pagination default: 20 items, max 100
### 4.3 Security
- All endpoints require authentication (JWT)
- Users can only access their own sources, dayBriefs, and reports
- Source URLs validated to prevent SSRF (whitelist protocols: http, https)
- Rate limit source creation: 50 per user
### 4.4 Reliability
- Idempotent news item creation (dedupe by guid)
- Failed processing items retried with exponential backoff
- Source fetch errors logged and surfaced in source status
- Scheduler resilient to individual job failures
### 4.5 Data Model Summary
```
Source
- id: UUID
- userId: UUID (FK)
- name: String
- url: String
- type: Enum (RSS)
- status: Enum (ACTIVE, PAUSED, ERROR, DELETED)
- tags: String[]
- lastFetchedAt: DateTime
- lastError: String
- createdAt: DateTime
- updatedAt: DateTime
NewsItem
- id: UUID
- sourceId: UUID (FK)
- guid: String (unique per source)
- title: String
- link: String
- author: String
- publishedAt: DateTime
- rawContent: Text
- cleanContent: Text
- summary: Text
- tags: JSON (topics, entities, sentiment)
- status: Enum (PENDING, SUMMARIZED, TAGGED, PROCESSED, ERROR)
- errorMessage: String
- createdAt: DateTime
- updatedAt: DateTime
DayBrief
- id: UUID
- userId: UUID (FK)
- title: String
- description: String
- briefing: Text (user's goals/interests)
- frequency: Enum (DAILY, WEEKLY)
- scheduleTime: Time
- timezone: String
- status: Enum (ACTIVE, PAUSED, DELETED)
- lastExecutedAt: DateTime
- createdAt: DateTime
- updatedAt: DateTime
DayBriefSource (join table)
- dayBriefId: UUID (FK)
- sourceId: UUID (FK)
DailyReport
- id: UUID
- dayBriefId: UUID (FK)
- generatedAt: DateTime
- status: Enum (PENDING, GENERATED, ERROR)
- createdAt: DateTime
ReportItem
- id: UUID
- reportId: UUID (FK)
- newsItemId: UUID (FK)
- score: Integer (0-100)
- position: Integer (ordering)
```
### 4.6 API Endpoints Summary
```
Sources:
POST /api/v1/sources - Create source
GET /api/v1/sources - List sources
GET /api/v1/sources/{id} - Get source
PUT /api/v1/sources/{id} - Update source
DELETE /api/v1/sources/{id} - Delete source
News Items:
GET /api/v1/news - Search/list news items
GET /api/v1/news/{id} - Get news item
DayBriefs:
POST /api/v1/daybriefs - Create daybrief
GET /api/v1/daybriefs - List daybriefs
GET /api/v1/daybriefs/{id} - Get daybrief
PUT /api/v1/daybriefs/{id} - Update daybrief
DELETE /api/v1/daybriefs/{id} - Delete daybrief
Reports:
GET /api/v1/daybriefs/{id}/reports - List reports for daybrief
GET /api/v1/daybriefs/{id}/reports/{reportId} - Get specific report
POST /api/v1/daybriefs/{id}/execute - Manually trigger briefing execution
```