Each feature lives under Features/<FeatureName>/ with its own endpoint registrations, handlers, and response DTOs. There are no shared service or repository layers — handlers depend directly on EchoDbContext and IFileStorage.
- Endpoints are registered as static extension methods on
IEndpointRouteBuilder(e.g.,RecordingEndpoints.MapRecordings). - Each HTTP operation is a separate class with a static
Handlemethod that receives its dependencies via parameter injection. Program.csonly callsAddInfrastructure, maps endpoints, and applies migrations — no controllers.
- EF Core with SQLite, configured with snake_case column naming.
- Enums are stored as lowercase strings via
HasConversion. - Migrations are applied automatically on startup via
ApplyMigrationsAsync. - IDs use
Guid.CreateVersion7()(time-ordered UUIDs).
IFileStorageabstracts upload/download/delete operations against S3-compatible storage.- Local development uses MinIO; production uses AWS S3.
- File keys are structured by context and identifier (e.g.,
audio-recordings/<id>/<filename>).
- The worker runs a continuous loop that polls SQLite for pending
TranscriptionJobrows. - Graceful shutdown via
signal.NotifyContext(SIGINT/SIGTERM). - On each iteration: fetch next pending job → download audio from S3 → transcribe → update job and recording status.
internal/config— loads environment variables into a typed config struct.internal/db— raw SQL queries viadatabase/sql(no ORM); aStoretype wraps the connection.internal/storage— S3 client for downloading audio files.internal/transcription—Transcriberinterface with provider implementations (OpenRouter, OpenAI).
- Both API and worker share the same SQLite database file and MinIO/S3 bucket.
- Docker Compose mounts a shared
appdatavolume for the database.
- Use Conventional Commits format:
<type>(<project>): <summary>. - Use the project name as the commit scope. For example, use
feat(worker): ...for worker changes andfeat(api): ...for API changes. - Do not include files from more than one project in the same commit.
- Commit repository-wide guidance or configuration separately from project-specific changes.
- Keep commit summaries imperative, concise, and without a trailing period.