Platform Architecture
Overview
Norman is built as a set of loosely coupled microservices. Each service owns its domain and communicates over HTTP/REST APIs. Authentication flows through ShellApps as the Identity Provider.
Service Dependency Graph
NormanEngine ──────────────────────────┐
NormanLibrary ─── NormanSearch ├──→ NormanChat (UI)
│ │
└── Toolshed ────┘
│
NormanAgent (uses Engine + Library) ───┘Key Design Decisions
- Provider Abstraction: Norman Engine abstracts LLM providers behind an interface — switch between OpenAI and AWS Bedrock via configuration.
- MongoDB Atlas for Everything: Single database for documents, vectors, chat history, and metadata. Vector search built-in. Migration path to Aurora + OpenSearch when scale triggers are met.
- ShellApps as IDP: Norman apps are consumer apps in the ShellApps app store. They authenticate via ShellApps OAuth, not as part of the IDP itself.
- Streaming-First: All chat endpoints support Server-Sent Events for real-time token streaming.
Service Communication
| Pattern | Usage |
|---|---|
| HTTP/REST | All service-to-service calls |
| SSE (Server-Sent Events) | Streaming chat responses |
| MongoDB Change Streams | Real-time data updates (planned) |
Authentication Flow
- User accesses Norman Chat
- Redirected to ShellApps OAuth authorize endpoint
- User authenticates → authorization code returned
- Norman exchanges code for access + ID tokens
- JWT session created via NextAuth.js
- All subsequent API calls carry session JWT
Infrastructure
- Compute: AWS ECS Fargate (serverless containers)
- Storage: Amazon S3 with 30-day versioning
- Database: MongoDB Atlas (vector search capable)
- Cache: Amazon ElastiCache (Redis)
- CDN: AWS CloudFront
- IaC: Terraform modules for networking, compute, storage, security