Skip to content

C4 Diagrams

Level 1: System Context

C4Context
    title System Context Diagram - Blue Braces (Recron)

    Person(user, "Job Seeker", "Prepares for interviews, tracks job applications, builds CV")
    Person(moderator, "Moderator", "Approves/rejects proposed questions")

    System(recron, "Blue Braces Platform", "Interview preparation, job search management, and CV portfolio building")

    System_Ext(keycloak, "Keycloak", "Identity & Access Management")
    System_Ext(openai, "OpenAI API", "AI-powered answers, offer parsing, CV matching, portfolio import")

    Rel(user, recron, "Uses", "HTTPS")
    Rel(moderator, recron, "Moderates", "HTTPS")
    Rel(recron, keycloak, "Authentication", "OIDC")
    Rel(recron, openai, "AI features", "HTTPS")

Level 2: Container Diagram

C4Container
    title Container Diagram - Blue Braces

    Person(user, "User")

    System_Boundary(recron, "Blue Braces Platform") {
        Container(webapp, "Web Application", "SolidJS, TypeScript, CSS Modules", "SPA for interview prep, job tracking, and CV building")
        Container(gateway, "API Gateway", "YARP", "Routes requests to microservices")

        Container(questions_api, "Questions API", ".NET 11", "Interview questions, categories, voting, learning, quiz")
        Container(organizer_api, "Organizer API", ".NET 11", "Job offers, interviews, AI parsing, stats, CV matching")
        Container(portfolio_api, "Portfolio API", ".NET 11", "CV portfolios, variants, AI import from LinkedIn/PDF")
        Container(users_api, "Users API", ".NET 11", "User profiles, token details")

        ContainerDb(questions_db, "Questions DB", "PostgreSQL", "Categories, questions, votes, learning")
        ContainerDb(organizer_db, "Organizer DB", "PostgreSQL", "Offers, interviews, dictionaries")
        ContainerDb(portfolio_db, "Portfolio DB", "PostgreSQL", "CV portfolios (JSONB)")
        ContainerDb(users_db, "Users DB", "PostgreSQL", "User profiles")
    }

    System_Ext(keycloak, "Keycloak")
    System_Ext(openai, "OpenAI")

    Rel(user, webapp, "Uses", "HTTPS")
    Rel(webapp, gateway, "API calls", "HTTPS")

    Rel(gateway, questions_api, "/questions/*", "HTTP")
    Rel(gateway, organizer_api, "/organizer/*", "HTTP")
    Rel(gateway, portfolio_api, "/portfolio/*", "HTTP")
    Rel(gateway, users_api, "/users/*", "HTTP")

    Rel(questions_api, questions_db, "Reads/Writes")
    Rel(organizer_api, organizer_db, "Reads/Writes")
    Rel(portfolio_api, portfolio_db, "Reads/Writes")
    Rel(users_api, users_db, "Reads/Writes")

    Rel(questions_api, keycloak, "Validates JWT")
    Rel(organizer_api, keycloak, "Validates JWT")
    Rel(portfolio_api, keycloak, "Validates JWT")
    Rel(users_api, keycloak, "Validates JWT")
    Rel(questions_api, openai, "AI answers")
    Rel(organizer_api, openai, "AI parsing, CV matching")
    Rel(portfolio_api, openai, "AI import")

Level 3: Component Diagram (Questions API)

C4Component
    title Component Diagram - Questions API (14 endpoints)

    Container_Boundary(api, "Questions API") {
        Component(endpoints, "Feature Endpoints", "Minimal API", "14 endpoints for questions, categories, quiz")
        Component(handlers, "CQRS Handlers", "Command/Query Handlers", "Business logic execution")
        Component(dbcontext, "ApplicationDbContext", "EF Core 10", "Data access layer")
        Component(ai_client, "IChatClient", "Microsoft.Extensions.AI", "AI answer generation")
        Component(user_service, "ICurrentUserService", "Domain Service", "Current user context")
    }

    ContainerDb(postgres, "PostgreSQL")
    System_Ext(keycloak, "Keycloak")
    System_Ext(openai, "OpenAI")

    Rel(endpoints, handlers, "Dispatches to")
    Rel(handlers, dbcontext, "Queries/Commands")
    Rel(handlers, ai_client, "Generate answers")
    Rel(handlers, user_service, "Get user context")
    Rel(dbcontext, postgres, "SQL")
    Rel(ai_client, openai, "Chat completions")
    Rel(user_service, keycloak, "Extract from JWT")

Level 3: Component Diagram (Organizer API)

C4Component
    title Component Diagram - Organizer API (17 endpoints)

    Container_Boundary(api, "Organizer API") {
        Component(endpoints, "Feature Endpoints", "Minimal API", "17 endpoints for offers, interviews, AI, stats")
        Component(handlers, "CQRS Handlers", "Command/Query Handlers", "Business logic")
        Component(validators, "Validators", "FluentValidation", "Request validation")
        Component(dbcontext, "ApplicationDbContext", "EF Core 10", "Data access")
        Component(ai_client, "IChatClient", "Microsoft.Extensions.AI", "Offer parsing, CV matching")
    }

    ContainerDb(postgres, "PostgreSQL")
    System_Ext(keycloak, "Keycloak")
    System_Ext(openai, "OpenAI")

    Rel(endpoints, validators, "Validates input")
    Rel(endpoints, handlers, "Dispatches to")
    Rel(handlers, dbcontext, "Queries/Commands")
    Rel(handlers, ai_client, "AI features")
    Rel(dbcontext, postgres, "SQL")
    Rel(endpoints, keycloak, "JWT validation")
    Rel(ai_client, openai, "Chat completions")

Level 3: Component Diagram (Portfolio API)

C4Component
    title Component Diagram - Portfolio API (6 endpoints)

    Container_Boundary(api, "Portfolio API") {
        Component(endpoints, "Feature Endpoints", "Minimal API", "6 endpoints for CRUD + AI import")
        Component(handlers, "CQRS Handlers", "Command/Query Handlers", "Business logic")
        Component(validators, "Validators", "FluentValidation", "Request validation")
        Component(dbcontext, "ApplicationDbContext", "EF Core 10", "Data access (JSONB)")
        Component(ai_client, "IChatClient", "Microsoft.Extensions.AI", "LinkedIn/PDF parsing")
    }

    ContainerDb(postgres, "PostgreSQL")
    System_Ext(keycloak, "Keycloak")
    System_Ext(openai, "OpenAI")

    Rel(endpoints, validators, "Validates input")
    Rel(endpoints, handlers, "Dispatches to")
    Rel(handlers, dbcontext, "Queries/Commands")
    Rel(handlers, ai_client, "AI import")
    Rel(dbcontext, postgres, "SQL + JSONB")
    Rel(endpoints, keycloak, "JWT validation")
    Rel(ai_client, openai, "Chat completions")

Level 3: Component Diagram (Users API)

C4Component
    title Component Diagram - Users API (3 endpoints)

    Container_Boundary(api, "Users API") {
        Component(endpoints, "Feature Endpoints", "Minimal API", "3 endpoints for token details + profile")
        Component(handlers, "CQRS Handlers", "Command/Query Handlers", "Business logic")
        Component(dbcontext, "ApplicationDbContext", "EF Core 10", "Data access")
        Component(user_service, "ICurrentUserService", "Domain Service", "Current user context")
    }

    ContainerDb(postgres, "PostgreSQL")
    System_Ext(keycloak, "Keycloak")

    Rel(endpoints, handlers, "Dispatches to")
    Rel(handlers, dbcontext, "Queries/Commands")
    Rel(handlers, user_service, "Get user context")
    Rel(dbcontext, postgres, "SQL")
    Rel(user_service, keycloak, "Extract from JWT")

Data Flow: Question Proposal Workflow

sequenceDiagram
    participant U as User
    participant W as Webapp
    participant G as Gateway
    participant Q as Questions API
    participant DB as PostgreSQL

    U->>W: Click "Propose Question"
    W->>W: Open FormDialog
    U->>W: Submit question text
    W->>G: POST /questions/questions/propose
    G->>Q: Forward request
    Q->>Q: Validate JWT & extract user
    Q->>DB: Insert QuestionEntity (status: Pending)
    DB-->>Q: Success
    Q-->>G: 201 Created
    G-->>W: Success
    W->>W: Invalidate questions query
    W->>U: Show success message

    Note over U,DB: Moderator Approval Flow
    participant M as Moderator
    M->>W: View pending questions
    W->>G: GET /questions (filter: pending)
    G->>Q: Forward
    Q->>DB: Query pending questions
    DB-->>Q: Results
    Q-->>W: Pending questions list
    M->>W: Click "Approve"
    W->>G: POST /questions/approve
    G->>Q: Forward
    Q->>DB: Update status to Approved
    Q-->>W: Success

Data Flow: AI Answer Generation

sequenceDiagram
    participant U as User
    participant W as Webapp
    participant G as Gateway
    participant Q as Questions API
    participant AI as OpenAI
    participant DB as PostgreSQL

    U->>W: Click "Ask AI" on question
    W->>G: GET /questions/ask-ai?questionId=xxx
    G->>Q: Forward request
    Q->>DB: Get question details
    DB-->>Q: Question with category context
    Q->>AI: ChatCompletion request
    Note right of AI: System prompt + question
    AI-->>Q: Generated answer
    Q->>DB: Update question description
    DB-->>Q: Success
    Q-->>G: AskAiResponse
    G-->>W: Answer text
    W->>W: Invalidate & refetch
    W->>U: Display AI answer

Data Flow: AI Offer Parsing

sequenceDiagram
    participant U as User
    participant W as Webapp
    participant G as Gateway
    participant O as Organizer API
    participant AI as OpenAI

    U->>W: Paste URL or offer text
    W->>G: POST /organizer/offers/parse-ai
    G->>O: Forward request
    O->>AI: Parse offer content
    Note right of AI: Extract structured fields
    AI-->>O: JSON with name, company, salary, etc.
    O-->>G: ParseOfferResponse
    G-->>W: Parsed offer data
    W->>W: Pre-fill offer form
    U->>W: Review & submit
    W->>G: POST /organizer/offers
    G->>O: Create offer
    O-->>W: Created offer

Data Flow: CV-to-Offer Matching

sequenceDiagram
    participant U as User
    participant W as Webapp
    participant G as Gateway
    participant O as Organizer API
    participant AI as OpenAI

    U->>W: Open offer drawer, select CV variant
    W->>G: POST /organizer/offers/match-cv
    G->>O: Forward (offer + portfolio data)
    O->>AI: Compare CV against offer requirements
    Note right of AI: Score, strengths, gaps
    AI-->>O: MatchCvResult JSON
    O-->>G: MatchCvResponse
    G-->>W: Score + analysis
    W->>U: Display score ring, strengths, gaps, recommendations