Files
org-parking/CLAUDE.md
Stefano Manfredi ce9e2fdf2a fix landing page
2025-12-02 23:18:43 +00:00

7.9 KiB

CLAUDE.md - Project Intelligence

Project Overview

Org-Parking is a manager-centric parking spot management system for organizations. It features fair parking assignment based on presence/parking ratio, supporting both standalone JWT authentication and Authelia/LLDAP SSO integration.

Technology Stack

  • Backend: FastAPI + SQLAlchemy + SQLite
  • Frontend: Vanilla JavaScript (no frameworks)
  • Auth: JWT tokens + Authelia SSO support
  • Containerization: Docker + Docker Compose
  • Rate Limiting: slowapi

Architecture

app/
├── config.py       → Configuration with logging and validation
└── routes/         → API endpoints (auth, users, managers, presence, parking)
services/           → Business logic (parking algorithm, auth, notifications)
database/           → SQLAlchemy models and connection
frontend/           → Static HTML pages + JS modules
utils/
├── auth_middleware.py → JWT/Authelia authentication
└── helpers.py         → Shared utility functions

Build & Run Commands

# Development
SECRET_KEY=dev-secret-key python -m uvicorn main:app --reload --host 0.0.0.0 --port 8000

# Docker
docker compose up -d

# Dependencies
pip install -r requirements.txt

# Initialize test database
python create_test_db.py

Code Style & Conventions

Python

  • FastAPI async patterns with Depends() for dependency injection
  • Pydantic models for request/response validation
  • SQLAlchemy ORM (no raw SQL)
  • Use generate_uuid() from utils.helpers for UUIDs
  • Use config.logger for logging (not print statements)
  • Dates stored as TEXT in "YYYY-MM-DD" format

JavaScript

  • ES6 modules with centralized API client (/js/api.js)
  • Token stored in localStorage, auto-included in requests
  • Utility functions in /js/utils.js
  • Role-based navigation in /js/nav.js

Authentication

  • Dual mode: JWT tokens (standalone) or Authelia headers (SSO)
  • LDAP users have password_hash = None
  • Use helper: is_ldap_user(user) from utils.helpers

Utility Functions (utils/helpers.py)

from utils.helpers import (
    generate_uuid,           # Use instead of str(uuid.uuid4())
    is_ldap_user,           # Check if user is LDAP-managed
    is_ldap_admin,          # Check if user is LDAP admin
    validate_password,       # Returns list of validation errors
    format_password_errors,  # Format errors into user message
    get_notification_default # Get setting value with default
)

Configuration (app/config.py)

Configuration is environment-based with required validation:

Required

  • SECRET_KEY - MUST be set (app exits if missing)

Security

  • RATE_LIMIT_REQUESTS - Requests per window (default: 5)
  • RATE_LIMIT_WINDOW - Window in seconds (default: 60)

Email (org-stack pattern)

  • SMTP_ENABLED - Set to true to enable SMTP sending
  • When disabled, emails are logged to EMAIL_LOG_FILE
  • Follows org-stack pattern: direct send with file fallback

Logging

  • LOG_LEVEL - DEBUG, INFO, WARNING, ERROR (default: INFO)
  • Use config.logger for all logging

Notifications (services/notifications.py)

Simplified notification service following org-stack pattern:

from services.notifications import (
    send_email,              # Direct send or file fallback
    notify_parking_assigned, # When spot assigned
    notify_parking_released, # When spot released
    notify_parking_reassigned, # When spot reassigned
    send_presence_reminder,  # Weekly presence reminder
    send_weekly_parking_summary, # Friday parking summary
    send_daily_parking_reminder, # Daily parking reminder
    run_scheduled_notifications  # Called by cron/scheduler
)

Email Behavior

  1. If SMTP_ENABLED=true: Send via SMTP
  2. If SMTP fails or disabled: Log to EMAIL_LOG_FILE
  3. Never throws - always returns success/failure

Recent Improvements

Security Enhancements

  • Required SECRET_KEY: App exits if not set
  • Rate limiting: Login/register endpoints limited to 5 req/min
  • Password validation: Requires uppercase, lowercase, number, 8+ chars
  • Proper logging: All security events logged

Performance Optimizations

  • Fixed N+1 queries in:
    • list_users() - Batch query for manager names and counts
    • list_managers() - Batch query for managed user counts
    • get_manager_guarantees() - Batch query for user names
    • get_manager_exclusions() - Batch query for user names

Code Consolidation

  • Utility functions (utils/helpers.py):
    • generate_uuid() - Replaces 50+ str(uuid.uuid4()) calls
    • is_ldap_user() - Replaces 4+ duplicated checks
    • validate_password() - Consistent password validation
  • Simplified notifications - Removed queue system, direct send

Logging Improvements

  • Centralized logging via config.logger
  • Replaced print() with proper logging
  • Security events logged (login, password change, etc.)

API Quick Reference

Authentication

  • POST /api/auth/register - Create user (rate limited)
  • POST /api/auth/login - Get JWT token (rate limited)
  • GET /api/auth/me - Current user (JWT or Authelia)

Presence

  • POST /api/presence/mark - Mark single day
  • POST /api/presence/mark-bulk - Mark multiple days
  • GET /api/presence/team - Team calendar with parking

Parking

  • POST /api/parking/manual-assign - Manager assigns spot
  • POST /api/parking/reassign-spot - Reassign existing spot
  • GET /api/parking/eligible-users/{id} - Users for reassignment

Manager Settings

  • GET/POST/DELETE /api/managers/closing-days
  • GET/POST/DELETE /api/managers/weekly-closing-days
  • GET/POST/DELETE /api/managers/guarantees
  • GET/POST/DELETE /api/managers/exclusions

Development Notes

Adding a New Route

  1. Create file in app/routes/
  2. Use APIRouter(prefix="/api/...", tags=["..."])
  3. Register in main.py: app.include_router(...)
  4. Add auth dependency: current_user: User = Depends(get_current_user)
  5. Use config.logger for logging
  6. Use generate_uuid() for new records

Database Changes

No migration system (Alembic) configured. Schema changes require:

  1. Update database/models.py
  2. Delete SQLite file or write manual migration
  3. Run create_test_db.py for fresh database

Email Testing

With SMTP_ENABLED=false, check email log:

tail -f /tmp/parking-emails.log

Running Scheduled Notifications

Add to cron or systemd timer:

# Every 5 minutes
*/5 * * * * cd /path/to/org-parking && python -c "
from database.connection import get_db
from services.notifications import run_scheduled_notifications
db = next(get_db())
run_scheduled_notifications(db)
"

Purpose File
Main entry main.py
Configuration app/config.py
Database models database/models.py
Parking algorithm services/parking.py
Notifications services/notifications.py
Auth middleware utils/auth_middleware.py
Utility helpers utils/helpers.py
Frontend API client frontend/js/api.js
CSS styles frontend/css/styles.css
Docker config compose.yml
Environment template .env.example

Deployment Notes

Remote Server

  • Host: rocketscale.it
  • User: rocky
  • SSH: ssh rocky@rocketscale.it
  • Project path: /home/rocky/org-parking
  • Related project: /home/rocky/org-stack (LLDAP, Authelia, etc.)

Environment Variables

Copy .env.example to .env and configure:

# Generate secure key
openssl rand -hex 32

Production Checklist

  • Set strong SECRET_KEY
  • Configure ALLOWED_ORIGINS (not *)
  • Set AUTHELIA_ENABLED=true if using SSO
  • Configure SMTP or check email log file
  • Set up notification scheduler (cron/systemd)