Skip to content

Develop - #81

Merged
ademboukabes merged 32 commits into
mainfrom
develop
Aug 31, 2026
Merged

Develop#81
ademboukabes merged 32 commits into
mainfrom
develop

Conversation

@ademboukabes

Copy link
Copy Markdown
Collaborator

Summary of Changes (Release Candidate)

This Pull Request merges all validated features and fixes from develop into main for production deployment.
It includes major improvements in robustness (Drive Sync, JetStream), new upload features (Direct Upload), and security enhancements.

New Features

  • Direct Bulk Upload: Added a comprehensive API to allow photographers to import their photos directly (bypassing Google Drive). Includes batching, pre-validation, SQLC queries, and Drive sync upon approval.
  • Event Automations: Events now automatically transition to active/closed states based on their scheduled start/end times.
  • Profile Updates: Added a self-service endpoint allowing users to update their display name.

Robustness & Stability Improvements

  • NATS JetStream: Full migration to NATS JetStream for guaranteed event delivery and crash resilience.
  • Drive Sync Worker (M-1): Completely overhauled Redis folder locking to prevent concurrency crashes on large Google Drive folders. Integrated exponential backoff.
  • Storage & Cleanup: Automated raw photo deletion (Storage Cleaner) now uses a secure threshold-based approach to prevent storage saturation.

Security & Integrity

  • Filters & Gates: Unapproved photos are now hidden from the general user gallery. Mobile endpoints are gated as long as the user has not completed face enrollment.
  • Enrollment Redis Lock: Secure handling of Redis unavailability during face enrollment.
  • Cookies: The secure cookie configuration now properly adapts to the environment.

Code Quality & CI/CD

  • Linting & Typing: Strictly resolved ruff warnings and mypy errors.
  • Continuous Integration & Deployment: Added automated Docker image generation during pushes to the develop branch.

wailbentafat and others added 30 commits August 24, 2026 23:58
- Add require_onboarded_mobile_user dependency: every mobile endpoint
  except /auth/* and /enroll now returns 403 until the user completes
  face enrollment (users.face_embedding is set).
- Add is_onboarded to GET /user/auth/me and the avatar upload response
  so clients can branch on a single field instead of parsing 403s.
- Fix asyncpg/SQLAlchemy jsonb handling: register a jsonb type codec on
  connect so dict params bind correctly and jsonb columns decode back
  to dict (was crashing audit_events writes, and silently mismatched
  on notifications/staff_notifications reads).
- Add a dev-env fixed OTP (DEV_OTP_BYPASS_CODE) for registration so
  local/mobile testing doesn't require a real inbox or NATS email flow.
…audit-fixes

feat: gate mobile endpoints behind face enrollment, fix jsonb round-trip
- Add events.end_date (nullable timestamptz) via migration.
- Add ActivateDueEvents / ArchiveEndedEvents queries: draft -> scheduled
  when event_date has passed, scheduled -> archived (+ archived_at) when
  end_date has passed.
- Add a polling worker (app/worker/event_lifecycle) that runs both
  transitions every EVENT_LIFECYCLE_POLL_INTERVAL_SECONDS (default 60s),
  wired into make run-workers.
- Thread end_date through EventCreate/EventResponse/UserEventResponse
  and CreateEvent/GetUserEvents.

Events with no end_date set are never auto-archived and stay in
scheduled until archived manually via the existing endpoint.
…cycle

feat: automate event lifecycle transitions on start/end time
Adds a per-photo face count (subquery over photo_faces) to
ListUserPhotos and ListEventPhotosForUser, and surfaces it as
face_count on GET /photos and GET /photos/event/{event_id}. Lets
clients distinguish solo photos (one face) from group photos
(multiple faces) without an extra request per photo.
ListUserPhotos (GET /user/photos) was missing the status='approved' filter
that ListEventPhotosForUser already has, so a photo a user was still
pending/rejected on could leak into the general gallery while correctly
staying hidden from the event-scoped view — same photo, inconsistent
visibility depending on which endpoint you hit.
PATCH /user/auth/me/profile lets a mobile user update their own
display name, reusing AuthService.update_user which already existed
but was only wired for admin/internal use.
- Switch NATS pub/sub to JetStream for persistent message queues
- Update all workers to use JetStream subscriptions and proper exception propagation (nak)
- Remove outdated duplicated test folder (app/worker/photo_worker/tests) which caused global state leakage
- Fix CreatePhotoParams missing source argument in tests
- Ensure 100% test pass rate
- TTL 30s → 120s to survive slow Drive API calls
- Lock value = unique UUID per acquisition (prevent foreign release)
- Async heartbeat refreshes TTL every 40s to avoid expiry mid-operation
- Extract _resolve_drive_folder to stay under ruff C901 limit
- Add missing logger import in staff_drive.py
@ademboukabes
ademboukabes merged commit 1fb94fb into main Aug 31, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants