This document describes what the Amigonimo API currently provides. For the technology stack, see README.md. For upcoming and in-progress work, see ROADMAP.md.
- Sign-up – create an account with email + password (
POST /auth/sign). - Login – authenticate and receive a JWT access token (
POST /auth/login). - Token regeneration – rotate an existing token (
PATCH /auth/regenerate). - Password reset – request and confirm a password reset via recovery code
(
PUT /auth/password/reset,PATCH /auth/password/check-recovery). - JWT authentication uses RSA key pairs; the middleware validates tokens on every protected route.
- Profile data (full name, etc.) is stored in a separate
user_profilestable, decoupled from auth credentials. - The
entities.Userstruct holds only identity and auth data;entities.UserProfileholds presentational data.
- Create a group (
POST /secret-friends/) – any authenticated user can create a new Secret Friend event with a name and optional configuration (e.g. max denylist size). - List own groups (
GET /secret-friends/) – returns all groups the current user owns or participates in. - Get group details (
GET /secret-friends/{id}). - Update group (
PATCH /secret-friends/{id}) – owners can rename or change group settings. - Invite codes – each group has a shareable invite code. Anyone with the code can look up group
information (
GET /secret-friends/invites/description/{code}) before deciding to join.
- Join a group (
POST /secret-friends/{id}/participants/) – a user joins via invite code; creates a participant record. - List participants (
GET /secret-friends/{id}/participants/) – returns all participants with their ready status. - Ready status – participants can mark themselves as ready (preferences locked), giving the organizer
visibility into who has finished filling in their lists (
SetParticipantReady).
- Get wishlist (
GET /secret-friends/{id}/wishlist/) – returns the current user's wishlist items for the group. - Add item (
POST /secret-friends/{id}/wishlist/) – append a new item (label + optional comments). - Delete item (
DELETE /secret-friends/{id}/wishlist/{itemId}). - Capacity enforcement – an internal hard cap (
maxWishListSize) prevents unbounded lists; the usecase returns a conflict error when the limit is reached. - Access control – only confirmed participants of the group may read or modify their own wishlist.
- Get denylist (
GET /secret-friends/{id}/denylist/) – returns the current user's denied pairings. - Add entry (
POST /secret-friends/{id}/denylist/) – prevent a specific participant from being assigned to the current user. - Remove entry (
DELETE /secret-friends/{id}/denylist/{deniedUserId}). - Self-deny protection – users cannot add themselves to their own denylist.
- Non-participant protection – only participants of the same group can be added.
- Capacity cap – the denylist is capped at 50% of the total participant count (hard constraint to
guarantee draw feasibility) and additionally limited by the group's configurable
MaxDenyListSize.
- Execute draw (
POST /secret-friends/{id}/draw) – the group owner triggers the pairing algorithm. The draw:- Loads all participants and their denylists.
- Builds a constraint graph.
- Attempts multiple matching strategies in order: greedy → reverse-greedy → chain-close.
- Persists results and transitions the group to a drawn state, all in a single database transaction.
- Get draw results (
GET /secret-friends/{id}/draw-result) – returns the current user's assigned Secret Friend (recipient).
Three configurable backends are available (selected via conf.toml):
| Backend | Use case |
|---|---|
stub |
Development / tests – no-op sender |
smtp |
Production email via any SMTP relay |
webhook |
Forward email payloads to an HTTP endpoint |
The mailer is integrated into the DI container and can be injected into any usecase that needs to send notifications.
- Embedded migrations – SQL migration files are embedded in the binary and applied automatically on startup via the built-in migrator (no external Atlas CLI needed at runtime).
- Schema-as-code – entity schemas are defined with Ent; migrations are generated with Atlas.
- Type-safe queries – all database queries are generated by sqlc from
.sqlfiles. - DTO mapping – Goverter generates compile-time-checked mapper code between DB models and domain entities.
- Dependency injection – Remy DI container wires services and injects per-request user context automatically.
- Error handling – structured
apperrpackage maps domain errors to HTTP status codes uniformly viapkg/web/error_mapper.go. - Docker support –
Dockerfileanddocker-compose.ymlprovided for local development and deployment. - Taskfile – common workflows (build, lint, migrate, test, dev-env) are scripted in
Taskfile.yml.
- Unit tests for all repository adapters (
authuserepo,authtokenrepo,denylistrepo,participantrepo,secretfriendrepo,wishlistrepo). - Unit tests for mappers, mailer backends, utils, and JWT middleware.
- Integration tests in
test/backed by a real MariaDB instance (viatestereiro), covering happy and failure paths for all currently mounted routes. - Draw matching strategies each have dedicated unit tests covering edge cases (odd counts, full denylist constraints, etc.).