# AGENT.md ## Overview This project is a mobile-first web application for an advertising agency to organize editorial calendars, important dates, deliveries, assets, and client-facing planning. The main goal is to replace the current messy Trello workflow with a centralized, secure, responsive application where: - agency staff can view and manage all clients they are allowed to access; - each client can access only their own area; - the calendar shows Brazilian national holidays, commemorative dates, and custom dates; - specific days can contain content such as post copy, images, notes, status, and attachments; - the dashboard includes a weekly overview so the team can quickly understand what is done and what is still pending. The application itself must be fully localized in Brazilian Portuguese (`pt-BR`). Project documentation and developer-facing instructions may be written in English unless explicitly requested otherwise. ## Audience - Internal users: advertising team, social media team, account managers, designers, managers, and administrators. - External users: agency clients, initially with read-only access. - Product tone: clear, professional, direct, and operational. - UI language: Brazilian Portuguese (`pt-BR`). ## Technical Stack ### Frontend - JavaScript. - React 19. - shadcn/ui. - Mobile-first and fully responsive. - UI text in `pt-BR`. - Accessible components, including keyboard navigation where applicable. ### Backend - Go 1.25. - Gin. - REST API. - Strong input validation. - Authentication and role-based authorization. - Clean, readable, modular structure. ### Infrastructure - Repository: Gitea. - Hosting: Portainer. - Configuration: environment variables only. - Delivery: Dockerfile, Docker Compose, and CI/CD pipelines. ## Product Identity - Project name: `Mira`. - Main brand color: orange. - The UI must support light and dark themes. - Theme switching must be available in the authenticated application shell. - The design should feel operational and polished, not like a marketing landing page. ## User Roles ### Super Admin The main administrative user for the agency. - Created from Portainer environment variables. - Can access all clients. - Can create, edit, and remove users. - Can create email invitations. - Can manage clients, calendars, custom dates, and content. - Can grant access to internal users and clients. Expected variables: - `SUPER_ADMIN_EMAIL` - `SUPER_ADMIN_PASSWORD` ### Agency User Internal operational user. - Can view assigned clients. - Can create and edit calendar content according to permissions. - Can view the weekly dashboard. - Can attach assets to calendar days. - Can update delivery/content statuses. ### Client Viewer External user linked to a specific client. - Can log in. - Can view only their own client area. - Cannot create, edit, or delete content in the first version. - Cannot access other clients. ## Authentication and Invitations - The application must have a login screen. - There must be no public registration screen. - The super admin can create users and send email invitations. - Invitations must use a unique token, expiration date, and single-use flow. - Passwords must be stored with a strong hash, never as plaintext. - Password reset, if implemented, must use temporary tokens. - Sessions must expire and be revocable. ## Permissions Model Use role-based access control with client scoping. Minimum roles: - `super_admin` - `agency_user` - `client_viewer` Minimum rules: - `super_admin` can access everything. - `agency_user` can access only assigned clients unless explicitly elevated. - `client_viewer` can access only their linked client. - Every sensitive route must validate authentication, role, and client scope. - Never rely on frontend-only access control. ## Core Modules ### Login - Simple, secure, responsive screen. - Fields: email and password. - Error messages in Portuguese. - Brute-force protection. - Do not reveal whether an email exists. ### Weekly Dashboard General view of the current week. It should show: - planned content and commitments for the week; - pending items; - completed items; - relevant holidays and commemorative dates; - filters by client, status, and owner; - clear highlight for today. ### Client Calendar The core product surface. It should support: - monthly view; - weekly view; - day detail view; - Brazilian national holidays; - Brazilian commemorative dates; - client-specific custom dates; - content/posts attached to a date; - attachments such as images, files, and text; - content status. ### Day Content Each day can contain one or more items. Suggested fields: - title; - description; - content type; - status; - owner; - client; - date; - optional time; - copy/text; - images and attachments; - internal notes; - client-visible notes; - change history. Suggested statuses: - `rascunho` - `planejado` - `em_producao` - `em_revisao` - `aprovado` - `publicado` - `cancelado` Keep status values compatible with Portuguese UI labels. ### Custom Dates Allow custom dates globally or per client. Examples: - company anniversary; - store anniversary; - institutional date; - recurring campaign; - commercial milestone; - internal event. Suggested fields: - name; - description; - date; - annual recurrence flag; - optional client; - visibility; - color or category. ### Clients Each client has their own area. Suggested fields: - name; - slug; - status; - contacts; - linked users; - calendar settings; - custom dates; - display preferences. ## Brazilian Calendar The application must support: - Brazilian national holidays; - Brazilian commemorative dates; - internal custom dates; - client-specific custom dates. Recommended implementation: - keep an internal table/cache for holidays and commemorative dates; - sync holidays by year from a configurable external provider; - allow manual fallback if the external API fails; - separate official holidays from non-official commemorative dates; - allow administrative review of imported dates. Provider decision: - Initial provider: BrasilAPI. - Regional holidays, municipal holidays, client-specific dates, and agency-specific commemorative dates will be added manually through the application. - The backend must still use a provider abstraction so another provider can be added later without rewriting calendar features. Providers considered: - BrasilAPI: Brazilian public API with national holiday endpoints. - Nager.Date: international public holiday API by country, with public endpoints that do not require an API key. - Feriados API or feriados.dev: Brazil-focused services with national, state, and city coverage. - Calendarific: international paid/freemium API with support for countries and regions. Initial recommendation: - implement a backend `CalendarProvider` abstraction; - configure the provider through `CALENDAR_PROVIDER`, defaulting to `brasilapi`; - persist provider results in the database; - allow manual registration of commemorative dates; - never depend on real-time external API availability to render the calendar. Expected variables: - `CALENDAR_PROVIDER` - `CALENDAR_API_BASE_URL` - `CALENDAR_API_KEY` - `CALENDAR_CACHE_TTL_HOURS` ## Security The project must strictly follow OWASP best practices. Minimum requirements: - validate and sanitize all inputs; - protect against XSS; - protect against CSRF where applicable; - protect against SQL injection using parameterized queries or safe ORM patterns; - enforce backend access control on all protected routes; - use strong password hashing; - use secure cookies if cookie-based sessions are used; - use restrictive CORS; - rate-limit login and sensitive routes; - set HTTP security headers; - avoid sensitive data in logs; - handle uploads securely; - limit file size; - validate MIME type and extension; - store attachments safely; - audit administrative actions; - use environment variables for secrets; - never commit credentials. OWASP references to consider during implementation: - OWASP Top 10. - OWASP ASVS. - OWASP Cheat Sheet Series. ## Suggested Repository Structure ```text . |-- AGENT.md |-- README.md |-- docker-compose.yml |-- .env.example |-- .gitea | `-- workflows | `-- ci.yml |-- frontend | |-- Dockerfile | |-- package.json | |-- src | | |-- app | | |-- components | | |-- features | | |-- lib | | |-- routes | | `-- styles | `-- public |-- backend | |-- Dockerfile | |-- go.mod | |-- cmd | | `-- api | | `-- main.go | |-- internal | | |-- auth | | |-- calendar | | |-- clients | | |-- config | | |-- content | | |-- database | | |-- mail | | |-- users | | `-- security | `-- migrations `-- docs |-- architecture.md |-- security.md `-- api.md ``` ## Database Database decision: PostgreSQL. PostgreSQL is the correct fit because the application is relational by nature: users, clients, permissions, invitations, calendar items, attachments, statuses, and audit logs all need strong consistency and queryable relationships. Initial entities: - users; - clients; - client_users; - invitations; - calendar_dates; - holidays; - commemorative_dates; - calendar_items; - calendar_item_attachments; - audit_logs; - sessions or refresh_tokens, depending on authentication strategy. Use consistent timestamps: - `created_at` - `updated_at` - `deleted_at` when soft delete is needed. Timezone rules: - handle dates and times carefully; - use `America/Sao_Paulo` as the default operational timezone; - store instants in UTC when time is involved; - store calendar-only dates as `date`, not timestamp. ## Uploads and Attachments Attachments are a critical security surface. Requirements: - limit file size; - restrict allowed file types; - validate actual file content; - rename files in storage; - avoid serving uploads directly from the same domain without protection; - prevent execution of uploaded files; - store metadata in the database; - support logical deletion. Expected variables: - `UPLOAD_MAX_SIZE_MB` - `UPLOAD_ALLOWED_MIME_TYPES` - `STORAGE_DRIVER` - `STORAGE_LOCAL_PATH` - `STORAGE_S3_ENDPOINT` - `STORAGE_S3_BUCKET` - `STORAGE_S3_ACCESS_KEY` - `STORAGE_S3_SECRET_KEY` ## Email Used for invitations and possibly password reset. Expected variables: - `SMTP_HOST` - `SMTP_PORT` - `SMTP_USER` - `SMTP_PASSWORD` - `SMTP_FROM_EMAIL` - `SMTP_FROM_NAME` - `APP_PUBLIC_URL` ## Minimum Environment Variables ```env APP_ENV=production APP_PUBLIC_URL=https://app.example.com.br APP_TIMEZONE=America/Sao_Paulo SUPER_ADMIN_EMAIL=admin@example.com.br SUPER_ADMIN_PASSWORD=change-me-secure-password DATABASE_URL=postgres://user:change-me-secure-password@postgres:5432/mira?sslmode=disable JWT_SECRET=change-me-with-a-long-random-secret JWT_ACCESS_TOKEN_TTL_MINUTES=15 JWT_REFRESH_TOKEN_TTL_DAYS=7 CORS_ALLOWED_ORIGINS=https://app.example.com.br CALENDAR_PROVIDER=brasilapi CALENDAR_API_BASE_URL=https://brasilapi.com.br CALENDAR_API_KEY= CALENDAR_CACHE_TTL_HOURS=24 SMTP_HOST=smtp.example.com.br SMTP_PORT=587 SMTP_USER= SMTP_PASSWORD= SMTP_FROM_EMAIL=no-reply@example.com.br SMTP_FROM_NAME=Mira UPLOAD_MAX_SIZE_MB=10 UPLOAD_ALLOWED_MIME_TYPES=image/jpeg,image/png,image/webp,application/pdf STORAGE_DRIVER=local STORAGE_LOCAL_PATH=/var/lib/mira/uploads ``` ## Backend API Standards: - versioned routes under `/api/v1`; - consistent JSON responses; - errors in `pt-BR`; - payload validation before business logic; - authentication middleware; - authorization middleware; - rate limit middleware; - security headers middleware; - structured logs. Suggested initial routes: ```text POST /api/v1/auth/login POST /api/v1/auth/logout POST /api/v1/auth/refresh GET /api/v1/me GET /api/v1/clients POST /api/v1/clients GET /api/v1/clients/:clientId PATCH /api/v1/clients/:clientId GET /api/v1/calendar/week GET /api/v1/clients/:clientId/calendar GET /api/v1/clients/:clientId/calendar/days/:date POST /api/v1/clients/:clientId/calendar-items GET /api/v1/calendar-items/:itemId PATCH /api/v1/calendar-items/:itemId DELETE /api/v1/calendar-items/:itemId POST /api/v1/calendar-items/:itemId/attachments DELETE /api/v1/attachments/:attachmentId GET /api/v1/calendar/holidays POST /api/v1/commemorative-dates PATCH /api/v1/commemorative-dates/:dateId DELETE /api/v1/commemorative-dates/:dateId GET /api/v1/users POST /api/v1/users/invitations POST /api/v1/invitations/:token/accept ``` ## Frontend Principles: - mobile-first; - dense, clear, operational screens; - no landing page; - first screen after login should be the weekly dashboard; - calendar must be easy to navigate on mobile; - use shadcn/ui consistently; - keep visible UI text in `pt-BR`; - do not rely on color alone to communicate status; - support loading, error, empty, and success states. Initial screens: - login; - weekly dashboard; - client list; - client calendar; - day detail; - calendar item detail/create/edit; - users and invitations; - custom date settings. ## Gitea CI/CD Minimum pipeline: - frontend lint; - frontend tests; - frontend build; - backend lint/vet; - backend tests; - backend build; - Docker image builds; - vulnerability checks where possible. Expected file: - `.gitea/workflows/ci.yml` ## Docker and Portainer Expected deliverables: - `frontend/Dockerfile` - `backend/Dockerfile` - `docker-compose.yml` - `.env.example` Docker Compose should include: - frontend; - backend; - PostgreSQL; - database volume; - local upload volume when `STORAGE_DRIVER=local`. All configuration must come from environment variables to support Portainer-based operation. ## Testing Backend: - business rule unit tests; - authorization tests; - calendar tests; - invitation tests; - validation tests; - upload tests. Frontend: - tests for critical components; - calendar rendering tests; - login flow tests; - role-based visibility tests. E2E, when possible: - super admin login; - client creation; - user invitation; - client read-only access; - calendar item creation; - weekly view. ## MVP Acceptance Criteria The MVP must allow: - login with the super admin loaded from environment variables; - client creation; - internal and client users created through invitations; - role-based access control; - clients to view only their own page; - agency users to view all permitted clients; - monthly calendar per client; - general weekly dashboard; - Brazilian national holiday display; - custom date registration; - content creation per day; - attachment of allowed images or files; - responsive mobile UI; - Docker Compose deployment through Portainer; - basic Gitea CI/CD pipeline. ## Out of Scope for the Initial MVP These can be planned after the MVP: - public registration; - client editing permissions; - formal approval workflows; - direct Instagram, Facebook, TikTok, or LinkedIn integration; - automated publishing; - real-time comments; - push notifications; - full kanban board; - complex subscription-based multi-tenancy. ## Implementation Principles - Prioritize clarity and security. - Keep frontend, backend, and infrastructure separated. - Avoid hard coupling to a single calendar provider. - Protect all backend routes. - Log important administrative actions. - Create reusable components only when there is a real need. - Prefer clear names over premature abstractions. - Document relevant technical decisions in `docs/architecture.md`. - Never commit secrets. ## Calendar References - [BrasilAPI](https://brasilapi.com.br/) - [Nager.Date](https://date.nager.at/) - [Feriados API](https://feriadosapi.com/docs) - [feriados.dev](https://feriados.dev/documentacao) - [Calendarific](https://calendarific.com/)