Architecture Overview¶
Last Updated: 2025-11-23
This document describes the high-level architecture of ocmonica, including the dual API design, technology stack, and request flow patterns.
Table of Contents¶
Dual API Architecture¶
Ocmonica implements a dual API architecture where both REST (Echo) and gRPC (ConnectRPC) APIs coexist as first-class citizens on the same HTTP server. This provides flexibility for different client types:
- REST API (Echo v4): Traditional HTTP/JSON endpoints for web browsers, curl, and standard HTTP clients
- gRPC API (ConnectRPC): Type-safe, high-performance RPC endpoints for modern web apps and native clients
Both APIs: - Share the same service layer (business logic) - Run on the same port (8080) using h2c (HTTP/2 Cleartext) - Enforce the same authentication and authorization rules - Are fully production-ready and tested
Design Philosophy¶
The dual API approach provides a best-of-both-worlds solution:
- REST API: Universal compatibility, authentication management, health checks
- gRPC API: Type safety, performance, streaming capabilities for core operations
This architecture maximizes flexibility without significant maintenance overhead. The shared service layer ensures no code duplication, and both APIs are production-ready.
Technology Stack¶
Backend Core¶
Go 1.25.2 - Modern Go features with generics support - Follows Go idioms and best practices
Echo v4.13.4 (REST Framework)
- Middleware stack: Logger → Recover → CORS → Security Headers → JWT → RBAC
- Group-based routing for /api/v1/*
- Custom error handler for consistent responses
- Documentation: https://echo.labstack.com/
ConnectRPC v1.19.1 (gRPC Framework) - Interceptors for auth and RBAC (similar to middleware) - Supports Connect, gRPC, and gRPC-Web protocols - Type-safe generated code from protobuf - Documentation: https://connectrpc.com/
SQLite (modernc.org/sqlite v1.39.0) - Pure Go implementation (no CGO) - In-memory databases for tests - Migration system - Connection pooling configured
Dependency Versions¶
Backend (Go) - From go.mod:
require (
connectrpc.com/connect v1.19.1 // ConnectRPC core
github.com/labstack/echo/v4 v4.13.4 // Echo web framework
github.com/labstack/echo-contrib v0.17.4 // Echo middleware
github.com/labstack/echo-jwt/v4 v4.3.1 // JWT middleware for Echo
google.golang.org/protobuf v1.36.10 // Protocol Buffers
golang.org/x/net v0.46.0 // HTTP/2 support (h2c)
)
Frontend (TypeScript/React) - From web/package.json:
{
"dependencies": {
"@bufbuild/protobuf": "^2.9.0", // Protobuf runtime
"@connectrpc/connect": "^2.1.0", // ConnectRPC client core
"@connectrpc/connect-query": "^2.2.0", // TanStack Query integration
"@connectrpc/connect-web": "^2.1.0", // Web transport layer
"@tanstack/react-query": "^5.90.2", // Server state management
"next": "15.5.4", // React framework
"react": "19.1.0", // UI library
"axios": "1.12.2" // REST API client (fallback)
}
}
For complete technology stack details, see CLAUDE.md (Technology Stack section) in the project root.
System Architecture¶
High-Level Overview¶
The following diagram shows the complete system architecture with all major components:
Complete system architecture showing client layer, API gateway, middleware/interceptors, handlers, services, repositories, and observability stack.
Architecture Highlights:
- Dual API: Both REST and gRPC on same port (8080) using h2c
- Layered Design: Clear separation between handlers, services, and repositories
- Shared Services: Both APIs use the same business logic layer
- Comprehensive Observability: OpenTelemetry tracing + Prometheus metrics
- Multi-Tenancy: Organization isolation enforced at repository layer
Request Flow¶
Both APIs follow a consistent request flow pattern through the application layers.
REST Request Flow¶
Sequence diagram showing the complete REST API request flow from client through middleware stack, handlers, services, repositories to database and back.
gRPC Request Flow¶
Sequence diagram showing the complete gRPC API request flow from client through interceptor chain, handlers, services, repositories to database and back.
Layered Architecture¶
The following diagram illustrates the strict layered architecture pattern:
Layered architecture showing separation between presentation layer (handlers), business logic layer (services), data access layer (repositories), and data storage.
Key Principles:
- Separation of Concerns: Each layer has a single responsibility
- Dependency Injection: Services and repositories injected into handlers
- Context Propagation:
context.Contextflows through all layers for tracing - Error Handling: Errors wrapped with context at each layer
- No Bypassing: Always go through the full stack (no shortcuts)
For detailed patterns, see CLAUDE.md (Architecture section) in the project root.
Integration Pattern¶
Both APIs are integrated on a single HTTP server using h2c (HTTP/2 Cleartext):
// cmd/server/main.go (lines 343-351)
server := &http.Server{
Addr: fmt.Sprintf("%s:%d", cfg.Server.Host, cfg.Server.Port),
Handler: h2c.NewHandler(e, &http2.Server{}), // h2c enables gRPC + REST on same port
}
Key Architecture Points:
1. Single Port: Both APIs accessible on port 8080
2. Path Separation:
- REST: /api/v1/*
- gRPC: /ocmonica.v1.*/*
3. Shared Service Layer: Both handlers call the same business logic services
4. Unified Auth: Both use JWT tokens with same validation
Protocol Support¶
ConnectRPC Protocol Support¶
ConnectRPC supports three protocols on the same endpoint:
- Connect Protocol (recommended)
- JSON or binary encoding
- Browser-friendly (uses standard HTTP/POST)
-
Best for web applications
-
gRPC Protocol
- Binary Protocol Buffers encoding
- Requires HTTP/2
-
Best for server-to-server
-
gRPC-Web Protocol
- Compatible with gRPC proxies (e.g., Envoy)
- Works with existing gRPC infrastructure
Client Selection:
// Frontend: Use Connect protocol with JSON (easy debugging)
const transport = createConnectTransport({
baseUrl: 'http://localhost:8080',
useBinaryFormat: false, // JSON format
});
// Or use binary format for better performance
const transport = createConnectTransport({
baseUrl: 'http://localhost:8080',
useBinaryFormat: true, // Protocol Buffers binary
});
Echo REST Protocol Support¶
- HTTP/1.1: Full support
- HTTP/2: Supported via h2c
- WebSocket: Supported via Echo WebSocket middleware
- Content Types: JSON (primary), XML, form data, multipart
Multi-Tenancy Architecture¶
Ocmonica implements complete data isolation between organizations through a comprehensive multi-tenancy model.
Data Model¶
Entity-relationship diagram showing the complete database schema including organizations, users, files, roles, permissions, and groups with their relationships and key attributes.
Organization Isolation¶
The following diagram shows how data isolation is enforced:
Flow diagram illustrating how organization-based data isolation is enforced through multiple layers: request context extraction, middleware validation, service filtering, and repository-level WHERE clauses.
Isolation Guarantees:
- Context-Based: Organization ID extracted from JWT token
- Middleware Enforcement: Early validation of organization access
- Service Layer: Business logic respects organization boundaries
- Repository Layer: All queries include
WHERE organization_id = ? - Database Level: Foreign key constraints ensure referential integrity
Security Rules:
- Users can only access resources in their organization
- Cross-organization access is forbidden (returns 404, not 403)
- All database queries MUST filter by
organization_id - Missing organization filter is a critical security vulnerability
For implementation details, see Authentication & Authorization Guide.
See Also¶
- REST API Documentation
- gRPC API Documentation
- Authentication & Authorization
- See
DEVELOPMENT.mdin the project root for development guide - See
CLAUDE.mdin the project root for Claude development guide