# Segurança e operação do 1MZ For Artists

## Ativação e atualização

A versão `1.5.641` carrega o núcleo em `includes/platform/bootstrap.php`. Na
ativação e no primeiro pedido administrativo/REST, as migrações versionadas
criam `rmbz_audit_log` e `rmbz_jobs`. Cada migração só atualiza a versão após
concluir e usa um lock para impedir duas execuções simultâneas.

Antes de publicar:

1. Crie um snapshot da base de dados e de `wp-content/uploads`.
2. Atualize o plugin e visite **1MZ Manager → Segurança & Privacidade**.
3. Execute **Verificar agora** e resolva itens críticos.
4. Confirme que WP-Cron, ou um cron real que chama `wp-cron.php`, está ativo.
5. Teste login, refresh, depósito, levantamento e acesso a comprovativos num
   ambiente de staging.

## MFA administrativo

O TOTP é compatível com aplicações autenticadoras comuns. O segredo é guardado
com AES-256-GCM e uma chave derivada das salts WordPress. Os dez códigos de
recuperação são mostrados uma única vez e armazenados apenas como hashes.

Ative primeiro o MFA na sua conta. Depois altere a política da equipa para
**Obrigatório**. Essa alteração revoga refresh tokens administrativos antigos,
bloqueia application passwords e impede AJAX, REST e XML-RPC privilegiados para
administradores ainda não inscritos. Esses utilizadores ainda conseguem entrar
no painel web exclusivamente para concluir o registo MFA.

## Auditoria

Os eventos são append-only na aplicação e ligados por HMAC ao hash anterior.
Alterar ou remover uma linha quebra a verificação exibida no painel. A auditoria
regista identificadores, estado e metadados reduzidos; palavras-passe, PINs,
tokens, códigos, documentos e comprovativos são sempre ocultados.

O CSV exporta até 1000 eventos e protege células contra fórmulas. A auditoria
não é apagada pela limpeza automática, porque pode ser necessária para
contratos, finanças e investigação de incidentes.

## S3/R2 e ficheiros privados

O fluxo **Comprovativos e KYC privados** fica **Somente local** por defeito. A
ativação é uma decisão explícita em **Configurações → S3 → Política por fluxo**.
O plugin recusa enfileirar estes ficheiros quando `ACL público` está ativo ou
existe uma `URL pública/CDN`. Num destino privado, o livro-razão confirma o
objeto por `HEAD` antes de qualquer limpeza local e a leitura usa URL assinada.

Nunca use o mesmo bucket público das capas para KYC/comprovativos. A credencial
deve ter acesso apenas ao prefixo 1MZ necessário e permissões `PutObject`,
`GetObject`, `HeadObject` e `DeleteObject`.

Em Nginx, aplique também o bloco mostrado em **Configurações → Ficheiros
protegidos**; `.htaccess` só é aplicado por Apache/LiteSpeed.

## Proxies e IP real

Os headers encaminhados só são considerados quando `REMOTE_ADDR` pertence a um
proxy confiável. Se usar Cloudflare, load balancer ou reverse proxy externo,
defina no `wp-config.php` apenas os CIDRs oficiais desse proxy:

```php
define( 'RMBZ_API_TRUSTED_PROXY_CIDRS', 'CIDR_1,CIDR_2' );
```

Não use `0.0.0.0/0` ou `::/0`; isso permite falsificar o IP e contornar rate
limits.

## Retenção e privacidade

O painel controla retenção de tokens revogados/expirados, buckets de rate
limit, jobs concluídos/falhados e comprovativos órfãos. Um comprovativo só é
apagado quando ultrapassa o prazo e já não aparece nas referências conhecidas.
Se a remoção no bucket falhar, o processo mantém o ficheiro e o ledger
(fail-closed).

O plugin integra os exportadores/erasers nativos do WordPress. Pedidos de
eliminação revogam sessões e dispositivos e desativam acesso, mas preservam
registos financeiros, contratos, catálogo e auditoria pelos prazos legais.

## API e fila

O contrato vivo está em:

`/wp-json/1mz/v1/openapi.json`

O worker `rmbz_job_queue_cron` corre a cada minuto. Push FCM é deduplicado,
executado fora do pedido web e repetido com backoff exponencial. Jobs em falha
definitiva aparecem no painel e geram evento de auditoria.

## Validação local

```bash
php tests/run.php
find . -type f -name '*.php' -not -path './.git/*' -print0 | xargs -0 -n1 php -l
cd android-app
./gradlew :app:compileDebugKotlin :admin:compileDebugKotlin :app:testDebugUnitTest :admin:testDebugUnitTest :app:lintDebug :admin:lintDebug
```

O workflow `.github/workflows/ci.yml` repete essas verificações em PHP 7.4,
PHP 8.2 e JDK 17.

## Hide WordPress e entrada administrativa privada

A função fica desativada por defeito para evitar bloqueio acidental. Ative em
**1MZ Manager → Segurança & Privacidade → Hide WordPress**. A gravação exige a
palavra-passe atual e, quando configurado, um código MFA. Antes de terminar a
sessão, abra os dois URLs privados numa janela anónima e confirme o login.

Quando ativa, a função:

- devolve 404 em `wp-login.php`, XML-RPC e páginas de `wp-admin` pedidas por
  visitantes, preservando `admin-ajax.php` e `admin-post.php`;
- apresenta uma página própria de login, recuperação e redefinição de senha;
- bloqueia por IP e IP+utilizador e deteta ataques distribuídos por utilizador;
- bloqueia enumeração pública de utilizadores e remove assinaturas dispensáveis;
- mantém REST 1MZ, cron, AJAX e o painel autenticado compatíveis.

O URL privado do painel é a entrada externa. Depois do login, o WordPress
continua a usar `wp-admin` internamente; tentar renomear fisicamente essa pasta
quebraria o core, atualizações e plugins.

Se houver lockout, adicione temporariamente ao `wp-config.php`:

```php
define( 'RMBZ_HIDE_WORDPRESS_BYPASS', true );
```

Entre pelo URL padrão, corrija a configuração e remova imediatamente a
constante. Em modo “Ligações permanentes simples” a ativação é recusada. O
bloqueio de ficheiros estáticos como `readme.html` deve ser feito também no
servidor ou CDN.

