# Decisões de Arquitetura — Ambiguidades Identificadas na Especificação

> Conforme pedido na secção 58 da especificação, este documento identifica pontos
> contraditórios ou ambíguos **antes** de qualquer implementação, com a decisão
> tomada e a razão. Qualquer decisão aqui pode ser revista com o cliente (amimak)
> antes do MVP ser fechado.

---

## D1. Mecanismo de Multi-Tenancy

**Ambiguidade:** a spec diz "cada organização deverá possuir um tenant lógico
isolado" e "`organization_id` ou mecanismo equivalente", sem escolher entre
single-database (row-level) ou database-per-tenant.

**Decisão:** **Single database, row-level isolation** com `organization_id` em
todas as tabelas relevantes, aplicado via **Global Scope** automático + Policies.

**Razão:**
- Custo operacional muito menor (1 DB para gerir, migrar, fazer backup).
- Mais simples de manter para uma equipa pequena/média.
- Prestadores de serviço (`service_providers`) trabalham para várias
  organizações (secção 19) — isto só é natural num modelo single-DB partilhado
  entre tenants relacionados. Database-per-tenant tornaria essa partilha
  artificialmente complicada.
- Se no futuro um cliente enterprise exigir isolamento físico total, o padrão
  Laravel (`organization_id` + scopes) permite migrar esse tenant específico
  para uma DB dedicada sem reescrever a aplicação.

**Trade-off aceite:** exige disciplina rigorosa (testes automáticos
anti-IDOR/cross-tenant — ver `06-ESTRATEGIA-TESTES.md`) porque um erro humano
num `where()` esquecido expõe dados de outro tenant. Mitigado com Global Scopes
+ testes obrigatórios em CI.

---

## D2. Prestadores de Serviço são entidades globais, não pertencem a uma organização

**Contradição aparente:** a secção 19 diz "um prestador poderá trabalhar para
várias organizações", mas o princípio de tenancy diz que tudo tem
`organization_id`.

**Decisão:** `service_providers` é uma entidade **sem** `organization_id`
próprio. A relação organização↔prestador vive numa tabela pivot
`organization_service_providers` (com `status`, `categorias contratadas`,
`rating interno`, `data de início/fim`). Os dados operacionais (work orders,
orçamentos, faturas) desse prestador **são** sempre scoped por
`organization_id`, porque pertencem à ordem de serviço/pedido, não ao
prestador em si.

Um técnico de um prestador só vê os work orders atribuídos a ele — nunca vê
dados de outra organização mesmo que o prestador dele trabalhe para as duas.

---

## D3. Propriedade do registo "Property" vs. múltiplas relações

**Ambiguidade:** a secção 3/4 deixa claro que a propriedade *física* de um
imóvel é diferente da relação operacional, mas não diz explicitamente **quem
"possui" o registo do imóvel na plataforma** quando duas organizações-cliente
distintas (ex: ABC Bank e a empresa de facilities que gere o imóvel) usam o
mesmo sistema.

**Decisão MVP:** cada `property` pertence a **uma única `organization_id`**
(a organização que criou/regista o imóvel na plataforma — normalmente a
gestora ou a proprietária). As relações (`property_relationships`) descrevem
os *papéis* dessa mesma organização (ou de outras, referenciadas por nome/NUIT
enquanto não forem também tenants) em relação ao imóvel: `OWNER`, `TENANT`,
`MANAGER`, etc.

**Fora do MVP (assinalado, não implementado agora):** partilha do *mesmo*
registo de `property` entre duas organizações-tenant distintas (ex: o
proprietário e o gestor são ambos clientes independentes da plataforma e
ambos devem ver o mesmo imóvel com permissões diferentes). Isto exigiria uma
tabela `property_organization_access` adicional. A arquitetura de dados já
está preparada para isto (property_relationships aceita `related_organization_id`
nullable), mas a UI/fluxo de aprovação cross-organização fica para Fase 2.

---

## D4. Roles fixos vs. permissões granulares

**Decisão:** usar **[spatie/laravel-permission](https://spatie.be/docs/laravel-permission)**
com suporte a **"teams"** (o pacote suporta nativamente scoping por
`organization_id` via a feature `teams`). Os 10 roles da secção 8 são
criados como *roles* pré-definidos (seed), cada um com um conjunto de
permissões da secção 9. Roles não são hardcoded no código — são geridos em
BD, para que o Organization Admin possa, no futuro, criar roles
personalizados. Autorização final é sempre verificada com **Policies**
(nunca só `hasRole()` em controllers).

---

## D5. Cardinalidade Maintenance Request → Work Order

**Ambiguidade:** a spec não diz explicitamente se é 1:1 ou 1:N.

**Decisão:** **1:N**. Um pedido de manutenção pode gerar mais do que uma
Work Order (ex: 1ª visita só diagnostica, 2ª visita repara; ou uma
reincidência do mesmo pedido). `work_orders.maintenance_request_id` é FK
nullable (uma Work Order pode também ser criada diretamente, sem pedido
prévio — ex. manutenção preventiva agendada).

---

## D6. Faturas com múltiplas FKs opcionais

A spec permite que uma fatura esteja associada a organização, prestador,
imóvel, pedido, work order e orçamento em simultâneo (secção 22).

**Decisão:** todos esses FKs são nullable exceto `organization_id` e
`service_provider_id` (obrigatórios sempre). Validação aplicacional (Form
Request) garante que pelo menos `work_order_id` OU `quote_id` está presente,
para nunca existir uma fatura "órfã" sem rasto de origem.

---

## D7. Preventive Maintenance → geração automática de tarefas

**Decisão:** implementado como um `Job` agendado (`Scheduler` do Laravel,
diário) que lê `preventive_maintenance_plans` com `next_execution_date <= hoje`
e gera automaticamente uma `maintenance_request` (origem = `PREVENTIVE`) +
avança `next_execution_date` conforme a frequência. Não gera a Work Order
diretamente — passa pelo workflow normal (fica coerente com a secção 17).

---

## D8. Nomenclatura de ficheiros/media

Unificar `media`, `documents`, `attachments de work orders` e `attachments de
maintenance requests` numa única tabela polimórfica `media_files`
(`fileable_type`, `fileable_id`) em vez de 4 tabelas de anexos separadas como
sugerido implicitamente na secção 45. Reduz duplicação de lógica de
storage/segurança (secção 15/16/37) para um único ponto de verdade.

---

## D9. Pontos assinalados para confirmar com o cliente (amimak)

Estes ficam **assinalados**, não implementados, até haver confirmação:

1. Moeda: a spec usa MZN nos exemplos — confirmar se o sistema deve ser
   multi-moeda desde o MVP ou só MZN.
2. MFA obrigatório para Super Admin/Admin/Finance (secção 35) — obrigatório
   já no MVP ou fica preparado (colunas na BD) mas ativado depois?
3. Retenção de faturas/dados financeiros (secção 49) — quantos anos? Depende
   da legislação fiscal moçambicana, não é uma decisão técnica.
4. Limite de storage por organização (quota) — qual o valor por plano?
