domrichardson 0849b8f27d
Some checks failed
Build and Push App Image / build-and-push (push) Failing after 1m31s
feat: more workflow fixes
2026-03-24 16:21:46 +00:00
2026-03-24 16:03:04 +00:00
2026-03-24 16:03:04 +00:00
2026-03-24 16:03:04 +00:00
2026-03-24 16:03:04 +00:00
2026-03-24 16:03:04 +00:00
2026-03-24 16:03:04 +00:00
2026-03-24 16:03:04 +00:00
2026-03-24 16:03:04 +00:00
2026-03-24 16:03:04 +00:00
2026-03-24 16:03:04 +00:00
2026-03-24 16:03:04 +00:00

Notely - Secure Multi-Space Note-Taking Application

A production-ready, secure multi-tenant note-taking platform built with Go, Vue 3, and MongoDB.

🚀 Quick Start

Prerequisites

  • Docker & Docker Compose
  • Go 1.21+ (for local development)
  • Node.js 18+ (for frontend development)
  • MongoDB 7.0+ (for local development)

Development with Docker Compose

# Start all services
docker-compose up

# Backend: http://localhost:8080
# Frontend: http://localhost:5173
# MongoDB: localhost:27017
# Nginx: http://localhost:80

Local Development Setup

Backend

cd backend

# Install dependencies
go mod download

# Set environment variables
export MONGODB_URI=mongodb://admin:password@localhost:27017/noteapp?authSource=admin
export JWT_SECRET=your-secret-key
export ENCRYPTION_KEY=00000000000000000000000000000000

# Run migrations and server
go run ./cmd/server/main.go

Frontend

cd frontend

# Install dependencies
npm install

# Start development server
npm run dev

📚 Architecture

Backend (GoClean Architecture)

backend/
├── cmd/server/           # Entry point
├── internal/
│   ├── domain/           # Business logic (entities, interfaces)
│   ├── application/      # Use cases (services, DTOs)
│   ├── infrastructure/   # External dependencies (DB, auth)
│   └── interfaces/       # API handlers & middleware
├── pkg/                  # Public packages
└── tests/               # Test suites

Frontend (Vue 3 Composition API)

frontend/
├── src/
│   ├── components/      # Reusable Vue components
│   ├── pages/          # Page components
│   ├── stores/         # Pinia state management
│   ├── services/       # API client
│   ├── router/         # Vue Router config
│   ├── assets/         # Styles and assets
│   └── main.js         # Entry point
├── index.html
└── vite.config.js

🔐 Security Features

Authentication

  • Argon2id password hashing - Industry-standard PBKDF2
  • JWT tokens with short expiration (1 hour)
  • HTTP-only secure cookies for refresh tokens
  • CSRF protection via SameSite cookies
  • Brute-force protection via login attempt tracking

Authorization

  • Role-based access control (RBAC) per space:
    • Owner: Full control
    • Editor: Edit notes and categories
    • Viewer: Read-only access
  • Space-level data isolation - all queries include space_id
  • IDOR prevention - middleware enforces ownership verification

Data Security

  • Encryption at rest for sensitive fields (OAuth secrets)
  • HTTPS/TLS in production (Nginx reverse proxy)
  • Content Security Policy (CSP) headers
  • XSS protection - DOMPurify for markdown sanitization
  • SQL injection prevention - parameterized queries (MongoDB)

API Security

  • Rate limiting - IP-based and user-based
  • Security headers - HSTS, X-Frame-Options, X-Content-Type-Options
  • CORS properly configured - whitelist origin domains
  • Input validation on all endpoints

📦 API Endpoints

Authentication

POST   /api/v1/auth/register      - Register new user
POST   /api/v1/auth/login         - Login user
POST   /api/v1/auth/refresh       - Refresh access token
POST   /api/v1/auth/logout        - Logout user
GET    /health                    - Health check

Spaces

GET    /api/v1/spaces             - List user's spaces
POST   /api/v1/spaces             - Create space
GET    /api/v1/spaces/{spaceId}   - Get space details
PUT    /api/v1/spaces/{spaceId}   - Update space
DELETE /api/v1/spaces/{spaceId}   - Delete space

Notes

GET    /api/v1/spaces/{spaceId}/notes              - List notes
POST   /api/v1/spaces/{spaceId}/notes              - Create note
GET    /api/v1/spaces/{spaceId}/notes/{noteId}    - Get note
PUT    /api/v1/spaces/{spaceId}/notes/{noteId}    - Update note
DELETE /api/v1/spaces/{spaceId}/notes/{noteId}    - Delete note
GET    /api/v1/spaces/{spaceId}/notes/search?q=   - Search notes

Categories

GET    /api/v1/spaces/{spaceId}/categories        - List categories
POST   /api/v1/spaces/{spaceId}/categories        - Create category
PUT    /api/v1/spaces/{spaceId}/categories/{id}   - Update category
DELETE /api/v1/spaces/{spaceId}/categories/{id}   - Delete category

🗄️ Database Design

MongoDB Collections

users

{
  _id: ObjectId,
  email: String (unique),
  username: String (unique),
  password_hash: String,
  first_name: String,
  last_name: String,
  avatar: String,
  is_active: Boolean,
  email_verified: Boolean,
  created_at: Date,
  updated_at: Date,
  last_login_at: Date
}

spaces

{
  _id: ObjectId,
  name: String,
  description: String,
  icon: String,
  owner_id: ObjectId,
  is_public: Boolean,
  created_at: Date,
  updated_at: Date
}

memberships

{
  _id: ObjectId,
  user_id: ObjectId,
  space_id: ObjectId,
  role: String (owner|editor|viewer),
  joined_at: Date,
  invited_by: ObjectId,
  invited_at: Date
}

notes

{
  _id: ObjectId,
  space_id: ObjectId,
  category_id: ObjectId,
  title: String,
  content: String (Markdown),
  tags: [String],
  is_pinned: Boolean,
  is_favorite: Boolean,
  created_by: ObjectId,
  updated_by: ObjectId,
  created_at: Date,
  updated_at: Date,
  viewed_at: Date
}

categories

{
  _id: ObjectId,
  space_id: ObjectId,
  name: String,
  description: String,
  parent_id: ObjectId (for hierarchical structure),
  icon: String,
  order: Number,
  created_by: ObjectId,
  updated_by: ObjectId,
  created_at: Date,
  updated_at: Date
}

Indexes

users: { email: 1 (unique), username: 1 (unique) }
spaces: { owner_id: 1, created_at: -1 }
memberships: { user_id: 1, space_id: 1 (unique), space_id: 1 }
notes: { space_id: 1, category_id: 1, updated_at: -1, text: "text" }
categories: { space_id: 1, parent_id: 1, order: 1 }

🐳 Deployment

Docker Compose (Development/Testing)

docker-compose up -d

Services:

  • MongoDB (port 27017)
  • Backend API (port 8080)
  • Frontend (port 5173)
  • Nginx Reverse Proxy (port 80)

Kubernetes (Production)

# Create namespace and secrets
kubectl apply -f devops/kubernetes/deployment.yaml

# Verify deployment
kubectl get pods -n noteapp
kubectl port-forward svc/frontend 5173:5173 -n noteapp
kubectl port-forward svc/backend 8080:8080 -n noteapp

Features:

  • StatefulSet for MongoDB with persistent storage
  • Deployments for backend and frontend with horizontal scaling
  • Ingress for routing (requires ingress controller)
  • HPA (Horizontal Pod Autoscaler) for automatic scaling
  • Liveness & readiness probes for health checks
  • Resource limits for fair resource allocation

🧪 Testing

Backend Tests

cd backend
go test ./...
go test -v ./tests/unit/...
go test -v ./tests/integration/...

Frontend Tests

cd frontend
npm run test
npm run test:watch

🔧 Configuration

Environment Variables

Backend (.env)

MONGODB_URI=mongodb://admin:password@localhost:27017/noteapp
JWT_SECRET=your-secret-key-min-32-chars
ENCRYPTION_KEY=32-char-encryption-key-for-secrets
PORT=8080
LOG_LEVEL=info
ENV=development

Frontend (.env)

VITE_API_BASE_URL=http://localhost:8080

📝 Development Guidelines

Code Structure

  • Follow clean architecture principles
  • Separate concerns: domain, application, infrastructure
  • Use interfaces for dependency injection
  • Keep services testable and focused

Security Best Practices

  1. Never store secrets in code - use environment variables
  2. Validate all inputs on backend
  3. Sanitize outputs before rendering
  4. Use HTTPS in production
  5. Implement rate limiting on APIs
  6. Log security events (login attempts, permission denied)
  7. Audit trail for sensitive operations

Commit Message Format

[TYPE] Description

types: feat, fix, docs, style, refactor, test, chore

📖 API Documentation

Request/Response Format

All API requests and responses use JSON.

# Example: Create Note
curl -X POST http://localhost:8080/api/v1/spaces/{spaceId}/notes \
  -H "Authorization: Bearer {accessToken}" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "My Note",
    "content": "# Markdown content",
    "tags": ["tag1", "tag2"],
    "category_id": null,
    "is_pinned": false,
    "is_favorite": false
  }'

🚨 Error Handling

All errors return appropriate HTTP status codes:

  • 400 - Bad Request
  • 401 - Unauthorized
  • 403 - Forbidden (insufficient permissions)
  • 404 - Not Found
  • 409 - Conflict (e.g., duplicate email)
  • 429 - Too Many Requests (rate limit exceeded)
  • 500 - Internal Server Error

🎯 Future Enhancements

  • OAuth2/OIDC integration
  • Email notifications
  • Real-time collaboration (WebSockets)
  • Full-text search with Elasticsearch
  • Export to PDF/Markdown
  • Mobile applications
  • Plugin system
  • Advanced permissions management

📄 License

MIT License - See LICENSE file

👥 Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Commit your changes
  4. Push to the branch
  5. Create a Pull Request

Built with ❤️ for secure, collaborative note-taking

Description
No description provided
Readme 899 KiB
Languages
Go 46.3%
Vue 41.7%
CSS 7.2%
JavaScript 4.7%