first commit
This commit is contained in:
653
AGENT.md
Normal file
653
AGENT.md
Normal file
@@ -0,0 +1,653 @@
|
||||
# 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/)
|
||||
Reference in New Issue
Block a user