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 Category → CategoryService::findById(categoryId)
  2. Map request → KnowledgeMapper::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. Persist → KnowledgePersistenceService::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 mrkdwn — SlackDigestDeliveryService converts links, bold, headers
  2. Send via Slack DM — SlackMessageTransport POSTs to the Slack bot's Express API
  3. Bot delivers DM — client.chat.postMessage() sends the formatted digest
  4. Log delivery — DigestDeliveryLogService::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