# AGENTS.md

Este arquivo contém regras obrigatórias para qualquer IA ou agente que altere
o `hub-mkp-core`.

## Limite de domínio

O Core conhece somente:

- usuários globais e autenticação central;
- grupos de empresas/tenants;
- instâncias/servidores do Hub;
- databases associados aos grupos;
- controle administrativo de acesso e bloqueio;
- provisionamento central e seus logs;
- broker OAuth/callback centralizado de marketplaces somente quando o
  provedor externo exigir ou favorecer Redirect URL Domain única.

É proibido implementar neste repositório qualquer tabela, campo, endpoint,
service, fila ou regra operacional relacionada a marketplace, TikTok, Mercado
Livre, Shopee, Amazon, anúncios, produtos, pedidos, categorias, preço,
sincronização ou estoque. Essas responsabilidades pertencem ao `hub-mkp`.

Exceção de coordenação: o Core pode manter `worker_task_locks` e endpoints
autenticados de acquire/heartbeat/release para impedir concorrência global
entre workers. `task_type` e `marketplace_code` são identificadores opacos de
lock; essa exceção não permite guardar fila, credencial, produto, preço,
estoque ou regra operacional de marketplace.

Exceção arquitetural restrita: o Core pode conter somente endpoints de
OAuth/callback centralizados para marketplaces, como os brokers OAuth da
Shopee e do TikTok Shop,
quando precisar receber o redirect em uma URL única e encaminhar o resultado
para a instância correta do Hub. Essa exceção não permite implementar regras
de negócio de marketplace, persistência operacional definitiva de tokens,
dependência direta da tabela `C003`, sincronização ou qualquer domínio de
produto, pedido, preço, estoque ou categoria.

O site comercial pertence ao `totalseller-hub-site`.

## Regras técnicas

1. Leia o `README.md` antes de alterar autenticação, usuários, provisionamento
   ou banco de dados.
2. Use PDO e prepared statements para todo valor dinâmico. Não monte SQL com
   entrada concatenada.
3. Valide e normalize entradas na borda da aplicação.
4. Nunca versione `.env`, credenciais, tokens, chaves ou senhas em texto puro.
5. Retorne erros públicos seguros. Detalhes sensíveis ficam somente nos logs.
6. Mantenha compatibilidade com PHP 7.4 ou superior.
7. Preserve o padrão PSR-4 definido no `composer.json`.
8. Não use JWT sem uma decisão arquitetural futura e explícita.
9. Nunca persista ou registre token puro; armazene somente hash do token.
10. Nunca salve senha de usuário fora do Core.
11. Não crie autenticação independente no `hub-mkp` sem consultar e validar o
    contrato do Core.
12. Cadastro público deve sempre validar configuração, entradas, captcha
    habilitado e limites antiabuso antes de criar usuário ou grupo.
12.1. Cadastro público deve validar CNPJ no backend, incluindo 14 dígitos,
      rejeição de sequências repetidas e conferência dos dígitos verificadores.
13. Nunca crie database diretamente em endpoint público.
14. Criação de database deve ocorrer somente por jobs e pelo worker de
    provisionamento; nunca diretamente em endpoint público.
15. A simulação é o modo padrão. O modo real exige simultaneamente a flag
    local `PROVISIONING_REAL_ENABLED=true` e a opção explícita `--real`.
16. Workers devem assumir tarefas com bloqueio transacional e nunca processar
    diretamente uma solicitação HTTP pública.
17. Cada worker processa somente a `hub_instance_id` indicada por `--instancia`
    ou `CORE_INSTANCE_CODE`; apenas a instância padrão ativa pode assumir um
    tenant ainda não atribuído.
18. Credenciais administrativas do MySQL de provisionamento pertencem somente
    ao `.env` local da instância. Nunca as grave em `hub_instances`,
    `tenant_databases`, `jobs` ou `audit_logs`.
19. No modelo distribuído, o Core prepara e registra `tenant_databases`, mas
    não cria database ou usuário MySQL fisicamente. O worker da instância cria
    os recursos físicos e o Core enfileira `RODAR_MIGRATIONS_CLIENTE` após o
    sucesso reportado.
20. Nunca registre senha de database, nem mesmo criptografada, em logs,
    payload de fila ou CLI. A única API que pode retornar senha descriptografada
    é `GET /api/worker/jobs/{id}/execution-context`, exclusivamente para o
    worker autenticado que já claimou o job da própria `hub_instance_id`.
21. Recursos MySQL parcialmente criados exigem intervenção manual. Não faça
    rollback destrutivo automático de database ou usuário.
22. Migrations do tenant devem ser executadas somente pelo runner oficial
    `bin/tenant_migrate.php` do clone local do `hub-mkp`; o Core não replica
    nem interpreta as migrations.
23. Passe `TENANT_DB_PASSWORD` ao runner somente por variável de ambiente.
    Nunca inclua senha em argumento, comando, stdout, stderr ou contexto.
24. Use `proc_open()` sem shell, ambiente mínimo, timeout e sanitização da
    saída ao chamar o runner.
25. O worker de migrations não pode executar seeds, liberar acesso do grupo
    ou implementar qualquer regra de marketplace.
26. A finalização do tenant deve usar somente o runner oficial
    `bin/tenant_finalize.php` do clone local do `hub-mkp`.
27. Passe `TENANT_DB_PASSWORD` ao runner de finalização somente por variável
    de ambiente; nunca por argumento, comando, stdout, stderr, payload ou log.
28. A senha do usuário existe somente no Core. O espelho local do tenant é
    identificado por `user_uuid` e nunca recebe senha do Core.
28.1. Usuários criados ou reativados pelo Hub devem passar pelos endpoints
      internos autenticados do Core; o Core cria/reutiliza o usuário global,
      mantém o vínculo em `tenant_users` e retorna o `user_uuid` para o espelho
      local. Ativação/desativação vinda do Hub altera somente o vínculo do
      tenant, não remove nem desativa globalmente o usuário.
29. Somente a conclusão bem-sucedida de `FINALIZAR_TENANT` pode mover o grupo
    para `PROVISIONADO` e liberar seu acesso.
30. Suporte é controlado exclusivamente pelo Core; não crie flag de suporte no
    database do tenant.
31. Não crie níveis ou perfis complexos de suporte sem decisão arquitetural
    explícita.
32. A senha do usuário continua existindo somente no Core, inclusive para
    usuários de suporte.
32.1. Recuperação de senha deve permanecer no Core, com token puro enviado
      somente pelo transporte de e-mail e persistência apenas do hash.
32.2. Limites antiabuso de login devem retornar mensagens públicas genéricas
      e nunca revelar se um e-mail existe.
32.3. Login pode retornar `EMAIL_NOT_CONFIRMED` somente quando a senha estiver
      correta e houver confirmação de e-mail pendente. Senha errada deve
      continuar usando erro genérico.
32.4. Reenvio público de confirmação deve respeitar cooldown e antiabuso,
      invalidar tokens pendentes antigos, persistir somente hash do novo token
      e não revelar existência de conta fora do fluxo autenticado por senha.
33. No `hub-mkp-core`, novas tabelas e colunas devem usar nomes convencionais
    em inglês sem prefixo. Não criar novas tabelas com prefixos antigos como
    `C001`, `Q001` ou `L001`.
34. Não implemente marketplace operacional no Core e não execute `git commit`
    ou `git push`.
34.1. A única exceção de marketplace permitida no Core é broker
      OAuth/callback centralizado, limitado a validar a origem Hub -> Core,
      criar estado temporário, receber callback do provedor, trocar `code` por
      tokens quando necessário e entregar o resultado para a instância correta
      do Hub por chamada servidor a servidor assinada.
34.2. O broker OAuth não pode criar regra de produto, pedido, estoque, preço,
      categoria, anúncio, sincronização, conciliação ou qualquer operação de
      marketplace.
34.3. O Core não deve depender diretamente da tabela legada `C003`. Dados como
      `c003_id` podem trafegar apenas como identificador opaco da integração
      dona no Hub.
34.4. A persistência final de `access_token`, `refresh_token`, `shop_id` e
      demais dados operacionais da integração pertence ao projeto dono da
      integração e da `C003`.
34.5. Tokens de marketplace nunca devem ser enviados ao navegador, query
      string, logs, auditoria, payload de fila ou resposta pública.
34.6. Chamadas Hub -> Core para iniciar OAuth devem validar instância,
      allowlist de domínio/retorno, `environment` e assinatura HMAC ou token
      interno servidor a servidor.
34.7. Chamadas Core -> Hub para concluir OAuth devem ser servidor a servidor,
      assinadas pelo Core e direcionadas somente ao callback interno permitido
      para a `hub_instance_code`.
34.8. `return_url`, `c003_id`, `integration_id`, `tenant_uuid`,
      `hub_instance_code` e `environment` recebidos por URL nunca devem ser
      confiados sem validação.
34.9. `environment=sandbox|production` escolhe a configuração OAuth do
      marketplace usada e não deve ser amarrado automaticamente ao domínio do
      servidor.
34.10. `partner_key`, tokens, `code` completo, payload sensível do provedor e
       stack trace nunca devem aparecer em tela, redirect, resposta pública ou
       logs.
34.11. O estado OAuth deve ter expiração curta, não depender de sessão do
       usuário no callback e, quando houver store persistente, salvar somente
       hash do state e ser consumido uma única vez.
34.12. Não faça chamadas reais a marketplaces sem autorização humana explícita,
       exceto ambiente de teste claramente configurado para o broker OAuth.
35. Não renomeie tabelas legadas sem pedido arquitetural explícito.
36. Autenticação de worker deve permanecer separada da autenticação de
    usuário; tokens de um domínio nunca autenticam o outro.
37. Nunca registre token de worker puro nem retorne segredos em endpoints de
    worker.
38. Worker não tem subdomínio próprio; ele consome a API central do Core por
    token.
39. Um worker só pode listar ou operar jobs vinculados à sua própria
    `hub_instance_id`.
40. Endpoints de worker controlam estado da fila e não executam trabalho
    pesado dentro da requisição HTTP.
41. Worker precisa claimar o job antes de pedir contexto de execução.
42. Não retorne segredo em listagem de jobs; contexto com segredo deve ser
    restrito ao job claimado pelo worker autenticado.
43. Nesta etapa, o Core não executa `CRIAR_DATABASE_CLIENTE`,
    `RODAR_MIGRATIONS_CLIENTE` nem `FINALIZAR_TENANT`; ele só fornece
    contexto, atualiza status e audita o resultado reportado pelo worker.
43.1. `GET /api/auth/tenants` pode retornar ambientes em preparação, mas deve
      expor somente status amigável para UI. Nunca retornar senha, token,
      credencial de banco, payload interno de job, stack trace, SQL ou detalhe
      técnico sensível.
43.2. Quando o tenant for marcado como `PROVISIONADO`, o Core pode enviar o
      aviso de ambiente pronto ao administrador inicial. Esse e-mail deve ser
      tentado uma única vez por tenant, controlado por
      `provisioning_completed_email_attempted_at` e
      `provisioning_completed_email_sent_at`; falha no envio não pode reverter
      provisionamento, reabrir job ou bloquear acesso. Nunca enviar token,
      senha, credenciais de banco ou segredo nesse e-mail.
44. Todo `.env.example` deve ter comentários em português explicando cada
    variável.
45. Toda nova variável de ambiente deve ser documentada em português e nunca
    deve expor senha, token ou segredo real em `.env.example`.
46. Comandos destrutivos de reset devem rodar em dry-run por padrão, exigir
    flag explícita de execução e confirmação textual.
47. Reset de tenant de teste nunca deve ser habilitado em produção.
48. Comandos destrutivos nunca devem apagar database físico ou usuário MySQL
    sem validar o padrão seguro esperado antes da operação.
49. Toda tarefa operacional recorrente futura deve combinar `flock` local com
    lock global no Core por instância, tarefa, marketplace opcional e slot.
50. Acquire de lock global deve ser atômico, usar chave determinística única e
    permitir takeover somente depois de `lock_expires_at`.
51. Heartbeat e release aceitam somente o `locked_by` pertencente ao worker
    autenticado e nunca podem alterar lock de outra instância ou proprietário.
52. Release deve limpar proprietário, PID, hostname e datas ativas, preservando
    `released_at` para diagnóstico.
53. Não criar cron por tenant; concorrência recorrente é organizada por
    tarefa/slot.
54. `GET /api/worker/operational-tenants` deve permanecer restrito ao worker
    autenticado e à sua própria instância. Nesta fase, a resposta contém
    somente identificadores e nomes necessários ao dry-run e nunca retorna
    host, usuário, senha de database, token, credencial ou segredo.

## Banco de dados

- Tabelas legadas usam uma letra e três dígitos: `C###`, `Q###` ou `L###`;
  no `hub-mkp-core`, novas tabelas preferem nomes convencionais em inglês.
- Campos legados usam o prefixo da tabela, por exemplo `C001_Id`, `C001_Nome`
  e `C001_Status`; no `hub-mkp-core`, novas colunas preferem inglês sem
  prefixo.
- Novas mudanças de schema devem ser migrations versionadas.
- `worker_task_locks` contém somente metadados genéricos de coordenação e não
  pode se tornar fila ou armazenamento operacional de marketplace.
- Senha de usuário é hash não reversível, existe somente no Core e nunca deve
  ser copiada para a C007 local do tenant.
- Token de confirmação nunca é armazenado puro; armazene seu hash.
- Hash de token de confirmação deve ser determinístico e autenticado com uma
  chave mantida fora do código.
- Token de sessão é opaco, tem expiração e nunca é armazenado puro.
- Senha de database exige criptografia autenticada reversível. Não use hash e
  não improvise chave fixa no código.
- O provisionamento real deve validar nomes e configuração, usar privilégios
  mínimos, testar a conexão, criptografar a senha antes de C003 e preservar
  retry, concorrência e auditoria.

## Alterações e validação

- Mantenha alterações pequenas, explícitas e dentro da responsabilidade do
  Core.
- Atualize o `README.md` quando mudar contrato, setup ou arquitetura.
- Cadastro e confirmação devem ser transacionais: falhas não podem deixar
  usuário, grupo, vínculo, token ou tarefa parcialmente criados.
- Provisionamento deve preservar retry, limite de tentativas e isolamento de
  erro por tarefa; uma falha não encerra o restante do lote.
- Rode lint nos PHPs alterados, valide o autoload do Composer e teste o health
  check e os scripts de banco quando houver ambiente disponível.
- Não execute `git commit` nem `git push`. Somente o responsável humano pode
  revisar, commitar e publicar mudanças.
- Alterações de finalização permanecem limitadas ao bootstrap administrativo;
  não implemente marketplace operacional, produtos, pedidos, categorias,
  anúncios, preço, sincronização ou estoque. Broker OAuth/callback segue a
  exceção restrita descrita acima.
- O cursor operacional `last_tenant_id` é metadado genérico do lock global:
  somente o proprietário autenticado pode atualizá-lo por heartbeat, e o
  release deve preservá-lo.
- Contexto operacional de tenant só pode ser entregue ao Worker autenticado da
  mesma instância, para tenant e database ativos e provisionados. A senha pode
  existir apenas na resposta `no-store` e nunca em logs ou auditoria.
