04 — Bounded Contexts & Context Map

Covers task 6. Bounded contexts (DDD) are the conceptual decomposition of the domain. They are not services yet — they are the seams along which the modular monolith is organized and, later, where services are extracted (05, 09).

The single most important modeling decision is in §1: the namespace (metadata) and the bytes (storage) are different contexts. Conflating them is the root cause of the dual-write bug (R2) and of leaky storage abstractions (R3).


1. The Core Modeling Insight: Metadata ≠ Bytes

A “file” is two distinct things:

A version points at a blob by content hash. Many versions/nodes (within a tenant) can reference one blob (dedup). The namespace can be reorganized (move/rename/copy) without touching a single byte. This separation is what makes moves cheap, dedup possible, GC safe, and the storage provider swappable.


2. The Contexts

Core domain (where we must be excellent)

Context Responsibility Ubiquitous language Why it’s core
File & Metadata The per-tenant namespace tree; nodes, versions, tags, metadata; move/copy/rename; trash. Source of truth. node, folder, version, path, tag, trash The product’s spine; everything references it
Synchronization Change journal, device cursors, delta computation, conflict detection & resolution change, journal, cursor, delta, conflict, conflicted-copy The headline competency (G2)
Storage Object-storage abstraction; blobs, buckets, providers; presigned URLs; multipart; lifecycle; ref-counted GC blob, content-hash, object key, provider, presign, refcount The “pluggable cloud” bet (G4)

Supporting domain (necessary, not differentiating)

Context Responsibility Ubiquitous language
Identity & Access Tenants, users, sessions, API tokens, OIDC, RBAC tenant, user, role, grant, token, principal
Sharing & Permissions ACLs, internal grants, external share links, inheritance share, link, grant, permission, expiry
Search & Indexing Derived search indexes over names/metadata/(content) index, document, query, facet, reindex
Notification & Events Webhooks, email/in-app notifications, fan-out event, webhook, subscription, notification

Generic domain (commodity; buy/borrow, don’t over-invest)

Context Responsibility Ubiquitous language
Billing & Metering Usage metering, quotas, plan limits (NOT payment processing) usage, quota, plan, meter, limit
Administration & Platform Tenant lifecycle, feature flags, config, audit views tenant-admin, flag, config, audit

Audit is modeled as a cross-cutting concern fed by the event backbone, not a standalone context — every context emits audit-relevant events; one append-only store consumes them.


3. Context Map

How contexts relate. Patterns: Upstream/Downstream, CS Customer-Supplier, ACL Anti-Corruption Layer, CF Conformist, OHS/PL Open-Host Service / Published Language (events).

flowchart TB
    classDef core fill:#fde68a,stroke:#b45309,color:#1f2937;
    classDef support fill:#bfdbfe,stroke:#1d4ed8,color:#1f2937;
    classDef generic fill:#e5e7eb,stroke:#6b7280,color:#1f2937;
    classDef infra fill:#d1fae5,stroke:#047857,color:#1f2937;

    IAM["Identity & Access<br/>(supporting)"]:::support
    FILE["File & Metadata<br/>(CORE — source of truth)"]:::core
    SYNC["Synchronization<br/>(CORE)"]:::core
    STORE["Storage<br/>(CORE)"]:::core
    SHARE["Sharing & Permissions<br/>(supporting)"]:::support
    SEARCH["Search & Indexing<br/>(supporting)"]:::support
    NOTIF["Notification & Events<br/>(supporting)"]:::support
    BILL["Billing & Metering<br/>(generic)"]:::generic
    ADMIN["Administration & Platform<br/>(generic)"]:::generic
    BUS{{"Event Backbone<br/>(Published Language / OHS)"}}:::infra

    IAM -- "U/CS: identity context for every op" --> FILE
    IAM -- "U/CS" --> SHARE
    IAM -- "U/CS" --> ADMIN

    FILE -- "U/CS: commits reference blobs by hash" --> STORE
    FILE -- "U: emits NodeChanged" --> BUS
    STORE -- "U: emits BlobCommitted/Orphaned" --> BUS

    BUS -- "D/CF: consumes NodeChanged" --> SYNC
    BUS -- "D/ACL: consumes events → docs" --> SEARCH
    BUS -- "D/CF: consumes events → fan-out" --> NOTIF
    BUS -- "D: consumes usage events" --> BILL
    BUS -- "D: consumes all → audit log" --> ADMIN

    SHARE -- "U: authorizes access to" --> FILE
    SYNC -- "reads namespace + requests presign" --> FILE
    SYNC -- "delta transfer via presign" --> STORE
    BILL -- "quota check (sync)" --> FILE

Reading the map


4. Why these seams (and not others)


5. Context → Aggregate sketch (detail lives in 08-data-model)

Each aggregate is a transactional consistency boundary. Cross-aggregate / cross-context consistency is achieved via events, never via distributed transactions (ADR-0006).