Skip to content

Release checklist#

A manual run-through to validate a fresh Ticket Board deployment.

  • Audience. The operator (John) or any engineer cutting a release.
  • Estimated time. About ten minutes.
  • When to run it. After any deploy that touches main.

Each step should produce the listed outcome. If it does not, stop and triage before proceeding.

0. Prerequisites#

  • Docker + Docker Compose installed on the target host.
  • .env file populated from .env.example with non-default SECRET_KEY and POSTGRES_PASSWORD.
  • In .env, ENV=prod AND COOKIE_SECURE=true for any real deploy. Dev hosts may use ENV=dev.

1. Bring up the stack#

docker compose up -d
  • docker compose ps shows postgres, backend, frontend, and proxy as healthy/running, plus migrate as Exited (0) (one-shot — expected).
  • docker compose logs --tail=20 backend shows ticket_board.startup with the redacted settings.
  • No service shows restarting after 60 seconds.

2. Health checks#

curl -s http://localhost/healthz | jq
curl -s http://localhost/readyz  | jq
  • /healthz returns {"status":"ok"} (200).
  • /readyz returns {"status":"ready","db":"ok","settings_loaded":true} (200).

3. Seed the dev workspace (skip in production)#

make seed-dev
  • Console shows the [seed_dev] prefix on every line, including [seed_dev] human user 'admin' (<uuid>), [seed_dev] project PROJ <uuid>, [seed_dev] project INFRA <uuid>, [seed_dev] created ~31 tickets, [seed_dev] created 5 wiki pages (1 broken link: monitoring-setup), [seed_dev] created 4 sticky notes, and ends with [seed_dev] Done.
  • Running again exits with [seed_dev] Workspace 'Default Workspace' already seeded — nothing to do.

4. Human login flow#

Open http://localhost/ in a browser.

  • Redirected to /login.
  • Log in as admin / changeme-please.
  • Redirected to dashboard. Topbar shows "Admin".
  • Rotate the password immediately via Settings → Security (/settings/security) in the app (or, for recovery, via the CLI: make reset-password USER=admin).

The seed credentials are dev-only

Never run a public deploy with make seed-dev data and the default password. Rotate before exposing the host to anything outside your homelab.

5. Project + ticket creation#

  • Navigate to /projects/PROJ. The Board, Backlog, and Wiki tabs render.
  • Click into Backlog. About 15 tickets visible.
  • Open any ticket (e.g. /tickets/PROJ-1). Header + description + comments render.
  • Click the title to edit; save; the title updates.
  • Open Board. Drag a card to a different column; the network panel shows POST /api/v1/tickets/{id}/transition returning 200.

6. Bot create + REST authentication#

# Get the seeded bot token:
BOT_TOKEN="tkb_devresearchtoken0000000000000001"

# Hit the API:
curl -s -H "X-API-Key: $BOT_TOKEN" http://localhost/api/v1/tickets | jq '.data | length'
  • Returns a number > 0.
  • No errors in docker compose logs backend.

7. MCP tool call#

curl -s -X POST \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}' \
  http://localhost/mcp/bot/$BOT_TOKEN/mcp
  • Returns a JSON-RPC response with tools containing entries like list_projects, get_self, search, etc.
  • The Caddy access log (docker compose logs proxy) shows /mcp/bot/<redacted>/mcpnever the literal token.

8. Wiki#

  • Navigate to /wiki. The seeded wiki pages render.
  • Open one (e.g. /wiki/infra-overview). Markdown renders. Backlinks panel shows linked pages.
  • Click on the deliberately-broken [[monitoring-setup]] link → it surfaces as a broken-link affordance ("Create this page?").

9. Sticky notes#

  • On the dashboard, personal sticky notes render.
  • On a project home, project sticky notes render.
  • Click a sticky note → expanded dialog with edit / delete / convert-to-ticket actions.

10. Webhook delivery (end-to-end)#

  • In another terminal, start a stub receiver:

    python3 -m http.server 9999  # or use requestbin.com / webhook.site
    
  • From /settings/webhooks, create a webhook pointing at http://host.docker.internal:9999/hook (or your public bin URL). Copy the secret.

  • Trigger an event: in the UI, update any ticket's description.
  • Check the receiver's log: a POST arrived with X-Webhook-Signature: sha256=<hex> + X-Webhook-Timestamp headers.
  • In the UI, /settings/webhooks/{id}/deliveries shows the attempt with status=succeeded.

11. Audit + tool-invocation logs#

  • Visit /audit. Recent activity from steps 4–10 visible (login, ticket transitions, comment creates, etc.).
  • Visit /audit/tools. The MCP tools/list call from step 7 visible as a bot.tool_invoked row.
  • Click the "Audit" link on the tool-log row → navigates to /audit?request_id=... showing the same request's audit events.
  • Type a known ticket title into the topbar search → results page shows the ticket.
  • Type a known wiki keyword → results page shows the wiki page.
  • Type a term in a deleted ticket → no result (soft-delete filter active).

13. Backup#

make backup
ls -la backups/
  • A .sql file timestamped to now is in backups/.
  • head -5 backups/<file>.sql shows the pg_dump header.

For the full backup and restore procedure, see Backup and restore.

14. Tear down#

docker compose down
  • All containers stop.
  • docker volume ls | grep ticket-board shows pgdata + pgbackup (data persists).
  • docker compose up -d again brings the stack back with all the data intact.

Success#

When every box is checked, the release is smoke-green. Production readiness additionally requires the steps in the deployment checklist (TLS, COOKIE_SECURE=true, DOCS_ENABLED=false, seed credentials rotated). File any failures against this checklist before signing off.