Skip to content

MVP: Knowledge to AI Summaries to Digest — Complete E2E Flow

This document describes the complete end-to-end flow from sharing knowledge via Slack through AI summary generation, Notion synchronization, and digest distribution. This is the canonical reference for how the system works.


1. Knowledge Sharing (Input)

Users share knowledge via Slack using one of these entry points:

Entry PointTriggerHandler
Message ShortcutRight-click message → "Add to YapHub"shortcuts.ts
Global ShortcutLightning bolt → "Quick Add to YapHub"shortcuts.ts
App Home ButtonClick "Add Knowledge" in App Homeactions.ts

What the user sees:

  1. A modal opens with fields: Title, Content, Category (select), Tags, URL
  2. For message shortcuts, content and URL are pre-filled from the Slack message
  3. User submits the form

What happens on submission:

Slack Bot calls the backend API:

POST /api/knowledge
Body: { title, content, tags, categoryId, url, userId, targetGroups }

2. Knowledge Creation

Backend (KnowledgeOrchestrator::createKnowledge):

  1. Resolve CategoryCategoryService::findById(categoryId)
  2. Map requestKnowledgeMapper::fromCreateRequest()
  3. Extract URL content (if URL present) → ContentExtractionService::extractContent(url)
    • Fetches page HTML
    • Extracts text with Readability parser
    • Appends extracted content to user's text
  4. PersistKnowledgePersistenceService::create() → SQLite
  5. Sync to Notion (best-effort) → NotionSyncService::syncKnowledgeToNotion()
    • Creates Notion page with title, content, tags, status, URL, category
    • Stores notionId and notionUrl on the Knowledge entity

3. Digest Generation

When enough knowledge items accumulate, users generate digests via Slack UI or API.

Trigger

POST /api/digests/generate
Body: { categoryId, preset: "7 days", limit: 20, distributeNow: false }

The 7-Step Pipeline (DigestOrchestrator::generateDigest)

Step 1 — Resolve CategoryCategoryService::findById(categoryId) — look up the target category.

Step 2 — Parse Date RangeDateRangeParser::parse("7 days") — converts user input into concrete start/end dates. Supports Dutch ("laatste week") and English ("7 days").

Step 3 — Query KnowledgeKnowledgeRepository::findByCategoryAndDateRange(categoryId, start, end, limit) — fetch matching items.

Step 4 — Generate AI Highlights For each knowledge item, KnowledgeHighlightGenerator::generateHighlight():

  • Check if highlight already exists (lazy — skip if present)
  • Build prompt: sprintf(HIGHLIGHT_SUMMARY_PROMPT, title, url, content)
  • Call AiProviderInterface::generateCompletion(prompt, options) with temperature 0.3, max 150 tokens
  • Store result in Knowledge.highlight
  • Fallback: truncate content to 200 chars on AI failure

Step 5 — Format MarkdownDigestContentFormatter::formatDigestContent() — builds Dutch Markdown:

markdown
# DevOps & Infrastructure Kennisdigest
Periode: 01/05/2026 - 08/05/2026 | Gegenereerd op 08/05/2026
5 items in deze digest

---

### [Kubernetes Best Practices](https://notion.so/...) (3 minuten)
AI-generated 2-3 sentence Dutch summary...
`DevOps` `Kubernetes`

Step 6 — Create EntityDigestCreationService::createFromGenerationData():

  • Auto-generate title: "Digest: {Category} ({dateRange})"
  • Set content, statistics (highlightCount, days), knowledgeHighlights JSON snapshot
  • Link knowledge items via ManyToMany

Step 7 — Persist & SyncDigestPersistenceService::persistAndSync():

  • Save to SQLite
  • NotionSyncService::syncDigestToNotion() — create Notion page with properties + embed full Markdown content

4. Digest Distribution

Trigger

POST /api/digests/{id}/distribute
Body: { initiatorUserId: "U01234567" }

Recipient Resolution

  1. Query active subscribers for the digest's category: SubscriptionQueryService::findActiveSubscriptionsWithUsers(categoryId)
  2. Add the initiating user if not already in the list
  3. Deduplicate by userId

Delivery Flow

For each recipient:

  1. Convert Markdown to Slack mrkdwnSlackDigestDeliveryService converts links, bold, headers
  2. Send via Slack DMSlackMessageTransport POSTs to the Slack bot's Express API
  3. Bot delivers DMclient.chat.postMessage() sends the formatted digest
  4. Log deliveryDigestDeliveryLogService::logDelivery() creates/updates DigestDelivery entity

Delivery Tracking

Each delivery is tracked in a DigestDelivery entity:

  • Status: pending → sent (or failed)
  • Retry support: max 3 attempts via canRetry()
  • Failed deliveries can be retried: POST /api/digests/{id}/retry-failed

Sync to Notion

Distribution results are synced back to Notion — the digest page is updated with recipient list and distributed status.


5. Subscription System

Users subscribe to categories to receive digests:

ActionEndpointBehavior
SubscribePOST /api/subscriptions/subscribeCreates Subscription (userId + categoryId)
UnsubscribePOST /api/subscriptions/unsubscribeSoft-delete: isActive = false, unsubscribedAt = now
List user subsGET /api/subscriptions/user/{userId}Returns active subscriptions
List subscribersGET /api/subscriptions/category/{categoryId}/subscribersReturns subscriber user IDs

Unique constraint ensures one subscription per user per category.


6. Digest Scheduling

Categories with digest settings can generate digests automatically:

  1. DigestSchedulerService::processScheduledDigests() checks all digest-enabled categories
  2. For each: compares lastDigestAt + frequency interval against current time
  3. Checks configured day of week and time
  4. If due → triggers the full 7-step pipeline

Frequency options: weekly (7d), biweekly (14d), monthly (30d), quarterly (90d).


Complete Flow Diagram

┌─────────────────────────────────────────────────────────────────────┐
│                        USER VIA SLACK                                │
│  [Message Shortcut] [Global Shortcut] [App Home]                   │
│  Fill: Title, Content, Category, Tags, URL                          │
└───────────────────────────────┬─────────────────────────────────────┘

┌───────────────────────────────────────────────────────────────────┐
│                    KNOWLEDGE CREATION                              │
│  1. Resolve Category                                              │
│  2. Extract URL content (if URL present)                          │
│  3. Persist to SQLite                                             │
│  4. Sync to Notion (page + properties)                            │
└───────────────────────────────┬───────────────────────────────────┘

                        ┌───────────────┐
                        │  ACCUMULATE   │
                        │  Knowledge    │
                        │  Items        │
                        └───────┬───────┘

┌───────────────────────────────────────────────────────────────────┐
│                    DIGEST GENERATION (7 steps)                     │
│  1. Resolve Category                                              │
│  2. Parse Date Range                                              │
│  3. Query Knowledge by category + date range                      │
│  4. Generate AI Highlights (lazy — skip if exists)                │
│  5. Format as Dutch Markdown                                      │
│  6. Create Digest entity with snapshot                            │
│  7. Persist to SQLite + sync to Notion                            │
└───────────────────────────────┬───────────────────────────────────┘

┌───────────────────────────────────────────────────────────────────┐
│                    DIGEST DISTRIBUTION                             │
│  1. Resolve recipients (category subscribers + initiator)         │
│  2. For each recipient:                                           │
│     - Convert Markdown → Slack mrkdwn                             │
│     - Send via Slack DM                                           │
│     - Log delivery status (DigestDelivery entity)                 │
│  3. Update digest status to "sent"                                │
│  4. Sync distribution results to Notion                           │
└───────────────────────────────────────────────────────────────────┘

Key Technical References

ComponentFilePurpose
Knowledge Orchestratorbackend/src/Service/Orchestrator/KnowledgeOrchestrator.phpKnowledge creation + Notion sync
Digest Orchestratorbackend/src/Service/Orchestrator/DigestOrchestrator.php7-step digest pipeline
Highlight Generatorbackend/src/Service/Digest/KnowledgeHighlightGenerator.phpAI summary generation
AI Providerbackend/src/Service/Ai/OpenAIService.phpOpenAI/OpenRouter API calls
Distribution Servicebackend/src/Service/Digest/DigestDistributionService.phpSubscriber resolution + delivery
Slack Deliverybackend/src/Service/Slack/SlackDigestDeliveryService.phpMarkdown → mrkdwn + DM sending
Subscription Servicebackend/src/Service/Subscription/SubscriptionService.phpSubscribe/unsubscribe facade
Schedulerbackend/src/Service/Digest/DigestSchedulerService.phpCron-based digest scheduling
Notion Syncbackend/src/Service/Notion/NotionSyncService.phpBidirectional sync for all entities