src/provision — a rotina que cria uma organização
Não é um módulo de API: é a rotina única chamada pelo mod-signup e pela linha de comando. Faz os 6 passos do flx-onboarding e é idempotente por etapa — reexecutar completa o que faltou, porque cada passo checa antes de agir.
Como se usa pela linha de comando
docker exec appstock-dev-api python -m src.provision \
--slug santonio --name "Santo Antonio" \
--admin-name "Fulano" --admin-email fulano@santonio.com.br \
--admin-password '...' [--default]Imprime um JSON com org_id, slug, app_db, sync_db, admin_email e o
sync_token em claro — a única vez que ele aparece. A plataforma guarda só o SHA-256.
--default marca a organização como is_default: é ela que atende rota pública sem ?org=
(hoje, a demo). Ver flx-resolucao-tenant.
O que cada peça faz
| Função | Responsabilidade |
|---|---|
bootstrap() | Garante que o appstock_core existe (CREATE DATABASE + create_all do metadata). |
_ensure_database() | CREATE DATABASE via engine em AUTOCOMMIT no banco postgres. Devolve False se já existia. |
_run_app_migrations() | alembic upgrade head por subprocess, em /app, com ALEMBIC_URL apontando para o DSN da organização. É como o mesmo histórico Alembic serve N bancos. |
_apply_sync_template() | Aplica db/sync_template.sql só se o schema public estiver vazio. Usa cursor bruto porque o arquivo tem múltiplos statements. |
_seed_app_db() | Dentro de org_context: linha da organização (mesmo UUID do core), sync_resources, perfil Administrador com todos os grants, usuário admin superusuário. |
_log_step() | Grava provisioning_log (OK/ERROR) a cada passo. |
O usuário admin nasce com local_username = "<slug>-admin", auth_type = "LOCAL",
status = "ACTIVE" e is_superuser = True.
Detalhes que economizam tempo depois
- O UUID da organização é o mesmo no core e no
app_<org>. Não há de-para. Isso é o que permiteorg_context(org_id)funcionar em scripts. tenants.invalidate(org_id)é chamado depois de registrar os DSNs — sem isso a engine da organização recém-criada não seria encontrada no mesmo processo.- A checagem de e-mail duplicado só roda quando a organização é nova. Numa reexecução (org já existe) o e-mail não é reconferido.
- Os 11 módulos de
MODULES_V1são gravados emorg_modules:stock,commercial,clients,offers,opportunities,orders,dashboards,dictionary_studio,ai_assistant,reports,media.
Estado real
Funciona e é a única forma suportada de criar organização. As duas orgs atuais nasceram daqui. Buracos:
1. org_modules é gravado e nunca lido [M]
Nenhum código consulta essa tabela. Os módulos não gateiam nada — não há como vender plano por módulo nem suspender inadimplente. Ver mod-organizations.
2. O appstock_core não tem migrations [P]
bootstrap() usa create_all. Qualquer evolução do plano de controle (plano, cobrança, domínio
por organização, usuário multi-org) não tem caminho seguro de aplicação nem rollback.
3. Sem console de operador [M]
Listar organizações, ver status, bancos, uso e o provisioning_log só por SQL. Um
provisionamento que falhou pela metade é invisível.
4. decommission_legacy.py está quebrado [P]
Lê SF_DB_USER/SF_DB_PASSWORD, variáveis que não existem mais — estoura com KeyError.
Pior: já executou um DROP DATABASE antes de estourar. Falha no meio. Além disso reintroduz
a nomenclatura SF_, proibida no projeto. O rewipe_orgs.py, ao lado, está íntegro.
Lacunas
Rastreadas na fase-1-onboarding.