Skip to content

Backend Architecture

Bootstrap

backend/main.go wires config loaders, database pools, Redis, crypto services, and the Fiber app created in server/app.go.

Routing

backend/routes.go registers middleware, REST handlers, WebSocket hub, and rate-limit tiers.

Background Jobs

backend/services/* schedules admin seeding, template import, key rotation, and cleanup tasks.

go run ./backend # Loads config.LoadConfig()
# Connects pgxpool + redis
# Creates crypto.CryptoService (ChaCha20-Poly1305)
# server.CreateFiberApp(...) -> routes.go -> ListenAndServe
recover.New(...) // Panic capture -> utils.LogError
requestID middleware // Adds X-Request-ID header
logger.New(...) // Structured request logs
compress.New(...) // GZip API responses (skips WebSocket)
Group("/api/v1/health/*") // Live / Ready probes before auth

server/health.go maintains a ReadyState guard:

  • Flags flip when admin bootstrapping, template seeding, allowlist import, and Redis readiness complete.
  • /api/v1/health/live: always available for load balancers.
  • /api/v1/health/ready: blocks until ReadyState.IsFullyReady() and verifies quick users count + Redis ping.
readyState := server.NewReadyState(db, crypto, cfg, redisClient)
go services.RunBootSequence(..., readyState)
app := server.CreateFiberApp(startTime, readyState)
setupRoutes(app, ...)

middleware/rate_limit.go builds Redis-backed limiters from the shared connection:

  • Tier 1 (AuthLimiter, RegisterLimiter, MFAVerifyLimiter): brute-force protection, 10 or fewer attempts per five minutes.
  • Tier 2 (ShareLinkPublicLimiter, ShareLinkCreateLimiter): throttles token enumeration and creation abuse.
  • Tier 3 (SearchLimiter, ImportExportLimiter, AttachmentUploadLimiter): resource-heavy endpoints.
  • Tier 4 (StandardCRUDLimiter, CollaborationLimiter): note CRUD and collaborator management.
  • Tier 5 (LightweightLimiter): profile reads and MFA status checks.

Redis keys use utils.ClientIP(c) to hash IPv4/IPv6 uniformly.

Authentication

handlers/auth.go issues JWTs signed with JWT_SECRET, coordinates Redis session caches, and delegates MFA to services/mfa.go.

Notes & Metadata

handlers/notes.go, tags.go, folders.go, templates.go work with encrypted payloads via crypto.CryptoService.

Collaboration

handlers/collaboration.go shares note keys using RSA public keys stored on users; WebSocket events broadcast through websocket/hub.go.

Share Links

handlers/share_links.go writes to the share_links table, caches tokens in Redis, and enforces password + usage limits.

All handlers receive pgx pools directly—no ORM—so transactional logic lives in each handler file. Where consistent patterns exist (e.g., backup code generation), shared helpers live under services/.

  • services/admin.go: seeds the default admin account if ENABLE_DEFAULT_ADMIN=true.
  • services/templates.go: imports bundled templates from backend/templates/ into the templates table.
  • services/cleanup.go: runs cleanup_old_deleted_notes() nightly and clears expired share links.
  • services/share_links.go: rotates tokens beyond max_uses and expires stale connections.

All jobs use context.Context timeouts and emit structured logs through utils.

websocket/hub.go orchestrates real-time sessions:

  • Fiber upgrades to /ws; websocket.HandleWebSocket registers clients.
  • Every message includes the collaborator UUID and note ID; authorization is validated via pgx queries.
  • Broadcasts fan out only to users with entries in the collaborations table; share-link viewers are excluded deliberately.