This commit is contained in:
2026-05-25 14:02:56 +02:00
parent 29bd42e52e
commit 758b152a0c
1798 changed files with 1991205 additions and 481068 deletions
@@ -0,0 +1,56 @@
# ICommand
- File ID: file:gg5jm5:icommand-cs
- Path: NexusReader.Application/Abstractions/Messaging/ICommand.cs
- Role: handler
- Layer: application
## Purpose
Defines application-level command message contracts used with MediatR and FluentResults to represent commands that return operation Results.
## Key Details
Two marker interfaces mapping application commands to MediatR IRequest<Result> / IRequest<Result<T>> using FluentResults; no runtime logic in this file.
## Symbols
- ICommand: Marker interface for commands that produce a FluentResults.Result with no payload via MediatR.
- ICommand<TResponse>: Generic marker interface for commands that produce a FluentResults.Result<TResponse> via MediatR.
## Dependencies
- No resolved dependencies.
## Calls
- No resolved calls.
## Coverage
- Symbols: 2
- Executable symbols: 0
- Executable symbols with control flow: 0
- Grounded edges: 2
- Unresolved references: 0
- Control-flow fragments: 0
- Unresolved jumps: 0
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 1
- Generated diagrams: 1
## Diagrams
### ICommand Neighborhood
```mermaid
flowchart LR
file_gg5jm5_icommand_cs("ICommand")
type_3fxux_icommand[/"ICommand"/]
type_l6ns3r_icommand_tresponse[/"ICommand<TResponse>"/]
```
## Diagram Validation
- Status: pass
@@ -0,0 +1,56 @@
# ICommandHandler
- File ID: file:kgb933:icommandhandler-cs
- Path: NexusReader.Application/Abstractions/Messaging/ICommandHandler.cs
- Role: handler
- Layer: application
## Purpose
Defines application-level command handler contracts that adapt MediatR IRequestHandler to return FluentResults.Result wrappers for command operations.
## Key Details
Two small generic interfaces that adapt MediatR's IRequestHandler to return FluentResults.Result/Result<T>, serving as the application-layer command handler abstractions.
## Symbols
- ICommandHandler<TCommand>: Contract for handling command messages that returns a FluentResults.Result indicating success or failure.
- ICommandHandler<TCommand, TResponse>: Contract for handling command messages that return a typed response wrapped in FluentResults.Result<TResponse>.
## Dependencies
- No resolved dependencies.
## Calls
- No resolved calls.
## Coverage
- Symbols: 2
- Executable symbols: 0
- Executable symbols with control flow: 0
- Grounded edges: 2
- Unresolved references: 0
- Control-flow fragments: 0
- Unresolved jumps: 0
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 1
- Generated diagrams: 1
## Diagrams
### ICommandHandler Neighborhood
```mermaid
flowchart LR
file_kgb933_icommandhandler_cs("ICommandHandler")
type_1a1s3lb_icommandhandler_tcommand_tresponse[/"ICommandHandler<TCommand, TResponse>"/]
type_l7ofd8_icommandhandler_tcommand[/"ICommandHandler<TCommand>"/]
```
## Diagram Validation
- Status: pass
@@ -0,0 +1,56 @@
# IQuery
- File ID: file:1k4g04u:iquery-cs
- Path: NexusReader.Application/Abstractions/Messaging/IQuery.cs
- Role: handler
- Layer: application
## Purpose
Defines a generic marker/query contract for application queries that return a FluentResults-wrapped response via MediatR.
## Key Details
A tiny application-layer abstraction: a generic query contract that maps to MediatR IRequest<Result<TResponse>> enabling handlers to return FluentResults.
## Symbols
- IQuery<TResponse>: Defines a generic marker/query contract for application queries that return a FluentResults-wrapped response via MediatR.
- IQuery<TResponse>: Marker interface representing a CQRS query that yields a Result-wrapped response handled by MediatR.
## Dependencies
- No resolved dependencies.
## Calls
- No resolved calls.
## Coverage
- Symbols: 2
- Executable symbols: 0
- Executable symbols with control flow: 0
- Grounded edges: 2
- Unresolved references: 0
- Control-flow fragments: 0
- Unresolved jumps: 0
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 1
- Generated diagrams: 1
## Diagrams
### IQuery Neighborhood
```mermaid
flowchart LR
class_4nrp60_iquery_tresponse("IQuery<TResponse>")
file_1k4g04u_iquery_cs("IQuery")
type_dj3u3k_iquery_tresponse[/"IQuery<TResponse>"/]
```
## Diagram Validation
- Status: pass
@@ -0,0 +1,76 @@
# IQueryHandler
- File ID: file:ayj9r2:iqueryhandler-cs
- Path: NexusReader.Application/Abstractions/Messaging/IQueryHandler.cs
- Role: handler
- Layer: application
## Purpose
Declares an application-layer abstraction for handling queries (CQRS) where handlers return a FluentResults.Result<TResponse> via MediatR.
## Key Details
Thin application-layer abstraction that binds the project's IQuery<TResponse> concept to MediatR's IRequestHandler and FluentResults.Result for uniform asynchronous query handling.
## Symbols
- IQueryHandler: Declares an application-layer abstraction for handling queries (CQRS) where handlers return a FluentResults.Result<TResponse> via MediatR.
- Handle(): Implied contract method for handling a query and returning a Result-wrapped TResponse asynchronously (inherited from MediatR IRequestHandler).
- IQueryHandler: Generic interface representing a query handler that processes a TQuery and returns a Result-wrapped TResponse using MediatR semantics.
## Dependencies
- No resolved dependencies.
## Calls
- No resolved calls.
## Unresolved References
- dependency-target: FluentResults
- dependency-target: MediatR
## Coverage
- Symbols: 3
- Executable symbols: 1
- Executable symbols with control flow: 1
- Grounded edges: 3
- Unresolved references: 2
- Control-flow fragments: 1
- Unresolved jumps: 0
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 2
- Generated diagrams: 2
## Control Flow Fragments
- Handle: 4 nodes, 3 edges, 0 jumps, 0 unsupported constructs
## Diagrams
### IQueryHandler Neighborhood
```mermaid
flowchart LR
class_daunpv_iqueryhandler("IQueryHandler")
file_ayj9r2_iqueryhandler_cs("IQueryHandler")
method_7ldigq_handle[["Handle()"]]
type_tpv4sn_iqueryhandler[/"IQueryHandler"/]
```
### IQueryHandler Execution Overview
```mermaid
flowchart TD
class_daunpv_iqueryhandler("IQueryHandler")
method_7ldigq_handle[["Handle()"]]
class_daunpv_iqueryhandler -->|contains| method_7ldigq_handle
```
## Diagram Validation
- Status: pass
@@ -0,0 +1,76 @@
# ISyncBroadcaster
- File ID: file:441s21:isyncbroadcaster-cs
- Path: NexusReader.Application/Abstractions/Messaging/ISyncBroadcaster.cs
- Role: service
- Layer: application
## Purpose
Defines an application-layer abstraction for broadcasting real-time synchronization and ingestion progress events to connected client devices (keeps Application layer decoupled from SignalR).
## Key Details
Interface intentionally defined in Application layer to avoid a direct dependency on SignalR; concrete implementations (in Infrastructure) will perform the actual SignalR or other transport operations.
## Symbols
- ISyncBroadcaster: Defines an application-layer abstraction for broadcasting real-time synchronization and ingestion progress events to connected client devices (keeps Application layer decoupled from SignalR).
- BroadcastProgressAsync(): Declares an asynchronous broadcast of a user's reading progress to that user's devices, optionally excluding a specific connection.
- BroadcastIngestionProgressAsync(): Declares an asynchronous broadcast of ingestion (background processing) status and progress to a specific user.
- ISyncBroadcaster: Application-layer interface abstracting real-time broadcasting behavior (keeps handlers free of SignalR dependency).
## Dependencies
- No resolved dependencies.
## Calls
- No resolved calls.
## Coverage
- Symbols: 4
- Executable symbols: 2
- Executable symbols with control flow: 2
- Grounded edges: 4
- Unresolved references: 0
- Control-flow fragments: 2
- Unresolved jumps: 0
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 2
- Generated diagrams: 2
## Control Flow Fragments
- BroadcastProgressAsync: 4 nodes, 3 edges, 0 jumps, 0 unsupported constructs
- BroadcastIngestionProgressAsync: 4 nodes, 3 edges, 0 jumps, 0 unsupported constructs
## Diagrams
### ISyncBroadcaster Neighborhood
```mermaid
flowchart LR
class_1kfpdx9_isyncbroadcaster("ISyncBroadcaster")
file_441s21_isyncbroadcaster_cs("ISyncBroadcaster")
method_3uewqk_broadcastprogressasync[["BroadcastProgressAsync()"]]
method_uqgfbl_broadcastingestionprogressasync[["BroadcastIngestionProgressAsync()"]]
type_dqp6wm_isyncbroadcaster[/"ISyncBroadcaster"/]
```
### ISyncBroadcaster Execution Overview
```mermaid
flowchart TD
class_1kfpdx9_isyncbroadcaster("ISyncBroadcaster")
method_3uewqk_broadcastprogressasync[["BroadcastProgressAsync()"]]
method_uqgfbl_broadcastingestionprogressasync[["BroadcastIngestionProgressAsync()"]]
class_1kfpdx9_isyncbroadcaster -->|contains| method_3uewqk_broadcastprogressasync
class_1kfpdx9_isyncbroadcaster -->|contains| method_uqgfbl_broadcastingestionprogressasync
```
## Diagram Validation
- Status: pass
@@ -0,0 +1,93 @@
# IEbookRepository
- File ID: file:1hlb3r7:iebookrepository-cs
- Path: NexusReader.Application/Abstractions/Persistence/IEbookRepository.cs
- Role: repository
- Layer: application
## Purpose
Defines the application-layer abstraction for ebook and author persistence operations (repository interface) so the Application layer can depend on an interface rather than EF Core or other infra implementations.
## Key Details
Interface lives in Application.Abstractions.Persistence to decouple application logic from EF Core; methods indicate staged add semantics and an explicit SaveChangesAsync for committing changes.
## Symbols
- IEbookRepository: Defines the application-layer abstraction for ebook and author persistence operations (repository interface) so the Application layer can depend on an interface rather than EF Core or other infra implementations.
- FindAuthorByNameAsync(): Asynchronously finds an Author by name using a case-insensitive comparison.
- AddAuthor(): Stages a new Author in the repository (adds to the change tracker / in-memory unit-of-work) but does not persist.
- AddEbook(): Stages a new Ebook in the repository (adds to the change tracker / in-memory unit-of-work) but does not persist.
- SaveChangesAsync(): Persists all staged changes to the underlying store and returns the number of affected entries.
- IEbookRepository: Application-layer abstraction describing persistence operations for Ebook and Author to avoid a direct dependency on EF Core.
## Dependencies
- No resolved dependencies.
## Calls
- No resolved calls.
## Unresolved References
- dependency-target: NexusReader.Domain/Entities
- interaction-target: Task<Author?> FindAuthorByNameAsync(string name, CancellationToken cancellationToken = default);
## Coverage
- Symbols: 6
- Executable symbols: 4
- Executable symbols with control flow: 4
- Grounded edges: 6
- Unresolved references: 2
- Control-flow fragments: 4
- Unresolved jumps: 0
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 2
- Generated diagrams: 2
## Control Flow Fragments
- FindAuthorByNameAsync: 5 nodes, 4 edges, 0 jumps, 0 unsupported constructs
- AddAuthor: 3 nodes, 2 edges, 0 jumps, 0 unsupported constructs
- AddEbook: 3 nodes, 2 edges, 0 jumps, 0 unsupported constructs
- SaveChangesAsync: 3 nodes, 2 edges, 0 jumps, 0 unsupported constructs
## Diagrams
### IEbookRepository Neighborhood
```mermaid
flowchart LR
class_ir9z2o_iebookrepository("IEbookRepository")
file_1hlb3r7_iebookrepository_cs("IEbookRepository")
method_2iyuvn_addauthor[["AddAuthor()"]]
method_3jcuy_findauthorbynameasync[["FindAuthorByNameAsync()"]]
method_grwwrg_savechangesasync[["SaveChangesAsync()"]]
method_ij0vl0_addebook[["AddEbook()"]]
type_sv23ol_iebookrepository[/"IEbookRepository"/]
```
### IEbookRepository Execution Overview
```mermaid
flowchart TD
class_ir9z2o_iebookrepository("IEbookRepository")
method_2iyuvn_addauthor[["AddAuthor()"]]
method_3jcuy_findauthorbynameasync[["FindAuthorByNameAsync()"]]
method_grwwrg_savechangesasync[["SaveChangesAsync()"]]
method_ij0vl0_addebook[["AddEbook()"]]
unresolved_unresolved_1bf761s_interaction_target{"Unresolved: Task<Author?> FindAuthorByNameAsync(string name, CancellationToken cancellationToken = default);"}
class_ir9z2o_iebookrepository -->|contains| method_2iyuvn_addauthor
class_ir9z2o_iebookrepository -->|contains| method_3jcuy_findauthorbynameasync
class_ir9z2o_iebookrepository -->|contains| method_grwwrg_savechangesasync
class_ir9z2o_iebookrepository -->|contains| method_ij0vl0_addebook
class_ir9z2o_iebookrepository -->|unresolved interaction| unresolved_unresolved_1bf761s_interaction_target
```
## Diagram Validation
- Status: pass
@@ -0,0 +1,81 @@
# IBillingService
- File ID: file:rfn6bc:ibillingservice-cs
- Path: NexusReader.Application/Abstractions/Services/IBillingService.cs
- Role: service
- Layer: application
## Purpose
Defines an application-layer billing service abstraction that declares handlers for subscription updates and deletions (used by infrastructure implementations to react to Stripe/customer events).
## Key Details
Pure interface in the Application.Abstractions layer; no runtime behavior here—concrete implementations will perform persistence, external calls, mapping, and error handling and return FluentResults.Result.
## Symbols
- IBillingService: Defines an application-layer billing service abstraction that declares handlers for subscription updates and deletions (used by infrastructure implementations to react to Stripe/customer events).
- HandleSubscriptionUpdatedAsync(): Contract for handling when a customer's subscription is created or updated (by Stripe or equivalent).
- HandleSubscriptionDeletedAsync(): Contract for handling when a customer's subscription is deleted (cleanup or downgrade actions).
- IBillingService: Abstraction exposing billing/subscription lifecycle handlers to be implemented by infrastructure or application services.
## Dependencies
- No resolved dependencies.
## Calls
- No resolved calls.
## Unresolved References
- dependency-target: NexusReader.Domain.Entities (using)
- dependency-target: FluentResults (using)
## Coverage
- Symbols: 4
- Executable symbols: 2
- Executable symbols with control flow: 2
- Grounded edges: 4
- Unresolved references: 2
- Control-flow fragments: 2
- Unresolved jumps: 0
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 2
- Generated diagrams: 2
## Control Flow Fragments
- HandleSubscriptionUpdatedAsync: 3 nodes, 2 edges, 0 jumps, 0 unsupported constructs
- HandleSubscriptionDeletedAsync: 3 nodes, 2 edges, 0 jumps, 0 unsupported constructs
## Diagrams
### IBillingService Neighborhood
```mermaid
flowchart LR
class_qlxnhj_ibillingservice("IBillingService")
file_rfn6bc_ibillingservice_cs("IBillingService")
method_16n7wyr_handlesubscriptiondeletedasync[["HandleSubscriptionDeletedAsync()"]]
method_1px2su2_handlesubscriptionupdatedasync[["HandleSubscriptionUpdatedAsync()"]]
type_dvqqtf_ibillingservice[/"IBillingService"/]
```
### IBillingService Execution Overview
```mermaid
flowchart TD
class_qlxnhj_ibillingservice("IBillingService")
method_16n7wyr_handlesubscriptiondeletedasync[["HandleSubscriptionDeletedAsync()"]]
method_1px2su2_handlesubscriptionupdatedasync[["HandleSubscriptionUpdatedAsync()"]]
class_qlxnhj_ibillingservice -->|contains| method_16n7wyr_handlesubscriptiondeletedasync
class_qlxnhj_ibillingservice -->|contains| method_1px2su2_handlesubscriptionupdatedasync
```
## Diagram Validation
- Status: pass
@@ -0,0 +1,86 @@
# IBookStorageService
- File ID: file:9fivst:ibookstorageservice-cs
- Path: NexusReader.Application/Abstractions/Services/IBookStorageService.cs
- Role: service
- Layer: application
## Purpose
Defines an application-level abstraction for saving ebook and cover files, returning relative paths/URLs; implementations handle actual storage persistence.
## Key Details
Interface provides async contracts for saving ebooks and covers (byte[] or Stream) and returning relative paths/URLs; cover methods explicitly allow null return when no data is provided.
## Symbols
- IBookStorageService: Defines an application-level abstraction for saving ebook and cover files, returning relative paths/URLs; implementations handle actual storage persistence.
- SaveEbookAsync(): Contract to save ebook binary data and return a relative path/URL.
- SaveEbookAsync(): Contract to save ebook data from a Stream and return a relative path/URL.
- SaveCoverAsync(): Contract to save cover image binary data and return a relative path/URL, or null if no cover provided.
- SaveCoverAsync(): Contract to save cover image from a Stream and return a relative path/URL, or null if no cover provided.
- IBookStorageService: Interface describing methods to persist ebooks and cover images and return their relative paths/URLs.
## Dependencies
- No resolved dependencies.
## Calls
- No resolved calls.
## Coverage
- Symbols: 6
- Executable symbols: 4
- Executable symbols with control flow: 4
- Grounded edges: 6
- Unresolved references: 0
- Control-flow fragments: 4
- Unresolved jumps: 0
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 2
- Generated diagrams: 2
## Control Flow Fragments
- SaveEbookAsync: 3 nodes, 2 edges, 0 jumps, 0 unsupported constructs
- SaveEbookAsync: 3 nodes, 2 edges, 0 jumps, 0 unsupported constructs
- SaveCoverAsync: 3 nodes, 2 edges, 0 jumps, 0 unsupported constructs
- SaveCoverAsync: 3 nodes, 2 edges, 0 jumps, 0 unsupported constructs
## Diagrams
### IBookStorageService Neighborhood
```mermaid
flowchart LR
class_lhjxtl_ibookstorageservice("IBookStorageService")
file_9fivst_ibookstorageservice_cs("IBookStorageService")
method_1bjnsl7_saveebookasync[["SaveEbookAsync()"]]
method_1cxlt22_saveebookasync[["SaveEbookAsync()"]]
method_1pww9i7_savecoverasync[["SaveCoverAsync()"]]
method_1sosafx_savecoverasync[["SaveCoverAsync()"]]
type_gqvtnh_ibookstorageservice[/"IBookStorageService"/]
```
### IBookStorageService Execution Overview
```mermaid
flowchart TD
class_lhjxtl_ibookstorageservice("IBookStorageService")
method_1bjnsl7_saveebookasync[["SaveEbookAsync()"]]
method_1cxlt22_saveebookasync[["SaveEbookAsync()"]]
method_1pww9i7_savecoverasync[["SaveCoverAsync()"]]
method_1sosafx_savecoverasync[["SaveCoverAsync()"]]
class_lhjxtl_ibookstorageservice -->|contains| method_1bjnsl7_saveebookasync
class_lhjxtl_ibookstorageservice -->|contains| method_1cxlt22_saveebookasync
class_lhjxtl_ibookstorageservice -->|contains| method_1pww9i7_savecoverasync
class_lhjxtl_ibookstorageservice -->|contains| method_1sosafx_savecoverasync
```
## Diagram Validation
- Status: pass
@@ -0,0 +1,75 @@
# IEpubMetadataExtractor
- File ID: file:vdwqp9:iepubmetadataextractor-cs
- Path: NexusReader.Application/Abstractions/Services/IEpubMetadataExtractor.cs
- Role: service
- Layer: application
## Purpose
Defines an application-layer abstraction for extracting metadata from an EPUB stream, returning a Result-wrapped LocalEpubMetadata asynchronously.
## Key Details
Interface exposes a single async method returning Task<Result<LocalEpubMetadata>>; implementation responsibilities include stream parsing and error/result handling via FluentResults.
## Symbols
- IEpubMetadataExtractor: Defines an application-layer abstraction for extracting metadata from an EPUB stream, returning a Result-wrapped LocalEpubMetadata asynchronously.
- ExtractMetadataAsync(): Asynchronously extracts metadata from the provided EPUB stream and returns it wrapped in a FluentResults Result.
## Dependencies
- No resolved dependencies.
## Calls
- No resolved calls.
## Unresolved References
- dependency-target: FluentResults (NuGet/namespace)
- dependency-target: NexusReader.Application.Queries.Reader (namespace containing LocalEpubMetadata)
- dependency-target: System.IO (Stream)
## Coverage
- Symbols: 2
- Executable symbols: 1
- Executable symbols with control flow: 1
- Grounded edges: 2
- Unresolved references: 3
- Control-flow fragments: 1
- Unresolved jumps: 0
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 2
- Generated diagrams: 2
## Control Flow Fragments
- ExtractMetadataAsync: 3 nodes, 2 edges, 0 jumps, 0 unsupported constructs
## Diagrams
### IEpubMetadataExtractor Neighborhood
```mermaid
flowchart LR
class_18sfucp_iepubmetadataextractor("IEpubMetadataExtractor")
file_vdwqp9_iepubmetadataextractor_cs("IEpubMetadataExtractor")
method_hwn6lg_extractmetadataasync[["ExtractMetadataAsync()"]]
```
### IEpubMetadataExtractor Execution Overview
```mermaid
flowchart TD
class_18sfucp_iepubmetadataextractor("IEpubMetadataExtractor")
method_hwn6lg_extractmetadataasync[["ExtractMetadataAsync()"]]
class_18sfucp_iepubmetadataextractor -->|contains| method_hwn6lg_extractmetadataasync
```
## Diagram Validation
- Status: pass
@@ -0,0 +1,76 @@
# IEpubReader
- File ID: file:1mo9e25:iepubreader-cs
- Path: NexusReader.Application/Abstractions/Services/IEpubReader.cs
- Role: service
- Layer: application
## Purpose
Defines the application service contract for reading and parsing EPUB content for a specific ebook and chapter (async, tenant-aware).
## Key Details
Single-method interface; method is async, returns FluentResults-wrapped ReaderPageViewModel, accepts optional userId for tenant isolation and CancellationToken for cancellation.
## Symbols
- IEpubReader: Defines the application service contract for reading and parsing EPUB content for a specific ebook and chapter (async, tenant-aware).
- GetEpubContentAsync(): Asynchronously retrieves parsed EPUB content blocks (a ReaderPageViewModel) for the specified ebook and zero-based chapter index, optionally scoped to a user and cancellable.
- IEpubReader: Service contract that exposes EPUB reading/parsing behavior for ebooks and chapters.
## Dependencies
- No resolved dependencies.
## Calls
- No resolved calls.
## Unresolved References
- dependency-target: NexusReader.Application.Queries.Reader (ReaderPageViewModel referenced)
- dependency-target: FluentResults (Result<T> usage)
## Coverage
- Symbols: 3
- Executable symbols: 1
- Executable symbols with control flow: 1
- Grounded edges: 3
- Unresolved references: 2
- Control-flow fragments: 1
- Unresolved jumps: 0
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 2
- Generated diagrams: 2
## Control Flow Fragments
- GetEpubContentAsync: 6 nodes, 5 edges, 0 jumps, 0 unsupported constructs
## Diagrams
### IEpubReader Neighborhood
```mermaid
flowchart LR
class_euc6fx_iepubreader("IEpubReader")
file_1mo9e25_iepubreader_cs("IEpubReader")
method_121clyd_getepubcontentasync[["GetEpubContentAsync()"]]
type_1yqx104_iepubreader[/"IEpubReader"/]
```
### IEpubReader Execution Overview
```mermaid
flowchart TD
class_euc6fx_iepubreader("IEpubReader")
method_121clyd_getepubcontentasync[["GetEpubContentAsync()"]]
class_euc6fx_iepubreader -->|contains| method_121clyd_getepubcontentasync
```
## Diagram Validation
- Status: pass
@@ -0,0 +1,100 @@
# IIdentityService
- File ID: file:1ud0jop:iidentityservice-cs
- Path: NexusReader.Application/Abstractions/Services/IIdentityService.cs
- Role: service
- Layer: application
## Purpose
Defines the identity/authentication abstraction for the Application layer: registration, login/logout, profile retrieval, token refresh, and an event for state invalidation.
## Key Details
This file only declares the IIdentityService interface and an OnStateInvalidated event; concrete implementations elsewhere will perform orchestration, external calls, persistence, and error handling.
## Symbols
- OnStateInvalidated(): Event triggered when identity/authentication state becomes invalid and consumers should react (e.g., clear state or re-authenticate).
- RegisterAsync(): Registers a new user account using email and password and returns a success/failure Result.
- LoginAsync(): Authenticates a user with credentials and optional persistence (rememberMe) and returns a Result.
- LogoutAsync(): Logs out the current user and returns a Result indicating success/failure.
- GetProfileAsync(): Retrieves the current user's profile wrapped in a Result with UserProfileDto on success.
- RefreshTokenAsync(): Requests a token refresh for the current authentication session and returns a Result indicating success/failure.
- IIdentityService: Service contract defining identity/authentication operations and an event for invalidation.
## Dependencies
- imports NexusReader.Application/DTOs/User/UserProfileDto.cs
## Calls
- No resolved calls.
## Unresolved References
- dependency-target: FluentResults (external package)
## Coverage
- Symbols: 7
- Executable symbols: 6
- Executable symbols with control flow: 6
- Grounded edges: 8
- Unresolved references: 1
- Control-flow fragments: 6
- Unresolved jumps: 0
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 2
- Generated diagrams: 2
## Control Flow Fragments
- OnStateInvalidated: 3 nodes, 2 edges, 0 jumps, 0 unsupported constructs
- RegisterAsync: 3 nodes, 2 edges, 0 jumps, 0 unsupported constructs
- LoginAsync: 3 nodes, 2 edges, 0 jumps, 0 unsupported constructs
- LogoutAsync: 3 nodes, 2 edges, 0 jumps, 0 unsupported constructs
- GetProfileAsync: 3 nodes, 2 edges, 0 jumps, 0 unsupported constructs
- RefreshTokenAsync: 3 nodes, 2 edges, 0 jumps, 0 unsupported constructs
## Diagrams
### IIdentityService Neighborhood
```mermaid
flowchart LR
file_1ud0jop_iidentityservice_cs("IIdentityService")
method_12nj2l_registerasync[["RegisterAsync()"]]
method_1gbqw83_refreshtokenasync[["RefreshTokenAsync()"]]
method_1ww1s1_loginasync[["LoginAsync()"]]
method_d5t49u_onstateinvalidated[["OnStateInvalidated()"]]
method_urpd77_logoutasync[["LogoutAsync()"]]
method_yzr6ph_getprofileasync[["GetProfileAsync()"]]
file_1fs0p2c_userprofiledto_cs[/"UserProfileDto"/]
type_udpmrx_iidentityservice[/"IIdentityService"/]
file_1ud0jop_iidentityservice_cs -->|UserProfileDto| file_1fs0p2c_userprofiledto_cs
```
### IIdentityService Execution Overview
```mermaid
flowchart TD
file_1ud0jop_iidentityservice_cs("IIdentityService")
method_12nj2l_registerasync[["RegisterAsync()"]]
method_1gbqw83_refreshtokenasync[["RefreshTokenAsync()"]]
method_1ww1s1_loginasync[["LoginAsync()"]]
method_d5t49u_onstateinvalidated[["OnStateInvalidated()"]]
method_urpd77_logoutasync[["LogoutAsync()"]]
method_yzr6ph_getprofileasync[["GetProfileAsync()"]]
file_1ud0jop_iidentityservice_cs -->|contains| method_12nj2l_registerasync
file_1ud0jop_iidentityservice_cs -->|contains| method_1gbqw83_refreshtokenasync
file_1ud0jop_iidentityservice_cs -->|contains| method_1ww1s1_loginasync
file_1ud0jop_iidentityservice_cs -->|contains| method_d5t49u_onstateinvalidated
file_1ud0jop_iidentityservice_cs -->|contains| method_urpd77_logoutasync
file_1ud0jop_iidentityservice_cs -->|contains| method_yzr6ph_getprofileasync
```
## Diagram Validation
- Status: pass
@@ -0,0 +1,116 @@
# IKnowledgeService
- File ID: file:pvs6tn:iknowledgeservice-cs
- Path: NexusReader.Application/Abstractions/Services/IKnowledgeService.cs
- Role: service
- Layer: application
## Purpose
Defines the application-level abstraction for knowledge-related operations (semantic search, summarization, QA, groundedness checks, cache management) used by higher-level components.
## Key Details
Application-level abstraction returning FluentResults-wrapped DTOs (KnowledgePacket, GroundedResponseDto, SemanticSearchResultDto). No runtime logic in this file; it defines contracts for knowledge-related orchestration implemented elsewhere.
## Symbols
- IKnowledgeService: Defines the application-level abstraction for knowledge-related operations (semantic search, summarization, QA, groundedness checks, cache management) used by higher-level components.
- GetKnowledgeAsync(): Return a KnowledgePacket for provided text scoped to a tenant and optional ebook.
- GetGraphDataAsync(): Produce graph-structured knowledge data for the given text and tenant context.
- GetKnowledgeMapAsync(): Generate a knowledge map (likely node/edge representation) for the supplied text and tenant.
- GetSummaryAndQuizAsync(): Create a summary and quiz (assessment) artifact for given text within tenant/ebook scope.
- GetRelevantContextAsync(): Retrieve a list of relevant context snippets for a query within a tenant.
- VerifyGroundednessAsync(): Evaluate whether an answer is grounded in provided context and return a score/rationale.
- SearchLibrarySemanticallyAsync(): Perform a semantic search over the library for a tenant and return top results up to a limit.
- AskQuestionAsync(): Ask a question against tenant (and optional ebook) data and return a grounded response, limited by passed limit.
- ClearCacheAsync(): Clear any service-level caches used by the knowledge subsystem.
- GroundednessResult: Represents the outcome of a groundedness check with score, rationale, and boolean flag.
## Dependencies
- No resolved dependencies.
## Calls
- No resolved calls.
## Unresolved References
- dependency-target: FluentResults
- dependency-target: NexusReader.Application.DTOs.AI
## Coverage
- Symbols: 11
- Executable symbols: 9
- Executable symbols with control flow: 9
- Grounded edges: 11
- Unresolved references: 2
- Control-flow fragments: 9
- Unresolved jumps: 0
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 2
- Generated diagrams: 2
## Control Flow Fragments
- GetKnowledgeAsync: 3 nodes, 2 edges, 0 jumps, 0 unsupported constructs
- GetGraphDataAsync: 3 nodes, 2 edges, 0 jumps, 0 unsupported constructs
- GetKnowledgeMapAsync: 3 nodes, 2 edges, 0 jumps, 0 unsupported constructs
- GetSummaryAndQuizAsync: 3 nodes, 2 edges, 0 jumps, 0 unsupported constructs
- GetRelevantContextAsync: 3 nodes, 2 edges, 0 jumps, 0 unsupported constructs
- VerifyGroundednessAsync: 3 nodes, 2 edges, 0 jumps, 0 unsupported constructs
- SearchLibrarySemanticallyAsync: 3 nodes, 2 edges, 0 jumps, 0 unsupported constructs
- AskQuestionAsync: 3 nodes, 2 edges, 0 jumps, 0 unsupported constructs
- ClearCacheAsync: 3 nodes, 2 edges, 0 jumps, 0 unsupported constructs
## Diagrams
### IKnowledgeService Neighborhood
```mermaid
flowchart LR
class_utixgx_iknowledgeservice("IKnowledgeService")
file_pvs6tn_iknowledgeservice_cs("IKnowledgeService")
method_1ckhg6n_getknowledgeasync[["GetKnowledgeAsync()"]]
method_1g8j6qo_getgraphdataasync[["GetGraphDataAsync()"]]
method_1oclqd_verifygroundednessasync[["VerifyGroundednessAsync()"]]
method_1odjeej_searchlibrarysemanticallyasync[["SearchLibrarySemanticallyAsync()"]]
method_1yhcrn6_getrelevantcontextasync[["GetRelevantContextAsync()"]]
method_26njdb_clearcacheasync[["ClearCacheAsync()"]]
method_7pcmld_getsummaryandquizasync[["GetSummaryAndQuizAsync()"]]
method_cuqhj0_getknowledgemapasync[["GetKnowledgeMapAsync()"]]
method_f76by4_askquestionasync[["AskQuestionAsync()"]]
type_1a84if1_groundednessresult[/"GroundednessResult"/]
```
### IKnowledgeService Execution Overview
```mermaid
flowchart TD
class_utixgx_iknowledgeservice("IKnowledgeService")
method_1ckhg6n_getknowledgeasync[["GetKnowledgeAsync()"]]
method_1g8j6qo_getgraphdataasync[["GetGraphDataAsync()"]]
method_1oclqd_verifygroundednessasync[["VerifyGroundednessAsync()"]]
method_1odjeej_searchlibrarysemanticallyasync[["SearchLibrarySemanticallyAsync()"]]
method_1yhcrn6_getrelevantcontextasync[["GetRelevantContextAsync()"]]
method_26njdb_clearcacheasync[["ClearCacheAsync()"]]
method_7pcmld_getsummaryandquizasync[["GetSummaryAndQuizAsync()"]]
method_cuqhj0_getknowledgemapasync[["GetKnowledgeMapAsync()"]]
method_f76by4_askquestionasync[["AskQuestionAsync()"]]
class_utixgx_iknowledgeservice -->|contains| method_1ckhg6n_getknowledgeasync
class_utixgx_iknowledgeservice -->|contains| method_1g8j6qo_getgraphdataasync
class_utixgx_iknowledgeservice -->|contains| method_1oclqd_verifygroundednessasync
class_utixgx_iknowledgeservice -->|contains| method_1odjeej_searchlibrarysemanticallyasync
class_utixgx_iknowledgeservice -->|contains| method_1yhcrn6_getrelevantcontextasync
class_utixgx_iknowledgeservice -->|contains| method_26njdb_clearcacheasync
class_utixgx_iknowledgeservice -->|contains| method_7pcmld_getsummaryandquizasync
class_utixgx_iknowledgeservice -->|contains| method_cuqhj0_getknowledgemapasync
class_utixgx_iknowledgeservice -->|contains| method_f76by4_askquestionasync
```
## Diagram Validation
- Status: pass
@@ -0,0 +1,106 @@
# INativeStorageService
- File ID: file:1it42kj:inativestorageservice-cs
- Path: NexusReader.Application/Abstractions/Services/INativeStorageService.cs
- Role: service
- Layer: application
## Purpose
Defines an application-level abstraction for platform/native key-value storage including secure and non-secure reads, writes, and removals.
## Key Details
Interface-only file that declares async Result-wrapped operations for secure and non-secure platform storage; implementations will perform the actual native persistence and security handling.
## Symbols
- INativeStorageService: Defines an application-level abstraction for platform/native key-value storage including secure and non-secure reads, writes, and removals.
- SaveStringAsync(): Persist a non-secure string value under the given key asynchronously.
- GetStringAsync(): Retrieve a non-secure string value by key asynchronously.
- SaveBoolAsync(): Persist a boolean value under the given key asynchronously.
- GetBoolAsync(): Retrieve a boolean value by key asynchronously, returning a provided default if absent.
- RemoveAsync(): Remove a non-secure entry by key from native storage asynchronously.
- SaveSecureString(): Persist a string securely (platform secure storage) under the given key asynchronously.
- GetSecureString(): Retrieve a secure string by key from platform secure storage asynchronously.
- RemoveSecureAsync(): Remove a secure entry by key from platform secure storage asynchronously.
- INativeStorageService: Abstraction for platform-specific key-value storage operations (secure and non-secure) used by application components.
## Dependencies
- No resolved dependencies.
## Calls
- No resolved calls.
## Coverage
- Symbols: 10
- Executable symbols: 8
- Executable symbols with control flow: 8
- Grounded edges: 10
- Unresolved references: 0
- Control-flow fragments: 8
- Unresolved jumps: 0
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 2
- Generated diagrams: 2
## Control Flow Fragments
- SaveStringAsync: 3 nodes, 2 edges, 0 jumps, 0 unsupported constructs
- GetStringAsync: 3 nodes, 2 edges, 0 jumps, 0 unsupported constructs
- SaveBoolAsync: 3 nodes, 2 edges, 0 jumps, 0 unsupported constructs
- GetBoolAsync: 7 nodes, 7 edges, 0 jumps, 0 unsupported constructs
- RemoveAsync: 3 nodes, 2 edges, 0 jumps, 0 unsupported constructs
- SaveSecureString: 3 nodes, 2 edges, 0 jumps, 0 unsupported constructs
- GetSecureString: 3 nodes, 2 edges, 0 jumps, 0 unsupported constructs
- RemoveSecureAsync: 3 nodes, 2 edges, 0 jumps, 0 unsupported constructs
## Diagrams
### INativeStorageService Neighborhood
```mermaid
flowchart LR
class_1owrs1t_inativestorageservice("INativeStorageService")
file_1it42kj_inativestorageservice_cs("INativeStorageService")
method_1070aok_getsecurestring[["GetSecureString()"]]
method_19tpzwe_getstringasync[["GetStringAsync()"]]
method_1oljw52_getboolasync[["GetBoolAsync()"]]
method_1wrq6fu_savestringasync[["SaveStringAsync()"]]
method_8lkc9b_saveboolasync[["SaveBoolAsync()"]]
method_ne3mm3_removeasync[["RemoveAsync()"]]
method_xfwbbe_removesecureasync[["RemoveSecureAsync()"]]
method_zxocvw_savesecurestring[["SaveSecureString()"]]
type_1vae1rw_inativestorageservice[/"INativeStorageService"/]
```
### INativeStorageService Execution Overview
```mermaid
flowchart TD
class_1owrs1t_inativestorageservice("INativeStorageService")
method_1070aok_getsecurestring[["GetSecureString()"]]
method_19tpzwe_getstringasync[["GetStringAsync()"]]
method_1oljw52_getboolasync[["GetBoolAsync()"]]
method_1wrq6fu_savestringasync[["SaveStringAsync()"]]
method_8lkc9b_saveboolasync[["SaveBoolAsync()"]]
method_ne3mm3_removeasync[["RemoveAsync()"]]
method_xfwbbe_removesecureasync[["RemoveSecureAsync()"]]
method_zxocvw_savesecurestring[["SaveSecureString()"]]
class_1owrs1t_inativestorageservice -->|contains| method_1070aok_getsecurestring
class_1owrs1t_inativestorageservice -->|contains| method_19tpzwe_getstringasync
class_1owrs1t_inativestorageservice -->|contains| method_1oljw52_getboolasync
class_1owrs1t_inativestorageservice -->|contains| method_1wrq6fu_savestringasync
class_1owrs1t_inativestorageservice -->|contains| method_8lkc9b_saveboolasync
class_1owrs1t_inativestorageservice -->|contains| method_ne3mm3_removeasync
class_1owrs1t_inativestorageservice -->|contains| method_xfwbbe_removesecureasync
class_1owrs1t_inativestorageservice -->|contains| method_zxocvw_savesecurestring
```
## Diagram Validation
- Status: pass
@@ -0,0 +1,90 @@
# IPlatformService
- File ID: file:wb18l0:iplatformservice-cs
- Path: NexusReader.Application/Abstractions/Services/IPlatformService.cs
- Role: service
- Layer: application
## Purpose
Defines a platform abstraction for device capabilities (vibration) and device metadata (device context) used by application code to remain platform-agnostic.
## Key Details
Uses FluentResults.Result for method returns, is an application-layer abstraction to be implemented by platform-specific code (likely in Infrastructure or UI platform projects).
## Symbols
- IPlatformService: Defines a platform abstraction for device capabilities (vibration) and device metadata (device context) used by application code to remain platform-agnostic.
- VibrateSuccessAsync(): Contract for invoking a short/success vibration on the device.
- VibrateErrorAsync(): Contract for invoking an error/alert vibration on the device.
- VibrateAsync(): Contract for invoking a vibration for a specified duration in milliseconds.
- GetDeviceContext(): Contract for obtaining device metadata (model, manufacturer, type, orientation) synchronously.
- DeviceContext: Holds device metadata (model, manufacturer, device type, and display orientation).
- DeviceType: Enumerates broad device categories.
- DisplayOrientation: Enumerates display orientations.
## Dependencies
- No resolved dependencies.
## Calls
- No resolved calls.
## Coverage
- Symbols: 8
- Executable symbols: 4
- Executable symbols with control flow: 4
- Grounded edges: 8
- Unresolved references: 0
- Control-flow fragments: 4
- Unresolved jumps: 0
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 2
- Generated diagrams: 2
## Control Flow Fragments
- VibrateSuccessAsync: 3 nodes, 2 edges, 0 jumps, 0 unsupported constructs
- VibrateErrorAsync: 3 nodes, 2 edges, 0 jumps, 0 unsupported constructs
- VibrateAsync: 4 nodes, 3 edges, 0 jumps, 0 unsupported constructs
- GetDeviceContext: 4 nodes, 3 edges, 0 jumps, 0 unsupported constructs
## Diagrams
### IPlatformService Neighborhood
```mermaid
flowchart LR
class_1gyz12d_iplatformservice("IPlatformService")
file_wb18l0_iplatformservice_cs("IPlatformService")
method_ptkxhj_vibratesuccessasync[["VibrateSuccessAsync()"]]
method_qdnq0x_vibrateerrorasync[["VibrateErrorAsync()"]]
method_sdo0jm_vibrateasync[["VibrateAsync()"]]
method_w31hua_getdevicecontext[["GetDeviceContext()"]]
type_1jksru0_devicetype[/"DeviceType"/]
type_1qhatfu_displayorientation[/"DisplayOrientation"/]
type_flcquz_devicecontext[/"DeviceContext"/]
```
### IPlatformService Execution Overview
```mermaid
flowchart TD
class_1gyz12d_iplatformservice("IPlatformService")
method_ptkxhj_vibratesuccessasync[["VibrateSuccessAsync()"]]
method_qdnq0x_vibrateerrorasync[["VibrateErrorAsync()"]]
method_sdo0jm_vibrateasync[["VibrateAsync()"]]
method_w31hua_getdevicecontext[["GetDeviceContext()"]]
class_1gyz12d_iplatformservice -->|contains| method_ptkxhj_vibratesuccessasync
class_1gyz12d_iplatformservice -->|contains| method_qdnq0x_vibrateerrorasync
class_1gyz12d_iplatformservice -->|contains| method_sdo0jm_vibrateasync
class_1gyz12d_iplatformservice -->|contains| method_w31hua_getdevicecontext
```
## Diagram Validation
- Status: pass
@@ -0,0 +1,108 @@
# VerifyGroundednessCommand
- File ID: file:2eckht:verifygroundednesscommand-cs
- Path: NexusReader.Application/Commands/AI/VerifyGroundednessCommand.cs
- Role: handler
- Layer: application
## Purpose
Defines a MediatR command and its handler that delegates verification of an answer's groundedness to the application's IKnowledgeService.
## Key Details
This file is a thin MediatR command handler that forwards the request to IKnowledgeService.VerifyGroundednessAsync without additional logic or validation. GroundednessResult is returned inside a FluentResults.Result wrapper.
## Symbols
- VerifyGroundednessCommandHandler: Defines a MediatR command and its handler that delegates verification of an answer's groundedness to the application's IKnowledgeService.
- VerifyGroundednessCommandHandler(): Constructor that receives and stores the IKnowledgeService dependency via DI.
- Handle(): Handles the VerifyGroundednessCommand by calling the knowledge service to verify groundedness and returning the service result.
- VerifyGroundednessCommand: Command DTO carrying an answer, context, and tenant id to be verified for groundedness.
## Dependencies
- No resolved dependencies.
## Calls
- No resolved calls.
## Unresolved References
- dependency-target: NexusReader.Application.Abstractions.Services (IKnowledgeService)
- dependency-target: FluentResults (Result<>)
- dependency-target: MediatR (IRequestHandler/IRequest)
- call-target: unknown
- interaction-target: await _knowledgeService.VerifyGroundednessAsync(...) and return its Result<GroundednessResult>
## Coverage
- Symbols: 4
- Executable symbols: 2
- Executable symbols with control flow: 2
- Grounded edges: 4
- Unresolved references: 5
- Control-flow fragments: 2
- Unresolved jumps: 1
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 2
- Generated diagrams: 3
## Control Flow Fragments
- VerifyGroundednessCommandHandler: 3 nodes, 2 edges, 0 jumps, 0 unsupported constructs
- Handle: 7 nodes, 6 edges, 1 jumps, 0 unsupported constructs
## Diagrams
### VerifyGroundednessCommand Neighborhood
```mermaid
flowchart LR
class_109ebx2_verifygroundednesscommandhandler("VerifyGroundednessCommandHandler")
file_2eckht_verifygroundednesscommand_cs("VerifyGroundednessCommand")
method_10jkor8_verifygroundednesscommandhandler[["VerifyGroundednessCommandHandler()"]]
method_1fl6nt2_handle[["Handle()"]]
type_6i8iop_verifygroundednesscommand[/"VerifyGroundednessCommand"/]
```
### VerifyGroundednessCommand Execution Overview
```mermaid
flowchart TD
class_109ebx2_verifygroundednesscommandhandler("VerifyGroundednessCommandHandler")
method_10jkor8_verifygroundednesscommandhandler[["VerifyGroundednessCommandHandler()"]]
method_1fl6nt2_handle[["Handle()"]]
unresolved_unresolved_1d98nmq_interaction_target{"Unresolved: await _knowledgeService.VerifyGroundednessAsync(...) and return its Result<GroundednessResult>"}
unresolved_unresolved_1x6qoip_call_target{"Unresolved: VerifyGroundednessAsync"}
class_109ebx2_verifygroundednesscommandhandler -->|contains| method_10jkor8_verifygroundednesscommandhandler
class_109ebx2_verifygroundednesscommandhandler -->|contains| method_1fl6nt2_handle
class_109ebx2_verifygroundednesscommandhandler -->|unresolved interaction| unresolved_unresolved_1d98nmq_interaction_target
method_1fl6nt2_handle -->|unresolved call| unresolved_unresolved_1x6qoip_call_target
```
### Handle() Control Flow
```mermaid
flowchart TD
method_1fl6nt2_handle__call_20_VerifyGroundednessAsync[["VerifyGroundednessAsync"]]
method_1fl6nt2_handle__action_20_async_return_20__linear("Return result from external service")
method_1fl6nt2_handle__action_20_handle_await_20_0__await[["Waits for async work"]]
method_1fl6nt2_handle__entry(["Handle entry"])
method_1fl6nt2_handle__action_20_external_call_20__linear("Delegate groundedness verification to knowledge service")
method_1fl6nt2_handle__action_20_handle_return_20_1__return(["Returns result"])
method_1fl6nt2_handle__implicit_return(["return"])
method_1fl6nt2_handle__action_20_async_return_20__linear -->|next| method_1fl6nt2_handle__action_20_external_call_20__linear
method_1fl6nt2_handle__action_20_external_call_20__linear -->|request.Answer, request.Context, request.TenantId, cancellationToken| method_1fl6nt2_handle__call_20_VerifyGroundednessAsync
method_1fl6nt2_handle__action_20_handle_await_20_0__await -->|return| method_1fl6nt2_handle__action_20_handle_return_20_1__return
method_1fl6nt2_handle__action_20_handle_return_20_1__return -->|next| method_1fl6nt2_handle__action_20_async_return_20__linear
method_1fl6nt2_handle__call_20_VerifyGroundednessAsync -->|return| method_1fl6nt2_handle__implicit_return
method_1fl6nt2_handle__entry -->|next| method_1fl6nt2_handle__action_20_handle_await_20_0__await
```
## Diagram Validation
- Status: warn
- Warning: Control-flow extraction left 1 unresolved jumps.
@@ -0,0 +1,56 @@
# IngestEbookCommand
- File ID: file:1tk8lz4:ingestebookcommand-cs
- Path: NexusReader.Application/Commands/Library/IngestEbookCommand.cs
- Role: handler
- Layer: application
## Purpose
Defines a CQRS command DTO used to ingest a new ebook into the library, carrying ebook metadata and binary payloads (cover and EPUB) across the application boundary.
## Key Details
Record implements ICommand<Guid>; TenantId defaults to "global" enabling single-tenant default behavior; carries binary payloads (CoverImage and EpubData) so consumers will perform IO/persistence when handling this command.
## Symbols
- IngestEbookCommand: Defines a CQRS command DTO used to ingest a new ebook into the library, carrying ebook metadata and binary payloads (cover and EPUB) across the application boundary.
- IngestEbookCommand: Represents the data required to ingest an ebook (metadata + binary payloads) and is dispatched as a command returning a Guid identifier.
## Dependencies
- No resolved dependencies.
## Calls
- No resolved calls.
## Coverage
- Symbols: 2
- Executable symbols: 0
- Executable symbols with control flow: 0
- Grounded edges: 2
- Unresolved references: 0
- Control-flow fragments: 0
- Unresolved jumps: 0
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 1
- Generated diagrams: 1
## Diagrams
### IngestEbookCommand Neighborhood
```mermaid
flowchart LR
class_byhisx_ingestebookcommand("IngestEbookCommand")
file_1tk8lz4_ingestebookcommand_cs("IngestEbookCommand")
type_dgxlfz_ingestebookcommand[/"IngestEbookCommand"/]
```
## Diagram Validation
- Status: pass
@@ -0,0 +1,202 @@
# IngestEbookCommandHandler
- File ID: file:lqr4h8:ingestebookcommandhandler-cs
- Path: NexusReader.Application/Commands/Library/IngestEbookCommandHandler.cs
- Role: handler
- Layer: application
## Purpose
Handles ingestion of an uploaded ebook: saves files to storage, resolves/creates author, creates Ebook entity and persists it to the repository, returning the new Ebook Id or a failure result.
## Key Details
Two-phase ingestion: first persist files to storage (with I/O error mapping), then create/resolve author and persist Ebook in DB (with DB error mapping). Uses MediatR IRequestHandler and repository/service abstractions to keep side effects encapsulated.
## Symbols
- IngestEbookCommandHandler: Handles ingestion of an uploaded ebook: saves files to storage, resolves/creates author, creates Ebook entity and persists it to the repository, returning the new Ebook Id or a failure result.
- IngestEbookCommandHandler(): Constructor; receives repository and storage service via DI and assigns to fields.
- Handle(): Orchestrates ebook ingestion: saves epub/cover to storage, resolves or creates author, constructs Ebook entity, persists it and returns the created Ebook Id or failure.
## Dependencies
- No resolved dependencies.
## Calls
- No resolved calls.
## Unresolved References
- dependency-target: NexusReader.Application.Abstractions.Persistence/IEbookRepository.cs
- dependency-target: NexusReader.Application.Abstractions.Services/IBookStorageService.cs
- dependency-target: NexusReader.Domain.Entities/Ebook.cs
- dependency-target: NexusReader.Domain.Entities/Author.cs
- call-target: NexusReader.Application.Abstractions.Services/IBookStorageService.cs
- call-target: NexusReader.Application.Abstractions.Services/IBookStorageService.cs
- call-target: NexusReader.Application.Abstractions.Persistence/IEbookRepository.cs
- call-target: NexusReader.Application.Abstractions.Persistence/IEbookRepository.cs
- call-target: NexusReader.Application.Abstractions.Persistence/IEbookRepository.cs
- call-target: NexusReader.Application.Abstractions.Persistence/IEbookRepository.cs
- interaction-target: var author = await _ebookRepository.FindAuthorByNameAsync(authorName, cancellationToken);
- interaction-target: Calls AddEbook and SaveChangesAsync to persist the new entity
## Coverage
- Symbols: 3
- Executable symbols: 2
- Executable symbols with control flow: 2
- Grounded edges: 3
- Unresolved references: 12
- Control-flow fragments: 2
- Unresolved jumps: 6
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 2
- Generated diagrams: 3
## Control Flow Fragments
- IngestEbookCommandHandler: 3 nodes, 2 edges, 0 jumps, 0 unsupported constructs
- Handle: 40 nodes, 42 edges, 6 jumps, 0 unsupported constructs
## Diagrams
### IngestEbookCommandHandler Neighborhood
```mermaid
flowchart LR
class_1kfw737_ingestebookcommandhandler("IngestEbookCommandHandler")
file_lqr4h8_ingestebookcommandhandler_cs("IngestEbookCommandHandler")
method_gy7qh_handle[["Handle()"]]
method_jlw375_ingestebookcommandhandler[["IngestEbookCommandHandler()"]]
```
### IngestEbookCommandHandler Execution Overview
```mermaid
flowchart TD
class_1kfw737_ingestebookcommandhandler("IngestEbookCommandHandler")
method_gy7qh_handle[["Handle()"]]
method_jlw375_ingestebookcommandhandler[["IngestEbookCommandHandler()"]]
unresolved_unresolved_100nowa_interaction_target{"Unresolved: var author = await _ebookRepository.FindAuthorByNameAsync(authorName, cancellationToken);"}
unresolved_unresolved_1foxj00_call_target{"Unresolved: FindAuthorByNameAsync"}
unresolved_unresolved_1hkxnh3_call_target{"Unresolved: SaveEbookAsync"}
unresolved_unresolved_1jnlalo_call_target{"Unresolved: SaveCoverAsync"}
unresolved_unresolved_1o7j1ya_call_target{"Unresolved: AddAuthor"}
unresolved_unresolved_6ikjt_call_target{"Unresolved: AddEbook"}
unresolved_unresolved_syqfv0_call_target{"Unresolved: SaveChangesAsync"}
unresolved_unresolved_yctv9m_interaction_target{"Unresolved: Calls AddEbook and SaveChangesAsync to persist the new entity"}
class_1kfw737_ingestebookcommandhandler -->|contains| method_gy7qh_handle
class_1kfw737_ingestebookcommandhandler -->|contains| method_jlw375_ingestebookcommandhandler
class_1kfw737_ingestebookcommandhandler -->|unresolved interaction| unresolved_unresolved_100nowa_interaction_target
class_1kfw737_ingestebookcommandhandler -->|unresolved interaction| unresolved_unresolved_yctv9m_interaction_target
method_gy7qh_handle -->|unresolved call| unresolved_unresolved_1foxj00_call_target
method_gy7qh_handle -->|unresolved call| unresolved_unresolved_1hkxnh3_call_target
method_gy7qh_handle -->|unresolved call| unresolved_unresolved_1jnlalo_call_target
method_gy7qh_handle -->|unresolved call| unresolved_unresolved_1o7j1ya_call_target
method_gy7qh_handle -->|unresolved call| unresolved_unresolved_6ikjt_call_target
method_gy7qh_handle -->|unresolved call| unresolved_unresolved_syqfv0_call_target
```
### Handle() Control Flow
_Warnings: diagram method_gy7qh_handle__fragment_diagram exceeds preferred complexity thresholds (40 nodes, 42 edges)._
```mermaid
---
config:
flowchart:
defaultRenderer: "elk"
---
flowchart TD
method_gy7qh_handle__call_31_SaveEbookAsync[["SaveEbookAsync"]]
method_gy7qh_handle__call_33_SaveCoverAsync[["SaveCoverAsync"]]
method_gy7qh_handle__call_52_FindAuthorByNameAsync[["FindAuthorByNameAsync"]]
method_gy7qh_handle__call_56_AddAuthor[["AddAuthor"]]
method_gy7qh_handle__call_72_AddEbook[["AddEbook"]]
method_gy7qh_handle__call_73_SaveChangesAsync[["SaveChangesAsync"]]
method_gy7qh_handle__action_28_handle_try_28_0__try("Begins protected execution")
method_gy7qh_handle__action_28_try_catch_28__linear("Storage save with I/O and generic exception handling")
method_gy7qh_handle__action_31_handle_await_31_1__await[["Waits for async work"]]
method_gy7qh_handle__action_32_branch_32__condition{"request.CoverImage != null && request.CoverImage.Length > 0"}
method_gy7qh_handle__action_32_branch_32__false("no cover (coverUrl = null)")
method_gy7qh_handle__action_32_branch_32__merge("merge")
method_gy7qh_handle__action_32_branch_32__true("save cover and set coverUrl")
method_gy7qh_handle__action_33_handle_await_33_2__await[["Waits for async work"]]
method_gy7qh_handle__action_36_handle_catch_36_3__catch("catch IOException ex")
method_gy7qh_handle__action_40_handle_catch_40_5__catch("catch Exception ex")
method_gy7qh_handle__action_45_handle_try_45_7__try("Begins protected execution")
method_gy7qh_handle__action_48_guard_clause_48__condition{"string.IsNullOrWhiteSpace(request.AuthorName)"}
method_gy7qh_handle__action_48_guard_clause_48__false("use trimmed request.AuthorName")
method_gy7qh_handle__action_48_guard_clause_48__merge("merge")
method_gy7qh_handle__action_48_guard_clause_48__true("use 'Unknown Author'")
method_gy7qh_handle__action_52_external_repository_read_52__linear("Find author case-insensitively (via repository)")
method_gy7qh_handle__action_52_handle_await_52_9__await[["Waits for async work"]]
method_gy7qh_handle__action_53_branch_fallback_53__linear("Create missing author")
method_gy7qh_handle__action_53_handle_branch_53_10__condition{"author == null"}
method_gy7qh_handle__action_53_handle_branch_53_10__false("false")
method_gy7qh_handle__action_53_handle_branch_53_10__merge("merge")
method_gy7qh_handle__action_53_handle_branch_53_10__true("true")
method_gy7qh_handle__action_60_entity_construction_60__linear("Construct Ebook entity")
method_gy7qh_handle__action_73_handle_await_73_11__await[["Waits for async work"]]
method_gy7qh_handle__action_77_handle_catch_77_13__catch("catch Exception ex")
method_gy7qh_handle__action_77_try_catch_77__linear("Database error handling during persistence")
method_gy7qh_handle__entry(["Handle entry"])
method_gy7qh_handle__action_52_handle_repository_read_52_8__linear[("Reads repository or persistence state")]
method_gy7qh_handle__action_72_repository_write_72__linear[("Add ebook and persist")]
method_gy7qh_handle__action_38_handle_return_38_4__return(["Returns result"])
method_gy7qh_handle__action_42_handle_return_42_6__return(["Returns result"])
method_gy7qh_handle__action_75_handle_return_75_12__return(["Returns result"])
method_gy7qh_handle__action_75_return_75__return(["Return success with Ebook Id"])
method_gy7qh_handle__action_79_handle_return_79_14__return(["Returns result"])
method_gy7qh_handle__action_28_handle_try_28_0__try -->|next| method_gy7qh_handle__action_31_handle_await_31_1__await
method_gy7qh_handle__action_28_try_catch_28__linear -->|next| method_gy7qh_handle__action_28_handle_try_28_0__try
method_gy7qh_handle__action_31_handle_await_31_1__await -->|request.EpubData, filename = request.Title .epub| method_gy7qh_handle__call_31_SaveEbookAsync
method_gy7qh_handle__action_32_branch_32__condition -->|no cover coverUrl = null| method_gy7qh_handle__action_32_branch_32__false
method_gy7qh_handle__action_32_branch_32__condition -->|save cover and set coverUrl| method_gy7qh_handle__action_32_branch_32__true
method_gy7qh_handle__action_32_branch_32__false -->|next| method_gy7qh_handle__action_32_branch_32__merge
method_gy7qh_handle__action_32_branch_32__merge -->|next| method_gy7qh_handle__action_33_handle_await_33_2__await
method_gy7qh_handle__action_32_branch_32__true -->|next| method_gy7qh_handle__action_32_branch_32__merge
method_gy7qh_handle__action_33_handle_await_33_2__await -->|request.CoverImage, filename = request.Title _cover.jpg called only if CoverImage present| method_gy7qh_handle__call_33_SaveCoverAsync
method_gy7qh_handle__action_36_handle_catch_36_3__catch -->|return| method_gy7qh_handle__action_38_handle_return_38_4__return
method_gy7qh_handle__action_38_handle_return_38_4__return -->|exception| method_gy7qh_handle__action_40_handle_catch_40_5__catch
method_gy7qh_handle__action_40_handle_catch_40_5__catch -->|return| method_gy7qh_handle__action_42_handle_return_42_6__return
method_gy7qh_handle__action_42_handle_return_42_6__return -->|next| method_gy7qh_handle__action_45_handle_try_45_7__try
method_gy7qh_handle__action_45_handle_try_45_7__try -->|next| method_gy7qh_handle__action_48_guard_clause_48__condition
method_gy7qh_handle__action_48_guard_clause_48__condition -->|use trimmed request.AuthorName| method_gy7qh_handle__action_48_guard_clause_48__false
method_gy7qh_handle__action_48_guard_clause_48__condition -->|transforms input| method_gy7qh_handle__action_48_guard_clause_48__true
method_gy7qh_handle__action_48_guard_clause_48__false -->|next| method_gy7qh_handle__action_48_guard_clause_48__merge
method_gy7qh_handle__action_48_guard_clause_48__merge -->|next| method_gy7qh_handle__action_52_handle_await_52_9__await
method_gy7qh_handle__action_48_guard_clause_48__true -->|next| method_gy7qh_handle__action_48_guard_clause_48__merge
method_gy7qh_handle__action_52_external_repository_read_52__linear -->|calls| method_gy7qh_handle__call_52_FindAuthorByNameAsync
method_gy7qh_handle__action_52_handle_await_52_9__await -->|next| method_gy7qh_handle__action_52_handle_repository_read_52_8__linear
method_gy7qh_handle__action_52_handle_repository_read_52_8__linear -->|next| method_gy7qh_handle__action_52_external_repository_read_52__linear
method_gy7qh_handle__action_53_branch_fallback_53__linear -->|new Author Name = authorName when author not found| method_gy7qh_handle__call_56_AddAuthor
method_gy7qh_handle__action_53_handle_branch_53_10__condition -->|false| method_gy7qh_handle__action_53_handle_branch_53_10__false
method_gy7qh_handle__action_53_handle_branch_53_10__condition -->|true| method_gy7qh_handle__action_53_handle_branch_53_10__true
method_gy7qh_handle__action_53_handle_branch_53_10__false -->|next| method_gy7qh_handle__action_53_handle_branch_53_10__merge
method_gy7qh_handle__action_53_handle_branch_53_10__merge -->|next| method_gy7qh_handle__action_53_branch_fallback_53__linear
method_gy7qh_handle__action_53_handle_branch_53_10__true -->|next| method_gy7qh_handle__action_53_handle_branch_53_10__merge
method_gy7qh_handle__action_60_entity_construction_60__linear -->|next| method_gy7qh_handle__action_72_repository_write_72__linear
method_gy7qh_handle__action_72_repository_write_72__linear -->|ebook Ebook entity constructed from request + paths + metadata| method_gy7qh_handle__call_72_AddEbook
method_gy7qh_handle__action_73_handle_await_73_11__await -->|cancellationToken| method_gy7qh_handle__call_73_SaveChangesAsync
method_gy7qh_handle__action_75_handle_return_75_12__return -->|return| method_gy7qh_handle__action_75_return_75__return
method_gy7qh_handle__action_75_return_75__return -->|exception| method_gy7qh_handle__action_77_handle_catch_77_13__catch
method_gy7qh_handle__action_77_handle_catch_77_13__catch -->|next| method_gy7qh_handle__action_77_try_catch_77__linear
method_gy7qh_handle__action_77_try_catch_77__linear -->|return| method_gy7qh_handle__action_79_handle_return_79_14__return
method_gy7qh_handle__call_31_SaveEbookAsync -->|next| method_gy7qh_handle__action_32_branch_32__condition
method_gy7qh_handle__call_33_SaveCoverAsync -->|exception| method_gy7qh_handle__action_36_handle_catch_36_3__catch
method_gy7qh_handle__call_52_FindAuthorByNameAsync -->|next| method_gy7qh_handle__action_53_handle_branch_53_10__condition
method_gy7qh_handle__call_56_AddAuthor -->|next| method_gy7qh_handle__action_60_entity_construction_60__linear
method_gy7qh_handle__call_72_AddEbook -->|next| method_gy7qh_handle__action_73_handle_await_73_11__await
method_gy7qh_handle__call_73_SaveChangesAsync -->|return| method_gy7qh_handle__action_75_handle_return_75_12__return
method_gy7qh_handle__entry -->|next| method_gy7qh_handle__action_28_try_catch_28__linear
```
## Diagram Validation
- Status: warn
- Warning: Control-flow extraction left 6 unresolved jumps.
- Warning: control-flow: diagram method_gy7qh_handle__fragment_diagram exceeds preferred complexity thresholds (40 nodes, 42 edges).
@@ -0,0 +1,54 @@
# IngestEbookRequest
- File ID: file:1qcpa0s:ingestebookrequest-cs
- Path: NexusReader.Application/Commands/Library/IngestEbookRequest.cs
- Role: handler
- Layer: application
## Purpose
Defines a command/DTO that carries data needed to ingest an EPUB ebook into the application (title, author, cover image, base64 epub payload, and optional description).
## Key Details
Simple immutable record used as an application-layer command/DTO; no methods or behavior in this file.
## Symbols
- IngestEbookRequest: Payload/DTO for requesting ingestion of an ebook into the library.
## Dependencies
- No resolved dependencies.
## Calls
- No resolved calls.
## Coverage
- Symbols: 1
- Executable symbols: 0
- Executable symbols with control flow: 0
- Grounded edges: 1
- Unresolved references: 0
- Control-flow fragments: 0
- Unresolved jumps: 0
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 1
- Generated diagrams: 1
## Diagrams
### IngestEbookRequest Neighborhood
```mermaid
flowchart LR
file_1qcpa0s_ingestebookrequest_cs("IngestEbookRequest")
type_1eqmnca_ingestebookrequest[/"IngestEbookRequest"/]
```
## Diagram Validation
- Status: pass
@@ -0,0 +1,60 @@
# SubmitAnswerCommand
- File ID: file:dskay:submitanswercommand-cs
- Path: NexusReader.Application/Commands/Quiz/SubmitAnswerCommand.cs
- Role: handler
- Layer: application
## Purpose
Defines a simple application command that carries a quiz answer selection (selected index and correct index) to be handled by the application's command pipeline.
## Key Details
Minimal DTO/command type used to submit a quiz answer; no methods or behavior in this file beyond the record declaration.
## Symbols
- SubmitAnswerCommand: Defines a simple application command that carries a quiz answer selection (selected index and correct index) to be handled by the application's command pipeline.
- SubmitAnswerCommand: Represents a CQRS command carrying the user's selected answer index and the correct answer index for a quiz question.
## Dependencies
- No resolved dependencies.
## Calls
- No resolved calls.
## Unresolved References
- dependency-target: NexusReader.Application.Abstractions.Messaging
## Coverage
- Symbols: 2
- Executable symbols: 0
- Executable symbols with control flow: 0
- Grounded edges: 2
- Unresolved references: 1
- Control-flow fragments: 0
- Unresolved jumps: 0
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 1
- Generated diagrams: 1
## Diagrams
### SubmitAnswerCommand Neighborhood
```mermaid
flowchart LR
class_cmiilf_submitanswercommand("SubmitAnswerCommand")
file_dskay_submitanswercommand_cs("SubmitAnswerCommand")
type_dvy3sa_submitanswercommand[/"SubmitAnswerCommand"/]
```
## Diagram Validation
- Status: pass
@@ -0,0 +1,120 @@
# SubmitAnswerCommandHandler
- File ID: file:hc4koi:submitanswercommandhandler-cs
- Path: NexusReader.Application/Commands/Quiz/SubmitAnswerCommandHandler.cs
- Role: handler
- Layer: application
## Purpose
Handles quiz answer submission: verifies the selected answer against the correct index, triggers a platform vibration on correct answers, and returns a success/failure Result.
## Key Details
Uses FluentResults.Result for success/failure; relies on IPlatformService for haptic feedback; trivial constructor injects dependency (_platformService at line 9).
## Symbols
- SubmitAnswerCommandHandler: Handles quiz answer submission: verifies the selected answer against the correct index, triggers a platform vibration on correct answers, and returns a success/failure Result.
- Handle(): Checks the submitted answer; vibrates the device and returns success if correct, otherwise returns a failure Result.
## Dependencies
- No resolved dependencies.
## Calls
- No resolved calls.
## Unresolved References
- dependency-target: NexusReader.Application.Abstractions.Services/IPlatformService.cs
- dependency-target: NexusReader.Application.Commands.Quiz/SubmitAnswerCommand.cs
- call-target: NexusReader.Application.Abstractions.Services/IPlatformService.cs
- interaction-target: _platformService.VibrateAsync(50) invoked to provide haptic feedback on correct answer
## Coverage
- Symbols: 2
- Executable symbols: 1
- Executable symbols with control flow: 1
- Grounded edges: 2
- Unresolved references: 4
- Control-flow fragments: 1
- Unresolved jumps: 1
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 2
- Generated diagrams: 3
## Control Flow Fragments
- Handle: 16 nodes, 17 edges, 1 jumps, 0 unsupported constructs
## Diagrams
### SubmitAnswerCommandHandler Neighborhood
```mermaid
flowchart LR
class_andjgd_submitanswercommandhandler("SubmitAnswerCommandHandler")
file_hc4koi_submitanswercommandhandler_cs("SubmitAnswerCommandHandler")
method_e8akyb_handle[["Handle()"]]
```
### SubmitAnswerCommandHandler Execution Overview
```mermaid
flowchart TD
class_andjgd_submitanswercommandhandler("SubmitAnswerCommandHandler")
method_e8akyb_handle[["Handle()"]]
unresolved_unresolved_gdtbd6_call_target{"Unresolved: VibrateAsync"}
unresolved_unresolved_h9q2v9_interaction_target{"Unresolved: _platformService.VibrateAsync(50) invoked to provide haptic feedback on correct answer"}
class_andjgd_submitanswercommandhandler -->|contains| method_e8akyb_handle
class_andjgd_submitanswercommandhandler -->|unresolved interaction| unresolved_unresolved_h9q2v9_interaction_target
method_e8akyb_handle -->|unresolved call| unresolved_unresolved_gdtbd6_call_target
```
### Handle() Control Flow
```mermaid
flowchart TD
method_e8akyb_handle__call_20_VibrateAsync[["VibrateAsync"]]
method_e8akyb_handle__action_18_guard_clause_18__condition{"request.SelectedIndex == request.CorrectIndex"}
method_e8akyb_handle__action_18_guard_clause_18__false("incorrect -> return failure")
method_e8akyb_handle__action_18_guard_clause_18__merge("merge")
method_e8akyb_handle__action_18_guard_clause_18__true("correct -> vibrate and return success")
method_e8akyb_handle__action_18_handle_branch_18_0__condition{"request.SelectedIndex == request.CorrectIndex"}
method_e8akyb_handle__action_18_handle_branch_18_0__false("false")
method_e8akyb_handle__action_18_handle_branch_18_0__merge("merge")
method_e8akyb_handle__action_18_handle_branch_18_0__true("true")
method_e8akyb_handle__action_20_handle_await_20_1__await[["Waits for async work"]]
method_e8akyb_handle__entry(["Handle entry"])
method_e8akyb_handle__action_20_external_call_20__linear("platform vibrate")
method_e8akyb_handle__action_21_handle_return_21_2__return(["Returns result"])
method_e8akyb_handle__action_21_return_21__return(["success-return"])
method_e8akyb_handle__action_24_handle_return_24_3__return(["Returns result"])
method_e8akyb_handle__action_24_return_24__return(["failure-return"])
method_e8akyb_handle__action_18_guard_clause_18__condition -->|incorrect -> return failure| method_e8akyb_handle__action_18_guard_clause_18__false
method_e8akyb_handle__action_18_guard_clause_18__condition -->|correct -> vibrate and return success| method_e8akyb_handle__action_18_guard_clause_18__true
method_e8akyb_handle__action_18_guard_clause_18__false -->|next| method_e8akyb_handle__action_18_guard_clause_18__merge
method_e8akyb_handle__action_18_guard_clause_18__merge -->|next| method_e8akyb_handle__action_20_handle_await_20_1__await
method_e8akyb_handle__action_18_guard_clause_18__true -->|next| method_e8akyb_handle__action_18_guard_clause_18__merge
method_e8akyb_handle__action_18_handle_branch_18_0__condition -->|false| method_e8akyb_handle__action_18_handle_branch_18_0__false
method_e8akyb_handle__action_18_handle_branch_18_0__condition -->|true| method_e8akyb_handle__action_18_handle_branch_18_0__true
method_e8akyb_handle__action_18_handle_branch_18_0__false -->|next| method_e8akyb_handle__action_18_handle_branch_18_0__merge
method_e8akyb_handle__action_18_handle_branch_18_0__merge -->|next| method_e8akyb_handle__action_18_guard_clause_18__condition
method_e8akyb_handle__action_18_handle_branch_18_0__true -->|next| method_e8akyb_handle__action_18_handle_branch_18_0__merge
method_e8akyb_handle__action_20_external_call_20__linear -->|50 int milliseconds| method_e8akyb_handle__call_20_VibrateAsync
method_e8akyb_handle__action_20_handle_await_20_1__await -->|next| method_e8akyb_handle__action_20_external_call_20__linear
method_e8akyb_handle__action_21_handle_return_21_2__return -->|return| method_e8akyb_handle__action_24_handle_return_24_3__return
method_e8akyb_handle__action_21_return_21__return -->|return| method_e8akyb_handle__action_21_handle_return_21_2__return
method_e8akyb_handle__action_24_handle_return_24_3__return -->|return| method_e8akyb_handle__action_24_return_24__return
method_e8akyb_handle__call_20_VibrateAsync -->|return| method_e8akyb_handle__action_21_return_21__return
method_e8akyb_handle__entry -->|next| method_e8akyb_handle__action_18_handle_branch_18_0__condition
```
## Diagram Validation
- Status: warn
- Warning: Control-flow extraction left 1 unresolved jumps.
@@ -0,0 +1,56 @@
# UpdateReadingProgressCommand
- File ID: file:xocicc:updatereadingprogresscommand-cs
- Path: NexusReader.Application/Commands/Sync/UpdateReadingProgressCommand.cs
- Role: handler
- Layer: application
## Purpose
Defines a MediatR command record that carries data for updating a user's reading progress for an ebook (used in sync operations).
## Key Details
Simple immutable record used as a MediatR IRequest<Result> to trigger update logic elsewhere; contains nullable fields for optional metadata and an excluded connection id to avoid echoing updates.
## Symbols
- UpdateReadingProgressCommand: Defines a MediatR command record that carries data for updating a user's reading progress for an ebook (used in sync operations).
- UpdateReadingProgressCommand: Carries parameters required to update a user's reading progress for an ebook in synchronization workflows.
## Dependencies
- No resolved dependencies.
## Calls
- No resolved calls.
## Coverage
- Symbols: 2
- Executable symbols: 0
- Executable symbols with control flow: 0
- Grounded edges: 2
- Unresolved references: 0
- Control-flow fragments: 0
- Unresolved jumps: 0
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 1
- Generated diagrams: 1
## Diagrams
### UpdateReadingProgressCommand Neighborhood
```mermaid
flowchart LR
class_1onwz_updatereadingprogresscommand("UpdateReadingProgressCommand")
file_xocicc_updatereadingprogresscommand_cs("UpdateReadingProgressCommand")
type_lwz5af_updatereadingprogresscommand[/"UpdateReadingProgressCommand"/]
```
## Diagram Validation
- Status: pass
@@ -0,0 +1,200 @@
# UpdateReadingProgressCommandHandler
- File ID: file:13c5eb4:updatereadingprogresscommandhandler-cs
- Path: NexusReader.Application/Commands/Sync/UpdateReadingProgressCommandHandler.cs
- Role: handler
- Layer: application
## Purpose
MediatR handler that persists a user's reading position (User and Ebook entities) and broadcasts the progress update to other connected devices.
## Key Details
Checks for user presence and returns failure if missing; updates user and optionally ebook, saves changes and broadcasts update to other devices while honoring an excluded connection id; cancellationToken is propagated to async DB and broadcaster calls.
## Symbols
- UpdateReadingProgressCommandHandler: MediatR handler that persists a user's reading position (User and Ebook entities) and broadcasts the progress update to other connected devices.
- UpdateReadingProgressCommandHandler(): Constructor: injects the AppDbContext factory and an ISyncBroadcaster.
- Handle(): Load user and ebook, update reading progress and timestamps, persist changes, then broadcast the progress to other devices; returns success or failure if user missing.
- UpdateReadingProgressCommandHandler: MediatR request handler that orchestrates persistence of reading progress and broadcasting updates.
## Dependencies
- No resolved dependencies.
## Calls
- No resolved calls.
## Unresolved References
- dependency-target: NexusReader.Data.Persistence
- dependency-target: NexusReader.Application.Abstractions.Messaging
- call-target: unknown
- call-target: NexusReader.Data.Persistence
- call-target: NexusReader.Data.Persistence
- call-target: NexusReader.Data.Persistence
- call-target: unknown
- interaction-target: var user = await context.Users.FirstOrDefaultAsync(u => u.Id == request.UserId, cancellationToken);
- interaction-target: var ebook = await context.Ebooks.FirstOrDefaultAsync(e => e.Id == request.EbookId, cancellationToken);
- interaction-target: await context.SaveChangesAsync(cancellationToken);
- interaction-target: await _broadcaster.BroadcastProgressAsync(request.UserId, request.PageId, now, request.ExcludedConnectionId, cancellationToken);
## Coverage
- Symbols: 4
- Executable symbols: 2
- Executable symbols with control flow: 2
- Grounded edges: 4
- Unresolved references: 11
- Control-flow fragments: 2
- Unresolved jumps: 5
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 2
- Generated diagrams: 3
## Control Flow Fragments
- UpdateReadingProgressCommandHandler: 3 nodes, 2 edges, 0 jumps, 0 unsupported constructs
- Handle: 37 nodes, 40 edges, 5 jumps, 0 unsupported constructs
## Diagrams
### UpdateReadingProgressCommandHandler Neighborhood
```mermaid
flowchart LR
class_2zm0w9_updatereadingprogresscommandhandler("UpdateReadingProgressCommandHandler")
file_13c5eb4_updatereadingprogresscommandhandler_cs("UpdateReadingProgressCommandHandler")
method_1ed5bhs_updatereadingprogresscommandhandler[["UpdateReadingProgressCommandHandler()"]]
method_1jqlijy_handle[["Handle()"]]
type_1hf0y4h_updatereadingprogresscommandhandler[/"UpdateReadingProgressCommandHandler"/]
```
### UpdateReadingProgressCommandHandler Execution Overview
```mermaid
flowchart TD
class_2zm0w9_updatereadingprogresscommandhandler("UpdateReadingProgressCommandHandler")
method_1ed5bhs_updatereadingprogresscommandhandler[["UpdateReadingProgressCommandHandler()"]]
method_1jqlijy_handle[["Handle()"]]
unresolved_unresolved_167ab0v_call_target{"Unresolved: AppDbContext.Users.FirstOrDefaultAsync"}
unresolved_unresolved_197jdm1_call_target{"Unresolved: IDbContextFactory<AppDbContext>.CreateDbContextAsync"}
unresolved_unresolved_1mfbj3f_interaction_target{"Unresolved: var ebook = await context.Ebooks.FirstOrDefaultAsync(e => e.Id == request.EbookId, cancellationToken);"}
unresolved_unresolved_1n2eft4_interaction_target{"Unresolved: await _broadcaster.BroadcastProgressAsync(request.UserId, request.PageId, now, request.ExcludedConnectionId, cancellationToken);"}
unresolved_unresolved_1rw33m5_call_target{"Unresolved: AppDbContext.SaveChangesAsync"}
unresolved_unresolved_35czhy_interaction_target{"Unresolved: var user = await context.Users.FirstOrDefaultAsync(u => u.Id == request.UserId, cancellationToken);"}
unresolved_unresolved_eld0cu_call_target{"Unresolved: AppDbContext.Ebooks.FirstOrDefaultAsync"}
unresolved_unresolved_jg0l72_call_target{"Unresolved: ISyncBroadcaster.BroadcastProgressAsync"}
unresolved_unresolved_k7dskm_interaction_target{"Unresolved: await context.SaveChangesAsync(cancellationToken);"}
class_2zm0w9_updatereadingprogresscommandhandler -->|contains| method_1ed5bhs_updatereadingprogresscommandhandler
class_2zm0w9_updatereadingprogresscommandhandler -->|contains| method_1jqlijy_handle
class_2zm0w9_updatereadingprogresscommandhandler -->|unresolved interaction| unresolved_unresolved_1mfbj3f_interaction_target
class_2zm0w9_updatereadingprogresscommandhandler -->|unresolved interaction| unresolved_unresolved_1n2eft4_interaction_target
class_2zm0w9_updatereadingprogresscommandhandler -->|unresolved interaction| unresolved_unresolved_35czhy_interaction_target
class_2zm0w9_updatereadingprogresscommandhandler -->|unresolved interaction| unresolved_unresolved_k7dskm_interaction_target
method_1jqlijy_handle -->|unresolved call| unresolved_unresolved_167ab0v_call_target
method_1jqlijy_handle -->|unresolved call| unresolved_unresolved_197jdm1_call_target
method_1jqlijy_handle -->|unresolved call| unresolved_unresolved_1rw33m5_call_target
method_1jqlijy_handle -->|unresolved call| unresolved_unresolved_eld0cu_call_target
method_1jqlijy_handle -->|unresolved call| unresolved_unresolved_jg0l72_call_target
```
### Handle() Control Flow
_Warnings: diagram method_1jqlijy_handle__fragment_diagram exceeds preferred complexity thresholds (37 nodes, 40 edges)._
```mermaid
---
config:
flowchart:
defaultRenderer: "elk"
---
flowchart TD
method_1jqlijy_handle__call_28_IDbContextFactory_AppDbContext_CreateDbContextAsync[["IDbContextFactory<AppDbContext>.CreateDbContextAsync"]]
method_1jqlijy_handle__call_30_AppDbContext_Users_FirstOrDefaultAsync[["AppDbContext.Users.FirstOrDefaultAsync"]]
method_1jqlijy_handle__call_40_AppDbContext_Ebooks_FirstOrDefaultAsync[["AppDbContext.Ebooks.FirstOrDefaultAsync"]]
method_1jqlijy_handle__call_49_AppDbContext_SaveChangesAsync[["AppDbContext.SaveChangesAsync"]]
method_1jqlijy_handle__call_52_ISyncBroadcaster_BroadcastProgressAsync[["ISyncBroadcaster.BroadcastProgressAsync"]]
method_1jqlijy_handle__action_28_handle_await_28_0__await[["Waits for async work"]]
method_1jqlijy_handle__action_28_resource_acquire_28__linear("Create DbContext scope")
method_1jqlijy_handle__action_30_handle_await_30_2__await[["Waits for async work"]]
method_1jqlijy_handle__action_31_guard_clause_31__condition{"user == null"}
method_1jqlijy_handle__action_31_guard_clause_31__false("continue")
method_1jqlijy_handle__action_31_guard_clause_31__merge("merge")
method_1jqlijy_handle__action_31_guard_clause_31__true("return Fail")
method_1jqlijy_handle__action_31_handle_branch_31_3__condition{"user == null"}
method_1jqlijy_handle__action_31_handle_branch_31_3__false("false")
method_1jqlijy_handle__action_31_handle_branch_31_3__merge("merge")
method_1jqlijy_handle__action_31_handle_branch_31_3__true("true")
method_1jqlijy_handle__action_37_field_update_37__linear("Update user reading pointers/timestamps")
method_1jqlijy_handle__action_40_handle_await_40_6__await[["Waits for async work"]]
method_1jqlijy_handle__action_41_branch_41__condition{"ebook != null"}
method_1jqlijy_handle__action_41_branch_41__false("skip")
method_1jqlijy_handle__action_41_branch_41__merge("merge")
method_1jqlijy_handle__action_41_branch_41__true("update ebook fields")
method_1jqlijy_handle__action_41_handle_branch_41_7__condition{"ebook != null"}
method_1jqlijy_handle__action_41_handle_branch_41_7__false("false")
method_1jqlijy_handle__action_41_handle_branch_41_7__merge("merge")
method_1jqlijy_handle__action_41_handle_branch_41_7__true("true")
method_1jqlijy_handle__action_49_handle_await_49_9__await[["Waits for async work"]]
method_1jqlijy_handle__action_49_persist_49__linear("Persist entity changes")
method_1jqlijy_handle__action_52_handle_await_52_10__await[["Waits for async work"]]
method_1jqlijy_handle__entry(["Handle entry"])
method_1jqlijy_handle__action_30_handle_repository_read_30_1__linear[("Reads repository or persistence state")]
method_1jqlijy_handle__action_40_handle_repository_read_40_5__linear[("Reads repository or persistence state")]
method_1jqlijy_handle__action_49_handle_repository_read_49_8__linear[("Reads repository or persistence state")]
method_1jqlijy_handle__action_52_external_call_52__linear("Broadcast progress to other devices")
method_1jqlijy_handle__action_33_handle_return_33_4__return(["Returns result"])
method_1jqlijy_handle__action_59_handle_return_59_11__return(["Returns result"])
method_1jqlijy_handle__action_59_return_59__return(["Return success result"])
method_1jqlijy_handle__action_28_handle_await_28_0__await -->|next| method_1jqlijy_handle__action_28_resource_acquire_28__linear
method_1jqlijy_handle__action_28_resource_acquire_28__linear -->|cancellationToken| method_1jqlijy_handle__call_28_IDbContextFactory_AppDbContext_CreateDbContextAsync
method_1jqlijy_handle__action_30_handle_await_30_2__await -->|next| method_1jqlijy_handle__action_30_handle_repository_read_30_1__linear
method_1jqlijy_handle__action_30_handle_repository_read_30_1__linear -->|predicate u => u.Id == request.UserId, cancellationToken| method_1jqlijy_handle__call_30_AppDbContext_Users_FirstOrDefaultAsync
method_1jqlijy_handle__action_31_guard_clause_31__condition -->|continue| method_1jqlijy_handle__action_31_guard_clause_31__false
method_1jqlijy_handle__action_31_guard_clause_31__condition -->|return Fail| method_1jqlijy_handle__action_31_guard_clause_31__true
method_1jqlijy_handle__action_31_guard_clause_31__false -->|next| method_1jqlijy_handle__action_31_guard_clause_31__merge
method_1jqlijy_handle__action_31_guard_clause_31__merge -->|next| method_1jqlijy_handle__action_31_handle_branch_31_3__condition
method_1jqlijy_handle__action_31_guard_clause_31__true -->|next| method_1jqlijy_handle__action_31_guard_clause_31__merge
method_1jqlijy_handle__action_31_handle_branch_31_3__condition -->|false| method_1jqlijy_handle__action_31_handle_branch_31_3__false
method_1jqlijy_handle__action_31_handle_branch_31_3__condition -->|true| method_1jqlijy_handle__action_31_handle_branch_31_3__true
method_1jqlijy_handle__action_31_handle_branch_31_3__false -->|next| method_1jqlijy_handle__action_31_handle_branch_31_3__merge
method_1jqlijy_handle__action_31_handle_branch_31_3__merge -->|return| method_1jqlijy_handle__action_33_handle_return_33_4__return
method_1jqlijy_handle__action_31_handle_branch_31_3__true -->|next| method_1jqlijy_handle__action_31_handle_branch_31_3__merge
method_1jqlijy_handle__action_33_handle_return_33_4__return -->|next| method_1jqlijy_handle__action_37_field_update_37__linear
method_1jqlijy_handle__action_37_field_update_37__linear -->|next| method_1jqlijy_handle__action_40_handle_await_40_6__await
method_1jqlijy_handle__action_40_handle_await_40_6__await -->|next| method_1jqlijy_handle__action_40_handle_repository_read_40_5__linear
method_1jqlijy_handle__action_40_handle_repository_read_40_5__linear -->|predicate e => e.Id == request.EbookId, cancellationToken| method_1jqlijy_handle__call_40_AppDbContext_Ebooks_FirstOrDefaultAsync
method_1jqlijy_handle__action_41_branch_41__condition -->|skip| method_1jqlijy_handle__action_41_branch_41__false
method_1jqlijy_handle__action_41_branch_41__condition -->|update ebook fields| method_1jqlijy_handle__action_41_branch_41__true
method_1jqlijy_handle__action_41_branch_41__false -->|next| method_1jqlijy_handle__action_41_branch_41__merge
method_1jqlijy_handle__action_41_branch_41__merge -->|next| method_1jqlijy_handle__action_41_handle_branch_41_7__condition
method_1jqlijy_handle__action_41_branch_41__true -->|next| method_1jqlijy_handle__action_41_branch_41__merge
method_1jqlijy_handle__action_41_handle_branch_41_7__condition -->|false| method_1jqlijy_handle__action_41_handle_branch_41_7__false
method_1jqlijy_handle__action_41_handle_branch_41_7__condition -->|true| method_1jqlijy_handle__action_41_handle_branch_41_7__true
method_1jqlijy_handle__action_41_handle_branch_41_7__false -->|next| method_1jqlijy_handle__action_41_handle_branch_41_7__merge
method_1jqlijy_handle__action_41_handle_branch_41_7__merge -->|next| method_1jqlijy_handle__action_49_handle_await_49_9__await
method_1jqlijy_handle__action_41_handle_branch_41_7__true -->|next| method_1jqlijy_handle__action_41_handle_branch_41_7__merge
method_1jqlijy_handle__action_49_handle_await_49_9__await -->|next| method_1jqlijy_handle__action_49_handle_repository_read_49_8__linear
method_1jqlijy_handle__action_49_handle_repository_read_49_8__linear -->|next| method_1jqlijy_handle__action_49_persist_49__linear
method_1jqlijy_handle__action_49_persist_49__linear -->|cancellationToken| method_1jqlijy_handle__call_49_AppDbContext_SaveChangesAsync
method_1jqlijy_handle__action_52_external_call_52__linear -->|request.UserId, request.PageId, now DateTime.UtcNow , request.ExcludedConnectionId, cancellationToken| method_1jqlijy_handle__call_52_ISyncBroadcaster_BroadcastProgressAsync
method_1jqlijy_handle__action_52_handle_await_52_10__await -->|next| method_1jqlijy_handle__action_52_external_call_52__linear
method_1jqlijy_handle__action_59_handle_return_59_11__return -->|return| method_1jqlijy_handle__action_59_return_59__return
method_1jqlijy_handle__call_28_IDbContextFactory_AppDbContext_CreateDbContextAsync -->|next| method_1jqlijy_handle__action_30_handle_await_30_2__await
method_1jqlijy_handle__call_30_AppDbContext_Users_FirstOrDefaultAsync -->|next| method_1jqlijy_handle__action_31_guard_clause_31__condition
method_1jqlijy_handle__call_40_AppDbContext_Ebooks_FirstOrDefaultAsync -->|next| method_1jqlijy_handle__action_41_branch_41__condition
method_1jqlijy_handle__call_49_AppDbContext_SaveChangesAsync -->|next| method_1jqlijy_handle__action_52_handle_await_52_10__await
method_1jqlijy_handle__call_52_ISyncBroadcaster_BroadcastProgressAsync -->|return| method_1jqlijy_handle__action_59_handle_return_59_11__return
method_1jqlijy_handle__entry -->|next| method_1jqlijy_handle__action_28_handle_await_28_0__await
```
## Diagram Validation
- Status: warn
- Warning: Control-flow extraction left 5 unresolved jumps.
- Warning: control-flow: diagram method_1jqlijy_handle__fragment_diagram exceeds preferred complexity thresholds (37 nodes, 40 edges).
@@ -0,0 +1,61 @@
# AppJsonContext
- File ID: file:wxheam:appjsoncontext-cs
- Path: NexusReader.Application/Common/AppJsonContext.cs
- Role: config
- Layer: application
## Purpose
Defines a System.Text.Json source-generated JsonSerializerContext for Graph DTO types used by the application, enabling ahead-of-time serialization metadata and configuration (WriteIndented = true).
## Key Details
Uses [JsonSourceGenerationOptions(WriteIndented = true)] and [JsonSerializable(...)] attributes to register GraphNodeDto, GraphLinkDto, GraphDataDto and their List<> variants for source-generation; class is a partial JsonSerializerContext with no custom members.
## Symbols
- AppJsonContext: Defines a System.Text.Json source-generated JsonSerializerContext for Graph DTO types used by the application, enabling ahead-of-time serialization metadata and configuration (WriteIndented = true).
- AppJsonContext: A source-generated JsonSerializerContext subclass configured to include serialization metadata for Graph DTO types and to emit indented JSON.
## Dependencies
- No resolved dependencies.
## Calls
- No resolved calls.
## Unresolved References
- dependency-target: System.Text.Json.Serialization
- dependency-target: NexusReader.Application.Queries.Graph
## Coverage
- Symbols: 2
- Executable symbols: 0
- Executable symbols with control flow: 0
- Grounded edges: 2
- Unresolved references: 2
- Control-flow fragments: 0
- Unresolved jumps: 0
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 1
- Generated diagrams: 1
## Diagrams
### AppJsonContext Neighborhood
```mermaid
flowchart LR
class_potzj8_appjsoncontext("AppJsonContext")
file_wxheam_appjsoncontext_cs("AppJsonContext")
type_1si295l_appjsoncontext[/"AppJsonContext"/]
```
## Diagram Validation
- Status: pass
@@ -0,0 +1,56 @@
# PlanConstants
- File ID: file:qqutlm:planconstants-cs
- Path: NexusReader.Application/Constants/PlanConstants.cs
- Role: unknown
- Layer: application
## Purpose
Holds application-wide default constants for plan behavior (default plan name, token limit, and activity label).
## Key Details
A small, focused static class providing compile-time constants for default plan behavior; no runtime logic, external calls, or registrations.
## Symbols
- PlanConstants: Holds application-wide default constants for plan behavior (default plan name, token limit, and activity label).
- PlanConstants: Static holder for default plan-related constants used by the application.
## Dependencies
- No resolved dependencies.
## Calls
- No resolved calls.
## Coverage
- Symbols: 2
- Executable symbols: 0
- Executable symbols with control flow: 0
- Grounded edges: 2
- Unresolved references: 0
- Control-flow fragments: 0
- Unresolved jumps: 0
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 1
- Generated diagrams: 1
## Diagrams
### PlanConstants Neighborhood
```mermaid
flowchart LR
class_59bgj0_planconstants("PlanConstants")
file_qqutlm_planconstants_cs("PlanConstants")
type_1l8om0z_planconstants[/"PlanConstants"/]
```
## Diagram Validation
- Status: pass
@@ -0,0 +1,56 @@
# StorageKeys
- File ID: file:g197tx:storagekeys-cs
- Path: NexusReader.Application/Constants/StorageKeys.cs
- Role: config
- Layer: application
## Purpose
Holds string constant keys used for storing authentication and user-related values in client/app storage (e.g., local storage or secure storage).
## Key Details
Simple static class with public const string fields; no runtime behavior, methods, or external calls. Typical usage: shared keys for storage reads/writes across Web, MAUI, or client layers.
## Symbols
- StorageKeys: Holds string constant keys used for storing authentication and user-related values in client/app storage (e.g., local storage or secure storage).
- StorageKeys: Container for storage key constants used throughout the application for persisting auth and user data.
## Dependencies
- No resolved dependencies.
## Calls
- No resolved calls.
## Coverage
- Symbols: 2
- Executable symbols: 0
- Executable symbols with control flow: 0
- Grounded edges: 2
- Unresolved references: 0
- Control-flow fragments: 0
- Unresolved jumps: 0
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 1
- Generated diagrams: 1
## Diagrams
### StorageKeys Neighborhood
```mermaid
flowchart LR
class_1mgndci_storagekeys("StorageKeys")
file_g197tx_storagekeys_cs("StorageKeys")
type_7t3l5d_storagekeys[/"StorageKeys"/]
```
## Diagram Validation
- Status: pass
@@ -0,0 +1,56 @@
# GroundedResponseDto
- File ID: file:1bdy8y4:groundedresponsedto-cs
- Path: NexusReader.Application/DTOs/AI/GroundedResponseDto.cs
- Role: dto
- Layer: application
## Purpose
Defines simple DTOs for AI grounded responses and their citations used across the application boundary.
## Key Details
Simple, immutable-seeming DTOs (with default initializers) meant for transporting AI answers and their provenance; no runtime behavior, external calls, or persistence in this file.
## Symbols
- GroundedResponseDto: Represents a grounded AI answer plus associated citations.
- CitationDto: Represents a single citation/snippet referencing source material supporting an AI response.
## Dependencies
- No resolved dependencies.
## Calls
- No resolved calls.
## Coverage
- Symbols: 2
- Executable symbols: 0
- Executable symbols with control flow: 0
- Grounded edges: 2
- Unresolved references: 0
- Control-flow fragments: 0
- Unresolved jumps: 0
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 1
- Generated diagrams: 1
## Diagrams
### GroundedResponseDto Neighborhood
```mermaid
flowchart LR
file_1bdy8y4_groundedresponsedto_cs("GroundedResponseDto")
type_58td3x_groundedresponsedto[/"GroundedResponseDto"/]
type_h0u00k_citationdto[/"CitationDto"/]
```
## Diagram Validation
- Status: pass
@@ -0,0 +1,68 @@
# KnowledgePacket
- File ID: file:hjtala:knowledgepacket-cs
- Path: NexusReader.Application/DTOs/AI/KnowledgePacket.cs
- Role: dto
- Layer: application
## Purpose
Defines data transfer objects (records) used to represent AI knowledge artifacts (concepts, quiz questions, knowledge units/links, and aggregated knowledge packets) for serialization across the Application layer.
## Key Details
Records are annotated with JsonPropertyName for stable JSON shape; KnowledgePacket composes multiple DTOs and references GraphDataDto from Queries.Graph.
## Symbols
- KnowledgePacket: Defines data transfer objects (records) used to represent AI knowledge artifacts (concepts, quiz questions, knowledge units/links, and aggregated knowledge packets) for serialization across the Application layer.
- KeyConcept: Represents a key concept with a title and description for JSON serialization.
- QuizQuestion: Represents a quiz question with options and the index of the correct answer.
- KnowledgeUnitDto: Represents a single knowledge unit with optional metadata.
- KnowledgeLinkDto: Represents a directed relation/link between two knowledge units.
- KnowledgePacket: Aggregates concepts, quizzes, units, links, optional graph data, and a summary into a single serializable package.
## Dependencies
- No resolved dependencies.
## Calls
- No resolved calls.
## Unresolved References
- dependency-target: NexusReader.Application/Queries/Graph/GraphDataDto.cs
## Coverage
- Symbols: 6
- Executable symbols: 0
- Executable symbols with control flow: 0
- Grounded edges: 6
- Unresolved references: 1
- Control-flow fragments: 0
- Unresolved jumps: 0
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 1
- Generated diagrams: 1
## Diagrams
### KnowledgePacket Neighborhood
```mermaid
flowchart LR
class_1h9lza8_knowledgepacket("KnowledgePacket")
file_hjtala_knowledgepacket_cs("KnowledgePacket")
type_11qfbw_knowledgepacket[/"KnowledgePacket"/]
type_1bqutxs_knowledgeunitdto[/"KnowledgeUnitDto"/]
type_1nt1924_quizquestion[/"QuizQuestion"/]
type_1rne00x_knowledgelinkdto[/"KnowledgeLinkDto"/]
type_uvv2sw_keyconcept[/"KeyConcept"/]
```
## Diagram Validation
- Status: pass
@@ -0,0 +1,56 @@
# RelevantContext
- File ID: file:q380me:relevantcontext-cs
- Path: NexusReader.Application/DTOs/AI/RelevantContext.cs
- Role: dto
- Layer: application
## Purpose
Defines a small data transfer object that carries a piece of text along with its source identifier and a confidence score for AI/processing scenarios.
## Key Details
A minimal DTO in the Application layer with default-initialized string properties and a numeric confidence field; no methods or external dependencies.
## Symbols
- RelevantContext: Defines a small data transfer object that carries a piece of text along with its source identifier and a confidence score for AI/processing scenarios.
- RelevantContext: Represents a piece of relevant textual context with its source identifier and confidence score for AI-related processing.
## Dependencies
- No resolved dependencies.
## Calls
- No resolved calls.
## Coverage
- Symbols: 2
- Executable symbols: 0
- Executable symbols with control flow: 0
- Grounded edges: 2
- Unresolved references: 0
- Control-flow fragments: 0
- Unresolved jumps: 0
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 1
- Generated diagrams: 1
## Diagrams
### RelevantContext Neighborhood
```mermaid
flowchart LR
class_1wekmss_relevantcontext("RelevantContext")
file_q380me_relevantcontext_cs("RelevantContext")
type_hegy2r_relevantcontext[/"RelevantContext"/]
```
## Diagram Validation
- Status: pass
@@ -0,0 +1,56 @@
# SemanticSearchResultDto
- File ID: file:1k69za4:semanticsearchresultdto-cs
- Path: NexusReader.Application/DTOs/AI/SemanticSearchResultDto.cs
- Role: dto
- Layer: application
## Purpose
Defines a simple Data Transfer Object (DTO) representing a semantic search result used by the Application layer to carry search snippet, relevance and metadata.
## Key Details
Simple immutable-shaped DTO (auto-properties) used to transfer semantic search results; no methods or runtime behavior in this file.
## Symbols
- SemanticSearchResultDto: Defines a simple Data Transfer Object (DTO) representing a semantic search result used by the Application layer to carry search snippet, relevance and metadata.
- SemanticSearchResultDto: Carries the result of a semantic search (content hash, snippet, relevance, source and optional metadata).
## Dependencies
- No resolved dependencies.
## Calls
- No resolved calls.
## Coverage
- Symbols: 2
- Executable symbols: 0
- Executable symbols with control flow: 0
- Grounded edges: 2
- Unresolved references: 0
- Control-flow fragments: 0
- Unresolved jumps: 0
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 1
- Generated diagrams: 1
## Diagrams
### SemanticSearchResultDto Neighborhood
```mermaid
flowchart LR
class_1lzvao4_semanticsearchresultdto("SemanticSearchResultDto")
file_1k69za4_semanticsearchresultdto_cs("SemanticSearchResultDto")
type_1qfkwqz_semanticsearchresultdto[/"SemanticSearchResultDto"/]
```
## Diagram Validation
- Status: pass
@@ -0,0 +1,56 @@
# AuthorDto
- File ID: file:e05hy9:authordto-cs
- Path: NexusReader.Application/DTOs/User/AuthorDto.cs
- Role: dto
- Layer: application
## Purpose
Defines an immutable data transfer object (DTO) representing an author with an Id and Name used across the application layer.
## Key Details
Small immutable DTO in the Application layer; no runtime logic, only two properties (Id, Name).
## Symbols
- AuthorDto: Defines an immutable data transfer object (DTO) representing an author with an Id and Name used across the application layer.
- AuthorDto: Carries author identity and display name across application boundaries.
## Dependencies
- No resolved dependencies.
## Calls
- No resolved calls.
## Coverage
- Symbols: 2
- Executable symbols: 0
- Executable symbols with control flow: 0
- Grounded edges: 2
- Unresolved references: 0
- Control-flow fragments: 0
- Unresolved jumps: 0
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 1
- Generated diagrams: 1
## Diagrams
### AuthorDto Neighborhood
```mermaid
flowchart LR
class_z1d2u7_authordto("AuthorDto")
file_e05hy9_authordto_cs("AuthorDto")
type_1m6ptus_authordto[/"AuthorDto"/]
```
## Diagram Validation
- Status: pass
@@ -0,0 +1,56 @@
# SubscriptionPlanDto
- File ID: file:9775p0:subscriptionplandto-cs
- Path: NexusReader.Application/DTOs/User/SubscriptionPlanDto.cs
- Role: dto
- Layer: application
## Purpose
Defines a data-transfer object representing a subscription plan (id, display name, token limits, and monthly price) used across the application layer.
## Key Details
Simple immutable record used as a DTO in the Application layer to represent subscription plan metadata; no runtime behavior (methods) in this file.
## Symbols
- SubscriptionPlanDto: Defines a data-transfer object representing a subscription plan (id, display name, token limits, and monthly price) used across the application layer.
- SubscriptionPlanDto: Carries subscription plan details (id, name, AI token limits, and price) across boundaries.
## Dependencies
- No resolved dependencies.
## Calls
- No resolved calls.
## Coverage
- Symbols: 2
- Executable symbols: 0
- Executable symbols with control flow: 0
- Grounded edges: 2
- Unresolved references: 0
- Control-flow fragments: 0
- Unresolved jumps: 0
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 1
- Generated diagrams: 1
## Diagrams
### SubscriptionPlanDto Neighborhood
```mermaid
flowchart LR
class_1r9yuyl_subscriptionplandto("SubscriptionPlanDto")
file_9775p0_subscriptionplandto_cs("SubscriptionPlanDto")
type_2f6m0y_subscriptionplandto[/"SubscriptionPlanDto"/]
```
## Diagram Validation
- Status: pass
@@ -0,0 +1,64 @@
# UserProfileDto
- File ID: file:1fs0p2c:userprofiledto-cs
- Path: NexusReader.Application/DTOs/User/UserProfileDto.cs
- Role: dto
- Layer: application
## Purpose
Defines DTOs for returning user profile and last-read book information across the application boundary (UI/API), including helper computed properties for UI compatibility.
## Key Details
Pure DTO definitions with computed helper properties for UI compatibility; no runtime logic, branches, or external calls in this file.
## Symbols
- UserProfileDto: Defines DTOs for returning user profile and last-read book information across the application boundary (UI/API), including helper computed properties for UI compatibility.
- UserProfileDto: Represents a user's profile information, subscription plan, roles, recent activity and UI-friendly computed properties.
- LastReadBookDto: Carries a compact summary of the last book the user was reading, for display in UI and profile pages.
## Dependencies
- No resolved dependencies.
## Calls
- No resolved calls.
## Unresolved References
- dependency-target: NexusReader.Application.Constants.PlanConstants (referenced)
- dependency-target: SubscriptionPlanDto (referenced, external file)
- dependency-target: AuthorDto (referenced, external file)
## Coverage
- Symbols: 3
- Executable symbols: 0
- Executable symbols with control flow: 0
- Grounded edges: 3
- Unresolved references: 3
- Control-flow fragments: 0
- Unresolved jumps: 0
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 1
- Generated diagrams: 1
## Diagrams
### UserProfileDto Neighborhood
```mermaid
flowchart LR
class_vgmc9n_userprofiledto("UserProfileDto")
file_1fs0p2c_userprofiledto_cs("UserProfileDto")
type_1g1re12_lastreadbookdto[/"LastReadBookDto"/]
type_wh8ieq_userprofiledto[/"UserProfileDto"/]
```
## Diagram Validation
- Status: pass
@@ -0,0 +1,99 @@
# DependencyInjection
- File ID: file:qieb5i:dependencyinjection-cs
- Path: NexusReader.Application/DependencyInjection.cs
- Role: service-registration
- Layer: application
## Purpose
Provides Application-layer dependency registrations (mappings, MediatR) and exposes the assembly for registration discovery.
## Key Details
This static helper centralizes Application-layer DI registration: it wires mapping configuration and asks MediatR to register handlers from the assembly exposed by the Assembly property.
## Symbols
- DependencyInjection: Provides Application-layer dependency registrations (mappings, MediatR) and exposes the assembly for registration discovery.
- AddApplication(): Extension method that registers application-layer services: Mapster mapping configuration and MediatR handlers, then returns the IServiceCollection.
- Assembly (property getter): Exposes the assembly containing the DependencyInjection type for registration/discovery.
## Dependencies
- No resolved dependencies.
## Calls
- No resolved calls.
## Unresolved References
- dependency-target: NexusReader.Application/Mappings
- call-target: NexusReader.Application/Mappings
## Coverage
- Symbols: 3
- Executable symbols: 2
- Executable symbols with control flow: 2
- Grounded edges: 3
- Unresolved references: 2
- Control-flow fragments: 2
- Unresolved jumps: 1
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 2
- Generated diagrams: 3
## Control Flow Fragments
- AddApplication: 6 nodes, 5 edges, 1 jumps, 0 unsupported constructs
- Assembly (property getter): 2 nodes, 1 edges, 0 jumps, 0 unsupported constructs
## Diagrams
### DependencyInjection Neighborhood
```mermaid
flowchart LR
class_5jkcay_dependencyinjection("DependencyInjection")
file_qieb5i_dependencyinjection_cs("DependencyInjection")
method_lhrad4_assembly_property_getter[["Assembly (property getter)"]]
method_zf4i3h_addapplication[["AddApplication()"]]
```
### DependencyInjection Execution Overview
```mermaid
flowchart TD
class_5jkcay_dependencyinjection("DependencyInjection")
method_lhrad4_assembly_property_getter[["Assembly (property getter)"]]
method_zf4i3h_addapplication[["AddApplication()"]]
unresolved_unresolved_1oo5v1s_call_target{"Unresolved: AddMapsterConfiguration"}
class_5jkcay_dependencyinjection -->|contains| method_lhrad4_assembly_property_getter
class_5jkcay_dependencyinjection -->|contains| method_zf4i3h_addapplication
method_zf4i3h_addapplication -->|unresolved call| unresolved_unresolved_1oo5v1s_call_target
```
### AddApplication() Control Flow
```mermaid
flowchart TD
method_zf4i3h_addapplication__call_10_AddMapsterConfiguration[["AddMapsterConfiguration"]]
method_zf4i3h_addapplication__action_10_service_registration_10__linear("Adds Mapster configuration to DI")
method_zf4i3h_addapplication__action_11_service_registration_11__linear("Registers MediatR and handlers from this assembly")
method_zf4i3h_addapplication__entry(["AddApplication entry"])
method_zf4i3h_addapplication__action_13_addapplication_return_13_0__return(["Returns result"])
method_zf4i3h_addapplication__action_13_return_13__return(["Returns IServiceCollection"])
method_zf4i3h_addapplication__action_10_service_registration_10__linear -->|this IServiceCollection extension call to add mapping configuration| method_zf4i3h_addapplication__call_10_AddMapsterConfiguration
method_zf4i3h_addapplication__action_11_service_registration_11__linear -->|return| method_zf4i3h_addapplication__action_13_addapplication_return_13_0__return
method_zf4i3h_addapplication__action_13_addapplication_return_13_0__return -->|return| method_zf4i3h_addapplication__action_13_return_13__return
method_zf4i3h_addapplication__call_10_AddMapsterConfiguration -->|next| method_zf4i3h_addapplication__action_11_service_registration_11__linear
method_zf4i3h_addapplication__entry -->|next| method_zf4i3h_addapplication__action_10_service_registration_10__linear
```
## Diagram Validation
- Status: warn
- Warning: Control-flow extraction left 1 unresolved jumps.
@@ -0,0 +1,77 @@
# MappingConfig
- File ID: file:w6cklc:mappingconfig-cs
- Path: NexusReader.Application/Mappings/MappingConfig.cs
- Role: service-registration
- Layer: application
## Purpose
Defines an IServiceCollection extension to configure Mapster mappings and register mapping services (TypeAdapterConfig and IMapper) into the application's DI container.
## Key Details
Extension method intended to be called during application startup to wire Mapster mappings and mapper into IServiceCollection; no branching, retries, or persistence logic present.
## Symbols
- MappingConfig: Defines an IServiceCollection extension to configure Mapster mappings and register mapping services (TypeAdapterConfig and IMapper) into the application's DI container.
- AddMapsterConfiguration(): Creates Mapster TypeAdapterConfig mappings and registers the config and IMapper in the DI container, returning the IServiceCollection for chaining.
## Dependencies
- No resolved dependencies.
## Calls
- No resolved calls.
## Unresolved References
- dependency-target: NexusReader.Domain/Entities (NexusUser, Ebook referenced)
- dependency-target: NexusReader.Application/DTOs/User (UserProfileDto, LastReadBookDto referenced)
- interaction-target: var config = TypeAdapterConfig.GlobalSettings (Mapster library global settings accessed)
## Coverage
- Symbols: 2
- Executable symbols: 1
- Executable symbols with control flow: 1
- Grounded edges: 2
- Unresolved references: 3
- Control-flow fragments: 1
- Unresolved jumps: 0
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 2
- Generated diagrams: 2
## Control Flow Fragments
- AddMapsterConfiguration: 9 nodes, 8 edges, 0 jumps, 0 unsupported constructs
## Diagrams
### MappingConfig Neighborhood
```mermaid
flowchart LR
class_1lmiwem_mappingconfig("MappingConfig")
file_w6cklc_mappingconfig_cs("MappingConfig")
method_14hjndb_addmapsterconfiguration[["AddMapsterConfiguration()"]]
```
### MappingConfig Execution Overview
```mermaid
flowchart TD
class_1lmiwem_mappingconfig("MappingConfig")
method_14hjndb_addmapsterconfiguration[["AddMapsterConfiguration()"]]
unresolved_unresolved_132t2nb_interaction_target{"Unresolved: var config = TypeAdapterConfig.GlobalSettings (Mapster library global settings accessed)"}
class_1lmiwem_mappingconfig -->|contains| method_14hjndb_addmapsterconfiguration
class_1lmiwem_mappingconfig -->|unresolved interaction| unresolved_unresolved_132t2nb_interaction_target
```
## Diagram Validation
- Status: pass
@@ -0,0 +1,68 @@
# NexusReader.Application
- File ID: file:mpxmz7:nexusreader-application-csproj
- Path: NexusReader.Application/NexusReader.Application.csproj
- Role: config
- Layer: application
## Purpose
MSBuild project file for the NexusReader.Application assembly; it declares project dependencies and NuGet package dependencies that define the Application layer's runtime capabilities and boundaries.
## Key Details
Targets net10.0 (line 22), enables implicit usings and nullable (lines 23-24), generates runtime configuration files (line 25). Project references to Domain and Data define boundaries; packages indicate MediatR-based orchestration, Mapster mapping, EF Core persistence, Pgvector for vector storage, and Microsoft.Extensions.AI for AI integrations.
## Symbols
- No extracted symbols.
## Dependencies
- No resolved dependencies.
## Calls
- No resolved calls.
## Unresolved References
- dependency-target: ../NexusReader.Domain/NexusReader.Domain.csproj
- dependency-target: ../NexusReader.Data/NexusReader.Data.csproj
- dependency-target: FluentResults (NuGet)
- dependency-target: Mapster (NuGet)
- dependency-target: Mapster.DependencyInjection (NuGet)
- dependency-target: MediatR (NuGet)
- dependency-target: Microsoft.AspNetCore.Authorization (NuGet)
- dependency-target: Microsoft.EntityFrameworkCore (NuGet)
- dependency-target: Microsoft.Extensions.AI (NuGet)
- dependency-target: Microsoft.Extensions.Identity.Core (NuGet)
- dependency-target: Pgvector.EntityFrameworkCore (NuGet)
- dependency-target: Microsoft.Extensions.Resilience (NuGet)
## Coverage
- Symbols: 0
- Executable symbols: 0
- Executable symbols with control flow: 0
- Grounded edges: 0
- Unresolved references: 12
- Control-flow fragments: 0
- Unresolved jumps: 0
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 1
- Generated diagrams: 1
## Diagrams
### NexusReader.Application Neighborhood
```mermaid
flowchart LR
file_mpxmz7_nexusreader_application_csproj("NexusReader.Application")
```
## Diagram Validation
- Status: pass
@@ -0,0 +1,61 @@
# GetKnowledgeGraphQuery
- File ID: file:10kr3oo:getknowledgegraphquery-cs
- Path: NexusReader.Application/Queries/Graph/GetKnowledgeGraphQuery.cs
- Role: handler
- Layer: application
## Purpose
Defines a CQRS query record used to request a knowledge graph extraction from provided text within a tenant scope and optional ebook context.
## Key Details
Simple immutable record used as a query DTO; no runtime logic in this file. Implements IQuery<GraphDataDto> and carries three parameters (Text, TenantId, optional EbookId).
## Symbols
- GetKnowledgeGraphQuery: Defines a CQRS query record used to request a knowledge graph extraction from provided text within a tenant scope and optional ebook context.
- GetKnowledgeGraphQuery: Represents a request to produce a GraphDataDto from input text for a given tenant and optional ebook.
## Dependencies
- No resolved dependencies.
## Calls
- No resolved calls.
## Unresolved References
- dependency-target: NexusReader.Application.Abstractions.Messaging (IQuery)
- dependency-target: GraphDataDto (output type)
## Coverage
- Symbols: 2
- Executable symbols: 0
- Executable symbols with control flow: 0
- Grounded edges: 2
- Unresolved references: 2
- Control-flow fragments: 0
- Unresolved jumps: 0
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 1
- Generated diagrams: 1
## Diagrams
### GetKnowledgeGraphQuery Neighborhood
```mermaid
flowchart LR
class_1qgqpgy_getknowledgegraphquery("GetKnowledgeGraphQuery")
file_10kr3oo_getknowledgegraphquery_cs("GetKnowledgeGraphQuery")
type_je3vog_getknowledgegraphquery[/"GetKnowledgeGraphQuery"/]
```
## Diagram Validation
- Status: pass
@@ -0,0 +1,155 @@
# GetKnowledgeGraphQueryHandler
- File ID: file:16f33jo:getknowledgegraphqueryhandler-cs
- Path: NexusReader.Application/Queries/Graph/GetKnowledgeGraphQueryHandler.cs
- Role: handler
- Layer: application
## Purpose
Handles GetKnowledgeGraphQuery by validating input, calling the knowledge service to retrieve graph data, and returning a GraphDataDto wrapped in a FluentResults Result.
## Key Details
Core runtime path: guard for empty input -> call knowledge service -> if service fails propagate failure -> if service returns null graph return empty GraphDataDto; uses FluentResults for result wrapping.
## Symbols
- GetKnowledgeGraphQueryHandler: Handles GetKnowledgeGraphQuery by validating input, calling the knowledge service to retrieve graph data, and returning a GraphDataDto wrapped in a FluentResults Result.
- GetKnowledgeGraphQueryHandler(): Constructor that injects the IKnowledgeService dependency.
- Handle(): Validates the query text, calls IKnowledgeService.GetGraphDataAsync to obtain graph data, and returns appropriate Result<GraphDataDto> (empty, failed, or the graph).
## Dependencies
- No resolved dependencies.
## Calls
- No resolved calls.
## Unresolved References
- dependency-target: NexusReader.Application.Abstractions.Messaging (IQueryHandler)
- dependency-target: NexusReader.Application.Abstractions.Services (IKnowledgeService)
- call-target: unknown
- interaction-target: await _knowledgeService.GetGraphDataAsync(...)
## Coverage
- Symbols: 3
- Executable symbols: 2
- Executable symbols with control flow: 2
- Grounded edges: 3
- Unresolved references: 4
- Control-flow fragments: 2
- Unresolved jumps: 1
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 2
- Generated diagrams: 3
## Control Flow Fragments
- GetKnowledgeGraphQueryHandler: 3 nodes, 2 edges, 0 jumps, 0 unsupported constructs
- Handle: 26 nodes, 29 edges, 1 jumps, 0 unsupported constructs
## Diagrams
### GetKnowledgeGraphQueryHandler Neighborhood
```mermaid
flowchart LR
class_p0no6_getknowledgegraphqueryhandler("GetKnowledgeGraphQueryHandler")
file_16f33jo_getknowledgegraphqueryhandler_cs("GetKnowledgeGraphQueryHandler")
method_rci0sa_getknowledgegraphqueryhandler[["GetKnowledgeGraphQueryHandler()"]]
method_tgg1x1_handle[["Handle()"]]
```
### GetKnowledgeGraphQueryHandler Execution Overview
```mermaid
flowchart TD
class_p0no6_getknowledgegraphqueryhandler("GetKnowledgeGraphQueryHandler")
method_rci0sa_getknowledgegraphqueryhandler[["GetKnowledgeGraphQueryHandler()"]]
method_tgg1x1_handle[["Handle()"]]
unresolved_unresolved_180ldv3_interaction_target{"Unresolved: await _knowledgeService.GetGraphDataAsync(...)"}
unresolved_unresolved_i84gum_call_target{"Unresolved: GetGraphDataAsync"}
class_p0no6_getknowledgegraphqueryhandler -->|contains| method_rci0sa_getknowledgegraphqueryhandler
class_p0no6_getknowledgegraphqueryhandler -->|contains| method_tgg1x1_handle
class_p0no6_getknowledgegraphqueryhandler -->|unresolved interaction| unresolved_unresolved_180ldv3_interaction_target
method_tgg1x1_handle -->|unresolved call| unresolved_unresolved_i84gum_call_target
```
### Handle() Control Flow
_Warnings: diagram method_tgg1x1_handle__fragment_diagram exceeds preferred complexity thresholds (26 nodes, 29 edges)._
```mermaid
---
config:
flowchart:
defaultRenderer: "elk"
---
flowchart TD
method_tgg1x1_handle__call_21_GetGraphDataAsync[["GetGraphDataAsync"]]
method_tgg1x1_handle__action_18_guard_clause_18__condition{"string.IsNullOrWhiteSpace(request.Text)"}
method_tgg1x1_handle__action_18_guard_clause_18__false("continue")
method_tgg1x1_handle__action_18_guard_clause_18__merge("merge")
method_tgg1x1_handle__action_18_guard_clause_18__true("return empty GraphDataDto")
method_tgg1x1_handle__action_18_handle_branch_18_0__condition{"string.IsNullOrWhiteSpace(request.Text)"}
method_tgg1x1_handle__action_18_handle_branch_18_0__false("false")
method_tgg1x1_handle__action_18_handle_branch_18_0__merge("merge")
method_tgg1x1_handle__action_18_handle_branch_18_0__true("true")
method_tgg1x1_handle__action_21_handle_await_21_2__await[["Waits for async work"]]
method_tgg1x1_handle__action_27_branch_27__condition{"result.IsFailed"}
method_tgg1x1_handle__action_27_branch_27__false("continue")
method_tgg1x1_handle__action_27_branch_27__merge("merge")
method_tgg1x1_handle__action_27_branch_27__true("return failure Result<GraphDataDto>")
method_tgg1x1_handle__action_27_handle_branch_27_3__condition{"result.IsFailed"}
method_tgg1x1_handle__action_27_handle_branch_27_3__false("false")
method_tgg1x1_handle__action_27_handle_branch_27_3__merge("merge")
method_tgg1x1_handle__action_27_handle_branch_27_3__true("true")
method_tgg1x1_handle__action_30_assignment_30__linear("Extract graph from service result")
method_tgg1x1_handle__action_32_null_check_32__linear("Return empty DTO if graph is null")
method_tgg1x1_handle__entry(["Handle entry"])
method_tgg1x1_handle__action_21_external_call_21__linear("Fetch graph data")
method_tgg1x1_handle__action_19_handle_return_19_1__return(["Returns result"])
method_tgg1x1_handle__action_28_handle_return_28_4__return(["Returns result"])
method_tgg1x1_handle__action_32_handle_return_32_5__return(["Returns result"])
method_tgg1x1_handle__implicit_return(["return"])
method_tgg1x1_handle__action_18_guard_clause_18__condition -->|continue| method_tgg1x1_handle__action_18_guard_clause_18__false
method_tgg1x1_handle__action_18_guard_clause_18__condition -->|return empty GraphDataDto| method_tgg1x1_handle__action_18_guard_clause_18__true
method_tgg1x1_handle__action_18_guard_clause_18__false -->|next| method_tgg1x1_handle__action_18_guard_clause_18__merge
method_tgg1x1_handle__action_18_guard_clause_18__merge -->|return| method_tgg1x1_handle__action_19_handle_return_19_1__return
method_tgg1x1_handle__action_18_guard_clause_18__true -->|next| method_tgg1x1_handle__action_18_guard_clause_18__merge
method_tgg1x1_handle__action_18_handle_branch_18_0__condition -->|false| method_tgg1x1_handle__action_18_handle_branch_18_0__false
method_tgg1x1_handle__action_18_handle_branch_18_0__condition -->|true| method_tgg1x1_handle__action_18_handle_branch_18_0__true
method_tgg1x1_handle__action_18_handle_branch_18_0__false -->|next| method_tgg1x1_handle__action_18_handle_branch_18_0__merge
method_tgg1x1_handle__action_18_handle_branch_18_0__merge -->|next| method_tgg1x1_handle__action_18_guard_clause_18__condition
method_tgg1x1_handle__action_18_handle_branch_18_0__true -->|next| method_tgg1x1_handle__action_18_handle_branch_18_0__merge
method_tgg1x1_handle__action_19_handle_return_19_1__return -->|next| method_tgg1x1_handle__action_21_handle_await_21_2__await
method_tgg1x1_handle__action_21_external_call_21__linear -->|request.Text, request.TenantId, ebookId: request.EbookId, cancellationToken: cancellationToken| method_tgg1x1_handle__call_21_GetGraphDataAsync
method_tgg1x1_handle__action_21_handle_await_21_2__await -->|next| method_tgg1x1_handle__action_21_external_call_21__linear
method_tgg1x1_handle__action_27_branch_27__condition -->|continue| method_tgg1x1_handle__action_27_branch_27__false
method_tgg1x1_handle__action_27_branch_27__condition -->|return failure Result GraphDataDto>| method_tgg1x1_handle__action_27_branch_27__true
method_tgg1x1_handle__action_27_branch_27__false -->|next| method_tgg1x1_handle__action_27_branch_27__merge
method_tgg1x1_handle__action_27_branch_27__merge -->|next| method_tgg1x1_handle__action_27_handle_branch_27_3__condition
method_tgg1x1_handle__action_27_branch_27__true -->|next| method_tgg1x1_handle__action_27_branch_27__merge
method_tgg1x1_handle__action_27_handle_branch_27_3__condition -->|false| method_tgg1x1_handle__action_27_handle_branch_27_3__false
method_tgg1x1_handle__action_27_handle_branch_27_3__condition -->|true| method_tgg1x1_handle__action_27_handle_branch_27_3__true
method_tgg1x1_handle__action_27_handle_branch_27_3__false -->|next| method_tgg1x1_handle__action_27_handle_branch_27_3__merge
method_tgg1x1_handle__action_27_handle_branch_27_3__merge -->|return| method_tgg1x1_handle__action_28_handle_return_28_4__return
method_tgg1x1_handle__action_27_handle_branch_27_3__true -->|next| method_tgg1x1_handle__action_27_handle_branch_27_3__merge
method_tgg1x1_handle__action_28_handle_return_28_4__return -->|next| method_tgg1x1_handle__action_30_assignment_30__linear
method_tgg1x1_handle__action_30_assignment_30__linear -->|return| method_tgg1x1_handle__action_32_handle_return_32_5__return
method_tgg1x1_handle__action_32_handle_return_32_5__return -->|next| method_tgg1x1_handle__action_32_null_check_32__linear
method_tgg1x1_handle__action_32_null_check_32__linear -->|return| method_tgg1x1_handle__implicit_return
method_tgg1x1_handle__call_21_GetGraphDataAsync -->|next| method_tgg1x1_handle__action_27_branch_27__condition
method_tgg1x1_handle__entry -->|next| method_tgg1x1_handle__action_18_handle_branch_18_0__condition
```
## Diagram Validation
- Status: warn
- Warning: Control-flow extraction left 1 unresolved jumps.
- Warning: control-flow: diagram method_tgg1x1_handle__fragment_diagram exceeds preferred complexity thresholds (26 nodes, 29 edges).
@@ -0,0 +1,58 @@
# GraphViewModels
- File ID: file:1c4q2p1:graphviewmodels-cs
- Path: NexusReader.Application/Queries/Graph/GraphViewModels.cs
- Role: dto
- Layer: application
## Purpose
Defines lightweight Graph view-model/DTO types used by application queries to represent nodes, links, and the aggregated graph data for UI or API consumption.
## Key Details
File solely defines immutable records for graph transfer; no runtime logic, external calls, or registrations present.
## Symbols
- GraphNodeDto: Represents a single graph node with an identifier, label, grouping, and optional type metadata.
- GraphLinkDto: Represents an edge/link between two nodes with a relation type and a numeric value/weight.
- GraphDataDto: Container for an in-memory graph payload: lists of nodes and links prepared for queries or UI rendering.
## Dependencies
- No resolved dependencies.
## Calls
- No resolved calls.
## Coverage
- Symbols: 3
- Executable symbols: 0
- Executable symbols with control flow: 0
- Grounded edges: 3
- Unresolved references: 0
- Control-flow fragments: 0
- Unresolved jumps: 0
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 1
- Generated diagrams: 1
## Diagrams
### GraphViewModels Neighborhood
```mermaid
flowchart LR
file_1c4q2p1_graphviewmodels_cs("GraphViewModels")
type_4tuqh6_graphlinkdto[/"GraphLinkDto"/]
type_5sl01j_graphnodedto[/"GraphNodeDto"/]
type_g75yh_graphdatadto[/"GraphDataDto"/]
```
## Diagram Validation
- Status: pass
@@ -0,0 +1,129 @@
# AskLibraryQuestionQuery
- File ID: file:xxwh7p:asklibraryquestionquery-cs
- Path: NexusReader.Application/Queries/Library/AskLibraryQuestionQuery.cs
- Role: handler
- Layer: application
## Purpose
Defines a MediatR query (AskLibraryQuestionQuery) and its handler which validates input and delegates question answering to an IKnowledgeService, returning a GroundedResponseDto result.
## Key Details
Handler enforces non-empty question, otherwise immediately fails; otherwise delegates to IKnowledgeService.AskQuestionAsync and returns that result.
## Symbols
- AskLibraryQuestionQueryHandler: Defines a MediatR query (AskLibraryQuestionQuery) and its handler which validates input and delegates question answering to an IKnowledgeService, returning a GroundedResponseDto result.
- AskLibraryQuestionQueryHandler(): Constructs the handler and captures the injected IKnowledgeService.
- Handle(): Validates the incoming question and forwards it to the knowledge service to obtain a grounded AI response.
- AskLibraryQuestionQuery: Represents a request to ask a question against the tenant's library (optionally scoped to an ebook) with a result limit.
- AskLibraryQuestionQueryHandler: MediatR request handler that orchestrates validation and calls the knowledge service.
## Dependencies
- No resolved dependencies.
## Calls
- No resolved calls.
## Unresolved References
- dependency-target: NexusReader.Application.Abstractions.Services
- dependency-target: NexusReader.Application.DTOs.AI
- dependency-target: MediatR
- dependency-target: FluentResults
- call-target: unknown
- interaction-target: Returns result of _knowledgeService.AskQuestionAsync(...)
## Coverage
- Symbols: 5
- Executable symbols: 2
- Executable symbols with control flow: 2
- Grounded edges: 5
- Unresolved references: 6
- Control-flow fragments: 2
- Unresolved jumps: 1
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 2
- Generated diagrams: 3
## Control Flow Fragments
- AskLibraryQuestionQueryHandler: 3 nodes, 2 edges, 0 jumps, 0 unsupported constructs
- Handle: 15 nodes, 16 edges, 1 jumps, 0 unsupported constructs
## Diagrams
### AskLibraryQuestionQuery Neighborhood
```mermaid
flowchart LR
class_1n4pq65_asklibraryquestionqueryhandler("AskLibraryQuestionQueryHandler")
file_xxwh7p_asklibraryquestionquery_cs("AskLibraryQuestionQuery")
method_17jlxw0_handle[["Handle()"]]
method_r0ndyk_asklibraryquestionqueryhandler[["AskLibraryQuestionQueryHandler()"]]
type_bzkzmt_asklibraryquestionquery[/"AskLibraryQuestionQuery"/]
type_s4lsqg_asklibraryquestionqueryhandler[/"AskLibraryQuestionQueryHandler"/]
```
### AskLibraryQuestionQuery Execution Overview
```mermaid
flowchart TD
class_1n4pq65_asklibraryquestionqueryhandler("AskLibraryQuestionQueryHandler")
method_17jlxw0_handle[["Handle()"]]
method_r0ndyk_asklibraryquestionqueryhandler[["AskLibraryQuestionQueryHandler()"]]
unresolved_unresolved_13z2o11_interaction_target{"Unresolved: Returns result of _knowledgeService.AskQuestionAsync(...)"}
unresolved_unresolved_19u8vwm_call_target{"Unresolved: AskQuestionAsync"}
class_1n4pq65_asklibraryquestionqueryhandler -->|contains| method_17jlxw0_handle
class_1n4pq65_asklibraryquestionqueryhandler -->|contains| method_r0ndyk_asklibraryquestionqueryhandler
class_1n4pq65_asklibraryquestionqueryhandler -->|unresolved interaction| unresolved_unresolved_13z2o11_interaction_target
method_17jlxw0_handle -->|unresolved call| unresolved_unresolved_19u8vwm_call_target
```
### Handle() Control Flow
```mermaid
flowchart TD
method_17jlxw0_handle__call_30_AskQuestionAsync[["AskQuestionAsync"]]
method_17jlxw0_handle__action_25_guard_clause_25__condition{"string.IsNullOrWhiteSpace(request.Question)"}
method_17jlxw0_handle__action_25_guard_clause_25__false("continue")
method_17jlxw0_handle__action_25_guard_clause_25__merge("merge")
method_17jlxw0_handle__action_25_guard_clause_25__true("invalid")
method_17jlxw0_handle__action_25_handle_branch_25_0__condition{"string.IsNullOrWhiteSpace(request.Question)"}
method_17jlxw0_handle__action_25_handle_branch_25_0__false("false")
method_17jlxw0_handle__action_25_handle_branch_25_0__merge("merge")
method_17jlxw0_handle__action_25_handle_branch_25_0__true("true")
method_17jlxw0_handle__action_30_handle_await_30_2__await[["Waits for async work"]]
method_17jlxw0_handle__entry(["Handle entry"])
method_17jlxw0_handle__action_30_external_call_30__linear("Delegate to knowledge service")
method_17jlxw0_handle__action_27_handle_return_27_1__return(["Returns result"])
method_17jlxw0_handle__action_30_handle_return_30_3__return(["Returns result"])
method_17jlxw0_handle__action_35_return_35__return(["Return service result"])
method_17jlxw0_handle__action_25_guard_clause_25__condition -->|continue| method_17jlxw0_handle__action_25_guard_clause_25__false
method_17jlxw0_handle__action_25_guard_clause_25__condition -->|invalid| method_17jlxw0_handle__action_25_guard_clause_25__true
method_17jlxw0_handle__action_25_guard_clause_25__false -->|next| method_17jlxw0_handle__action_25_guard_clause_25__merge
method_17jlxw0_handle__action_25_guard_clause_25__merge -->|next| method_17jlxw0_handle__action_25_handle_branch_25_0__condition
method_17jlxw0_handle__action_25_guard_clause_25__true -->|next| method_17jlxw0_handle__action_25_guard_clause_25__merge
method_17jlxw0_handle__action_25_handle_branch_25_0__condition -->|false| method_17jlxw0_handle__action_25_handle_branch_25_0__false
method_17jlxw0_handle__action_25_handle_branch_25_0__condition -->|true| method_17jlxw0_handle__action_25_handle_branch_25_0__true
method_17jlxw0_handle__action_25_handle_branch_25_0__false -->|next| method_17jlxw0_handle__action_25_handle_branch_25_0__merge
method_17jlxw0_handle__action_25_handle_branch_25_0__merge -->|return| method_17jlxw0_handle__action_27_handle_return_27_1__return
method_17jlxw0_handle__action_25_handle_branch_25_0__true -->|next| method_17jlxw0_handle__action_25_handle_branch_25_0__merge
method_17jlxw0_handle__action_27_handle_return_27_1__return -->|next| method_17jlxw0_handle__action_30_handle_await_30_2__await
method_17jlxw0_handle__action_30_external_call_30__linear -->|request.Question, request.TenantId, request.EbookId, request.Limit, cancellationToken| method_17jlxw0_handle__call_30_AskQuestionAsync
method_17jlxw0_handle__action_30_handle_await_30_2__await -->|return| method_17jlxw0_handle__action_30_handle_return_30_3__return
method_17jlxw0_handle__action_30_handle_return_30_3__return -->|next| method_17jlxw0_handle__action_30_external_call_30__linear
method_17jlxw0_handle__call_30_AskQuestionAsync -->|return| method_17jlxw0_handle__action_35_return_35__return
method_17jlxw0_handle__entry -->|next| method_17jlxw0_handle__action_25_guard_clause_25__condition
```
## Diagram Validation
- Status: warn
- Warning: Control-flow extraction left 1 unresolved jumps.
@@ -0,0 +1,90 @@
# GetMyEbooksQuery
- File ID: file:16axv5i:getmyebooksquery-cs
- Path: NexusReader.Application/Queries/Library/GetMyEbooksQuery.cs
- Role: handler
- Layer: application
## Purpose
MediatR query and handler that reads the current user's ebooks from the AppDbContext, projects them into LastReadBookDto instances, and returns them wrapped in a FluentResults Result.
## Key Details
Performs a single DB query projecting entities to LastReadBookDto; uses IDbContextFactory for DbContext creation and returns a FluentResults Result wrapping the list.
## Symbols
- GetMyEbooksQueryHandler: MediatR query and handler that reads the current user's ebooks from the AppDbContext, projects them into LastReadBookDto instances, and returns them wrapped in a FluentResults Result.
- Handle(): Opens a DbContext, queries ebooks for the given user id, projects results to LastReadBookDto list, and returns Result.Ok(list).
- GetMyEbooksQueryHandler (ctor): Stores injected IDbContextFactory<AppDbContext> to a readonly field.
- GetMyEbooksQuery: MediatR request holding the UserId for which ebooks should be fetched.
## Dependencies
- No resolved dependencies.
## Calls
- No resolved calls.
## Unresolved References
- dependency-target: NexusReader.Application.DTOs.User
- dependency-target: NexusReader.Data.Persistence
- dependency-target: FluentResults
- dependency-target: MediatR
- dependency-target: Microsoft.EntityFrameworkCore
- interaction-target: .Where(e => e.UserId == request.UserId)
- interaction-target: ToListAsync(cancellationToken) - EF Core async materialization
## Coverage
- Symbols: 4
- Executable symbols: 2
- Executable symbols with control flow: 2
- Grounded edges: 4
- Unresolved references: 7
- Control-flow fragments: 2
- Unresolved jumps: 0
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 2
- Generated diagrams: 2
## Control Flow Fragments
- Handle: 12 nodes, 11 edges, 0 jumps, 0 unsupported constructs
- GetMyEbooksQueryHandler (ctor): 3 nodes, 2 edges, 0 jumps, 0 unsupported constructs
## Diagrams
### GetMyEbooksQuery Neighborhood
```mermaid
flowchart LR
class_1far2m1_getmyebooksqueryhandler("GetMyEbooksQueryHandler")
file_16axv5i_getmyebooksquery_cs("GetMyEbooksQuery")
method_1epuq0y_handle[["Handle()"]]
method_527vme_getmyebooksqueryhandler_ctor[["GetMyEbooksQueryHandler (ctor)"]]
type_y84j0y_getmyebooksquery[/"GetMyEbooksQuery"/]
```
### GetMyEbooksQuery Execution Overview
```mermaid
flowchart TD
class_1far2m1_getmyebooksqueryhandler("GetMyEbooksQueryHandler")
method_1epuq0y_handle[["Handle()"]]
method_527vme_getmyebooksqueryhandler_ctor[["GetMyEbooksQueryHandler (ctor)"]]
unresolved_unresolved_wfw9je_interaction_target{"Unresolved: ToListAsync(cancellationToken) - EF Core async materialization"}
unresolved_unresolved_x17hvs_interaction_target{"Unresolved: .Where(e => e.UserId == request.UserId)"}
class_1far2m1_getmyebooksqueryhandler -->|contains| method_1epuq0y_handle
class_1far2m1_getmyebooksqueryhandler -->|contains| method_527vme_getmyebooksqueryhandler_ctor
class_1far2m1_getmyebooksqueryhandler -->|unresolved interaction| unresolved_unresolved_wfw9je_interaction_target
class_1far2m1_getmyebooksqueryhandler -->|unresolved interaction| unresolved_unresolved_x17hvs_interaction_target
```
## Diagram Validation
- Status: pass
@@ -0,0 +1,196 @@
# SearchLibrarySemanticallyQuery
- File ID: file:qbybjm:searchlibrarysemanticallyquery-cs
- Path: NexusReader.Application/Queries/Library/SearchLibrarySemanticallyQuery.cs
- Role: handler
- Layer: application
## Purpose
Provides a MediatR query and handler that performs a semantic search over a tenant-scoped semantic knowledge cache: it generates an embedding for the input query (with retry), runs a vector similarity DB query, maps results to DTOs, and returns them.
## Key Details
Uses a resilience pipeline named "ai-retry" to wrap embedding generation, computes cosine distance using Pgvector and orders DB results by similarity, then maps entities to SemanticSearchResultDto and returns a FluentResults.Result.
## Symbols
- SearchLibrarySemanticallyQueryHandler: Provides a MediatR query and handler that performs a semantic search over a tenant-scoped semantic knowledge cache: it generates an embedding for the input query (with retry), runs a vector similarity DB query, maps results to DTOs, and returns them.
- SearchLibrarySemanticallyQueryHandler(): Constructor that stores injected services and obtains a named resilience pipeline for retries.
- Handle(): Executes a semantic search: validates input, obtains an embedding with retry, queries the DB for nearest cached vectors for the tenant, maps to DTOs and returns a Result.
- SearchLibrarySemanticallyQuery: CQRS request record carrying query text, tenant id and optional limit for semantic search.
- SearchLibrarySemanticallyQueryHandler: MediatR handler that orchestrates embedding generation, resilient execution, DB similarity query and mapping to DTOs.
## Dependencies
- No resolved dependencies.
## Calls
- No resolved calls.
## Unresolved References
- dependency-target: NexusReader.Data.Persistence (imported at line 15)
- dependency-target: Mapster/MapsterMapper (imported at lines 12-13)
- dependency-target: MediatR (imported line 2)
- dependency-target: Pgvector (imported lines 3-4)
- dependency-target: Microsoft.Extensions.Resilience / Polly (lines 9-11)
- call-target: unknown
- call-target: unknown
- call-target: unknown
- call-target: unknown
- call-target: unknown
- interaction-target: .Where(c => c.TenantId == request.TenantId && c.Embedding != null)
- interaction-target: pipelineProvider.GetPipeline("ai-retry") used to set _retryPipeline
- interaction-target: _embeddingGenerator.GenerateAsync called with request.QueryText
## Coverage
- Symbols: 5
- Executable symbols: 2
- Executable symbols with control flow: 2
- Grounded edges: 5
- Unresolved references: 13
- Control-flow fragments: 2
- Unresolved jumps: 5
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 2
- Generated diagrams: 4
## Control Flow Fragments
- SearchLibrarySemanticallyQueryHandler: 5 nodes, 4 edges, 1 jumps, 0 unsupported constructs
- Handle: 27 nodes, 29 edges, 4 jumps, 0 unsupported constructs
## Diagrams
### SearchLibrarySemanticallyQuery Neighborhood
```mermaid
flowchart LR
class_1x3939l_searchlibrarysemanticallyqueryhandler("SearchLibrarySemanticallyQueryHandler")
file_qbybjm_searchlibrarysemanticallyquery_cs("SearchLibrarySemanticallyQuery")
method_17jd9c8_searchlibrarysemanticallyqueryhandler[["SearchLibrarySemanticallyQueryHandler()"]]
method_1bus1hn_handle[["Handle()"]]
type_165f8vd_searchlibrarysemanticallyqueryhandler[/"SearchLibrarySemanticallyQueryHandler"/]
type_17161bt_searchlibrarysemanticallyquery[/"SearchLibrarySemanticallyQuery"/]
```
### SearchLibrarySemanticallyQuery Execution Overview
```mermaid
flowchart TD
class_1x3939l_searchlibrarysemanticallyqueryhandler("SearchLibrarySemanticallyQueryHandler")
method_17jd9c8_searchlibrarysemanticallyqueryhandler[["SearchLibrarySemanticallyQueryHandler()"]]
method_1bus1hn_handle[["Handle()"]]
unresolved_unresolved_1gdzso6_interaction_target{"Unresolved: _embeddingGenerator.GenerateAsync called with request.QueryText"}
unresolved_unresolved_1nh5es3_call_target{"Unresolved: GetPipeline"}
unresolved_unresolved_1oqa70v_call_target{"Unresolved: CreateDbContextAsync"}
unresolved_unresolved_1ubjsmz_interaction_target{"Unresolved: pipelineProvider.GetPipeline(\\"ai-retry\\") used to set _retryPipeline"}
unresolved_unresolved_1ywu2kl_call_target{"Unresolved: ExecuteAsync"}
unresolved_unresolved_2r3zjw_interaction_target{"Unresolved: .Where(c => c.TenantId == request.TenantId && c.Embedding != null)"}
unresolved_unresolved_8t3u5h_call_target{"Unresolved: GenerateAsync"}
unresolved_unresolved_rglo3u_call_target{"Unresolved: Map"}
class_1x3939l_searchlibrarysemanticallyqueryhandler -->|contains| method_17jd9c8_searchlibrarysemanticallyqueryhandler
class_1x3939l_searchlibrarysemanticallyqueryhandler -->|contains| method_1bus1hn_handle
class_1x3939l_searchlibrarysemanticallyqueryhandler -->|unresolved interaction| unresolved_unresolved_1gdzso6_interaction_target
class_1x3939l_searchlibrarysemanticallyqueryhandler -->|unresolved interaction| unresolved_unresolved_1ubjsmz_interaction_target
class_1x3939l_searchlibrarysemanticallyqueryhandler -->|unresolved interaction| unresolved_unresolved_2r3zjw_interaction_target
method_17jd9c8_searchlibrarysemanticallyqueryhandler -->|unresolved call| unresolved_unresolved_1nh5es3_call_target
method_1bus1hn_handle -->|unresolved call| unresolved_unresolved_1oqa70v_call_target
method_1bus1hn_handle -->|unresolved call| unresolved_unresolved_1ywu2kl_call_target
method_1bus1hn_handle -->|unresolved call| unresolved_unresolved_8t3u5h_call_target
method_1bus1hn_handle -->|unresolved call| unresolved_unresolved_rglo3u_call_target
```
### SearchLibrarySemanticallyQueryHandler() Control Flow
```mermaid
flowchart TD
method_17jd9c8_searchlibrarysemanticallyqueryhandler__call_37_GetPipeline[["GetPipeline"]]
method_17jd9c8_searchlibrarysemanticallyqueryhandler__action_35_field_assignment_35__linear("Assigns injected dependencies")
method_17jd9c8_searchlibrarysemanticallyqueryhandler__entry(["SearchLibrarySemanticallyQueryHandler entry"])
method_17jd9c8_searchlibrarysemanticallyqueryhandler__action_37_external_call_37__linear("Resilience pipeline lookup")
method_17jd9c8_searchlibrarysemanticallyqueryhandler__implicit_return(["return"])
method_17jd9c8_searchlibrarysemanticallyqueryhandler__action_35_field_assignment_35__linear -->|next| method_17jd9c8_searchlibrarysemanticallyqueryhandler__action_37_external_call_37__linear
method_17jd9c8_searchlibrarysemanticallyqueryhandler__action_37_external_call_37__linear -->|string ai-retry| method_17jd9c8_searchlibrarysemanticallyqueryhandler__call_37_GetPipeline
method_17jd9c8_searchlibrarysemanticallyqueryhandler__call_37_GetPipeline -->|return| method_17jd9c8_searchlibrarysemanticallyqueryhandler__implicit_return
method_17jd9c8_searchlibrarysemanticallyqueryhandler__entry -->|next| method_17jd9c8_searchlibrarysemanticallyqueryhandler__action_35_field_assignment_35__linear
```
### Handle() Control Flow
_Warnings: diagram method_1bus1hn_handle__fragment_diagram exceeds preferred complexity thresholds (27 nodes, 29 edges)._
```mermaid
---
config:
flowchart:
defaultRenderer: "elk"
---
flowchart TD
method_1bus1hn_handle__call_49_ExecuteAsync[["ExecuteAsync"]]
method_1bus1hn_handle__call_50_GenerateAsync[["GenerateAsync"]]
method_1bus1hn_handle__call_53_CreateDbContextAsync[["CreateDbContextAsync"]]
method_1bus1hn_handle__call_60_Map[["Map"]]
method_1bus1hn_handle__action_43_guard_clause_43__condition{"string.IsNullOrWhiteSpace(request.QueryText)"}
method_1bus1hn_handle__action_43_guard_clause_43__false("continue")
method_1bus1hn_handle__action_43_guard_clause_43__merge("merge")
method_1bus1hn_handle__action_43_guard_clause_43__true("invalid")
method_1bus1hn_handle__action_43_handle_branch_43_0__condition{"string.IsNullOrWhiteSpace(request.QueryText)"}
method_1bus1hn_handle__action_43_handle_branch_43_0__false("false")
method_1bus1hn_handle__action_43_handle_branch_43_0__merge("merge")
method_1bus1hn_handle__action_43_handle_branch_43_0__true("true")
method_1bus1hn_handle__action_49_handle_await_49_2__await[["Waits for async work"]]
method_1bus1hn_handle__action_49_retry_49__loop_body[["_retryPipeline.ExecuteAsync wraps _embeddingGenerator.GenerateAsync to obtain embedding"]]
method_1bus1hn_handle__action_49_retry_49__loop_entry("Generate embedding with resilience pipeline")
method_1bus1hn_handle__action_49_retry_49__loop_exit("exit loop")
method_1bus1hn_handle__action_50_handle_await_50_3__await[["Waits for async work"]]
method_1bus1hn_handle__action_53_handle_await_53_4__await[["Waits for async work"]]
method_1bus1hn_handle__action_54_handle_await_54_5__await[["Waits for async work"]]
method_1bus1hn_handle__action_54_persistence_read_54__linear("Query SemanticKnowledgeCache for tenant and compute cosine distance")
method_1bus1hn_handle__action_60_mapping_60__linear("Map entities to DTOs")
method_1bus1hn_handle__entry(["Handle entry"])
method_1bus1hn_handle__action_50_external_call_50__linear("Embedding generation")
method_1bus1hn_handle__action_55_handle_repository_read_55_6__linear[("Reads repository or persistence state")]
method_1bus1hn_handle__action_45_handle_return_45_1__return(["Returns result"])
method_1bus1hn_handle__action_61_handle_return_61_7__return(["Returns result"])
method_1bus1hn_handle__action_61_return_61__return(["Return successful Result with mapped DTOs"])
method_1bus1hn_handle__action_43_guard_clause_43__condition -->|continue| method_1bus1hn_handle__action_43_guard_clause_43__false
method_1bus1hn_handle__action_43_guard_clause_43__condition -->|invalid| method_1bus1hn_handle__action_43_guard_clause_43__true
method_1bus1hn_handle__action_43_guard_clause_43__false -->|next| method_1bus1hn_handle__action_43_guard_clause_43__merge
method_1bus1hn_handle__action_43_guard_clause_43__merge -->|next| method_1bus1hn_handle__action_43_handle_branch_43_0__condition
method_1bus1hn_handle__action_43_guard_clause_43__true -->|next| method_1bus1hn_handle__action_43_guard_clause_43__merge
method_1bus1hn_handle__action_43_handle_branch_43_0__condition -->|false| method_1bus1hn_handle__action_43_handle_branch_43_0__false
method_1bus1hn_handle__action_43_handle_branch_43_0__condition -->|true| method_1bus1hn_handle__action_43_handle_branch_43_0__true
method_1bus1hn_handle__action_43_handle_branch_43_0__false -->|next| method_1bus1hn_handle__action_43_handle_branch_43_0__merge
method_1bus1hn_handle__action_43_handle_branch_43_0__merge -->|return| method_1bus1hn_handle__action_45_handle_return_45_1__return
method_1bus1hn_handle__action_43_handle_branch_43_0__true -->|next| method_1bus1hn_handle__action_43_handle_branch_43_0__merge
method_1bus1hn_handle__action_45_handle_return_45_1__return -->|next| method_1bus1hn_handle__action_49_handle_await_49_2__await
method_1bus1hn_handle__action_49_handle_await_49_2__await -->|next| method_1bus1hn_handle__action_49_retry_49__loop_entry
method_1bus1hn_handle__action_49_retry_49__loop_body -->|retry| method_1bus1hn_handle__action_49_retry_49__loop_entry
method_1bus1hn_handle__action_49_retry_49__loop_entry -->|iterate| method_1bus1hn_handle__action_49_retry_49__loop_body
method_1bus1hn_handle__action_49_retry_49__loop_entry -->|exit| method_1bus1hn_handle__action_49_retry_49__loop_exit
method_1bus1hn_handle__action_49_retry_49__loop_exit -->|Func CancellationToken, Task Embedding >> that calls _embeddingGenerator.GenerateAsync| method_1bus1hn_handle__call_49_ExecuteAsync
method_1bus1hn_handle__action_50_external_call_50__linear -->|string request.QueryText cancellation token forwarded| method_1bus1hn_handle__call_50_GenerateAsync
method_1bus1hn_handle__action_50_handle_await_50_3__await -->|next| method_1bus1hn_handle__action_50_external_call_50__linear
method_1bus1hn_handle__action_53_handle_await_53_4__await -->|cancellationToken| method_1bus1hn_handle__call_53_CreateDbContextAsync
method_1bus1hn_handle__action_54_handle_await_54_5__await -->|next| method_1bus1hn_handle__action_54_persistence_read_54__linear
method_1bus1hn_handle__action_54_persistence_read_54__linear -->|next| method_1bus1hn_handle__action_55_handle_repository_read_55_6__linear
method_1bus1hn_handle__action_55_handle_repository_read_55_6__linear -->|next| method_1bus1hn_handle__action_60_mapping_60__linear
method_1bus1hn_handle__action_60_mapping_60__linear -->|List SemanticKnowledgeCache> -> List SemanticSearchResultDto>| method_1bus1hn_handle__call_60_Map
method_1bus1hn_handle__action_61_handle_return_61_7__return -->|return| method_1bus1hn_handle__action_61_return_61__return
method_1bus1hn_handle__call_49_ExecuteAsync -->|next| method_1bus1hn_handle__action_50_handle_await_50_3__await
method_1bus1hn_handle__call_50_GenerateAsync -->|next| method_1bus1hn_handle__action_53_handle_await_53_4__await
method_1bus1hn_handle__call_53_CreateDbContextAsync -->|next| method_1bus1hn_handle__action_54_handle_await_54_5__await
method_1bus1hn_handle__call_60_Map -->|return| method_1bus1hn_handle__action_61_handle_return_61_7__return
method_1bus1hn_handle__entry -->|next| method_1bus1hn_handle__action_43_guard_clause_43__condition
```
## Diagram Validation
- Status: warn
- Warning: Control-flow extraction left 5 unresolved jumps.
- Warning: control-flow: diagram method_1bus1hn_handle__fragment_diagram exceeds preferred complexity thresholds (27 nodes, 29 edges).
@@ -0,0 +1,56 @@
# QuizViewModels
- File ID: file:uhcd4x:quizviewmodels-cs
- Path: NexusReader.Application/Queries/Quiz/QuizViewModels.cs
- Role: dto
- Layer: application
## Purpose
Defines simple immutable view-model DTOs for quiz query responses (questions and quiz payload).
## Key Details
Two positional C# record DTOs only; no methods, logic, external calls, or persistence in this file.
## Symbols
- QuizQuestionDto: Represents a single quiz question with its options and the index of the correct option.
- QuizDto: Encapsulates a collection of quiz questions as the payload for quiz-related queries/responses.
## Dependencies
- No resolved dependencies.
## Calls
- No resolved calls.
## Coverage
- Symbols: 2
- Executable symbols: 0
- Executable symbols with control flow: 0
- Grounded edges: 2
- Unresolved references: 0
- Control-flow fragments: 0
- Unresolved jumps: 0
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 1
- Generated diagrams: 1
## Diagrams
### QuizViewModels Neighborhood
```mermaid
flowchart LR
file_uhcd4x_quizviewmodels_cs("QuizViewModels")
type_1mrj3g3_quizdto[/"QuizDto"/]
type_5b8im_quizquestiondto[/"QuizQuestionDto"/]
```
## Diagram Validation
- Status: pass
@@ -0,0 +1,60 @@
# GetReaderPageQuery
- File ID: file:9lh011:getreaderpagequery-cs
- Path: NexusReader.Application/Queries/Reader/GetReaderPageQuery.cs
- Role: handler
- Layer: application
## Purpose
Defines a CQRS query record used to request a specific ebook chapter (reader page) for a given user/tenant, returning a ReaderPageViewModel.
## Key Details
Simple immutable record implementing IQuery<ReaderPageViewModel>; carries ebook id, chapter index (default 0), and optional user id for tenant-scoped read operations.
## Symbols
- GetReaderPageQuery: Defines a CQRS query record used to request a specific ebook chapter (reader page) for a given user/tenant, returning a ReaderPageViewModel.
- GetReaderPageQuery: Represents a request to retrieve a specific chapter (page) of a user's ebook, used in the application's query pipeline.
## Dependencies
- No resolved dependencies.
## Calls
- No resolved calls.
## Unresolved References
- dependency-target: NexusReader.Application.Abstractions.Messaging (IQuery<ReaderPageViewModel>)
## Coverage
- Symbols: 2
- Executable symbols: 0
- Executable symbols with control flow: 0
- Grounded edges: 2
- Unresolved references: 1
- Control-flow fragments: 0
- Unresolved jumps: 0
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 1
- Generated diagrams: 1
## Diagrams
### GetReaderPageQuery Neighborhood
```mermaid
flowchart LR
class_z6s0dl_getreaderpagequery("GetReaderPageQuery")
file_9lh011_getreaderpagequery_cs("GetReaderPageQuery")
type_a2sfsr_getreaderpagequery[/"GetReaderPageQuery"/]
```
## Diagram Validation
- Status: pass
@@ -0,0 +1,101 @@
# GetReaderPageQueryHandler
- File ID: file:y077jr:getreaderpagequeryhandler-cs
- Path: NexusReader.Application/Queries/Reader/GetReaderPageQueryHandler.cs
- Role: handler
- Layer: application
## Purpose
Query handler that responds to GetReaderPageQuery by delegating to an IEpubReader to fetch a ReaderPageViewModel for a given ebook/chapter and user.
## Key Details
Very thin handler: no validation, mapping, retries, or logging — it simply delegates to IEpubReader.GetEpubContentAsync and returns its Result<Task<ReaderPageViewModel>>.
## Symbols
- GetReaderPageQueryHandler: Query handler that responds to GetReaderPageQuery by delegating to an IEpubReader to fetch a ReaderPageViewModel for a given ebook/chapter and user.
- Handle(): Handles GetReaderPageQuery by calling the epub reader to fetch the requested page content and returns the Result-wrapped ReaderPageViewModel.
- GetReaderPageQueryHandler: Internal query handler class that coordinates fetching reader page content via IEpubReader.
## Dependencies
- No resolved dependencies.
## Calls
- No resolved calls.
## Unresolved References
- dependency-target: NexusReader.Application.Abstractions.Messaging
- dependency-target: NexusReader.Application.Abstractions.Services
- dependency-target: FluentResults
- call-target: unknown
- interaction-target: _epubReader.GetEpubContentAsync(request.EbookId, request.ChapterIndex, request.UserId, cancellationToken)
## Coverage
- Symbols: 3
- Executable symbols: 1
- Executable symbols with control flow: 1
- Grounded edges: 3
- Unresolved references: 5
- Control-flow fragments: 1
- Unresolved jumps: 1
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 2
- Generated diagrams: 3
## Control Flow Fragments
- Handle: 6 nodes, 5 edges, 1 jumps, 0 unsupported constructs
## Diagrams
### GetReaderPageQueryHandler Neighborhood
```mermaid
flowchart LR
class_1lgm7qp_getreaderpagequeryhandler("GetReaderPageQueryHandler")
file_y077jr_getreaderpagequeryhandler_cs("GetReaderPageQueryHandler")
method_1al0hre_handle[["Handle()"]]
type_4pvcwi_getreaderpagequeryhandler[/"GetReaderPageQueryHandler"/]
```
### GetReaderPageQueryHandler Execution Overview
```mermaid
flowchart TD
class_1lgm7qp_getreaderpagequeryhandler("GetReaderPageQueryHandler")
method_1al0hre_handle[["Handle()"]]
unresolved_unresolved_7zd42w_call_target{"Unresolved: GetEpubContentAsync"}
unresolved_unresolved_nzxkp1_interaction_target{"Unresolved: _epubReader.GetEpubContentAsync(request.EbookId, request.ChapterIndex, request.UserId, cancellationToken)"}
class_1lgm7qp_getreaderpagequeryhandler -->|contains| method_1al0hre_handle
class_1lgm7qp_getreaderpagequeryhandler -->|unresolved interaction| unresolved_unresolved_nzxkp1_interaction_target
method_1al0hre_handle -->|unresolved call| unresolved_unresolved_7zd42w_call_target
```
### Handle() Control Flow
```mermaid
flowchart TD
method_1al0hre_handle__call_18_GetEpubContentAsync[["GetEpubContentAsync"]]
method_1al0hre_handle__entry(["Handle entry"])
method_1al0hre_handle__action_18_external_call_18__linear("Delegate to epub reader")
method_1al0hre_handle__action_18_handle_return_18_0__return(["Returns result"])
method_1al0hre_handle__action_18_return_18__return(["Return epub reader result"])
method_1al0hre_handle__implicit_return(["return"])
method_1al0hre_handle__action_18_external_call_18__linear -->|request.EbookId, request.ChapterIndex, request.UserId, cancellationToken| method_1al0hre_handle__call_18_GetEpubContentAsync
method_1al0hre_handle__action_18_handle_return_18_0__return -->|return| method_1al0hre_handle__action_18_return_18__return
method_1al0hre_handle__action_18_return_18__return -->|next| method_1al0hre_handle__action_18_external_call_18__linear
method_1al0hre_handle__call_18_GetEpubContentAsync -->|return| method_1al0hre_handle__implicit_return
method_1al0hre_handle__entry -->|return| method_1al0hre_handle__action_18_handle_return_18_0__return
```
## Diagram Validation
- Status: warn
- Warning: Control-flow extraction left 1 unresolved jumps.
@@ -0,0 +1,56 @@
# LocalEpubMetadata
- File ID: file:485hwz:localepubmetadata-cs
- Path: NexusReader.Application/Queries/Reader/LocalEpubMetadata.cs
- Role: dto
- Layer: application
## Purpose
Defines a simple data transfer shape that carries metadata extracted from a local EPUB file (title, author, cover bytes, description).
## Key Details
A simple record used in the Application.Queries.Reader namespace to carry local EPUB metadata; no runtime behavior, methods, or external calls in this file.
## Symbols
- LocalEpubMetadata: Defines a simple data transfer shape that carries metadata extracted from a local EPUB file (title, author, cover bytes, description).
- LocalEpubMetadata: Represents metadata extracted from a local EPUB file for query/transfer purposes.
## Dependencies
- No resolved dependencies.
## Calls
- No resolved calls.
## Coverage
- Symbols: 2
- Executable symbols: 0
- Executable symbols with control flow: 0
- Grounded edges: 2
- Unresolved references: 0
- Control-flow fragments: 0
- Unresolved jumps: 0
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 1
- Generated diagrams: 1
## Diagrams
### LocalEpubMetadata Neighborhood
```mermaid
flowchart LR
class_1vvya1l_localepubmetadata("LocalEpubMetadata")
file_485hwz_localepubmetadata_cs("LocalEpubMetadata")
type_1b16u65_localepubmetadata[/"LocalEpubMetadata"/]
```
## Diagram Validation
- Status: pass
@@ -0,0 +1,60 @@
# ViewModels
- File ID: file:1rikffk:viewmodels-cs
- Path: NexusReader.Application/Queries/Reader/ViewModels.cs
- Role: dto
- Layer: application
## Purpose
Defines polymorphic content-block models and a reader page view model used by the application query layer to transport reader UI data (blocks, chapter indexes, ebook id).
## Key Details
Defines JSON polymorphism via JsonDerivedType attributes mapping discriminator values "text" and "trigger" to concrete record types; used in the Application.Queries.Reader boundary for transporting reader UI data.
## Symbols
- ContentBlock: Abstract base record for polymorphic content blocks carrying an Id.
- TextSegmentBlock: Represents a text segment block containing textual content.
- AiActionTriggerBlock: Represents an actionable AI-trigger block with dialogue and selectable action options.
- ReaderPageViewModel: Aggregates content blocks and chapter/ebook metadata for rendering a reader page.
## Dependencies
- No resolved dependencies.
## Calls
- No resolved calls.
## Coverage
- Symbols: 4
- Executable symbols: 0
- Executable symbols with control flow: 0
- Grounded edges: 4
- Unresolved references: 0
- Control-flow fragments: 0
- Unresolved jumps: 0
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 1
- Generated diagrams: 1
## Diagrams
### ViewModels Neighborhood
```mermaid
flowchart LR
file_1rikffk_viewmodels_cs("ViewModels")
type_15iy4fl_textsegmentblock[/"TextSegmentBlock"/]
type_1jbz88m_aiactiontriggerblock[/"AiActionTriggerBlock"/]
type_6l0ozw_readerpageviewmodel[/"ReaderPageViewModel"/]
type_aqqzdn_contentblock[/"ContentBlock"/]
```
## Diagram Validation
- Status: pass
@@ -0,0 +1,60 @@
# GetInitializationStatusQuery
- File ID: file:1m26se1:getinitializationstatusquery-cs
- Path: NexusReader.Application/Queries/System/GetInitializationStatusQuery.cs
- Role: handler
- Layer: application
## Purpose
Defines a CQRS query message used to request the application's initialization status (string) from the Application layer.
## Key Details
A simple marker record implementing IQuery<string>; no behavior, fields, or methods are defined in this file. Used as a request DTO in the application's query/handler pipeline.
## Symbols
- GetInitializationStatusQuery: Defines a CQRS query message used to request the application's initialization status (string) from the Application layer.
- GetInitializationStatusQuery: Represents a request message for retrieving initialization status; a marker query returning a string result.
## Dependencies
- No resolved dependencies.
## Calls
- No resolved calls.
## Unresolved References
- dependency-target: NexusReader.Application.Abstractions.Messaging (IQuery<string>)
## Coverage
- Symbols: 2
- Executable symbols: 0
- Executable symbols with control flow: 0
- Grounded edges: 2
- Unresolved references: 1
- Control-flow fragments: 0
- Unresolved jumps: 0
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 1
- Generated diagrams: 1
## Diagrams
### GetInitializationStatusQuery Neighborhood
```mermaid
flowchart LR
class_904yf3_getinitializationstatusquery("GetInitializationStatusQuery")
file_1m26se1_getinitializationstatusquery_cs("GetInitializationStatusQuery")
type_18ezfq6_getinitializationstatusquery[/"GetInitializationStatusQuery"/]
```
## Diagram Validation
- Status: pass
@@ -0,0 +1,77 @@
# GetInitializationStatusQueryHandler
- File ID: file:1fn3yz7:getinitializationstatusqueryhandler-cs
- Path: NexusReader.Application/Queries/System/GetInitializationStatusQueryHandler.cs
- Role: handler
- Layer: application
## Purpose
A simple application query handler that responds to a GetInitializationStatusQuery with a constant success message indicating the application is initialized.
## Key Details
Trivial handler returning a static success message; no external IO, persistence, branching, or error handling. Likely used by health/initialization checks or UI status queries.
## Symbols
- GetInitializationStatusQueryHandler: A simple application query handler that responds to a GetInitializationStatusQuery with a constant success message indicating the application is initialized.
- Handle(): Handles the GetInitializationStatusQuery by returning a successful Result<string> containing a static initialization message.
- GetInitializationStatusQueryHandler: Query handler that provides a ready/initialized status string for the application.
## Dependencies
- No resolved dependencies.
## Calls
- No resolved calls.
## Unresolved References
- dependency-target: NexusReader.Application.Abstractions.Messaging
- dependency-target: NexusReader.Application.Queries.System.GetInitializationStatusQuery
- dependency-target: FluentResults
## Coverage
- Symbols: 3
- Executable symbols: 1
- Executable symbols with control flow: 1
- Grounded edges: 3
- Unresolved references: 3
- Control-flow fragments: 1
- Unresolved jumps: 0
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 2
- Generated diagrams: 2
## Control Flow Fragments
- Handle: 6 nodes, 5 edges, 0 jumps, 0 unsupported constructs
## Diagrams
### GetInitializationStatusQueryHandler Neighborhood
```mermaid
flowchart LR
class_19ihp67_getinitializationstatusqueryhandler("GetInitializationStatusQueryHandler")
file_1fn3yz7_getinitializationstatusqueryhandler_cs("GetInitializationStatusQueryHandler")
method_11mh753_handle[["Handle()"]]
type_g3vwaj_getinitializationstatusqueryhandler[/"GetInitializationStatusQueryHandler"/]
```
### GetInitializationStatusQueryHandler Execution Overview
```mermaid
flowchart TD
class_19ihp67_getinitializationstatusqueryhandler("GetInitializationStatusQueryHandler")
method_11mh753_handle[["Handle()"]]
class_19ihp67_getinitializationstatusqueryhandler -->|contains| method_11mh753_handle
```
## Diagram Validation
- Status: pass
@@ -0,0 +1,62 @@
# GetUserProfileQuery
- File ID: file:vjfxh7:getuserprofilequery-cs
- Path: NexusReader.Application/Queries/User/GetUserProfileQuery.cs
- Role: dto
- Layer: application
## Purpose
Defines a MediatR query message used to request a user's profile (UserProfileDto) by user id.
## Key Details
Single-line record defining a MediatR IRequest<Result<UserProfileDto>>; no runtime logic in this file.
## Symbols
- GetUserProfileQuery: Defines a MediatR query message used to request a user's profile (UserProfileDto) by user id.
- GetUserProfileQuery: Represents a request message to fetch a user's profile given a UserId.
## Dependencies
- No resolved dependencies.
## Calls
- No resolved calls.
## Unresolved References
- dependency-target: NexusReader.Application.DTOs.User (UserProfileDto)
- dependency-target: MediatR
- dependency-target: FluentResults
## Coverage
- Symbols: 2
- Executable symbols: 0
- Executable symbols with control flow: 0
- Grounded edges: 2
- Unresolved references: 3
- Control-flow fragments: 0
- Unresolved jumps: 0
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 1
- Generated diagrams: 1
## Diagrams
### GetUserProfileQuery Neighborhood
```mermaid
flowchart LR
class_1opd2vh_getuserprofilequery("GetUserProfileQuery")
file_vjfxh7_getuserprofilequery_cs("GetUserProfileQuery")
type_1u9bw06_getuserprofilequery[/"GetUserProfileQuery"/]
```
## Diagram Validation
- Status: pass
@@ -0,0 +1,180 @@
# GetUserProfileQueryHandler
- File ID: file:4pj82p:getuserprofilequeryhandler-cs
- Path: NexusReader.Application/Queries/User/GetUserProfileQueryHandler.cs
- Role: handler
- Layer: application
## Purpose
MediatR query handler that reads user profile data from the application's EF Core DbContext, projects it into UserProfileDto and returns it wrapped in a FluentResults Result.
## Key Details
Single MediatR query handler that performs a single EF Core projection query to build a rich UserProfileDto with multiple fallback paths (tenant parsing, subscription plan, last read book fallback), computes an average quiz score, and materializes role names via a join.
## Symbols
- GetUserProfileQueryHandler: MediatR query handler that reads user profile data from the application's EF Core DbContext, projects it into UserProfileDto and returns it wrapped in a FluentResults Result.
- GetUserProfileQueryHandler(): Constructor that captures the IDbContextFactory dependency.
- Handle(): Loads a single user's profile from the database, maps nested DTOs (plan, last read book, roles, quiz score) and returns Result.Ok(profile) or Result.Fail when not found.
## Dependencies
- No resolved dependencies.
## Calls
- No resolved calls.
## Unresolved References
- dependency-target: NexusReader.Data.Persistence
- dependency-target: NexusReader.Application.DTOs.User
- dependency-target: FluentResults
- dependency-target: MediatR
- call-target: NexusReader.Data.Persistence
- call-target: NexusReader.Data.Persistence
- call-target: NexusReader.Data.Persistence
- interaction-target: .Where(u => u.Id == request.UserId)
- interaction-target: ? (int)u.QuizResults.Where(q => q.TotalQuestions > 0).Average(q => (double)q.Score / q.TotalQuestions * 100)
- interaction-target: }).FirstOrDefault(),
- interaction-target: .Where(ur => ur.UserId == u.Id)
## Coverage
- Symbols: 3
- Executable symbols: 2
- Executable symbols with control flow: 2
- Grounded edges: 3
- Unresolved references: 11
- Control-flow fragments: 2
- Unresolved jumps: 3
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 2
- Generated diagrams: 3
## Control Flow Fragments
- GetUserProfileQueryHandler: 3 nodes, 2 edges, 0 jumps, 0 unsupported constructs
- Handle: 31 nodes, 32 edges, 3 jumps, 0 unsupported constructs
## Diagrams
### GetUserProfileQueryHandler Neighborhood
```mermaid
flowchart LR
class_158ohhh_getuserprofilequeryhandler("GetUserProfileQueryHandler")
file_4pj82p_getuserprofilequeryhandler_cs("GetUserProfileQueryHandler")
method_16gxcfa_handle[["Handle()"]]
method_1t48k4l_getuserprofilequeryhandler[["GetUserProfileQueryHandler()"]]
```
### GetUserProfileQueryHandler Execution Overview
```mermaid
flowchart TD
class_158ohhh_getuserprofilequeryhandler("GetUserProfileQueryHandler")
method_16gxcfa_handle[["Handle()"]]
method_1t48k4l_getuserprofilequeryhandler[["GetUserProfileQueryHandler()"]]
unresolved_unresolved_15t570c_call_target{"Unresolved: AppDbContext.Users (DbSet)"}
unresolved_unresolved_1mpyomv_interaction_target{"Unresolved: }).FirstOrDefault(),"}
unresolved_unresolved_1o052g9_interaction_target{"Unresolved: .Where(u => u.Id == request.UserId)"}
unresolved_unresolved_1s9n6fm_interaction_target{"Unresolved: ? (int)u.QuizResults.Where(q => q.TotalQuestions > 0).Average(q => (double)q.Score / q.TotalQuestions * 100)"}
unresolved_unresolved_b2sea4_call_target{"Unresolved: AppDbContext.UserRoles (DbSet)"}
unresolved_unresolved_jtwisz_interaction_target{"Unresolved: .Where(ur => ur.UserId == u.Id)"}
unresolved_unresolved_nutxq5_call_target{"Unresolved: AppDbContext.Roles (DbSet)"}
class_158ohhh_getuserprofilequeryhandler -->|contains| method_16gxcfa_handle
class_158ohhh_getuserprofilequeryhandler -->|contains| method_1t48k4l_getuserprofilequeryhandler
class_158ohhh_getuserprofilequeryhandler -->|unresolved interaction| unresolved_unresolved_1mpyomv_interaction_target
class_158ohhh_getuserprofilequeryhandler -->|unresolved interaction| unresolved_unresolved_1o052g9_interaction_target
class_158ohhh_getuserprofilequeryhandler -->|unresolved interaction| unresolved_unresolved_1s9n6fm_interaction_target
class_158ohhh_getuserprofilequeryhandler -->|unresolved interaction| unresolved_unresolved_jtwisz_interaction_target
method_16gxcfa_handle -->|unresolved call| unresolved_unresolved_15t570c_call_target
method_16gxcfa_handle -->|unresolved call| unresolved_unresolved_b2sea4_call_target
method_16gxcfa_handle -->|unresolved call| unresolved_unresolved_nutxq5_call_target
```
### Handle() Control Flow
_Warnings: diagram method_16gxcfa_handle__fragment_diagram exceeds preferred complexity thresholds (31 nodes, 32 edges)._
```mermaid
---
config:
flowchart:
defaultRenderer: "elk"
---
flowchart TD
method_16gxcfa_handle__call_21_AppDbContext_Users_DbSet_[["AppDbContext.Users (DbSet)"]]
method_16gxcfa_handle__call_53_AppDbContext_UserRoles_DbSet_[["AppDbContext.UserRoles (DbSet)"]]
method_16gxcfa_handle__call_55_AppDbContext_Roles_DbSet_[["AppDbContext.Roles (DbSet)"]]
method_16gxcfa_handle__action_20_handle_await_20_0__await[["Waits for async work"]]
method_16gxcfa_handle__action_20_resource_acquisition_20__linear("Create DbContext")
method_16gxcfa_handle__action_21_db_read_21__linear("Query Users and project into UserProfileDto")
method_16gxcfa_handle__action_21_handle_await_21_1__await[["Waits for async work"]]
method_16gxcfa_handle__action_23_handle_mapping_23_3__linear("Maps data or transforms shape")
method_16gxcfa_handle__action_23_projection_23__linear("Map primitive fields and nested DTOs")
method_16gxcfa_handle__action_27_branch_fallback_27__linear("TenantId parse with fallback")
method_16gxcfa_handle__action_28_branch_fallback_28__linear("Subscription plan projection with fallback")
method_16gxcfa_handle__action_35_conditional_computation_35__linear("Average quiz score calculation with guard on total questions")
method_16gxcfa_handle__action_38_collection_selection_38__linear("Select last read book or null")
method_16gxcfa_handle__action_38_handle_mapping_38_5__linear("Maps data or transforms shape")
method_16gxcfa_handle__action_53_join_53__linear("Build roles array via join")
method_16gxcfa_handle__action_60_guard_clause_60__condition{"profile == null"}
method_16gxcfa_handle__action_60_guard_clause_60__false("continue")
method_16gxcfa_handle__action_60_guard_clause_60__merge("merge")
method_16gxcfa_handle__action_60_guard_clause_60__true("Result.Fail(\\"Profile not found.\\")")
method_16gxcfa_handle__action_60_handle_branch_60_8__condition{"profile == null"}
method_16gxcfa_handle__action_60_handle_branch_60_8__false("false")
method_16gxcfa_handle__action_60_handle_branch_60_8__merge("merge")
method_16gxcfa_handle__action_60_handle_branch_60_8__true("true")
method_16gxcfa_handle__entry(["Handle entry"])
method_16gxcfa_handle__action_22_handle_repository_read_22_2__linear[("Reads repository or persistence state")]
method_16gxcfa_handle__action_36_handle_repository_read_36_4__linear[("Reads repository or persistence state")]
method_16gxcfa_handle__action_52_handle_repository_read_52_6__linear[("Reads repository or persistence state")]
method_16gxcfa_handle__action_54_handle_repository_read_54_7__linear[("Reads repository or persistence state")]
method_16gxcfa_handle__action_62_handle_return_62_9__return(["Returns result"])
method_16gxcfa_handle__action_65_handle_return_65_10__return(["Returns result"])
method_16gxcfa_handle__action_65_return_65__return(["Return successful result"])
method_16gxcfa_handle__action_20_handle_await_20_0__await -->|next| method_16gxcfa_handle__action_20_resource_acquisition_20__linear
method_16gxcfa_handle__action_20_resource_acquisition_20__linear -->|next| method_16gxcfa_handle__action_21_handle_await_21_1__await
method_16gxcfa_handle__action_21_db_read_21__linear -->|LINQ: filter u.Id == request.UserId projection into UserProfileDto| method_16gxcfa_handle__call_21_AppDbContext_Users_DbSet_
method_16gxcfa_handle__action_21_handle_await_21_1__await -->|next| method_16gxcfa_handle__action_21_db_read_21__linear
method_16gxcfa_handle__action_22_handle_repository_read_22_2__linear -->|next| method_16gxcfa_handle__action_23_handle_mapping_23_3__linear
method_16gxcfa_handle__action_23_handle_mapping_23_3__linear -->|next| method_16gxcfa_handle__action_23_projection_23__linear
method_16gxcfa_handle__action_23_projection_23__linear -->|next| method_16gxcfa_handle__action_27_branch_fallback_27__linear
method_16gxcfa_handle__action_27_branch_fallback_27__linear -->|next| method_16gxcfa_handle__action_28_branch_fallback_28__linear
method_16gxcfa_handle__action_28_branch_fallback_28__linear -->|next| method_16gxcfa_handle__action_35_conditional_computation_35__linear
method_16gxcfa_handle__action_35_conditional_computation_35__linear -->|next| method_16gxcfa_handle__action_36_handle_repository_read_36_4__linear
method_16gxcfa_handle__action_36_handle_repository_read_36_4__linear -->|next| method_16gxcfa_handle__action_38_collection_selection_38__linear
method_16gxcfa_handle__action_38_collection_selection_38__linear -->|next| method_16gxcfa_handle__action_38_handle_mapping_38_5__linear
method_16gxcfa_handle__action_38_handle_mapping_38_5__linear -->|next| method_16gxcfa_handle__action_52_handle_repository_read_52_6__linear
method_16gxcfa_handle__action_52_handle_repository_read_52_6__linear -->|next| method_16gxcfa_handle__action_53_join_53__linear
method_16gxcfa_handle__action_53_join_53__linear -->|Used to filter roles by ur.UserId == u.Id and join with Roles| method_16gxcfa_handle__call_53_AppDbContext_UserRoles_DbSet_
method_16gxcfa_handle__action_54_handle_repository_read_54_7__linear -->|Joined with UserRoles to select role names| method_16gxcfa_handle__call_55_AppDbContext_Roles_DbSet_
method_16gxcfa_handle__action_60_guard_clause_60__condition -->|continue| method_16gxcfa_handle__action_60_guard_clause_60__false
method_16gxcfa_handle__action_60_guard_clause_60__condition -->|Result.Fail Profile not found.| method_16gxcfa_handle__action_60_guard_clause_60__true
method_16gxcfa_handle__action_60_guard_clause_60__false -->|next| method_16gxcfa_handle__action_60_guard_clause_60__merge
method_16gxcfa_handle__action_60_guard_clause_60__merge -->|next| method_16gxcfa_handle__action_60_handle_branch_60_8__condition
method_16gxcfa_handle__action_60_guard_clause_60__true -->|next| method_16gxcfa_handle__action_60_guard_clause_60__merge
method_16gxcfa_handle__action_60_handle_branch_60_8__condition -->|false| method_16gxcfa_handle__action_60_handle_branch_60_8__false
method_16gxcfa_handle__action_60_handle_branch_60_8__condition -->|true| method_16gxcfa_handle__action_60_handle_branch_60_8__true
method_16gxcfa_handle__action_60_handle_branch_60_8__false -->|next| method_16gxcfa_handle__action_60_handle_branch_60_8__merge
method_16gxcfa_handle__action_60_handle_branch_60_8__merge -->|return| method_16gxcfa_handle__action_62_handle_return_62_9__return
method_16gxcfa_handle__action_60_handle_branch_60_8__true -->|next| method_16gxcfa_handle__action_60_handle_branch_60_8__merge
method_16gxcfa_handle__action_62_handle_return_62_9__return -->|return| method_16gxcfa_handle__action_65_handle_return_65_10__return
method_16gxcfa_handle__action_65_handle_return_65_10__return -->|return| method_16gxcfa_handle__action_65_return_65__return
method_16gxcfa_handle__call_21_AppDbContext_Users_DbSet_ -->|next| method_16gxcfa_handle__action_22_handle_repository_read_22_2__linear
method_16gxcfa_handle__call_53_AppDbContext_UserRoles_DbSet_ -->|next| method_16gxcfa_handle__action_54_handle_repository_read_54_7__linear
method_16gxcfa_handle__call_55_AppDbContext_Roles_DbSet_ -->|next| method_16gxcfa_handle__action_60_guard_clause_60__condition
method_16gxcfa_handle__entry -->|next| method_16gxcfa_handle__action_20_handle_await_20_0__await
```
## Diagram Validation
- Status: warn
- Warning: Control-flow extraction left 3 unresolved jumps.
- Warning: control-flow: diagram method_16gxcfa_handle__fragment_diagram exceeds preferred complexity thresholds (31 nodes, 32 edges).
@@ -0,0 +1,194 @@
# ProUserHandler
- File ID: file:1hyu1ez:prouserhandler-cs
- Path: NexusReader.Application/Security/Authorization/ProUserHandler.cs
- Role: handler
- Layer: application
## Purpose
Authorization handler that enforces 'Pro' user access by checking the current user's subscription and AI token usage against limits in the application's database.
## Key Details
Enforces two rules: unlimited-subscription bypass and per-user AI token quota. Uses IDbContextFactory to create a short-lived AppDbContext and loads SubscriptionPlan via EF Include; succeeds the Authorization requirement when either rule passes.
## Symbols
- ProUserHandler: Authorization handler that enforces 'Pro' user access by checking the current user's subscription and AI token usage against limits in the application's database.
- ProUserHandler(): Constructor: receives and stores a DbContext factory for use by the handler.
- HandleRequirementAsync(): Core authorization logic: loads the current user from the DB and grants the requirement when the user has unlimited tokens or remaining AI token quota.
## Dependencies
- No resolved dependencies.
## Calls
- No resolved calls.
## Unresolved References
- dependency-target: NexusReader.Data.Persistence
- dependency-target: NexusReader.Domain.Entities
- dependency-target: Microsoft.EntityFrameworkCore
- interaction-target: var userId = context.User.FindFirstValue(ClaimTypes.NameIdentifier);
- interaction-target: context.Succeed(requirement);
- interaction-target: context.Succeed(requirement);
## Coverage
- Symbols: 3
- Executable symbols: 2
- Executable symbols with control flow: 2
- Grounded edges: 3
- Unresolved references: 6
- Control-flow fragments: 2
- Unresolved jumps: 0
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 2
- Generated diagrams: 3
## Control Flow Fragments
- ProUserHandler: 3 nodes, 2 edges, 0 jumps, 0 unsupported constructs
- HandleRequirementAsync: 43 nodes, 49 edges, 0 jumps, 0 unsupported constructs
## Diagrams
### ProUserHandler Neighborhood
```mermaid
flowchart LR
class_1hxasb_prouserhandler("ProUserHandler")
file_1hyu1ez_prouserhandler_cs("ProUserHandler")
method_14jdxkg_handlerequirementasync[["HandleRequirementAsync()"]]
method_1va0nah_prouserhandler[["ProUserHandler()"]]
```
### ProUserHandler Execution Overview
```mermaid
flowchart TD
class_1hxasb_prouserhandler("ProUserHandler")
method_14jdxkg_handlerequirementasync[["HandleRequirementAsync()"]]
method_1va0nah_prouserhandler[["ProUserHandler()"]]
unresolved_unresolved_7uqyo8_interaction_target{"Unresolved: context.Succeed(requirement);"}
unresolved_unresolved_yv01sb_interaction_target{"Unresolved: var userId = context.User.FindFirstValue(ClaimTypes.NameIdentifier);"}
class_1hxasb_prouserhandler -->|contains| method_14jdxkg_handlerequirementasync
class_1hxasb_prouserhandler -->|contains| method_1va0nah_prouserhandler
class_1hxasb_prouserhandler -->|unresolved interaction| unresolved_unresolved_7uqyo8_interaction_target
class_1hxasb_prouserhandler -->|unresolved interaction| unresolved_unresolved_7uqyo8_interaction_target
class_1hxasb_prouserhandler -->|unresolved interaction| unresolved_unresolved_yv01sb_interaction_target
```
### HandleRequirementAsync() Control Flow
_Warnings: diagram method_14jdxkg_handlerequirementasync__fragment_diagram exceeds preferred complexity thresholds (43 nodes, 49 edges)._
```mermaid
---
config:
flowchart:
defaultRenderer: "elk"
---
flowchart TD
method_14jdxkg_handlerequirementasync__action_24_claim_read_24__linear("Read user id from ClaimsPrincipal")
method_14jdxkg_handlerequirementasync__action_25_guard_clause_25__condition{"string.IsNullOrEmpty(userId)"}
method_14jdxkg_handlerequirementasync__action_25_guard_clause_25__false("otherwise")
method_14jdxkg_handlerequirementasync__action_25_guard_clause_25__merge("merge")
method_14jdxkg_handlerequirementasync__action_25_guard_clause_25__true("return (no authorization attempt)")
method_14jdxkg_handlerequirementasync__action_25_handlerequirementasync_branch_25_1__condition{"string.IsNullOrEmpty(userId)"}
method_14jdxkg_handlerequirementasync__action_25_handlerequirementasync_branch_25_1__false("false")
method_14jdxkg_handlerequirementasync__action_25_handlerequirementasync_branch_25_1__merge("merge")
method_14jdxkg_handlerequirementasync__action_25_handlerequirementasync_branch_25_1__true("true")
method_14jdxkg_handlerequirementasync__action_30_db_context_create_30__linear("Create DbContext from factory (scoped local using)")
method_14jdxkg_handlerequirementasync__action_31_db_query_31__linear("Load user with subscription")
method_14jdxkg_handlerequirementasync__action_31_handlerequirementasync_await_31_3__await[["Waits for async work"]]
method_14jdxkg_handlerequirementasync__action_35_handlerequirementasync_branch_35_4__condition{"user == null"}
method_14jdxkg_handlerequirementasync__action_35_handlerequirementasync_branch_35_4__false("false")
method_14jdxkg_handlerequirementasync__action_35_handlerequirementasync_branch_35_4__merge("merge")
method_14jdxkg_handlerequirementasync__action_35_handlerequirementasync_branch_35_4__true("true")
method_14jdxkg_handlerequirementasync__action_35_null_check_35__linear("Return if user not found")
method_14jdxkg_handlerequirementasync__action_40_branch_40__condition{"user.SubscriptionPlan?.IsUnlimitedTokens == true"}
method_14jdxkg_handlerequirementasync__action_40_branch_40__false("return")
method_14jdxkg_handlerequirementasync__action_40_branch_40__merge("merge")
method_14jdxkg_handlerequirementasync__action_40_branch_40__true("context.Succeed(requirement)")
method_14jdxkg_handlerequirementasync__action_41_handlerequirementasync_branch_41_6__condition{"user.SubscriptionPlan?.IsUnlimitedTokens == true"}
method_14jdxkg_handlerequirementasync__action_41_handlerequirementasync_branch_41_6__false("false")
method_14jdxkg_handlerequirementasync__action_41_handlerequirementasync_branch_41_6__merge("merge")
method_14jdxkg_handlerequirementasync__action_41_handlerequirementasync_branch_41_6__true("true")
method_14jdxkg_handlerequirementasync__action_47_branch_47__condition{"user.AITokensUsed < user.AITokenLimit"}
method_14jdxkg_handlerequirementasync__action_47_branch_47__false("return")
method_14jdxkg_handlerequirementasync__action_47_branch_47__merge("merge")
method_14jdxkg_handlerequirementasync__action_47_branch_47__true("context.Succeed(requirement)")
method_14jdxkg_handlerequirementasync__action_48_handlerequirementasync_branch_48_9__condition{"user.AITokensUsed < user.AITokenLimit"}
method_14jdxkg_handlerequirementasync__action_48_handlerequirementasync_branch_48_9__false("false")
method_14jdxkg_handlerequirementasync__action_48_handlerequirementasync_branch_48_9__merge("merge")
method_14jdxkg_handlerequirementasync__action_48_handlerequirementasync_branch_48_9__true("true")
method_14jdxkg_handlerequirementasync__action_52_implicit_fallback_52__linear("Deny by omission")
method_14jdxkg_handlerequirementasync__entry(["HandleRequirementAsync entry"])
method_14jdxkg_handlerequirementasync__action_24_handlerequirementasync_repository_read_24_0__linear[("Reads repository or persistence state")]
method_14jdxkg_handlerequirementasync__action_43_handlerequirementasync_repository_read_43_7__linear[("Reads repository or persistence state")]
method_14jdxkg_handlerequirementasync__action_50_handlerequirementasync_repository_read_50_10__linear[("Reads repository or persistence state")]
method_14jdxkg_handlerequirementasync__action_27_handlerequirementasync_return_27_2__return(["Returns result"])
method_14jdxkg_handlerequirementasync__action_37_handlerequirementasync_return_37_5__return(["Returns result"])
method_14jdxkg_handlerequirementasync__action_44_handlerequirementasync_return_44_8__return(["Returns result"])
method_14jdxkg_handlerequirementasync__action_51_handlerequirementasync_return_51_11__return(["Returns result"])
method_14jdxkg_handlerequirementasync__implicit_return(["return"])
method_14jdxkg_handlerequirementasync__action_24_claim_read_24__linear -->|next| method_14jdxkg_handlerequirementasync__action_25_guard_clause_25__condition
method_14jdxkg_handlerequirementasync__action_24_handlerequirementasync_repository_read_24_0__linear -->|next| method_14jdxkg_handlerequirementasync__action_24_claim_read_24__linear
method_14jdxkg_handlerequirementasync__action_25_guard_clause_25__condition -->|otherwise| method_14jdxkg_handlerequirementasync__action_25_guard_clause_25__false
method_14jdxkg_handlerequirementasync__action_25_guard_clause_25__condition -->|return no authorization attempt| method_14jdxkg_handlerequirementasync__action_25_guard_clause_25__true
method_14jdxkg_handlerequirementasync__action_25_guard_clause_25__false -->|next| method_14jdxkg_handlerequirementasync__action_25_guard_clause_25__merge
method_14jdxkg_handlerequirementasync__action_25_guard_clause_25__merge -->|next| method_14jdxkg_handlerequirementasync__action_25_handlerequirementasync_branch_25_1__condition
method_14jdxkg_handlerequirementasync__action_25_guard_clause_25__true -->|next| method_14jdxkg_handlerequirementasync__action_25_guard_clause_25__merge
method_14jdxkg_handlerequirementasync__action_25_handlerequirementasync_branch_25_1__condition -->|false| method_14jdxkg_handlerequirementasync__action_25_handlerequirementasync_branch_25_1__false
method_14jdxkg_handlerequirementasync__action_25_handlerequirementasync_branch_25_1__condition -->|true| method_14jdxkg_handlerequirementasync__action_25_handlerequirementasync_branch_25_1__true
method_14jdxkg_handlerequirementasync__action_25_handlerequirementasync_branch_25_1__false -->|next| method_14jdxkg_handlerequirementasync__action_25_handlerequirementasync_branch_25_1__merge
method_14jdxkg_handlerequirementasync__action_25_handlerequirementasync_branch_25_1__merge -->|return| method_14jdxkg_handlerequirementasync__action_27_handlerequirementasync_return_27_2__return
method_14jdxkg_handlerequirementasync__action_25_handlerequirementasync_branch_25_1__true -->|next| method_14jdxkg_handlerequirementasync__action_25_handlerequirementasync_branch_25_1__merge
method_14jdxkg_handlerequirementasync__action_27_handlerequirementasync_return_27_2__return -->|next| method_14jdxkg_handlerequirementasync__action_30_db_context_create_30__linear
method_14jdxkg_handlerequirementasync__action_30_db_context_create_30__linear -->|next| method_14jdxkg_handlerequirementasync__action_31_handlerequirementasync_await_31_3__await
method_14jdxkg_handlerequirementasync__action_31_db_query_31__linear -->|next| method_14jdxkg_handlerequirementasync__action_35_null_check_35__linear
method_14jdxkg_handlerequirementasync__action_31_handlerequirementasync_await_31_3__await -->|next| method_14jdxkg_handlerequirementasync__action_31_db_query_31__linear
method_14jdxkg_handlerequirementasync__action_35_handlerequirementasync_branch_35_4__condition -->|false| method_14jdxkg_handlerequirementasync__action_35_handlerequirementasync_branch_35_4__false
method_14jdxkg_handlerequirementasync__action_35_handlerequirementasync_branch_35_4__condition -->|true| method_14jdxkg_handlerequirementasync__action_35_handlerequirementasync_branch_35_4__true
method_14jdxkg_handlerequirementasync__action_35_handlerequirementasync_branch_35_4__false -->|next| method_14jdxkg_handlerequirementasync__action_35_handlerequirementasync_branch_35_4__merge
method_14jdxkg_handlerequirementasync__action_35_handlerequirementasync_branch_35_4__merge -->|return| method_14jdxkg_handlerequirementasync__action_37_handlerequirementasync_return_37_5__return
method_14jdxkg_handlerequirementasync__action_35_handlerequirementasync_branch_35_4__true -->|next| method_14jdxkg_handlerequirementasync__action_35_handlerequirementasync_branch_35_4__merge
method_14jdxkg_handlerequirementasync__action_35_null_check_35__linear -->|next| method_14jdxkg_handlerequirementasync__action_35_handlerequirementasync_branch_35_4__condition
method_14jdxkg_handlerequirementasync__action_37_handlerequirementasync_return_37_5__return -->|next| method_14jdxkg_handlerequirementasync__action_40_branch_40__condition
method_14jdxkg_handlerequirementasync__action_40_branch_40__condition -->|return| method_14jdxkg_handlerequirementasync__action_40_branch_40__false
method_14jdxkg_handlerequirementasync__action_40_branch_40__condition -->|context.Succeed requirement| method_14jdxkg_handlerequirementasync__action_40_branch_40__true
method_14jdxkg_handlerequirementasync__action_40_branch_40__false -->|next| method_14jdxkg_handlerequirementasync__action_40_branch_40__merge
method_14jdxkg_handlerequirementasync__action_40_branch_40__merge -->|next| method_14jdxkg_handlerequirementasync__action_41_handlerequirementasync_branch_41_6__condition
method_14jdxkg_handlerequirementasync__action_40_branch_40__true -->|next| method_14jdxkg_handlerequirementasync__action_40_branch_40__merge
method_14jdxkg_handlerequirementasync__action_41_handlerequirementasync_branch_41_6__condition -->|false| method_14jdxkg_handlerequirementasync__action_41_handlerequirementasync_branch_41_6__false
method_14jdxkg_handlerequirementasync__action_41_handlerequirementasync_branch_41_6__condition -->|true| method_14jdxkg_handlerequirementasync__action_41_handlerequirementasync_branch_41_6__true
method_14jdxkg_handlerequirementasync__action_41_handlerequirementasync_branch_41_6__false -->|next| method_14jdxkg_handlerequirementasync__action_41_handlerequirementasync_branch_41_6__merge
method_14jdxkg_handlerequirementasync__action_41_handlerequirementasync_branch_41_6__merge -->|next| method_14jdxkg_handlerequirementasync__action_43_handlerequirementasync_repository_read_43_7__linear
method_14jdxkg_handlerequirementasync__action_41_handlerequirementasync_branch_41_6__true -->|next| method_14jdxkg_handlerequirementasync__action_41_handlerequirementasync_branch_41_6__merge
method_14jdxkg_handlerequirementasync__action_43_handlerequirementasync_repository_read_43_7__linear -->|return| method_14jdxkg_handlerequirementasync__action_44_handlerequirementasync_return_44_8__return
method_14jdxkg_handlerequirementasync__action_44_handlerequirementasync_return_44_8__return -->|next| method_14jdxkg_handlerequirementasync__action_47_branch_47__condition
method_14jdxkg_handlerequirementasync__action_47_branch_47__condition -->|return| method_14jdxkg_handlerequirementasync__action_47_branch_47__false
method_14jdxkg_handlerequirementasync__action_47_branch_47__condition -->|context.Succeed requirement| method_14jdxkg_handlerequirementasync__action_47_branch_47__true
method_14jdxkg_handlerequirementasync__action_47_branch_47__false -->|next| method_14jdxkg_handlerequirementasync__action_47_branch_47__merge
method_14jdxkg_handlerequirementasync__action_47_branch_47__merge -->|next| method_14jdxkg_handlerequirementasync__action_48_handlerequirementasync_branch_48_9__condition
method_14jdxkg_handlerequirementasync__action_47_branch_47__true -->|next| method_14jdxkg_handlerequirementasync__action_47_branch_47__merge
method_14jdxkg_handlerequirementasync__action_48_handlerequirementasync_branch_48_9__condition -->|false| method_14jdxkg_handlerequirementasync__action_48_handlerequirementasync_branch_48_9__false
method_14jdxkg_handlerequirementasync__action_48_handlerequirementasync_branch_48_9__condition -->|true| method_14jdxkg_handlerequirementasync__action_48_handlerequirementasync_branch_48_9__true
method_14jdxkg_handlerequirementasync__action_48_handlerequirementasync_branch_48_9__false -->|next| method_14jdxkg_handlerequirementasync__action_48_handlerequirementasync_branch_48_9__merge
method_14jdxkg_handlerequirementasync__action_48_handlerequirementasync_branch_48_9__merge -->|next| method_14jdxkg_handlerequirementasync__action_50_handlerequirementasync_repository_read_50_10__linear
method_14jdxkg_handlerequirementasync__action_48_handlerequirementasync_branch_48_9__true -->|next| method_14jdxkg_handlerequirementasync__action_48_handlerequirementasync_branch_48_9__merge
method_14jdxkg_handlerequirementasync__action_50_handlerequirementasync_repository_read_50_10__linear -->|return| method_14jdxkg_handlerequirementasync__action_51_handlerequirementasync_return_51_11__return
method_14jdxkg_handlerequirementasync__action_51_handlerequirementasync_return_51_11__return -->|next| method_14jdxkg_handlerequirementasync__action_52_implicit_fallback_52__linear
method_14jdxkg_handlerequirementasync__action_52_implicit_fallback_52__linear -->|return| method_14jdxkg_handlerequirementasync__implicit_return
method_14jdxkg_handlerequirementasync__entry -->|next| method_14jdxkg_handlerequirementasync__action_24_handlerequirementasync_repository_read_24_0__linear
```
## Diagram Validation
- Status: warn
- Warning: control-flow: diagram method_14jdxkg_handlerequirementasync__fragment_diagram exceeds preferred complexity thresholds (43 nodes, 49 edges).
@@ -0,0 +1,56 @@
# ProUserRequirement
- File ID: file:1vi6r42:prouserrequirement-cs
- Path: NexusReader.Application/Security/Authorization/ProUserRequirement.cs
- Role: middleware
- Layer: application
## Purpose
Defines an authorization requirement used to gate features to users with an active "Pro" subscription or sufficient AI tokens.
## Key Details
Simple marker class implementing IAuthorizationRequirement (lines 8-10). No runtime logic, fields, or methods; intended to be used with an authorization handler elsewhere that enforces the Pro/token rules.
## Symbols
- ProUserRequirement: Defines an authorization requirement used to gate features to users with an active "Pro" subscription or sufficient AI tokens.
- ProUserRequirement: Marker requirement indicating the user must have an active Pro subscription or sufficient AI tokens for authorization policies.
## Dependencies
- No resolved dependencies.
## Calls
- No resolved calls.
## Coverage
- Symbols: 2
- Executable symbols: 0
- Executable symbols with control flow: 0
- Grounded edges: 2
- Unresolved references: 0
- Control-flow fragments: 0
- Unresolved jumps: 0
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 1
- Generated diagrams: 1
## Diagrams
### ProUserRequirement Neighborhood
```mermaid
flowchart LR
class_42ukrv_prouserrequirement("ProUserRequirement")
file_1vi6r42_prouserrequirement_cs("ProUserRequirement")
type_11vxpr5_prouserrequirement[/"ProUserRequirement"/]
```
## Diagram Validation
- Status: pass
@@ -0,0 +1,82 @@
# 20260428184727_InitialPostgres.Designer
- File ID: file:yngxn0:20260428184727-initialpostgres-designer-cs
- Path: NexusReader.Data/Migrations/20260428184727_InitialPostgres.Designer.cs
- Role: database-config
- Layer: data
## Purpose
EF Core auto-generated migration designer for the InitialPostgres migration; describes the target model (tables, columns, keys, indexes, relationships, and provider annotations) for applying the schema to a Postgres database.
## Key Details
Auto-generated EF Core designer file for an initial Postgres migration; defines schema shape (tables, columns, indexes, PKs, FKs, cascade deletes) and uses Npgsql provider identity extensions. Not an application runtime entrypoint; used by EF migrations to create/update database schema.
## Symbols
- InitialPostgres: EF Core auto-generated migration designer for the InitialPostgres migration; describes the target model (tables, columns, keys, indexes, relationships, and provider annotations) for applying the schema to a Postgres database.
- BuildTargetModel(): Constructs the EF Core model for the InitialPostgres migration (annotations, entities, properties, keys, indexes, relationships, and navigations).
- InitialPostgres: Partial EF Core Migration class representing the InitialPostgres migration; contains BuildTargetModel to describe the schema.
## Dependencies
- imports NexusReader.Data/Persistence/AppDbContext.cs
- imports NexusReader.Domain/Entities/Ebook.cs
- imports NexusReader.Domain/Entities/NexusUser.cs
- imports NexusReader.Domain/Entities/SemanticKnowledgeCache.cs
## Calls
- No resolved calls.
## Coverage
- Symbols: 3
- Executable symbols: 1
- Executable symbols with control flow: 1
- Grounded edges: 7
- Unresolved references: 0
- Control-flow fragments: 1
- Unresolved jumps: 0
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 2
- Generated diagrams: 2
## Control Flow Fragments
- BuildTargetModel: 17 nodes, 16 edges, 0 jumps, 0 unsupported constructs
## Diagrams
### 20260428184727_InitialPostgres.Designer Neighborhood
```mermaid
flowchart LR
class_1a6v1w9_initialpostgres("InitialPostgres")
file_yngxn0_20260428184727_initialpostgres_designer_cs("20260428184727_InitialPostgres.Designer")
method_4nawp0_buildtargetmodel[["BuildTargetModel()"]]
file_1d4ycw2_semanticknowledgecache_cs[/"SemanticKnowledgeCache"/]
file_1pacvtg_appdbcontext_cs[/"AppDbContext"/]
file_lcvwj6_ebook_cs[/"Ebook"/]
file_xcxh5w_nexususer_cs[/"NexusUser"/]
type_1wumbre_initialpostgres[/"InitialPostgres"/]
file_yngxn0_20260428184727_initialpostgres_designer_cs -->|SemanticKnowledgeCache| file_1d4ycw2_semanticknowledgecache_cs
file_yngxn0_20260428184727_initialpostgres_designer_cs -->|AppDbContext| file_1pacvtg_appdbcontext_cs
file_yngxn0_20260428184727_initialpostgres_designer_cs -->|Ebook| file_lcvwj6_ebook_cs
file_yngxn0_20260428184727_initialpostgres_designer_cs -->|NexusUser| file_xcxh5w_nexususer_cs
```
### 20260428184727_InitialPostgres.Designer Execution Overview
```mermaid
flowchart TD
class_1a6v1w9_initialpostgres("InitialPostgres")
method_4nawp0_buildtargetmodel[["BuildTargetModel()"]]
class_1a6v1w9_initialpostgres -->|contains| method_4nawp0_buildtargetmodel
```
## Diagram Validation
- Status: pass
@@ -0,0 +1,84 @@
# 20260428184727_InitialPostgres
- File ID: file:a32vvn:20260428184727-initialpostgres-cs
- Path: NexusReader.Data/Migrations/20260428184727_InitialPostgres.cs
- Role: database-config
- Layer: data
## Purpose
An Entity Framework Core migration that creates the initial PostgreSQL schema for identity tables, application user/ebook tables and a semantic knowledge cache for the NexusReader application.
## Key Details
Postgres-specific migration using Npgsql value generation strategy for integer identity columns, unique indexes on normalized name/email and FK relationships between AspNetUsers and Ebooks; semantic cache keyed by ContentHash to deduplicate semantic computations.
## Symbols
- InitialPostgres: An Entity Framework Core migration that creates the initial PostgreSQL schema for identity tables, application user/ebook tables and a semantic knowledge cache for the NexusReader application.
- Up(): Creates database tables, constraints and indexes needed for initial application schema on Postgres (identity tables, semantic cache, ebooks) during migration up.
- Down(): Drops the tables created by Up in reverse order to roll back the migration.
- AspNetRoles: Identity roles table used by ASP.NET Identity.
- AspNetUsers: Application users table extended with tenant and AI token tracking fields.
- SemanticKnowledgeCache: Stores cached semantic embeddings/metadata keyed by content hash to avoid recomputation.
- Ebooks: Represents ebooks uploaded or tracked by users in the application.
- AspNetRoleClaims / AspNetUserClaims / AspNetUserLogins / AspNetUserRoles / AspNetUserTokens: Standard ASP.NET Identity auxiliary tables for claims, logins, roles and tokens.
## Dependencies
- No resolved dependencies.
## Calls
- No resolved calls.
## Coverage
- Symbols: 8
- Executable symbols: 2
- Executable symbols with control flow: 2
- Grounded edges: 8
- Unresolved references: 0
- Control-flow fragments: 2
- Unresolved jumps: 0
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 2
- Generated diagrams: 2
## Control Flow Fragments
- Up: 12 nodes, 11 edges, 0 jumps, 0 unsupported constructs
- Down: 11 nodes, 10 edges, 0 jumps, 0 unsupported constructs
## Diagrams
### 20260428184727_InitialPostgres Neighborhood
```mermaid
flowchart LR
class_1xhm2de_initialpostgres("InitialPostgres")
file_a32vvn_20260428184727_initialpostgres_cs("20260428184727_InitialPostgres")
method_19ym4q4_up[["Up()"]]
method_1kuci8n_down[["Down()"]]
type_10b7z70_semanticknowledgecache[/"SemanticKnowledgeCache"/]
type_18g2en_aspnetroles[/"AspNetRoles"/]
type_1iyorzj_aspnetusers[/"AspNetUsers"/]
type_1yhkunt_aspnetroleclaims_aspnetuserclaims_aspnetuserlogi[/"AspNetRoleClaims / AspNetUserClaims / AspNetUserLogins / AspNetUserRoles / AspNetUserTokens"/]
type_96fzwh_ebooks[/"Ebooks"/]
```
### 20260428184727_InitialPostgres Execution Overview
```mermaid
flowchart TD
class_1xhm2de_initialpostgres("InitialPostgres")
method_19ym4q4_up[["Up()"]]
method_1kuci8n_down[["Down()"]]
class_1xhm2de_initialpostgres -->|contains| method_19ym4q4_up
class_1xhm2de_initialpostgres -->|contains| method_1kuci8n_down
```
## Diagram Validation
- Status: pass
@@ -0,0 +1,88 @@
# 20260428185239_IncreaseHashLength.Designer
- File ID: file:qoj05g:20260428185239-increasehashlength-designer-cs
- Path: NexusReader.Data/Migrations/20260428185239_IncreaseHashLength.Designer.cs
- Role: database-config
- Layer: data
## Purpose
EF Core migration designer for the IncreaseHashLength migration; describes the target EF Core model (entities, properties, indexes, relationships) used by migrations and tooling.
## Key Details
Defines EF Core model shape for this migration. Notable: SemanticKnowledgeCache.ContentHash is configured with max length 128 (lines 277-305) and is the primary key/unique index; standard ASP.NET Identity tables and Ebook->User relationships are present. The class is auto-generated designer code and is not application logic.
## Symbols
- IncreaseHashLength: EF Core migration designer for the IncreaseHashLength migration; describes the target EF Core model (entities, properties, indexes, relationships) used by migrations and tooling.
- BuildTargetModel(): Populates the EF Core ModelBuilder with entity configurations, annotations, columns, indexes and relationships representing the target schema for this migration.
- IncreaseHashLength: Partial migration class representing the IncreaseHashLength EF Core migration and holding the generated BuildTargetModel.
## Dependencies
- imports NexusReader.Data/Persistence/AppDbContext.cs
- imports NexusReader.Domain/Entities/Ebook.cs
- imports NexusReader.Domain/Entities/NexusUser.cs
- imports NexusReader.Domain/Entities/SemanticKnowledgeCache.cs
## Calls
- No resolved calls.
## Unresolved References
- interaction-target: NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder) (external Npgsql EF provider)
## Coverage
- Symbols: 3
- Executable symbols: 1
- Executable symbols with control flow: 1
- Grounded edges: 7
- Unresolved references: 1
- Control-flow fragments: 1
- Unresolved jumps: 0
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 2
- Generated diagrams: 2
## Control Flow Fragments
- BuildTargetModel: 21 nodes, 20 edges, 0 jumps, 0 unsupported constructs
## Diagrams
### 20260428185239_IncreaseHashLength.Designer Neighborhood
```mermaid
flowchart LR
class_mi743e_increasehashlength("IncreaseHashLength")
file_qoj05g_20260428185239_increasehashlength_designer_cs("20260428185239_IncreaseHashLength.Designer")
method_1wohrks_buildtargetmodel[["BuildTargetModel()"]]
file_1d4ycw2_semanticknowledgecache_cs[/"SemanticKnowledgeCache"/]
file_1pacvtg_appdbcontext_cs[/"AppDbContext"/]
file_lcvwj6_ebook_cs[/"Ebook"/]
file_xcxh5w_nexususer_cs[/"NexusUser"/]
type_gbavgv_increasehashlength[/"IncreaseHashLength"/]
file_qoj05g_20260428185239_increasehashlength_designer_cs -->|SemanticKnowledgeCache| file_1d4ycw2_semanticknowledgecache_cs
file_qoj05g_20260428185239_increasehashlength_designer_cs -->|AppDbContext| file_1pacvtg_appdbcontext_cs
file_qoj05g_20260428185239_increasehashlength_designer_cs -->|Ebook| file_lcvwj6_ebook_cs
file_qoj05g_20260428185239_increasehashlength_designer_cs -->|NexusUser| file_xcxh5w_nexususer_cs
```
### 20260428185239_IncreaseHashLength.Designer Execution Overview
```mermaid
flowchart TD
class_mi743e_increasehashlength("IncreaseHashLength")
method_1wohrks_buildtargetmodel[["BuildTargetModel()"]]
unresolved_unresolved_1041pkd_interaction_target{"Unresolved: NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder) (external Npgsql EF provider)"}
class_mi743e_increasehashlength -->|contains| method_1wohrks_buildtargetmodel
class_mi743e_increasehashlength -->|unresolved interaction| unresolved_unresolved_1041pkd_interaction_target
```
## Diagram Validation
- Status: pass
@@ -0,0 +1,103 @@
# 20260428185239_IncreaseHashLength
- File ID: file:1m4p1ej:20260428185239-increasehashlength-cs
- Path: NexusReader.Data/Migrations/20260428185239_IncreaseHashLength.cs
- Role: database-config
- Layer: data
## Purpose
EF Core migration that updates column types/constraints: increases the ContentHash length and switches certain DateTime columns to use 'timestamp without time zone' (with a Down method to revert).
## Key Details
Primary change: ContentHash column in SemanticKnowledgeCache grows from 64 to 128 characters; several DateTime columns switch between 'timestamp with time zone' and 'timestamp without time zone' depending on Up/Down.
## Symbols
- IncreaseHashLength: EF Core migration that updates column types/constraints: increases the ContentHash length and switches certain DateTime columns to use 'timestamp without time zone' (with a Down method to revert).
- Up(): Apply schema changes: alter several columns (timestamps and the ContentHash length) to new types/constraints.
- Down(): Revert schema changes made in Up: restore previous timestamp types and ContentHash length.
- IncreaseHashLength: EF Core migration class that applies and reverts schema changes related to timestamp types and ContentHash length.
## Dependencies
- No resolved dependencies.
## Calls
- No resolved calls.
## Unresolved References
- interaction-target: migrationBuilder.AlterColumn<DateTime>(name: "CreatedAt", table: "SemanticKnowledgeCache", type: "timestamp without time zone", nullable: false, oldClrType: typeof(DateTime), oldType: "timestamp with time zone");
- interaction-target: migrationBuilder.AlterColumn<string>(name: "ContentHash", table: "SemanticKnowledgeCache", type: "character varying(128)", maxLength: 128, nullable: false, oldClrType: typeof(string), oldType: "character varying(64)", oldMaxLength: 64);
- interaction-target: migrationBuilder.AlterColumn<DateTime>(name: "LastReadDate", table: "Ebooks", type: "timestamp without time zone", nullable: true, oldClrType: typeof(DateTime), oldType: "timestamp with time zone", oldNullable: true);
- interaction-target: migrationBuilder.AlterColumn<DateTime>(name: "AddedDate", table: "Ebooks", type: "timestamp without time zone", nullable: false, oldClrType: typeof(DateTime), oldType: "timestamp with time zone");
- interaction-target: migrationBuilder.AlterColumn<DateTime>(name: "CreatedAt", table: "SemanticKnowledgeCache", type: "timestamp with time zone", nullable: false, oldClrType: typeof(DateTime), oldType: "timestamp without time zone");
- interaction-target: migrationBuilder.AlterColumn<string>(name: "ContentHash", table: "SemanticKnowledgeCache", type: "character varying(64)", maxLength: 64, nullable: false, oldClrType: typeof(string), oldType: "character varying(128)", oldMaxLength: 128);
- interaction-target: migrationBuilder.AlterColumn<DateTime>(name: "LastReadDate", table: "Ebooks", type: "timestamp with time zone", nullable: true, oldClrType: typeof(DateTime), oldType: "timestamp without time zone", oldNullable: true);
- interaction-target: migrationBuilder.AlterColumn<DateTime>(name: "AddedDate", table: "Ebooks", type: "timestamp with time zone", nullable: false, oldClrType: typeof(DateTime), oldType: "timestamp without time zone");
## Coverage
- Symbols: 4
- Executable symbols: 2
- Executable symbols with control flow: 2
- Grounded edges: 4
- Unresolved references: 8
- Control-flow fragments: 2
- Unresolved jumps: 0
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 2
- Generated diagrams: 2
## Control Flow Fragments
- Up: 6 nodes, 5 edges, 0 jumps, 0 unsupported constructs
- Down: 6 nodes, 5 edges, 0 jumps, 0 unsupported constructs
## Diagrams
### 20260428185239_IncreaseHashLength Neighborhood
```mermaid
flowchart LR
class_14xe27n_increasehashlength("IncreaseHashLength")
file_1m4p1ej_20260428185239_increasehashlength_cs("20260428185239_IncreaseHashLength")
method_1x7fw9j_up[["Up()"]]
method_pkbr0t_down[["Down()"]]
type_cn85p2_increasehashlength[/"IncreaseHashLength"/]
```
### 20260428185239_IncreaseHashLength Execution Overview
```mermaid
flowchart TD
class_14xe27n_increasehashlength("IncreaseHashLength")
method_1x7fw9j_up[["Up()"]]
method_pkbr0t_down[["Down()"]]
unresolved_unresolved_15lpvbv_interaction_target{"Unresolved: migrationBuilder.AlterColumn<DateTime>(name: \\"LastReadDate\\", table: \\"Ebooks\\", type: \\"timestamp with time zone\\", nullable: true, oldClrType: typeof(DateTime), oldType: \\"timestamp without time zone\\", oldNullable: true);"}
unresolved_unresolved_1liwgtv_interaction_target{"Unresolved: migrationBuilder.AlterColumn<DateTime>(name: \\"LastReadDate\\", table: \\"Ebooks\\", type: \\"timestamp without time zone\\", nullable: true, oldClrType: typeof(DateTime), oldType: \\"timestamp with time zone\\", oldNullable: true);"}
unresolved_unresolved_1tqhoi7_interaction_target{"Unresolved: migrationBuilder.AlterColumn<string>(name: \\"ContentHash\\", table: \\"SemanticKnowledgeCache\\", type: \\"character varying(64)\\", maxLength: 64, nullable: false, oldClrType: typeof(string), oldType: \\"character varying(128)\\", oldMaxLength: 128);"}
unresolved_unresolved_1xkic68_interaction_target{"Unresolved: migrationBuilder.AlterColumn<DateTime>(name: \\"CreatedAt\\", table: \\"SemanticKnowledgeCache\\", type: \\"timestamp with time zone\\", nullable: false, oldClrType: typeof(DateTime), oldType: \\"timestamp without time zone\\");"}
unresolved_unresolved_d95c5g_interaction_target{"Unresolved: migrationBuilder.AlterColumn<DateTime>(name: \\"AddedDate\\", table: \\"Ebooks\\", type: \\"timestamp with time zone\\", nullable: false, oldClrType: typeof(DateTime), oldType: \\"timestamp without time zone\\");"}
unresolved_unresolved_gp3i3y_interaction_target{"Unresolved: migrationBuilder.AlterColumn<DateTime>(name: \\"AddedDate\\", table: \\"Ebooks\\", type: \\"timestamp without time zone\\", nullable: false, oldClrType: typeof(DateTime), oldType: \\"timestamp with time zone\\");"}
unresolved_unresolved_hddsir_interaction_target{"Unresolved: migrationBuilder.AlterColumn<string>(name: \\"ContentHash\\", table: \\"SemanticKnowledgeCache\\", type: \\"character varying(128)\\", maxLength: 128, nullable: false, oldClrType: typeof(string), oldType: \\"character varying(64)\\", oldMaxLength: 64);"}
unresolved_unresolved_raiqd6_interaction_target{"Unresolved: migrationBuilder.AlterColumn<DateTime>(name: \\"CreatedAt\\", table: \\"SemanticKnowledgeCache\\", type: \\"timestamp without time zone\\", nullable: false, oldClrType: typeof(DateTime), oldType: \\"timestamp with time zone\\");"}
class_14xe27n_increasehashlength -->|contains| method_1x7fw9j_up
class_14xe27n_increasehashlength -->|contains| method_pkbr0t_down
class_14xe27n_increasehashlength -->|unresolved interaction| unresolved_unresolved_15lpvbv_interaction_target
class_14xe27n_increasehashlength -->|unresolved interaction| unresolved_unresolved_1liwgtv_interaction_target
class_14xe27n_increasehashlength -->|unresolved interaction| unresolved_unresolved_1tqhoi7_interaction_target
class_14xe27n_increasehashlength -->|unresolved interaction| unresolved_unresolved_1xkic68_interaction_target
class_14xe27n_increasehashlength -->|unresolved interaction| unresolved_unresolved_d95c5g_interaction_target
class_14xe27n_increasehashlength -->|unresolved interaction| unresolved_unresolved_gp3i3y_interaction_target
class_14xe27n_increasehashlength -->|unresolved interaction| unresolved_unresolved_hddsir_interaction_target
class_14xe27n_increasehashlength -->|unresolved interaction| unresolved_unresolved_raiqd6_interaction_target
```
## Diagram Validation
- Status: pass
@@ -0,0 +1,91 @@
# 20260429080302_AddQuizResults.Designer
- File ID: file:1j2onoi:20260429080302-addquizresults-designer-cs
- Path: NexusReader.Data/Migrations/20260429080302_AddQuizResults.Designer.cs
- Role: database-config
- Layer: data
## Purpose
EF Core migration designer that defines the target database model (tables, columns, keys, indices, and relationships) for the AddQuizResults migration.
## Key Details
This auto-generated EF Core migration designer defines the QuizResults table and wiring to NexusUser, plus other identity and application tables; it configures columns, PKs, indices, and cascade-delete foreign keys for the PostgreSQL provider.
## Symbols
- AddQuizResults: EF Core migration designer that defines the target database model (tables, columns, keys, indices, and relationships) for the AddQuizResults migration.
- BuildTargetModel(): Constructs the EF Core model for the migration: declares entities, columns, keys, indexes, relationships, and Npgsql identity config.
- Ebook (entity mapping): Represents e-book metadata persisted in Ebooks table and linked to a NexusUser.
- NexusUser (entity mapping): Application user (extends IdentityUser) persisted in AspNetUsers with authentication/tenant and AI token tracking fields.
- QuizResult (entity mapping): Represents a completed quiz result persisted in QuizResults and linked to a NexusUser.
- SemanticKnowledgeCache (entity mapping): Caches semantic knowledge artifacts keyed by content hash for reuse (stored as JSON), persisted in SemanticKnowledgeCache.
## Dependencies
- imports NexusReader.Data/Persistence/AppDbContext.cs
- imports NexusReader.Domain/Entities/Ebook.cs
- imports NexusReader.Domain/Entities/NexusUser.cs
- imports NexusReader.Domain/Entities/QuizResult.cs
- imports NexusReader.Domain/Entities/SemanticKnowledgeCache.cs
## Calls
- No resolved calls.
## Coverage
- Symbols: 6
- Executable symbols: 1
- Executable symbols with control flow: 1
- Grounded edges: 11
- Unresolved references: 0
- Control-flow fragments: 1
- Unresolved jumps: 0
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 2
- Generated diagrams: 2
## Control Flow Fragments
- BuildTargetModel: 21 nodes, 20 edges, 0 jumps, 0 unsupported constructs
## Diagrams
### 20260429080302_AddQuizResults.Designer Neighborhood
```mermaid
flowchart LR
class_9ftatg_addquizresults("AddQuizResults")
file_1j2onoi_20260429080302_addquizresults_designer_cs("20260429080302_AddQuizResults.Designer")
method_eacfb6_buildtargetmodel[["BuildTargetModel()"]]
file_1d4ycw2_semanticknowledgecache_cs[/"SemanticKnowledgeCache"/]
file_1pacvtg_appdbcontext_cs[/"AppDbContext"/]
file_1wyr0y8_quizresult_cs[/"QuizResult"/]
file_lcvwj6_ebook_cs[/"Ebook"/]
file_xcxh5w_nexususer_cs[/"NexusUser"/]
type_1agxbak_semanticknowledgecache_entity_mapping[/"SemanticKnowledgeCache (entity mapping)"/]
type_1dtv9c0_nexususer_entity_mapping[/"NexusUser (entity mapping)"/]
type_exuypx_ebook_entity_mapping[/"Ebook (entity mapping)"/]
type_ffgofm_quizresult_entity_mapping[/"QuizResult (entity mapping)"/]
file_1j2onoi_20260429080302_addquizresults_designer_cs -->|SemanticKnowledgeCache| file_1d4ycw2_semanticknowledgecache_cs
file_1j2onoi_20260429080302_addquizresults_designer_cs -->|AppDbContext| file_1pacvtg_appdbcontext_cs
file_1j2onoi_20260429080302_addquizresults_designer_cs -->|QuizResult| file_1wyr0y8_quizresult_cs
file_1j2onoi_20260429080302_addquizresults_designer_cs -->|Ebook| file_lcvwj6_ebook_cs
file_1j2onoi_20260429080302_addquizresults_designer_cs -->|NexusUser| file_xcxh5w_nexususer_cs
```
### 20260429080302_AddQuizResults.Designer Execution Overview
```mermaid
flowchart TD
class_9ftatg_addquizresults("AddQuizResults")
method_eacfb6_buildtargetmodel[["BuildTargetModel()"]]
class_9ftatg_addquizresults -->|contains| method_eacfb6_buildtargetmodel
```
## Diagram Validation
- Status: pass
@@ -0,0 +1,78 @@
# 20260429080302_AddQuizResults
- File ID: file:q6hq0x:20260429080302-addquizresults-cs
- Path: NexusReader.Data/Migrations/20260429080302_AddQuizResults.cs
- Role: database-config
- Layer: data
## Purpose
EF Core migration that adds a new QuizResults table (with columns, PK, FK to AspNetUsers, and an index) and provides rollback to drop it.
## Key Details
Adds QuizResults table with PK Id, FK UserId -> AspNetUsers.Id (cascade), and an index on UserId to support lookups by user.
## Symbols
- AddQuizResults: EF Core migration that adds a new QuizResults table (with columns, PK, FK to AspNetUsers, and an index) and provides rollback to drop it.
- Up(): Creates the QuizResults table with columns, primary key, foreign key to AspNetUsers (cascade) and an index on UserId.
- Down(): Drops the QuizResults table to rollback the migration.
- AddQuizResults: EF Core Migration class that applies schema changes to add QuizResults and rollback.
- QuizResults (table schema): Represents the database table schema created by this migration.
## Dependencies
- No resolved dependencies.
## Calls
- No resolved calls.
## Coverage
- Symbols: 5
- Executable symbols: 2
- Executable symbols with control flow: 2
- Grounded edges: 5
- Unresolved references: 0
- Control-flow fragments: 2
- Unresolved jumps: 0
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 2
- Generated diagrams: 2
## Control Flow Fragments
- Up: 7 nodes, 6 edges, 0 jumps, 0 unsupported constructs
- Down: 3 nodes, 2 edges, 0 jumps, 0 unsupported constructs
## Diagrams
### 20260429080302_AddQuizResults Neighborhood
```mermaid
flowchart LR
class_3a8sch_addquizresults("AddQuizResults")
file_q6hq0x_20260429080302_addquizresults_cs("20260429080302_AddQuizResults")
method_1sa6em1_up[["Up()"]]
method_1sgd810_down[["Down()"]]
type_1f6rpfs_addquizresults[/"AddQuizResults"/]
type_1tv21lf_quizresults_table_schema[/"QuizResults (table schema)"/]
```
### 20260429080302_AddQuizResults Execution Overview
```mermaid
flowchart TD
class_3a8sch_addquizresults("AddQuizResults")
method_1sa6em1_up[["Up()"]]
method_1sgd810_down[["Down()"]]
class_3a8sch_addquizresults -->|contains| method_1sa6em1_up
class_3a8sch_addquizresults -->|contains| method_1sgd810_down
```
## Diagram Validation
- Status: pass
@@ -0,0 +1,125 @@
# 20260503175906_FinalNormalizedSubscriptionArchitecture.Designer
- File ID: file:1xzhi6b:20260503175906-finalnormalizedsubscriptionarchit
- Path: NexusReader.Data/Migrations/20260503175906_FinalNormalizedSubscriptionArchitecture.Designer.cs
- Role: database-config
- Layer: data
## Purpose
EF Core migration designer that defines the target EF model for the AppDbContext: configures entities, relationships, indices, Postgres/vector extensions and includes seed data for subscription plans.
## Key Details
Migration snapshot configures Postgres vector extension and embedding columns (vector(768)/vector(1536)), defines identity and domain entities with indices and FKs, and inserts four SubscriptionPlan seed rows (Free, Basic, Pro, Enterprise).
## Symbols
- FinalNormalizedSubscriptionArchitecture: EF Core migration designer that defines the target EF model for the AppDbContext: configures entities, relationships, indices, Postgres/vector extensions and includes seed data for subscription plans.
- BuildTargetModel(): Populates the EF Core ModelBuilder with entity types, columns, keys, indices, relationships, Postgres/vector extensions and seed data for this migration snapshot.
- Microsoft.AspNetCore.Identity.IdentityRole: Identity role mapping configured in the EF model for AspNetRoles table
- NexusReader.Domain.Entities.Ebook: Domain entity configuration for ebooks table
- NexusReader.Domain.Entities.KnowledgeUnit: Vectorized knowledge unit used for semantic search and storage
- NexusReader.Domain.Entities.KnowledgeUnitLink: Represents directional links between knowledge units
- NexusReader.Domain.Entities.NexusUser: Application user mapped to AspNetUsers with subscription and tenant info
- NexusReader.Domain.Entities.SemanticKnowledgeCache: Cached semantic results with embedding vector and prompt/model metadata
- NexusReader.Domain.Entities.SubscriptionPlan: Subscription plan catalog with token limits, price and Stripe product id; seeded by migration
- NexusReader.Domain.Entities.QuizResult: User quiz result entries with score and topic
## Dependencies
- imports NexusReader.Data/Persistence/AppDbContext.cs
- imports NexusReader.Domain/Entities/Ebook.cs
- imports NexusReader.Domain/Entities/KnowledgeUnit.cs
- imports NexusReader.Domain/Entities/KnowledgeUnitLink.cs
- imports NexusReader.Domain/Entities/NexusUser.cs
- imports NexusReader.Domain/Entities/SemanticKnowledgeCache.cs
- imports NexusReader.Domain/Entities/SubscriptionPlan.cs
- imports NexusReader.Domain/Entities/QuizResult.cs
## Calls
- No resolved calls.
## Unresolved References
- interaction-target: NpgsqlModelBuilderExtensions.HasPostgresExtension(modelBuilder, "vector")
- interaction-target: NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder)
## Coverage
- Symbols: 10
- Executable symbols: 1
- Executable symbols with control flow: 1
- Grounded edges: 18
- Unresolved references: 2
- Control-flow fragments: 1
- Unresolved jumps: 0
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 2
- Generated diagrams: 2
## Control Flow Fragments
- BuildTargetModel: 15 nodes, 14 edges, 0 jumps, 0 unsupported constructs
## Diagrams
### 20260503175906_FinalNormalizedSubscriptionArchitecture.Designer Neighborhood
_Warnings: diagram file_1xzhi6b_20260503175906_finalnormalizedsubscriptionarchit_neighborhood_view exceeds preferred complexity thresholds (19 nodes, 8 edges)._
```mermaid
---
config:
flowchart:
defaultRenderer: "elk"
---
flowchart LR
class_zj074q_finalnormalizedsubscriptionarchitecture("FinalNormalizedSubscriptionArchitecture")
file_1xzhi6b_20260503175906_finalnormalizedsubscriptionarchit("20260503175906_FinalNormalizedSubscriptionArchitecture.Designer")
method_tz9mq3_buildtargetmodel[["BuildTargetModel()"]]
file_1b03oou_subscriptionplan_cs[/"SubscriptionPlan"/]
file_1d4ycw2_semanticknowledgecache_cs[/"SemanticKnowledgeCache"/]
file_1m6x5qy_knowledgeunitlink_cs[/"KnowledgeUnitLink"/]
file_1pacvtg_appdbcontext_cs[/"AppDbContext"/]
file_1wyr0y8_quizresult_cs[/"QuizResult"/]
file_h6a0xu_knowledgeunit_cs[/"KnowledgeUnit"/]
file_lcvwj6_ebook_cs[/"Ebook"/]
file_xcxh5w_nexususer_cs[/"NexusUser"/]
type_13day2p_nexusreader_domain_entities_knowledgeunit[/"NexusReader.Domain.Entities.KnowledgeUnit"/]
type_14w07kf_nexusreader_domain_entities_subscriptionplan[/"NexusReader.Domain.Entities.SubscriptionPlan"/]
type_15ow7t1_nexusreader_domain_entities_nexususer[/"NexusReader.Domain.Entities.NexusUser"/]
type_30kk08_nexusreader_domain_entities_semanticknowledgecac[/"NexusReader.Domain.Entities.SemanticKnowledgeCache"/]
type_6xl8d4_nexusreader_domain_entities_quizresult[/"NexusReader.Domain.Entities.QuizResult"/]
type_7ob3p3_nexusreader_domain_entities_ebook[/"NexusReader.Domain.Entities.Ebook"/]
type_9y8b30_nexusreader_domain_entities_knowledgeunitlink[/"NexusReader.Domain.Entities.KnowledgeUnitLink"/]
type_hhlqtu_microsoft_aspnetcore_identity_identityrole[/"Microsoft.AspNetCore.Identity.IdentityRole"/]
file_1xzhi6b_20260503175906_finalnormalizedsubscriptionarchit -->|SubscriptionPlan| file_1b03oou_subscriptionplan_cs
file_1xzhi6b_20260503175906_finalnormalizedsubscriptionarchit -->|SemanticKnowledgeCache| file_1d4ycw2_semanticknowledgecache_cs
file_1xzhi6b_20260503175906_finalnormalizedsubscriptionarchit -->|KnowledgeUnitLink| file_1m6x5qy_knowledgeunitlink_cs
file_1xzhi6b_20260503175906_finalnormalizedsubscriptionarchit -->|AppDbContext| file_1pacvtg_appdbcontext_cs
file_1xzhi6b_20260503175906_finalnormalizedsubscriptionarchit -->|QuizResult| file_1wyr0y8_quizresult_cs
file_1xzhi6b_20260503175906_finalnormalizedsubscriptionarchit -->|KnowledgeUnit| file_h6a0xu_knowledgeunit_cs
file_1xzhi6b_20260503175906_finalnormalizedsubscriptionarchit -->|Ebook| file_lcvwj6_ebook_cs
file_1xzhi6b_20260503175906_finalnormalizedsubscriptionarchit -->|NexusUser| file_xcxh5w_nexususer_cs
```
### 20260503175906_FinalNormalizedSubscriptionArchitecture.Designer Execution Overview
```mermaid
flowchart TD
class_zj074q_finalnormalizedsubscriptionarchitecture("FinalNormalizedSubscriptionArchitecture")
method_tz9mq3_buildtargetmodel[["BuildTargetModel()"]]
unresolved_unresolved_1meayaz_interaction_target{"Unresolved: NpgsqlModelBuilderExtensions.HasPostgresExtension(modelBuilder, \\"vector\\")"}
unresolved_unresolved_1x958ae_interaction_target{"Unresolved: NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder)"}
class_zj074q_finalnormalizedsubscriptionarchitecture -->|contains| method_tz9mq3_buildtargetmodel
class_zj074q_finalnormalizedsubscriptionarchitecture -->|unresolved interaction| unresolved_unresolved_1meayaz_interaction_target
class_zj074q_finalnormalizedsubscriptionarchitecture -->|unresolved interaction| unresolved_unresolved_1x958ae_interaction_target
```
## Diagram Validation
- Status: warn
- Warning: neighborhood-view: diagram file_1xzhi6b_20260503175906_finalnormalizedsubscriptionarchit_neighborhood_view exceeds preferred complexity thresholds (19 nodes, 8 edges).
@@ -0,0 +1,80 @@
# 20260503175906_FinalNormalizedSubscriptionArchitecture
- File ID: file:18pke7q:20260503175906-finalnormalizedsubscriptionarchit
- Path: NexusReader.Data/Migrations/20260503175906_FinalNormalizedSubscriptionArchitecture.cs
- Role: database-config
- Layer: data
## Purpose
EF Core migration that alters database schema to introduce normalized subscription plans, tenant scoping, vector columns (pgvector), and related knowledge unit tables; also seeds subscription plan rows.
## Key Details
Adds pgvector extension usage and vector columns (1536 and 768 dims), migrates several dates to timestamptz, normalizes subscriptions into a SubscriptionPlans table seeded with Free/Basic/Pro/Enterprise, introduces tenant scoping columns across multiple tables and creates knowledge unit/link tables with FK constraints.
## Symbols
- FinalNormalizedSubscriptionArchitecture: EF Core migration that alters database schema to introduce normalized subscription plans, tenant scoping, vector columns (pgvector), and related knowledge unit tables; also seeds subscription plan rows.
- Up(): Apply schema changes: remove/alter columns, add tenant and vector columns, create KnowledgeUnits/SubscriptionPlans/KnowledgeUnitLinks tables, seed SubscriptionPlans, create indexes and add foreign key.
- Down(): Revert schema changes performed in Up: drop created tables, indexes, columns and restore previous column types/values and the dropped CurrentPlan column.
- KnowledgeUnits (table): Stores normalized knowledge unit records with tenant scoping and vector embedding for semantic search.
- SubscriptionPlans (table): Represents normalized subscription plans with token limits, pricing and Stripe product mapping.
- KnowledgeUnitLinks (table): Associative links between knowledge units to model relations; enforces FK constraints to KnowledgeUnits.
## Dependencies
- No resolved dependencies.
## Calls
- No resolved calls.
## Coverage
- Symbols: 6
- Executable symbols: 2
- Executable symbols with control flow: 2
- Grounded edges: 6
- Unresolved references: 0
- Control-flow fragments: 2
- Unresolved jumps: 0
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 2
- Generated diagrams: 2
## Control Flow Fragments
- Up: 24 nodes, 23 edges, 0 jumps, 0 unsupported constructs
- Down: 12 nodes, 11 edges, 0 jumps, 0 unsupported constructs
## Diagrams
### 20260503175906_FinalNormalizedSubscriptionArchitecture Neighborhood
```mermaid
flowchart LR
class_tkzvf7_finalnormalizedsubscriptionarchitecture("FinalNormalizedSubscriptionArchitecture")
file_18pke7q_20260503175906_finalnormalizedsubscriptionarchit("20260503175906_FinalNormalizedSubscriptionArchitecture")
method_1b2dxzu_up[["Up()"]]
method_llsrxk_down[["Down()"]]
type_11syh06_subscriptionplans_table[/"SubscriptionPlans (table)"/]
type_19jp6ev_knowledgeunits_table[/"KnowledgeUnits (table)"/]
type_1pi9458_knowledgeunitlinks_table[/"KnowledgeUnitLinks (table)"/]
```
### 20260503175906_FinalNormalizedSubscriptionArchitecture Execution Overview
```mermaid
flowchart TD
class_tkzvf7_finalnormalizedsubscriptionarchitecture("FinalNormalizedSubscriptionArchitecture")
method_1b2dxzu_up[["Up()"]]
method_llsrxk_down[["Down()"]]
class_tkzvf7_finalnormalizedsubscriptionarchitecture -->|contains| method_1b2dxzu_up
class_tkzvf7_finalnormalizedsubscriptionarchitecture -->|contains| method_llsrxk_down
```
## Diagram Validation
- Status: pass
@@ -0,0 +1,87 @@
# 20260506184227_UpdateSubscriptionPlanIsUnlimitedTokens.Designer
- File ID: file:1psv1cv:20260506184227-updatesubscriptionplanisunlimited
- Path: NexusReader.Data/Migrations/20260506184227_UpdateSubscriptionPlanIsUnlimitedTokens.Designer.cs
- Role: database-config
- Layer: data
## Purpose
EF Core migration designer that builds the target EF Core model for the migration UpdateSubscriptionPlanIsUnlimitedTokens; contains the model snapshot/configuration (entities, properties, indexes, relations, and seed data) used by EF migrations.
## Key Details
This auto-generated migration designer configures schema details including vector columns (pgvector), identity defaults for Postgres, navigation and FK behaviors (cascade/restrict), and seeds four SubscriptionPlan rows — notably Enterprise has IsUnlimitedTokens = true and a very large AITokenLimit.
## Symbols
- UpdateSubscriptionPlanIsUnlimitedTokens: EF Core migration designer that builds the target EF Core model for the migration UpdateSubscriptionPlanIsUnlimitedTokens; contains the model snapshot/configuration (entities, properties, indexes, relations, and seed data) used by EF migrations.
- BuildTargetModel(): Constructs the EF Core model for this migration: configures entities, properties, constraints, relationships, annotations and seed data.
- Ebook: Represents an uploaded ebook file and metadata belonging to a user/tenant.
- KnowledgeUnit: Represents a chunk of semantic content with vector embedding and metadata for tenant/source.
- KnowledgeUnitLink: Represents a directed relation/link between knowledge units.
- NexusUser: Application user entity (extends IdentityUser style) with AI token tracking and subscription reference.
- QuizResult: Stores quiz completion results for a user and tenant.
- SemanticKnowledgeCache: Caches semantic embedding results with original text, model and tenant scoping.
- SubscriptionPlan: Represents subscription tiers including AI token limits and a flag for unlimited tokens; seeded with default plans.
## Dependencies
- No resolved dependencies.
## Calls
- No resolved calls.
## Unresolved References
- dependency-target: NexusReader.Data.Persistence/AppDbContext (referenced in [DbContext(typeof(AppDbContext))])
## Coverage
- Symbols: 9
- Executable symbols: 1
- Executable symbols with control flow: 1
- Grounded edges: 9
- Unresolved references: 1
- Control-flow fragments: 1
- Unresolved jumps: 0
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 2
- Generated diagrams: 2
## Control Flow Fragments
- BuildTargetModel: 19 nodes, 18 edges, 0 jumps, 0 unsupported constructs
## Diagrams
### 20260506184227_UpdateSubscriptionPlanIsUnlimitedTokens.Designer Neighborhood
```mermaid
flowchart LR
class_1jcp5tl_updatesubscriptionplanisunlimitedtokens("UpdateSubscriptionPlanIsUnlimitedTokens")
file_1psv1cv_20260506184227_updatesubscriptionplanisunlimited("20260506184227_UpdateSubscriptionPlanIsUnlimitedTokens.Designer")
method_e4n4cn_buildtargetmodel[["BuildTargetModel()"]]
type_1djp2cc_subscriptionplan[/"SubscriptionPlan"/]
type_4o1nar_semanticknowledgecache[/"SemanticKnowledgeCache"/]
type_5xf7z1_knowledgeunitlink[/"KnowledgeUnitLink"/]
type_bldst0_nexususer[/"NexusUser"/]
type_brf3z8_knowledgeunit[/"KnowledgeUnit"/]
type_d7ymkn_quizresult[/"QuizResult"/]
type_mdf15q_ebook[/"Ebook"/]
```
### 20260506184227_UpdateSubscriptionPlanIsUnlimitedTokens.Designer Execution Overview
```mermaid
flowchart TD
class_1jcp5tl_updatesubscriptionplanisunlimitedtokens("UpdateSubscriptionPlanIsUnlimitedTokens")
method_e4n4cn_buildtargetmodel[["BuildTargetModel()"]]
class_1jcp5tl_updatesubscriptionplanisunlimitedtokens -->|contains| method_e4n4cn_buildtargetmodel
```
## Diagram Validation
- Status: pass
@@ -0,0 +1,76 @@
# 20260506184227_UpdateSubscriptionPlanIsUnlimitedTokens
- File ID: file:1y1rue2:20260506184227-updatesubscriptionplanisunlimited
- Path: NexusReader.Data/Migrations/20260506184227_UpdateSubscriptionPlanIsUnlimitedTokens.cs
- Role: database-config
- Layer: data
## Purpose
EF Core migration that adds an IsUnlimitedTokens column to the SubscriptionPlans table and adjusts seeded SubscriptionPlans data (AITokenLimit and StripeProductId) to reflect the new column; reversible via Down.
## Key Details
Adds non-nullable boolean IsUnlimitedTokens (default false) and updates seeded plans: Id=1 -> smaller token limit and free product id, Id=4 -> very large token limit with IsUnlimitedTokens=true; Down reverses these changes.
## Symbols
- UpdateSubscriptionPlanIsUnlimitedTokens: EF Core migration that adds an IsUnlimitedTokens column to the SubscriptionPlans table and adjusts seeded SubscriptionPlans data (AITokenLimit and StripeProductId) to reflect the new column; reversible via Down.
- Up(): Apply the migration: add IsUnlimitedTokens column to SubscriptionPlans and update seeded data for multiple plan rows.
- Down(): Revert the migration: remove IsUnlimitedTokens column and restore previous seeded SubscriptionPlans values.
- UpdateSubscriptionPlanIsUnlimitedTokens: EF Core Migration type that encapsulates schema and seed-data changes to SubscriptionPlans.
## Dependencies
- No resolved dependencies.
## Calls
- No resolved calls.
## Coverage
- Symbols: 4
- Executable symbols: 2
- Executable symbols with control flow: 2
- Grounded edges: 4
- Unresolved references: 0
- Control-flow fragments: 2
- Unresolved jumps: 0
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 2
- Generated diagrams: 2
## Control Flow Fragments
- Up: 7 nodes, 6 edges, 0 jumps, 0 unsupported constructs
- Down: 5 nodes, 4 edges, 0 jumps, 0 unsupported constructs
## Diagrams
### 20260506184227_UpdateSubscriptionPlanIsUnlimitedTokens Neighborhood
```mermaid
flowchart LR
class_588td0_updatesubscriptionplanisunlimitedtokens("UpdateSubscriptionPlanIsUnlimitedTokens")
file_1y1rue2_20260506184227_updatesubscriptionplanisunlimited("20260506184227_UpdateSubscriptionPlanIsUnlimitedTokens")
method_1pxp1t3_up[["Up()"]]
method_3zfaqn_down[["Down()"]]
type_bqctk6_updatesubscriptionplanisunlimitedtokens[/"UpdateSubscriptionPlanIsUnlimitedTokens"/]
```
### 20260506184227_UpdateSubscriptionPlanIsUnlimitedTokens Execution Overview
```mermaid
flowchart TD
class_588td0_updatesubscriptionplanisunlimitedtokens("UpdateSubscriptionPlanIsUnlimitedTokens")
method_1pxp1t3_up[["Up()"]]
method_3zfaqn_down[["Down()"]]
class_588td0_updatesubscriptionplanisunlimitedtokens -->|contains| method_1pxp1t3_up
class_588td0_updatesubscriptionplanisunlimitedtokens -->|contains| method_3zfaqn_down
```
## Diagram Validation
- Status: pass
@@ -0,0 +1,91 @@
# 20260510151022_NormalizeAuthor.Designer
- File ID: file:1jljncb:20260510151022-normalizeauthor-designer-cs
- Path: NexusReader.Data/Migrations/20260510151022_NormalizeAuthor.Designer.cs
- Role: database-config
- Layer: data
## Purpose
EF Core migration designer snapshot that defines the target database model for the "NormalizeAuthor" migration: maps entities, properties, keys, indices, relationships, and seed data used by migrations at runtime.
## Key Details
This auto-generated migration designer captures the complete EF Core model snapshot for the NormalizeAuthor migration: it configures Postgres vector extension, identity defaults, entity schemas, FK relationships and seeds subscription plans (Free/Basic/Pro/Enterprise).
## Symbols
- NormalizeAuthor: EF Core migration designer snapshot that defines the target database model for the "NormalizeAuthor" migration: maps entities, properties, keys, indices, relationships, and seed data used by migrations at runtime.
- BuildTargetModel(): Builds the EF Core model snapshot for this migration: adds annotations, DB extensions, defines all entity mappings (tables, columns, keys, indices), relationships, navigations, and seed data.
- Author: Represents an ebook author; mapped to Authors table.
- Ebook: Represents an ebook record with owner, author, and tenant scoping.
- KnowledgeUnit: Stores extracted semantic units with vector embeddings for similarity search.
- KnowledgeUnitLink: Represents directed relations between knowledge units.
- NexusUser: Application user record mapped to AspNetUsers with tenant and subscription data.
- SubscriptionPlan: Represents subscription tiers and token limits; seeded with default plans.
- SemanticKnowledgeCache: Caches computed semantic responses and embedding vector for quick retrieval.
- QuizResult: Stores quiz results per user and tenant.
## Dependencies
- No resolved dependencies.
## Calls
- No resolved calls.
## Unresolved References
- dependency-target: NexusReader.Data.Persistence (AppDbContext reference via attribute)
- dependency-target: Npgsql.EntityFrameworkCore.PostgreSQL (extension usage)
- dependency-target: Pgvector (Vector type usage)
## Coverage
- Symbols: 10
- Executable symbols: 1
- Executable symbols with control flow: 1
- Grounded edges: 10
- Unresolved references: 3
- Control-flow fragments: 1
- Unresolved jumps: 0
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 2
- Generated diagrams: 2
## Control Flow Fragments
- BuildTargetModel: 14 nodes, 14 edges, 0 jumps, 0 unsupported constructs
## Diagrams
### 20260510151022_NormalizeAuthor.Designer Neighborhood
```mermaid
flowchart LR
class_1l7wkbd_normalizeauthor("NormalizeAuthor")
file_1jljncb_20260510151022_normalizeauthor_designer_cs("20260510151022_NormalizeAuthor.Designer")
method_b38ztv_buildtargetmodel[["BuildTargetModel()"]]
type_16wzuux_nexususer[/"NexusUser"/]
type_19fc1gq_ebook[/"Ebook"/]
type_1nn41cx_knowledgeunitlink[/"KnowledgeUnitLink"/]
type_1trrs3x_author[/"Author"/]
type_brf48c_subscriptionplan[/"SubscriptionPlan"/]
type_mla8ro_knowledgeunit[/"KnowledgeUnit"/]
type_n866i0_quizresult[/"QuizResult"/]
type_nk74zf_semanticknowledgecache[/"SemanticKnowledgeCache"/]
```
### 20260510151022_NormalizeAuthor.Designer Execution Overview
```mermaid
flowchart TD
class_1l7wkbd_normalizeauthor("NormalizeAuthor")
method_b38ztv_buildtargetmodel[["BuildTargetModel()"]]
class_1l7wkbd_normalizeauthor -->|contains| method_b38ztv_buildtargetmodel
```
## Diagram Validation
- Status: pass
@@ -0,0 +1,76 @@
# 20260510151022_NormalizeAuthor
- File ID: file:13u663i:20260510151022-normalizeauthor-cs
- Path: NexusReader.Data/Migrations/20260510151022_NormalizeAuthor.cs
- Role: database-config
- Layer: data
## Purpose
EF Core migration that normalizes authors by replacing an Author string column on Ebooks with an Authors table and an AuthorId FK, and provides the inverse Down migration.
## Key Details
This migration normalizes author storage by introducing an Authors table and an AuthorId FK on Ebooks (non-nullable, default 0) and sets referential action to Restrict. Down reverses these changes and restores the Author string column with max length 255.
## Symbols
- NormalizeAuthor: EF Core migration that normalizes authors by replacing an Author string column on Ebooks with an Authors table and an AuthorId FK, and provides the inverse Down migration.
- Up(): Apply schema changes: remove Ebooks.Author string, add Ebooks.AuthorId int, create Authors table, create index and foreign key.
- Down(): Revert the Up changes: drop FK, drop Authors table, drop index and AuthorId column, and re-add Ebooks.Author string column.
- NormalizeAuthor: EF Core migration class that applies and reverts schema normalization for authors.
## Dependencies
- No resolved dependencies.
## Calls
- No resolved calls.
## Coverage
- Symbols: 4
- Executable symbols: 2
- Executable symbols with control flow: 2
- Grounded edges: 4
- Unresolved references: 0
- Control-flow fragments: 2
- Unresolved jumps: 0
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 2
- Generated diagrams: 2
## Control Flow Fragments
- Up: 7 nodes, 6 edges, 0 jumps, 0 unsupported constructs
- Down: 7 nodes, 6 edges, 0 jumps, 0 unsupported constructs
## Diagrams
### 20260510151022_NormalizeAuthor Neighborhood
```mermaid
flowchart LR
class_1j6dl20_normalizeauthor("NormalizeAuthor")
file_13u663i_20260510151022_normalizeauthor_cs("20260510151022_NormalizeAuthor")
method_5tn4c6_up[["Up()"]]
method_wcoxzi_down[["Down()"]]
type_1p2z625_normalizeauthor[/"NormalizeAuthor"/]
```
### 20260510151022_NormalizeAuthor Execution Overview
```mermaid
flowchart TD
class_1j6dl20_normalizeauthor("NormalizeAuthor")
method_5tn4c6_up[["Up()"]]
method_wcoxzi_down[["Down()"]]
class_1j6dl20_normalizeauthor -->|contains| method_5tn4c6_up
class_1j6dl20_normalizeauthor -->|contains| method_wcoxzi_down
```
## Diagram Validation
- Status: pass
@@ -0,0 +1,92 @@
# 20260510161155_AddEbookProgressAndChapter.Designer
- File ID: file:kwumax:20260510161155-addebookprogressandchapter-design
- Path: NexusReader.Data/Migrations/20260510161155_AddEbookProgressAndChapter.Designer.cs
- Role: database-config
- Layer: data
## Purpose
EF Core migration designer: describes the target EF Core model state for the migration named AddEbookProgressAndChapter (schema, entity mappings, relationships, indices, and seed data).
## Key Details
Migration designer configures Postgres vector extension and vector columns, identity-by-default columns, many tenant-scoped entities, FK relationships and indexes, and seeds SubscriptionPlans (Free/Basic/Pro/Enterprise). File is auto-generated by EF Core migrations and represents model snapshot for migration 20260510161155.
## Symbols
- AddEbookProgressAndChapter: EF Core migration designer: describes the target EF Core model state for the migration named AddEbookProgressAndChapter (schema, entity mappings, relationships, indices, and seed data).
- BuildTargetModel(): Constructs the EF Core model: registers Postgres vector extension, identity and domain entities, their properties, relationships, indices and seed data for SubscriptionPlans.
- Ebook (model configured): Represents an ebook record tracked per user/tenant with reading progress and last chapter metadata.
- KnowledgeUnit (model configured): Stores text chunks with vector embeddings and tenant/source metadata for semantic search.
- KnowledgeUnitLink (model configured): Represents directed relations between KnowledgeUnits (source -> target) with relation type.
- NexusUser (model configured): Application user with subscription & usage tracking fields plus identity columns.
- SubscriptionPlan (model configured): Defines available subscription tiers and token limits; seeded with default plans.
- SemanticKnowledgeCache (model configured): Cache of semantic embeddings and JSON response data per tenant and model/version to avoid recomputation.
- Author (model configured): Book author with a collection of Ebooks.
- QuizResult (model configured): User quiz attempt result tied to tenant and user.
## Dependencies
- imports NexusReader.Data/Persistence/AppDbContext.cs
## Calls
- No resolved calls.
## Unresolved References
- dependency-target: Pgvector (external)
- dependency-target: Npgsql.EntityFrameworkCore.PostgreSQL (external)
## Coverage
- Symbols: 10
- Executable symbols: 1
- Executable symbols with control flow: 1
- Grounded edges: 11
- Unresolved references: 2
- Control-flow fragments: 1
- Unresolved jumps: 0
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 2
- Generated diagrams: 2
## Control Flow Fragments
- BuildTargetModel: 13 nodes, 12 edges, 0 jumps, 0 unsupported constructs
## Diagrams
### 20260510161155_AddEbookProgressAndChapter.Designer Neighborhood
```mermaid
flowchart LR
class_1eh84ev_addebookprogressandchapter("AddEbookProgressAndChapter")
file_kwumax_20260510161155_addebookprogressandchapter_design("20260510161155_AddEbookProgressAndChapter.Designer")
method_145q8gt_buildtargetmodel[["BuildTargetModel()"]]
file_1pacvtg_appdbcontext_cs[/"AppDbContext"/]
type_12mtiix_knowledgeunitlink_model_configured[/"KnowledgeUnitLink (model configured)"/]
type_1d5hut9_author_model_configured[/"Author (model configured)"/]
type_1p6mlsn_nexususer_model_configured[/"NexusUser (model configured)"/]
type_1w5eq5k_semanticknowledgecache_model_configured[/"SemanticKnowledgeCache (model configured)"/]
type_mrafiy_subscriptionplan_model_configured[/"SubscriptionPlan (model configured)"/]
type_q2ghu0_ebook_model_configured[/"Ebook (model configured)"/]
type_vznymy_knowledgeunit_model_configured[/"KnowledgeUnit (model configured)"/]
type_xrqv0u_quizresult_model_configured[/"QuizResult (model configured)"/]
file_kwumax_20260510161155_addebookprogressandchapter_design -->|AppDbContext| file_1pacvtg_appdbcontext_cs
```
### 20260510161155_AddEbookProgressAndChapter.Designer Execution Overview
```mermaid
flowchart TD
class_1eh84ev_addebookprogressandchapter("AddEbookProgressAndChapter")
method_145q8gt_buildtargetmodel[["BuildTargetModel()"]]
class_1eh84ev_addebookprogressandchapter -->|contains| method_145q8gt_buildtargetmodel
```
## Diagram Validation
- Status: pass
@@ -0,0 +1,74 @@
# 20260510161155_AddEbookProgressAndChapter
- File ID: file:1orks5g:20260510161155-addebookprogressandchapter-cs
- Path: NexusReader.Data/Migrations/20260510161155_AddEbookProgressAndChapter.cs
- Role: database-config
- Layer: data
## Purpose
EF Core migration that adds two columns (LastChapter, Progress) to the Ebooks table and provides a Down method to remove them.
## Key Details
Adds a nullable string LastChapter (max 255) and a non-nullable double Progress with default 0.0 to the Ebooks table; Down removes both columns.
## Symbols
- AddEbookProgressAndChapter: EF Core migration that adds two columns (LastChapter, Progress) to the Ebooks table and provides a Down method to remove them.
- Up(): Applies schema changes: adds LastChapter (string) and Progress (double) columns to the Ebooks table.
- Down(): Reverts schema changes applied in Up by dropping LastChapter and Progress columns from the Ebooks table.
## Dependencies
- No resolved dependencies.
## Calls
- No resolved calls.
## Coverage
- Symbols: 3
- Executable symbols: 2
- Executable symbols with control flow: 2
- Grounded edges: 3
- Unresolved references: 0
- Control-flow fragments: 2
- Unresolved jumps: 0
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 2
- Generated diagrams: 2
## Control Flow Fragments
- Up: 4 nodes, 3 edges, 0 jumps, 0 unsupported constructs
- Down: 4 nodes, 3 edges, 0 jumps, 0 unsupported constructs
## Diagrams
### 20260510161155_AddEbookProgressAndChapter Neighborhood
```mermaid
flowchart LR
class_kshwxo_addebookprogressandchapter("AddEbookProgressAndChapter")
file_1orks5g_20260510161155_addebookprogressandchapter_cs("20260510161155_AddEbookProgressAndChapter")
method_1cxxeft_up[["Up()"]]
method_xctw2t_down[["Down()"]]
```
### 20260510161155_AddEbookProgressAndChapter Execution Overview
```mermaid
flowchart TD
class_kshwxo_addebookprogressandchapter("AddEbookProgressAndChapter")
method_1cxxeft_up[["Up()"]]
method_xctw2t_down[["Down()"]]
class_kshwxo_addebookprogressandchapter -->|contains| method_1cxxeft_up
class_kshwxo_addebookprogressandchapter -->|contains| method_xctw2t_down
```
## Diagram Validation
- Status: pass
@@ -0,0 +1,91 @@
# 20260510171941_AddEbookLastChapterIndex.Designer
- File ID: file:la4sdl:20260510171941-addebooklastchapterindex-designer
- Path: NexusReader.Data/Migrations/20260510171941_AddEbookLastChapterIndex.Designer.cs
- Role: database-config
- Layer: data
## Purpose
EF Core migration designer file that captures the target model snapshot for the AddEbookLastChapterIndex migration; used by EF Core to recreate the model/state for migrations and tooling.
## Key Details
Auto-generated EF Core migration designer that sets Postgres vector extension, identity defaults, defines schema for identity and domain entities, configures relationships and indexes, and seeds SubscriptionPlan records (Free, Basic, Pro, Enterprise).
## Symbols
- AddEbookLastChapterIndex: EF Core migration designer file that captures the target model snapshot for the AddEbookLastChapterIndex migration; used by EF Core to recreate the model/state for migrations and tooling.
- BuildTargetModel(): Builds the EF Core model snapshot: configures entity types, properties, indexes, relationships, annotations and seed data for the target database model.
- AddEbookLastChapterIndex: Partial EF Core Migration designer class representing the AddEbookLastChapterIndex migration and its model snapshot.
## Dependencies
- imports NexusReader.Data/Persistence/AppDbContext.cs
- imports NexusReader.Domain/Entities/Ebook.cs
- imports NexusReader.Domain/Entities/NexusUser.cs
- imports NexusReader.Domain/Entities/SubscriptionPlan.cs
- imports NexusReader.Domain/Entities/KnowledgeUnit.cs
- imports NexusReader.Domain/Entities/KnowledgeUnitLink.cs
- imports NexusReader.Domain/Entities/SemanticKnowledgeCache.cs
## Calls
- No resolved calls.
## Coverage
- Symbols: 3
- Executable symbols: 1
- Executable symbols with control flow: 1
- Grounded edges: 10
- Unresolved references: 0
- Control-flow fragments: 1
- Unresolved jumps: 0
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 2
- Generated diagrams: 2
## Control Flow Fragments
- BuildTargetModel: 20 nodes, 19 edges, 0 jumps, 0 unsupported constructs
## Diagrams
### 20260510171941_AddEbookLastChapterIndex.Designer Neighborhood
```mermaid
flowchart LR
class_1ojuflh_addebooklastchapterindex("AddEbookLastChapterIndex")
file_la4sdl_20260510171941_addebooklastchapterindex_designer("20260510171941_AddEbookLastChapterIndex.Designer")
method_1febov1_buildtargetmodel[["BuildTargetModel()"]]
file_1b03oou_subscriptionplan_cs[/"SubscriptionPlan"/]
file_1d4ycw2_semanticknowledgecache_cs[/"SemanticKnowledgeCache"/]
file_1m6x5qy_knowledgeunitlink_cs[/"KnowledgeUnitLink"/]
file_1pacvtg_appdbcontext_cs[/"AppDbContext"/]
file_h6a0xu_knowledgeunit_cs[/"KnowledgeUnit"/]
file_lcvwj6_ebook_cs[/"Ebook"/]
file_xcxh5w_nexususer_cs[/"NexusUser"/]
type_1fj6zpl_addebooklastchapterindex[/"AddEbookLastChapterIndex"/]
file_la4sdl_20260510171941_addebooklastchapterindex_designer -->|SubscriptionPlan| file_1b03oou_subscriptionplan_cs
file_la4sdl_20260510171941_addebooklastchapterindex_designer -->|SemanticKnowledgeCache| file_1d4ycw2_semanticknowledgecache_cs
file_la4sdl_20260510171941_addebooklastchapterindex_designer -->|KnowledgeUnitLink| file_1m6x5qy_knowledgeunitlink_cs
file_la4sdl_20260510171941_addebooklastchapterindex_designer -->|AppDbContext| file_1pacvtg_appdbcontext_cs
file_la4sdl_20260510171941_addebooklastchapterindex_designer -->|KnowledgeUnit| file_h6a0xu_knowledgeunit_cs
file_la4sdl_20260510171941_addebooklastchapterindex_designer -->|Ebook| file_lcvwj6_ebook_cs
file_la4sdl_20260510171941_addebooklastchapterindex_designer -->|NexusUser| file_xcxh5w_nexususer_cs
```
### 20260510171941_AddEbookLastChapterIndex.Designer Execution Overview
```mermaid
flowchart TD
class_1ojuflh_addebooklastchapterindex("AddEbookLastChapterIndex")
method_1febov1_buildtargetmodel[["BuildTargetModel()"]]
class_1ojuflh_addebooklastchapterindex -->|contains| method_1febov1_buildtargetmodel
```
## Diagram Validation
- Status: pass
@@ -0,0 +1,76 @@
# 20260510171941_AddEbookLastChapterIndex
- File ID: file:12mya84:20260510171941-addebooklastchapterindex-cs
- Path: NexusReader.Data/Migrations/20260510171941_AddEbookLastChapterIndex.cs
- Role: database-config
- Layer: data
## Purpose
An Entity Framework Core migration that adds an integer LastChapterIndex column (default 0) to the Ebooks table, and can remove it on rollback.
## Key Details
Adds a non-nullable integer LastChapterIndex column to the Ebooks table with default 0; Down removes it. Located in Data.Migrations namespace as an EF Core Migration.
## Symbols
- AddEbookLastChapterIndex: An Entity Framework Core migration that adds an integer LastChapterIndex column (default 0) to the Ebooks table, and can remove it on rollback.
- Up(): Applies the migration: adds LastChapterIndex (integer, non-nullable, default 0) to the Ebooks table.
- Down(): Reverts the migration: drops the LastChapterIndex column from the Ebooks table.
- AddEbookLastChapterIndex: EF Core migration class representing the schema change that adds/removes LastChapterIndex on Ebooks.
## Dependencies
- No resolved dependencies.
## Calls
- No resolved calls.
## Coverage
- Symbols: 4
- Executable symbols: 2
- Executable symbols with control flow: 2
- Grounded edges: 4
- Unresolved references: 0
- Control-flow fragments: 2
- Unresolved jumps: 0
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 2
- Generated diagrams: 2
## Control Flow Fragments
- Up: 4 nodes, 3 edges, 0 jumps, 0 unsupported constructs
- Down: 3 nodes, 2 edges, 0 jumps, 0 unsupported constructs
## Diagrams
### 20260510171941_AddEbookLastChapterIndex Neighborhood
```mermaid
flowchart LR
class_1kl84eu_addebooklastchapterindex("AddEbookLastChapterIndex")
file_12mya84_20260510171941_addebooklastchapterindex_cs("20260510171941_AddEbookLastChapterIndex")
method_10r2ds4_down[["Down()"]]
method_1lw55w9_up[["Up()"]]
type_1obfu5w_addebooklastchapterindex[/"AddEbookLastChapterIndex"/]
```
### 20260510171941_AddEbookLastChapterIndex Execution Overview
```mermaid
flowchart TD
class_1kl84eu_addebooklastchapterindex("AddEbookLastChapterIndex")
method_10r2ds4_down[["Down()"]]
method_1lw55w9_up[["Up()"]]
class_1kl84eu_addebooklastchapterindex -->|contains| method_10r2ds4_down
class_1kl84eu_addebooklastchapterindex -->|contains| method_1lw55w9_up
```
## Diagram Validation
- Status: pass
@@ -0,0 +1,105 @@
# AppDbContextModelSnapshot
- File ID: file:1yttr8x:appdbcontextmodelsnapshot-cs
- Path: NexusReader.Data/Migrations/AppDbContextModelSnapshot.cs
- Role: database-config
- Layer: data
## Purpose
EF Core model snapshot that records the database model (entities, properties, indexes, relationships, and seed data) for AppDbContext so migrations can compare model changes at runtime.
## Key Details
Contains full schema mapping (properties, types, max lengths, indexes, relationships) plus seed data for SubscriptionPlan (4 entries). The snapshot enables migrations to detect model changes; it's a generated, data-layer artifact and not runtime business logic.
## Symbols
- AppDbContextModelSnapshot: EF Core model snapshot that records the database model (entities, properties, indexes, relationships, and seed data) for AppDbContext so migrations can compare model changes at runtime.
- BuildModel(): Populates the provided ModelBuilder with the full EF Core model: annotations, extensions, entity/property definitions, indexes, relationships, navigations, and seed data used by migrations.
- AppDbContextModelSnapshot: Generated EF Core ModelSnapshot class that captures the compiled model for AppDbContext used by the migrations system.
## Dependencies
- imports NexusReader.Data/Persistence/AppDbContext.cs
- imports NexusReader.Domain/Entities/Author.cs
- imports NexusReader.Domain/Entities/Ebook.cs
- imports NexusReader.Domain/Entities/KnowledgeUnit.cs
- imports NexusReader.Domain/Entities/KnowledgeUnitLink.cs
- imports NexusReader.Domain/Entities/NexusUser.cs
- imports NexusReader.Domain/Entities/QuizResult.cs
- imports NexusReader.Domain/Entities/SemanticKnowledgeCache.cs
- imports NexusReader.Domain/Entities/SubscriptionPlan.cs
## Calls
- No resolved calls.
## Coverage
- Symbols: 3
- Executable symbols: 1
- Executable symbols with control flow: 1
- Grounded edges: 12
- Unresolved references: 0
- Control-flow fragments: 1
- Unresolved jumps: 0
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 2
- Generated diagrams: 2
## Control Flow Fragments
- BuildModel: 31 nodes, 30 edges, 0 jumps, 0 unsupported constructs
## Diagrams
### AppDbContextModelSnapshot Neighborhood
_Warnings: diagram file_1yttr8x_appdbcontextmodelsnapshot_cs_neighborhood_view exceeds preferred complexity thresholds (13 nodes, 9 edges)._
```mermaid
---
config:
flowchart:
defaultRenderer: "elk"
---
flowchart LR
class_1v2rkom_appdbcontextmodelsnapshot("AppDbContextModelSnapshot")
file_1yttr8x_appdbcontextmodelsnapshot_cs("AppDbContextModelSnapshot")
method_1nrn8uy_buildmodel[["BuildModel()"]]
file_1b03oou_subscriptionplan_cs[/"SubscriptionPlan"/]
file_1d4ycw2_semanticknowledgecache_cs[/"SemanticKnowledgeCache"/]
file_1m6x5qy_knowledgeunitlink_cs[/"KnowledgeUnitLink"/]
file_1pacvtg_appdbcontext_cs[/"AppDbContext"/]
file_1wyr0y8_quizresult_cs[/"QuizResult"/]
file_1y56eud_author_cs[/"Author"/]
file_h6a0xu_knowledgeunit_cs[/"KnowledgeUnit"/]
file_lcvwj6_ebook_cs[/"Ebook"/]
file_xcxh5w_nexususer_cs[/"NexusUser"/]
type_11t8gjy_appdbcontextmodelsnapshot[/"AppDbContextModelSnapshot"/]
file_1yttr8x_appdbcontextmodelsnapshot_cs -->|SubscriptionPlan| file_1b03oou_subscriptionplan_cs
file_1yttr8x_appdbcontextmodelsnapshot_cs -->|SemanticKnowledgeCache| file_1d4ycw2_semanticknowledgecache_cs
file_1yttr8x_appdbcontextmodelsnapshot_cs -->|KnowledgeUnitLink| file_1m6x5qy_knowledgeunitlink_cs
file_1yttr8x_appdbcontextmodelsnapshot_cs -->|AppDbContext| file_1pacvtg_appdbcontext_cs
file_1yttr8x_appdbcontextmodelsnapshot_cs -->|QuizResult| file_1wyr0y8_quizresult_cs
file_1yttr8x_appdbcontextmodelsnapshot_cs -->|Author| file_1y56eud_author_cs
file_1yttr8x_appdbcontextmodelsnapshot_cs -->|KnowledgeUnit| file_h6a0xu_knowledgeunit_cs
file_1yttr8x_appdbcontextmodelsnapshot_cs -->|Ebook| file_lcvwj6_ebook_cs
file_1yttr8x_appdbcontextmodelsnapshot_cs -->|NexusUser| file_xcxh5w_nexususer_cs
```
### AppDbContextModelSnapshot Execution Overview
```mermaid
flowchart TD
class_1v2rkom_appdbcontextmodelsnapshot("AppDbContextModelSnapshot")
method_1nrn8uy_buildmodel[["BuildModel()"]]
class_1v2rkom_appdbcontextmodelsnapshot -->|contains| method_1nrn8uy_buildmodel
```
## Diagram Validation
- Status: warn
- Warning: neighborhood-view: diagram file_1yttr8x_appdbcontextmodelsnapshot_cs_neighborhood_view exceeds preferred complexity thresholds (13 nodes, 9 edges).
@@ -0,0 +1,66 @@
# NexusReader.Data
- File ID: file:bk6gk1:nexusreader-data-csproj
- Path: NexusReader.Data/NexusReader.Data.csproj
- Role: config
- Layer: data
## Purpose
Defines the .NET project configuration for the NexusReader.Data assembly, declaring target framework, NuGet package dependencies (EF Core, providers, configuration packages, Pgvector) and a project reference to the domain project.
## Key Details
TargetFramework net10.0 (line 4); implicit usings enabled and nullable enabled (lines 5-6); multiple EF Core providers and config packages declared; design package marked PrivateAssets; project references NexusReader.Domain for domain models (line 25).
## Symbols
- No extracted symbols.
## Dependencies
- No resolved dependencies.
## Calls
- No resolved calls.
## Unresolved References
- dependency-target: [object Object]
- dependency-target: [object Object]
- dependency-target: [object Object]
- dependency-target: [object Object]
- dependency-target: [object Object]
- dependency-target: [object Object]
- dependency-target: [object Object]
- dependency-target: [object Object]
- dependency-target: [object Object]
- dependency-target: [object Object]
## Coverage
- Symbols: 0
- Executable symbols: 0
- Executable symbols with control flow: 0
- Grounded edges: 0
- Unresolved references: 10
- Control-flow fragments: 0
- Unresolved jumps: 0
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 1
- Generated diagrams: 1
## Diagrams
### NexusReader.Data Neighborhood
```mermaid
flowchart LR
file_bk6gk1_nexusreader_data_csproj("NexusReader.Data")
```
## Diagram Validation
- Status: pass
@@ -0,0 +1,191 @@
# AppDbContext
- File ID: file:1pacvtg:appdbcontext-cs
- Path: NexusReader.Data/Persistence/AppDbContext.cs
- Role: database-config
- Layer: data
## Purpose
Defines the Entity Framework Core database context for the application: DbSet surface, EF configuration, model mapping (indexes, FKs, delete behavior), provider-specific type mapping, and deterministic seed data for subscription plans.
## Key Details
Important runtime behaviors: suppresses PendingModelChangesWarning (OnConfiguring), conditional provider-specific mapping for vector embeddings and HNSW index when PostgreSQL is used (lines 58-63), and seeds SubscriptionPlan rows with fixed IDs (lines 121-127) to ensure deterministic plan IDs.
## Symbols
- AppDbContext: Defines the Entity Framework Core database context for the application: DbSet surface, EF configuration, model mapping (indexes, FKs, delete behavior), provider-specific type mapping, and deterministic seed data for subscription plans.
- AppDbContext(): Constructs the EF DbContext with provided options.
- OnConfiguring(): Performs additional EF configuration; suppresses a pending-model-changes warning to avoid runtime exceptions in some environments.
- SemanticKnowledgeCache (DbSet property): Exposes the DbSet for SemanticKnowledgeCache entities.
- KnowledgeUnits (DbSet property): Exposes the DbSet for KnowledgeUnit entities.
- KnowledgeUnitLinks (DbSet property): Exposes the DbSet for KnowledgeUnitLink entities.
- Ebooks (DbSet property): Exposes the DbSet for Ebook entities.
- QuizResults (DbSet property): Exposes the DbSet for QuizResult entities.
- SubscriptionPlans (DbSet property): Exposes the DbSet for SubscriptionPlan entities.
- Authors (DbSet property): Exposes the DbSet for Author entities.
- OnModelCreating(): Configures EF model mappings: entity properties, indexes, relationships, provider-specific column types, and seeds subscription plans with deterministic IDs.
- AppDbContext: EF Core DbContext for application persistence, extending IdentityDbContext for user identity and domain entities.
## Dependencies
- No resolved dependencies.
## Calls
- No resolved calls.
## Unresolved References
- dependency-target: NexusReader.Domain/Entities (referenced via using NexusReader.Domain.Entities at line 3)
- dependency-target: Microsoft.EntityFrameworkCore (EF Core usage evident)
## Coverage
- Symbols: 12
- Executable symbols: 10
- Executable symbols with control flow: 10
- Grounded edges: 12
- Unresolved references: 2
- Control-flow fragments: 10
- Unresolved jumps: 0
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 2
- Generated diagrams: 3
## Control Flow Fragments
- AppDbContext: 3 nodes, 2 edges, 0 jumps, 0 unsupported constructs
- OnConfiguring: 4 nodes, 3 edges, 0 jumps, 0 unsupported constructs
- SemanticKnowledgeCache (DbSet property): 3 nodes, 2 edges, 0 jumps, 0 unsupported constructs
- KnowledgeUnits (DbSet property): 3 nodes, 2 edges, 0 jumps, 0 unsupported constructs
- KnowledgeUnitLinks (DbSet property): 3 nodes, 2 edges, 0 jumps, 0 unsupported constructs
- Ebooks (DbSet property): 3 nodes, 2 edges, 0 jumps, 0 unsupported constructs
- QuizResults (DbSet property): 3 nodes, 2 edges, 0 jumps, 0 unsupported constructs
- SubscriptionPlans (DbSet property): 3 nodes, 2 edges, 0 jumps, 0 unsupported constructs
- Authors (DbSet property): 3 nodes, 2 edges, 0 jumps, 0 unsupported constructs
- OnModelCreating: 23 nodes, 25 edges, 0 jumps, 0 unsupported constructs
## Diagrams
### AppDbContext Neighborhood
_Warnings: diagram file_1pacvtg_appdbcontext_cs_neighborhood_view exceeds preferred complexity thresholds (13 nodes, 0 edges)._
```mermaid
---
config:
flowchart:
defaultRenderer: "elk"
---
flowchart LR
class_wtyati_appdbcontext("AppDbContext")
file_1pacvtg_appdbcontext_cs("AppDbContext")
method_1jwlkph_knowledgeunitlinks_dbset_property[["KnowledgeUnitLinks (DbSet property)"]]
method_1of3kqt_onmodelcreating[["OnModelCreating()"]]
method_1r4sskm_authors_dbset_property[["Authors (DbSet property)"]]
method_1v6tqnu_semanticknowledgecache_dbset_property[["SemanticKnowledgeCache (DbSet property)"]]
method_1wn8qlw_onconfiguring[["OnConfiguring()"]]
method_cfsfui_ebooks_dbset_property[["Ebooks (DbSet property)"]]
method_cusclc_subscriptionplans_dbset_property[["SubscriptionPlans (DbSet property)"]]
method_ex6nhz_appdbcontext[["AppDbContext()"]]
method_w8lt4l_quizresults_dbset_property[["QuizResults (DbSet property)"]]
method_zj5uq4_knowledgeunits_dbset_property[["KnowledgeUnits (DbSet property)"]]
type_c5amk9_appdbcontext[/"AppDbContext"/]
```
### AppDbContext Execution Overview
```mermaid
flowchart TD
class_wtyati_appdbcontext("AppDbContext")
method_1jwlkph_knowledgeunitlinks_dbset_property[["KnowledgeUnitLinks (DbSet property)"]]
method_1of3kqt_onmodelcreating[["OnModelCreating()"]]
method_1r4sskm_authors_dbset_property[["Authors (DbSet property)"]]
method_1v6tqnu_semanticknowledgecache_dbset_property[["SemanticKnowledgeCache (DbSet property)"]]
method_1wn8qlw_onconfiguring[["OnConfiguring()"]]
method_cfsfui_ebooks_dbset_property[["Ebooks (DbSet property)"]]
method_cusclc_subscriptionplans_dbset_property[["SubscriptionPlans (DbSet property)"]]
method_ex6nhz_appdbcontext[["AppDbContext()"]]
method_w8lt4l_quizresults_dbset_property[["QuizResults (DbSet property)"]]
method_zj5uq4_knowledgeunits_dbset_property[["KnowledgeUnits (DbSet property)"]]
class_wtyati_appdbcontext -->|contains| method_1jwlkph_knowledgeunitlinks_dbset_property
class_wtyati_appdbcontext -->|contains| method_1of3kqt_onmodelcreating
class_wtyati_appdbcontext -->|contains| method_1r4sskm_authors_dbset_property
class_wtyati_appdbcontext -->|contains| method_1v6tqnu_semanticknowledgecache_dbset_property
class_wtyati_appdbcontext -->|contains| method_1wn8qlw_onconfiguring
class_wtyati_appdbcontext -->|contains| method_cfsfui_ebooks_dbset_property
class_wtyati_appdbcontext -->|contains| method_cusclc_subscriptionplans_dbset_property
class_wtyati_appdbcontext -->|contains| method_ex6nhz_appdbcontext
class_wtyati_appdbcontext -->|contains| method_w8lt4l_quizresults_dbset_property
class_wtyati_appdbcontext -->|contains| method_zj5uq4_knowledgeunits_dbset_property
```
### OnModelCreating() Control Flow
_Warnings: diagram method_1of3kqt_onmodelcreating__fragment_diagram exceeds preferred complexity thresholds (23 nodes, 25 edges)._
```mermaid
---
config:
flowchart:
defaultRenderer: "elk"
---
flowchart TD
method_1of3kqt_onmodelcreating__action_111_entity_configuration_111__linear("QuizResult relationship and index")
method_1of3kqt_onmodelcreating__action_121_data_seed_121__linear("Seed SubscriptionPlan rows with deterministic IDs")
method_1of3kqt_onmodelcreating__action_30_framework_call_30__linear("Calls base OnModelCreating")
method_1of3kqt_onmodelcreating__action_32_entity_configuration_32__linear("NexusUser property & index mapping")
method_1of3kqt_onmodelcreating__action_48_entity_configuration_48__linear("SubscriptionPlan unique index")
method_1of3kqt_onmodelcreating__action_53_entity_configuration_53__linear("SemanticKnowledgeCache key/index and provider-specific embedding handling")
method_1of3kqt_onmodelcreating__action_58_branch_58__condition{"Database.IsNpgsql()"}
method_1of3kqt_onmodelcreating__action_58_branch_58__false("other-db-path")
method_1of3kqt_onmodelcreating__action_58_branch_58__merge("merge")
method_1of3kqt_onmodelcreating__action_58_branch_58__true("postgresql-path")
method_1of3kqt_onmodelcreating__action_58_onmodelcreating_branch_58_0__condition{"Database.IsNpgsql()"}
method_1of3kqt_onmodelcreating__action_58_onmodelcreating_branch_58_0__false("false")
method_1of3kqt_onmodelcreating__action_58_onmodelcreating_branch_58_0__merge("merge")
method_1of3kqt_onmodelcreating__action_58_onmodelcreating_branch_58_0__true("true")
method_1of3kqt_onmodelcreating__action_64_onmodelcreating_fallback_64_1__condition{"Falls back to alternate path"}
method_1of3kqt_onmodelcreating__action_64_onmodelcreating_fallback_64_1__false("otherwise")
method_1of3kqt_onmodelcreating__action_64_onmodelcreating_fallback_64_1__merge("merge")
method_1of3kqt_onmodelcreating__action_64_onmodelcreating_fallback_64_1__true("fallback")
method_1of3kqt_onmodelcreating__action_70_entity_configuration_70__linear("KnowledgeUnit keys, indexes, relationship to Ebook")
method_1of3kqt_onmodelcreating__action_82_entity_configuration_82__linear("KnowledgeUnitLink relationships")
method_1of3kqt_onmodelcreating__action_96_entity_configuration_96__linear("Ebook relationships")
method_1of3kqt_onmodelcreating__entry(["OnModelCreating entry"])
method_1of3kqt_onmodelcreating__implicit_return(["return"])
method_1of3kqt_onmodelcreating__action_111_entity_configuration_111__linear -->|next| method_1of3kqt_onmodelcreating__action_121_data_seed_121__linear
method_1of3kqt_onmodelcreating__action_121_data_seed_121__linear -->|return| method_1of3kqt_onmodelcreating__implicit_return
method_1of3kqt_onmodelcreating__action_30_framework_call_30__linear -->|next| method_1of3kqt_onmodelcreating__action_32_entity_configuration_32__linear
method_1of3kqt_onmodelcreating__action_32_entity_configuration_32__linear -->|next| method_1of3kqt_onmodelcreating__action_48_entity_configuration_48__linear
method_1of3kqt_onmodelcreating__action_48_entity_configuration_48__linear -->|next| method_1of3kqt_onmodelcreating__action_53_entity_configuration_53__linear
method_1of3kqt_onmodelcreating__action_53_entity_configuration_53__linear -->|next| method_1of3kqt_onmodelcreating__action_58_branch_58__condition
method_1of3kqt_onmodelcreating__action_58_branch_58__condition -->|other-db-path| method_1of3kqt_onmodelcreating__action_58_branch_58__false
method_1of3kqt_onmodelcreating__action_58_branch_58__condition -->|postgresql-path| method_1of3kqt_onmodelcreating__action_58_branch_58__true
method_1of3kqt_onmodelcreating__action_58_branch_58__false -->|next| method_1of3kqt_onmodelcreating__action_58_branch_58__merge
method_1of3kqt_onmodelcreating__action_58_branch_58__merge -->|next| method_1of3kqt_onmodelcreating__action_58_onmodelcreating_branch_58_0__condition
method_1of3kqt_onmodelcreating__action_58_branch_58__true -->|next| method_1of3kqt_onmodelcreating__action_58_branch_58__merge
method_1of3kqt_onmodelcreating__action_58_onmodelcreating_branch_58_0__condition -->|false| method_1of3kqt_onmodelcreating__action_58_onmodelcreating_branch_58_0__false
method_1of3kqt_onmodelcreating__action_58_onmodelcreating_branch_58_0__condition -->|true| method_1of3kqt_onmodelcreating__action_58_onmodelcreating_branch_58_0__true
method_1of3kqt_onmodelcreating__action_58_onmodelcreating_branch_58_0__false -->|next| method_1of3kqt_onmodelcreating__action_58_onmodelcreating_branch_58_0__merge
method_1of3kqt_onmodelcreating__action_58_onmodelcreating_branch_58_0__merge -->|fallback| method_1of3kqt_onmodelcreating__action_64_onmodelcreating_fallback_64_1__condition
method_1of3kqt_onmodelcreating__action_58_onmodelcreating_branch_58_0__true -->|next| method_1of3kqt_onmodelcreating__action_58_onmodelcreating_branch_58_0__merge
method_1of3kqt_onmodelcreating__action_64_onmodelcreating_fallback_64_1__condition -->|otherwise| method_1of3kqt_onmodelcreating__action_64_onmodelcreating_fallback_64_1__false
method_1of3kqt_onmodelcreating__action_64_onmodelcreating_fallback_64_1__condition -->|fallback| method_1of3kqt_onmodelcreating__action_64_onmodelcreating_fallback_64_1__true
method_1of3kqt_onmodelcreating__action_64_onmodelcreating_fallback_64_1__false -->|next| method_1of3kqt_onmodelcreating__action_64_onmodelcreating_fallback_64_1__merge
method_1of3kqt_onmodelcreating__action_64_onmodelcreating_fallback_64_1__merge -->|next| method_1of3kqt_onmodelcreating__action_70_entity_configuration_70__linear
method_1of3kqt_onmodelcreating__action_64_onmodelcreating_fallback_64_1__true -->|next| method_1of3kqt_onmodelcreating__action_64_onmodelcreating_fallback_64_1__merge
method_1of3kqt_onmodelcreating__action_70_entity_configuration_70__linear -->|next| method_1of3kqt_onmodelcreating__action_82_entity_configuration_82__linear
method_1of3kqt_onmodelcreating__action_82_entity_configuration_82__linear -->|next| method_1of3kqt_onmodelcreating__action_96_entity_configuration_96__linear
method_1of3kqt_onmodelcreating__action_96_entity_configuration_96__linear -->|next| method_1of3kqt_onmodelcreating__action_111_entity_configuration_111__linear
method_1of3kqt_onmodelcreating__entry -->|next| method_1of3kqt_onmodelcreating__action_30_framework_call_30__linear
```
## Diagram Validation
- Status: warn
- Warning: neighborhood-view: diagram file_1pacvtg_appdbcontext_cs_neighborhood_view exceeds preferred complexity thresholds (13 nodes, 0 edges).
- Warning: control-flow: diagram method_1of3kqt_onmodelcreating__fragment_diagram exceeds preferred complexity thresholds (23 nodes, 25 edges).
@@ -0,0 +1,152 @@
# AppDbContextFactory
- File ID: file:1h2hpbe:appdbcontextfactory-cs
- Path: NexusReader.Data/Persistence/AppDbContextFactory.cs
- Role: unknown
- Layer: unknown
## Purpose
Design-time EF Core DbContext factory: locates solution/web project, builds configuration, resolves a Postgres connection (with fallback), configures DbContextOptions (including pgvector) and returns an AppDbContext for design-time tooling (migrations, scaffolding).
## Key Details
Searches upward for NexusReader.slnx to locate Web project's appsettings, supports environment-specific appsettings, falls back to a hard-coded Postgres connection for design-time scenarios, and enables pgvector via UseVector().
## Symbols
- AppDbContextFactory: Design-time EF Core DbContext factory: locates solution/web project, builds configuration, resolves a Postgres connection (with fallback), configures DbContextOptions (including pgvector) and returns an AppDbContext for design-time tooling (migrations, scaffolding).
- CreateDbContext(): Creates and configures an AppDbContext for design-time use by reading environment, locating the Web project for configuration files, resolving a connection string (with fallback), applying Npgsql + pgvector options, and returning the context.
- AppDbContextFactory: Design-time factory to create AppDbContext instances for EF Core tooling.
## Dependencies
- imports NexusReader.Data/Persistence/AppDbContext.cs
## Calls
- No resolved calls.
## Unresolved References
- call-target: NexusReader.Data/Persistence/AppDbContext.cs
## Coverage
- Symbols: 3
- Executable symbols: 1
- Executable symbols with control flow: 1
- Grounded edges: 4
- Unresolved references: 1
- Control-flow fragments: 1
- Unresolved jumps: 1
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 2
- Generated diagrams: 3
## Control Flow Fragments
- CreateDbContext: 27 nodes, 31 edges, 1 jumps, 0 unsupported constructs
## Diagrams
### AppDbContextFactory Neighborhood
```mermaid
flowchart LR
class_1g09xpu_appdbcontextfactory("AppDbContextFactory")
file_1h2hpbe_appdbcontextfactory_cs("AppDbContextFactory")
method_nwogow_createdbcontext[["CreateDbContext()"]]
file_1pacvtg_appdbcontext_cs[/"AppDbContext"/]
type_1tyno9s_appdbcontextfactory[/"AppDbContextFactory"/]
file_1h2hpbe_appdbcontextfactory_cs -->|AppDbContext| file_1pacvtg_appdbcontext_cs
```
### AppDbContextFactory Execution Overview
```mermaid
flowchart TD
class_1g09xpu_appdbcontextfactory("AppDbContextFactory")
method_nwogow_createdbcontext[["CreateDbContext()"]]
unresolved_unresolved_1tf41qv_call_target{"Unresolved: AppDbContext..ctor"}
class_1g09xpu_appdbcontextfactory -->|contains| method_nwogow_createdbcontext
method_nwogow_createdbcontext -->|unresolved call| unresolved_unresolved_1tf41qv_call_target
```
### CreateDbContext() Control Flow
_Warnings: diagram method_nwogow_createdbcontext__fragment_diagram exceeds preferred complexity thresholds (27 nodes, 31 edges)._
```mermaid
---
config:
flowchart:
defaultRenderer: "elk"
---
flowchart TD
method_nwogow_createdbcontext__call_43_AppDbContext_ctor[["AppDbContext..ctor"]]
method_nwogow_createdbcontext__action_12_env_read_12__linear("Read ASPNETCORE_ENVIRONMENT")
method_nwogow_createdbcontext__action_15_loop_15__loop_body[["while (currentDir != null && !File.Exists(Path.Combine(currentDir.FullName, \\"NexusReader.slnx\\"))) currentDir = currentDir.Parent;"]]
method_nwogow_createdbcontext__action_15_loop_15__loop_entry("Walk up directories to find solution file")
method_nwogow_createdbcontext__action_15_loop_15__loop_exit("exit loop")
method_nwogow_createdbcontext__action_16_createdbcontext_loop_16_0__loop_body[["while (currentDir != null && !File.Exists(Path.Combine(currentDir.FullName, \\"NexusReader.slnx\\")))"]]
method_nwogow_createdbcontext__action_16_createdbcontext_loop_16_0__loop_entry("currentDir != null && !File.Exists(Path.Combine(currentDir.FullName, \\"NexusReader.slnx\\"))")
method_nwogow_createdbcontext__action_16_createdbcontext_loop_16_0__loop_exit("Leaves the loop when the condition no longer holds.")
method_nwogow_createdbcontext__action_21_branch_21__condition{"currentDir != null"}
method_nwogow_createdbcontext__action_21_branch_21__false("use current working directory")
method_nwogow_createdbcontext__action_21_branch_21__merge("merge")
method_nwogow_createdbcontext__action_21_branch_21__true("use src/NexusReader.Web")
method_nwogow_createdbcontext__action_25_config_build_25__linear("Build configuration from appsettings and environment")
method_nwogow_createdbcontext__action_33_call_33__linear("Get connection string")
method_nwogow_createdbcontext__action_35_createdbcontext_branch_35_1__condition{"string.IsNullOrEmpty(connectionString)"}
method_nwogow_createdbcontext__action_35_createdbcontext_branch_35_1__false("false")
method_nwogow_createdbcontext__action_35_createdbcontext_branch_35_1__merge("merge")
method_nwogow_createdbcontext__action_35_createdbcontext_branch_35_1__true("true")
method_nwogow_createdbcontext__action_35_guard_clause_35__condition{"string.IsNullOrEmpty(connectionString)"}
method_nwogow_createdbcontext__action_35_guard_clause_35__false("keep discovered connection")
method_nwogow_createdbcontext__action_35_guard_clause_35__merge("merge")
method_nwogow_createdbcontext__action_35_guard_clause_35__true("assign default Postgres connection")
method_nwogow_createdbcontext__action_41_persistence_config_41__linear("Configure Npgsql with pgvector")
method_nwogow_createdbcontext__entry(["CreateDbContext entry"])
method_nwogow_createdbcontext__action_43_createdbcontext_return_43_2__return(["Returns result"])
method_nwogow_createdbcontext__action_43_return_43__return(["Return configured DbContext"])
method_nwogow_createdbcontext__implicit_return(["return"])
method_nwogow_createdbcontext__action_12_env_read_12__linear -->|next| method_nwogow_createdbcontext__action_15_loop_15__loop_entry
method_nwogow_createdbcontext__action_15_loop_15__loop_body -->|continue| method_nwogow_createdbcontext__action_15_loop_15__loop_entry
method_nwogow_createdbcontext__action_15_loop_15__loop_entry -->|iterate| method_nwogow_createdbcontext__action_15_loop_15__loop_body
method_nwogow_createdbcontext__action_15_loop_15__loop_entry -->|exit| method_nwogow_createdbcontext__action_15_loop_15__loop_exit
method_nwogow_createdbcontext__action_15_loop_15__loop_exit -->|next| method_nwogow_createdbcontext__action_16_createdbcontext_loop_16_0__loop_entry
method_nwogow_createdbcontext__action_16_createdbcontext_loop_16_0__loop_body -->|continue| method_nwogow_createdbcontext__action_16_createdbcontext_loop_16_0__loop_entry
method_nwogow_createdbcontext__action_16_createdbcontext_loop_16_0__loop_entry -->|transforms input| method_nwogow_createdbcontext__action_16_createdbcontext_loop_16_0__loop_body
method_nwogow_createdbcontext__action_16_createdbcontext_loop_16_0__loop_entry -->|Leaves the loop when the condition no longer holds.| method_nwogow_createdbcontext__action_16_createdbcontext_loop_16_0__loop_exit
method_nwogow_createdbcontext__action_16_createdbcontext_loop_16_0__loop_exit -->|next| method_nwogow_createdbcontext__action_21_branch_21__condition
method_nwogow_createdbcontext__action_21_branch_21__condition -->|use current working directory| method_nwogow_createdbcontext__action_21_branch_21__false
method_nwogow_createdbcontext__action_21_branch_21__condition -->|use src / NexusReader.Web| method_nwogow_createdbcontext__action_21_branch_21__true
method_nwogow_createdbcontext__action_21_branch_21__false -->|next| method_nwogow_createdbcontext__action_21_branch_21__merge
method_nwogow_createdbcontext__action_21_branch_21__merge -->|next| method_nwogow_createdbcontext__action_25_config_build_25__linear
method_nwogow_createdbcontext__action_21_branch_21__true -->|next| method_nwogow_createdbcontext__action_21_branch_21__merge
method_nwogow_createdbcontext__action_25_config_build_25__linear -->|next| method_nwogow_createdbcontext__action_33_call_33__linear
method_nwogow_createdbcontext__action_33_call_33__linear -->|next| method_nwogow_createdbcontext__action_35_guard_clause_35__condition
method_nwogow_createdbcontext__action_35_createdbcontext_branch_35_1__condition -->|false| method_nwogow_createdbcontext__action_35_createdbcontext_branch_35_1__false
method_nwogow_createdbcontext__action_35_createdbcontext_branch_35_1__condition -->|true| method_nwogow_createdbcontext__action_35_createdbcontext_branch_35_1__true
method_nwogow_createdbcontext__action_35_createdbcontext_branch_35_1__false -->|next| method_nwogow_createdbcontext__action_35_createdbcontext_branch_35_1__merge
method_nwogow_createdbcontext__action_35_createdbcontext_branch_35_1__merge -->|next| method_nwogow_createdbcontext__action_41_persistence_config_41__linear
method_nwogow_createdbcontext__action_35_createdbcontext_branch_35_1__true -->|next| method_nwogow_createdbcontext__action_35_createdbcontext_branch_35_1__merge
method_nwogow_createdbcontext__action_35_guard_clause_35__condition -->|keep discovered connection| method_nwogow_createdbcontext__action_35_guard_clause_35__false
method_nwogow_createdbcontext__action_35_guard_clause_35__condition -->|assign default Postgres connection| method_nwogow_createdbcontext__action_35_guard_clause_35__true
method_nwogow_createdbcontext__action_35_guard_clause_35__false -->|next| method_nwogow_createdbcontext__action_35_guard_clause_35__merge
method_nwogow_createdbcontext__action_35_guard_clause_35__merge -->|next| method_nwogow_createdbcontext__action_35_createdbcontext_branch_35_1__condition
method_nwogow_createdbcontext__action_35_guard_clause_35__true -->|next| method_nwogow_createdbcontext__action_35_guard_clause_35__merge
method_nwogow_createdbcontext__action_41_persistence_config_41__linear -->|return| method_nwogow_createdbcontext__action_43_createdbcontext_return_43_2__return
method_nwogow_createdbcontext__action_43_createdbcontext_return_43_2__return -->|return| method_nwogow_createdbcontext__action_43_return_43__return
method_nwogow_createdbcontext__action_43_return_43__return -->|optionsBuilder.Options DbContextOptions AppDbContext>| method_nwogow_createdbcontext__call_43_AppDbContext_ctor
method_nwogow_createdbcontext__call_43_AppDbContext_ctor -->|return| method_nwogow_createdbcontext__implicit_return
method_nwogow_createdbcontext__entry -->|next| method_nwogow_createdbcontext__action_12_env_read_12__linear
```
## Diagram Validation
- Status: warn
- Warning: Control-flow extraction left 1 unresolved jumps.
- Warning: control-flow: diagram method_nwogow_createdbcontext__fragment_diagram exceeds preferred complexity thresholds (27 nodes, 31 edges).
@@ -0,0 +1,284 @@
# DbInitializer
- File ID: file:136c3oe:dbinitializer-cs
- Path: NexusReader.Data/Persistence/DbInitializer.cs
- Role: bootstrap
- Layer: data
## Purpose
Database seeder that runs at application startup to ensure initial data (subscription plans, roles, admin user, sample author and ebook) exist in the AppDbContext.
## Key Details
Runs inside a DI scope, creates/uses AppDbContext via IDbContextFactory, performs multiple conditional seeds with SaveChangesAsync calls and top-level exception logging; intended to be executed at app startup to ensure minimal required data exists.
## Symbols
- DbInitializer: Database seeder that runs at application startup to ensure initial data (subscription plans, roles, admin user, sample author and ebook) exist in the AppDbContext.
- SeedAsync(): Create a scoped DbContext and seed initial database data: subscription plans, roles, an admin user (with role), a sample author and an ebook, with logging and error handling.
## Dependencies
- imports NexusReader.Domain/Entities/SubscriptionPlan.cs
- imports NexusReader.Domain/Entities/NexusUser.cs
- imports NexusReader.Domain/Entities/Author.cs
- imports NexusReader.Domain/Entities/Ebook.cs
- imports NexusReader.Data/Persistence/AppDbContext.cs
## Calls
- No resolved calls.
## Unresolved References
- call-target: NexusReader.Domain/Entities/SubscriptionPlan.cs
- call-target: NexusReader.Domain/Entities/NexusUser.cs
- call-target: NexusReader.Domain/Entities/Author.cs
- call-target: NexusReader.Domain/Entities/Ebook.cs
- interaction-target: dbContext.Roles.Add(new IdentityRole { Name = roleName, NormalizedName = roleName.ToUpper() });
- interaction-target: dbContext.Users.Add(adminUser);
- interaction-target: dbContext.UserRoles.Add(new IdentityUserRole<string> { UserId = adminUser.Id, RoleId = adminRole.Id });
- interaction-target: dbContext.Authors.Add(author);
- interaction-target: dbContext.Ebooks.Add(new Ebook
- interaction-target: await dbContextFactory.CreateDbContextAsync() — obtains AppDbContext for persistence operations
## Coverage
- Symbols: 2
- Executable symbols: 1
- Executable symbols with control flow: 1
- Grounded edges: 7
- Unresolved references: 10
- Control-flow fragments: 1
- Unresolved jumps: 4
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 2
- Generated diagrams: 3
## Control Flow Fragments
- SeedAsync: 72 nodes, 81 edges, 4 jumps, 0 unsupported constructs
## Diagrams
### DbInitializer Neighborhood
```mermaid
flowchart LR
class_1t4ptj6_dbinitializer("DbInitializer")
file_136c3oe_dbinitializer_cs("DbInitializer")
method_n19kbi_seedasync[["SeedAsync()"]]
file_1b03oou_subscriptionplan_cs[/"SubscriptionPlan"/]
file_1pacvtg_appdbcontext_cs[/"AppDbContext"/]
file_1y56eud_author_cs[/"Author"/]
file_lcvwj6_ebook_cs[/"Ebook"/]
file_xcxh5w_nexususer_cs[/"NexusUser"/]
file_136c3oe_dbinitializer_cs -->|SubscriptionPlan| file_1b03oou_subscriptionplan_cs
file_136c3oe_dbinitializer_cs -->|AppDbContext| file_1pacvtg_appdbcontext_cs
file_136c3oe_dbinitializer_cs -->|Author| file_1y56eud_author_cs
file_136c3oe_dbinitializer_cs -->|Ebook| file_lcvwj6_ebook_cs
file_136c3oe_dbinitializer_cs -->|NexusUser| file_xcxh5w_nexususer_cs
```
### DbInitializer Execution Overview
```mermaid
flowchart TD
class_1t4ptj6_dbinitializer("DbInitializer")
method_n19kbi_seedasync[["SeedAsync()"]]
unresolved_unresolved_148q98d_call_target{"Unresolved: FreeId / FreeName / ProId / ProName / EnterpriseId / EnterpriseName (static properties)"}
unresolved_unresolved_17a2h42_interaction_target{"Unresolved: dbContext.Roles.Add(new IdentityRole { Name = roleName, NormalizedName = roleName.ToUpper() });"}
unresolved_unresolved_30rgkl_interaction_target{"Unresolved: await dbContextFactory.CreateDbContextAsync() — obtains AppDbContext for persistence operations"}
unresolved_unresolved_8fs4dr_call_target{"Unresolved: Ebook .ctor (entity creation)"}
unresolved_unresolved_d456c0_interaction_target{"Unresolved: dbContext.Users.Add(adminUser);"}
unresolved_unresolved_sdjm8i_interaction_target{"Unresolved: dbContext.UserRoles.Add(new IdentityUserRole<string> { UserId = adminUser.Id, RoleId = adminRole.Id });"}
unresolved_unresolved_t3ot5v_call_target{"Unresolved: Author .ctor (entity creation)"}
unresolved_unresolved_uowqml_interaction_target{"Unresolved: dbContext.Ebooks.Add(new Ebook"}
unresolved_unresolved_v6805b_call_target{"Unresolved: NexusUser .ctor (entity creation)"}
unresolved_unresolved_w7mczj_interaction_target{"Unresolved: dbContext.Authors.Add(author);"}
class_1t4ptj6_dbinitializer -->|contains| method_n19kbi_seedasync
class_1t4ptj6_dbinitializer -->|unresolved interaction| unresolved_unresolved_17a2h42_interaction_target
class_1t4ptj6_dbinitializer -->|unresolved interaction| unresolved_unresolved_30rgkl_interaction_target
class_1t4ptj6_dbinitializer -->|unresolved interaction| unresolved_unresolved_d456c0_interaction_target
class_1t4ptj6_dbinitializer -->|unresolved interaction| unresolved_unresolved_sdjm8i_interaction_target
class_1t4ptj6_dbinitializer -->|unresolved interaction| unresolved_unresolved_uowqml_interaction_target
class_1t4ptj6_dbinitializer -->|unresolved interaction| unresolved_unresolved_w7mczj_interaction_target
method_n19kbi_seedasync -->|unresolved call| unresolved_unresolved_148q98d_call_target
method_n19kbi_seedasync -->|unresolved call| unresolved_unresolved_8fs4dr_call_target
method_n19kbi_seedasync -->|unresolved call| unresolved_unresolved_t3ot5v_call_target
method_n19kbi_seedasync -->|unresolved call| unresolved_unresolved_v6805b_call_target
```
### SeedAsync() Control Flow
_Warnings: diagram method_n19kbi_seedasync__fragment_diagram exceeds preferred complexity thresholds (72 nodes, 81 edges)._
```mermaid
---
config:
flowchart:
defaultRenderer: "elk"
---
flowchart TD
method_n19kbi_seedasync__call_30_FreeId_FreeName_ProId_ProName_EnterpriseId_EnterpriseName_static_properties_[["FreeId / FreeName / ProId / ProName / EnterpriseId / EnterpriseName (static properties)"]]
method_n19kbi_seedasync__call_58_NexusUser_ctor_entity_creation_[["NexusUser .ctor (entity creation)"]]
method_n19kbi_seedasync__call_86_Author_ctor_entity_creation_[["Author .ctor (entity creation)"]]
method_n19kbi_seedasync__call_94_Ebook_ctor_entity_creation_[["Ebook .ctor (entity creation)"]]
method_n19kbi_seedasync__action_105_seedasync_await_105_21__await[["Waits for async work"]]
method_n19kbi_seedasync__action_109_seedasync_fallback_109_22__condition{"Falls back to alternate path"}
method_n19kbi_seedasync__action_109_seedasync_fallback_109_22__false("otherwise")
method_n19kbi_seedasync__action_109_seedasync_fallback_109_22__merge("merge")
method_n19kbi_seedasync__action_109_seedasync_fallback_109_22__true("fallback")
method_n19kbi_seedasync__action_114_error_handling_114__linear("Top-level seeding exception catch")
method_n19kbi_seedasync__action_114_seedasync_catch_114_23__catch("catch Exception ex")
method_n19kbi_seedasync__action_16_resource_acquire_16__linear("Create service scope and resolve services")
method_n19kbi_seedasync__action_19_seedasync_await_19_0__await[["Waits for async work"]]
method_n19kbi_seedasync__action_21_seedasync_try_21_1__try("Begins protected execution")
method_n19kbi_seedasync__action_23_log_23__linear("Starting seeding")
method_n19kbi_seedasync__action_26_guard_clause_26__condition{"!dbContext.SubscriptionPlans.Any()"}
method_n19kbi_seedasync__action_26_guard_clause_26__false("skip")
method_n19kbi_seedasync__action_26_guard_clause_26__merge("merge")
method_n19kbi_seedasync__action_26_guard_clause_26__true("add-plans")
method_n19kbi_seedasync__action_26_seedasync_branch_26_2__condition{"!dbContext.SubscriptionPlans.Any()"}
method_n19kbi_seedasync__action_26_seedasync_branch_26_2__false("false")
method_n19kbi_seedasync__action_26_seedasync_branch_26_2__merge("merge")
method_n19kbi_seedasync__action_26_seedasync_branch_26_2__true("true")
method_n19kbi_seedasync__action_28_persistence_write_28__linear("AddRange SubscriptionPlans")
method_n19kbi_seedasync__action_34_seedasync_await_34_3__await[["Waits for async work"]]
method_n19kbi_seedasync__action_35_log_35__linear("Seed progress/info logs")
method_n19kbi_seedasync__action_40_loop_40__loop_body[["foreach roleName in roleNames -> checks dbContext.Roles.Any(...) and adds missing IdentityRole entries; then SaveChangesAsync() (lines 40-49, 49)"]]
method_n19kbi_seedasync__action_40_loop_40__loop_entry("Seed roles (Admin, User)")
method_n19kbi_seedasync__action_40_loop_40__loop_exit("exit loop")
method_n19kbi_seedasync__action_40_seedasync_loop_40_4__loop_body[["foreach (var roleName in roleNames)"]]
method_n19kbi_seedasync__action_40_seedasync_loop_40_4__loop_entry("var roleName in roleNames")
method_n19kbi_seedasync__action_40_seedasync_loop_40_4__loop_exit("Leaves the loop when the condition no longer holds.")
method_n19kbi_seedasync__action_43_seedasync_branch_43_5__condition{"!roleExist"}
method_n19kbi_seedasync__action_43_seedasync_branch_43_5__false("false")
method_n19kbi_seedasync__action_43_seedasync_branch_43_5__merge("merge")
method_n19kbi_seedasync__action_43_seedasync_branch_43_5__true("true")
method_n19kbi_seedasync__action_49_seedasync_await_49_7__await[["Waits for async work"]]
method_n19kbi_seedasync__action_54_persistence_read_54__linear("Check for existing admin user")
method_n19kbi_seedasync__action_54_seedasync_await_54_8__await[["Waits for async work"]]
method_n19kbi_seedasync__action_56_branch_56__condition{"adminUser == null"}
method_n19kbi_seedasync__action_56_branch_56__false("admin-exists")
method_n19kbi_seedasync__action_56_branch_56__merge("merge")
method_n19kbi_seedasync__action_56_branch_56__true("create-admin")
method_n19kbi_seedasync__action_56_seedasync_branch_56_9__condition{"adminUser == null"}
method_n19kbi_seedasync__action_56_seedasync_branch_56_9__false("false")
method_n19kbi_seedasync__action_56_seedasync_branch_56_9__merge("merge")
method_n19kbi_seedasync__action_56_seedasync_branch_56_9__true("true")
method_n19kbi_seedasync__action_71_persistence_write_71__linear("Create admin user and save")
method_n19kbi_seedasync__action_74_seedasync_await_74_11__await[["Waits for async work"]]
method_n19kbi_seedasync__action_76_persistence_write_76__linear("Assign Admin role to user")
method_n19kbi_seedasync__action_76_seedasync_await_76_12__await[["Waits for async work"]]
method_n19kbi_seedasync__action_78_seedasync_await_78_14__await[["Waits for async work"]]
method_n19kbi_seedasync__action_83_persistence_read_write_83__linear("Ensure sample Author exists")
method_n19kbi_seedasync__action_83_seedasync_await_83_15__await[["Waits for async work"]]
method_n19kbi_seedasync__action_84_seedasync_branch_84_16__condition{"author == null"}
method_n19kbi_seedasync__action_84_seedasync_branch_84_16__false("false")
method_n19kbi_seedasync__action_84_seedasync_branch_84_16__merge("merge")
method_n19kbi_seedasync__action_84_seedasync_branch_84_16__true("true")
method_n19kbi_seedasync__action_88_seedasync_await_88_18__await[["Waits for async work"]]
method_n19kbi_seedasync__action_92_persistence_read_write_92__linear("Add sample Ebook for admin user")
method_n19kbi_seedasync__action_92_seedasync_branch_92_19__condition{"!dbContext.Ebooks.Any(e => e.UserId == adminUser.Id)"}
method_n19kbi_seedasync__action_92_seedasync_branch_92_19__false("false")
method_n19kbi_seedasync__action_92_seedasync_branch_92_19__merge("merge")
method_n19kbi_seedasync__action_92_seedasync_branch_92_19__true("true")
method_n19kbi_seedasync__entry(["SeedAsync entry"])
method_n19kbi_seedasync__action_19_external_call_19__linear("Create DbContext async")
method_n19kbi_seedasync__action_45_seedasync_repository_write_45_6__linear[("Writes repository or persistence state")]
method_n19kbi_seedasync__action_73_seedasync_repository_write_73_10__linear[("Writes repository or persistence state")]
method_n19kbi_seedasync__action_77_seedasync_repository_write_77_13__linear[("Writes repository or persistence state")]
method_n19kbi_seedasync__action_87_seedasync_repository_write_87_17__linear[("Writes repository or persistence state")]
method_n19kbi_seedasync__action_94_seedasync_repository_write_94_20__linear[("Writes repository or persistence state")]
method_n19kbi_seedasync__implicit_return(["return"])
method_n19kbi_seedasync__action_105_seedasync_await_105_21__await -->|fallback| method_n19kbi_seedasync__action_109_seedasync_fallback_109_22__condition
method_n19kbi_seedasync__action_109_seedasync_fallback_109_22__condition -->|otherwise| method_n19kbi_seedasync__action_109_seedasync_fallback_109_22__false
method_n19kbi_seedasync__action_109_seedasync_fallback_109_22__condition -->|fallback| method_n19kbi_seedasync__action_109_seedasync_fallback_109_22__true
method_n19kbi_seedasync__action_109_seedasync_fallback_109_22__false -->|next| method_n19kbi_seedasync__action_109_seedasync_fallback_109_22__merge
method_n19kbi_seedasync__action_109_seedasync_fallback_109_22__merge -->|next| method_n19kbi_seedasync__action_114_error_handling_114__linear
method_n19kbi_seedasync__action_109_seedasync_fallback_109_22__true -->|next| method_n19kbi_seedasync__action_109_seedasync_fallback_109_22__merge
method_n19kbi_seedasync__action_114_error_handling_114__linear -->|exception| method_n19kbi_seedasync__action_114_seedasync_catch_114_23__catch
method_n19kbi_seedasync__action_114_seedasync_catch_114_23__catch -->|return| method_n19kbi_seedasync__implicit_return
method_n19kbi_seedasync__action_16_resource_acquire_16__linear -->|next| method_n19kbi_seedasync__action_19_seedasync_await_19_0__await
method_n19kbi_seedasync__action_19_external_call_19__linear -->|next| method_n19kbi_seedasync__action_21_seedasync_try_21_1__try
method_n19kbi_seedasync__action_19_seedasync_await_19_0__await -->|next| method_n19kbi_seedasync__action_19_external_call_19__linear
method_n19kbi_seedasync__action_21_seedasync_try_21_1__try -->|next| method_n19kbi_seedasync__action_23_log_23__linear
method_n19kbi_seedasync__action_23_log_23__linear -->|next| method_n19kbi_seedasync__action_26_guard_clause_26__condition
method_n19kbi_seedasync__action_26_guard_clause_26__condition -->|skip| method_n19kbi_seedasync__action_26_guard_clause_26__false
method_n19kbi_seedasync__action_26_guard_clause_26__condition -->|add-plans| method_n19kbi_seedasync__action_26_guard_clause_26__true
method_n19kbi_seedasync__action_26_guard_clause_26__false -->|next| method_n19kbi_seedasync__action_26_guard_clause_26__merge
method_n19kbi_seedasync__action_26_guard_clause_26__merge -->|next| method_n19kbi_seedasync__action_26_seedasync_branch_26_2__condition
method_n19kbi_seedasync__action_26_guard_clause_26__true -->|next| method_n19kbi_seedasync__action_26_guard_clause_26__merge
method_n19kbi_seedasync__action_26_seedasync_branch_26_2__condition -->|false| method_n19kbi_seedasync__action_26_seedasync_branch_26_2__false
method_n19kbi_seedasync__action_26_seedasync_branch_26_2__condition -->|true| method_n19kbi_seedasync__action_26_seedasync_branch_26_2__true
method_n19kbi_seedasync__action_26_seedasync_branch_26_2__false -->|next| method_n19kbi_seedasync__action_26_seedasync_branch_26_2__merge
method_n19kbi_seedasync__action_26_seedasync_branch_26_2__merge -->|next| method_n19kbi_seedasync__action_28_persistence_write_28__linear
method_n19kbi_seedasync__action_26_seedasync_branch_26_2__true -->|next| method_n19kbi_seedasync__action_26_seedasync_branch_26_2__merge
method_n19kbi_seedasync__action_28_persistence_write_28__linear -->|used to set Id and PlanName when creating SubscriptionPlan instances| method_n19kbi_seedasync__call_30_FreeId_FreeName_ProId_ProName_EnterpriseId_EnterpriseName_static_properties_
method_n19kbi_seedasync__action_34_seedasync_await_34_3__await -->|next| method_n19kbi_seedasync__action_35_log_35__linear
method_n19kbi_seedasync__action_35_log_35__linear -->|next| method_n19kbi_seedasync__action_40_loop_40__loop_entry
method_n19kbi_seedasync__action_40_loop_40__loop_body -->|continue| method_n19kbi_seedasync__action_40_loop_40__loop_entry
method_n19kbi_seedasync__action_40_loop_40__loop_entry -->|iterate| method_n19kbi_seedasync__action_40_loop_40__loop_body
method_n19kbi_seedasync__action_40_loop_40__loop_entry -->|exit| method_n19kbi_seedasync__action_40_loop_40__loop_exit
method_n19kbi_seedasync__action_40_loop_40__loop_exit -->|next| method_n19kbi_seedasync__action_40_seedasync_loop_40_4__loop_entry
method_n19kbi_seedasync__action_40_seedasync_loop_40_4__loop_body -->|continue| method_n19kbi_seedasync__action_40_seedasync_loop_40_4__loop_entry
method_n19kbi_seedasync__action_40_seedasync_loop_40_4__loop_entry -->|var roleName in roleNames| method_n19kbi_seedasync__action_40_seedasync_loop_40_4__loop_body
method_n19kbi_seedasync__action_40_seedasync_loop_40_4__loop_entry -->|Leaves the loop when the condition no longer holds.| method_n19kbi_seedasync__action_40_seedasync_loop_40_4__loop_exit
method_n19kbi_seedasync__action_40_seedasync_loop_40_4__loop_exit -->|next| method_n19kbi_seedasync__action_43_seedasync_branch_43_5__condition
method_n19kbi_seedasync__action_43_seedasync_branch_43_5__condition -->|false| method_n19kbi_seedasync__action_43_seedasync_branch_43_5__false
method_n19kbi_seedasync__action_43_seedasync_branch_43_5__condition -->|true| method_n19kbi_seedasync__action_43_seedasync_branch_43_5__true
method_n19kbi_seedasync__action_43_seedasync_branch_43_5__false -->|next| method_n19kbi_seedasync__action_43_seedasync_branch_43_5__merge
method_n19kbi_seedasync__action_43_seedasync_branch_43_5__merge -->|next| method_n19kbi_seedasync__action_45_seedasync_repository_write_45_6__linear
method_n19kbi_seedasync__action_43_seedasync_branch_43_5__true -->|next| method_n19kbi_seedasync__action_43_seedasync_branch_43_5__merge
method_n19kbi_seedasync__action_45_seedasync_repository_write_45_6__linear -->|next| method_n19kbi_seedasync__action_49_seedasync_await_49_7__await
method_n19kbi_seedasync__action_49_seedasync_await_49_7__await -->|next| method_n19kbi_seedasync__action_54_seedasync_await_54_8__await
method_n19kbi_seedasync__action_54_persistence_read_54__linear -->|next| method_n19kbi_seedasync__action_56_seedasync_branch_56_9__condition
method_n19kbi_seedasync__action_54_seedasync_await_54_8__await -->|next| method_n19kbi_seedasync__action_54_persistence_read_54__linear
method_n19kbi_seedasync__action_56_branch_56__condition -->|admin-exists| method_n19kbi_seedasync__action_56_branch_56__false
method_n19kbi_seedasync__action_56_branch_56__condition -->|create-admin| method_n19kbi_seedasync__action_56_branch_56__true
method_n19kbi_seedasync__action_56_branch_56__false -->|next| method_n19kbi_seedasync__action_56_branch_56__merge
method_n19kbi_seedasync__action_56_branch_56__merge -->|instantiates admin NexusUser with email, subscription, tokens, tenant / security stamps| method_n19kbi_seedasync__call_58_NexusUser_ctor_entity_creation_
method_n19kbi_seedasync__action_56_branch_56__true -->|next| method_n19kbi_seedasync__action_56_branch_56__merge
method_n19kbi_seedasync__action_56_seedasync_branch_56_9__condition -->|false| method_n19kbi_seedasync__action_56_seedasync_branch_56_9__false
method_n19kbi_seedasync__action_56_seedasync_branch_56_9__condition -->|true| method_n19kbi_seedasync__action_56_seedasync_branch_56_9__true
method_n19kbi_seedasync__action_56_seedasync_branch_56_9__false -->|next| method_n19kbi_seedasync__action_56_seedasync_branch_56_9__merge
method_n19kbi_seedasync__action_56_seedasync_branch_56_9__merge -->|next| method_n19kbi_seedasync__action_56_branch_56__condition
method_n19kbi_seedasync__action_56_seedasync_branch_56_9__true -->|next| method_n19kbi_seedasync__action_56_seedasync_branch_56_9__merge
method_n19kbi_seedasync__action_71_persistence_write_71__linear -->|next| method_n19kbi_seedasync__action_73_seedasync_repository_write_73_10__linear
method_n19kbi_seedasync__action_73_seedasync_repository_write_73_10__linear -->|next| method_n19kbi_seedasync__action_74_seedasync_await_74_11__await
method_n19kbi_seedasync__action_74_seedasync_await_74_11__await -->|next| method_n19kbi_seedasync__action_76_seedasync_await_76_12__await
method_n19kbi_seedasync__action_76_persistence_write_76__linear -->|next| method_n19kbi_seedasync__action_77_seedasync_repository_write_77_13__linear
method_n19kbi_seedasync__action_76_seedasync_await_76_12__await -->|next| method_n19kbi_seedasync__action_76_persistence_write_76__linear
method_n19kbi_seedasync__action_77_seedasync_repository_write_77_13__linear -->|next| method_n19kbi_seedasync__action_78_seedasync_await_78_14__await
method_n19kbi_seedasync__action_78_seedasync_await_78_14__await -->|next| method_n19kbi_seedasync__action_83_seedasync_await_83_15__await
method_n19kbi_seedasync__action_83_persistence_read_write_83__linear -->|next| method_n19kbi_seedasync__action_84_seedasync_branch_84_16__condition
method_n19kbi_seedasync__action_83_seedasync_await_83_15__await -->|next| method_n19kbi_seedasync__action_83_persistence_read_write_83__linear
method_n19kbi_seedasync__action_84_seedasync_branch_84_16__condition -->|false| method_n19kbi_seedasync__action_84_seedasync_branch_84_16__false
method_n19kbi_seedasync__action_84_seedasync_branch_84_16__condition -->|true| method_n19kbi_seedasync__action_84_seedasync_branch_84_16__true
method_n19kbi_seedasync__action_84_seedasync_branch_84_16__false -->|next| method_n19kbi_seedasync__action_84_seedasync_branch_84_16__merge
method_n19kbi_seedasync__action_84_seedasync_branch_84_16__merge -->|calls| method_n19kbi_seedasync__call_86_Author_ctor_entity_creation_
method_n19kbi_seedasync__action_84_seedasync_branch_84_16__true -->|next| method_n19kbi_seedasync__action_84_seedasync_branch_84_16__merge
method_n19kbi_seedasync__action_87_seedasync_repository_write_87_17__linear -->|next| method_n19kbi_seedasync__action_88_seedasync_await_88_18__await
method_n19kbi_seedasync__action_88_seedasync_await_88_18__await -->|next| method_n19kbi_seedasync__action_92_seedasync_branch_92_19__condition
method_n19kbi_seedasync__action_92_persistence_read_write_92__linear -->|next| method_n19kbi_seedasync__action_94_seedasync_repository_write_94_20__linear
method_n19kbi_seedasync__action_92_seedasync_branch_92_19__condition -->|false| method_n19kbi_seedasync__action_92_seedasync_branch_92_19__false
method_n19kbi_seedasync__action_92_seedasync_branch_92_19__condition -->|true| method_n19kbi_seedasync__action_92_seedasync_branch_92_19__true
method_n19kbi_seedasync__action_92_seedasync_branch_92_19__false -->|next| method_n19kbi_seedasync__action_92_seedasync_branch_92_19__merge
method_n19kbi_seedasync__action_92_seedasync_branch_92_19__merge -->|next| method_n19kbi_seedasync__action_92_persistence_read_write_92__linear
method_n19kbi_seedasync__action_92_seedasync_branch_92_19__true -->|next| method_n19kbi_seedasync__action_92_seedasync_branch_92_19__merge
method_n19kbi_seedasync__action_94_seedasync_repository_write_94_20__linear -->|creates sample Ebook for admin user with metadata and file path| method_n19kbi_seedasync__call_94_Ebook_ctor_entity_creation_
method_n19kbi_seedasync__call_30_FreeId_FreeName_ProId_ProName_EnterpriseId_EnterpriseName_static_properties_ -->|next| method_n19kbi_seedasync__action_34_seedasync_await_34_3__await
method_n19kbi_seedasync__call_58_NexusUser_ctor_entity_creation_ -->|next| method_n19kbi_seedasync__action_71_persistence_write_71__linear
method_n19kbi_seedasync__call_86_Author_ctor_entity_creation_ -->|next| method_n19kbi_seedasync__action_87_seedasync_repository_write_87_17__linear
method_n19kbi_seedasync__call_94_Ebook_ctor_entity_creation_ -->|next| method_n19kbi_seedasync__action_105_seedasync_await_105_21__await
method_n19kbi_seedasync__entry -->|next| method_n19kbi_seedasync__action_16_resource_acquire_16__linear
```
## Diagram Validation
- Status: warn
- Warning: Control-flow extraction left 4 unresolved jumps.
- Warning: control-flow: diagram method_n19kbi_seedasync__fragment_diagram exceeds preferred complexity thresholds (72 nodes, 81 edges).
@@ -0,0 +1,77 @@
# 20260513181743_AddEbookReadyFlag.Designer
- File ID: file:jl4svh:20260513181743-addebookreadyflag-designer-cs
- Path: NexusReader.Data/Persistence/Migrations/20260513181743_AddEbookReadyFlag.Designer.cs
- Role: database-config
- Layer: data
## Purpose
EF Core migration designer snapshot that builds the target model for the migration AddEbookReadyFlag; it defines tables, columns, indexes, relationships, Postgres extensions and seed data used to represent the current schema in code.
## Key Details
This migration snapshot configures a Postgres vector extension, vector-typed columns for semantic search, identity tables, and seeds four subscription plans; notably the Ebook entity includes an IsReadyForReading boolean property (migration name AddEbookReadyFlag aligns with this addition).
## Symbols
- AddEbookReadyFlag: EF Core migration designer snapshot that builds the target model for the migration AddEbookReadyFlag; it defines tables, columns, indexes, relationships, Postgres extensions and seed data used to represent the current schema in code.
- BuildTargetModel(): Constructs the EF Core model snapshot for this migration: configures Postgres extensions, identity defaults, all entity types, properties, indexes, foreign keys, navigations and seed data.
- AddEbookReadyFlag: Partial migration class representing the AddEbookReadyFlag migration (contains BuildTargetModel snapshot).
## Dependencies
- imports NexusReader.Data/Persistence/AppDbContext.cs
## Calls
- No resolved calls.
## Unresolved References
- dependency-target: NexusReader.Domain/Entities/* (Author, Ebook, KnowledgeUnit, KnowledgeUnitLink, NexusUser, QuizResult, SemanticKnowledgeCache, SubscriptionPlan)
## Coverage
- Symbols: 3
- Executable symbols: 1
- Executable symbols with control flow: 1
- Grounded edges: 4
- Unresolved references: 1
- Control-flow fragments: 1
- Unresolved jumps: 0
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 2
- Generated diagrams: 2
## Control Flow Fragments
- BuildTargetModel: 21 nodes, 20 edges, 0 jumps, 0 unsupported constructs
## Diagrams
### 20260513181743_AddEbookReadyFlag.Designer Neighborhood
```mermaid
flowchart LR
class_4p0c5r_addebookreadyflag("AddEbookReadyFlag")
file_jl4svh_20260513181743_addebookreadyflag_designer_cs("20260513181743_AddEbookReadyFlag.Designer")
method_16i3kbl_buildtargetmodel[["BuildTargetModel()"]]
file_1pacvtg_appdbcontext_cs[/"AppDbContext"/]
type_1l23zuf_addebookreadyflag[/"AddEbookReadyFlag"/]
file_jl4svh_20260513181743_addebookreadyflag_designer_cs -->|AppDbContext| file_1pacvtg_appdbcontext_cs
```
### 20260513181743_AddEbookReadyFlag.Designer Execution Overview
```mermaid
flowchart TD
class_4p0c5r_addebookreadyflag("AddEbookReadyFlag")
method_16i3kbl_buildtargetmodel[["BuildTargetModel()"]]
class_4p0c5r_addebookreadyflag -->|contains| method_16i3kbl_buildtargetmodel
```
## Diagram Validation
- Status: pass
@@ -0,0 +1,76 @@
# 20260513181743_AddEbookReadyFlag
- File ID: file:1wy1v1s:20260513181743-addebookreadyflag-cs
- Path: NexusReader.Data/Persistence/Migrations/20260513181743_AddEbookReadyFlag.cs
- Role: database-config
- Layer: data
## Purpose
Entity Framework Core migration that adds a boolean 'IsReadyForReading' flag to the 'Ebooks' table and provides a rollback to remove it.
## Key Details
Adds non-nullable boolean column IsReadyForReading to Ebooks with default false; Down removes the column.
## Symbols
- AddEbookReadyFlag: Entity Framework Core migration that adds a boolean 'IsReadyForReading' flag to the 'Ebooks' table and provides a rollback to remove it.
- Up(): Applies the migration: adds a non-nullable boolean column 'IsReadyForReading' with default false to the 'Ebooks' table.
- Down(): Rolls back the migration: removes the 'IsReadyForReading' column from the 'Ebooks' table.
- AddEbookReadyFlag: EF Core migration class that encapsulates schema changes to add/remove the IsReadyForReading flag on Ebooks.
## Dependencies
- No resolved dependencies.
## Calls
- No resolved calls.
## Coverage
- Symbols: 4
- Executable symbols: 2
- Executable symbols with control flow: 2
- Grounded edges: 4
- Unresolved references: 0
- Control-flow fragments: 2
- Unresolved jumps: 0
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 2
- Generated diagrams: 2
## Control Flow Fragments
- Up: 3 nodes, 2 edges, 0 jumps, 0 unsupported constructs
- Down: 3 nodes, 2 edges, 0 jumps, 0 unsupported constructs
## Diagrams
### 20260513181743_AddEbookReadyFlag Neighborhood
```mermaid
flowchart LR
class_1eb2dy_addebookreadyflag("AddEbookReadyFlag")
file_1wy1v1s_20260513181743_addebookreadyflag_cs("20260513181743_AddEbookReadyFlag")
method_8mq94d_up[["Up()"]]
method_y8prsw_down[["Down()"]]
type_swoy5w_addebookreadyflag[/"AddEbookReadyFlag"/]
```
### 20260513181743_AddEbookReadyFlag Execution Overview
```mermaid
flowchart TD
class_1eb2dy_addebookreadyflag("AddEbookReadyFlag")
method_8mq94d_up[["Up()"]]
method_y8prsw_down[["Down()"]]
class_1eb2dy_addebookreadyflag -->|contains| method_8mq94d_up
class_1eb2dy_addebookreadyflag -->|contains| method_y8prsw_down
```
## Diagram Validation
- Status: pass
@@ -0,0 +1,77 @@
# 20260513183726_FixKnowledgeUnitEbookId.Designer
- File ID: file:sl1mo0:20260513183726-fixknowledgeunitebookid-designer-
- Path: NexusReader.Data/Persistence/Migrations/20260513183726_FixKnowledgeUnitEbookId.Designer.cs
- Role: database-config
- Layer: data
## Purpose
EF Core migration designer file that describes the target EF model for the migration 'FixKnowledgeUnitEbookId'; it encodes entity mappings, indices, relationships, extension usage and seed data used by the migration snapshot.
## Key Details
BuildTargetModel configures Postgres 'vector' extension, identity default columns, declares entity schemas (properties, indices, keys), establishes FK relationships with explicit delete behaviors and navigation properties, and seeds SubscriptionPlan table with four rows. KnowledgeUnit.EbookId is mapped as a uuid (Guid) and indexed (lines 253, 277).
## Symbols
- FixKnowledgeUnitEbookId: EF Core migration designer file that describes the target EF model for the migration 'FixKnowledgeUnitEbookId'; it encodes entity mappings, indices, relationships, extension usage and seed data used by the migration snapshot.
- BuildTargetModel(): Constructs the EF Core model snapshot for this migration: annotations, DB extensions, entities, properties, indices, relationships and seed data.
- FixKnowledgeUnitEbookId: Partial migration class representing the migration snapshot and model-building logic for 'FixKnowledgeUnitEbookId'.
## Dependencies
- imports NexusReader.Data/Persistence/AppDbContext.cs
## Calls
- No resolved calls.
## Unresolved References
- dependency-target: NexusReader.Domain/Entities (referenced entity types: Author, Ebook, KnowledgeUnit, KnowledgeUnitLink, NexusUser, SubscriptionPlan, QuizResult, SemanticKnowledgeCache)
## Coverage
- Symbols: 3
- Executable symbols: 1
- Executable symbols with control flow: 1
- Grounded edges: 4
- Unresolved references: 1
- Control-flow fragments: 1
- Unresolved jumps: 0
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 2
- Generated diagrams: 2
## Control Flow Fragments
- BuildTargetModel: 23 nodes, 22 edges, 0 jumps, 0 unsupported constructs
## Diagrams
### 20260513183726_FixKnowledgeUnitEbookId.Designer Neighborhood
```mermaid
flowchart LR
class_181ukvc_fixknowledgeunitebookid("FixKnowledgeUnitEbookId")
file_sl1mo0_20260513183726_fixknowledgeunitebookid_designer_("20260513183726_FixKnowledgeUnitEbookId.Designer")
method_16euo54_buildtargetmodel[["BuildTargetModel()"]]
file_1pacvtg_appdbcontext_cs[/"AppDbContext"/]
type_1sj29na_fixknowledgeunitebookid[/"FixKnowledgeUnitEbookId"/]
file_sl1mo0_20260513183726_fixknowledgeunitebookid_designer_ -->|AppDbContext| file_1pacvtg_appdbcontext_cs
```
### 20260513183726_FixKnowledgeUnitEbookId.Designer Execution Overview
```mermaid
flowchart TD
class_181ukvc_fixknowledgeunitebookid("FixKnowledgeUnitEbookId")
method_16euo54_buildtargetmodel[["BuildTargetModel()"]]
class_181ukvc_fixknowledgeunitebookid -->|contains| method_16euo54_buildtargetmodel
```
## Diagram Validation
- Status: pass
@@ -0,0 +1,76 @@
# 20260513183726_FixKnowledgeUnitEbookId
- File ID: file:1r47ykv:20260513183726-fixknowledgeunitebookid-cs
- Path: NexusReader.Data/Persistence/Migrations/20260513183726_FixKnowledgeUnitEbookId.cs
- Role: database-config
- Layer: data
## Purpose
EF Core migration that replaces KnowledgeUnits.SourceId (string) with KnowledgeUnits.EbookId (Guid), adds index and FK to Ebooks, and provides the reverse Down migration.
## Key Details
Up adds a non-nullable Guid EbookId with default Guid.Empty, index, and FK to Ebooks (cascade delete). Down restores previous SourceId string column (varchar(128)) and its index.
## Symbols
- FixKnowledgeUnitEbookId: EF Core migration that replaces KnowledgeUnits.SourceId (string) with KnowledgeUnits.EbookId (Guid), adds index and FK to Ebooks, and provides the reverse Down migration.
- Up(): Apply schema changes: remove SourceId column and index from KnowledgeUnits, add non-nullable EbookId Guid column with default, create index on EbookId, and add FK to Ebooks with cascade delete.
- Down(): Revert schema changes applied in Up: remove FK and index on EbookId, drop EbookId column, re-add SourceId string column with constraints and recreate its index.
- FixKnowledgeUnitEbookId: EF Core Migration class that applies and reverts schema changes to replace SourceId with EbookId on KnowledgeUnits.
## Dependencies
- No resolved dependencies.
## Calls
- No resolved calls.
## Coverage
- Symbols: 4
- Executable symbols: 2
- Executable symbols with control flow: 2
- Grounded edges: 4
- Unresolved references: 0
- Control-flow fragments: 2
- Unresolved jumps: 0
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 2
- Generated diagrams: 2
## Control Flow Fragments
- Up: 7 nodes, 6 edges, 0 jumps, 0 unsupported constructs
- Down: 7 nodes, 6 edges, 0 jumps, 0 unsupported constructs
## Diagrams
### 20260513183726_FixKnowledgeUnitEbookId Neighborhood
```mermaid
flowchart LR
class_1jh8uof_fixknowledgeunitebookid("FixKnowledgeUnitEbookId")
file_1r47ykv_20260513183726_fixknowledgeunitebookid_cs("20260513183726_FixKnowledgeUnitEbookId")
method_1ste7vn_down[["Down()"]]
method_cdxwj_up[["Up()"]]
type_1a7gg4i_fixknowledgeunitebookid[/"FixKnowledgeUnitEbookId"/]
```
### 20260513183726_FixKnowledgeUnitEbookId Execution Overview
```mermaid
flowchart TD
class_1jh8uof_fixknowledgeunitebookid("FixKnowledgeUnitEbookId")
method_1ste7vn_down[["Down()"]]
method_cdxwj_up[["Up()"]]
class_1jh8uof_fixknowledgeunitebookid -->|contains| method_1ste7vn_down
class_1jh8uof_fixknowledgeunitebookid -->|contains| method_cdxwj_up
```
## Diagram Validation
- Status: pass
@@ -0,0 +1,156 @@
# 20260513185108_MakeKnowledgeUnitEbookIdNullable.Designer
- File ID: file:6fusgm:20260513185108-makeknowledgeunitebookidnullable-
- Path: NexusReader.Data/Persistence/Migrations/20260513185108_MakeKnowledgeUnitEbookIdNullable.Designer.cs
- Role: database-config
- Layer: data
## Purpose
EF Core migration designer that defines the target EF Core model for the migration 'MakeKnowledgeUnitEbookIdNullable' — configures entities, relationships, indices, vector extension, identity settings and seeds subscription plan data.
## Key Details
This EF migration snapshot configures the Postgres vector extension, identity-by-default columns, many entity schemas and relationships, and explicitly declares KnowledgeUnit.EbookId as nullable (Guid?). It also seeds SubscriptionPlans with four entries.
## Symbols
- MakeKnowledgeUnitEbookIdNullable: EF Core migration designer that defines the target EF Core model for the migration 'MakeKnowledgeUnitEbookIdNullable' — configures entities, relationships, indices, vector extension, identity settings and seeds subscription plan data.
- BuildTargetModel(): Constructs the EF Core model snapshot for this migration: annotations, extensions, entity schemas, relationships, indices and data seeding.
- MakeKnowledgeUnitEbookIdNullable: Partial migration class representing the migration that makes KnowledgeUnit.EbookId nullable and supplies the target model snapshot.
## Dependencies
- imports NexusReader.Data/Persistence/AppDbContext.cs
- imports NexusReader.Domain/Entities/Ebook.cs
- imports NexusReader.Domain/Entities/KnowledgeUnit.cs
- imports NexusReader.Domain/Entities/SubscriptionPlan.cs
- imports NexusReader.Domain/Entities/NexusUser.cs
- imports NexusReader.Domain/Entities/Author.cs
- imports NexusReader.Domain/Entities/KnowledgeUnitLink.cs
- imports NexusReader.Domain/Entities/QuizResult.cs
- imports NexusReader.Domain/Entities/SemanticKnowledgeCache.cs
## Calls
- No resolved calls.
## Unresolved References
- call-target: unknown
- call-target: unknown
- call-target: unknown
- call-target: unknown
## Coverage
- Symbols: 3
- Executable symbols: 1
- Executable symbols with control flow: 1
- Grounded edges: 12
- Unresolved references: 4
- Control-flow fragments: 1
- Unresolved jumps: 4
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 2
- Generated diagrams: 3
## Control Flow Fragments
- BuildTargetModel: 15 nodes, 14 edges, 4 jumps, 0 unsupported constructs
## Diagrams
### 20260513185108_MakeKnowledgeUnitEbookIdNullable.Designer Neighborhood
_Warnings: diagram file_6fusgm_20260513185108_makeknowledgeunitebookidnullable__neighborhood_view exceeds preferred complexity thresholds (13 nodes, 9 edges)._
```mermaid
---
config:
flowchart:
defaultRenderer: "elk"
---
flowchart LR
class_1gem37m_makeknowledgeunitebookidnullable("MakeKnowledgeUnitEbookIdNullable")
file_6fusgm_20260513185108_makeknowledgeunitebookidnullable_("20260513185108_MakeKnowledgeUnitEbookIdNullable.Designer")
method_1egmvje_buildtargetmodel[["BuildTargetModel()"]]
file_1b03oou_subscriptionplan_cs[/"SubscriptionPlan"/]
file_1d4ycw2_semanticknowledgecache_cs[/"SemanticKnowledgeCache"/]
file_1m6x5qy_knowledgeunitlink_cs[/"KnowledgeUnitLink"/]
file_1pacvtg_appdbcontext_cs[/"AppDbContext"/]
file_1wyr0y8_quizresult_cs[/"QuizResult"/]
file_1y56eud_author_cs[/"Author"/]
file_h6a0xu_knowledgeunit_cs[/"KnowledgeUnit"/]
file_lcvwj6_ebook_cs[/"Ebook"/]
file_xcxh5w_nexususer_cs[/"NexusUser"/]
type_1juajpg_makeknowledgeunitebookidnullable[/"MakeKnowledgeUnitEbookIdNullable"/]
file_6fusgm_20260513185108_makeknowledgeunitebookidnullable_ -->|SubscriptionPlan| file_1b03oou_subscriptionplan_cs
file_6fusgm_20260513185108_makeknowledgeunitebookidnullable_ -->|SemanticKnowledgeCache| file_1d4ycw2_semanticknowledgecache_cs
file_6fusgm_20260513185108_makeknowledgeunitebookidnullable_ -->|KnowledgeUnitLink| file_1m6x5qy_knowledgeunitlink_cs
file_6fusgm_20260513185108_makeknowledgeunitebookidnullable_ -->|AppDbContext| file_1pacvtg_appdbcontext_cs
file_6fusgm_20260513185108_makeknowledgeunitebookidnullable_ -->|QuizResult| file_1wyr0y8_quizresult_cs
file_6fusgm_20260513185108_makeknowledgeunitebookidnullable_ -->|Author| file_1y56eud_author_cs
file_6fusgm_20260513185108_makeknowledgeunitebookidnullable_ -->|KnowledgeUnit| file_h6a0xu_knowledgeunit_cs
file_6fusgm_20260513185108_makeknowledgeunitebookidnullable_ -->|Ebook| file_lcvwj6_ebook_cs
file_6fusgm_20260513185108_makeknowledgeunitebookidnullable_ -->|NexusUser| file_xcxh5w_nexususer_cs
```
### 20260513185108_MakeKnowledgeUnitEbookIdNullable.Designer Execution Overview
```mermaid
flowchart TD
class_1gem37m_makeknowledgeunitebookidnullable("MakeKnowledgeUnitEbookIdNullable")
method_1egmvje_buildtargetmodel[["BuildTargetModel()"]]
unresolved_unresolved_1ii6wwa_call_target{"Unresolved: ModelBuilder.Entity"}
unresolved_unresolved_1oombcg_call_target{"Unresolved: NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns"}
unresolved_unresolved_83awfv_call_target{"Unresolved: EntityTypeBuilder.HasData"}
unresolved_unresolved_vzpeg0_call_target{"Unresolved: NpgsqlModelBuilderExtensions.HasPostgresExtension"}
class_1gem37m_makeknowledgeunitebookidnullable -->|contains| method_1egmvje_buildtargetmodel
method_1egmvje_buildtargetmodel -->|unresolved call| unresolved_unresolved_1ii6wwa_call_target
method_1egmvje_buildtargetmodel -->|unresolved call| unresolved_unresolved_1oombcg_call_target
method_1egmvje_buildtargetmodel -->|unresolved call| unresolved_unresolved_83awfv_call_target
method_1egmvje_buildtargetmodel -->|unresolved call| unresolved_unresolved_vzpeg0_call_target
```
### BuildTargetModel() Control Flow
```mermaid
flowchart TD
method_1egmvje_buildtargetmodel__call_27_NpgsqlModelBuilderExtensions_HasPostgresExtension[["NpgsqlModelBuilderExtensions.HasPostgresExtension"]]
method_1egmvje_buildtargetmodel__call_28_NpgsqlModelBuilderExtensions_UseIdentityByDefaultColumns[["NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns"]]
method_1egmvje_buildtargetmodel__call_30_ModelBuilder_Entity[["ModelBuilder.Entity"]]
method_1egmvje_buildtargetmodel__call_530_EntityTypeBuilder_HasData[["EntityTypeBuilder.HasData"]]
method_1egmvje_buildtargetmodel__action_23_annotation_23__linear("Set model annotations")
method_1egmvje_buildtargetmodel__action_253_property_change_253__linear("Make KnowledgeUnit.EbookId nullable")
method_1egmvje_buildtargetmodel__action_27_enable_extension_27__linear("Enable Postgres vector extension")
method_1egmvje_buildtargetmodel__action_28_configuration_28__linear("Use identity-by-default columns for Postgres")
method_1egmvje_buildtargetmodel__action_30_entity_declaration_30__linear("Define Identity and domain entities schemas")
method_1egmvje_buildtargetmodel__action_49_index_creation_49__linear("Create indices")
method_1egmvje_buildtargetmodel__action_530_data_seed_530__linear("Seed SubscriptionPlan table")
method_1egmvje_buildtargetmodel__action_620_relationship_620__linear("Configure relationships and delete behaviors")
method_1egmvje_buildtargetmodel__action_634_navigation_634__linear("Define EF navigation properties")
method_1egmvje_buildtargetmodel__entry(["BuildTargetModel entry"])
method_1egmvje_buildtargetmodel__implicit_return(["return"])
method_1egmvje_buildtargetmodel__action_23_annotation_23__linear -->|next| method_1egmvje_buildtargetmodel__action_27_enable_extension_27__linear
method_1egmvje_buildtargetmodel__action_253_property_change_253__linear -->|next| method_1egmvje_buildtargetmodel__action_530_data_seed_530__linear
method_1egmvje_buildtargetmodel__action_27_enable_extension_27__linear -->|modelBuilder, extension name vector| method_1egmvje_buildtargetmodel__call_27_NpgsqlModelBuilderExtensions_HasPostgresExtension
method_1egmvje_buildtargetmodel__action_28_configuration_28__linear -->|modelBuilder| method_1egmvje_buildtargetmodel__call_28_NpgsqlModelBuilderExtensions_UseIdentityByDefaultColumns
method_1egmvje_buildtargetmodel__action_30_entity_declaration_30__linear -->|entity type name strings for many domain types e.g. Microsoft.AspNetCore.Identity.IdentityRole| method_1egmvje_buildtargetmodel__call_30_ModelBuilder_Entity
method_1egmvje_buildtargetmodel__action_49_index_creation_49__linear -->|next| method_1egmvje_buildtargetmodel__action_253_property_change_253__linear
method_1egmvje_buildtargetmodel__action_530_data_seed_530__linear -->|seed array for SubscriptionPlans 4 items with Id, AITokenLimit, MonthlyPrice, PlanName, StripeProductId| method_1egmvje_buildtargetmodel__call_530_EntityTypeBuilder_HasData
method_1egmvje_buildtargetmodel__action_620_relationship_620__linear -->|next| method_1egmvje_buildtargetmodel__action_634_navigation_634__linear
method_1egmvje_buildtargetmodel__action_634_navigation_634__linear -->|return| method_1egmvje_buildtargetmodel__implicit_return
method_1egmvje_buildtargetmodel__call_27_NpgsqlModelBuilderExtensions_HasPostgresExtension -->|next| method_1egmvje_buildtargetmodel__action_28_configuration_28__linear
method_1egmvje_buildtargetmodel__call_28_NpgsqlModelBuilderExtensions_UseIdentityByDefaultColumns -->|next| method_1egmvje_buildtargetmodel__action_30_entity_declaration_30__linear
method_1egmvje_buildtargetmodel__call_30_ModelBuilder_Entity -->|next| method_1egmvje_buildtargetmodel__action_49_index_creation_49__linear
method_1egmvje_buildtargetmodel__call_530_EntityTypeBuilder_HasData -->|next| method_1egmvje_buildtargetmodel__action_620_relationship_620__linear
method_1egmvje_buildtargetmodel__entry -->|next| method_1egmvje_buildtargetmodel__action_23_annotation_23__linear
```
## Diagram Validation
- Status: warn
- Warning: Control-flow extraction left 4 unresolved jumps.
- Warning: neighborhood-view: diagram file_6fusgm_20260513185108_makeknowledgeunitebookidnullable__neighborhood_view exceeds preferred complexity thresholds (13 nodes, 9 edges).
@@ -0,0 +1,76 @@
# 20260513185108_MakeKnowledgeUnitEbookIdNullable
- File ID: file:u0dg0d:20260513185108-makeknowledgeunitebookidnullable-
- Path: NexusReader.Data/Persistence/Migrations/20260513185108_MakeKnowledgeUnitEbookIdNullable.cs
- Role: database-config
- Layer: data
## Purpose
EF Core migration that makes the KnowledgeUnits.EbookId column nullable in the database schema and provides a reversible Down migration.
## Key Details
Up makes KnowledgeUnits.EbookId nullable (uuid); Down makes it non-nullable and assigns an all-zero Guid default.
## Symbols
- MakeKnowledgeUnitEbookIdNullable: EF Core migration that makes the KnowledgeUnits.EbookId column nullable in the database schema and provides a reversible Down migration.
- Up(): Applies the schema change to alter KnowledgeUnits.EbookId to be nullable.
- Down(): Reverts the schema change by making KnowledgeUnits.EbookId non-nullable and setting a default Guid value.
- MakeKnowledgeUnitEbookIdNullable: Represents an EF Core migration that changes the EbookId nullability on KnowledgeUnits.
## Dependencies
- No resolved dependencies.
## Calls
- No resolved calls.
## Coverage
- Symbols: 4
- Executable symbols: 2
- Executable symbols with control flow: 2
- Grounded edges: 4
- Unresolved references: 0
- Control-flow fragments: 2
- Unresolved jumps: 0
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 2
- Generated diagrams: 2
## Control Flow Fragments
- Up: 3 nodes, 2 edges, 0 jumps, 0 unsupported constructs
- Down: 3 nodes, 2 edges, 0 jumps, 0 unsupported constructs
## Diagrams
### 20260513185108_MakeKnowledgeUnitEbookIdNullable Neighborhood
```mermaid
flowchart LR
class_1gb1hzf_makeknowledgeunitebookidnullable("MakeKnowledgeUnitEbookIdNullable")
file_u0dg0d_20260513185108_makeknowledgeunitebookidnullable_("20260513185108_MakeKnowledgeUnitEbookIdNullable")
method_1xywi1n_down[["Down()"]]
method_jenau5_up[["Up()"]]
type_1e3plwu_makeknowledgeunitebookidnullable[/"MakeKnowledgeUnitEbookIdNullable"/]
```
### 20260513185108_MakeKnowledgeUnitEbookIdNullable Execution Overview
```mermaid
flowchart TD
class_1gb1hzf_makeknowledgeunitebookidnullable("MakeKnowledgeUnitEbookIdNullable")
method_1xywi1n_down[["Down()"]]
method_jenau5_up[["Up()"]]
class_1gb1hzf_makeknowledgeunitebookidnullable -->|contains| method_1xywi1n_down
class_1gb1hzf_makeknowledgeunitebookidnullable -->|contains| method_jenau5_up
```
## Diagram Validation
- Status: pass
@@ -0,0 +1,105 @@
# 20260514184243_AddDescriptionToEbook.Designer
- File ID: file:1vkv6ym:20260514184243-adddescriptiontoebook-designer-cs
- Path: NexusReader.Data/Persistence/Migrations/20260514184243_AddDescriptionToEbook.Designer.cs
- Role: database-config
- Layer: data
## Purpose
EF Core migration designer for 'AddDescriptionToEbook' that defines the target EF Core model snapshot (tables, columns, keys, indexes, relationships) and seeds subscription plan data for the database migration.
## Key Details
This migration snapshot registers the Postgres 'vector' extension (pgvector), configures vector columns for embeddings, extends AspNetUsers with subscription and AI token tracking, and seeds four subscription plans; it also adds a Description column to the Ebook table schema.
## Symbols
- AddDescriptionToEbook: EF Core migration designer for 'AddDescriptionToEbook' that defines the target EF Core model snapshot (tables, columns, keys, indexes, relationships) and seeds subscription plan data for the database migration.
- BuildTargetModel(): Builds the EF Core model snapshot used by this migration: applies annotations, extensions, entity/table/property/index/relationship mappings and data seeding.
- AddDescriptionToEbook: Partial EF Core Migration class that contains the BuildTargetModel snapshot for the 'AddDescriptionToEbook' migration.
## Dependencies
- imports NexusReader.Data/Persistence/AppDbContext.cs
- imports NexusReader.Domain/Entities/Author.cs
- imports NexusReader.Domain/Entities/Ebook.cs
- imports NexusReader.Domain/Entities/KnowledgeUnit.cs
- imports NexusReader.Domain/Entities/KnowledgeUnitLink.cs
- imports NexusReader.Domain/Entities/NexusUser.cs
- imports NexusReader.Domain/Entities/QuizResult.cs
- imports NexusReader.Domain/Entities/SemanticKnowledgeCache.cs
- imports NexusReader.Domain/Entities/SubscriptionPlan.cs
## Calls
- No resolved calls.
## Coverage
- Symbols: 3
- Executable symbols: 1
- Executable symbols with control flow: 1
- Grounded edges: 12
- Unresolved references: 0
- Control-flow fragments: 1
- Unresolved jumps: 0
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 2
- Generated diagrams: 2
## Control Flow Fragments
- BuildTargetModel: 18 nodes, 17 edges, 0 jumps, 0 unsupported constructs
## Diagrams
### 20260514184243_AddDescriptionToEbook.Designer Neighborhood
_Warnings: diagram file_1vkv6ym_20260514184243_adddescriptiontoebook_designer_cs_neighborhood_view exceeds preferred complexity thresholds (13 nodes, 9 edges)._
```mermaid
---
config:
flowchart:
defaultRenderer: "elk"
---
flowchart LR
class_tfj298_adddescriptiontoebook("AddDescriptionToEbook")
file_1vkv6ym_20260514184243_adddescriptiontoebook_designer_cs("20260514184243_AddDescriptionToEbook.Designer")
method_13h9yo2_buildtargetmodel[["BuildTargetModel()"]]
file_1b03oou_subscriptionplan_cs[/"SubscriptionPlan"/]
file_1d4ycw2_semanticknowledgecache_cs[/"SemanticKnowledgeCache"/]
file_1m6x5qy_knowledgeunitlink_cs[/"KnowledgeUnitLink"/]
file_1pacvtg_appdbcontext_cs[/"AppDbContext"/]
file_1wyr0y8_quizresult_cs[/"QuizResult"/]
file_1y56eud_author_cs[/"Author"/]
file_h6a0xu_knowledgeunit_cs[/"KnowledgeUnit"/]
file_lcvwj6_ebook_cs[/"Ebook"/]
file_xcxh5w_nexususer_cs[/"NexusUser"/]
type_52venu_adddescriptiontoebook[/"AddDescriptionToEbook"/]
file_1vkv6ym_20260514184243_adddescriptiontoebook_designer_cs -->|SubscriptionPlan| file_1b03oou_subscriptionplan_cs
file_1vkv6ym_20260514184243_adddescriptiontoebook_designer_cs -->|SemanticKnowledgeCache| file_1d4ycw2_semanticknowledgecache_cs
file_1vkv6ym_20260514184243_adddescriptiontoebook_designer_cs -->|KnowledgeUnitLink| file_1m6x5qy_knowledgeunitlink_cs
file_1vkv6ym_20260514184243_adddescriptiontoebook_designer_cs -->|AppDbContext| file_1pacvtg_appdbcontext_cs
file_1vkv6ym_20260514184243_adddescriptiontoebook_designer_cs -->|QuizResult| file_1wyr0y8_quizresult_cs
file_1vkv6ym_20260514184243_adddescriptiontoebook_designer_cs -->|Author| file_1y56eud_author_cs
file_1vkv6ym_20260514184243_adddescriptiontoebook_designer_cs -->|KnowledgeUnit| file_h6a0xu_knowledgeunit_cs
file_1vkv6ym_20260514184243_adddescriptiontoebook_designer_cs -->|Ebook| file_lcvwj6_ebook_cs
file_1vkv6ym_20260514184243_adddescriptiontoebook_designer_cs -->|NexusUser| file_xcxh5w_nexususer_cs
```
### 20260514184243_AddDescriptionToEbook.Designer Execution Overview
```mermaid
flowchart TD
class_tfj298_adddescriptiontoebook("AddDescriptionToEbook")
method_13h9yo2_buildtargetmodel[["BuildTargetModel()"]]
class_tfj298_adddescriptiontoebook -->|contains| method_13h9yo2_buildtargetmodel
```
## Diagram Validation
- Status: warn
- Warning: neighborhood-view: diagram file_1vkv6ym_20260514184243_adddescriptiontoebook_designer_cs_neighborhood_view exceeds preferred complexity thresholds (13 nodes, 9 edges).
@@ -0,0 +1,76 @@
# 20260514184243_AddDescriptionToEbook
- File ID: file:145xyqd:20260514184243-adddescriptiontoebook-cs
- Path: NexusReader.Data/Persistence/Migrations/20260514184243_AddDescriptionToEbook.cs
- Role: database-config
- Layer: data
## Purpose
EF Core migration that adds a nullable text Description column to the Ebooks table and can remove it on rollback.
## Key Details
Adds a nullable text column named 'Description' to the 'Ebooks' table in Up(); Down() drops that column.
## Symbols
- AddDescriptionToEbook: EF Core migration that adds a nullable text Description column to the Ebooks table and can remove it on rollback.
- Up(): Apply schema change: add a nullable text 'Description' column to the 'Ebooks' table.
- Down(): Revert schema change: remove the 'Description' column from the 'Ebooks' table.
- AddDescriptionToEbook: EF Core Migration class that encapsulates the schema change to add/remove the Description column on Ebooks.
## Dependencies
- No resolved dependencies.
## Calls
- No resolved calls.
## Coverage
- Symbols: 4
- Executable symbols: 2
- Executable symbols with control flow: 2
- Grounded edges: 4
- Unresolved references: 0
- Control-flow fragments: 2
- Unresolved jumps: 0
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 2
- Generated diagrams: 2
## Control Flow Fragments
- Up: 3 nodes, 2 edges, 0 jumps, 0 unsupported constructs
- Down: 3 nodes, 2 edges, 0 jumps, 0 unsupported constructs
## Diagrams
### 20260514184243_AddDescriptionToEbook Neighborhood
```mermaid
flowchart LR
class_1ca124f_adddescriptiontoebook("AddDescriptionToEbook")
file_145xyqd_20260514184243_adddescriptiontoebook_cs("20260514184243_AddDescriptionToEbook")
method_98t2qk_down[["Down()"]]
method_e05nak_up[["Up()"]]
type_8wi1r9_adddescriptiontoebook[/"AddDescriptionToEbook"/]
```
### 20260514184243_AddDescriptionToEbook Execution Overview
```mermaid
flowchart TD
class_1ca124f_adddescriptiontoebook("AddDescriptionToEbook")
method_98t2qk_down[["Down()"]]
method_e05nak_up[["Up()"]]
class_1ca124f_adddescriptiontoebook -->|contains| method_98t2qk_down
class_1ca124f_adddescriptiontoebook -->|contains| method_e05nak_up
```
## Diagram Validation
- Status: pass
@@ -0,0 +1,58 @@
# Author
- File ID: file:1y56eud:author-cs
- Path: NexusReader.Domain/Entities/Author.cs
- Role: entity
- Layer: domain
## Purpose
Domain entity representing an author with identity, name, and a collection of authored ebooks for persistence and ORM mapping.
## Key Details
POCO domain entity with data annotations for validation and schema ([Key], [Required], [MaxLength(255)]). Ebooks navigation collection is virtual and pre-initialized to List<Ebook>.
## Symbols
- Author: Domain entity representing an author with identity, name, and a collection of authored ebooks for persistence and ORM mapping.
- Author: Represents an author record for the domain/ORM layer, including primary key, name and related ebooks.
## Dependencies
- imports NexusReader.Domain/Entities/Ebook.cs
## Calls
- No resolved calls.
## Coverage
- Symbols: 2
- Executable symbols: 0
- Executable symbols with control flow: 0
- Grounded edges: 3
- Unresolved references: 0
- Control-flow fragments: 0
- Unresolved jumps: 0
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 1
- Generated diagrams: 1
## Diagrams
### Author Neighborhood
```mermaid
flowchart LR
class_1nsniny_author("Author")
file_1y56eud_author_cs("Author")
file_lcvwj6_ebook_cs[/"Ebook"/]
type_y9wry3_author[/"Author"/]
file_1y56eud_author_cs -->|Ebook| file_lcvwj6_ebook_cs
```
## Diagram Validation
- Status: pass
@@ -0,0 +1,61 @@
# Ebook
- File ID: file:lcvwj6:ebook-cs
- Path: NexusReader.Domain/Entities/Ebook.cs
- Role: entity
- Layer: domain
## Purpose
Defines the domain entity representing an uploaded or owned e-book, including metadata, relationships (Author, NexusUser), tenancy and ingestion/readiness status for application use and persistence.
## Key Details
POCO entity with EF Core data annotations: primary key (Id), required fields, max length constraints, foreign keys to Author and NexusUser, defaults for Id, AddedDate, TenantId and Progress, and a readiness flag (IsReadyForReading) used to indicate AI processing completion.
## Symbols
- Ebook: Defines the domain entity representing an uploaded or owned e-book, including metadata, relationships (Author, NexusUser), tenancy and ingestion/readiness status for application use and persistence.
- Ebook: Represents an e-book record stored in the domain/data model with metadata, relationships and ingestion/readiness state.
## Dependencies
- imports NexusReader.Domain/Entities/Author.cs
- imports NexusReader.Domain/Entities/NexusUser.cs
## Calls
- No resolved calls.
## Coverage
- Symbols: 2
- Executable symbols: 0
- Executable symbols with control flow: 0
- Grounded edges: 4
- Unresolved references: 0
- Control-flow fragments: 0
- Unresolved jumps: 0
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 1
- Generated diagrams: 1
## Diagrams
### Ebook Neighborhood
```mermaid
flowchart LR
class_1k2zgaa_ebook("Ebook")
file_lcvwj6_ebook_cs("Ebook")
file_1y56eud_author_cs[/"Author"/]
file_xcxh5w_nexususer_cs[/"NexusUser"/]
type_kzfhbn_ebook[/"Ebook"/]
file_lcvwj6_ebook_cs -->|Author| file_1y56eud_author_cs
file_lcvwj6_ebook_cs -->|NexusUser| file_xcxh5w_nexususer_cs
```
## Diagram Validation
- Status: pass
@@ -0,0 +1,64 @@
# KnowledgeUnit
- File ID: file:h6a0xu:knowledgeunit-cs
- Path: NexusReader.Domain/Entities/KnowledgeUnit.cs
- Role: entity
- Layer: domain
## Purpose
Defines the domain entity KnowledgeUnit representing a unit of extracted/ingested knowledge (content, type, metadata, links) stored per tenant with EF Core mapping attributes.
## Key Details
Primary key Id is intended as a content hash (comment). CreatedAt defaults to UTC now. Uses EF Core data annotations for schema (Key, Required, MaxLength, ForeignKey). Navigation properties are initialized to avoid null collections.
## Symbols
- KnowledgeUnit: Defines the domain entity KnowledgeUnit representing a unit of extracted/ingested knowledge (content, type, metadata, links) stored per tenant with EF Core mapping attributes.
- KnowledgeUnit: Represents a stored piece of knowledge (content + type + metadata) with tenant scoping and links to other KnowledgeUnits and an optional Ebook.
## Dependencies
- imports NexusReader.Domain/Entities/Ebook.cs
- imports NexusReader.Domain/Entities/KnowledgeUnitLink.cs
- imports NexusReader.Domain/Enums/KnowledgeUnitType.cs
## Calls
- No resolved calls.
## Coverage
- Symbols: 2
- Executable symbols: 0
- Executable symbols with control flow: 0
- Grounded edges: 5
- Unresolved references: 0
- Control-flow fragments: 0
- Unresolved jumps: 0
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 1
- Generated diagrams: 1
## Diagrams
### KnowledgeUnit Neighborhood
```mermaid
flowchart LR
class_fvtez6_knowledgeunit("KnowledgeUnit")
file_h6a0xu_knowledgeunit_cs("KnowledgeUnit")
file_17um7nh_knowledgeunittype_cs[/"KnowledgeUnitType"/]
file_1m6x5qy_knowledgeunitlink_cs[/"KnowledgeUnitLink"/]
file_lcvwj6_ebook_cs[/"Ebook"/]
type_sahnml_knowledgeunit[/"KnowledgeUnit"/]
file_h6a0xu_knowledgeunit_cs -->|KnowledgeUnitType| file_17um7nh_knowledgeunittype_cs
file_h6a0xu_knowledgeunit_cs -->|KnowledgeUnitLink| file_1m6x5qy_knowledgeunitlink_cs
file_h6a0xu_knowledgeunit_cs -->|Ebook| file_lcvwj6_ebook_cs
```
## Diagram Validation
- Status: pass
@@ -0,0 +1,58 @@
# KnowledgeUnitLink
- File ID: file:1m6x5qy:knowledgeunitlink-cs
- Path: NexusReader.Domain/Entities/KnowledgeUnitLink.cs
- Role: entity
- Layer: domain
## Purpose
Defines the domain entity KnowledgeUnitLink which models a directed relation between two KnowledgeUnit entities with metadata (relation type) and EF Core persistence annotations.
## Key Details
Entity uses EF Core data annotations for schema constraints and navigation: Id is PK, SourceUnitId/TargetUnitId are required string FKs (max 128), RelationType is required (max 50) with default "References", and navigation properties reference KnowledgeUnit via [ForeignKey].
## Symbols
- KnowledgeUnitLink: Defines the domain entity KnowledgeUnitLink which models a directed relation between two KnowledgeUnit entities with metadata (relation type) and EF Core persistence annotations.
- KnowledgeUnitLink: Represents a directed link between two KnowledgeUnit entities with a typed relation for persistence via EF Core.
## Dependencies
- imports NexusReader.Domain/Entities/KnowledgeUnit.cs
## Calls
- No resolved calls.
## Coverage
- Symbols: 2
- Executable symbols: 0
- Executable symbols with control flow: 0
- Grounded edges: 3
- Unresolved references: 0
- Control-flow fragments: 0
- Unresolved jumps: 0
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 1
- Generated diagrams: 1
## Diagrams
### KnowledgeUnitLink Neighborhood
```mermaid
flowchart LR
class_mqaz6_knowledgeunitlink("KnowledgeUnitLink")
file_1m6x5qy_knowledgeunitlink_cs("KnowledgeUnitLink")
file_h6a0xu_knowledgeunit_cs[/"KnowledgeUnit"/]
type_wq74ui_knowledgeunitlink[/"KnowledgeUnitLink"/]
file_1m6x5qy_knowledgeunitlink_cs -->|KnowledgeUnit| file_h6a0xu_knowledgeunit_cs
```
## Diagram Validation
- Status: pass
@@ -0,0 +1,63 @@
# NexusUser
- File ID: file:xcxh5w:nexususer-cs
- Path: NexusReader.Domain/Entities/NexusUser.cs
- Role: entity
- Layer: domain
## Purpose
Domain entity representing an application user, extending ASP.NET IdentityUser with multi-tenant, subscription and usage tracking plus navigation collections for related domain data.
## Key Details
NexusUser extends IdentityUser and embeds multi-tenancy (TenantId default 'global'), subscription linkage (SubscriptionPlanId + navigation), AI token accounting (AITokenLimit/AITokensUsed/LastAiActionDate) and collections for owned ebooks and quiz results; no runtime methods are defined in this file.
## Symbols
- NexusUser: Domain entity representing an application user, extending ASP.NET IdentityUser with multi-tenant, subscription and usage tracking plus navigation collections for related domain data.
- NexusUser: Represents a user in the NexusReader domain with tenant, subscription and AI-usage metadata plus relationships to ebooks and quiz results.
## Dependencies
- No resolved dependencies.
## Calls
- No resolved calls.
## Unresolved References
- dependency-target: Microsoft.AspNetCore.Identity.IdentityUser
- dependency-target: SubscriptionPlan (NexusReader.Domain.Entities)
- dependency-target: Ebook (NexusReader.Domain.Entities)
- dependency-target: QuizResult (NexusReader.Domain.Entities)
## Coverage
- Symbols: 2
- Executable symbols: 0
- Executable symbols with control flow: 0
- Grounded edges: 2
- Unresolved references: 4
- Control-flow fragments: 0
- Unresolved jumps: 0
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 1
- Generated diagrams: 1
## Diagrams
### NexusUser Neighborhood
```mermaid
flowchart LR
class_q7xqjm_nexususer("NexusUser")
file_xcxh5w_nexususer_cs("NexusUser")
type_1fmha7h_nexususer[/"NexusUser"/]
```
## Diagram Validation
- Status: pass
@@ -0,0 +1,76 @@
# QuizResult
- File ID: file:1wyr0y8:quizresult-cs
- Path: NexusReader.Domain/Entities/QuizResult.cs
- Role: entity
- Layer: domain
## Purpose
Domain entity that models and persists the result of an AI-generated quiz taken by a user, including score, totals, tenant scoping and completion timestamp.
## Key Details
Entity includes attribute metadata for EF (Key, Required, ForeignKey, MaxLength), default initializers (Guid.NewGuid, DateTime.UtcNow), and a computed Percentage property which guards against division by zero.
## Symbols
- QuizResult: Domain entity that models and persists the result of an AI-generated quiz taken by a user, including score, totals, tenant scoping and completion timestamp.
- .ctor (implicit): Implicit object initializer that sets default values for several properties when a QuizResult is created.
- Percentage (getter): Computes the score percentage of correct answers; guards against division by zero.
- QuizResult: Represents a persisted quiz attempt by a user, including score details, topic and tenant context.
## Dependencies
- No resolved dependencies.
## Calls
- No resolved calls.
## Coverage
- Symbols: 4
- Executable symbols: 2
- Executable symbols with control flow: 2
- Grounded edges: 4
- Unresolved references: 0
- Control-flow fragments: 2
- Unresolved jumps: 0
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 2
- Generated diagrams: 2
## Control Flow Fragments
- .ctor (implicit): 7 nodes, 6 edges, 0 jumps, 0 unsupported constructs
- Percentage (getter): 6 nodes, 6 edges, 0 jumps, 0 unsupported constructs
## Diagrams
### QuizResult Neighborhood
```mermaid
flowchart LR
class_xbp5rm_quizresult("QuizResult")
file_1wyr0y8_quizresult_cs("QuizResult")
method_160zwvx_ctor_implicit[[".ctor (implicit)"]]
method_ml3mse_percentage_getter[["Percentage (getter)"]]
type_1j77tf7_quizresult[/"QuizResult"/]
```
### QuizResult Execution Overview
```mermaid
flowchart TD
class_xbp5rm_quizresult("QuizResult")
method_160zwvx_ctor_implicit[[".ctor (implicit)"]]
method_ml3mse_percentage_getter[["Percentage (getter)"]]
class_xbp5rm_quizresult -->|contains| method_160zwvx_ctor_implicit
class_xbp5rm_quizresult -->|contains| method_ml3mse_percentage_getter
```
## Diagram Validation
- Status: pass
@@ -0,0 +1,61 @@
# SemanticKnowledgeCache
- File ID: file:1d4ycw2:semanticknowledgecache-cs
- Path: NexusReader.Domain/Entities/SemanticKnowledgeCache.cs
- Role: entity
- Layer: domain
## Purpose
Defines a domain entity that persists cached semantic knowledge (original text, model/prompt metadata, JSON payload) and its vector embedding for semantic search.
## Key Details
Entity stores deduplicated cached semantic artifacts keyed by ContentHash, includes model/prompt metadata, tenant scoping, JSON payload, optional Pgvector embedding (commented as 768 dims), and a UTC creation timestamp.
## Symbols
- SemanticKnowledgeCache: Defines a domain entity that persists cached semantic knowledge (original text, model/prompt metadata, JSON payload) and its vector embedding for semantic search.
- SemanticKnowledgeCache: Represents a cached semantic artifact including original text, serialized JSON, model/prompt metadata, tenant scoping, and an optional vector embedding used for semantic search.
## Dependencies
- No resolved dependencies.
## Calls
- No resolved calls.
## Unresolved References
- dependency-target: Pgvector (external package)
- dependency-target: System.ComponentModel.DataAnnotations (framework)
## Coverage
- Symbols: 2
- Executable symbols: 0
- Executable symbols with control flow: 0
- Grounded edges: 2
- Unresolved references: 2
- Control-flow fragments: 0
- Unresolved jumps: 0
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 1
- Generated diagrams: 1
## Diagrams
### SemanticKnowledgeCache Neighborhood
```mermaid
flowchart LR
class_e0216a_semanticknowledgecache("SemanticKnowledgeCache")
file_1d4ycw2_semanticknowledgecache_cs("SemanticKnowledgeCache")
type_1gdonul_semanticknowledgecache[/"SemanticKnowledgeCache"/]
```
## Diagram Validation
- Status: pass
@@ -0,0 +1,56 @@
# SubscriptionPlan
- File ID: file:1b03oou:subscriptionplan-cs
- Path: NexusReader.Domain/Entities/SubscriptionPlan.cs
- Role: entity
- Layer: domain
## Purpose
Defines the domain entity SubscriptionPlan which models subscription tiers, pricing, and token/quota limits for the application.
## Key Details
Simple POCO entity used for persisting subscription tier metadata; includes constants for well-known plan names and IDs, token quota fields (limit + unlimited flag), monthly price, and Stripe product id for billing integration.
## Symbols
- SubscriptionPlan: Defines the domain entity SubscriptionPlan which models subscription tiers, pricing, and token/quota limits for the application.
- SubscriptionPlan: Represents a subscription tier including identifiers, human name, token limits, pricing, and Stripe product mapping.
## Dependencies
- No resolved dependencies.
## Calls
- No resolved calls.
## Coverage
- Symbols: 2
- Executable symbols: 0
- Executable symbols with control flow: 0
- Grounded edges: 2
- Unresolved references: 0
- Control-flow fragments: 0
- Unresolved jumps: 0
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 1
- Generated diagrams: 1
## Diagrams
### SubscriptionPlan Neighborhood
```mermaid
flowchart LR
class_1ajhp9e_subscriptionplan("SubscriptionPlan")
file_1b03oou_subscriptionplan_cs("SubscriptionPlan")
type_1cvgax3_subscriptionplan[/"SubscriptionPlan"/]
```
## Diagram Validation
- Status: pass
@@ -0,0 +1,54 @@
# KnowledgeUnitType
- File ID: file:17um7nh:knowledgeunittype-cs
- Path: NexusReader.Domain/Enums/KnowledgeUnitType.cs
- Role: entity
- Layer: domain
## Purpose
Defines the KnowledgeUnitType enumeration used to categorize different kinds of knowledge units across the domain.
## Key Details
Simple domain enum used to tag or switch behavior based on the type of knowledge unit; no runtime logic in this file.
## Symbols
- KnowledgeUnitType: Enumerates the possible kinds of knowledge units (Section, Table, Definition, etc.) used by the domain.
## Dependencies
- No resolved dependencies.
## Calls
- No resolved calls.
## Coverage
- Symbols: 1
- Executable symbols: 0
- Executable symbols with control flow: 0
- Grounded edges: 1
- Unresolved references: 0
- Control-flow fragments: 0
- Unresolved jumps: 0
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 1
- Generated diagrams: 1
## Diagrams
### KnowledgeUnitType Neighborhood
```mermaid
flowchart LR
file_17um7nh_knowledgeunittype_cs("KnowledgeUnitType")
type_1jmw5xq_knowledgeunittype[/"KnowledgeUnitType"/]
```
## Diagram Validation
- Status: pass
@@ -0,0 +1,59 @@
# NexusReader.Domain
- File ID: file:167q7jt:nexusreader-domain-csproj
- Path: NexusReader.Domain/NexusReader.Domain.csproj
- Role: config
- Layer: infrastructure
## Purpose
Proj file for the NexusReader.Domain project: declares build/runtime settings and package dependencies for the Domain assembly.
## Key Details
Project uses SDK-style csproj (Microsoft.NET.Sdk). Implicit usings enabled, nullable reference types enabled, runtime configuration files generation enabled. Declares Pgvector and Microsoft.Extensions.Identity.Stores package dependencies.
## Symbols
- No extracted symbols.
## Dependencies
- No resolved dependencies.
## Calls
- No resolved calls.
## Unresolved References
- dependency-target: TargetFramework: net10.0 (line 4)
- dependency-target: PackageReference: Pgvector (line 11)
- dependency-target: PackageReference: Microsoft.Extensions.Identity.Stores (line 12)
## Coverage
- Symbols: 0
- Executable symbols: 0
- Executable symbols with control flow: 0
- Grounded edges: 0
- Unresolved references: 3
- Control-flow fragments: 0
- Unresolved jumps: 0
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 1
- Generated diagrams: 1
## Diagrams
### NexusReader.Domain Neighborhood
```mermaid
flowchart LR
file_167q7jt_nexusreader_domain_csproj("NexusReader.Domain")
```
## Diagram Validation
- Status: pass
@@ -0,0 +1,56 @@
# Class1
- File ID: file:43kjze:class1-cs
- Path: NexusReader.Infrastructure.Mobile/Class1.cs
- Role: unknown
- Layer: infrastructure
## Purpose
Placeholder/infrastructure mobile file; defines an empty class in the NexusReader.Infrastructure.Mobile namespace. Likely a stub for MAUI platform-specific services but contains no runtime behavior.
## Key Details
File contains a single empty class (lines 3-6). No methods, fields, registrations, or startup code present.
## Symbols
- Class1: Placeholder/infrastructure mobile file; defines an empty class in the NexusReader.Infrastructure.Mobile namespace. Likely a stub for MAUI platform-specific services but contains no runtime behavior.
- Class1: Empty placeholder class in the mobile infrastructure namespace; no behavior or members defined.
## Dependencies
- No resolved dependencies.
## Calls
- No resolved calls.
## Coverage
- Symbols: 2
- Executable symbols: 0
- Executable symbols with control flow: 0
- Grounded edges: 2
- Unresolved references: 0
- Control-flow fragments: 0
- Unresolved jumps: 0
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 1
- Generated diagrams: 1
## Diagrams
### Class1 Neighborhood
```mermaid
flowchart LR
class_1133tob_class1("Class1")
file_43kjze_class1_cs("Class1")
type_1n37540_class1[/"Class1"/]
```
## Diagram Validation
- Status: pass
@@ -0,0 +1,58 @@
# NexusReader.Infrastructure.Mobile
- File ID: file:qnk9mr:nexusreader-infrastructure-mobile-csproj
- Path: NexusReader.Infrastructure.Mobile/NexusReader.Infrastructure.Mobile.csproj
- Role: config
- Layer: infrastructure
## Purpose
MSBuild project file for the NexusReader.Infrastructure.Mobile MAUI mobile app; declares target frameworks, MAUI usage, a project reference to the Application project, and a NuGet dependency on Microsoft.Maui.Essentials.
## Key Details
Targets net10.0-android by default (lines 46 include conditional extensions for iOS/MacCatalyst/Windows), enables MAUI and MAUI Essentials (lines 78,20), references the application layer project (line 16). No runtime code present in this file; it configures build and package composition for the mobile infrastructure project.
## Symbols
- No extracted symbols.
## Dependencies
- No resolved dependencies.
## Calls
- No resolved calls.
## Unresolved References
- dependency-target: ../NexusReader.Application/NexusReader.Application.csproj
- dependency-target: Microsoft.Maui.Essentials (nuget)@10.0.20
## Coverage
- Symbols: 0
- Executable symbols: 0
- Executable symbols with control flow: 0
- Grounded edges: 0
- Unresolved references: 2
- Control-flow fragments: 0
- Unresolved jumps: 0
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 1
- Generated diagrams: 1
## Diagrams
### NexusReader.Infrastructure.Mobile Neighborhood
```mermaid
flowchart LR
file_qnk9mr_nexusreader_infrastructure_mobile_csproj("NexusReader.Infrastructure.Mobile")
```
## Diagram Validation
- Status: pass
@@ -0,0 +1,286 @@
# MauiPlatformService
- File ID: file:12lov7s:mauiplatformservice-cs
- Path: NexusReader.Infrastructure.Mobile/Services/MauiPlatformService.cs
- Role: service
- Layer: infrastructure
## Purpose
MAUI platform implementation of IPlatformService providing device context and haptic/vibration behaviors for the mobile app.
## Key Details
MAUI-specific service implementing IPlatformService; exposes device metadata mapping and uses MAUI HapticFeedback and Device APIs. Methods use try/catch to convert platform exceptions into FluentResults.
## Symbols
- MauiPlatformService: MAUI platform implementation of IPlatformService providing device context and haptic/vibration behaviors for the mobile app.
- VibrateSuccessAsync(): Performs a short double haptic click to indicate success and returns a FluentResults Result.
- VibrateErrorAsync(): Performs a long haptic press to indicate an error and returns a FluentResults Result.
- VibrateAsync(): Performs a single haptic click (parameter provided but not used) and returns a FluentResults Result.
- GetDeviceContext(): Reads MAUI Device and Display information, maps idiom and orientation to application types, and returns a DeviceContext wrapped in a FluentResults Result.
- MapDeviceType(): Maps MAUI DeviceIdiom values to the application's DeviceType enum.
- MapOrientation(): Maps MAUI DisplayOrientation values to the application's DisplayOrientation enum using a switch expression.
## Dependencies
- No resolved dependencies.
## Calls
- No resolved calls.
## Unresolved References
- dependency-target: NexusReader.Application.Abstractions/Services
- dependency-target: Microsoft.Maui.Devices (platform API)
- call-target: self
- call-target: self
## Coverage
- Symbols: 7
- Executable symbols: 6
- Executable symbols with control flow: 6
- Grounded edges: 7
- Unresolved references: 4
- Control-flow fragments: 6
- Unresolved jumps: 0
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 2
- Generated diagrams: 7
## Control Flow Fragments
- VibrateSuccessAsync: 11 nodes, 10 edges, 0 jumps, 0 unsupported constructs
- VibrateErrorAsync: 8 nodes, 7 edges, 0 jumps, 0 unsupported constructs
- VibrateAsync: 8 nodes, 7 edges, 0 jumps, 0 unsupported constructs
- GetDeviceContext: 16 nodes, 15 edges, 2 jumps, 0 unsupported constructs
- MapDeviceType: 28 nodes, 33 edges, 0 jumps, 0 unsupported constructs
- MapOrientation: 6 nodes, 5 edges, 0 jumps, 0 unsupported constructs
## Diagrams
### MauiPlatformService Neighborhood
```mermaid
flowchart LR
class_tx0x5k_mauiplatformservice("MauiPlatformService")
file_12lov7s_mauiplatformservice_cs("MauiPlatformService")
method_18ccdu4_mapdevicetype[["MapDeviceType()"]]
method_1ro58qu_vibrateerrorasync[["VibrateErrorAsync()"]]
method_60f4ut_getdevicecontext[["GetDeviceContext()"]]
method_jhc678_maporientation[["MapOrientation()"]]
method_twu1zj_vibratesuccessasync[["VibrateSuccessAsync()"]]
method_va46s8_vibrateasync[["VibrateAsync()"]]
```
### MauiPlatformService Execution Overview
```mermaid
flowchart TD
class_tx0x5k_mauiplatformservice("MauiPlatformService")
method_18ccdu4_mapdevicetype[["MapDeviceType()"]]
method_1ro58qu_vibrateerrorasync[["VibrateErrorAsync()"]]
method_60f4ut_getdevicecontext[["GetDeviceContext()"]]
method_jhc678_maporientation[["MapOrientation()"]]
method_twu1zj_vibratesuccessasync[["VibrateSuccessAsync()"]]
method_va46s8_vibrateasync[["VibrateAsync()"]]
unresolved_unresolved_31gcz4_call_target{"Unresolved: MapOrientation"}
unresolved_unresolved_eh9ae0_call_target{"Unresolved: MapDeviceType"}
class_tx0x5k_mauiplatformservice -->|contains| method_18ccdu4_mapdevicetype
class_tx0x5k_mauiplatformservice -->|contains| method_1ro58qu_vibrateerrorasync
class_tx0x5k_mauiplatformservice -->|contains| method_60f4ut_getdevicecontext
class_tx0x5k_mauiplatformservice -->|contains| method_jhc678_maporientation
class_tx0x5k_mauiplatformservice -->|contains| method_twu1zj_vibratesuccessasync
class_tx0x5k_mauiplatformservice -->|contains| method_va46s8_vibrateasync
method_60f4ut_getdevicecontext -->|unresolved call| unresolved_unresolved_31gcz4_call_target
method_60f4ut_getdevicecontext -->|unresolved call| unresolved_unresolved_eh9ae0_call_target
```
### VibrateSuccessAsync() Control Flow
```mermaid
flowchart TD
method_twu1zj_vibratesuccessasync__action_12_try_catch_12__linear("Wraps platform haptic calls and returns failure on exception")
method_twu1zj_vibratesuccessasync__action_12_vibratesuccessasync_try_12_0__try("Begins protected execution")
method_twu1zj_vibratesuccessasync__action_14_platform_call_14__linear("Haptic click (first)")
method_twu1zj_vibratesuccessasync__action_15_async_wait_15__linear("Delay between haptic calls")
method_twu1zj_vibratesuccessasync__action_15_vibratesuccessasync_await_15_1__await[["Waits for async work"]]
method_twu1zj_vibratesuccessasync__action_16_platform_call_16__linear("Haptic click (second)")
method_twu1zj_vibratesuccessasync__action_19_vibratesuccessasync_catch_19_3__catch("catch Exception ex")
method_twu1zj_vibratesuccessasync__entry(["VibrateSuccessAsync entry"])
method_twu1zj_vibratesuccessasync__action_17_return_17__return(["returns success"])
method_twu1zj_vibratesuccessasync__action_17_vibratesuccessasync_return_17_2__return(["Returns result"])
method_twu1zj_vibratesuccessasync__action_21_vibratesuccessasync_return_21_4__return(["Returns result"])
method_twu1zj_vibratesuccessasync__action_12_try_catch_12__linear -->|next| method_twu1zj_vibratesuccessasync__action_12_vibratesuccessasync_try_12_0__try
method_twu1zj_vibratesuccessasync__action_12_vibratesuccessasync_try_12_0__try -->|next| method_twu1zj_vibratesuccessasync__action_14_platform_call_14__linear
method_twu1zj_vibratesuccessasync__action_14_platform_call_14__linear -->|next| method_twu1zj_vibratesuccessasync__action_15_vibratesuccessasync_await_15_1__await
method_twu1zj_vibratesuccessasync__action_15_async_wait_15__linear -->|next| method_twu1zj_vibratesuccessasync__action_16_platform_call_16__linear
method_twu1zj_vibratesuccessasync__action_15_vibratesuccessasync_await_15_1__await -->|next| method_twu1zj_vibratesuccessasync__action_15_async_wait_15__linear
method_twu1zj_vibratesuccessasync__action_16_platform_call_16__linear -->|return| method_twu1zj_vibratesuccessasync__action_17_return_17__return
method_twu1zj_vibratesuccessasync__action_17_return_17__return -->|return| method_twu1zj_vibratesuccessasync__action_17_vibratesuccessasync_return_17_2__return
method_twu1zj_vibratesuccessasync__action_17_vibratesuccessasync_return_17_2__return -->|exception| method_twu1zj_vibratesuccessasync__action_19_vibratesuccessasync_catch_19_3__catch
method_twu1zj_vibratesuccessasync__action_19_vibratesuccessasync_catch_19_3__catch -->|return| method_twu1zj_vibratesuccessasync__action_21_vibratesuccessasync_return_21_4__return
method_twu1zj_vibratesuccessasync__entry -->|next| method_twu1zj_vibratesuccessasync__action_12_try_catch_12__linear
```
### VibrateErrorAsync() Control Flow
```mermaid
flowchart TD
method_1ro58qu_vibrateerrorasync__action_27_try_catch_27__linear("Wraps platform haptic call and returns failure on exception")
method_1ro58qu_vibrateerrorasync__action_27_vibrateerrorasync_try_27_0__try("Begins protected execution")
method_1ro58qu_vibrateerrorasync__action_29_platform_call_29__linear("Haptic long press")
method_1ro58qu_vibrateerrorasync__action_32_vibrateerrorasync_catch_32_2__catch("catch Exception ex")
method_1ro58qu_vibrateerrorasync__entry(["VibrateErrorAsync entry"])
method_1ro58qu_vibrateerrorasync__action_30_return_30__return(["returns success"])
method_1ro58qu_vibrateerrorasync__action_30_vibrateerrorasync_return_30_1__return(["Returns result"])
method_1ro58qu_vibrateerrorasync__action_34_vibrateerrorasync_return_34_3__return(["Returns result"])
method_1ro58qu_vibrateerrorasync__action_27_try_catch_27__linear -->|next| method_1ro58qu_vibrateerrorasync__action_27_vibrateerrorasync_try_27_0__try
method_1ro58qu_vibrateerrorasync__action_27_vibrateerrorasync_try_27_0__try -->|next| method_1ro58qu_vibrateerrorasync__action_29_platform_call_29__linear
method_1ro58qu_vibrateerrorasync__action_29_platform_call_29__linear -->|return| method_1ro58qu_vibrateerrorasync__action_30_return_30__return
method_1ro58qu_vibrateerrorasync__action_30_return_30__return -->|return| method_1ro58qu_vibrateerrorasync__action_30_vibrateerrorasync_return_30_1__return
method_1ro58qu_vibrateerrorasync__action_30_vibrateerrorasync_return_30_1__return -->|exception| method_1ro58qu_vibrateerrorasync__action_32_vibrateerrorasync_catch_32_2__catch
method_1ro58qu_vibrateerrorasync__action_32_vibrateerrorasync_catch_32_2__catch -->|return| method_1ro58qu_vibrateerrorasync__action_34_vibrateerrorasync_return_34_3__return
method_1ro58qu_vibrateerrorasync__entry -->|next| method_1ro58qu_vibrateerrorasync__action_27_try_catch_27__linear
```
### VibrateAsync() Control Flow
```mermaid
flowchart TD
method_va46s8_vibrateasync__action_40_try_catch_40__linear("Wraps platform haptic call and returns failure on exception")
method_va46s8_vibrateasync__action_40_vibrateasync_try_40_0__try("Begins protected execution")
method_va46s8_vibrateasync__action_42_platform_call_42__linear("Haptic click")
method_va46s8_vibrateasync__action_45_vibrateasync_catch_45_2__catch("catch Exception ex")
method_va46s8_vibrateasync__entry(["VibrateAsync entry"])
method_va46s8_vibrateasync__action_43_return_43__return(["returns success"])
method_va46s8_vibrateasync__action_43_vibrateasync_return_43_1__return(["Returns result"])
method_va46s8_vibrateasync__action_47_vibrateasync_return_47_3__return(["Returns result"])
method_va46s8_vibrateasync__action_40_try_catch_40__linear -->|next| method_va46s8_vibrateasync__action_40_vibrateasync_try_40_0__try
method_va46s8_vibrateasync__action_40_vibrateasync_try_40_0__try -->|next| method_va46s8_vibrateasync__action_42_platform_call_42__linear
method_va46s8_vibrateasync__action_42_platform_call_42__linear -->|return| method_va46s8_vibrateasync__action_43_return_43__return
method_va46s8_vibrateasync__action_43_return_43__return -->|return| method_va46s8_vibrateasync__action_43_vibrateasync_return_43_1__return
method_va46s8_vibrateasync__action_43_vibrateasync_return_43_1__return -->|exception| method_va46s8_vibrateasync__action_45_vibrateasync_catch_45_2__catch
method_va46s8_vibrateasync__action_45_vibrateasync_catch_45_2__catch -->|return| method_va46s8_vibrateasync__action_47_vibrateasync_return_47_3__return
method_va46s8_vibrateasync__entry -->|next| method_va46s8_vibrateasync__action_40_try_catch_40__linear
```
### GetDeviceContext() Control Flow
```mermaid
flowchart TD
method_60f4ut_getdevicecontext__call_61_MapDeviceType[["MapDeviceType"]]
method_60f4ut_getdevicecontext__call_62_MapOrientation[["MapOrientation"]]
method_60f4ut_getdevicecontext__action_53_getdevicecontext_try_53_0__try("Begins protected execution")
method_60f4ut_getdevicecontext__action_53_try_catch_53__linear("Wraps device reads and mapping and returns failure on exception")
method_60f4ut_getdevicecontext__action_55_platform_call_55__linear("Read device info")
method_60f4ut_getdevicecontext__action_56_platform_call_56__linear("Read display info")
method_60f4ut_getdevicecontext__action_58_construct_58__linear("Construct DeviceContext DTO")
method_60f4ut_getdevicecontext__action_61_getdevicecontext_mapping_61_2__linear("Maps data or transforms shape")
method_60f4ut_getdevicecontext__action_61_mapping_61__linear("Map idiom to application DeviceType")
method_60f4ut_getdevicecontext__action_62_getdevicecontext_mapping_62_3__linear("Maps data or transforms shape")
method_60f4ut_getdevicecontext__action_62_mapping_62__linear("Map display orientation to application DisplayOrientation")
method_60f4ut_getdevicecontext__action_65_getdevicecontext_catch_65_4__catch("catch Exception ex")
method_60f4ut_getdevicecontext__entry(["GetDeviceContext entry"])
method_60f4ut_getdevicecontext__action_58_getdevicecontext_return_58_1__return(["Returns result"])
method_60f4ut_getdevicecontext__action_58_return_58__return(["returns success with DeviceContext"])
method_60f4ut_getdevicecontext__action_67_getdevicecontext_return_67_5__return(["Returns result"])
method_60f4ut_getdevicecontext__action_53_getdevicecontext_try_53_0__try -->|next| method_60f4ut_getdevicecontext__action_55_platform_call_55__linear
method_60f4ut_getdevicecontext__action_53_try_catch_53__linear -->|next| method_60f4ut_getdevicecontext__action_53_getdevicecontext_try_53_0__try
method_60f4ut_getdevicecontext__action_55_platform_call_55__linear -->|next| method_60f4ut_getdevicecontext__action_56_platform_call_56__linear
method_60f4ut_getdevicecontext__action_56_platform_call_56__linear -->|return| method_60f4ut_getdevicecontext__action_58_return_58__return
method_60f4ut_getdevicecontext__action_58_construct_58__linear -->|next| method_60f4ut_getdevicecontext__action_61_getdevicecontext_mapping_61_2__linear
method_60f4ut_getdevicecontext__action_58_getdevicecontext_return_58_1__return -->|next| method_60f4ut_getdevicecontext__action_58_construct_58__linear
method_60f4ut_getdevicecontext__action_58_return_58__return -->|return| method_60f4ut_getdevicecontext__action_58_getdevicecontext_return_58_1__return
method_60f4ut_getdevicecontext__action_61_getdevicecontext_mapping_61_2__linear -->|next| method_60f4ut_getdevicecontext__action_61_mapping_61__linear
method_60f4ut_getdevicecontext__action_61_mapping_61__linear -->|device.Idiom| method_60f4ut_getdevicecontext__call_61_MapDeviceType
method_60f4ut_getdevicecontext__action_62_getdevicecontext_mapping_62_3__linear -->|next| method_60f4ut_getdevicecontext__action_62_mapping_62__linear
method_60f4ut_getdevicecontext__action_62_mapping_62__linear -->|display.Orientation| method_60f4ut_getdevicecontext__call_62_MapOrientation
method_60f4ut_getdevicecontext__action_65_getdevicecontext_catch_65_4__catch -->|return| method_60f4ut_getdevicecontext__action_67_getdevicecontext_return_67_5__return
method_60f4ut_getdevicecontext__call_61_MapDeviceType -->|next| method_60f4ut_getdevicecontext__action_62_getdevicecontext_mapping_62_3__linear
method_60f4ut_getdevicecontext__call_62_MapOrientation -->|exception| method_60f4ut_getdevicecontext__action_65_getdevicecontext_catch_65_4__catch
method_60f4ut_getdevicecontext__entry -->|next| method_60f4ut_getdevicecontext__action_53_try_catch_53__linear
```
### MapDeviceType() Control Flow
_Warnings: diagram method_18ccdu4_mapdevicetype__fragment_diagram exceeds preferred complexity thresholds (28 nodes, 33 edges)._
```mermaid
---
config:
flowchart:
defaultRenderer: "elk"
---
flowchart TD
method_18ccdu4_mapdevicetype__action_71_mapdevicetype_mapping_71_0__linear("Maps data or transforms shape")
method_18ccdu4_mapdevicetype__action_73_branch_73__condition{"idiom == DeviceIdiom.Phone"}
method_18ccdu4_mapdevicetype__action_73_branch_73__false("continue")
method_18ccdu4_mapdevicetype__action_73_branch_73__merge("merge")
method_18ccdu4_mapdevicetype__action_73_branch_73__true("Phone")
method_18ccdu4_mapdevicetype__action_73_mapdevicetype_guard_clause_73_1__condition{"idiom == DeviceIdiom.Phone"}
method_18ccdu4_mapdevicetype__action_73_mapdevicetype_guard_clause_73_1__false("continue")
method_18ccdu4_mapdevicetype__action_73_mapdevicetype_guard_clause_73_1__merge("merge")
method_18ccdu4_mapdevicetype__action_73_mapdevicetype_guard_clause_73_1__true("exit")
method_18ccdu4_mapdevicetype__action_74_branch_74__condition{"idiom == DeviceIdiom.Tablet"}
method_18ccdu4_mapdevicetype__action_74_branch_74__false("continue")
method_18ccdu4_mapdevicetype__action_74_branch_74__merge("merge")
method_18ccdu4_mapdevicetype__action_74_branch_74__true("Tablet")
method_18ccdu4_mapdevicetype__action_74_mapdevicetype_guard_clause_74_2__condition{"idiom == DeviceIdiom.Tablet"}
method_18ccdu4_mapdevicetype__action_74_mapdevicetype_guard_clause_74_2__false("continue")
method_18ccdu4_mapdevicetype__action_74_mapdevicetype_guard_clause_74_2__merge("merge")
method_18ccdu4_mapdevicetype__action_74_mapdevicetype_guard_clause_74_2__true("exit")
method_18ccdu4_mapdevicetype__action_75_branch_75__condition{"idiom == DeviceIdiom.Desktop"}
method_18ccdu4_mapdevicetype__action_75_branch_75__false("continue")
method_18ccdu4_mapdevicetype__action_75_branch_75__merge("merge")
method_18ccdu4_mapdevicetype__action_75_branch_75__true("Desktop")
method_18ccdu4_mapdevicetype__action_75_mapdevicetype_guard_clause_75_3__condition{"idiom == DeviceIdiom.Desktop"}
method_18ccdu4_mapdevicetype__action_75_mapdevicetype_guard_clause_75_3__false("continue")
method_18ccdu4_mapdevicetype__action_75_mapdevicetype_guard_clause_75_3__merge("merge")
method_18ccdu4_mapdevicetype__action_75_mapdevicetype_guard_clause_75_3__true("exit")
method_18ccdu4_mapdevicetype__entry(["MapDeviceType entry"])
method_18ccdu4_mapdevicetype__action_76_mapdevicetype_return_76_4__return(["Returns result"])
method_18ccdu4_mapdevicetype__action_76_return_76__return(["default Unknown"])
method_18ccdu4_mapdevicetype__action_71_mapdevicetype_mapping_71_0__linear -->|next| method_18ccdu4_mapdevicetype__action_73_branch_73__condition
method_18ccdu4_mapdevicetype__action_73_branch_73__condition -->|continue| method_18ccdu4_mapdevicetype__action_73_branch_73__false
method_18ccdu4_mapdevicetype__action_73_branch_73__condition -->|Phone| method_18ccdu4_mapdevicetype__action_73_branch_73__true
method_18ccdu4_mapdevicetype__action_73_branch_73__false -->|next| method_18ccdu4_mapdevicetype__action_73_branch_73__merge
method_18ccdu4_mapdevicetype__action_73_branch_73__merge -->|next| method_18ccdu4_mapdevicetype__action_73_mapdevicetype_guard_clause_73_1__condition
method_18ccdu4_mapdevicetype__action_73_branch_73__true -->|next| method_18ccdu4_mapdevicetype__action_73_branch_73__merge
method_18ccdu4_mapdevicetype__action_73_mapdevicetype_guard_clause_73_1__condition -->|continue| method_18ccdu4_mapdevicetype__action_73_mapdevicetype_guard_clause_73_1__false
method_18ccdu4_mapdevicetype__action_73_mapdevicetype_guard_clause_73_1__condition -->|exit| method_18ccdu4_mapdevicetype__action_73_mapdevicetype_guard_clause_73_1__true
method_18ccdu4_mapdevicetype__action_73_mapdevicetype_guard_clause_73_1__false -->|next| method_18ccdu4_mapdevicetype__action_73_mapdevicetype_guard_clause_73_1__merge
method_18ccdu4_mapdevicetype__action_73_mapdevicetype_guard_clause_73_1__merge -->|next| method_18ccdu4_mapdevicetype__action_74_branch_74__condition
method_18ccdu4_mapdevicetype__action_73_mapdevicetype_guard_clause_73_1__true -->|next| method_18ccdu4_mapdevicetype__action_73_mapdevicetype_guard_clause_73_1__merge
method_18ccdu4_mapdevicetype__action_74_branch_74__condition -->|continue| method_18ccdu4_mapdevicetype__action_74_branch_74__false
method_18ccdu4_mapdevicetype__action_74_branch_74__condition -->|Tablet| method_18ccdu4_mapdevicetype__action_74_branch_74__true
method_18ccdu4_mapdevicetype__action_74_branch_74__false -->|next| method_18ccdu4_mapdevicetype__action_74_branch_74__merge
method_18ccdu4_mapdevicetype__action_74_branch_74__merge -->|next| method_18ccdu4_mapdevicetype__action_74_mapdevicetype_guard_clause_74_2__condition
method_18ccdu4_mapdevicetype__action_74_branch_74__true -->|next| method_18ccdu4_mapdevicetype__action_74_branch_74__merge
method_18ccdu4_mapdevicetype__action_74_mapdevicetype_guard_clause_74_2__condition -->|continue| method_18ccdu4_mapdevicetype__action_74_mapdevicetype_guard_clause_74_2__false
method_18ccdu4_mapdevicetype__action_74_mapdevicetype_guard_clause_74_2__condition -->|exit| method_18ccdu4_mapdevicetype__action_74_mapdevicetype_guard_clause_74_2__true
method_18ccdu4_mapdevicetype__action_74_mapdevicetype_guard_clause_74_2__false -->|next| method_18ccdu4_mapdevicetype__action_74_mapdevicetype_guard_clause_74_2__merge
method_18ccdu4_mapdevicetype__action_74_mapdevicetype_guard_clause_74_2__merge -->|next| method_18ccdu4_mapdevicetype__action_75_mapdevicetype_guard_clause_75_3__condition
method_18ccdu4_mapdevicetype__action_74_mapdevicetype_guard_clause_74_2__true -->|next| method_18ccdu4_mapdevicetype__action_74_mapdevicetype_guard_clause_74_2__merge
method_18ccdu4_mapdevicetype__action_75_branch_75__condition -->|continue| method_18ccdu4_mapdevicetype__action_75_branch_75__false
method_18ccdu4_mapdevicetype__action_75_branch_75__condition -->|Desktop| method_18ccdu4_mapdevicetype__action_75_branch_75__true
method_18ccdu4_mapdevicetype__action_75_branch_75__false -->|next| method_18ccdu4_mapdevicetype__action_75_branch_75__merge
method_18ccdu4_mapdevicetype__action_75_branch_75__merge -->|return| method_18ccdu4_mapdevicetype__action_76_mapdevicetype_return_76_4__return
method_18ccdu4_mapdevicetype__action_75_branch_75__true -->|next| method_18ccdu4_mapdevicetype__action_75_branch_75__merge
method_18ccdu4_mapdevicetype__action_75_mapdevicetype_guard_clause_75_3__condition -->|continue| method_18ccdu4_mapdevicetype__action_75_mapdevicetype_guard_clause_75_3__false
method_18ccdu4_mapdevicetype__action_75_mapdevicetype_guard_clause_75_3__condition -->|exit| method_18ccdu4_mapdevicetype__action_75_mapdevicetype_guard_clause_75_3__true
method_18ccdu4_mapdevicetype__action_75_mapdevicetype_guard_clause_75_3__false -->|next| method_18ccdu4_mapdevicetype__action_75_mapdevicetype_guard_clause_75_3__merge
method_18ccdu4_mapdevicetype__action_75_mapdevicetype_guard_clause_75_3__merge -->|next| method_18ccdu4_mapdevicetype__action_75_branch_75__condition
method_18ccdu4_mapdevicetype__action_75_mapdevicetype_guard_clause_75_3__true -->|next| method_18ccdu4_mapdevicetype__action_75_mapdevicetype_guard_clause_75_3__merge
method_18ccdu4_mapdevicetype__action_76_mapdevicetype_return_76_4__return -->|return| method_18ccdu4_mapdevicetype__action_76_return_76__return
method_18ccdu4_mapdevicetype__entry -->|next| method_18ccdu4_mapdevicetype__action_71_mapdevicetype_mapping_71_0__linear
```
## Diagram Validation
- Status: warn
- Warning: control-flow: diagram method_18ccdu4_mapdevicetype__fragment_diagram exceeds preferred complexity thresholds (28 nodes, 33 edges).
@@ -0,0 +1,291 @@
# MauiStorageService
- File ID: file:d17zn6:mauistorageservice-cs
- Path: NexusReader.Infrastructure.Mobile/Services/MauiStorageService.cs
- Role: service
- Layer: infrastructure
## Purpose
Provides a MAUI-specific implementation of INativeStorageService that wraps Preferences and SecureStorage to persist simple keys/values, returning FluentResults and converting exceptions to failure results.
## Key Details
Synchronous Preferences calls are wrapped in Task.FromResult; secure storage calls are awaited. All methods catch Exception and convert to Result.Fail(ex.Message), exposing exception messages as failure reasons.
## Symbols
- MauiStorageService: Provides a MAUI-specific implementation of INativeStorageService that wraps Preferences and SecureStorage to persist simple keys/values, returning FluentResults and converting exceptions to failure results.
- SaveStringAsync(): Saves a string value to MAUI Preferences under the provided key and returns a Fluent Result indicating success or failure.
- GetStringAsync(): Reads a string from MAUI Preferences for the given key and returns the value wrapped in a Fluent Result.
- SaveBoolAsync(): Saves a boolean value to MAUI Preferences and returns success/failure as a Fluent Result.
- GetBoolAsync(): Reads a boolean from MAUI Preferences with an optional default and returns it wrapped in a Fluent Result.
- RemoveAsync(): Removes a key from MAUI Preferences and returns a Fluent Result indicating success or failure.
- SaveSecureString(): Asynchronously saves a string to MAUI SecureStorage and returns a Fluent Result for success/failure.
- GetSecureString(): Asynchronously retrieves a string from MAUI SecureStorage and returns it wrapped in a Fluent Result.
- RemoveSecureAsync(): Removes a key from MAUI SecureStorage and returns a Fluent Result indicating success or failure.
- MauiStorageService: Concrete MAUI implementation of INativeStorageService that adapts Preferences and SecureStorage to the application's storage abstraction.
## Dependencies
- No resolved dependencies.
## Calls
- No resolved calls.
## Unresolved References
- dependency-target: NexusReader.Application.Abstractions.Services (interface reference)
- dependency-target: Microsoft.Maui.Storage (Preferences, SecureStorage)
- dependency-target: FluentResults (Result)
- interaction-target: Preferences.Default.Set(key, value)
- interaction-target: Preferences.Default.Get(key, (string?)null)
- interaction-target: Preferences.Default.Set(key, value)
- interaction-target: Preferences.Default.Get(key, defaultValue)
- interaction-target: Preferences.Default.Remove(key)
- interaction-target: await SecureStorage.Default.SetAsync(key, value)
- interaction-target: await SecureStorage.Default.GetAsync(key)
- interaction-target: SecureStorage.Default.Remove(key)
## Coverage
- Symbols: 10
- Executable symbols: 8
- Executable symbols with control flow: 8
- Grounded edges: 10
- Unresolved references: 11
- Control-flow fragments: 8
- Unresolved jumps: 0
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 2
- Generated diagrams: 10
## Control Flow Fragments
- SaveStringAsync: 7 nodes, 6 edges, 0 jumps, 0 unsupported constructs
- GetStringAsync: 7 nodes, 6 edges, 0 jumps, 0 unsupported constructs
- SaveBoolAsync: 7 nodes, 6 edges, 0 jumps, 0 unsupported constructs
- GetBoolAsync: 7 nodes, 6 edges, 0 jumps, 0 unsupported constructs
- RemoveAsync: 7 nodes, 6 edges, 0 jumps, 0 unsupported constructs
- SaveSecureString: 8 nodes, 7 edges, 0 jumps, 0 unsupported constructs
- GetSecureString: 8 nodes, 7 edges, 0 jumps, 0 unsupported constructs
- RemoveSecureAsync: 7 nodes, 6 edges, 0 jumps, 0 unsupported constructs
## Diagrams
### MauiStorageService Neighborhood
```mermaid
flowchart LR
class_jm4wx0_mauistorageservice("MauiStorageService")
file_d17zn6_mauistorageservice_cs("MauiStorageService")
method_1bfedhw_getsecurestring[["GetSecureString()"]]
method_1w0f8ik_removeasync[["RemoveAsync()"]]
method_6i8lek_getstringasync[["GetStringAsync()"]]
method_ef0iff_saveboolasync[["SaveBoolAsync()"]]
method_h3fyyz_savesecurestring[["SaveSecureString()"]]
method_kv7eey_removesecureasync[["RemoveSecureAsync()"]]
method_rzym3m_getboolasync[["GetBoolAsync()"]]
method_s95smj_savestringasync[["SaveStringAsync()"]]
type_1nbofxi_mauistorageservice[/"MauiStorageService"/]
```
### MauiStorageService Execution Overview
```mermaid
flowchart TD
class_jm4wx0_mauistorageservice("MauiStorageService")
method_1bfedhw_getsecurestring[["GetSecureString()"]]
method_1w0f8ik_removeasync[["RemoveAsync()"]]
method_6i8lek_getstringasync[["GetStringAsync()"]]
method_ef0iff_saveboolasync[["SaveBoolAsync()"]]
method_h3fyyz_savesecurestring[["SaveSecureString()"]]
method_kv7eey_removesecureasync[["RemoveSecureAsync()"]]
method_rzym3m_getboolasync[["GetBoolAsync()"]]
method_s95smj_savestringasync[["SaveStringAsync()"]]
unresolved_unresolved_14jpd1a_interaction_target{"Unresolved: SecureStorage.Default.Remove(key)"}
unresolved_unresolved_14mo52j_interaction_target{"Unresolved: Preferences.Default.Set(key, value)"}
unresolved_unresolved_1kr9h8o_interaction_target{"Unresolved: Preferences.Default.Get(key, (string?)null)"}
unresolved_unresolved_1n470aa_interaction_target{"Unresolved: Preferences.Default.Remove(key)"}
unresolved_unresolved_1owtkrk_interaction_target{"Unresolved: await SecureStorage.Default.GetAsync(key)"}
unresolved_unresolved_iaz95s_interaction_target{"Unresolved: Preferences.Default.Get(key, defaultValue)"}
unresolved_unresolved_kxn7x9_interaction_target{"Unresolved: await SecureStorage.Default.SetAsync(key, value)"}
class_jm4wx0_mauistorageservice -->|contains| method_1bfedhw_getsecurestring
class_jm4wx0_mauistorageservice -->|contains| method_1w0f8ik_removeasync
class_jm4wx0_mauistorageservice -->|contains| method_6i8lek_getstringasync
class_jm4wx0_mauistorageservice -->|contains| method_ef0iff_saveboolasync
class_jm4wx0_mauistorageservice -->|contains| method_h3fyyz_savesecurestring
class_jm4wx0_mauistorageservice -->|contains| method_kv7eey_removesecureasync
class_jm4wx0_mauistorageservice -->|contains| method_rzym3m_getboolasync
class_jm4wx0_mauistorageservice -->|contains| method_s95smj_savestringasync
class_jm4wx0_mauistorageservice -->|unresolved interaction| unresolved_unresolved_14jpd1a_interaction_target
class_jm4wx0_mauistorageservice -->|unresolved interaction| unresolved_unresolved_14mo52j_interaction_target
class_jm4wx0_mauistorageservice -->|unresolved interaction| unresolved_unresolved_14mo52j_interaction_target
class_jm4wx0_mauistorageservice -->|unresolved interaction| unresolved_unresolved_1kr9h8o_interaction_target
class_jm4wx0_mauistorageservice -->|unresolved interaction| unresolved_unresolved_1n470aa_interaction_target
class_jm4wx0_mauistorageservice -->|unresolved interaction| unresolved_unresolved_1owtkrk_interaction_target
class_jm4wx0_mauistorageservice -->|unresolved interaction| unresolved_unresolved_iaz95s_interaction_target
class_jm4wx0_mauistorageservice -->|unresolved interaction| unresolved_unresolved_kxn7x9_interaction_target
```
### SaveStringAsync() Control Flow
```mermaid
flowchart TD
method_s95smj_savestringasync__action_12_savestringasync_try_12_0__try("Begins protected execution")
method_s95smj_savestringasync__action_12_try_catch_12__linear("Handle exceptions and return failure result")
method_s95smj_savestringasync__action_17_savestringasync_catch_17_2__catch("catch Exception ex")
method_s95smj_savestringasync__entry(["SaveStringAsync entry"])
method_s95smj_savestringasync__action_14_external_call_14__linear("Write to Preferences")
method_s95smj_savestringasync__action_15_savestringasync_return_15_1__return(["Returns result"])
method_s95smj_savestringasync__action_19_savestringasync_return_19_3__return(["Returns result"])
method_s95smj_savestringasync__action_12_savestringasync_try_12_0__try -->|next| method_s95smj_savestringasync__action_14_external_call_14__linear
method_s95smj_savestringasync__action_12_try_catch_12__linear -->|next| method_s95smj_savestringasync__action_12_savestringasync_try_12_0__try
method_s95smj_savestringasync__action_14_external_call_14__linear -->|return| method_s95smj_savestringasync__action_15_savestringasync_return_15_1__return
method_s95smj_savestringasync__action_15_savestringasync_return_15_1__return -->|exception| method_s95smj_savestringasync__action_17_savestringasync_catch_17_2__catch
method_s95smj_savestringasync__action_17_savestringasync_catch_17_2__catch -->|return| method_s95smj_savestringasync__action_19_savestringasync_return_19_3__return
method_s95smj_savestringasync__entry -->|next| method_s95smj_savestringasync__action_12_try_catch_12__linear
```
### GetStringAsync() Control Flow
```mermaid
flowchart TD
method_6i8lek_getstringasync__action_25_getstringasync_try_25_0__try("Begins protected execution")
method_6i8lek_getstringasync__action_25_try_catch_25__linear("Handle exceptions and return failure result")
method_6i8lek_getstringasync__action_29_getstringasync_catch_29_2__catch("catch Exception ex")
method_6i8lek_getstringasync__entry(["GetStringAsync entry"])
method_6i8lek_getstringasync__action_27_external_call_27__linear("Read from Preferences")
method_6i8lek_getstringasync__action_27_getstringasync_return_27_1__return(["Returns result"])
method_6i8lek_getstringasync__action_31_getstringasync_return_31_3__return(["Returns result"])
method_6i8lek_getstringasync__action_25_getstringasync_try_25_0__try -->|return| method_6i8lek_getstringasync__action_27_getstringasync_return_27_1__return
method_6i8lek_getstringasync__action_25_try_catch_25__linear -->|next| method_6i8lek_getstringasync__action_25_getstringasync_try_25_0__try
method_6i8lek_getstringasync__action_27_external_call_27__linear -->|exception| method_6i8lek_getstringasync__action_29_getstringasync_catch_29_2__catch
method_6i8lek_getstringasync__action_27_getstringasync_return_27_1__return -->|next| method_6i8lek_getstringasync__action_27_external_call_27__linear
method_6i8lek_getstringasync__action_29_getstringasync_catch_29_2__catch -->|return| method_6i8lek_getstringasync__action_31_getstringasync_return_31_3__return
method_6i8lek_getstringasync__entry -->|next| method_6i8lek_getstringasync__action_25_try_catch_25__linear
```
### SaveBoolAsync() Control Flow
```mermaid
flowchart TD
method_ef0iff_saveboolasync__action_37_saveboolasync_try_37_0__try("Begins protected execution")
method_ef0iff_saveboolasync__action_37_try_catch_37__linear("Handle exceptions")
method_ef0iff_saveboolasync__action_42_saveboolasync_catch_42_2__catch("catch Exception ex")
method_ef0iff_saveboolasync__entry(["SaveBoolAsync entry"])
method_ef0iff_saveboolasync__action_39_external_call_39__linear("Write bool to Preferences")
method_ef0iff_saveboolasync__action_40_saveboolasync_return_40_1__return(["Returns result"])
method_ef0iff_saveboolasync__action_44_saveboolasync_return_44_3__return(["Returns result"])
method_ef0iff_saveboolasync__action_37_saveboolasync_try_37_0__try -->|next| method_ef0iff_saveboolasync__action_39_external_call_39__linear
method_ef0iff_saveboolasync__action_37_try_catch_37__linear -->|next| method_ef0iff_saveboolasync__action_37_saveboolasync_try_37_0__try
method_ef0iff_saveboolasync__action_39_external_call_39__linear -->|return| method_ef0iff_saveboolasync__action_40_saveboolasync_return_40_1__return
method_ef0iff_saveboolasync__action_40_saveboolasync_return_40_1__return -->|exception| method_ef0iff_saveboolasync__action_42_saveboolasync_catch_42_2__catch
method_ef0iff_saveboolasync__action_42_saveboolasync_catch_42_2__catch -->|return| method_ef0iff_saveboolasync__action_44_saveboolasync_return_44_3__return
method_ef0iff_saveboolasync__entry -->|next| method_ef0iff_saveboolasync__action_37_try_catch_37__linear
```
### GetBoolAsync() Control Flow
```mermaid
flowchart TD
method_rzym3m_getboolasync__action_50_getboolasync_try_50_0__try("Begins protected execution")
method_rzym3m_getboolasync__action_50_try_catch_50__linear("Handle exceptions")
method_rzym3m_getboolasync__action_54_getboolasync_catch_54_2__catch("catch Exception ex")
method_rzym3m_getboolasync__entry(["GetBoolAsync entry"])
method_rzym3m_getboolasync__action_52_external_call_52__linear("Read bool from Preferences")
method_rzym3m_getboolasync__action_52_getboolasync_return_52_1__return(["Returns result"])
method_rzym3m_getboolasync__action_56_getboolasync_return_56_3__return(["Returns result"])
method_rzym3m_getboolasync__action_50_getboolasync_try_50_0__try -->|return| method_rzym3m_getboolasync__action_52_getboolasync_return_52_1__return
method_rzym3m_getboolasync__action_50_try_catch_50__linear -->|next| method_rzym3m_getboolasync__action_50_getboolasync_try_50_0__try
method_rzym3m_getboolasync__action_52_external_call_52__linear -->|exception| method_rzym3m_getboolasync__action_54_getboolasync_catch_54_2__catch
method_rzym3m_getboolasync__action_52_getboolasync_return_52_1__return -->|next| method_rzym3m_getboolasync__action_52_external_call_52__linear
method_rzym3m_getboolasync__action_54_getboolasync_catch_54_2__catch -->|return| method_rzym3m_getboolasync__action_56_getboolasync_return_56_3__return
method_rzym3m_getboolasync__entry -->|next| method_rzym3m_getboolasync__action_50_try_catch_50__linear
```
### RemoveAsync() Control Flow
```mermaid
flowchart TD
method_1w0f8ik_removeasync__action_62_removeasync_try_62_0__try("Begins protected execution")
method_1w0f8ik_removeasync__action_62_try_catch_62__linear("Handle exceptions")
method_1w0f8ik_removeasync__action_67_removeasync_catch_67_2__catch("catch Exception ex")
method_1w0f8ik_removeasync__entry(["RemoveAsync entry"])
method_1w0f8ik_removeasync__action_64_external_call_64__linear("Remove key from Preferences")
method_1w0f8ik_removeasync__action_65_removeasync_return_65_1__return(["Returns result"])
method_1w0f8ik_removeasync__action_69_removeasync_return_69_3__return(["Returns result"])
method_1w0f8ik_removeasync__action_62_removeasync_try_62_0__try -->|next| method_1w0f8ik_removeasync__action_64_external_call_64__linear
method_1w0f8ik_removeasync__action_62_try_catch_62__linear -->|next| method_1w0f8ik_removeasync__action_62_removeasync_try_62_0__try
method_1w0f8ik_removeasync__action_64_external_call_64__linear -->|return| method_1w0f8ik_removeasync__action_65_removeasync_return_65_1__return
method_1w0f8ik_removeasync__action_65_removeasync_return_65_1__return -->|exception| method_1w0f8ik_removeasync__action_67_removeasync_catch_67_2__catch
method_1w0f8ik_removeasync__action_67_removeasync_catch_67_2__catch -->|return| method_1w0f8ik_removeasync__action_69_removeasync_return_69_3__return
method_1w0f8ik_removeasync__entry -->|next| method_1w0f8ik_removeasync__action_62_try_catch_62__linear
```
### SaveSecureString() Control Flow
```mermaid
flowchart TD
method_h3fyyz_savesecurestring__action_75_savesecurestring_try_75_0__try("Begins protected execution")
method_h3fyyz_savesecurestring__action_75_try_catch_75__linear("Handle exceptions for secure save")
method_h3fyyz_savesecurestring__action_77_savesecurestring_await_77_1__await[["Waits for async work"]]
method_h3fyyz_savesecurestring__action_80_savesecurestring_catch_80_3__catch("catch Exception ex")
method_h3fyyz_savesecurestring__entry(["SaveSecureString entry"])
method_h3fyyz_savesecurestring__action_77_external_call_77__linear("Write to SecureStorage (async)")
method_h3fyyz_savesecurestring__action_78_savesecurestring_return_78_2__return(["Returns result"])
method_h3fyyz_savesecurestring__action_82_savesecurestring_return_82_4__return(["Returns result"])
method_h3fyyz_savesecurestring__action_75_savesecurestring_try_75_0__try -->|next| method_h3fyyz_savesecurestring__action_77_external_call_77__linear
method_h3fyyz_savesecurestring__action_75_try_catch_75__linear -->|next| method_h3fyyz_savesecurestring__action_75_savesecurestring_try_75_0__try
method_h3fyyz_savesecurestring__action_77_external_call_77__linear -->|next| method_h3fyyz_savesecurestring__action_77_savesecurestring_await_77_1__await
method_h3fyyz_savesecurestring__action_77_savesecurestring_await_77_1__await -->|return| method_h3fyyz_savesecurestring__action_78_savesecurestring_return_78_2__return
method_h3fyyz_savesecurestring__action_78_savesecurestring_return_78_2__return -->|exception| method_h3fyyz_savesecurestring__action_80_savesecurestring_catch_80_3__catch
method_h3fyyz_savesecurestring__action_80_savesecurestring_catch_80_3__catch -->|return| method_h3fyyz_savesecurestring__action_82_savesecurestring_return_82_4__return
method_h3fyyz_savesecurestring__entry -->|next| method_h3fyyz_savesecurestring__action_75_try_catch_75__linear
```
### GetSecureString() Control Flow
```mermaid
flowchart TD
method_1bfedhw_getsecurestring__action_88_getsecurestring_try_88_0__try("Begins protected execution")
method_1bfedhw_getsecurestring__action_88_try_catch_88__linear("Handle exceptions for secure read")
method_1bfedhw_getsecurestring__action_90_getsecurestring_await_90_1__await[["Waits for async work"]]
method_1bfedhw_getsecurestring__action_92_getsecurestring_catch_92_3__catch("catch Exception ex")
method_1bfedhw_getsecurestring__entry(["GetSecureString entry"])
method_1bfedhw_getsecurestring__action_90_external_call_90__linear("Read from SecureStorage (async)")
method_1bfedhw_getsecurestring__action_90_getsecurestring_return_90_2__return(["Returns result"])
method_1bfedhw_getsecurestring__action_94_getsecurestring_return_94_4__return(["Returns result"])
method_1bfedhw_getsecurestring__action_88_getsecurestring_try_88_0__try -->|next| method_1bfedhw_getsecurestring__action_90_getsecurestring_await_90_1__await
method_1bfedhw_getsecurestring__action_88_try_catch_88__linear -->|next| method_1bfedhw_getsecurestring__action_88_getsecurestring_try_88_0__try
method_1bfedhw_getsecurestring__action_90_external_call_90__linear -->|exception| method_1bfedhw_getsecurestring__action_92_getsecurestring_catch_92_3__catch
method_1bfedhw_getsecurestring__action_90_getsecurestring_await_90_1__await -->|return| method_1bfedhw_getsecurestring__action_90_getsecurestring_return_90_2__return
method_1bfedhw_getsecurestring__action_90_getsecurestring_return_90_2__return -->|next| method_1bfedhw_getsecurestring__action_90_external_call_90__linear
method_1bfedhw_getsecurestring__action_92_getsecurestring_catch_92_3__catch -->|return| method_1bfedhw_getsecurestring__action_94_getsecurestring_return_94_4__return
method_1bfedhw_getsecurestring__entry -->|next| method_1bfedhw_getsecurestring__action_88_try_catch_88__linear
```
### RemoveSecureAsync() Control Flow
```mermaid
flowchart TD
method_kv7eey_removesecureasync__action_100_removesecureasync_try_100_0__try("Begins protected execution")
method_kv7eey_removesecureasync__action_100_try_catch_100__linear("Handle exceptions")
method_kv7eey_removesecureasync__action_105_removesecureasync_catch_105_2__catch("catch Exception ex")
method_kv7eey_removesecureasync__entry(["RemoveSecureAsync entry"])
method_kv7eey_removesecureasync__action_102_external_call_102__linear("Remove key from SecureStorage")
method_kv7eey_removesecureasync__action_103_removesecureasync_return_103_1__return(["Returns result"])
method_kv7eey_removesecureasync__action_107_removesecureasync_return_107_3__return(["Returns result"])
method_kv7eey_removesecureasync__action_100_removesecureasync_try_100_0__try -->|next| method_kv7eey_removesecureasync__action_102_external_call_102__linear
method_kv7eey_removesecureasync__action_100_try_catch_100__linear -->|next| method_kv7eey_removesecureasync__action_100_removesecureasync_try_100_0__try
method_kv7eey_removesecureasync__action_102_external_call_102__linear -->|return| method_kv7eey_removesecureasync__action_103_removesecureasync_return_103_1__return
method_kv7eey_removesecureasync__action_103_removesecureasync_return_103_1__return -->|exception| method_kv7eey_removesecureasync__action_105_removesecureasync_catch_105_2__catch
method_kv7eey_removesecureasync__action_105_removesecureasync_catch_105_2__catch -->|return| method_kv7eey_removesecureasync__action_107_removesecureasync_return_107_3__return
method_kv7eey_removesecureasync__entry -->|next| method_kv7eey_removesecureasync__action_100_try_catch_100__linear
```
## Diagram Validation
- Status: pass
@@ -0,0 +1,56 @@
# AiSettings
- File ID: file:11mkiaz:aisettings-cs
- Path: NexusReader.Infrastructure/Configuration/AiSettings.cs
- Role: config
- Layer: infrastructure
## Purpose
Defines typed configuration/settings for AI (Google) integration used for options binding and runtime configuration of model, embedding, token limits, retries, and temperature.
## Key Details
Exposes SectionName = "Ai:Google" for config binding; defaults target Gemini family models, embedding model id, high MaxInputTokens (15000), MaxOutputTokens 1000, RetryAttempts 3 and low Temperature 0.1.
## Symbols
- AiSettings: Defines typed configuration/settings for AI (Google) integration used for options binding and runtime configuration of model, embedding, token limits, retries, and temperature.
- AiSettings: Holds AI integration configuration values (Google API key, model choices, token limits, retry and sampling settings) for options/config binding.
## Dependencies
- No resolved dependencies.
## Calls
- No resolved calls.
## Coverage
- Symbols: 2
- Executable symbols: 0
- Executable symbols with control flow: 0
- Grounded edges: 2
- Unresolved references: 0
- Control-flow fragments: 0
- Unresolved jumps: 0
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 1
- Generated diagrams: 1
## Diagrams
### AiSettings Neighborhood
```mermaid
flowchart LR
class_1e23oyo_aisettings("AiSettings")
file_11mkiaz_aisettings_cs("AiSettings")
type_7ek9gn_aisettings[/"AiSettings"/]
```
## Diagram Validation
- Status: pass
@@ -0,0 +1,56 @@
# StripeSettings
- File ID: file:faws7u:stripesettings-cs
- Path: NexusReader.Infrastructure/Configuration/StripeSettings.cs
- Role: config
- Layer: infrastructure
## Purpose
Defines a configuration model for Stripe-related settings (product IDs) used for binding application configuration (Options pattern).
## Key Details
Simple immutable record used for configuration binding; includes a SectionName constant ("Stripe") to locate settings in IConfiguration.
## Symbols
- StripeSettings: Defines a configuration model for Stripe-related settings (product IDs) used for binding application configuration (Options pattern).
- StripeSettings: Holds Stripe product identifiers and exposes the configuration section name for binding.
## Dependencies
- No resolved dependencies.
## Calls
- No resolved calls.
## Coverage
- Symbols: 2
- Executable symbols: 0
- Executable symbols with control flow: 0
- Grounded edges: 2
- Unresolved references: 0
- Control-flow fragments: 0
- Unresolved jumps: 0
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 1
- Generated diagrams: 1
## Diagrams
### StripeSettings Neighborhood
```mermaid
flowchart LR
class_1mqu7tw_stripesettings("StripeSettings")
file_faws7u_stripesettings_cs("StripeSettings")
type_mcoiln_stripesettings[/"StripeSettings"/]
```
## Diagram Validation
- Status: pass
@@ -0,0 +1,340 @@
# DependencyInjection
- File ID: file:r7svsj:dependencyinjection-cs
- Path: NexusReader.Infrastructure/DependencyInjection.cs
- Role: service-registration
- Layer: infrastructure
## Purpose
Registers and configures infrastructure services (persistence, external clients, AI/embedding, background jobs, authorization, and scoped application services) into the DI container for the NexusReader application.
## Key Details
Conditional DB provider selection (Postgres vs Sqlite), conditional Hangfire registration when Postgres present, AI resilience pipeline with custom exception predicate and configurable retry attempts, AI API key presence warning, multiple scoped service registrations to align with AppDbContext lifetime.
## Symbols
- DependencyInjection: Registers and configures infrastructure services (persistence, external clients, AI/embedding, background jobs, authorization, and scoped application services) into the DI container for the NexusReader application.
- AddInfrastructure(): Configures and registers persistence (Postgres/Sqlite), external clients (Qdrant, Neo4j), Hangfire, AI settings/pipelines/clients, application service implementations, and authorization into the DI container.
- Assembly(): Exposes the assembly that contains the DependencyInjection class (useful for scanning/registration reflection).
- DependencyInjection: Static DI composition class that exposes AddInfrastructure and the assembly reference for the Infrastructure layer.
- IInfrastructureMarker: Marker interface used to identify the infrastructure assembly/types during scanning or composition.
- InfrastructureMarker: Internal concrete implementation of IInfrastructureMarker used solely to register a marker instance in DI.
## Dependencies
- imports NexusReader.Infrastructure/Services/KnowledgeService.cs
- imports NexusReader.Infrastructure/Services/EpubReaderService.cs
- imports NexusReader.Infrastructure/Services/EpubMetadataExtractor.cs
- imports NexusReader.Infrastructure/Services/BookStorageService.cs
- imports NexusReader.Infrastructure/Persistence/EbookRepository.cs
- imports NexusReader.Infrastructure/RealTime/SignalRSyncBroadcaster.cs
## Calls
- No resolved calls.
## Unresolved References
- dependency-target: NexusReader.Data.Persistence/AppDbContext.cs
- dependency-target: NexusReader.Application.Security.Authorization/ProUserHandler.cs
- call-target: NexusReader.Data.Persistence/AppDbContext.cs
- call-target: unknown
- call-target: unknown
- call-target: unknown
- call-target: unknown
- call-target: unknown
- call-target: unknown
- call-target: NexusReader.Infrastructure/Configuration/AiSettings.cs
- call-target: unknown
- call-target: unknown
- call-target: unknown
- call-target: unknown
- call-target: unknown
- call-target: NexusReader.Infrastructure/Services/KnowledgeService.cs
- call-target: NexusReader.Infrastructure/Services/EpubReaderService.cs
- call-target: NexusReader.Infrastructure/Services/EpubMetadataExtractor.cs
- call-target: NexusReader.Infrastructure/Services/BookStorageService.cs
- call-target: NexusReader.Infrastructure/Persistence/EbookRepository.cs
- call-target: NexusReader.Infrastructure/RealTime/SignalRSyncBroadcaster.cs
- call-target: NexusReader.Application.Security.Authorization/ProUserHandler.cs
- call-target: self
- call-target: self
## Coverage
- Symbols: 6
- Executable symbols: 2
- Executable symbols with control flow: 2
- Grounded edges: 12
- Unresolved references: 24
- Control-flow fragments: 2
- Unresolved jumps: 22
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 2
- Generated diagrams: 4
## Control Flow Fragments
- AddInfrastructure: 61 nodes, 67 edges, 21 jumps, 0 unsupported constructs
- Assembly: 4 nodes, 3 edges, 1 jumps, 0 unsupported constructs
## Diagrams
### DependencyInjection Neighborhood
_Warnings: diagram file_r7svsj_dependencyinjection_cs_neighborhood_view exceeds preferred complexity thresholds (13 nodes, 6 edges)._
```mermaid
---
config:
flowchart:
defaultRenderer: "elk"
---
flowchart LR
class_k4fx0v_dependencyinjection("DependencyInjection")
file_r7svsj_dependencyinjection_cs("DependencyInjection")
method_1c1pgjw_assembly[["Assembly()"]]
method_7atrx1_addinfrastructure[["AddInfrastructure()"]]
file_10i5sd6_signalrsyncbroadcaster_cs[/"SignalRSyncBroadcaster"/]
file_14qnurl_bookstorageservice_cs[/"BookStorageService"/]
file_27eki7_knowledgeservice_cs[/"KnowledgeService"/]
file_d3gg9l_epubmetadataextractor_cs[/"EpubMetadataExtractor"/]
file_q4k94a_epubreaderservice_cs[/"EpubReaderService"/]
file_veuxa3_ebookrepository_cs[/"EbookRepository"/]
type_14djij0_infrastructuremarker[/"InfrastructureMarker"/]
type_1f52ore_dependencyinjection[/"DependencyInjection"/]
type_1y9p8ya_iinfrastructuremarker[/"IInfrastructureMarker"/]
file_r7svsj_dependencyinjection_cs -->|SignalRSyncBroadcaster| file_10i5sd6_signalrsyncbroadcaster_cs
file_r7svsj_dependencyinjection_cs -->|BookStorageService| file_14qnurl_bookstorageservice_cs
file_r7svsj_dependencyinjection_cs -->|KnowledgeService| file_27eki7_knowledgeservice_cs
file_r7svsj_dependencyinjection_cs -->|EpubMetadataExtractor| file_d3gg9l_epubmetadataextractor_cs
file_r7svsj_dependencyinjection_cs -->|EpubReaderService| file_q4k94a_epubreaderservice_cs
file_r7svsj_dependencyinjection_cs -->|EbookRepository| file_veuxa3_ebookrepository_cs
```
### DependencyInjection Execution Overview
_Warnings: diagram file_r7svsj_dependencyinjection_cs_execution_view exceeds preferred complexity thresholds (25 nodes, 24 edges)._
```mermaid
---
config:
flowchart:
defaultRenderer: "elk"
---
flowchart TD
class_k4fx0v_dependencyinjection("DependencyInjection")
method_1c1pgjw_assembly[["Assembly()"]]
method_7atrx1_addinfrastructure[["AddInfrastructure()"]]
unresolved_unresolved_10n4wv1_call_target{"Unresolved: InfrastructureMarker (type)"}
unresolved_unresolved_134hl5l_call_target{"Unresolved: ShouldHandle predicate"}
unresolved_unresolved_15cp2jv_call_target{"Unresolved: AiSettings (type)"}
unresolved_unresolved_15p1osa_call_target{"Unresolved: SignalRSyncBroadcaster (type)"}
unresolved_unresolved_19yvsnv_call_target{"Unresolved: EpubReaderService (type)"}
unresolved_unresolved_1a0lsd0_call_target{"Unresolved: AppDbContext (type)"}
unresolved_unresolved_1e9zmi6_call_target{"Unresolved: GraphDatabase.Driver"}
unresolved_unresolved_1en7f0v_call_target{"Unresolved: BookStorageService (type)"}
unresolved_unresolved_1qfa48h_call_target{"Unresolved: AddDbContextFactory<T>"}
unresolved_unresolved_1quafzl_call_target{"Unresolved: EpubMetadataExtractor (type)"}
unresolved_unresolved_1s64w8s_call_target{"Unresolved: AddHangfire"}
unresolved_unresolved_1sopn1x_call_target{"Unresolved: AddChatClient"}
unresolved_unresolved_1xf24ib_call_target{"Unresolved: AddResiliencePipeline"}
unresolved_unresolved_72pwa6_call_target{"Unresolved: EbookRepository (type)"}
unresolved_unresolved_err9l6_call_target{"Unresolved: AddEmbeddingGenerator"}
unresolved_unresolved_fkfwxl_call_target{"Unresolved: typeof(DependencyInjection).Assembly"}
unresolved_unresolved_grr5wo_call_target{"Unresolved: ProUserHandler (type)"}
unresolved_unresolved_kw71kk_call_target{"Unresolved: AddSingleton<QdrantClient>"}
unresolved_unresolved_lpwlzz_call_target{"Unresolved: AddHangfireServer"}
unresolved_unresolved_qnp595_call_target{"Unresolved: AddDbContext<T>"}
unresolved_unresolved_rm4h5e_call_target{"Unresolved: Get<T> (IConfigurationSection)"}
unresolved_unresolved_t9z36n_call_target{"Unresolved: KnowledgeService (type)"}
class_k4fx0v_dependencyinjection -->|contains| method_1c1pgjw_assembly
class_k4fx0v_dependencyinjection -->|contains| method_7atrx1_addinfrastructure
method_1c1pgjw_assembly -->|unresolved call| unresolved_unresolved_fkfwxl_call_target
method_7atrx1_addinfrastructure -->|unresolved call| unresolved_unresolved_10n4wv1_call_target
method_7atrx1_addinfrastructure -->|unresolved call| unresolved_unresolved_134hl5l_call_target
method_7atrx1_addinfrastructure -->|unresolved call| unresolved_unresolved_15cp2jv_call_target
method_7atrx1_addinfrastructure -->|unresolved call| unresolved_unresolved_15p1osa_call_target
method_7atrx1_addinfrastructure -->|unresolved call| unresolved_unresolved_19yvsnv_call_target
method_7atrx1_addinfrastructure -->|unresolved call| unresolved_unresolved_1a0lsd0_call_target
method_7atrx1_addinfrastructure -->|unresolved call| unresolved_unresolved_1e9zmi6_call_target
method_7atrx1_addinfrastructure -->|unresolved call| unresolved_unresolved_1en7f0v_call_target
method_7atrx1_addinfrastructure -->|unresolved call| unresolved_unresolved_1qfa48h_call_target
method_7atrx1_addinfrastructure -->|unresolved call| unresolved_unresolved_1quafzl_call_target
method_7atrx1_addinfrastructure -->|unresolved call| unresolved_unresolved_1s64w8s_call_target
method_7atrx1_addinfrastructure -->|unresolved call| unresolved_unresolved_1sopn1x_call_target
method_7atrx1_addinfrastructure -->|unresolved call| unresolved_unresolved_1xf24ib_call_target
method_7atrx1_addinfrastructure -->|unresolved call| unresolved_unresolved_72pwa6_call_target
method_7atrx1_addinfrastructure -->|unresolved call| unresolved_unresolved_err9l6_call_target
method_7atrx1_addinfrastructure -->|unresolved call| unresolved_unresolved_grr5wo_call_target
method_7atrx1_addinfrastructure -->|unresolved call| unresolved_unresolved_kw71kk_call_target
method_7atrx1_addinfrastructure -->|unresolved call| unresolved_unresolved_lpwlzz_call_target
method_7atrx1_addinfrastructure -->|unresolved call| unresolved_unresolved_qnp595_call_target
method_7atrx1_addinfrastructure -->|unresolved call| unresolved_unresolved_rm4h5e_call_target
method_7atrx1_addinfrastructure -->|unresolved call| unresolved_unresolved_t9z36n_call_target
```
### AddInfrastructure() Control Flow
_Warnings: diagram method_7atrx1_addinfrastructure__fragment_diagram exceeds preferred complexity thresholds (61 nodes, 67 edges)._
```mermaid
---
config:
flowchart:
defaultRenderer: "elk"
---
flowchart TD
method_7atrx1_addinfrastructure__call_105_AddEmbeddingGenerator[["AddEmbeddingGenerator"]]
method_7atrx1_addinfrastructure__call_112_KnowledgeService_type_[["KnowledgeService (type)"]]
method_7atrx1_addinfrastructure__call_113_EpubReaderService_type_[["EpubReaderService (type)"]]
method_7atrx1_addinfrastructure__call_114_EpubMetadataExtractor_type_[["EpubMetadataExtractor (type)"]]
method_7atrx1_addinfrastructure__call_118_BookStorageService_type_[["BookStorageService (type)"]]
method_7atrx1_addinfrastructure__call_121_EbookRepository_type_[["EbookRepository (type)"]]
method_7atrx1_addinfrastructure__call_124_SignalRSyncBroadcaster_type_[["SignalRSyncBroadcaster (type)"]]
method_7atrx1_addinfrastructure__call_131_ProUserHandler_type_[["ProUserHandler (type)"]]
method_7atrx1_addinfrastructure__call_132_InfrastructureMarker_type_[["InfrastructureMarker (type)"]]
method_7atrx1_addinfrastructure__call_36_AddDbContextFactory_T_[["AddDbContextFactory<T>"]]
method_7atrx1_addinfrastructure__call_36_AppDbContext_type_[["AppDbContext (type)"]]
method_7atrx1_addinfrastructure__call_41_AddDbContext_T_[["AddDbContext<T>"]]
method_7atrx1_addinfrastructure__call_57_AddSingleton_QdrantClient_[["AddSingleton<QdrantClient>"]]
method_7atrx1_addinfrastructure__call_61_GraphDatabase_Driver[["GraphDatabase.Driver"]]
method_7atrx1_addinfrastructure__call_66_AddHangfire[["AddHangfire"]]
method_7atrx1_addinfrastructure__call_69_AddHangfireServer[["AddHangfireServer"]]
method_7atrx1_addinfrastructure__call_72_AiSettings_type_[["AiSettings (type)"]]
method_7atrx1_addinfrastructure__call_74_Get_T_IConfigurationSection_[["Get<T> (IConfigurationSection)"]]
method_7atrx1_addinfrastructure__call_81_AddResiliencePipeline[["AddResiliencePipeline"]]
method_7atrx1_addinfrastructure__call_85_ShouldHandle_predicate[["ShouldHandle predicate"]]
method_7atrx1_addinfrastructure__call_99_AddChatClient[["AddChatClient"]]
method_7atrx1_addinfrastructure__action_111_service_registration_111__linear("Register application-layer services")
method_7atrx1_addinfrastructure__action_126_authorization_126__linear("Add 'ProUser' policy and handler")
method_7atrx1_addinfrastructure__action_33_branch_33__condition{"Choose DB provider (Postgres vs Sqlite)"}
method_7atrx1_addinfrastructure__action_33_branch_33__false("false")
method_7atrx1_addinfrastructure__action_33_branch_33__merge("merge")
method_7atrx1_addinfrastructure__action_33_branch_33__true("true")
method_7atrx1_addinfrastructure__action_34_addinfrastructure_branch_34_0__condition{"!string.IsNullOrEmpty(pgConnectionString)"}
method_7atrx1_addinfrastructure__action_34_addinfrastructure_branch_34_0__false("false")
method_7atrx1_addinfrastructure__action_34_addinfrastructure_branch_34_0__merge("merge")
method_7atrx1_addinfrastructure__action_34_addinfrastructure_branch_34_0__true("true")
method_7atrx1_addinfrastructure__action_36_service_registration_36__linear("Register AppDbContext factory scoped")
method_7atrx1_addinfrastructure__action_41_service_registration_41__linear("Register AppDbContext scoped")
method_7atrx1_addinfrastructure__action_44_addinfrastructure_fallback_44_1__condition{"Falls back to alternate path"}
method_7atrx1_addinfrastructure__action_44_addinfrastructure_fallback_44_1__false("otherwise")
method_7atrx1_addinfrastructure__action_44_addinfrastructure_fallback_44_1__merge("merge")
method_7atrx1_addinfrastructure__action_44_addinfrastructure_fallback_44_1__true("fallback")
method_7atrx1_addinfrastructure__action_57_service_registration_57__linear("Register Qdrant client singleton")
method_7atrx1_addinfrastructure__action_61_service_registration_61__linear("Register Neo4j driver singleton")
method_7atrx1_addinfrastructure__action_64_addinfrastructure_branch_64_2__condition{"!string.IsNullOrEmpty(pgConnectionString)"}
method_7atrx1_addinfrastructure__action_64_addinfrastructure_branch_64_2__false("false")
method_7atrx1_addinfrastructure__action_64_addinfrastructure_branch_64_2__merge("merge")
method_7atrx1_addinfrastructure__action_64_addinfrastructure_branch_64_2__true("true")
method_7atrx1_addinfrastructure__action_64_branch_64__condition{"pgConnectionString not empty"}
method_7atrx1_addinfrastructure__action_64_branch_64__false("skip hangfire")
method_7atrx1_addinfrastructure__action_64_branch_64__merge("merge")
method_7atrx1_addinfrastructure__action_64_branch_64__true("register hangfire")
method_7atrx1_addinfrastructure__action_72_configure_72__linear("Bind configuration sections")
method_7atrx1_addinfrastructure__action_76_addinfrastructure_branch_76_3__condition{"string.IsNullOrWhiteSpace(aiSettings.ApiKey) || aiSettings.ApiKey == \\"PLACEHOLDER\\""}
method_7atrx1_addinfrastructure__action_76_addinfrastructure_branch_76_3__false("false")
method_7atrx1_addinfrastructure__action_76_addinfrastructure_branch_76_3__merge("merge")
method_7atrx1_addinfrastructure__action_76_addinfrastructure_branch_76_3__true("true")
method_7atrx1_addinfrastructure__action_76_guard_clause_76__condition{"aiSettings.ApiKey null/whitespace or 'PLACEHOLDER'"}
method_7atrx1_addinfrastructure__action_76_guard_clause_76__false("continue")
method_7atrx1_addinfrastructure__action_76_guard_clause_76__merge("merge")
method_7atrx1_addinfrastructure__action_76_guard_clause_76__true("warning")
method_7atrx1_addinfrastructure__action_81_retry_policy_81__linear("AI retry resilience pipeline")
method_7atrx1_addinfrastructure__action_99_service_registration_99__linear("Register AI chat and embedding clients")
method_7atrx1_addinfrastructure__entry(["AddInfrastructure entry"])
method_7atrx1_addinfrastructure__action_134_addinfrastructure_return_134_4__return(["Returns result"])
method_7atrx1_addinfrastructure__action_134_return_134__return(["Return modified IServiceCollection"])
method_7atrx1_addinfrastructure__action_111_service_registration_111__linear -->|registered as IKnowledgeService scoped| method_7atrx1_addinfrastructure__call_112_KnowledgeService_type_
method_7atrx1_addinfrastructure__action_126_authorization_126__linear -->|registered as IAuthorizationHandler scoped| method_7atrx1_addinfrastructure__call_131_ProUserHandler_type_
method_7atrx1_addinfrastructure__action_134_addinfrastructure_return_134_4__return -->|return| method_7atrx1_addinfrastructure__action_134_return_134__return
method_7atrx1_addinfrastructure__action_33_branch_33__condition -->|false| method_7atrx1_addinfrastructure__action_33_branch_33__false
method_7atrx1_addinfrastructure__action_33_branch_33__condition -->|true| method_7atrx1_addinfrastructure__action_33_branch_33__true
method_7atrx1_addinfrastructure__action_33_branch_33__false -->|next| method_7atrx1_addinfrastructure__action_33_branch_33__merge
method_7atrx1_addinfrastructure__action_33_branch_33__merge -->|next| method_7atrx1_addinfrastructure__action_34_addinfrastructure_branch_34_0__condition
method_7atrx1_addinfrastructure__action_33_branch_33__true -->|next| method_7atrx1_addinfrastructure__action_33_branch_33__merge
method_7atrx1_addinfrastructure__action_34_addinfrastructure_branch_34_0__condition -->|false| method_7atrx1_addinfrastructure__action_34_addinfrastructure_branch_34_0__false
method_7atrx1_addinfrastructure__action_34_addinfrastructure_branch_34_0__condition -->|true| method_7atrx1_addinfrastructure__action_34_addinfrastructure_branch_34_0__true
method_7atrx1_addinfrastructure__action_34_addinfrastructure_branch_34_0__false -->|next| method_7atrx1_addinfrastructure__action_34_addinfrastructure_branch_34_0__merge
method_7atrx1_addinfrastructure__action_34_addinfrastructure_branch_34_0__merge -->|next| method_7atrx1_addinfrastructure__action_36_service_registration_36__linear
method_7atrx1_addinfrastructure__action_34_addinfrastructure_branch_34_0__true -->|next| method_7atrx1_addinfrastructure__action_34_addinfrastructure_branch_34_0__merge
method_7atrx1_addinfrastructure__action_36_service_registration_36__linear -->|pgConnectionString or sqliteConnectionString passed into UseNpgsql / UseSqlite options| method_7atrx1_addinfrastructure__call_36_AppDbContext_type_
method_7atrx1_addinfrastructure__action_41_service_registration_41__linear -->|AppDbContext with DB provider options| method_7atrx1_addinfrastructure__call_41_AddDbContext_T_
method_7atrx1_addinfrastructure__action_44_addinfrastructure_fallback_44_1__condition -->|otherwise| method_7atrx1_addinfrastructure__action_44_addinfrastructure_fallback_44_1__false
method_7atrx1_addinfrastructure__action_44_addinfrastructure_fallback_44_1__condition -->|fallback| method_7atrx1_addinfrastructure__action_44_addinfrastructure_fallback_44_1__true
method_7atrx1_addinfrastructure__action_44_addinfrastructure_fallback_44_1__false -->|next| method_7atrx1_addinfrastructure__action_44_addinfrastructure_fallback_44_1__merge
method_7atrx1_addinfrastructure__action_44_addinfrastructure_fallback_44_1__merge -->|next| method_7atrx1_addinfrastructure__action_57_service_registration_57__linear
method_7atrx1_addinfrastructure__action_44_addinfrastructure_fallback_44_1__true -->|next| method_7atrx1_addinfrastructure__action_44_addinfrastructure_fallback_44_1__merge
method_7atrx1_addinfrastructure__action_57_service_registration_57__linear -->|new QdrantClient new Uri qdrantUrl| method_7atrx1_addinfrastructure__call_57_AddSingleton_QdrantClient_
method_7atrx1_addinfrastructure__action_61_service_registration_61__linear -->|neo4jUrl, AuthTokens.None| method_7atrx1_addinfrastructure__call_61_GraphDatabase_Driver
method_7atrx1_addinfrastructure__action_64_addinfrastructure_branch_64_2__condition -->|false| method_7atrx1_addinfrastructure__action_64_addinfrastructure_branch_64_2__false
method_7atrx1_addinfrastructure__action_64_addinfrastructure_branch_64_2__condition -->|true| method_7atrx1_addinfrastructure__action_64_addinfrastructure_branch_64_2__true
method_7atrx1_addinfrastructure__action_64_addinfrastructure_branch_64_2__false -->|next| method_7atrx1_addinfrastructure__action_64_addinfrastructure_branch_64_2__merge
method_7atrx1_addinfrastructure__action_64_addinfrastructure_branch_64_2__merge -->|next| method_7atrx1_addinfrastructure__action_64_branch_64__condition
method_7atrx1_addinfrastructure__action_64_addinfrastructure_branch_64_2__true -->|next| method_7atrx1_addinfrastructure__action_64_addinfrastructure_branch_64_2__merge
method_7atrx1_addinfrastructure__action_64_branch_64__condition -->|skip hangfire| method_7atrx1_addinfrastructure__action_64_branch_64__false
method_7atrx1_addinfrastructure__action_64_branch_64__condition -->|register hangfire| method_7atrx1_addinfrastructure__action_64_branch_64__true
method_7atrx1_addinfrastructure__action_64_branch_64__false -->|next| method_7atrx1_addinfrastructure__action_64_branch_64__merge
method_7atrx1_addinfrastructure__action_64_branch_64__merge -->|Configure Hangfire with PostgreSqlStorage using pgConnectionString| method_7atrx1_addinfrastructure__call_66_AddHangfire
method_7atrx1_addinfrastructure__action_64_branch_64__true -->|next| method_7atrx1_addinfrastructure__action_64_branch_64__merge
method_7atrx1_addinfrastructure__action_72_configure_72__linear -->|Configure and bind AiSettings from configuration| method_7atrx1_addinfrastructure__call_72_AiSettings_type_
method_7atrx1_addinfrastructure__action_76_addinfrastructure_branch_76_3__condition -->|false| method_7atrx1_addinfrastructure__action_76_addinfrastructure_branch_76_3__false
method_7atrx1_addinfrastructure__action_76_addinfrastructure_branch_76_3__condition -->|true| method_7atrx1_addinfrastructure__action_76_addinfrastructure_branch_76_3__true
method_7atrx1_addinfrastructure__action_76_addinfrastructure_branch_76_3__false -->|next| method_7atrx1_addinfrastructure__action_76_addinfrastructure_branch_76_3__merge
method_7atrx1_addinfrastructure__action_76_addinfrastructure_branch_76_3__merge -->|next| method_7atrx1_addinfrastructure__action_81_retry_policy_81__linear
method_7atrx1_addinfrastructure__action_76_addinfrastructure_branch_76_3__true -->|next| method_7atrx1_addinfrastructure__action_76_addinfrastructure_branch_76_3__merge
method_7atrx1_addinfrastructure__action_76_guard_clause_76__condition -->|continue| method_7atrx1_addinfrastructure__action_76_guard_clause_76__false
method_7atrx1_addinfrastructure__action_76_guard_clause_76__condition -->|warning| method_7atrx1_addinfrastructure__action_76_guard_clause_76__true
method_7atrx1_addinfrastructure__action_76_guard_clause_76__false -->|next| method_7atrx1_addinfrastructure__action_76_guard_clause_76__merge
method_7atrx1_addinfrastructure__action_76_guard_clause_76__merge -->|next| method_7atrx1_addinfrastructure__action_76_addinfrastructure_branch_76_3__condition
method_7atrx1_addinfrastructure__action_76_guard_clause_76__true -->|next| method_7atrx1_addinfrastructure__action_76_guard_clause_76__merge
method_7atrx1_addinfrastructure__action_81_retry_policy_81__linear -->|calls| method_7atrx1_addinfrastructure__call_81_AddResiliencePipeline
method_7atrx1_addinfrastructure__action_99_service_registration_99__linear -->|GeminiChatClient configured with AiSettings.ApiKey and ModelId| method_7atrx1_addinfrastructure__call_99_AddChatClient
method_7atrx1_addinfrastructure__call_105_AddEmbeddingGenerator -->|next| method_7atrx1_addinfrastructure__action_111_service_registration_111__linear
method_7atrx1_addinfrastructure__call_112_KnowledgeService_type_ -->|registered as IEpubReader transient| method_7atrx1_addinfrastructure__call_113_EpubReaderService_type_
method_7atrx1_addinfrastructure__call_113_EpubReaderService_type_ -->|registered as IEpubMetadataExtractor transient| method_7atrx1_addinfrastructure__call_114_EpubMetadataExtractor_type_
method_7atrx1_addinfrastructure__call_114_EpubMetadataExtractor_type_ -->|registered as IBookStorageService scoped| method_7atrx1_addinfrastructure__call_118_BookStorageService_type_
method_7atrx1_addinfrastructure__call_118_BookStorageService_type_ -->|registered as IEbookRepository scoped| method_7atrx1_addinfrastructure__call_121_EbookRepository_type_
method_7atrx1_addinfrastructure__call_121_EbookRepository_type_ -->|registered as ISyncBroadcaster scoped| method_7atrx1_addinfrastructure__call_124_SignalRSyncBroadcaster_type_
method_7atrx1_addinfrastructure__call_124_SignalRSyncBroadcaster_type_ -->|next| method_7atrx1_addinfrastructure__action_126_authorization_126__linear
method_7atrx1_addinfrastructure__call_131_ProUserHandler_type_ -->|registered as IInfrastructureMarker scoped| method_7atrx1_addinfrastructure__call_132_InfrastructureMarker_type_
method_7atrx1_addinfrastructure__call_132_InfrastructureMarker_type_ -->|return| method_7atrx1_addinfrastructure__action_134_addinfrastructure_return_134_4__return
method_7atrx1_addinfrastructure__call_36_AddDbContextFactory_T_ -->|next| method_7atrx1_addinfrastructure__action_41_service_registration_41__linear
method_7atrx1_addinfrastructure__call_36_AppDbContext_type_ -->|AppDbContext factory with DB provider options| method_7atrx1_addinfrastructure__call_36_AddDbContextFactory_T_
method_7atrx1_addinfrastructure__call_41_AddDbContext_T_ -->|fallback| method_7atrx1_addinfrastructure__action_44_addinfrastructure_fallback_44_1__condition
method_7atrx1_addinfrastructure__call_57_AddSingleton_QdrantClient_ -->|next| method_7atrx1_addinfrastructure__action_61_service_registration_61__linear
method_7atrx1_addinfrastructure__call_61_GraphDatabase_Driver -->|next| method_7atrx1_addinfrastructure__action_64_addinfrastructure_branch_64_2__condition
method_7atrx1_addinfrastructure__call_66_AddHangfire -->|start Hangfire server| method_7atrx1_addinfrastructure__call_69_AddHangfireServer
method_7atrx1_addinfrastructure__call_69_AddHangfireServer -->|next| method_7atrx1_addinfrastructure__action_72_configure_72__linear
method_7atrx1_addinfrastructure__call_72_AiSettings_type_ -->|Bind AiSettings section into AiSettings instance| method_7atrx1_addinfrastructure__call_74_Get_T_IConfigurationSection_
method_7atrx1_addinfrastructure__call_74_Get_T_IConfigurationSection_ -->|next| method_7atrx1_addinfrastructure__action_76_guard_clause_76__condition
method_7atrx1_addinfrastructure__call_81_AddResiliencePipeline -->|exception -> check message contains 429 / Too Many Requests / quota / 503 / ServiceUnavailable / demand| method_7atrx1_addinfrastructure__call_85_ShouldHandle_predicate
method_7atrx1_addinfrastructure__call_85_ShouldHandle_predicate -->|next| method_7atrx1_addinfrastructure__action_99_service_registration_99__linear
method_7atrx1_addinfrastructure__call_99_AddChatClient -->|GeminiEmbeddingGenerator configured with ApiKey and EmbeddingModel| method_7atrx1_addinfrastructure__call_105_AddEmbeddingGenerator
method_7atrx1_addinfrastructure__entry -->|next| method_7atrx1_addinfrastructure__action_33_branch_33__condition
```
### Assembly() Control Flow
```mermaid
flowchart TD
method_1c1pgjw_assembly__call_137_typeof_DependencyInjection_Assembly[["typeof(DependencyInjection).Assembly"]]
method_1c1pgjw_assembly__action_137_expose_metadata_137__linear("Return assembly for scanning")
method_1c1pgjw_assembly__entry(["Assembly entry"])
method_1c1pgjw_assembly__implicit_return(["return"])
method_1c1pgjw_assembly__action_137_expose_metadata_137__linear -->|reflection on DependencyInjection type| method_1c1pgjw_assembly__call_137_typeof_DependencyInjection_Assembly
method_1c1pgjw_assembly__call_137_typeof_DependencyInjection_Assembly -->|return| method_1c1pgjw_assembly__implicit_return
method_1c1pgjw_assembly__entry -->|next| method_1c1pgjw_assembly__action_137_expose_metadata_137__linear
```
## Diagram Validation
- Status: warn
- Warning: Control-flow extraction left 22 unresolved jumps.
- Warning: neighborhood-view: diagram file_r7svsj_dependencyinjection_cs_neighborhood_view exceeds preferred complexity thresholds (13 nodes, 6 edges).
- Warning: execution-overview: diagram file_r7svsj_dependencyinjection_cs_execution_view exceeds preferred complexity thresholds (25 nodes, 24 edges).
- Warning: control-flow: diagram method_7atrx1_addinfrastructure__fragment_diagram exceeds preferred complexity thresholds (61 nodes, 67 edges).
@@ -0,0 +1,163 @@
# ContentHasher
- File ID: file:13kvr59:contenthasher-cs
- Path: NexusReader.Infrastructure/Helpers/ContentHasher.cs
- Role: service
- Layer: infrastructure
## Purpose
Provides deterministic normalization and SHA-256 hashing for content strings used across the infrastructure (e.g., content fingerprinting / cache keys).
## Key Details
Deterministic normalization (trim, collapse whitespace, lower-case) + SHA-256 and lower-case hex output. Guard-clauses return empty string for null/whitespace inputs.
## Symbols
- ContentHasher: Provides deterministic normalization and SHA-256 hashing for content strings used across the infrastructure (e.g., content fingerprinting / cache keys).
- ComputeHash(): Normalize the provided string and return its SHA-256 hash as a lower-case hex string; returns empty string for null/whitespace input.
- Normalize(): Produce a deterministic normalized version of the input by trimming, collapsing whitespace to single spaces, and lower-casing; returns empty for null/whitespace input.
- ContentHasher: Static helper class exposing normalization and hashing utilities for content.
## Dependencies
- No resolved dependencies.
## Calls
- No resolved calls.
## Unresolved References
- call-target: self
- interaction-target: var hashBytes = SHA256.HashData(inputBytes) (framework API)
## Coverage
- Symbols: 4
- Executable symbols: 2
- Executable symbols with control flow: 2
- Grounded edges: 4
- Unresolved references: 2
- Control-flow fragments: 2
- Unresolved jumps: 0
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 2
- Generated diagrams: 4
## Control Flow Fragments
- ComputeHash: 18 nodes, 19 edges, 1 jumps, 0 unsupported constructs
- Normalize: 14 nodes, 15 edges, 0 jumps, 0 unsupported constructs
## Diagrams
### ContentHasher Neighborhood
```mermaid
flowchart LR
class_lvxelt_contenthasher("ContentHasher")
file_13kvr59_contenthasher_cs("ContentHasher")
method_1e84qm4_normalize[["Normalize()"]]
method_pslukv_computehash[["ComputeHash()"]]
type_7fsbyq_contenthasher[/"ContentHasher"/]
```
### ContentHasher Execution Overview
```mermaid
flowchart TD
class_lvxelt_contenthasher("ContentHasher")
method_1e84qm4_normalize[["Normalize()"]]
method_pslukv_computehash[["ComputeHash()"]]
unresolved_unresolved_7qxs61_interaction_target{"Unresolved: var hashBytes = SHA256.HashData(inputBytes) (framework API)"}
unresolved_unresolved_p2lu8n_call_target{"Unresolved: Normalize"}
class_lvxelt_contenthasher -->|contains| method_1e84qm4_normalize
class_lvxelt_contenthasher -->|contains| method_pslukv_computehash
class_lvxelt_contenthasher -->|unresolved interaction| unresolved_unresolved_7qxs61_interaction_target
method_pslukv_computehash -->|unresolved call| unresolved_unresolved_p2lu8n_call_target
```
### ComputeHash() Control Flow
```mermaid
flowchart TD
method_pslukv_computehash__call_16_Normalize[["Normalize"]]
method_pslukv_computehash__action_11_computehash_branch_11_0__condition{"string.IsNullOrWhiteSpace(input)"}
method_pslukv_computehash__action_11_computehash_branch_11_0__false("false")
method_pslukv_computehash__action_11_computehash_branch_11_0__merge("merge")
method_pslukv_computehash__action_11_computehash_branch_11_0__true("true")
method_pslukv_computehash__action_11_guard_clause_11__condition{"string.IsNullOrWhiteSpace(input)"}
method_pslukv_computehash__action_11_guard_clause_11__false("continue")
method_pslukv_computehash__action_11_guard_clause_11__merge("merge")
method_pslukv_computehash__action_11_guard_clause_11__true("return-empty")
method_pslukv_computehash__action_16_orchestration_16__linear("Normalization call")
method_pslukv_computehash__action_18_transform_18__linear("UTF-8 encoding")
method_pslukv_computehash__action_21_transform_21__linear("Hex conversion and normalization")
method_pslukv_computehash__entry(["ComputeHash entry"])
method_pslukv_computehash__action_19_external_call_19__linear("SHA-256 hash computation")
method_pslukv_computehash__action_13_computehash_return_13_1__return(["Returns result"])
method_pslukv_computehash__action_21_computehash_return_21_2__return(["Returns result"])
method_pslukv_computehash__action_21_return_21__return(["Returns hash string"])
method_pslukv_computehash__implicit_return(["return"])
method_pslukv_computehash__action_11_computehash_branch_11_0__condition -->|false| method_pslukv_computehash__action_11_computehash_branch_11_0__false
method_pslukv_computehash__action_11_computehash_branch_11_0__condition -->|true| method_pslukv_computehash__action_11_computehash_branch_11_0__true
method_pslukv_computehash__action_11_computehash_branch_11_0__false -->|next| method_pslukv_computehash__action_11_computehash_branch_11_0__merge
method_pslukv_computehash__action_11_computehash_branch_11_0__merge -->|return| method_pslukv_computehash__action_13_computehash_return_13_1__return
method_pslukv_computehash__action_11_computehash_branch_11_0__true -->|next| method_pslukv_computehash__action_11_computehash_branch_11_0__merge
method_pslukv_computehash__action_11_guard_clause_11__condition -->|continue| method_pslukv_computehash__action_11_guard_clause_11__false
method_pslukv_computehash__action_11_guard_clause_11__condition -->|return-empty| method_pslukv_computehash__action_11_guard_clause_11__true
method_pslukv_computehash__action_11_guard_clause_11__false -->|next| method_pslukv_computehash__action_11_guard_clause_11__merge
method_pslukv_computehash__action_11_guard_clause_11__merge -->|next| method_pslukv_computehash__action_11_computehash_branch_11_0__condition
method_pslukv_computehash__action_11_guard_clause_11__true -->|next| method_pslukv_computehash__action_11_guard_clause_11__merge
method_pslukv_computehash__action_13_computehash_return_13_1__return -->|next| method_pslukv_computehash__action_16_orchestration_16__linear
method_pslukv_computehash__action_16_orchestration_16__linear -->|input string to normalize| method_pslukv_computehash__call_16_Normalize
method_pslukv_computehash__action_18_transform_18__linear -->|next| method_pslukv_computehash__action_19_external_call_19__linear
method_pslukv_computehash__action_19_external_call_19__linear -->|return| method_pslukv_computehash__action_21_computehash_return_21_2__return
method_pslukv_computehash__action_21_computehash_return_21_2__return -->|return| method_pslukv_computehash__action_21_return_21__return
method_pslukv_computehash__action_21_return_21__return -->|next| method_pslukv_computehash__action_21_transform_21__linear
method_pslukv_computehash__action_21_transform_21__linear -->|return| method_pslukv_computehash__implicit_return
method_pslukv_computehash__call_16_Normalize -->|next| method_pslukv_computehash__action_18_transform_18__linear
method_pslukv_computehash__entry -->|next| method_pslukv_computehash__action_11_guard_clause_11__condition
```
### Normalize() Control Flow
```mermaid
flowchart TD
method_1e84qm4_normalize__action_26_guard_clause_26__condition{"string.IsNullOrWhiteSpace(input)"}
method_1e84qm4_normalize__action_26_guard_clause_26__false("continue")
method_1e84qm4_normalize__action_26_guard_clause_26__merge("merge")
method_1e84qm4_normalize__action_26_guard_clause_26__true("return-empty")
method_1e84qm4_normalize__action_26_normalize_branch_26_0__condition{"string.IsNullOrWhiteSpace(input)"}
method_1e84qm4_normalize__action_26_normalize_branch_26_0__false("false")
method_1e84qm4_normalize__action_26_normalize_branch_26_0__merge("merge")
method_1e84qm4_normalize__action_26_normalize_branch_26_0__true("true")
method_1e84qm4_normalize__action_31_transform_31__linear("Trim and collapse whitespace")
method_1e84qm4_normalize__action_34_transform_34__linear("Case normalization")
method_1e84qm4_normalize__entry(["Normalize entry"])
method_1e84qm4_normalize__action_28_normalize_return_28_1__return(["Returns result"])
method_1e84qm4_normalize__action_35_normalize_return_35_2__return(["Returns result"])
method_1e84qm4_normalize__action_35_return_35__return(["Returns normalized string"])
method_1e84qm4_normalize__action_26_guard_clause_26__condition -->|continue| method_1e84qm4_normalize__action_26_guard_clause_26__false
method_1e84qm4_normalize__action_26_guard_clause_26__condition -->|return-empty| method_1e84qm4_normalize__action_26_guard_clause_26__true
method_1e84qm4_normalize__action_26_guard_clause_26__false -->|next| method_1e84qm4_normalize__action_26_guard_clause_26__merge
method_1e84qm4_normalize__action_26_guard_clause_26__merge -->|next| method_1e84qm4_normalize__action_26_normalize_branch_26_0__condition
method_1e84qm4_normalize__action_26_guard_clause_26__true -->|next| method_1e84qm4_normalize__action_26_guard_clause_26__merge
method_1e84qm4_normalize__action_26_normalize_branch_26_0__condition -->|false| method_1e84qm4_normalize__action_26_normalize_branch_26_0__false
method_1e84qm4_normalize__action_26_normalize_branch_26_0__condition -->|true| method_1e84qm4_normalize__action_26_normalize_branch_26_0__true
method_1e84qm4_normalize__action_26_normalize_branch_26_0__false -->|next| method_1e84qm4_normalize__action_26_normalize_branch_26_0__merge
method_1e84qm4_normalize__action_26_normalize_branch_26_0__merge -->|return| method_1e84qm4_normalize__action_28_normalize_return_28_1__return
method_1e84qm4_normalize__action_26_normalize_branch_26_0__true -->|next| method_1e84qm4_normalize__action_26_normalize_branch_26_0__merge
method_1e84qm4_normalize__action_28_normalize_return_28_1__return -->|next| method_1e84qm4_normalize__action_31_transform_31__linear
method_1e84qm4_normalize__action_31_transform_31__linear -->|next| method_1e84qm4_normalize__action_34_transform_34__linear
method_1e84qm4_normalize__action_34_transform_34__linear -->|return| method_1e84qm4_normalize__action_35_normalize_return_35_2__return
method_1e84qm4_normalize__action_35_normalize_return_35_2__return -->|return| method_1e84qm4_normalize__action_35_return_35__return
method_1e84qm4_normalize__entry -->|next| method_1e84qm4_normalize__action_26_guard_clause_26__condition
```
## Diagram Validation
- Status: pass
@@ -0,0 +1,299 @@
# JsonRepairHelper
- File ID: file:1dyqnkg:jsonrepairhelper-cs
- Path: NexusReader.Infrastructure/Helpers/JsonRepairHelper.cs
- Role: unknown
- Layer: infrastructure
## Purpose
Utility that attempts to repair truncated or malformed JSON strings by pruning trailing garbage and appending necessary closing quotes/brackets/braces.
## Key Details
Repairs truncated JSON by pruning trailing garbage and using a stack-based scan that respects quoted strings and escape sequences; returns original input unchanged when it already ends with a closing brace/bracket or is blank.
## Symbols
- JsonRepairHelper: Utility that attempts to repair truncated or malformed JSON strings by pruning trailing garbage and appending necessary closing quotes/brackets/braces.
- Repair(): Inspect a JSON string and attempt to repair common truncation/malformed scenarios by trimming, pruning trailing garbage, and appending missing closing characters.
- JsonRepairHelper: Static helper class that contains JSON repair utilities.
## Dependencies
- No resolved dependencies.
## Calls
- No resolved calls.
## Coverage
- Symbols: 3
- Executable symbols: 1
- Executable symbols with control flow: 1
- Grounded edges: 3
- Unresolved references: 0
- Control-flow fragments: 1
- Unresolved jumps: 0
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 2
- Generated diagrams: 3
## Control Flow Fragments
- Repair: 96 nodes, 118 edges, 0 jumps, 0 unsupported constructs
## Diagrams
### JsonRepairHelper Neighborhood
```mermaid
flowchart LR
class_ogoid1_jsonrepairhelper("JsonRepairHelper")
file_1dyqnkg_jsonrepairhelper_cs("JsonRepairHelper")
method_1diht7t_repair[["Repair()"]]
type_awil0x_jsonrepairhelper[/"JsonRepairHelper"/]
```
### JsonRepairHelper Execution Overview
```mermaid
flowchart TD
class_ogoid1_jsonrepairhelper("JsonRepairHelper")
method_1diht7t_repair[["Repair()"]]
class_ogoid1_jsonrepairhelper -->|contains| method_1diht7t_repair
```
### Repair() Control Flow
_Warnings: diagram method_1diht7t_repair__fragment_diagram exceeds preferred complexity thresholds (96 nodes, 118 edges)._
```mermaid
---
config:
flowchart:
defaultRenderer: "elk"
---
flowchart TD
method_1diht7t_repair__action_10_guard_clause_10__condition{"string.IsNullOrWhiteSpace(json)"}
method_1diht7t_repair__action_10_guard_clause_10__false("continue")
method_1diht7t_repair__action_10_guard_clause_10__merge("merge")
method_1diht7t_repair__action_10_guard_clause_10__true("return-original")
method_1diht7t_repair__action_10_repair_guard_clause_10_0__condition{"string.IsNullOrWhiteSpace(json)"}
method_1diht7t_repair__action_10_repair_guard_clause_10_0__false("continue")
method_1diht7t_repair__action_10_repair_guard_clause_10_0__merge("merge")
method_1diht7t_repair__action_10_repair_guard_clause_10_0__true("exit")
method_1diht7t_repair__action_11_transformation_11__linear("Trim input")
method_1diht7t_repair__action_14_branch_14__condition{"not EndsWith('}') and not EndsWith(']')"}
method_1diht7t_repair__action_14_branch_14__false("no-repair-needed")
method_1diht7t_repair__action_14_branch_14__merge("merge")
method_1diht7t_repair__action_14_branch_14__true("attempt-repair")
method_1diht7t_repair__action_14_repair_branch_14_1__condition{"!json.EndsWith(\\"}\\") && !json.EndsWith(\\"]\\")"}
method_1diht7t_repair__action_14_repair_branch_14_1__false("false")
method_1diht7t_repair__action_14_repair_branch_14_1__merge("merge")
method_1diht7t_repair__action_14_repair_branch_14_1__true("true")
method_1diht7t_repair__action_18_extraction_18__linear("Locate last plausible cut point")
method_1diht7t_repair__action_24_guard_clause_24__condition{"cutoff > 0"}
method_1diht7t_repair__action_24_guard_clause_24__false("skip-pruning")
method_1diht7t_repair__action_24_guard_clause_24__merge("merge")
method_1diht7t_repair__action_24_guard_clause_24__true("prune-garbage")
method_1diht7t_repair__action_24_repair_branch_24_2__condition{"cutoff > 0"}
method_1diht7t_repair__action_24_repair_branch_24_2__false("false")
method_1diht7t_repair__action_24_repair_branch_24_2__merge("merge")
method_1diht7t_repair__action_24_repair_branch_24_2__true("true")
method_1diht7t_repair__action_31_state_init_31__linear("Prepare stack and string/escape state")
method_1diht7t_repair__action_35_loop_35__loop_body[["foreach char: handle escape toggling (line 37-38), toggle inString on '\\"' (line 39), skip content inside strings (line 40), push '{'/'[' (line 42), and match/pop on '}'/']' (lines 43-51). This implements bracket matching for unclosed structures."]]
method_1diht7t_repair__action_35_loop_35__loop_entry("Iterate characters to rebuild structural stack")
method_1diht7t_repair__action_35_loop_35__loop_exit("exit loop")
method_1diht7t_repair__action_35_repair_loop_35_3__loop_body[["foreach (char c in json)"]]
method_1diht7t_repair__action_35_repair_loop_35_3__loop_entry("char c in json")
method_1diht7t_repair__action_35_repair_loop_35_3__loop_exit("Leaves the loop when the condition no longer holds.")
method_1diht7t_repair__action_37_repair_guard_clause_37_4__condition{"escaped"}
method_1diht7t_repair__action_37_repair_guard_clause_37_4__false("continue")
method_1diht7t_repair__action_37_repair_guard_clause_37_4__merge("merge")
method_1diht7t_repair__action_37_repair_guard_clause_37_4__true("exit")
method_1diht7t_repair__action_38_repair_guard_clause_38_5__condition{"c == '\\'"}
method_1diht7t_repair__action_38_repair_guard_clause_38_5__false("continue")
method_1diht7t_repair__action_38_repair_guard_clause_38_5__merge("merge")
method_1diht7t_repair__action_38_repair_guard_clause_38_5__true("exit")
method_1diht7t_repair__action_39_repair_guard_clause_39_6__condition{"c == '\\"'"}
method_1diht7t_repair__action_39_repair_guard_clause_39_6__false("continue")
method_1diht7t_repair__action_39_repair_guard_clause_39_6__merge("merge")
method_1diht7t_repair__action_39_repair_guard_clause_39_6__true("exit")
method_1diht7t_repair__action_40_repair_guard_clause_40_7__condition{"inString"}
method_1diht7t_repair__action_40_repair_guard_clause_40_7__false("continue")
method_1diht7t_repair__action_40_repair_guard_clause_40_7__merge("merge")
method_1diht7t_repair__action_40_repair_guard_clause_40_7__true("exit")
method_1diht7t_repair__action_42_repair_branch_42_8__condition{"c == '{' || c == '[') stack.Push(c"}
method_1diht7t_repair__action_42_repair_branch_42_8__false("false")
method_1diht7t_repair__action_42_repair_branch_42_8__merge("merge")
method_1diht7t_repair__action_42_repair_branch_42_8__true("true")
method_1diht7t_repair__action_43_repair_branch_43_9__condition{"c == '}' || c == ']'"}
method_1diht7t_repair__action_43_repair_branch_43_9__false("false")
method_1diht7t_repair__action_43_repair_branch_43_9__merge("merge")
method_1diht7t_repair__action_43_repair_branch_43_9__true("true")
method_1diht7t_repair__action_43_repair_fallback_43_10__condition{"Falls back to alternate path"}
method_1diht7t_repair__action_43_repair_fallback_43_10__false("otherwise")
method_1diht7t_repair__action_43_repair_fallback_43_10__merge("merge")
method_1diht7t_repair__action_43_repair_fallback_43_10__true("fallback")
method_1diht7t_repair__action_45_repair_branch_45_11__condition{"stack.Count > 0"}
method_1diht7t_repair__action_45_repair_branch_45_11__false("false")
method_1diht7t_repair__action_45_repair_branch_45_11__merge("merge")
method_1diht7t_repair__action_45_repair_branch_45_11__true("true")
method_1diht7t_repair__action_48_repair_branch_48_12__condition{"(c == '}' && last == '{') || (c == ']' && last == '[')"}
method_1diht7t_repair__action_48_repair_branch_48_12__false("false")
method_1diht7t_repair__action_48_repair_branch_48_12__merge("merge")
method_1diht7t_repair__action_48_repair_branch_48_12__true("true")
method_1diht7t_repair__action_55_repair_branch_55_13__condition{"inString) builder.Append('\\"'"}
method_1diht7t_repair__action_55_repair_branch_55_13__false("false")
method_1diht7t_repair__action_55_repair_branch_55_13__merge("merge")
method_1diht7t_repair__action_55_repair_branch_55_13__true("true")
method_1diht7t_repair__action_55_state_based_action_55__linear("Handle unterminated string")
method_1diht7t_repair__action_57_loop_57__loop_body[["While stack not empty, pop and append '}' for '{' and ']' for '[' (lines 57-62)"]]
method_1diht7t_repair__action_57_loop_57__loop_entry("Append closing characters for remaining open brackets/braces")
method_1diht7t_repair__action_57_loop_57__loop_exit("exit loop")
method_1diht7t_repair__action_57_repair_loop_57_14__loop_body[["while (stack.Count > 0)"]]
method_1diht7t_repair__action_57_repair_loop_57_14__loop_entry("stack.Count > 0")
method_1diht7t_repair__action_57_repair_loop_57_14__loop_exit("Leaves the loop when the condition no longer holds.")
method_1diht7t_repair__action_60_repair_branch_60_15__condition{"c == '{') builder.Append(\\"}\\""}
method_1diht7t_repair__action_60_repair_branch_60_15__false("false")
method_1diht7t_repair__action_60_repair_branch_60_15__merge("merge")
method_1diht7t_repair__action_60_repair_branch_60_15__true("true")
method_1diht7t_repair__action_61_repair_branch_61_16__condition{"c == '[') builder.Append(\\"]\\""}
method_1diht7t_repair__action_61_repair_branch_61_16__false("false")
method_1diht7t_repair__action_61_repair_branch_61_16__merge("merge")
method_1diht7t_repair__action_61_repair_branch_61_16__true("true")
method_1diht7t_repair__action_61_repair_fallback_61_17__condition{"Falls back to alternate path"}
method_1diht7t_repair__action_61_repair_fallback_61_17__false("otherwise")
method_1diht7t_repair__action_61_repair_fallback_61_17__merge("merge")
method_1diht7t_repair__action_61_repair_fallback_61_17__true("fallback")
method_1diht7t_repair__entry(["Repair entry"])
method_1diht7t_repair__action_64_repair_return_64_18__return(["Returns result"])
method_1diht7t_repair__action_64_return_64__return(["Return repaired JSON"])
method_1diht7t_repair__action_67_repair_return_67_19__return(["Returns result"])
method_1diht7t_repair__action_10_guard_clause_10__condition -->|continue| method_1diht7t_repair__action_10_guard_clause_10__false
method_1diht7t_repair__action_10_guard_clause_10__condition -->|return-original| method_1diht7t_repair__action_10_guard_clause_10__true
method_1diht7t_repair__action_10_guard_clause_10__false -->|next| method_1diht7t_repair__action_10_guard_clause_10__merge
method_1diht7t_repair__action_10_guard_clause_10__merge -->|next| method_1diht7t_repair__action_10_repair_guard_clause_10_0__condition
method_1diht7t_repair__action_10_guard_clause_10__true -->|next| method_1diht7t_repair__action_10_guard_clause_10__merge
method_1diht7t_repair__action_10_repair_guard_clause_10_0__condition -->|continue| method_1diht7t_repair__action_10_repair_guard_clause_10_0__false
method_1diht7t_repair__action_10_repair_guard_clause_10_0__condition -->|exit| method_1diht7t_repair__action_10_repair_guard_clause_10_0__true
method_1diht7t_repair__action_10_repair_guard_clause_10_0__false -->|next| method_1diht7t_repair__action_10_repair_guard_clause_10_0__merge
method_1diht7t_repair__action_10_repair_guard_clause_10_0__merge -->|next| method_1diht7t_repair__action_11_transformation_11__linear
method_1diht7t_repair__action_10_repair_guard_clause_10_0__true -->|next| method_1diht7t_repair__action_10_repair_guard_clause_10_0__merge
method_1diht7t_repair__action_11_transformation_11__linear -->|next| method_1diht7t_repair__action_14_repair_branch_14_1__condition
method_1diht7t_repair__action_14_branch_14__condition -->|no-repair-needed| method_1diht7t_repair__action_14_branch_14__false
method_1diht7t_repair__action_14_branch_14__condition -->|attempt-repair| method_1diht7t_repair__action_14_branch_14__true
method_1diht7t_repair__action_14_branch_14__false -->|next| method_1diht7t_repair__action_14_branch_14__merge
method_1diht7t_repair__action_14_branch_14__merge -->|next| method_1diht7t_repair__action_18_extraction_18__linear
method_1diht7t_repair__action_14_branch_14__true -->|next| method_1diht7t_repair__action_14_branch_14__merge
method_1diht7t_repair__action_14_repair_branch_14_1__condition -->|false| method_1diht7t_repair__action_14_repair_branch_14_1__false
method_1diht7t_repair__action_14_repair_branch_14_1__condition -->|true| method_1diht7t_repair__action_14_repair_branch_14_1__true
method_1diht7t_repair__action_14_repair_branch_14_1__false -->|next| method_1diht7t_repair__action_14_repair_branch_14_1__merge
method_1diht7t_repair__action_14_repair_branch_14_1__merge -->|next| method_1diht7t_repair__action_14_branch_14__condition
method_1diht7t_repair__action_14_repair_branch_14_1__true -->|next| method_1diht7t_repair__action_14_repair_branch_14_1__merge
method_1diht7t_repair__action_18_extraction_18__linear -->|next| method_1diht7t_repair__action_24_guard_clause_24__condition
method_1diht7t_repair__action_24_guard_clause_24__condition -->|skip-pruning| method_1diht7t_repair__action_24_guard_clause_24__false
method_1diht7t_repair__action_24_guard_clause_24__condition -->|prune-garbage| method_1diht7t_repair__action_24_guard_clause_24__true
method_1diht7t_repair__action_24_guard_clause_24__false -->|next| method_1diht7t_repair__action_24_guard_clause_24__merge
method_1diht7t_repair__action_24_guard_clause_24__merge -->|next| method_1diht7t_repair__action_24_repair_branch_24_2__condition
method_1diht7t_repair__action_24_guard_clause_24__true -->|next| method_1diht7t_repair__action_24_guard_clause_24__merge
method_1diht7t_repair__action_24_repair_branch_24_2__condition -->|false| method_1diht7t_repair__action_24_repair_branch_24_2__false
method_1diht7t_repair__action_24_repair_branch_24_2__condition -->|true| method_1diht7t_repair__action_24_repair_branch_24_2__true
method_1diht7t_repair__action_24_repair_branch_24_2__false -->|next| method_1diht7t_repair__action_24_repair_branch_24_2__merge
method_1diht7t_repair__action_24_repair_branch_24_2__merge -->|next| method_1diht7t_repair__action_31_state_init_31__linear
method_1diht7t_repair__action_24_repair_branch_24_2__true -->|next| method_1diht7t_repair__action_24_repair_branch_24_2__merge
method_1diht7t_repair__action_31_state_init_31__linear -->|next| method_1diht7t_repair__action_35_repair_loop_35_3__loop_entry
method_1diht7t_repair__action_35_loop_35__loop_body -->|continue| method_1diht7t_repair__action_35_loop_35__loop_entry
method_1diht7t_repair__action_35_loop_35__loop_entry -->|iterate| method_1diht7t_repair__action_35_loop_35__loop_body
method_1diht7t_repair__action_35_loop_35__loop_entry -->|exit| method_1diht7t_repair__action_35_loop_35__loop_exit
method_1diht7t_repair__action_35_loop_35__loop_exit -->|next| method_1diht7t_repair__action_37_repair_guard_clause_37_4__condition
method_1diht7t_repair__action_35_repair_loop_35_3__loop_body -->|continue| method_1diht7t_repair__action_35_repair_loop_35_3__loop_entry
method_1diht7t_repair__action_35_repair_loop_35_3__loop_entry -->|char c in json| method_1diht7t_repair__action_35_repair_loop_35_3__loop_body
method_1diht7t_repair__action_35_repair_loop_35_3__loop_entry -->|Leaves the loop when the condition no longer holds.| method_1diht7t_repair__action_35_repair_loop_35_3__loop_exit
method_1diht7t_repair__action_35_repair_loop_35_3__loop_exit -->|next| method_1diht7t_repair__action_35_loop_35__loop_entry
method_1diht7t_repair__action_37_repair_guard_clause_37_4__condition -->|continue| method_1diht7t_repair__action_37_repair_guard_clause_37_4__false
method_1diht7t_repair__action_37_repair_guard_clause_37_4__condition -->|exit| method_1diht7t_repair__action_37_repair_guard_clause_37_4__true
method_1diht7t_repair__action_37_repair_guard_clause_37_4__false -->|next| method_1diht7t_repair__action_37_repair_guard_clause_37_4__merge
method_1diht7t_repair__action_37_repair_guard_clause_37_4__merge -->|next| method_1diht7t_repair__action_38_repair_guard_clause_38_5__condition
method_1diht7t_repair__action_37_repair_guard_clause_37_4__true -->|next| method_1diht7t_repair__action_37_repair_guard_clause_37_4__merge
method_1diht7t_repair__action_38_repair_guard_clause_38_5__condition -->|continue| method_1diht7t_repair__action_38_repair_guard_clause_38_5__false
method_1diht7t_repair__action_38_repair_guard_clause_38_5__condition -->|exit| method_1diht7t_repair__action_38_repair_guard_clause_38_5__true
method_1diht7t_repair__action_38_repair_guard_clause_38_5__false -->|next| method_1diht7t_repair__action_38_repair_guard_clause_38_5__merge
method_1diht7t_repair__action_38_repair_guard_clause_38_5__merge -->|next| method_1diht7t_repair__action_39_repair_guard_clause_39_6__condition
method_1diht7t_repair__action_38_repair_guard_clause_38_5__true -->|next| method_1diht7t_repair__action_38_repair_guard_clause_38_5__merge
method_1diht7t_repair__action_39_repair_guard_clause_39_6__condition -->|continue| method_1diht7t_repair__action_39_repair_guard_clause_39_6__false
method_1diht7t_repair__action_39_repair_guard_clause_39_6__condition -->|exit| method_1diht7t_repair__action_39_repair_guard_clause_39_6__true
method_1diht7t_repair__action_39_repair_guard_clause_39_6__false -->|next| method_1diht7t_repair__action_39_repair_guard_clause_39_6__merge
method_1diht7t_repair__action_39_repair_guard_clause_39_6__merge -->|next| method_1diht7t_repair__action_40_repair_guard_clause_40_7__condition
method_1diht7t_repair__action_39_repair_guard_clause_39_6__true -->|next| method_1diht7t_repair__action_39_repair_guard_clause_39_6__merge
method_1diht7t_repair__action_40_repair_guard_clause_40_7__condition -->|continue| method_1diht7t_repair__action_40_repair_guard_clause_40_7__false
method_1diht7t_repair__action_40_repair_guard_clause_40_7__condition -->|exit| method_1diht7t_repair__action_40_repair_guard_clause_40_7__true
method_1diht7t_repair__action_40_repair_guard_clause_40_7__false -->|next| method_1diht7t_repair__action_40_repair_guard_clause_40_7__merge
method_1diht7t_repair__action_40_repair_guard_clause_40_7__merge -->|next| method_1diht7t_repair__action_42_repair_branch_42_8__condition
method_1diht7t_repair__action_40_repair_guard_clause_40_7__true -->|next| method_1diht7t_repair__action_40_repair_guard_clause_40_7__merge
method_1diht7t_repair__action_42_repair_branch_42_8__condition -->|false| method_1diht7t_repair__action_42_repair_branch_42_8__false
method_1diht7t_repair__action_42_repair_branch_42_8__condition -->|true| method_1diht7t_repair__action_42_repair_branch_42_8__true
method_1diht7t_repair__action_42_repair_branch_42_8__false -->|next| method_1diht7t_repair__action_42_repair_branch_42_8__merge
method_1diht7t_repair__action_42_repair_branch_42_8__merge -->|fallback| method_1diht7t_repair__action_43_repair_fallback_43_10__condition
method_1diht7t_repair__action_42_repair_branch_42_8__true -->|next| method_1diht7t_repair__action_42_repair_branch_42_8__merge
method_1diht7t_repair__action_43_repair_branch_43_9__condition -->|false| method_1diht7t_repair__action_43_repair_branch_43_9__false
method_1diht7t_repair__action_43_repair_branch_43_9__condition -->|true| method_1diht7t_repair__action_43_repair_branch_43_9__true
method_1diht7t_repair__action_43_repair_branch_43_9__false -->|next| method_1diht7t_repair__action_43_repair_branch_43_9__merge
method_1diht7t_repair__action_43_repair_branch_43_9__merge -->|next| method_1diht7t_repair__action_45_repair_branch_45_11__condition
method_1diht7t_repair__action_43_repair_branch_43_9__true -->|next| method_1diht7t_repair__action_43_repair_branch_43_9__merge
method_1diht7t_repair__action_43_repair_fallback_43_10__condition -->|otherwise| method_1diht7t_repair__action_43_repair_fallback_43_10__false
method_1diht7t_repair__action_43_repair_fallback_43_10__condition -->|fallback| method_1diht7t_repair__action_43_repair_fallback_43_10__true
method_1diht7t_repair__action_43_repair_fallback_43_10__false -->|next| method_1diht7t_repair__action_43_repair_fallback_43_10__merge
method_1diht7t_repair__action_43_repair_fallback_43_10__merge -->|next| method_1diht7t_repair__action_43_repair_branch_43_9__condition
method_1diht7t_repair__action_43_repair_fallback_43_10__true -->|next| method_1diht7t_repair__action_43_repair_fallback_43_10__merge
method_1diht7t_repair__action_45_repair_branch_45_11__condition -->|false| method_1diht7t_repair__action_45_repair_branch_45_11__false
method_1diht7t_repair__action_45_repair_branch_45_11__condition -->|true| method_1diht7t_repair__action_45_repair_branch_45_11__true
method_1diht7t_repair__action_45_repair_branch_45_11__false -->|next| method_1diht7t_repair__action_45_repair_branch_45_11__merge
method_1diht7t_repair__action_45_repair_branch_45_11__merge -->|next| method_1diht7t_repair__action_48_repair_branch_48_12__condition
method_1diht7t_repair__action_45_repair_branch_45_11__true -->|next| method_1diht7t_repair__action_45_repair_branch_45_11__merge
method_1diht7t_repair__action_48_repair_branch_48_12__condition -->|false| method_1diht7t_repair__action_48_repair_branch_48_12__false
method_1diht7t_repair__action_48_repair_branch_48_12__condition -->|true| method_1diht7t_repair__action_48_repair_branch_48_12__true
method_1diht7t_repair__action_48_repair_branch_48_12__false -->|next| method_1diht7t_repair__action_48_repair_branch_48_12__merge
method_1diht7t_repair__action_48_repair_branch_48_12__merge -->|next| method_1diht7t_repair__action_55_state_based_action_55__linear
method_1diht7t_repair__action_48_repair_branch_48_12__true -->|next| method_1diht7t_repair__action_48_repair_branch_48_12__merge
method_1diht7t_repair__action_55_repair_branch_55_13__condition -->|false| method_1diht7t_repair__action_55_repair_branch_55_13__false
method_1diht7t_repair__action_55_repair_branch_55_13__condition -->|true| method_1diht7t_repair__action_55_repair_branch_55_13__true
method_1diht7t_repair__action_55_repair_branch_55_13__false -->|next| method_1diht7t_repair__action_55_repair_branch_55_13__merge
method_1diht7t_repair__action_55_repair_branch_55_13__merge -->|next| method_1diht7t_repair__action_57_repair_loop_57_14__loop_entry
method_1diht7t_repair__action_55_repair_branch_55_13__true -->|next| method_1diht7t_repair__action_55_repair_branch_55_13__merge
method_1diht7t_repair__action_55_state_based_action_55__linear -->|next| method_1diht7t_repair__action_55_repair_branch_55_13__condition
method_1diht7t_repair__action_57_loop_57__loop_body -->|continue| method_1diht7t_repair__action_57_loop_57__loop_entry
method_1diht7t_repair__action_57_loop_57__loop_entry -->|iterate| method_1diht7t_repair__action_57_loop_57__loop_body
method_1diht7t_repair__action_57_loop_57__loop_entry -->|exit| method_1diht7t_repair__action_57_loop_57__loop_exit
method_1diht7t_repair__action_57_loop_57__loop_exit -->|next| method_1diht7t_repair__action_60_repair_branch_60_15__condition
method_1diht7t_repair__action_57_repair_loop_57_14__loop_body -->|continue| method_1diht7t_repair__action_57_repair_loop_57_14__loop_entry
method_1diht7t_repair__action_57_repair_loop_57_14__loop_entry -->|stack.Count > 0| method_1diht7t_repair__action_57_repair_loop_57_14__loop_body
method_1diht7t_repair__action_57_repair_loop_57_14__loop_entry -->|Leaves the loop when the condition no longer holds.| method_1diht7t_repair__action_57_repair_loop_57_14__loop_exit
method_1diht7t_repair__action_57_repair_loop_57_14__loop_exit -->|next| method_1diht7t_repair__action_57_loop_57__loop_entry
method_1diht7t_repair__action_60_repair_branch_60_15__condition -->|false| method_1diht7t_repair__action_60_repair_branch_60_15__false
method_1diht7t_repair__action_60_repair_branch_60_15__condition -->|true| method_1diht7t_repair__action_60_repair_branch_60_15__true
method_1diht7t_repair__action_60_repair_branch_60_15__false -->|next| method_1diht7t_repair__action_60_repair_branch_60_15__merge
method_1diht7t_repair__action_60_repair_branch_60_15__merge -->|fallback| method_1diht7t_repair__action_61_repair_fallback_61_17__condition
method_1diht7t_repair__action_60_repair_branch_60_15__true -->|next| method_1diht7t_repair__action_60_repair_branch_60_15__merge
method_1diht7t_repair__action_61_repair_branch_61_16__condition -->|false| method_1diht7t_repair__action_61_repair_branch_61_16__false
method_1diht7t_repair__action_61_repair_branch_61_16__condition -->|true| method_1diht7t_repair__action_61_repair_branch_61_16__true
method_1diht7t_repair__action_61_repair_branch_61_16__false -->|next| method_1diht7t_repair__action_61_repair_branch_61_16__merge
method_1diht7t_repair__action_61_repair_branch_61_16__merge -->|return| method_1diht7t_repair__action_64_repair_return_64_18__return
method_1diht7t_repair__action_61_repair_branch_61_16__true -->|next| method_1diht7t_repair__action_61_repair_branch_61_16__merge
method_1diht7t_repair__action_61_repair_fallback_61_17__condition -->|otherwise| method_1diht7t_repair__action_61_repair_fallback_61_17__false
method_1diht7t_repair__action_61_repair_fallback_61_17__condition -->|fallback| method_1diht7t_repair__action_61_repair_fallback_61_17__true
method_1diht7t_repair__action_61_repair_fallback_61_17__false -->|next| method_1diht7t_repair__action_61_repair_fallback_61_17__merge
method_1diht7t_repair__action_61_repair_fallback_61_17__merge -->|next| method_1diht7t_repair__action_61_repair_branch_61_16__condition
method_1diht7t_repair__action_61_repair_fallback_61_17__true -->|next| method_1diht7t_repair__action_61_repair_fallback_61_17__merge
method_1diht7t_repair__action_64_repair_return_64_18__return -->|return| method_1diht7t_repair__action_64_return_64__return
method_1diht7t_repair__action_64_return_64__return -->|return| method_1diht7t_repair__action_67_repair_return_67_19__return
method_1diht7t_repair__entry -->|next| method_1diht7t_repair__action_10_guard_clause_10__condition
```
## Diagram Validation
- Status: warn
- Warning: control-flow: diagram method_1diht7t_repair__fragment_diagram exceeds preferred complexity thresholds (96 nodes, 118 edges).

Some files were not shown because too many files have changed in this diff Show More