396 lines
21 KiB
Markdown
396 lines
21 KiB
Markdown
---
|
|
tags:
|
|
- eventkit
|
|
---
|
|
|
|
# Technical Requirements
|
|
|
|
## Purpose
|
|
|
|
Non-functional requirements, deployment model, API design, and infrastructure considerations for EventKit.
|
|
|
|
---
|
|
|
|
## Technology Stack
|
|
|
|
### Core Decisions
|
|
|
|
| Layer | Technology | Rationale |
|
|
| -------------------- | -------------------------------------------- | -------------------------------------------------------------------------------------------------------------- |
|
|
| **Backend language** | **Go** | Fast compilation, single binary deployment, excellent concurrency, strong ecosystem for network services |
|
|
| **API protocol** | **ConnectRPC** (gRPC wrapper) | Type-safe, code-generated clients, supports gRPC, gRPC-Web, and Connect protocols — works in browsers natively |
|
|
| **API definition** | **Protocol Buffers (Protobuf)** | Schema-first API design, backward-compatible evolution, generates Go server stubs + TypeScript/JS clients |
|
|
| **Database** | **PostgreSQL 15+** | Robust, proven, excellent JSON support, full-text search, strong ecosystem |
|
|
| **Frontend** | **React** (TanStack Router + TanStack Query) | Team expertise, strong ecosystem, ConnectRPC generates typed TS clients |
|
|
| **File storage** | Local filesystem or S3-compatible | Configurable per deployment |
|
|
|
|
### Why ConnectRPC
|
|
|
|
[ConnectRPC](https://connectrpc.com/) wraps gRPC to provide **three protocols in one**:
|
|
|
|
| Protocol | Transport | Use Case |
|
|
| ------------ | ------------------------------------ | ---------------------------------------------------------- |
|
|
| **Connect** | HTTP/1.1 or HTTP/2, JSON or Protobuf | Browser clients (no proxy needed), simple `curl` debugging |
|
|
| **gRPC** | HTTP/2, Protobuf | Server-to-server, federation, high-performance clients |
|
|
| **gRPC-Web** | HTTP/1.1, Protobuf | Legacy browser support via Envoy/proxy |
|
|
|
|
This means:
|
|
|
|
- **Web browsers** call the same API using the Connect protocol (plain HTTP + JSON or Protobuf) — no Envoy proxy required
|
|
- **[[04 - Federation Architecture|Federation]]** between instances uses gRPC for efficient binary communication
|
|
- **Mobile apps** can use gRPC natively
|
|
- **One `.proto` definition** generates server code (Go), browser client (TypeScript), and mobile client code
|
|
|
|
### Frontend Stack
|
|
|
|
| Component | Technology | Notes |
|
|
| ----------------- | ---------------------------- | -------------------------------------------------- |
|
|
| **Framework** | React | SPA — SEO is not a requirement |
|
|
| **Routing** | @tanstack/router | Type-safe, file-based routing |
|
|
| **Data fetching** | @tanstack/query | Caching, background refetching, optimistic updates |
|
|
| **API client** | ConnectRPC generated TS code | Type-safe from `.proto` definitions |
|
|
| **Build tool** | Vite | Fast dev server and optimised builds |
|
|
|
|
### Mobile App
|
|
|
|
| Component | Technology | Notes |
|
|
| ----------------- | ---------------------------- | ------------------------------------------------ |
|
|
| **Framework** | React Native / Expo | Shared knowledge with web React team |
|
|
| **Data fetching** | @tanstack/query | Same patterns as web client |
|
|
| **API client** | ConnectRPC generated TS code | Same `.proto` definitions as web |
|
|
| **Priority** | Planned but not prioritised | PWA / responsive web covers initial mobile needs |
|
|
| **Offline** | Nice-to-have | Queue scan operations and sync when reconnected |
|
|
|
|
### Project Structure (Proposed)
|
|
|
|
```
|
|
eventkit/
|
|
├── proto/ # Protobuf definitions
|
|
│ ├── eventkit/v1/
|
|
│ │ ├── inventory.proto
|
|
│ │ ├── planning.proto
|
|
│ │ ├── crm.proto
|
|
│ │ ├── scanning.proto
|
|
│ │ ├── federation.proto
|
|
│ │ └── common.proto # Shared types (UUID, timestamps, pagination)
|
|
│ └── buf.yaml # Buf schema registry config
|
|
├── cmd/
|
|
│ └── eventkit/
|
|
│ └── main.go # Application entrypoint
|
|
├── internal/
|
|
│ ├── server/ # ConnectRPC service implementations
|
|
│ ├── domain/ # Business logic (pure Go, no framework deps)
|
|
│ ├── store/ # Database access (PostgreSQL)
|
|
│ ├── federation/ # Federation protocol handler
|
|
│ └── scanner/ # Scanning workflow logic
|
|
├── gen/ # Generated code (protoc / buf)
|
|
│ ├── go/
|
|
│ └── ts/ # TypeScript client for frontend
|
|
├── web/ # Frontend application
|
|
├── migrations/ # SQL migrations
|
|
├── docker-compose.yml
|
|
├── Dockerfile
|
|
└── buf.gen.yaml # Code generation config
|
|
```
|
|
|
|
### Key Go Libraries
|
|
|
|
| Library | Purpose |
|
|
| ---------------------------------- | ------------------------------------------------------ |
|
|
| **connectrpc.com/connect** | ConnectRPC server and client |
|
|
| **buf.build/gen** | Protobuf code generation (replaces `protoc`) |
|
|
| **jackc/pgx** | PostgreSQL driver (high-performance, pure Go) |
|
|
| **golang-migrate/migrate** | Database migrations |
|
|
| **rs/zerolog** or **slog** | Structured logging (slog is stdlib in Go 1.21+) |
|
|
| **go-chi/chi** or **std net/http** | HTTP router (ConnectRPC mounts on standard `net/http`) |
|
|
| **prometheus/client_golang** | Metrics |
|
|
| **golang-jwt/jwt** | JWT authentication |
|
|
| **testcontainers-go** | Integration testing with real PostgreSQL |
|
|
|
|
---
|
|
|
|
## Deployment
|
|
|
|
### Self-Hosted (Primary Model)
|
|
|
|
Each company runs their own instance. The deployment should be **simple and reproducible**.
|
|
|
|
### Multi-Tenancy (Managed SaaS)
|
|
|
|
For the hosted SaaS offering, use a **shared database with tenant isolation**:
|
|
|
|
| Aspect | Approach |
|
|
| -------------------- | ----------------------------------------------------------------------- |
|
|
| **Database** | Shared PostgreSQL instance, tenant ID on every table |
|
|
| **Isolation** | Row-level security (RLS) policies enforce tenant boundaries |
|
|
| **Connection** | Connection pooling shared across tenants |
|
|
| **Migration** | Single schema, all tenants upgrade together |
|
|
| **Data sovereignty** | Tenants wanting full isolation should use self-hosted or dedicated tier |
|
|
|
|
| Approach | Description |
|
|
| ---------------------- | -------------------------------------------------------------------- |
|
|
| **Docker Compose** | Recommended for single-server deployments — all services in one file |
|
|
| **Kubernetes / Helm** | For larger companies wanting HA, auto-scaling, or multi-node |
|
|
| **Single binary + DB** | Possible for minimal deployments — app server + PostgreSQL |
|
|
|
|
### Minimum Infrastructure
|
|
|
|
| Component | Requirement |
|
|
| ---------------------- | ----------------------------------------------------------- |
|
|
| **Application server** | Linux VPS, 2+ CPU, 4+ GB RAM |
|
|
| **Database** | PostgreSQL 15+ |
|
|
| **File storage** | Local filesystem or S3-compatible object storage |
|
|
| **Reverse proxy** | Nginx / Caddy / Traefik (TLS termination) |
|
|
| **Domain + TLS** | Required for federation (valid certificate needed for mTLS) |
|
|
|
|
### Docker Compose Example Structure
|
|
|
|
```yaml
|
|
services:
|
|
eventkit:
|
|
image: eventkit/server:latest
|
|
# Single Go binary — serves ConnectRPC API + static frontend
|
|
ports:
|
|
- "8080:8080" # Connect protocol (HTTP/1.1 + HTTP/2)
|
|
- "8081:8081" # gRPC (federation, native clients)
|
|
environment:
|
|
- DATABASE_URL=postgres://eventkit:secret@db:5432/eventkit?sslmode=disable
|
|
- FEDERATION_ENABLED=true
|
|
- INSTANCE_URL=https://inventory.company-a.com
|
|
- FEDERATION_GRPC_PORT=8081
|
|
volumes:
|
|
- ./data/uploads:/app/uploads
|
|
|
|
db:
|
|
image: postgres:15
|
|
environment:
|
|
- POSTGRES_USER=eventkit
|
|
- POSTGRES_PASSWORD=secret
|
|
- POSTGRES_DB=eventkit
|
|
volumes:
|
|
- ./data/postgres:/var/lib/postgresql/data
|
|
|
|
caddy:
|
|
image: caddy:latest
|
|
ports:
|
|
- "443:443"
|
|
- "80:80"
|
|
volumes:
|
|
- ./Caddyfile:/etc/caddy/Caddyfile
|
|
```
|
|
|
|
> [!NOTE]
|
|
> Go compiles to a **single static binary** — no runtime, no JVM, no interpreter. The `eventkit` container is typically < 30 MB. Background workers run as goroutines within the same process.
|
|
|
|
---
|
|
|
|
## API Design
|
|
|
|
### Protocol
|
|
|
|
| Decision | Choice |
|
|
| -------------------------- | -------------------------------------------------------------------------------- |
|
|
| **API protocol** | ConnectRPC (supports Connect, gRPC, and gRPC-Web protocols simultaneously) |
|
|
| **Schema language** | Protocol Buffers v3 (`.proto` files) |
|
|
| **Code generation** | `buf` CLI — generates Go server stubs + TypeScript clients |
|
|
| **Transport (browsers)** | Connect protocol over HTTP/1.1 or HTTP/2 (JSON or Protobuf encoding) |
|
|
| **Transport (federation)** | gRPC over HTTP/2 (Protobuf encoding) |
|
|
| **Authentication** | JWT tokens (local users) + mTLS (federation) |
|
|
| **Pagination** | Cursor-based using `page_token` / `next_page_token` pattern in Protobuf messages |
|
|
| **Rate limiting** | Per-user and per-federation-partner, implemented as ConnectRPC interceptors |
|
|
|
|
### Protobuf Service Definitions
|
|
|
|
All APIs are defined as Protobuf services. Example structure:
|
|
|
|
```protobuf
|
|
// proto/eventkit/v1/inventory.proto
|
|
syntax = "proto3";
|
|
package eventkit.v1;
|
|
|
|
service InventoryService {
|
|
rpc ListProducts(ListProductsRequest) returns (ListProductsResponse);
|
|
rpc GetProduct(GetProductRequest) returns (Product);
|
|
rpc CreateProduct(CreateProductRequest) returns (Product);
|
|
rpc UpdateProduct(UpdateProductRequest) returns (Product);
|
|
rpc DeleteProduct(DeleteProductRequest) returns (DeleteProductResponse);
|
|
|
|
rpc ListAssets(ListAssetsRequest) returns (ListAssetsResponse);
|
|
rpc GetAsset(GetAssetRequest) returns (Asset);
|
|
rpc CheckAvailability(CheckAvailabilityRequest) returns (CheckAvailabilityResponse);
|
|
}
|
|
```
|
|
|
|
### Service Map
|
|
|
|
| Protobuf Service | Package | Purpose |
|
|
| ------------------- | ------------- | ------------------------------------------------ |
|
|
| `InventoryService` | `eventkit.v1` | Products, assets, cases, locations, availability |
|
|
| `PlanningService` | `eventkit.v1` | Events, pull lists, scheduling |
|
|
| `CrewService` | `eventkit.v1` | Crew profiles, assignments, availability |
|
|
| `TransportService` | `eventkit.v1` | Vehicles, truck packs, dispatch |
|
|
| `CRMService` | `eventkit.v1` | Contacts, companies, deals, pipeline |
|
|
| `QuoteService` | `eventkit.v1` | Quote building, versioning, PDF generation |
|
|
| `ScanningService` | `eventkit.v1` | Check-in, check-out, stocktake, case packing |
|
|
| `FederationService` | `eventkit.v1` | Trust handshake, sub-hire, asset resolution |
|
|
| `AuthService` | `eventkit.v1` | Login, token refresh, user management |
|
|
| `ReportService` | `eventkit.v1` | Dashboards, analytics, data export |
|
|
|
|
### How Clients Connect
|
|
|
|
| Client | Protocol | Encoding | Notes |
|
|
| -------------------- | --------------- | ----------------------------- | -------------------------------------------------------------------------------------------------------------------- |
|
|
| **Web browser** | Connect | JSON (dev) or Protobuf (prod) | No proxy needed — standard `fetch()` under the hood |
|
|
| **Mobile app** | gRPC | Protobuf | Native gRPC client libraries |
|
|
| **Federation** | gRPC | Protobuf | Instance-to-instance via mTLS |
|
|
| **CLI tool** | Connect or gRPC | Protobuf | For automation and scripting |
|
|
| **cURL / debugging** | Connect | JSON | `curl -X POST -H 'Content-Type: application/json' -d '{...}' https://host/eventkit.v1.InventoryService/ListProducts` |
|
|
|
|
### ConnectRPC Interceptors (Middleware)
|
|
|
|
| Interceptor | Purpose |
|
|
| ------------------- | ------------------------------------------------- |
|
|
| **Auth** | Validate JWT, extract user context |
|
|
| **Federation Auth** | Validate mTLS certificate, check trust level |
|
|
| **Rate Limiter** | Per-user and per-partner rate limiting |
|
|
| **Logger** | Structured request/response logging |
|
|
| **Recovery** | Panic recovery with error reporting |
|
|
| **Validator** | Protobuf message validation (e.g. `buf validate`) |
|
|
| **Metrics** | Prometheus request duration, error rates |
|
|
|
|
---
|
|
|
|
## Authentication & Authorisation
|
|
|
|
### Authentication Methods
|
|
|
|
| Method | Use Case |
|
|
| --------------------------- | -------------------------------------- |
|
|
| **Email + password** | Default for local users |
|
|
| **OAuth 2.0 / OIDC** | SSO via Google, Microsoft, etc. |
|
|
| **LDAP / Active Directory** | Enterprise directory integration |
|
|
| **API keys** | For programmatic access / integrations |
|
|
| **mTLS** | Federation — instance-to-instance |
|
|
|
|
### Role-Based Access Control (RBAC)
|
|
|
|
| Role | Permissions |
|
|
| ------------- | -------------------------------------------------------------------- |
|
|
| **Admin** | Full system access, user management, federation management, settings |
|
|
| **Manager** | All operational features, reporting, approve quotes and purchases |
|
|
| **Planner** | Create/edit events, manage pull lists, assign crew |
|
|
| **Warehouse** | Scan in/out, manage stock, stocktakes, maintenance |
|
|
| **Sales** | CRM access, create/send quotes, manage pipeline |
|
|
| **Crew** | View assigned events, update availability, timesheets |
|
|
| **Read-only** | View dashboards and reports, no edit capabilities |
|
|
|
|
Custom roles with granular permission sets should also be possible.
|
|
|
|
---
|
|
|
|
## Data Model Highlights
|
|
|
|
### Key Relationships
|
|
|
|
```mermaid
|
|
erDiagram
|
|
COMPANY ||--o{ CONTACT : has
|
|
COMPANY ||--o{ DEAL : has
|
|
DEAL ||--o{ QUOTE : has
|
|
DEAL ||--o| EVENT : creates
|
|
|
|
EVENT ||--o{ PULL_LIST_ITEM : has
|
|
EVENT ||--o{ CREW_ASSIGNMENT : has
|
|
EVENT ||--o{ LOAD : has
|
|
EVENT }o--|| VENUE : at
|
|
EVENT }o--o| PROJECT : part_of
|
|
|
|
PRODUCT ||--o{ ASSET : has_instances
|
|
PRODUCT ||--o{ PULL_LIST_ITEM : referenced_by
|
|
ASSET }o--o| CASE : packed_in
|
|
ASSET }o--|| LOCATION : stored_at
|
|
ASSET ||--o{ ASSET_STATUS_LOG : has
|
|
ASSET ||--o{ MAINTENANCE_RECORD : has
|
|
|
|
CASE }o--|| LOCATION : stored_at
|
|
CASE ||--o{ ASSET : contains
|
|
|
|
KIT ||--o{ KIT_ITEM : contains
|
|
KIT_ITEM }o--|| PRODUCT : references
|
|
```
|
|
|
|
---
|
|
|
|
## Performance Requirements
|
|
|
|
| Metric | Target |
|
|
| --------------------- | ------------------------------------ |
|
|
| **Page load time** | < 2 seconds |
|
|
| **API response time** | < 500ms (p95) |
|
|
| **Search response** | < 1 second |
|
|
| **Scan processing** | < 500ms (perceived instant) |
|
|
| **Concurrent users** | 50+ per instance |
|
|
| **Asset count** | Support 100,000+ assets per instance |
|
|
| **Event count** | Support 10,000+ events per instance |
|
|
|
|
---
|
|
|
|
## Backup & Recovery
|
|
|
|
| Feature | Description |
|
|
| ------------------------- | -------------------------------------------------- |
|
|
| **Automated backups** | Daily database backups with configurable retention |
|
|
| **Point-in-time restore** | Transaction log backups for precise recovery |
|
|
| **File backup** | Uploaded files backed up alongside database |
|
|
| **Export** | Full data export in standard formats (JSON, CSV) |
|
|
| **Import** | Data import for migration from other systems |
|
|
|
|
---
|
|
|
|
## Notifications
|
|
|
|
| Channel | Supported | Notes |
|
|
| --------------- | --------- | --------------------------------------------- |
|
|
| **Email** | ✅ Yes | Transactional emails (SMTP or provider API) |
|
|
| **Web push** | ✅ Yes | Browser push notifications via service worker |
|
|
| **Native push** | ✅ Yes | Via Expo push / APNs / FCM for mobile app |
|
|
| **Webhooks** | ✅ Yes | Outbound webhooks for third-party integration |
|
|
| **SMS** | ❌ No | Not planned |
|
|
|
|
---
|
|
|
|
## Monitoring & Observability
|
|
|
|
| Feature | Description |
|
|
| ------------------------- | ------------------------------------------------------ |
|
|
| **Health check endpoint** | `/health` for uptime monitoring |
|
|
| **Structured logging** | JSON logs for easy parsing and analysis |
|
|
| **Metrics** | Prometheus-compatible metrics endpoint |
|
|
| **Error tracking** | Integration with Sentry or similar |
|
|
| **Federation health** | Monitor federation connection status with each partner |
|
|
|
|
---
|
|
|
|
## Internationalisation
|
|
|
|
| Feature | Description |
|
|
| ----------------------- | -------------------------------------------------------- |
|
|
| **Multi-language UI** | Support for multiple interface languages |
|
|
| **Multi-currency** | Prices and costs in different currencies with conversion |
|
|
| **Timezone support** | Per-user timezone, event times stored in UTC |
|
|
| **Date/number formats** | Locale-aware formatting |
|
|
| **Right-to-left** | RTL layout support for applicable languages |
|
|
|
|
---
|
|
|
|
## Related Documentation
|
|
|
|
- [[00 - System Overview]] — High-level system overview
|
|
- [[01 - Inventory Management]] — Inventory module served by `InventoryService`
|
|
- [[02 - Planning Module]] — Planning module served by `PlanningService`
|
|
- [[03 - CRM Module]] — CRM module served by `CRMService` and `QuoteService`
|
|
- [[04 - Federation Architecture]] — Federation deployment and security
|
|
- [[05 - Barcode and QR Scanning]] — Hardware requirements and `ScanningService`
|
|
- [[06 - Module Integration]] — Cross-module workflows
|
|
- [[08 - Open Questions]] — Remaining technical decisions
|