Grand Diomande Research · Full HTML Reader

GraphQL API Layer — Architecture Document

- **Performance Prophet** → Health metrics streaming, trend-based subscriptions - **Thought Mesh** → Distributed real-time state propagation - **Cross-Script Bridge** → WebSocket-based real-time translation - **Dream Weaver** → Event-driven lifecycle with state transitions

Business Systems architecture technical paper candidate score 36 .md

Full Public Reader

GraphQL API Layer — Architecture Document

## Dream Origin
Dream ID: `dream_202601260133_1b112f`
Pattern connections: Supabase integration, streaming pipelines, API performance, cross-project pollination

---

1. Design Philosophy

This GraphQL layer is built on patterns observed across the project ecosystem:

  • Performance Prophet → Health metrics streaming, trend-based subscriptions
  • Thought Mesh → Distributed real-time state propagation
  • Cross-Script Bridge → WebSocket-based real-time translation
  • Dream Weaver → Event-driven lifecycle with state transitions

The API unifies these into a single, subscription-aware GraphQL gateway.

### Core Principles
1. Subscription-first — Every mutation that changes observable state emits to subscribers
2. Datasource-agnostic — Resolvers talk to abstract datasource interfaces (Supabase, REST, in-memory)
3. Layered middleware — Auth, rate limiting, caching, and logging compose cleanly
4. Type-safe end-to-end — Schema → codegen → resolvers → client, all TypeScript

---

2. High-Level Architecture

                    ┌──────────────────────────────────────┐
                    │            Client Layer               │
                    │   (React, Mobile, CLI, Other APIs)    │
                    └────────────┬─────────────────────────┘
                                 │
                    ┌────────────▼─────────────────────────┐
                    │         Transport Layer                │
                    │                                        │
                    │  HTTP (queries/mutations)               │
                    │  WebSocket (subscriptions via ws)       │
                    │  SSE (alternative subscription          │
                    │       transport for HTTP/2)             │
                    └────────────┬─────────────────────────┘
                                 │
                    ┌────────────▼─────────────────────────┐
                    │       GraphQL Engine (Yoga)            │
                    │                                        │
                    │  ┌─────────┐ ┌──────────┐ ┌────────┐ │
                    │  │ Schema  │ │ Resolvers│ │ Plugins│ │
                    │  └────┬────┘ └────┬─────┘ └───┬────┘ │
                    │       │           │            │      │
                    │  ┌────▼───────────▼────────────▼────┐ │
                    │  │        Execution Pipeline         │ │
                    │  │  Auth → Validate → Execute → Log  │ │
                    │  └──────────────────────────────────┘ │
                    └────────────┬─────────────────────────┘
                                 │
                    ┌────────────▼─────────────────────────┐
                    │       Datasource Layer                 │
                    │                                        │
                    │  ┌──────────┐  ┌──────────┐           │
                    │  │ Supabase │  │  Redis   │           │
                    │  │ (CRUD +  │  │ (PubSub +│           │
                    │  │  Realtime│  │  Cache)  │           │
                    │  └──────────┘  └──────────┘           │
                    │  ┌──────────┐  ┌──────────┐           │
                    │  │  REST    │  │ In-Memory│           │
                    │  │  APIs    │  │  (Dev)   │           │
                    │  └──────────┘  └──────────┘           │
                    └──────────────────────────────────────┘

---

3. Schema Design

Domain Modeling

The schema follows a domain-driven approach. Core domains identified from cross-project patterns:

graphql
# Core entity types (see full schema in src/schema/)

type User           # Auth & identity
type Project        # Container for work
type Dream          # Dream lifecycle entity (from dream-weaver)
type Metric         # Performance metrics (from performance-prophet)
type Thought        # Distributed thoughts (from thought-mesh)
type Event          # Generic domain event
type Notification   # Push/stream notification

Schema Organization

src/schema/
├── base.graphql        # Scalars, enums, interfaces, directives
├── user.graphql        # User type, auth mutations
├── project.graphql     # Project CRUD
├── dream.graphql       # Dream lifecycle
├── metric.graphql      # Metrics recording & querying
├── notification.graphql # Notification subscriptions
└── index.ts            # Schema stitching / merge

Key Design Decisions

1. Relay-style pagination — All list fields use `Connection` types with `edges` + `pageInfo`
2. Input types for mutations — Every mutation takes a single `input` argument
3. Subscription payloads — Subscriptions return wrapper types with `event` enum + `data` union
4. Error unions — Mutations return `Result` union types (`Success | ValidationError | NotFoundError`)

---

4. Subscription Model

Transport: graphql-ws protocol

Using the modern `graphql-ws` protocol (not legacy `subscriptions-transport-ws`).

PubSub Architecture

                   ┌──────────────┐
                   │   Mutation    │
                   │   Resolver    │
                   └──────┬───────┘
                          │ publish(topic, payload)
                          ▼
                   ┌──────────────┐
                   │   PubSub     │
                   │   Engine     │──────── Redis (production)
                   │              │──────── In-Memory (dev)
                   └──────┬───────┘
                          │ asyncIterator(topic)
                          ▼
                   ┌──────────────┐
                   │ Subscription │
                   │  Resolver    │
                   │  (filter +   │
                   │   transform) │
                   └──────┬───────┘
                          │
                          ▼
                   ┌──────────────┐
                   │   Client     │
                   │  (WebSocket) │
                   └──────────────┘

Topic Naming Convention

ENTITY.EVENT.SCOPE

Examples:
  dream.updated.project:abc123
  metric.recorded.system:global
  notification.created.user:user456
  thought.resonated.session:sess789

Subscription Filtering

Subscriptions accept filter arguments to scope events:

graphql
subscription OnDreamUpdated($projectId: ID!) {
  dreamUpdated(projectId: $projectId) {
    event     # CREATED | UPDATED | EVOLVED | BLOOMED
    dream {
      id
      title
      strength
      stage
    }
  }
}

Server-side filtering prevents sending irrelevant events to clients:

typescript
subscribe: {
  resolve: (payload) => payload,
  subscribe: withFilter(
    () => pubsub.asyncIterableIterator('dream.updated'),
    (payload, variables) => payload.projectId === variables.projectId
  )
}

---

5. Resolver Patterns

Pattern: Datasource Delegation

Resolvers are thin — they validate args, call datasources, publish events. No business logic in resolvers.

typescript
// Pattern: mutation resolver
const Mutation = {
  createDream: async (_parent, { input }, ctx) => {
    // 1. Auth check (middleware handles this via directive)
    // 2. Delegate to datasource
    const dream = await ctx.dataSources.dreams.create(input);
    // 3. Publish event
    ctx.pubsub.publish(`dream.created.project:${dream.projectId}`, {
      event: 'CREATED',
      dream,
    });
    // 4. Return result
    return { __typename: 'CreateDreamSuccess', dream };
  },
};

Pattern: DataLoader for N+1

All relationship resolvers use DataLoader:

typescript
const Dream = {
  project: (dream, _args, ctx) =>
    ctx.loaders.projects.load(dream.projectId),
  metrics: (dream, args, ctx) =>
    ctx.loaders.dreamMetrics.load({ dreamId: dream.id, ...args }),
};

Pattern: Subscription with Backpressure

For high-throughput subscriptions (metrics streaming), use buffered delivery:

typescript
subscribe: {
  subscribe: pipe(
    pubsub.asyncIterableIterator('metric.recorded'),
    buffer(100, 1000), // max 100 items or 1s window
    map(batch => ({ metricsBatch: batch }))
  )
}

---

6. Middleware Stack

Request → Auth → Rate Limit → Depth Limit → Complexity → Execute → Log → Response
MiddlewarePurposeConfig
AuthJWT validation, context enrichment`@auth` directive
Rate LimitPer-user/IP request throttling100 req/min default
Depth LimitPrevent deeply nested queriesMax depth: 10
ComplexityQuery cost analysisMax complexity: 1000
LoggingStructured request/response loggingJSON format
CachingResponse caching for queriesRedis, TTL-based
Error MaskingHide internal errors in productionenv-based

---

7. Authentication & Authorization

### Auth Flow
1. Client sends JWT in `Authorization: Bearer <token>` header
2. Auth middleware validates token, attaches user to context
3. `@auth` directive on fields checks role/permission
4. Subscriptions authenticate on `connection_init` message

Directive-Based Authorization

graphql
directive @auth(requires: Role = USER) on FIELD_DEFINITION

enum Role {
  ADMIN
  USER
  VIEWER
}

---

8. Supabase Integration

Supabase serves as the primary datasource with these integration points:

Supabase FeatureGraphQL Usage
PostgresPrimary data store, queried via datasources
AuthJWT validation, user management
RealtimeDatabase change events → PubSub bridge
StorageFile upload mutations
Edge FunctionsComplex business logic delegation

Realtime Bridge

Supabase Realtime changes are bridged into the GraphQL PubSub:

typescript
// Bridge Supabase Realtime → GraphQL PubSub
supabase
  .channel('db-changes')
  .on('postgres_changes', { event: '*', schema: 'public' }, (payload) => {
    const topic = `${payload.table}.${payload.eventType}`;
    pubsub.publish(topic, payload);
  })
  .subscribe();

---

9. Error Handling

Result Union Pattern

graphql
union CreateDreamResult = CreateDreamSuccess | ValidationError | NotFoundError

type CreateDreamSuccess {
  dream: Dream!
}

type ValidationError {
  field: String!
  message: String!
}

type NotFoundError {
  entityType: String!
  id: ID!
}

Clients use inline fragments:

graphql
mutation {
  createDream(input: { ... }) {
    ... on CreateDreamSuccess { dream { id title } }
    ... on ValidationError { field message }
  }
}

---

10. Performance Considerations

  • DataLoader batches all N+1 queries within a single request tick
  • Persisted queries reduce parsing overhead and prevent arbitrary queries
  • Response caching with cache-control hints (`@cacheControl(maxAge: 60)`)
  • Subscription throttling prevents overwhelming clients with rapid updates
  • Query complexity analysis rejects expensive queries before execution
  • Connection pooling for database connections via Supabase client

---

11. Technology Stack

ComponentChoiceRationale
ServerGraphQL YogaSpec-compliant, plugin system, built-in ws
Schemagraphql-tools (SDL-first)Readable, familiar, good tooling
Codegengraphql-codegenType-safe resolvers + client types
PubSubgraphql-subscriptions + RedisScalable, multi-instance support
AuthSupabase Auth + custom JWTExisting integration pattern
ORMSupabase JS client (no ORM)Direct, less abstraction
TestingVitestConsistent with existing projects
RuntimeNode.js / BunTypeScript native

Promotion Decision

Promote into a technical note or architecture paper with implementation anchors.

Source Anchor

projects/dream-metamorphosis/graphql-api/docs/ARCHITECTURE.md

Detected Structure

Method · Code Anchors · Architecture