Skip to content

About

No description, website, or topics provided.

Resources

Stars

5 stars

Watchers

0 watching

Forks

Repository files navigation

BetterTicket

BetterTicket is a public ticketing web application. It supports anonymous ticket creation, viewing, and replies through a React frontend and Fastify API, plus a minimal provisioned-user login and technician-assignment backend. Tickets, replies, users, and server-side sessions are stored in PostgreSQL.

Repository map

Location Purpose
apps/web React/Vite ticket, reply, and creation frontend with component tests.
apps/api Fastify API, Drizzle schema/migrations, and API/database tests.
docker/ and compose.yml Pinned Docker toolchain and local PostgreSQL/S3-compatible services.
scripts/smoke.sh Disposable infrastructure smoke test.
.github/workflows/ Pull-request checks and scheduled CodeQL analysis.
.agents/skills/ Repository-specific Codex skills.
docs/ Product specs, implementation plans, and architecture decisions.
infrastructure_plan.md Approved infrastructure decisions and deferred product decisions.

Getting started

  1. Install Git, Docker Desktop (or Docker Engine with Compose), and a current evergreen browser. Node.js and pnpm run inside Docker; they are not host prerequisites.

  2. Clone the repository and create local-only service settings:

    cp .env.example .env

    The example values are safe local development credentials. Keep real service credentials in the untracked .env file or a provider secret manager.

  3. Build the pinned Node 24.21.0/pnpm 10.34.5 toolchain and install the lockfile:

    docker compose --profile tools build toolchain
    docker compose --profile tools run --rm toolchain pnpm install --frozen-lockfile
  4. Run local PostgreSQL and S3-compatible object storage. Ports bind only to localhost:

    docker compose up --detach postgres object-storage
  5. Apply the versioned PostgreSQL migrations, then start the frontend and API in the pinned toolchain. Vite serves the application at http://localhost:5173 and proxies /api to Fastify on port 3000:

    docker compose --profile tools run --rm toolchain pnpm db:migrate
    docker compose --profile tools run --rm --service-ports toolchain pnpm dev
  6. Run the quality checks in the toolchain container, then the host Docker smoke test. PostgreSQL must be running because the API suite includes a real persistence test:

    docker compose --profile tools run --rm toolchain pnpm format:check
    docker compose --profile tools run --rm toolchain pnpm lint
    docker compose --profile tools run --rm toolchain pnpm typecheck
    docker compose --profile tools run --rm toolchain pnpm test
    docker compose --profile tools run --rm toolchain pnpm coverage
    docker compose --profile tools run --rm toolchain pnpm build
    bash scripts/smoke.sh
  7. Stop the long-lived local services when finished:

    docker compose down

    To discard their local data as well, use docker compose down --volumes.

Ticket creation baseline

Anonymous visitors can submit a title, issue description, setup details, and optional additional information. POST /api/tickets validates the request, rejects unknown fields, and stores the ticket with a generated UUID, OPEN status, and timestamps. See the feature spec and ADR-001 for scope and rationale.

Ticket viewer baseline

The anonymous ticket list is at /tickets, each ticket opens at /tickets/:id, and the ticket form lives at /new. GET /api/tickets returns the 100 most recently created tickets as { "tickets": [...] }, and GET /api/tickets/:id returns one ticket or a 404. Everything a visitor submits is publicly visible. See the feature spec and ADR-002 for scope and rationale.

Ticket progress

Ticket detail pages show the current public status, a five-stage progress timeline, and the ticket's last-updated time. New tickets start OPEN and the approved forward-only lifecycle is OPEN → UNDER_REVIEW → IN_PROGRESS → RESOLVED → COMPLETED. Status changes require a future authenticated, authorized staff workflow; this baseline provides no status-update endpoint. See the feature spec and ADR-003.

Ticket replies baseline

Each ticket page shows its replies, oldest first, with a form for adding one without signing in. GET /api/tickets/:id/replies returns the ticket's 200 most recent replies as { "replies": [...] }, and POST /api/tickets/:id/replies stores a { "body": "..." } reply of up to 5,000 characters. Replies are anonymous and public: they carry no author or role, so a submitter's reply and a technician's look the same until replies are tied to accounts. See the feature spec and ADR-004 for scope and rationale.

Technician assignment MVP

After applying migrations, provision each account interactively from the pinned toolchain:

docker compose --profile tools run --rm toolchain pnpm user:create

The command requests a name, username, password, and either the USER or TECHNICIAN role. It hashes the password and never accepts credentials as command-line arguments. Do not commit provisioned credentials.

POST /api/sessions logs a user in and sets an HttpOnly session cookie; DELETE /api/sessions/current logs the user out. An authenticated technician can call PATCH /api/tickets/:ticketId/assignment with {"assignedTechnicianId":"<technician UUID>"} to assign or reassign a ticket, or with {"assignedTechnicianId":null} to unassign it. The selected user must also be a technician, and assignment never changes ticket status.

See the technician-assignment spec and ADR-003 for the complete MVP scope and security decisions.

Public registration and login

The homepage (/) lets a visitor sign in, create a regular-user account, or continue anonymously to /tickets. POST /api/users creates only USER accounts; it never accepts a role from the browser. Technician accounts must still be created with pnpm user:create. New accounts return to the login form rather than creating a session automatically. See the feature spec and ADR-004.

Tooling and CI

The pnpm workspace contains React/Vite and Fastify packages. Drizzle schema files are the database source of truth, and generated SQL migrations are committed under apps/api/drizzle.

Pull requests run locked installation, formatting, linting, type checking, migrations against PostgreSQL, unit/component/integration tests, coverage, application builds, Compose validation, the infrastructure smoke test, and Gitleaks. CodeQL runs weekly and on manual dispatch. Dependabot tracks npm, Docker, and GitHub Actions updates. Playwright, Trivy scanning, deployment, and release workflows remain deferred.

Docker image tags are deliberately pinned. Dependabot proposes updates; review and test them before merging.

GitHub setup still required

Before enabling a release workflow, select the static host, API container host, registry, PostgreSQL provider, object-storage provider, and release owner. Then configure protected staging and production environments and the named secrets/variables listed in infrastructure_plan.md—including API_CONTAINER_REGISTRY_TOKEN, API_DEPLOY_TOKEN, FRONTEND_DEPLOY_TOKEN, DATABASE_URL, object-storage settings, and AUTH_SECRET. No release workflow is present yet because these providers have not been selected.

Troubleshooting

  • If Docker cannot connect, start Docker Desktop and rerun docker compose config --quiet.
  • If ports 5432 or 8333 are occupied, stop the conflicting local service or change the loopback mapping in compose.yml.
  • If Docker reports a bind-mount permission issue, grant Docker Desktop access to this repository and rerun the command.
  • If tests report that a required database relation or column does not exist, run docker compose --profile tools run --rm toolchain pnpm db:migrate.
  • If ports 3000 or 5173 are occupied, stop the conflicting application before running the development command.
  • If a locked install fails after changing dependencies, regenerate pnpm-lock.yaml from the toolchain with docker compose --profile tools run --rm toolchain pnpm install, review the diff, then rerun with --frozen-lockfile.

About

No description, website, or topics provided.

Resources

Stars

5 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages