Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
f6aff01
feat(DB): Setup makers + models + images schemas
risixdzn May 27, 2026
d72d887
refactor(DB): Compat column types to hold scraped data
risixdzn May 27, 2026
d64af4e
chore(DB): Fix hanging migrations + table names
risixdzn May 27, 2026
b0234e9
fix(DB): Revert migration states to correct order
risixdzn May 27, 2026
fb753f3
feat(Devices): Routes for reading categories, makers and models
risixdzn May 31, 2026
2a1a276
feat(Devices): Create, update and delete models for your company
risixdzn May 31, 2026
271f09a
fix(Models): Flatten select, source images from model_images, drop un…
risixdzn May 31, 2026
b0b23ba
refactor(Devices): Remove unknown casts on known types
risixdzn May 31, 2026
30b44c4
fix(Server): Copilot code quality review improvements
risixdzn Jun 12, 2026
bf9c8c3
merge: feat(Devices): Categories, models and makers for known devices
risixdzn Jun 12, 2026
b5ef0ea
fix(Auth): disable submit button while turnstile token is missing
risixdzn Jun 12, 2026
4a23bb0
feat(Cache): add @Cached and @InvalidateCache decorators for Redis ca…
risixdzn Jun 12, 2026
c887281
feat(Models): add @Cached and @InvalidateCache decorators
risixdzn Jun 12, 2026
1545820
feat(Auth): replace manual cache with @Cached and @InvalidateCache
risixdzn Jun 12, 2026
9929db6
feat(Account): replace manual cache with @Cached decorator
risixdzn Jun 12, 2026
fa26f88
feat(Companies): replace manual cache with @Cached and @InvalidateCache
risixdzn Jun 12, 2026
1e03850
feat(Credentials): replace manual cache with @InvalidateCache
risixdzn Jun 12, 2026
dcea96c
feat(Cache): add @Cached to Categories, Makers, Employees, ServiceOrd…
risixdzn Jun 12, 2026
da24aeb
chore(Cache): remove legacy cache.ts helper
risixdzn Jun 12, 2026
19f57ed
feat(Server): GET /health endpoint with MySQL, Redis and Workers probes
risixdzn Jun 13, 2026
946463b
refactor(UI): Sidebar, color and spacing improvements on the app inte…
risixdzn Jun 13, 2026
0cd0b83
feat(UI): Reduce font size a bit for better visual consistency
risixdzn Jun 13, 2026
b4c592b
feat(UI): Intercepted parallel-routes for rendering forms as dialogs
risixdzn Jun 14, 2026
90275d6
feat(UI): Downscale ServiceOrder page and some other tables
risixdzn Jun 15, 2026
235ed1c
fix(Web): JWT refresh redirect loop and f5 revalidation
risixdzn Jun 15, 2026
1eb320b
merge: feat(UI): Improvements on forms UX, app colors, font sizes and…
risixdzn Jun 17, 2026
28c378d
chore(Env): Update example files
risixdzn Jun 17, 2026
124fa33
feat(Repo): Run only API, frontend and workers on dev cmd
risixdzn Jun 17, 2026
3c977fb
chore(Merge):"fixrfam/refactor/cache
risixdzn Jul 12, 2026
f6556b4
feat(Server): Add avatar upload presign, update, and remove endpoints
risixdzn Jun 19, 2026
f303427
Feat(Web): Add avatar upload dialog, crop, and profile integration
risixdzn Jun 19, 2026
77d5dd4
feat(Server): Consolidate upload endpoints into purpose-based presign…
risixdzn Jul 16, 2026
12d3d7b
fix(Account): Resolve unresolved merge conflict in account repository
risixdzn Sep 18, 2026
d998760
feat(Web): Add Rybbit analytics tracking script to root layouts
risixdzn Sep 18, 2026
5fa6833
docs(Repo): Add AGENTS.md, CLAUDE.md and per-app guardrails for AI ag…
risixdzn Sep 19, 2026
b8ff5cc
docs(Repo): Add product context doc and impeccable skill hook config
risixdzn Sep 19, 2026
646a77e
chore(Repo): Merge fixrfam/docs/repo/agent-guardrails
risixdzn Sep 19, 2026
2ab9388
docs(Repo): Add MIT license, CONTRIBUTING.md and OSS repo standards
risixdzn Sep 19, 2026
5b04c3b
docs(Repo): Fix outdated setup instructions in README
risixdzn Sep 19, 2026
13230db
fix(License): Move to MD
risixdzn Sep 19, 2026
f221fbd
chore(Repo): Add MIT License to the project
risixdzn Sep 19, 2026
ad1bb92
fix(License): Burn
risixdzn Sep 19, 2026
a4d4c0b
chore(Repo): Add MIT License to the project
risixdzn Sep 19, 2026
d45263b
chore(Repo): Run formatter
risixdzn Sep 19, 2026
be2e7a8
feat(Repo): Make pre push hook run formatter
risixdzn Sep 19, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions .github/ISSUE_TEMPLATE/bug_report.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
---
name: Relatar um bug
about: Relate um problema com o Fixr
title: "[Bug] "
labels: bug
---

## Descrição

Uma descrição clara e concisa do bug.

## Passos para reproduzir

1. Vá até '...'
2. Clique em '...'
3. Veja o erro

## Comportamento esperado

O que você esperava que acontecesse.

## Comportamento atual

O que realmente aconteceu. Inclua mensagens de erro, stack traces ou screenshots, se relevante.

## Ambiente

- App afetado: (web / admin / server / workers)
- Navegador/SO (se relevante):
- Commit ou versão:

## Contexto adicional

Qualquer outra informação que possa ajudar a diagnosticar o problema.
22 changes: 22 additions & 0 deletions .github/ISSUE_TEMPLATE/feature_request.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
---
name: Sugerir uma feature
about: Sugira uma ideia ou melhoria para o Fixr
title: "[Feature] "
labels: enhancement
---

## Problema

Qual problema isso resolve? Para quem é?

## Solução proposta

Descreva a feature ou mudança que você gostaria de ver.

## Alternativas consideradas

Alguma solução alternativa ou workaround que você já considerou.

## Contexto adicional

Qualquer outra informação que possa ajudar (mockups, issues relacionadas, etc).
18 changes: 18 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
## O que mudou

<!-- Descreva o que este PR faz e por quê. -->

## Issue relacionada

<!-- Vincule a issue relacionada, ex.: Closes #123 -->

## Como testar

<!-- Passos para verificar a mudança localmente. -->

## Checklist

- [ ] `bun run check-types` passa
- [ ] `bun run lint` passa
- [ ] Testes adicionados/atualizados quando relevante
- [ ] Mensagens de commit seguem a convenção `action(Scope): message`
13 changes: 13 additions & 0 deletions .github/hooks/impeccable.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"version": 1,
"hooks": {
"postToolUse": [
{
"type": "command",
"matcher": "edit|create|apply_patch",
"bash": "[ ! -f \"$(git rev-parse --show-toplevel)/.github/skills/impeccable/scripts/impeccable\" ] || \"$(git rev-parse --show-toplevel)/.github/skills/impeccable/scripts/impeccable\" hook",
"timeoutSec": 5
}
]
}
}
11 changes: 0 additions & 11 deletions .husky/pre-commit

This file was deleted.

25 changes: 25 additions & 0 deletions .husky/pre-push
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#!/bin/sh
set -e

echo "Running lint..."
bun run lint

echo "Running type checks..."
bun run check-types:ci

echo "Formatting..."
bun run format

if ! git diff --quiet; then
echo ""
echo "Formatter made changes. Committing them now..."
git add -A
git commit -m "chore(Repo): Run formatter"
echo ""
echo "A new commit with formatting fixes was created locally."
echo "Push again to include it."
exit 1
fi

echo "All checks passed!"
exit 0
98 changes: 98 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
# Fixr — Agent Guardrails

Instructions for AI coding agents (Claude Code, Cursor, Copilot, etc.) working in this repository. This file is the open, tool-agnostic standard; `CLAUDE.md` imports it for Claude Code.

## Project overview

Fixr is a service-order management platform for electronics repair shops (see `README.md` for product context). It's a **Bun workspaces monorepo**:

```
apps/
├─ web/ Next.js — client/technician-facing app, JWT auth
├─ admin/ Next.js — internal admin panel, Clerk auth
├─ server/ Fastify REST API — business logic, DB access
└─ workers/ BullMQ job processors (email, etc.)

packages/
├─ db/ Drizzle ORM schema, migrations, MySQL connection
├─ schemas/ Zod schemas shared between frontend and backend
├─ constants/ Shared constants/enums (roles, cookies, masks, messages)
├─ env/ Centralized env var validation (Zod, per app)
├─ permissions/ RBAC ability definitions
├─ mail/ React Email templates + mail queue
├─ infra/ Deploy infrastructure
└─ typescript-config/ Shared tsconfig bases
```

Each app/package with its own local conventions may have its own `CLAUDE.md` — check for one before working there.

## Commands

Run from the repo root unless noted:

- `bun run dev` — start server, web, workers in dev mode
- `bun run dev:admin` — start admin app in dev mode
- `bun run build` / `build:packages` / `build:apps` / `build:<app>` — build
- `bun run check-types` — TypeScript check across all workspaces
- `bun run lint` / `lint:write` — Biome check / autofix
- `bun run format` — `ultracite fix` (formats + safe lint fixes)
- `bun run db:start` / `db:stop` — MySQL + Redis via Docker
- `bun run db:migrate` — apply migrations
- `bun run db:generate` — generate migration SQL from schema changes
- `bun run db:studio` — Drizzle Studio GUI
- Inside `apps/server` or `apps/workers`: `bun run test` (Vitest)

## Code conventions

- **Formatting/linting**: Biome via the `ultracite` preset (`biome.json`). Tabs, double quotes, imports auto-organized. Don't hand-format against these rules or fight the formatter — run `bun run lint:write` instead of manual style edits.
- **TypeScript**: strict mode. Run `bun run check-types` after non-trivial changes.
- **IDs**: use `createId()` from `@paralleldrive/cuid2` for primary keys (`.$defaultFn(() => createId())` in Drizzle schema). Not UUID, not auto-increment.
- **Workspace imports**: use the `@fixr/<package>` workspace protocol with subpath exports, e.g. `@fixr/db/connection`, `@fixr/db/schema`, `@fixr/schemas/account`, `@fixr/permissions`. Don't deep-import across a package's internal file paths.
- **Env vars**: always go through `@fixr/env/<app>` (Zod-validated via `@t3-oss/env-core`). Never read `process.env` directly in app code — add the var to the relevant `packages/env/src/<app>.ts` first.

### Server (`apps/server`) module structure

Each feature lives under `src/modules/<name>/` with a fixed layout:

```
modules/<name>/
├─ routes/index.ts Fastify route registration, wires preHandlers
├─ controllers/index.ts Thin orchestration: parse request, call service, shape response
├─ services/index.ts Business logic
├─ repositories/index.ts Drizzle queries (data access only)
├─ schemas/index.ts Module-local Zod schemas
└─ errors/index.ts Module's AppError registry (see below)
```

Follow this layering for new modules/endpoints — don't put query logic in controllers or business logic in repositories.

- **Errors**: every thrown error is a typed key from a registry built with `defineErrors({...})` (see `apps/server/src/modules/account/errors/index.ts` and `src/core/errors`). Throw with `throw new AppError("SOME_KEY")`; never throw raw `Error` or ad-hoc objects from route/controller/service code. Wrap route handlers with `withErrorHandler(...)`.
- **`tryCatch()`** (`src/core/lib/try-catch.ts`) wraps a promise into `{ data, error }` — prefer it over raw `try/catch` where it fits the existing style in that file.
- **Auth/RBAC**: JWT-based (`@fastify/jwt`), role lives at `user.company.role` in the JWT payload. `authenticate` middleware verifies the JWT and loads the user; `requirePermission(permissions.<resource>.<action>)` (from `@fixr/permissions`) gates routes. Add new permissions in `packages/permissions`, don't invent ad-hoc role checks in route handlers.
- **Caching**: repository methods use `@Cached({ ttl, key })` / `@InvalidateCache({ patterns })` decorators from `shared/infra/cache`. When a repository write invalidates cached reads, add the matching `@InvalidateCache` patterns.

### Frontend (`apps/web`, `apps/admin`)

- Next.js App Router. Route groups: `(public)` vs `(protected)` separate unauthenticated and authenticated routes.
- `apps/web` auth is JWT/cookie-based against `apps/server` (see `lib/auth/axios.ts`, `lib/auth/utils.ts`). `apps/admin` auth is **Clerk**, a separate system — don't mix the two apps' auth patterns.
- API calls from `apps/web` go through `lib/services/*.ts` using the shared `axios` instance and the `tryCatch()` helper (`lib/utils`), not raw `fetch`/`axios` calls scattered in components.
- `components/ui/**` and `components/magicui/**` are generated/vendored (shadcn-style) and excluded from Biome linting — treat them as vendored, avoid hand-editing unless intentionally customizing a primitive.

### Database (`packages/db`)

- Schema files live in `src/schema/*.ts` (Drizzle). To change the schema: edit the schema file, then run `bun run db:generate` to produce the migration — don't hand-write SQL in `drizzle/*.sql` or edit `drizzle/meta/*.json` snapshots.
- Shared validation schemas for DB-backed entities live in `packages/schemas`, consumed by both `apps/server` and frontend apps for consistent validation.

## Guardrails — do not do without explicit approval

- **Don't hand-edit generated migration files**: `packages/db/drizzle/*.sql` and `packages/db/drizzle/meta/*` are generated by `drizzle-kit`. Change the schema source and regenerate.
- **Don't commit env files** (`.env`, `.env.production`, etc.) or secrets. `.env.example` files are the place to document new required vars.
- **Don't touch deploy/infra** (`packages/infra`, `.github/workflows/deploy.yml`) or auth secrets (`JWT_SECRET`, `COOKIE_ENCRYPTION_SECRET`, Clerk keys) without the user explicitly asking.
- **Don't weaken RBAC** (removing/bypassing `requirePermission`, loosening `@fixr/permissions` ability rules) to make something "just work" — flag the permission gap instead.
- **Don't bypass Husky/lint-staged** (`--no-verify`) or leave `check-types`/`lint` failing.
- **Never push, and never commit unless explicitly asked.** When asked to commit, use `action(Scope): Message` (lowercase action, capitalized Scope, e.g. `feat(Account): Add avatar removal endpoint`) — enforced by `.husky/commit-msg`.
- Small changes can land directly on `develop`; larger features should get a branch named `action/scope/change` (e.g. `feat/service-orders/bulk-close`).

## Testing

Vitest is set up in `apps/server` and `apps/workers` (`bun run test` from inside the app). Coverage is currently minimal — check whether a module already has tests before assuming a suite exists, and don't remove the placeholder spec files as a way to "pass" checks.
1 change: 1 addition & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
@AGENTS.md
63 changes: 63 additions & 0 deletions CODE_OF_CONDUCT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# Código de Conduta do Contribuidor

## Nosso compromisso

Nós, como membros, contribuidores e líderes, nos comprometemos a fazer da
participação em nossa comunidade uma experiência livre de assédio para todos,
independentemente de idade, tamanho corporal, deficiência visível ou invisível,
etnia, características sexuais, identidade e expressão de gênero, nível de
experiência, educação, condição socioeconômica, nacionalidade, aparência
pessoal, raça, religião ou identidade e orientação sexual.

Nos comprometemos a agir e interagir de maneiras que contribuam para uma
comunidade aberta, acolhedora, diversa, inclusiva e saudável.

## Nossos padrões

Exemplos de comportamento que contribuem para um ambiente positivo:

- Demonstrar empatia e gentileza com outras pessoas
- Respeitar opiniões, pontos de vista e experiências diferentes
- Dar e aceitar com elegância feedback construtivo
- Assumir responsabilidade e pedir desculpas a quem for afetado por nossos
erros, aprendendo com a experiência
- Focar no que é melhor não apenas para nós individualmente, mas para a
comunidade como um todo

Exemplos de comportamento inaceitável:

- Uso de linguagem ou imagens sexualizadas, e atenção ou investidas sexuais de
qualquer tipo
- Trollagem, comentários insultuosos ou depreciativos, e ataques pessoais ou
políticos
- Assédio público ou privado
- Publicar informações privadas de terceiros, como endereço físico ou de
e-mail, sem permissão explícita
- Outras condutas que possam razoavelmente ser consideradas inadequadas em um
ambiente profissional

## Responsabilidades de aplicação

Os mantenedores do projeto são responsáveis por esclarecer e aplicar nossos
padrões de comportamento aceitável, tomando ações corretivas apropriadas e
justas em resposta a qualquer comportamento que considerem inadequado,
ameaçador, ofensivo ou prejudicial.

## Escopo

Este Código de Conduta se aplica a todos os espaços da comunidade (issues,
pull requests, discussões), e também quando alguém está representando
oficialmente a comunidade em espaços públicos.

## Aplicação

Casos de comportamento abusivo, de assédio ou de outra forma inaceitável podem
ser reportados aos mantenedores do projeto através de uma denúncia
confidencial pelo GitHub. Todas as reclamações serão revisadas e investigadas
de forma pronta e justa.

## Atribuição

Este Código de Conduta é adaptado do [Contributor Covenant](https://www.contributor-covenant.org),
versão 2.1, disponível em
https://www.contributor-covenant.org/version/2/1/code_of_conduct.html.
Loading
Loading