Software Design Diagrams

This document walks through the design of Harborlight, a small order-and-payment service. It is written as ordinary reading material: prose sections, then a diagram, then more prose. Each diagram is a standard Mermaid fenced block that NoteThink renders inline.

Authentication flow

When a customer signs in, Harborlight delegates identity to an external OAuth provider and exchanges the returned authorization code for tokens before establishing a session. The sequence below traces a single sign-in, including the path where the provider rejects the code.

sequenceDiagram
    participant U as User
    participant W as Web App
    participant A as Auth Service
    participant P as OAuth Provider
    U->>W: Click Sign in
    W->>P: Redirect to authorize endpoint
    P-->>U: Present consent screen
    U->>P: Approve and return code
    P-->>W: Redirect with auth code
    W->>A: Exchange code for tokens
    activate A
    A->>P: POST /token (code, client secret)
    alt Code valid
        P-->>A: Access and refresh tokens
        A-->>W: Session established
        W-->>U: Show dashboard
    else Code expired or reused
        P-->>A: 400 invalid_grant
        A-->>W: Authentication failed
        W-->>U: Show retry prompt
    end
    deactivate A
    Note over A,P: Tokens are cached server-side. The browser never sees the refresh token.

Notice that the refresh token stays on the server. The browser only ever holds a short-lived session reference, which limits the blast radius if a client device is compromised.

Data model

Harborlight's persistence layer is a relational schema. A customer places orders; each order contains line items that reference catalogue products, and each order has at most one payment record. The entity-relationship diagram captures the cardinalities and the primary/foreign keys.

erDiagram
    CUSTOMER ||--o{ ORDER : places
    CUSTOMER ||--o{ ADDRESS : has
    ORDER ||--|{ LINE_ITEM : contains
    ORDER ||--o| PAYMENT : settled_by
    PRODUCT ||--o{ LINE_ITEM : "appears in"
    CATEGORY ||--o{ PRODUCT : groups

    CUSTOMER {
        int id PK
        string email
        string display_name
        datetime created_at
    }
    ADDRESS {
        int id PK
        int customer_id FK
        string line1
        string postcode
        string country
    }
    ORDER {
        int id PK
        int customer_id FK
        string status
        decimal total
        datetime placed_at
    }
    LINE_ITEM {
        int id PK
        int order_id FK
        int product_id FK
        int quantity
        decimal unit_price
    }
    PRODUCT {
        int id PK
        int category_id FK
        string sku
        string name
        decimal list_price
    }
    CATEGORY {
        int id PK
        string name
    }
    PAYMENT {
        int id PK
        int order_id FK
        string provider_ref
        string status
        decimal amount
    }

The LINE_ITEM table snapshots unit_price at purchase time rather than reading PRODUCT.list_price live, so historical orders remain accurate after price changes.

Domain classes

The service layer models the same domain in code. A base Account is specialised into Customer and Administrator. An Order is composed of LineItem objects and associates with a PaymentGateway that performs the actual charge.

classDiagram
    class Account {
        +int id
        +string email
        +login(password) bool
        +logout() void
    }
    class Customer {
        +string displayName
        +placeOrder(cart) Order
    }
    class Administrator {
        +string role
        +refund(order) bool
    }
    class Order {
        +int id
        +string status
        +decimal total
        +addItem(item) void
        +checkout() bool
    }
    class LineItem {
        +int quantity
        +decimal unitPrice
        +subtotal() decimal
    }
    class PaymentGateway {
        +charge(amount) string
        +reverse(ref) bool
    }

    Account <|-- Customer
    Account <|-- Administrator
    Order *-- LineItem
    Customer --> Order : places
    Order --> PaymentGateway : settles via

This keeps authorization logic on Account, so both customer-facing and admin flows inherit a single, audited login path while differing only in their domain capabilities.

Demonstrates NoteThink's Mermaid support for software design - sequence, entity-relationship, and class diagrams rendered inline from your markdown.