Skip to content

LAYERED ARCHITECTURE


Naming Conventions

Entity-Specific Services

{Entity}PersistenceService    = CRUD operations on LOCAL database only
                                 (Create, Read, Update, Delete + persistence)
                                 Example: KnowledgePersistenceService
                                 Location: Service/Knowledge/
                                 Base: extends BasePersistenceService<TEntity, TRepository>
                                 Rule: ALWAYS final class.
                                 Rule: Receives injected repository, NOT EntityManager.

{Entity}Orchestrator          = Business logic orchestration + workflows
                                 (Orchestrates Persistence + Notion sync)
                                 Example: KnowledgeOrchestrator
                                 Location: Service/Knowledge/
                                 Base: extends BaseOrchestrator
                                 Rule: ALWAYS final class.
                                 Rule: Uses concrete NotionSync{Entity} type-hints, NOT
                                       NotionSyncInterface (avoids DI ambiguity).
                                 Rule: Uses MapperRegistry with MapperNames constants,
                                       NOT direct mapper injection.

NotionSync{Entity}            = Entity-specific sync implementation
                                 (Bidirectional sync: Local ↔ Notion)
                                 Example: NotionSyncKnowledge
                                 Location: Service/Notion/Sync/
                                 Base: extends AbstractNotionSync implements NotionSyncInterface

{Entity}ResolutionService      = Entity resolution from an opaque identifier
                                 (Normalizes IDs, checks local DB via QueryService, name lookup)
                                 Example: CategoryResolutionService
                                 Location: Service/{Domain}/
                                 Base: extends BaseResolutionService
                                 Pattern: Strategy Pattern (Strategies: ID, NotionID, Name)
                                 Rule: ALWAYS final class.
                                 Rule: READ-ONLY. Must NOT use PersistenceService.
                                 Rule: ALWAYS delegated to by orchestrators when mapping external
                                       identifiers (from API requests, Slack events) to entities.

{Entity}QueryService           = Domain-level read queries + Notion repository gateway
                                 (Search, filter, list, date range, findAll, getNotionRepository())
                                 Example: KnowledgeQueryService
                                 Location: Service/{Domain}/
                                 Base: extends BaseQueryService<TEntity, TRepository>
                                 Rule: ALWAYS final class.
                                 Rule: READ-ONLY queries only — no mutations.
                                 Rule: Used by ResolutionServices as their data source.
                                 Rule: Used by Orchestrators for domain searches and Notion sync
                                       (via getNotionRepository()). NOT for entity-by-ID lookup
                                       (that belongs to ResolutionService).

Cross-Entity Services

NotionSyncService             = Top-level sync orchestrator for all entity syncs
  (transitional)                (Currently named NotionSyncService; will be renamed to
                                 NotionSyncOrchestrator to match origin/dev)
                                 (Delegates to NotionSync{Entity} concrete services)
                                 Location: Service/Notion/
                                 Pattern: Delegates to concrete NotionSyncCategory,
                                          NotionSyncKnowledge via injected dependencies.
                                 Note: POC scope covers Knowledge + Category only.

NotionRepositoryManager       = Repository facade (smart repository selection)
                                 (Provides getKnowledgeRepository(), getCategoryRepository(),
                                  getLocalKnowledgeRepository(), etc.)
                                 Location: Service/Notion/
                                 Pattern: Facade Pattern

Repository Pattern

{Entity}Repository            = PostgreSQL access via Doctrine
                                 Example: KnowledgeRepository
                                 Location: Repository/
                                 Base: extends ServiceEntityRepository implements BaseRepositoryInterface

Notion{Entity}Repository      = Notion API access via NotionClient
                                 Example: NotionKnowledgeRepository
                                 Location: Service/Notion/
                                 Rule: Data access only — no logging (logging belongs in sync layer).

Service Responsibilities

Orchestrators

ServiceResponsibilities
KnowledgeOrchestratorCreate/update/delete knowledge, coordinate sync with Notion. AI summaries are deferred to async via separate endpoint to comply with Slack 3s timeout
CategoryOrchestratorManage categories, coordinate sync with Notion
PromptTemplateOrchestratorManage prompt templates, coordinate sync with Notion
NotionSyncOrchestratorCoordinate all entity syncs using strategy pattern
TargetGroupSubscriptionOrchestratorManage target group subscriptions, coordinate Slack home refresh
CategorySubscriptionOrchestratorManage category subscriptions and user preferences
AiSummaryOrchestratorAI summary generation lifecycle and coordination
DigestOrchestratorMain digest orchestrator for generation (distribution delegated to DigestDistributionService)
DigestSummaryOrchestratorEnsure AI summaries exist for all knowledge items before digest generation (generates missing summaries on-demand)
UserDeliveryPreferenceOrchestratorManage user delivery channel preferences

Query Services

ServiceDomain QueriesNotion Access
KnowledgeQueryServiceadvancedSearch, searchByTitle, searchByCategory, getRecentKnowledge✅ via getNotionRepository()
CategoryQueryServicefindByNotionId, findById, findAll, findByName✅ via getNotionRepository()
AiSummaryQueryServicefindAllByKnowledge, findLatestByKnowledgeAndTargetGroup
DigestQueryServicefindKnowledgeForDigest, parseDateRange, getStatistics
TargetGroupQueryServicefindByName, findById, getActiveGroups
CategorySubscriptionQueryServicefindActiveSubscriptions, findSubscribers, isSubscribed, findByUserAndCategory
TargetGroupSubscriptionQueryServicefindActiveSubscriptions, findSubscribers, isSubscribed, findByUserAndTargetGroup
PromptTemplateQueryServicefindByTargetGroupAndCategory✅ via getNotionRepository()

Resolution Services

ServiceResponsibilities
KnowledgeResolutionServiceResolve Knowledge IDs (Notion/Local)
CategoryResolutionServiceResolve Category identifiers (ID, NotionID, Name)
TargetGroupResolutionServiceResolve Target Group identifiers (ID, Name)

Persistence Services

ServiceResponsibilities
KnowledgePersistenceServiceCRUD operations for Knowledge entity in local database
CategoryPersistenceServiceCRUD operations for Category entity in local database
SummaryPersistenceServiceCRUD operations for AiSummary entity in local database
DigestPersistenceServiceCRUD operations for Digest entity in local database
TargetGroupSubscriptionPersistenceServiceMutation operations (create, update) for TargetGroupSubscription entity
PromptTemplatePersistenceServiceCRUD operations for PromptTemplate entity in local database
CategorySubscriptionPersistenceServiceMutation operations (create, update) for CategorySubscription entity

Sync Services

ServiceResponsibilities
NotionSyncKnowledgeBidirectional sync for Knowledge (Local ↔ Notion)
NotionSyncCategoryBidirectional sync for Category (Local ↔ Notion)
NotionAiSummaryServiceOne-way sync: Fetch AI summaries from Notion (read-only)
NotionContentServiceManage Notion page body content (blocks): append, replace, retrieve
DeliveryChannelFactoryCreate delivery channel instances based on user preference
SlackDeliveryChannelGeneric delivery via Slack direct messages (supports all deliverables)
EmailDeliveryChannelGeneric delivery via email (supports digest, knowledge)
NotionDeliveryChannelGeneric delivery via Notion pages (supports digest, knowledge)
DistributionServiceUnified distribution service for any deliverable type
UserDeliveryPreferenceServiceManage user delivery preferences, get effective channel

Delivery & Transport Services

Transport Layer (Low-Level I/O)

Purpose: Pure message transport to external APIs (Slack, Email, Notion)

ServiceResponsibilities
MessageTransportInterfaceContract for transport implementations (pure I/O)
SlackMessageTransportHTTP transport for Slack API (auth, timeouts, error handling)
TransportPayloadDtoImmutable payload structure for transport
TransportResultDtoImmutable result from transport operations

Formatting Layer (Content Transformation)

Purpose: Transform DeliverableInterface into channel-specific formats

| Service | Responsibilities | |---------|-----------------|| | SlackBlockFormatterInterface | Contract for Slack Block Kit formatting | | SlackBlockFormatter | Format any deliverable as Slack Block Kit JSON (supports Digest, Knowledge, AiSummary) |

Channel Layer (Strategy Pattern)

Purpose: Implement channel-specific delivery logic using transport + formatter

| Service | Responsibilities | |---------|-----------------|| | DeliveryChannelInterface | Strategy contract for all delivery channels | | AbstractDeliveryChannel | Template Method base class (shared validation, logging, success/failure handling) | | SlackDeliveryChannel | Slack channel implementation (extends AbstractDeliveryChannel) | | EmailDeliveryChannel | Email channel stub (extends AbstractDeliveryChannel) | | NotionDeliveryChannel | Notion channel stub (extends AbstractDeliveryChannel) |

Distribution Layer (Orchestration)

Purpose: Coordinate channel selection and delivery to multiple users

| Service | Responsibilities | |---------|-----------------|| | DistributionService | Main distribution orchestrator for any DeliverableInterface | | DeliveryChannelFactory | Strategy Factory - creates appropriate channel based on user preference |

AI Services

ServiceResponsibilities
AiProviderInterfaceAbstract interface for all AI providers
SymfonyAiProviderMain AI provider using Symfony AI Platform, agent selection, cost tracking
CustomGatewayPlatformCustom Symfony AI Platform implementation, bypasses model validation
AuthOverrideHttpClientHTTP client decorator for auth/URL overrides
PromptBuilderServiceBuild prompts from templates with variable substitution
AiSummaryQueryServiceQuery service for AI summaries with filtering and search

Repository Manager

ServiceResponsibilities
NotionRepositoryManagerSmart repository selection based on ID type (UUID → Local, Notion ID → Notion)

Repositories

RepositoryTypeResponsibilities
KnowledgeRepositoryLocalPostgreSQL access for Knowledge
NotionKnowledgeRepositoryNotionNotion API access for Knowledge
CategoryRepositoryLocalPostgreSQL access for Category
NotionCategoryRepositoryNotionNotion API access for Category
DigestRepositoryLocalPostgreSQL access for Digest
NotionDigestRepositoryNotionNotion API access for Digest
PromptTemplateRepositoryLocalPostgreSQL access for PromptTemplate
NotionPromptTemplateRepositoryNotionNotion API access for PromptTemplate
AiSummaryRepositoryLocalPostgreSQL access for AiSummary
NotionAiSummaryServiceNotionOne-way sync: Fetch AI summaries from Notion (read-only)
TargetGroupSubscriptionRepositoryLocalPostgreSQL access for TargetGroupSubscription
UserDeliveryPreferenceRepositoryLocalPostgreSQL access for UserDeliveryPreference

Generic Delivery Layer

The generic delivery system enables ANY content to be delivered through ANY channel. It uses a 4-layer architecture: Transport → Formatter → Channel → Distribution.

Architecture

                         DeliverableInterface (Contract)

                ┌────────────────────┼────────────────────┐
                │                    │                    │
        ┌───────────────┐     ┌─────────────┐    ┌────────────────────┐
        │ Digest Entity │     │ Knowledge   │    │ AiSummaryDeliverable│
        │               │     │ Entity      │    │ DTO                │
        └───────────────┘     └─────────────┘    └────────────────────┘
                │                    │                    │
                └────────────────────┴────────────────────┘

                        ┌─────────────────────────┐
                        │  DistributionService    │
                        │  (orchestrates delivery)│
                        └──────────────┬──────────┘

                        ┌─────────────────────────┐
                        │ DeliveryChannelFactory  │
                        │  (creates channels)    │
                        └──────────────┬──────────┘

                ┌──────────────────────┼──────────────────────┐
                ▼                      ▼                      ▼
        ┌─────────────────┐    ┌──────────────────┐   ┌────────────────┐
        │CHANNEL LAYER    │    │ CHANNEL LAYER    │   │ CHANNEL LAYER  │
        │                 │    │                  │   │                │
        │SlackDelivery    │    │ EmailDelivery    │   │ NotionDelivery │
        │Channel          │    │ Channel          │   │ Channel        │
        │(AbstractImpl)   │    │ (AbstractImpl)   │   │ (AbstractImpl) │
        └────────┬────────┘    └────────┬─────────┘   └────────┬───────┘
                 ▼                      ▼                      ▼
        ┌──────────────────────────────────────────────────────┐
        │       FORMATTER LAYER (Content Transformation)       │
        ├──────────────────────────────────────────────────────┤
        │  SlackBlockFormatter → Slack Block Kit JSON          │
        │  EmailFormatter → HTML/Plain Text (future)           │
        │  NotionFormatter → Notion Block structure (future)   │
        └───────────────┬──────────────────────────────────────┘

        ┌──────────────────────────────────────────────────────┐
        │    TRANSPORT LAYER (Pure I/O to External APIs)       │
        ├──────────────────────────────────────────────────────┤
        │  MessageTransportInterface (contract)                │
        │  ├─ SlackMessageTransport (HTTP to Slack Bot API)    │
        │  ├─ EmailTransport (SMTP) [future]                   │
        │  └─ NotionTransport (HTTP to Notion API) [future]    │
        └───────────────┬──────────────────────────────────────┘

        ┌──────────────────────────────────────────────────────┐
        │         EXTERNAL APIs (Slack, Email, Notion)         │
        └──────────────────────────────────────────────────────┘

Design Patterns

Result Pattern

ResultInterface: Common interface for all Result objects

  • Methods: isSuccess(), isFailure(), getMessage()
  • Implemented by 17 Result classes across the codebase
  • Enables polymorphic result handling

Implementations:

  • BaseResult<T>: Generic template class (extended by 2 classes)
  • Rich Result Objects (8 classes): Domain-specific with static factories
    • DigestDistributionResult, ContentExtractionResult, DeliveryResult
    • CategorySubscriptionResult, TargetGroupSubscriptionResult
    • Factory methods: success(), failure()
    • Domain methods: getSuccessRate(), getPreview(), etc.
  • Simple Result Objects (7 classes): Data containers
    • BlockAppendResult, BlockReplaceResult, SyncResultDto
    • DigestGenerationResultDto, NotionDatabaseQueryResultDto

Data Transfer Object (DTO) Pattern

Categories:

  • Request DTOs: CreateCategoryRequest, UpdateKnowledgeRequest, SearchKnowledgeRequest, GenerateDigestRequest
    • Include Symfony validation constraints
    • Factory methods: fromArray() for construction
  • Response DTOs: CategoryResponse, KnowledgeResponse, SyncResultResponse, DigestResponse
    • Serialized to JSON for API responses
  • Internal DTOs: SyncResultDto, PromptVariablesDto, SearchResultItemDTO
    • Used for service-to-service communication
  • Log Context DTOs: OperationContextDto, DomainContextDto, QueryContextDto

Structured Logging Context DTO Pattern

Rule: Every base service class has exactly one corresponding context DTO type. Using the wrong DTO type in a layer is a static analysis violation.

Base ClassLayerContext DTOUsed In
BaseOrchestratorL2 – OrchestrationOperationContextDtologOperationStart, logOperationSuccess, logOperationFailure, executeWithLogging
BaseResolutionServiceL4 – DomainDomainContextDtologInfo on resolve/unresolved
BasePersistenceServiceL5 – PersistenceDomainContextDtobuildCreateContext, buildUpdateContext, buildDeleteContext
BaseQueryServiceL4 – DomainQueryContextDtologQuery, logQueryResult

Builders: Each DTO has a companion builder via AbstractContextBuilder:

php
// Layer 2 — Orchestrators
OperationContextDto::builder()
    ->withTitle($request->title)
    ->build();

// Layer 4/5 — Persistence & Resolution
DomainContextDto::builder()
    ->withId($entity->getId())
    ->withTitle($entity->getTitle())
    ->build();

// Layer 4 — Query Services
QueryContextDto::builder()
    ->withNotionId($notionId)
    ->build();

BaseService::logInfo() accepts the abstract LogContextDto parent, so all three types flow through it — but the concrete method signatures on each base class (logOperationStart(?OperationContextDto), buildCreateContext(): DomainContextDto, logQuery(?QueryContextDto)) enforce the correct type at the point of use.

Resolution Service Pattern

BaseResolutionService: Abstract base providing common resolution logic:

  • Normalization: Notion ID hyphenation and format validation
  • Caching: In-memory caching for repeated lookups
  • Batching: Methods for resolving multiple identifiers at once
  • Error Handling: Standardized logging and exception catching
  • Concrete Implementations:
    • KnowledgeResolutionService: Resolves by local ID or Notion ID
    • CategoryResolutionService: Resolves by ID, Notion ID, or Name
    • TargetGroupResolutionService: Resolves by ID or Name

Value Object Pattern

Implementations:

  • ContentExtractionResult: Extraction results with content, type, metadata
  • UrlMetadata: URL metadata (title, description, favicon)
  • TargetGroup: Target group configuration (name, description)
  • BlockCollection: Collection of Notion blocks
    • Properties: blocks (list of BlockInterface)
    • Methods: all(), count(), isEmpty()
    • Used by: NotionContentService::getPageContent()

Factory Pattern

Implementations:

  • NotionClientFactory: Creates Notion client instances
    • Production: Real HTTP client with API credentials
    • Test: Mock HTTP client for testing
    • Handles environment detection and configuration
  • DeliveryChannelFactory: Creates delivery channel instances
    • Selects appropriate channel based on user preference
    • Returns: SlackDeliveryChannel, EmailDeliveryChannel, or NotionDeliveryChannel
    • Handles fallback to default channel (Slack)

Builder Pattern

Implementations:

  • NotionPageBuilder: Builds Notion pages with properties and relations
    • Methods: addTitle(), addRichText(), addRelation(), addDate(), build()
    • Stateless, reusable across multiple page constructions
  • DigestEntityBuilder: Builds Digest entities from data arrays
    • Method: buildFromData() with all required parameters
  • DigestContextBuilder: Builds context for AI generation
    • Method: buildContext() with knowledge items and metadata
  • PromptBuilderService: Builds AI prompts with variable substitution
    • Methods: buildPrompt(), substituteVariables()
  • Log Context Builders (OperationContextDtoBuilder, DomainContextDtoBuilder, QueryContextDtoBuilder):
    • All extend AbstractContextBuilder — fluent ->set(key, value)->build()
    • Each produces its layer-specific DTO type (see: Structured Logging Context DTO Pattern)

Repository Pattern

Implementations:

  • Local repositories: PostgreSQL access via Doctrine ORM
    • Extend ServiceEntityRepository and implement BaseRepositoryInterface
    • CategoryRepository, KnowledgeRepository, DigestRepository
    • Methods: find(), findAll(), findOneBy(), save(), flush(), custom queries
  • Remote repositories: Notion API access via NotionClient
    • NotionKnowledgeRepository, NotionCategoryRepository, NotionDigestRepository
    • Methods: create(), update(), listAll(), custom queries
    • Rule: No logging — data access only (logging belongs in sync service layer)
  • Interface: BaseRepositoryInterface (generic interface for local repositories)

Service Layer Pattern

Organization by Responsibility:

  • Persistence Services: CRUD operations (CategoryPersistenceService, DigestPersistenceService)
  • Query Services: Complex queries (DigestQueryService, AiSummaryQueryService, KnowledgeQueryService)
  • Orchestrators: Multi-service workflows (CategoryOrchestrator, KnowledgeOrchestrator, DigestOrchestrator)
  • Domain Services: Business logic (DigestGenerationService, DigestContentFormatter, DigestDistributionService)

Base Service: BaseService provides common functionality (logging, entity manager, flush).

QueryServiceInterface Pattern

Interface Methods:

  • Core query operations for read-only data access
  • Implemented by domain-specific query services
  • Separates query concerns from persistence operations

Implementations:

  • AiSummaryQueryService: AI summary queries
  • DigestQueryService: Digest queries with date ranges
  • KnowledgeQueryService: Knowledge search and filtering (with Notion repository access)

BaseQueryService Pattern

Features:

  • Generic: BaseQueryService<TEntity, TRepository>
  • Implements QueryServiceInterface contract
  • Manages own $logger property (does NOT extend BaseService)
  • Receives $repository and $logger via constructor
  • Provides logQuery(), logAndReturnSingleResult(), logAndReturnCollectionResult() helpers
  • Enforces read-only operations (no flush/persist)

Usage:

  • Extended by all query service implementations (must be final)
  • Ensures consistent query service structure
  • Centralizes common query patterns

Mapper Pattern

Implementations:

  • BaseMapper<TEntity, TDto>: Abstract template with toDto(), toEntity(), collection mapping
  • CategoryMapper: Category ↔ CategoryResponse
  • KnowledgeMapper: Knowledge ↔ KnowledgeResponse
  • DigestMapper: Digest ↔ DigestResponse
  • SummaryMapper: Summary ↔ SummaryResponseDto
  • NotionResponseMapper: Notion API responses ↔ internal DTOs

Command Pattern

Implementations (10 commands):

  • GenerateDigestCommand: Generate digests for categories
  • SyncKnowledgeFromNotionCommand: Sync knowledge from Notion
  • SyncCategoriesFromNotionCommand: Sync categories from Notion
  • SyncAllCommand: Sync all entities
  • TestAiCommand: Test AI provider integration

Responsibilities: Transaction management, error handling, service coordination, business rule enforcement.

Orchestrator Pipeline Pattern

Orchestrators follow a standard "Pipeline" pattern for write operations:

  1. Resolve: Use {Entity}ResolutionService to convert identifiers to entities.
  2. Map: Use MapperRegistry to get the {Entity}Mapper and map request DTOs to entities.
  3. Persist: Use {Entity}PersistenceService to save the business item to the local database.
  4. Sync: (Optional, best-effort with try/catch) Delegate to concrete NotionSync{Entity} for remote synchronization.

Rule: Orchestrators MUST use final class. Rule: Orchestrators MUST use concrete NotionSync{Entity} type-hints (e.g., NotionSyncKnowledge), NOT NotionSyncInterface — avoids Symfony DI ambiguity when multiple implementations exist. Rule: Orchestrators should NOT inject direct mappers; use MapperRegistry with MapperNames constants. Rule: Orchestrators should NOT inject redundant services (avoid injecting PersistenceService if only Resolution is needed). Rule: Controllers should NOT contain logging, filtering, or try/catch logic — delegate everything to orchestrators.

Adapter Pattern

Implementations:

  • OpenAiPlatformAdapter: Adapts Symfony AI Platform interface to OpenAI API
    • Implements PlatformInterface
    • Delegates to underlying OpenAI platform
    • Adds custom API key formatting

Template Method Pattern

Implementations:

  • AbstractNotionSync: Common sync logic (validation, structured logging via DomainContextDto, error handling)
    • Abstract methods: performSync(), getEntityNameTitleCase(), buildSyncContext(), log message getters
    • Template method: syncToNotion() orchestrates the flow
  • BasePersistenceService<TEntity, TRepository>: Common CRUD logic
    • Receives injected $repository (BaseRepositoryInterface) — NOT EntityManager
    • Template methods: create(), update(), delete() with structured logging
    • Concrete services MUST be final
  • BaseMapper<TEntity, TDto>: Common mapping logic
    • Abstract methods: toDto(), toEntity()
    • Template methods: toDtoCollection(), toEntityCollection()
  • BaseService: Common service functionality
    • Methods: flush(), logInfo(), logWarning(), logError()
  • BaseException: Common exception handling
    • Constructor with message and code

Strategy Pattern (Interface-based)

Implementations:

  • NotionSyncInterface: Sync strategy interface
    • Implementations: NotionSyncKnowledge, NotionSyncCategory (POC), NotionSyncDigest (MVP)
    • Used by: NotionSyncService (transitional) to delegate entity-specific sync
    • Important: Orchestrators MUST inject concrete types, NOT NotionSyncInterface (avoids Symfony DI ambiguity with multiple implementations)
  • ContentBlockConverterInterface: Content format conversion strategy
    • Implementations: MarkdownBlockConverter (supports markdown → Notion blocks)
    • Used by: NotionContentService to convert content formats to Notion blocks
    • Extensible: Add new converters for HTML, JSON, plain text formats
  • DeliveryChannelInterface: Generic delivery channel strategy
    • Implementations: SlackDeliveryChannel, EmailDeliveryChannel, NotionDeliveryChannel
    • Used by: DistributionService to deliver any DeliverableInterface
    • Extensible: Add new channels (SMS, webhook, etc.) by implementing interface
    • Methods: deliver(), getChannelName(), isAvailable(), supports(), getSupportedContentTypes()
  • ResolutionStrategyInterface: Entity resolution strategy interface
    • Base class: BaseResolutionService (provides concrete multi-strategy algorithm: DB ID → Notion ID → raw Notion ID via NotionResolvableQueryServiceInterface, batch resolution, Notion ID normalization)
    • Implementations (only need to provide getEntityName() and pass their query service):
      • CategoryResolutionService
      • KnowledgeResolutionService
      • TargetGroupResolutionService
    • Pattern: Template Method and concrete multi-strategy resolution
    • Location: Service/Resolution/ (base), Service/Category/, Service/Knowledge/, Service/Subscription/
  • PromptBuilderServiceInterface: Prompt building strategy
  • AiSummaryOrchestratorInterface: AI summary generation strategy
  • KnowledgeRepositoryInterface: Repository selection strategy

Facade Pattern

Implementations:

  • NotionRepositoryManager: Simplifies repository selection (local vs remote)
    • Methods: getKnowledgeRepository(), getCategoryRepository()
    • Decides local vs remote based on ID type (UUID vs Notion ID)
  • HealthCheckService: Unified health check interface
    • Aggregates: DatabaseHealthCheck, NotionHealthCheck

Decorator Pattern

Implementations:

  • AuthOverrideHttpClient: Decorates Symfony HttpClient
    • Adds: Authorization header injection, base URL override
    • Wraps: Original HttpClient interface

Dependency Injection

All services use constructor injection for dependencies, configured via Symfony's service container.


Base Classes & Interfaces

Inheritance Hierarchy

BaseService (logging: logInfo, logWarning, logError)
├── BasePersistenceService<TEntity, TRepository>  (CRUD + repository pattern)
│   ├── final CategoryPersistenceService
│   ├── final KnowledgePersistenceService
│   ├── DigestPersistenceService (MVP)
│   └── ...
├── BaseResolutionService (ID normalization, caching, strategy resolve)
│   ├── final CategoryResolutionService
│   ├── final KnowledgeResolutionService
│   └── TargetGroupResolutionService (MVP)
└── AbstractNotionSync implements NotionSyncInterface
    ├── NotionSyncCategory
    └── NotionSyncKnowledge

BaseOrchestrator implements OrchestratorInterface (own $logger, executeWithLogging)
├── final CategoryOrchestrator
├── final KnowledgeOrchestrator
├── DigestOrchestrator (MVP)
└── ...

BaseQueryService<TEntity, TRepository> implements QueryServiceInterface (own $logger, read-only)
├── final CategoryQueryService
├── final KnowledgeQueryService
├── DigestQueryService (MVP)
└── ...

BaseMapper<TEntity, TDto> implements MapperInterface (toDto, toEntity, collections)
├── CategoryMapper
├── KnowledgeMapper
└── ...

Note: BaseQueryService and BaseOrchestrator each manage their own $logger property. They do NOT extend BaseService. Only BasePersistenceService, BaseResolutionService, and AbstractNotionSync extend BaseService.

BaseOrchestrator

Purpose: Common orchestration patterns for all orchestrators Location: /backend/src/Service/BaseOrchestrator.phpInterface: OrchestratorInterface

Features:

  • Manages own $logger (does NOT extend BaseService)
  • Structured logging with context (logOperationStart, logOperationSuccess, logOperationFailure)
  • Error handling utilities
  • Transaction coordination helpers (executeWithLogging)
  • Result aggregation patterns

Extended by (all final):

  • final KnowledgeOrchestrator
  • final CategoryOrchestrator
  • DigestOrchestrator (MVP)
  • DigestSummaryOrchestrator (MVP)
  • AiSummaryOrchestrator (MVP)
  • PromptTemplateOrchestrator (MVP)
  • CategorySubscriptionOrchestrator (MVP)
  • TargetGroupSubscriptionOrchestrator (MVP)
  • UserDeliveryPreferenceOrchestrator (MVP)

BasePersistenceService

Purpose: Common CRUD operations using repository pattern Location: /backend/src/Service/BasePersistenceService.phpGeneric: BasePersistenceService<TEntity, TRepository>

Features:

  • Extends BaseService for logging
  • Receives BaseRepositoryInterface via constructor — NOT EntityManagerInterface
  • Template methods: create(), update(), delete() with structured logging
  • Entity lifecycle management via injected repository

Extended by (all final):

  • final CategoryPersistenceService
  • final KnowledgePersistenceService
  • SummaryPersistenceService (MVP)
  • DigestPersistenceService (MVP)

BaseDomainService

Purpose: Common domain service functionality Location: /backend/src/Service/BaseDomainService.phpInterface: DomainServiceInterface

Features:

  • Extends BaseService for logging and entity manager
  • Domain-specific business logic patterns
  • Validation and error handling

Extended by:

  • DigestGenerationService
  • DigestContentFormatter
  • DigestDistributionService
  • KnowledgeValidationService
  • MetadataExtractionService

BaseResolutionService

Purpose: Common resolution strategy patterns Location: /backend/src/Service/Resolution/BaseResolutionService.php

Features:

  • Extends BaseService for logging
  • Provides concrete multi-strategy resolution algorithm (resolveFromSource checking ID then Notion ID)
  • Receives NotionResolvableQueryServiceInterface via constructor
  • Caching for performance
  • Batch resolution support
  • Notion ID normalization

Extended by (all final):

  • final KnowledgeResolutionService
  • final CategoryResolutionService
  • TargetGroupResolutionService (MVP)

BaseMapper

Purpose: Common entity-DTO mapping patterns Location: /backend/src/Mapper/BaseMapper.phpInterface: MapperInterface

Features:

  • Generic template class BaseMapper<TEntity, TDto>
  • Abstract methods: toDto(), toEntity()
  • Template methods: toDtoCollection(), toEntityCollection()
  • Null-safe mapping utilities

Extended by:

  • CategoryMapper
  • KnowledgeMapper
  • DigestMapper (MVP)
  • SummaryMapper (MVP)
  • NotionResponseMapper (MVP)

BaseQueryService

Purpose: Common query service patterns Location: /backend/src/Service/BaseQueryService.phpInterface: QueryServiceInterfaceGeneric: BaseQueryService<TEntity, TRepository>

Features:

  • Manages own $logger (does NOT extend BaseService)
  • Receives $repository (BaseRepositoryInterface) and $logger via constructor
  • Read-only operations (no flush/persist)
  • Provides logQuery(), logAndReturnSingleResult(), logAndReturnCollectionResult()
  • Pagination and filtering patterns

Extended by (all final):

  • final CategoryQueryService
  • final KnowledgeQueryService
  • DigestQueryService (MVP)
  • AiSummaryQueryService (MVP)
  • CategorySubscriptionQueryService (MVP)
  • TargetGroupSubscriptionQueryService (MVP)

Enhanced Naming Conventions

Service Naming Patterns

Orchestrators

Pattern: {Entity}OrchestratorPurpose: High-level business workflows, multi-service coordination

Examples:

  • KnowledgeOrchestrator - Knowledge lifecycle management
  • DigestOrchestrator - Digest generation and distribution
  • AiSummaryOrchestrator - AI summary generation lifecycle

Responsibilities:

  • Coordinate multiple services
  • Transaction management
  • Business rule enforcement
  • Error handling and rollback

Domain Services

Pattern: {Entity}{Purpose}ServicePurpose: Specialized business logic for specific domains

Examples:

  • DigestGenerationService - Generate digest data
  • DigestContentFormatter - Format digest output
  • KnowledgeValidationService - Validate knowledge data

Responsibilities:

  • Focused business logic
  • Data transformation
  • Complex calculations
  • Domain-specific rules

Resolution Services

Pattern: {Entity}ResolutionServicePurpose: Entity resolution and conflict handling

Examples:

  • KnowledgeResolutionService - Resolve knowledge conflicts
  • CategoryResolutionService - Resolve category conflicts
  • TargetGroupResolutionService - Resolve target group conflicts

Responsibilities:

  • Entity resolution logic
  • Conflict detection and resolution
  • Merge strategies
  • Deduplication

Persistence Services

Pattern: {Entity}PersistenceServicePurpose: CRUD operations on local database

Examples:

  • KnowledgePersistenceService - Knowledge CRUD
  • CategoryPersistenceService - Category CRUD
  • DigestPersistenceService - Digest CRUD

Responsibilities:

  • Create, Read, Update, Delete
  • Entity lifecycle management
  • Basic validation
  • Database transactions

Query Services

Pattern: {Entity}QueryService or {Entity}SearchServicePurpose: Complex read-only queries

Examples:

  • DigestQueryService - Digest queries with date ranges
  • AiSummaryQueryService - AI summary queries
  • KnowledgeQueryService - Knowledge search, filtering, and Notion repository access

Responsibilities:

  • Complex queries
  • Filtering and pagination
  • Aggregations and statistics
  • Read-only operations

Sync Services

Pattern: NotionSync{Entity} or {Entity}SyncServicePurpose: Bidirectional sync between local and Notion

Examples:

  • NotionSyncKnowledge - Knowledge sync (Local ↔ Notion)
  • NotionSyncCategory - Category sync (Local ↔ Notion)
  • NotionAiSummaryService - AI summary sync (Notion → Local, one-way)

Responsibilities:

  • Entity-specific sync logic
  • Data transformation
  • Conflict resolution
  • Batch processing


Complete Layer Architecture

┌─────────────────────────────────────────────────────────────────────────────┐
│                         INPUT LAYER: EXTERNAL SOURCES                       │
│                                                                             │
│  Slack Events          Slack Commands        Slack App Home                 │
│  • message_action      • /knowledge          • Add Knowledge button         │
│  • message (URL)       • /digest             • View items                   │
│  • view_submission                                                          │
│                                                                             │
│  HTTP API Requests     CLI Commands          Cron Jobs                      │
│  • POST /api/knowledge • app:generate-digest • Scheduled digests            │
│  • POST /api/digests   • app:sync-notion     • Periodic syncs               │
└─────────────────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────────────────┐
│                         LAYER 1: PRESENTATION                               │
│                    (Controllers, Commands, API)                             │
│                                                                             │
│  CONTROLLERS (14):                                                          │
│  • KnowledgeController • CategoryController • DigestController              │
│  • NotionSyncController • NotionDigestController • LocalKnowledgeController │
│  • Api/SummaryController • Api/TargetGroupController                        │
│  • Api/PromptTemplateController • Health/HealthController                   │
│  • Api/TargetGroupSubscriptionController • Api/UserDeliveryPreferenceController │
│  • SubscriptionController • SlackWebhookController                          │
│                                                                             │
│  COMMANDS (9):                                                              │
│  • GenerateDigestCommand • SyncAllCommand                                   │
│  • SyncKnowledgeFromNotionCommand • SyncCategoriesFromNotionCommand         │
│  • SyncAiSummariesFromNotionCommand • SyncTargetGroupsFromNotionCommand     │
│  • SyncDigestsToNotionCommand • SyncPromptTemplatesFromNotionCommand        │
│  • TestAiCommand                                                            │
│                                                                             │
│  Responsibilities:                                                          │
│  • HTTP request/response handling                                           │
│  • Input validation and DTO mapping                                         │
│  • CLI command execution                                                    │
│  • Delegates to Orchestrators                                               │
└─────────────────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────────────────┐
│                      LAYER 2: ORCHESTRATION                                 │
│                   (High-Level Business Workflows)                           │
│                                                                             │
│  ORCHESTRATORS (10):                                                        │
│  • KnowledgeOrchestrator - Knowledge lifecycle + Notion sync                │
│  • CategoryOrchestrator - Category lifecycle + target groups                │
│  • PromptTemplateOrchestrator - Template versioning + sync                  │
│  • NotionSyncOrchestrator - Coordinate entity syncs (Strategy)              │
│  • DigestOrchestrator - Main digest orchestrator (generation only)          │
│  • AiSummaryOrchestrator - AI summary generation lifecycle                  │
│  • CategorySubscriptionOrchestrator - Manage category subscriptions         │
│  • TargetGroupSubscriptionOrchestrator - Manage target group subscriptions  │
│  • UserDeliveryPreferenceOrchestrator - Manage delivery preferences         │
│                                                                             │
│  Responsibilities:                                                          │
│  • Coordinate multi-service workflows                                       │
│  • Transaction management and rollback                                      │
│  • Business rule enforcement                                                │
│  • Delegates to Domain Services, Sync Services, and Persistence Services    │
└─────────────────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────────────────┐
│                       LAYER 3: SYNC SERVICES                                │
│                  (Bidirectional Sync: Local ↔ Notion)                       │
│                                                                             │
│  NotionSyncKnowledge  NotionSyncCategory  NotionSyncDigest                  │
│  NotionAiSummaryService  DigestNotionSyncService  SyncQueryService          │
│  NotionSyncSubscription                                                     │
│                                                                             │
│  Responsibilities:                                                          │
│  • Entity-specific sync logic (extends AbstractNotionSync)                  │
│  • Data transformation (Local ↔ Notion)                                     │
│  • Conflict resolution and merge strategies                                 │
│  • Batch processing with pagination                                         │
└─────────────────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────────────────┐
│                    LAYER 4: DOMAIN SERVICES                                 │
│                (Specialized Business Logic)                                 │
│                                                                             │
│  DIGEST DOMAIN (18):                                                        │
│  DigestQueryService  DigestGenerationService  DigestContentFormatter        │
│  DigestEntityBuilder  DigestContextBuilder  DigestAiSummaryGenerator        │
│  DigestRelationLinker  DateRangeParser  NotionRelationExtractor             │
│  TargetGroupResolver  DigestDistributionService  DigestRecipientResolver    │
│  DigestDeliveryLogService  DigestDeliveryPersistenceService                 │
│  DigestDeliveryQueryService  DigestPersistenceService  DigestOrchestrator   │
│  DigestSummaryOrchestrator                                                  │
│                                                                             │
│  KNOWLEDGE DOMAIN (5):                                                      │
│  KnowledgeQueryService  KnowledgeValidationService                          │
│  KnowledgeResolutionService  MetadataExtractionService                      │
│  TargetGroupResolutionService                                               │
│                                                                             │
│  CATEGORY DOMAIN (2):                                                       │
│  CategoryResolutionService  CategoryQueryService                            │
│                                                                             │
│  SUBSCRIPTION DOMAIN (7):                                                   │
│  CategorySubscriptionOrchestrator  CategorySubscriptionPersistenceService   │
│  CategorySubscriptionQueryService  TargetGroupSubscriptionOrchestrator      │
│  TargetGroupSubscriptionPersistenceService                                  │
│  TargetGroupSubscriptionQueryService  UserDeliveryPreferenceService         │
│                                                                             │
│  DELIVERY DOMAIN (9):                                                       │
│  DeliveryChannelInterface (Strategy Pattern)                                │
│  • AbstractDeliveryChannel - Template Method base class                     │
│  • SlackDeliveryChannel - Deliver via Slack DM (extends Abstract)           │
│  • EmailDeliveryChannel - Deliver via email stub (extends Abstract)         │
│  • NotionDeliveryChannel - Deliver via Notion page stub (extends Abstract)  │
│  DeliveryChannelFactory - Channel selection based on user preference        │
│  UserDeliveryPreferenceOrchestrator  UserDeliveryPreferencePersistenceService│
│  UserDeliveryPreferenceQueryService  DistributionService                    │
│                                                                             │
│  SLACK NOTIFICATION DOMAIN (4):                                             │
│  HomeRefreshStrategyInterface (Strategy Pattern)                            │
│  • ImmediateRefreshStrategy - User-initiated actions                        │
│  • SelectiveRefreshStrategy - Affected users only                           │
│  • BatchRefreshStrategy - Bulk operations with queuing                      │
│                                                                             │
│  CONTENT EXTRACTION (5):                                                    │
│  ContentExtractionService  HtmlContentExtractor  PdfContentExtractor        │
│  NotionContentExtractor  PlainTextToNotionConverter                         │
│                                                                             │
│  CONTENT MANAGEMENT (4):                                                    │
│  NotionContentService  MarkdownBlockConverter                               │
│  ContentBlockConverterInterface  BlockCollection                            │
│                                                                             │
│  AI SERVICES (7):                                                           │
│  AiProviderInterface  SymfonyAiProvider  CustomGatewayPlatform              │
│  AuthOverrideHttpClient  OpenAiPlatformAdapter  AiContentCleanerService     │
│  PromptBuilderService  SimpleResultConverter  AiSummaryQueryService         │
│                                                                             │
│  TARGET GROUP (4):                                                          │
│  TargetGroupResolutionService  TargetGroupManagerService                    │
│  TargetGroupQueryService  TargetGroupQueryServiceInterface                  │
│                                                                             │
│  Responsibilities:                                                          │
│  • Focused business logic for specific domains                              │
│  • Data transformation and formatting                                       │
│  • Complex queries and filtering                                            │
│  • Entity building and validation                                           │
└─────────────────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────────────────┐
│                    LAYER 5: PERSISTENCE SERVICES                            │
│                      (CRUD Operations)                                      │
│                                                                             │
│  KnowledgePersistenceService  CategoryPersistenceService                    │
│  DigestPersistenceService  SummaryPersistenceService                        │
│  PromptTemplatePersistenceService  CategorySubscriptionPersistenceService   │
│  TargetGroupSubscriptionPersistenceService                                  │
│                                                                             │
│  Responsibilities:                                                          │
│  • Create, Read, Update, Delete operations                                  │
│  • Entity lifecycle management                                              │
│  • Basic validation and error handling                                      │
│  • Uses Repository Manager for data access                                  │
└─────────────────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────────────────┐
│                    LAYER 6: REPOSITORY MANAGER                              │
│                    (Smart Repository Selection)                             │
│                                                                             │
│  NotionRepositoryManager (Facade Pattern)                                   │
│                                                                             │
│  Responsibilities:                                                          │
│  • Determines local vs remote repository based on ID type                   │
│  • Numeric ID → Local repository (PostgreSQL)                               │
│  • UUID/Notion ID → Notion repository (Notion API)                          │
│  • Provides unified interface for data access                               │
│  • Simplifies repository selection for upper layers                         │
└─────────────────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────────────────┐
│                      LAYER 7: DATA ACCESS                                   │
│                         (Repositories)                                      │
│                                                                             │
│  LOCAL REPOSITORIES               NOTION REPOSITORIES                       │
│  (implement BaseRepositoryInterface)                                        │
│  KnowledgeRepository              NotionKnowledgeRepository                 │
│  CategoryRepository               NotionCategoryRepository                  │
│  DigestRepository (MVP)           NotionDigestRepository (MVP)              │
│  PromptTemplateRepository (MVP)   NotionPromptTemplateRepository (MVP)      │
│  AiSummaryRepository (MVP)        NotionAiSummaryService (MVP)              │
│  SummaryRepository (MVP)          NotionTargetGroupRepository (MVP)         │
│  TargetGroupRepository (MVP)      NotionDigestOrchestrator (MVP)            │
│  CategorySubscriptionRepository (MVP)  NotionSubscriptionRepository (MVP)   │
│  TargetGroupSubscriptionRepository (MVP)                                    │
│  UserDeliveryPreferenceRepository (MVP)                                     │
│  DigestDeliveryRepository (MVP)                                             │
│  ResourceRepository (MVP)                                                   │
│  ResourceContentRepository (MVP)                                            │
│  TagRepository (MVP)                                                        │
│                                                                             │
│  UTILITY SERVICES:                                                          │
│  NotionPageBuilder  NotionPropertyExtractor  NotionDatabaseService          │
│  NotionClientFactory  EmojiConverter                                        │
│                                                                             │
│  Responsibilities:                                                          │
│  • Database queries (local) or API calls (Notion)                           │
│  • Entity mapping and hydration                                             │
│  • Query optimization and pagination                                        │
│  • Data transformation between storage and domain models                    │
└─────────────────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────────────────┐
│                       LAYER 8: DATA STORAGE                                 │
│                                                                             │
│  PostgreSQL Database             Notion API                                 │
│  • Knowledge entities            • Notion pages and databases               │
│  • Categories                    • Blocks and properties                    │
│  • Digests                       • Relations and rollups                    │
│  • AI Summaries                  • Rich text and files                      │
│  • Prompt Templates                                                         │
│  • Target Groups                                                            │
│  • Resources and Tags                                                       │
│  • Category Subscriptions                                                   │
│  • Target Group Subscriptions                                               │
│  • User Delivery Preferences                                                │
│  • Digest Deliveries                                                        │
│                                                                             │
│  Doctrine ORM                    Notion SDK                                 │
│  • Entity mapping                • API client                               │
│  • Query builder                 • Pagination                               │
│  • Migrations                    • Rate limiting                            │
└─────────────────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────────────────┐
│                  LAYER 9: CROSS-CUTTING CONCERNS                            │
│                                                                             │
│  LOGGING & MONITORING:                                                      │
│  • Monolog (PSR-3 Logger)                                                   │
│  • Structured logging with context                                          │
│  • Log levels: debug, info, warning, error                                  │
│                                                                             │
│  HEALTH CHECKS:                                                             │
│  • HealthCheckService (orchestrator)                                        │
│  • DatabaseHealthCheck (PostgreSQL connectivity)                            │
│  • NotionHealthCheck (Notion API connectivity)                              │
│  • SlackHealthCheck (Slack app connectivity)                                │
│  • MetricsService (system metrics collection)                               │
│                                                                             │
│  EXTERNAL INTEGRATIONS:                                                     │
│  • SlackNotificationInterface (abstract notification interface)             │
│    ├─ SlackHomeRefreshService (home tab refresh operations)                 │
│    ├─ SlackDigestDeliveryService (digest delivery via DM)                   │
│    └─ SlackApiClient (HTTP communication with Slack app)                    │
│  • Uses Facade Pattern for simplified external communication                │
│  • Uses Strategy Pattern for different notification types                   │
│  • Retry logic with exponential backoff                                     │
│  • Batch processing for bulk operations                                     │
│                                                                             │
│  VALIDATION:                                                                │
│  • Symfony Validator (constraint-based)                                     │
│  • Custom validators: ValidTargetGroup, ValidUrl                            │
│  • Domain validation in services                                            │
│                                                                             │
│  ERROR HANDLING:                                                            │
│  • BaseException (custom exception hierarchy)                               │
│  • Specific exceptions: KnowledgeNotFoundException, DigestNotFoundException │
│  • ValidationException for constraint violations                            │
│  • Result pattern for expected failures                                     │
│                                                                             │
│  SECURITY:                                                                  │
│  • Symfony Security component                                               │
│  • API key authentication                                                   │
│  • CORS configuration                                                       │
│  • Internal API secret for service-to-service auth                          │
│                                                                             │
│  CACHING:                                                                   │
│  • Symfony Cache component                                                  │
│  • Repository-level caching                                                 │
│  • Active user list caching (5 minutes)                                     │
│  • Subscription data caching (1 minute)                                     │
│                                                                             │
│  EVENTS:                                                                    │
│  • Symfony EventDispatcher                                                  │
│  • Gedmo Timestampable (automatic timestamps)                               │
│                                                                             │
│  • Applied across all layers via Symfony DI and AOP                         │
└─────────────────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────────────────┐
│                    LAYER 10: AI PROVIDER STACK                              │
│                  (AI Service Integration Layer)                             │
│                                                                             │
│  ┌───────────────────────────────────────────────────────────────────────┐  │
│  │ APPLICATION SERVICES                                                  │  │
│  │ AiSummaryOrchestrator, DigestSummaryOrchestrator, PromptBuilderService│  │
│  └───────────────────────────────────────────────────────────────────────┘  │
│                                  ↓                                          │
│  ┌───────────────────────────────────────────────────────────────────────┐  │
│  │ PROVIDER INTERFACE                                                    │  │
│  │ AiProviderInterface                                                   │  │
│  │ • generateCompletion(prompt, options): AiResponse                     │  │
│  └───────────────────────────────────────────────────────────────────────┘  │
│                                  ↓                                          │
│  ┌───────────────────────────────────────────────────────────────────────┐  │
│  │ SYMFONY AI PROVIDER                                                   │  │
│  │ SymfonyAiProvider                                                     │  │
│  │ • Agent selection (creative/balanced/precise)                         │  │
│  │ • Cost calculation and metadata tracking                              │  │
│  │ • Mock mode support                                                   │  │
│  └───────────────────────────────────────────────────────────────────────┘  │
│                                  ↓                                          │
│  ┌───────────────────────────────────────────────────────────────────────┐  │
│  │ CUSTOM GATEWAY PLATFORM                                               │  │
│  │ CustomGatewayPlatform (implements PlatformInterface)                  │  │
│  │ • Bypasses model catalog validation                                   │  │
│  │ • Supports custom model names (claude-sonnet-4.5)                     │  │
│  │ • Extracts messages from Symfony AI objects                           │  │
│  │ • Builds OpenAI-compatible payloads                                   │  │
│  └───────────────────────────────────────────────────────────────────────┘  │
│                                  ↓                                          │
│  ┌───────────────────────────────────────────────────────────────────────┐  │
│  │ AUTH OVERRIDE HTTP CLIENT                                             │  │
│  │ AuthOverrideHttpClient (decorates HttpClient)                         │  │
│  │ • Overrides auth_bearer with actual API key                           │  │
│  │ • Rewrites URLs: /v1/responses → /v1/chat/completions                 │  │
│  │ • Transforms payload: indexed messages → messages array               │  │
│  └───────────────────────────────────────────────────────────────────────┘  │
│                                  ↓                                          │
│  ┌───────────────────────────────────────────────────────────────────────┐  │
│  │ HTTP CLIENT                                                           │  │
│  │ Symfony HttpClient                                                    │  │
│  │ • HTTP requests, connection pooling, retries, timeouts                │  │
│  └───────────────────────────────────────────────────────────────────────┘  │
│                                  ↓                                          │
│  ┌───────────────────────────────────────────────────────────────────────┐  │
│  │ AI GATEWAY / API                                                      │  │
│  │ • OpenAI API (api.openai.com)                                         │  │
│  │ •  Gateway (api.yappa.ai)                                             │  │
│  └───────────────────────────────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────────────────┐
│                      OUTPUT LAYER: EXTERNAL DESTINATIONS                    │
│                                                                             │
│  Notion Pages          Email (SMTP)          Slack Messages                 │
│  • Digest pages        • Digest emails       • Digest notifications         │
│  • Knowledge sync      • Summary reports     • Knowledge updates            │
│  • Category sync                                                            │
│                                                                             │
│  API Responses         CLI Output            Webhooks                       │
│  • JSON responses      • Console output      • External integrations        │
│  • Status codes        • Progress logs                                      │
└─────────────────────────────────────────────────────────────────────────────┘

Directory Structure

NOTE

The detailed directory structure for the entire project is now maintained in [project_structure.md](file:///home/ubuntu/yappa-knowledge-hub/docs/project/project_structure.md). Please refer to that file for the most up-to-date tree view of the codebase.