ToDo
This document tracks actionable items that are not yet captured in an issue. Completed items are removed — history lives in git.
1.0.0
Documentation
- [x] Replace drawio diagrams (
docs/assets/architecture_*.drawio.svg) with Mermaid diagrams embedded directly indocs/ARCHITECTURE.mdso they can be maintained without a separate diagramming tool - [x] Architecture diagram
- [x] User documentation (API consumers)
- [x] Developer documentation (contributors)
- [x] Administrator documentation (installation and operations; cover creating a dedicated
snackboxsystem user/group and running the binary under it) - [x] Add package-level comments plus exported type/method docs to key server packages (config, database, middleware, handlers, router) so
go docsurfaces meaningful context in IDE hovers - [x] Document how to preview the API via
godoc(e.g.godoc -http=:6060) inside docs/DEVELOPER.md so contributors can discover it without digging through issues
Deployment
- [x] Provide example systemd service file (incl. recommended FHS paths as env vars and
User=snackbox/Group=snackbox) - [x] Dockerfile (run as non-root
snackboxuser viaUSERinstruction) - [x] docker-compose.yml
Release
- [x] CI/CD pipeline (boilerplate already there)
Testing
- [ ] Replace the placeholder
cmd/server/main_test.gowith a real smoke test that starts the server on an ephemeral port, hits/healthz, exercises the metrics mux, and shuts everything down via context cancel - [x] Consolidate
withUserContext(users_test.go) intowithUserID(posts_test.go) — both helpers inpackage handlers_testdo the same thing; deletewithUserContext, replace its call-sites withwithUserID, and movewithUserID+withUserRoletohandlers_test.goso they are obviously available to all files in the package - [ ] Fix shared-state ordering dependency in
TestUserHandler_FindAll— the "empty list" and "returns all users" subtests share the same outerrepo; give each subtest its own isolated DB/repo like the "limit capped at 100" subtest already does - [x] Trim
TestLoggingMiddleware— the three status-code subtests (200, 404, 500) exercise the same code path; one is sufficient; keep theTestLoggingMiddleware_RemoteAddrtest as-is - [ ] Fix weak assertion in
TestRouter_AdminAuthorRoutes_AllowedRoles— routes are hit without a body so they return 400 (bad request), which satisfies the!= 401/403check but proves nothing; either supply minimal valid bodies per route or remove the test (the auth matrix is already covered by the no-auth and wrong-role router tests) - [ ] Add admin-override subtest to
TestPageHandler_Update_Ownershipto match the equivalent three-subtest structure inTestPostHandler_Update_Ownership - [x] Add
.golangci.ymland enableparalleltestandthelperlinters — all tests already use isolated in-memory DBs andt.TempDir()so addingt.Parallel()to the ~80 top-level test functions is safe and will cut CI test time significantly on multi-core runners;thelperprevents helper functions from regressing on missingt.Helper()calls - [ ] Add focused unit tests for
internal/metrics(path normalization/status helpers),internal/config(env fallback/validation), and the error branches ininternal/database.RunMigrationsto close the remaining coverage gaps - [x] Add a race-enabled test target (e.g.
make test-racewrappinggo test -race ./...) so developers can catch data races locally before CI
Tooling
- [x] Expand
.PHONYcoverage for every developer-facing target and reorganize the Makefile into clearly labeled sections (build, test, run, tooling) - [x] Add a discoverable
make helptarget that prints concise descriptions for all public targets and highlights daily vs pre-PR workflows - [ ] Centralize development environment variables (JWT secret, admin creds, DB path, port) via a shared include or variable block used by
runandsmoketargets to eliminate duplication - [ ] Provide a
make setup(orinstall-tools) target that verifies required CLIs (golangci-lint,hurl, etc.) and gives clear install guidance - [ ] Enhance test targets so
make testproduces coverage artifacts underbuild/coverageand supports aFAST=1flag to skip expensive smoke tests when needed - [ ] Replace arbitrary test data identifiers (e.g.
smoke-tag,smoke-post,smoke-author@example.com) intest/*.hurlwith well-known patterns such as RFC 2606 names (Alice, Bob) and reserved domains (alice@example.com) to improve readability and intent - [x] Rename the Hurl-based
smokeworkflow (e.g.make smoketarget and docs) to an "API"/"integration" label so Go-based smoke tests own the name; be sure to update documentation and CI references alongside the rename - [ ] Harden dev-server lifecycle management (controllable port, graceful teardown/trap, no manual
lsofcleanup) forrun/smoke - [ ] Add Docker convenience targets (e.g.
docker-run,docker-compose-up,docker-compose-down,docker-logs) to streamline parity environments - [ ] Update README and docs/DEVELOPER.md quickstart sections to showcase the improved Makefile workflow (
make setup && make run, etc.) - [x] Configure
golangci-lint(e.g. enablerevive'sdoc-commentsrule) so CI fails when exported identifiers lack documentation - [x] Add a
make fmt(ormake format) target that runsgo fmt ./...(and optionallygoimports) so contributors can auto-format before committing - [ ] Extend README quickstart with a native Go workflow (using
make run/make unit) so contributors who skip Docker know the supported steps
Optional / To Evaluate
- [ ] Investigate pinning developer tooling versions (e.g.
golangci-lint,hurl) via atools/tools.gopattern or alternatives like Mage/Just; document the recommended approach before enforcing it in CI
Optional
- [ ] Startup and shutdown banner — the server currently emits plain
log.Printlnlines on start and stop. Replace with a short, single-line banner that surfaces key runtime facts (listen address, database path, version). Avoid ANSI color codes or multi-line ASCII art — they break line-oriented log collectors (Loki, Fluentd, CloudWatch). If a version string is included, embed it at build time via-ldflags "-X main.version=…"so the binary is self-describing without requiring a separate file - [ ] Lightweight feature flags
2.0.0
Features
- [ ] Add an
editorrole — can manage any post/page regardless of author. Requires: new role in DB CHECK constraint +ValidRole, updated router guards, migration, and test coverage - [ ] Multiple authors per post/page — replace single
author_idwith apost_authors/page_authorsjoin table. Requires: migration, updated models,syncAuthorshelper, handler + OpenAPI changes, and tests - [ ] MariaDB as an alternative database backend (recommended for Kubernetes). Introduce
DATABASE_DRIVERenv var (sqlite3default,mariadbopt-in); abstract driver-specific setup indatabase.New(); use dialect-specific migration directories orgolang-migrate - [ ] Images for tags — add optional
image_url TEXTcolumn totags(migration), expose inTag/TagInputmodels, update OpenAPI + validation + tests - [ ] CLI flags for configuration — add
flagorcobralayer so operators can pass--config,--listen-addr,--database-path; flags take precedence over env vars - [ ] S3-compatible media storage backend — add
MEDIA_BACKENDenv var (localdefault,s3opt-in) withS3_ENDPOINT,S3_BUCKET,S3_REGION,S3_ACCESS_KEY_ID,S3_SECRET_ACCESS_KEY; replace local disk writes inhandlers/media.gowith an S3 client. Recommended backend for Kubernetes deployments (e.g. Garage) - [ ] Kubernetes manifest or Helm chart — recommended stack: MariaDB + S3 media (e.g. Garage). Resources:
Deployment,Service,ConfigMap,Secret,Ingress. Depends on MariaDB backend + S3 media items above and rootless + FHS path items from 1.0.0 Deployment - [ ] Scheduled publishing — allow posts/pages to define a future publish timestamp so content goes live automatically; implement via
publish_atplus an explicitsnackbox publish-dueadmin command suitable for cron or Kubernetes CronJobs before considering a dedicated worker model - [ ] Social-post automation — when content is published, auto-generate and send shareable snippets to X/Twitter, LinkedIn, Facebook, Instagram, and especially Mastodon (highest priority). Build this on top of publish events/webhooks and provider adapters rather than coupling network calls directly into the core request path; requires provider credentials, per-network formatting, opt-in settings, and retry-safe delivery
- [ ] Explicit admin subcommands — add dedicated CLI entry points such as
snackbox migrate,snackbox create-admin,snackbox seed-fixtures,snackbox publish-due, andsnackbox backupso one-off operational tasks are not coupled to web-server startup - [ ] Backup command — add
snackbox backupto create operator-friendly backups of the database and media directory, with a format that works for both local storage and future MariaDB/S3-backed deployments - [ ] Outbound webhooks/event hooks — emit structured publish/update/delete events to operator-configured endpoints so external automation can react without polling; define this as the primary integration boundary for downstream automations; include signing/verification and retry-safe delivery
- [ ] Redis-backed shared state — add Redis as an attachable backing service for cross-instance rate limiting, caching, lightweight analytics buffering, or future coordination so replicas do not depend on in-memory process-local state
- [ ] Lightweight content analytics — let users see which posts/pages are most popular and basic trends without turning Snackbox into a full analytics platform. Prefer aggregated counters/top-lists and optional batched writes or Redis-assisted buffering over raw per-request event storage in the primary database