From a3efc434e7ebf209507bc44abeefe01face6a1c4 Mon Sep 17 00:00:00 2001 From: Morrow Contributors Date: Sat, 1 Aug 2026 16:54:28 +0800 Subject: [PATCH] docs: publish architecture and context graph overview --- README.md | 6 +- docs/architecture-overview.md | 19 ++++ docs/architecture.md | 4 + docs/assets/architecture-overview.svg | 127 ++++++++++++++++++++++++++ docs/assets/context-graph.svg | 111 ++++++++++++++++++++++ docs/context-graph.md | 113 +++++++++++++++++++++++ docs/roadmap.md | 3 +- 7 files changed, 380 insertions(+), 3 deletions(-) create mode 100644 docs/architecture-overview.md create mode 100644 docs/assets/architecture-overview.svg create mode 100644 docs/assets/context-graph.svg create mode 100644 docs/context-graph.md diff --git a/README.md b/README.md index 581e921..8b8d482 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,9 @@ Morrow Desk is the first application. It combines a support desk, customer direc > **Project status:** early V1. The architecture and core Desk flows are implemented and tested, but Morrow does not yet claim production readiness. A deployed Worker is not, by itself, an operational support desk. -[Project site](https://codeyogi911.github.io/morrow-site/) · [V1 contract](docs/product-v1.md) · [Roadmap](docs/roadmap.md) · [Architecture](docs/architecture.md) +[Project site](https://codeyogi911.github.io/morrow-site/) · [V1 contract](docs/product-v1.md) · [Roadmap](docs/roadmap.md) · [Architecture overview](docs/architecture-overview.md) · [Architecture reference](docs/architecture.md) + +![Morrow Desk architecture overview](docs/assets/architecture-overview.svg) ## Why agent-first @@ -41,7 +43,7 @@ morrow/ ├── apps/ │ └── desk/ # Buildable Desk Worker, migrations, tests, assets, and configs ├── packages/ # Future reusable modules, extracted only behind proven interfaces -├── docs/ # Product contract, architecture, ADRs, deployment, and roadmap +├── docs/ # Product contract, architecture visuals, ADRs, deployment, and roadmap ├── scripts/ # Repository-wide publication and history gates └── .github/ # CI, security scanning, and contributor templates ``` diff --git a/docs/architecture-overview.md b/docs/architecture-overview.md new file mode 100644 index 0000000..c20c9d8 --- /dev/null +++ b/docs/architecture-overview.md @@ -0,0 +1,19 @@ +# Architecture overview + +![Morrow Desk architecture overview](assets/architecture-overview.svg) + +Morrow Desk is one Cloudflare Worker with narrow channel adapters, deep business modules, and Cloudflare-managed storage and delivery services. This diagram describes the implemented V1 architecture; the binding details remain in [the architecture reference](architecture.md) and [V1 product contract](product-v1.md). + +## How to read the diagram + +- **Operator plane:** agent clients reach MCP and the small `/ops` recovery surface only through verified Cloudflare Access identity. +- **Customer channels:** the public portal, knowledge base, browser voice, email, and signed WhatsApp ingress enter through channel-specific security boundaries. +- **Adapters:** MCP, portal, email, WhatsApp, voice, and `/ops` authenticate, translate, and render. They do not own business policy. +- **Deep modules:** Communications, Helpdesk, Directory, CRM, Operations, and Improvement own their state, lifecycle, revisions, evidence, and public interfaces. +- **Platform:** D1 holds canonical business state, private R2 holds originals, queues and cron isolate asynchronous work, one Durable Object owns a verified voice session, and Workers AI, Images, Email Service, and external providers remain bounded infrastructure. + +The normal truth flow is: authenticate, load a bounded workspace, commit state plus audit and receipt, deliver asynchronously, then observe the business outcome. Provider acceptance and successful business outcome are deliberately different states. + +## Context direction + +Morrow already composes revisioned cross-module context through public interfaces. A richer relationship view should extend that boundary as a rebuildable projection, not let agents query module tables or receive an unbounded graph dump. See the [bounded context graph proposal](context-graph.md). diff --git a/docs/architecture.md b/docs/architecture.md index 81d4ef1..c2e8f29 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -1,5 +1,7 @@ # Architecture +For the system at a glance, start with the [architecture overview](architecture-overview.md). This document defines the detailed boundaries behind that diagram. + Morrow Desk is one Cloudflare Worker with Hono JSX server rendering, static assets, D1, a private R2 bucket, Email Service, a rate-limit binding, and a retry cron. The V1 product has no browser SPA or live-chat state. Verified browser voice support adds one Agents SDK Durable Object: Turnstile and a short-lived email OTP bind a customer identity to one WebSocket connection, then narrow bridge methods can open Helpdesk cases or read status only for that verified email. The model never supplies the customer identity. Portal branding is deployment data behind one shared validator: `/ops/settings` and the admin-only MCP customization tool write the same bounded identity, asset URL, color, and font fields and emit the same audit event. Customer email templates are separate audited deployment data: the admin MCP tool validates known brace placeholders, stores plain-text and Markdown variants, and sanitizes rich HTML before it enters the durable outbox. ## Deep modules @@ -61,3 +63,5 @@ Email places the capability in the URL fragment of `/requests/access`, so it is Workspace settings and operators are deployment-wide. Directory identity, context envelopes, operation closures, audit, operation receipts, attachments, delivery, provenance, and inactive improvement records are shared substrate. A business module may reuse that substrate but cannot reach into another module's tables or lifecycle logic. See [ADR 0001](adr/0001-agent-first-suite.md) for the long-term module rule and [ADR 0002](adr/0002-agent-first-desk-crm-foundation.md) for the Desk + CRM and closed-loop decisions. + +A richer cross-module relationship view is proposed as a rebuildable, read-only projection in [the bounded context graph proposal](context-graph.md). It is not part of the implemented V1 architecture or a source of business truth. diff --git a/docs/assets/architecture-overview.svg b/docs/assets/architecture-overview.svg new file mode 100644 index 0000000..102d680 --- /dev/null +++ b/docs/assets/architecture-overview.svg @@ -0,0 +1,127 @@ + + Morrow Desk architecture overview + Operator agents and customer channels enter a Cloudflare Worker through narrow adapters. Deep Communications, Helpdesk, Directory, CRM, Operations, and Improvement modules own policy. D1, R2, queues, a Durable Object, Workers AI, Images, Email Service, and external providers form the platform layer. + + + + + + + + + CURRENT V1 + Morrow Desk on Cloudflare + Small agent interfaces at the edge; business truth stays inside deep modules. + + + Operator plane + + Agent clients + Claude · Codex · MCP hosts + + + Cloudflare Access + verified operator identity + + + Customer channels + + Portal · KB · browser voice + capabilities · Turnstile · rate limits + + Email + ingress · durable delivery + + WhatsApp + signed webhook · explicit routing + + + + + + + + ONE CLOUDFLARE WORKER + Task-shaped adapters + + + MCP + MCP App + normal operator interface + + Portal + knowledge + accessible public interface + + Email + WhatsApp + channel translation + + Voice bridge + verified session · narrow RPC + + /ops recovery + small Access-protected surface + + + Adapters authenticate, translate, and render. They do not own business policy. + Deep business modules + + + Communications + channels · addressing + provider evidence + + Helpdesk + cases · lifecycle + revisions · audit + + Directory + parties · contact points + source links + + CRM + relationships · activity + follow-ups + + Operations + receipts · outcomes + reconciliation + + Improvement + proposals · evaluation + inactive in V1 + + Cross-module work uses public interfaces and revisioned context envelopes. + + + + Cloudflare platform and delivery + + + D1 · canonical state + + Private R2 · files + + Queues + retry cron + + DO · voice session + + Workers AI + Images + + Email + external providers + + Authenticate → load a bounded workspace → commit state + audit + receipt → deliver asynchronously → observe outcome + diff --git a/docs/assets/context-graph.svg b/docs/assets/context-graph.svg new file mode 100644 index 0000000..1bb4c4e --- /dev/null +++ b/docs/assets/context-graph.svg @@ -0,0 +1,111 @@ + + Proposed Morrow bounded context graph + Canonical business modules emit a rebuildable node and edge projection into D1 and optional embeddings into Vectorize. An authorized context lens resolves a seed, traverses selected typed edges within budgets, hydrates current module projections, and returns a cited context envelope to an agent. + + + + + + + + + + + + PROPOSED · NOT YET IMPLEMENTED + Bounded context graph on Cloudflare + A rebuildable retrieval projection—not a second source of business truth. + + + Canonical modules + Communications + Helpdesk · cases + public knowledge + Directory · CRM · Operations + Improvement + Own policy, revisions, audit, and truth. + + + outbox / queue + + Projection compiler + Typed nodes and edges + Module revision + provenance + Visibility + freshness + Idempotent and fully rebuildable. + + + + + D1 graph projection + nodes · typed edges · cursors + + Vectorize + optional semantic seed discovery + + + Evidence stores + Private R2 originals + Public knowledge documents + Bounded derived summaries + Content remains evidence, never instructions. + + + + + ONE READ-ONLY CONTEXT INTERFACE + + + 1 · Authorize + actor · deployment + visibility boundary + + + + 2 · Resolve seed + exact identity first + semantic fallback + + + + 3 · Traverse lens + edge allowlist · direction + depth · node budget + + + + 4 · Hydrate + current public module views + revision · unknowns + + + + 5 · Pack context envelope + facts · relationships · evidence + freshness · citations · next actions + + Every lens has a token ceiling and returns explicit truncation and unresolved facts. + + + + Agent receives useful context, not a graph dump + via one task-shaped MCP tool or resource + + Graph deletion loses no business truth. + Rebuild from module-owned state and recorded projection cursors. + diff --git a/docs/context-graph.md b/docs/context-graph.md new file mode 100644 index 0000000..406bf7d --- /dev/null +++ b/docs/context-graph.md @@ -0,0 +1,113 @@ +# Bounded context graph proposal + +- Status: proposed; not implemented +- Last reviewed: 2026-08-01 +- Decision owner: repository maintainers + +![Proposed bounded context graph on Cloudflare](assets/context-graph.svg) + +## Recommendation + +Build the first context graph as a **rebuildable D1 projection with optional Vectorize seed discovery**, exposed through one read-only, task-shaped context interface. Keep every business module as the source of truth and hydrate current facts through its public readers before returning context. + +This is intentionally not a generic graph API, a second write model, agent memory, or a replacement for `morrow_customer_workspace`. It is a bounded retrieval layer for questions that cross modules, such as: + +- What customer, conversations, cases, relationships, orders, evidence, and outcomes are relevant to this decision? +- Which prior operations and authoritative observations explain the present state? +- Which knowledge and unresolved facts should the operator see before acting? + +## Why this fits Cloudflare + +Cloudflare's current native storage catalog does not expose a managed property-graph API. The useful native pieces are complementary: + +| Cloudflare capability | Role in Morrow | Boundary | +| --- | --- | --- | +| [D1](https://developers.cloudflare.com/d1/sql-api/sql-statements/) | Nodes, typed edges, projection cursors, exact lookup, bounded traversal, and FTS5 when useful | Canonical module tables still own truth; D1 graph tables are disposable projections | +| [Vectorize](https://developers.cloudflare.com/vectorize/) | Optional semantic seed discovery and relevance ranking, with namespace or metadata filters | Similarity proposes candidates; it never asserts identity or relationships | +| [Workers AI](https://developers.cloudflare.com/workers-ai/models/) | Embeddings or bounded evidence summaries when evaluation proves value | Derived output remains versioned, attributable, and untrusted where sourced from customers | +| [R2-backed AI Search](https://developers.cloudflare.com/ai-search/configuration/data-source/r2/) | Search over public documentation or a deliberately curated knowledge corpus | Useful for documents, not the business relationship graph | +| [Agents SDK state](https://developers.cloudflare.com/agents/runtime/lifecycle/state/) | Durable SQLite state per Agent instance when Morrow later hosts agent loops; it is session-scoped only when routing deliberately maps one session to one instance | Agent-instance memory is not shared business truth and must not replace module reads | +| [MCP tools](https://developers.cloudflare.com/agents/model-context-protocol/) | Deliver a small context envelope to external agents | Do not expose every node, edge, or table as tools | + +Cloudflare's GraphQL Analytics API queries Cloudflare analytics datasets; it is not application graph storage. A managed external graph database remains possible through a Worker, but adds another authority, security, latency, backup, and data-residency boundary. It should be considered only after measured queries outgrow the D1 projection. + +## Projection contract + +The minimal projection has four responsibilities: + +1. **Stable identity:** every node points to a module, entity type, entity ID, and module revision. +2. **Typed relationships:** every edge has a declared type, direction, immutable source coordinate and revision, visibility, and creation time. +3. **Rebuildability:** a queue-driven compiler is idempotent and records per-module cursors. Deleting all graph tables loses no canonical business state. +4. **Safe summaries:** the projection stores only bounded labels or summaries approved by the owning module. Large or sensitive evidence stays behind its existing authorization boundary. + +An initial schema can remain deliberately small: + +```text +context_nodes( + id, module, entity_type, entity_id, module_revision, + label, summary, visibility, observed_at, projected_at +) + +context_edges( + id, from_node_id, edge_type, to_node_id, + provenance_module, provenance_entity_id, + provenance_revision, provenance_event_id, + visibility, observed_at, projected_at +) + +context_projection_cursors(module, cursor, updated_at) +``` + +Vectorize entries use the node ID as their external identifier and return candidate node IDs only. Namespace or metadata filters narrow discovery but never authorize a result; non-namespace filter properties require explicit metadata indexes. Never return Vectorize metadata or summaries to the agent until D1 scope checks and the owning module's authorization and hydration have succeeded. Indexed metadata should be limited to fields needed to narrow discovery, such as module, entity type, visibility class, and freshness bucket. + +## Bounded retrieval + +A context request follows a fixed sequence: + +1. Authenticate the actor and establish the visibility boundary before lookup. +2. Resolve an exact business identifier first. Use D1 FTS5 or Vectorize only to produce candidate node IDs, then re-enter the D1 and module authorization path. +3. Choose a named lens with an edge allowlist, direction, depth, node ceiling, and token ceiling. +4. Traverse the D1 projection within those budgets. +5. Hydrate selected nodes through their owning modules' public read interfaces. Revalidate projected relationships against current module projections when the owning reader supports it; otherwise mark them stale or unverified and exclude them from authoritative facts. Discard every unauthorized projection. +6. Return a revisioned context envelope containing facts, relationships, evidence coordinates, freshness, explicit unknowns, truncation, and permitted next actions. + +The agent receives a decision workspace, not raw graph traversal output. A first public interface could be: + +```ts +morrow_context({ + subject: { module, entityType, entityId }, + lens: "support_decision" | "customer_history" | "outcome_investigation", + maxNodes?: number, +}) +``` + +`maxNodes` remains server-capped. Mutation authority never follows an edge: every subsequent write still requires the owning module's task-shaped tool and latest revision. + +## Initial vocabulary + +Begin with relationships already proved by current workflows: + +- `involves_party` +- `originated_from_conversation` +- `routed_to_case` +- `routed_to_sales_lead` +- `records_activity` +- `scheduled_followup` +- `evidenced_by` +- `tracked_by_operation` +- `observed_by` +- `suggested_knowledge` + +Adding an edge type is an ontology change. It requires an owner, direction, allowed source and target kinds, provenance rule, visibility rule, and tests for missing, stale, contradictory, and unauthorized targets. + +## Delivery stages + +1. **Measure the baseline.** Create a small evaluation set for cross-module support decisions and record answer completeness, context tokens, latency, stale facts, and authorization failures using current tools. +2. **D1 projection only.** Project Party, Relationship, Conversation, Case, Knowledge Article, Operation, Observation, and Follow-up references. Use exact identifiers and FTS5; do not add embeddings yet. +3. **One context lens.** Add `support_decision` behind a read-only interface and compare it with `morrow_customer_workspace` on the same evaluations. +4. **Semantic seed discovery.** Add Vectorize only if measured seed resolution or relevance remains poor. Similarity results must stay candidates until exact identities are resolved. +5. **Re-evaluate storage.** Consider an external graph engine only when concrete traversal or scale evidence shows D1 is the limiting factor. + +## Acceptance bar + +The proposal is ready for implementation only when an ADR fixes the first lens, node and edge vocabulary, authorization semantics, rebuild process, staleness policy, and evaluation set. Shipping requires evidence that it improves decision completeness or context efficiency without leaking information, hiding unresolved facts, or weakening module boundaries. diff --git a/docs/roadmap.md b/docs/roadmap.md index 07c5296..7f91d21 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -25,12 +25,13 @@ The V1 foundation includes a Desk + CRM tracer over the shared substrate, MCP-fi - **Communications:** WhatsApp media, templates, and `sent`/`delivered`/`read` status projection as explicit pilot gates; further channels only when their verification and reply-window invariants are owned, not adapted in. - **Voice:** telephone-network calling only behind a real availability/queue/timeout/receipt/fallback state machine and a telephony provider; until then the channel never claims calls or live-human transfer. Prioritize measured end-to-end latency, barge-in behavior, and truthful fallback states before expanding the channel. - **CRM:** opportunity and pipeline commands beyond the relationship tracer; fuzzy entity-resolution candidates with explicit merge/split workflows (candidates never become equality automatically). +- **Bounded context graph:** evaluate a rebuildable D1 node-and-edge projection behind one read-only context lens. Add Vectorize only if measured seed discovery needs semantic help; see [the proposal](context-graph.md). - **Controlled improvement:** recovery-console controls for version manifests, bounded rollout, promotion, and rollback; tenant adaptation activation stays separately authorized and off by default. ## Later — the suite - Inventory, purchasing, orders, and accounting as deep vertical modules with small agent interfaces, reusing identity, context envelopes, receipts, audit, files, delivery, and provenance — never each other's private tables. -- A dedicated graph or semantic store only when measured cross-module query value justifies it. +- A dedicated external graph database only when measured traversal or scale evidence shows the D1 projection is the limiting factor. - Externally delegated agent-to-agent operation only after the delegation model in ADR 0002 gains explicit fields and authorization. ## Standing non-goals