Files
agenciapsilmno/docs/planos/dev-documentacao-planos-seeder-complemento.html

232 lines
5.0 KiB
HTML

<!doctype html>
<html lang="pt-BR">
<head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>Agência PSI — Billing (Arquitetura Oficial v1.1)</title>
<style>
:root{
--bg0:#f6f8fc;
--bg1:#eef2f8;
--panel:rgba(255,255,255,.85);
--border:rgba(15,23,42,.10);
--text:rgba(15,23,42,.92);
--muted:rgba(15,23,42,.70);
--accent:#2563eb;
--ok:#047857;
--warn:#b45309;
--danger:#b91c1c;
--radius:18px;
--shadow:0 18px 60px rgba(2,6,23,.10);
--mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
--sans: ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial;
}
*{box-sizing:border-box}
body{
margin:0;
font-family:var(--sans);
background:linear-gradient(180deg,var(--bg0),var(--bg1));
color:var(--text);
}
.layout{
max-width:1100px;
margin:0 auto;
padding:40px 20px 80px;
}
header{
border:1px solid var(--border);
background:var(--panel);
border-radius:var(--radius);
padding:28px;
box-shadow:var(--shadow);
}
h1{margin:0 0 12px;font-size:30px}
h2{margin-top:40px;font-size:20px}
p{color:var(--muted);line-height:1.6}
.section{
margin-top:30px;
border:1px solid var(--border);
background:var(--panel);
padding:24px;
border-radius:var(--radius);
box-shadow:var(--shadow);
}
.rule{
border-left:4px solid var(--accent);
background:rgba(37,99,235,.08);
padding:14px;
border-radius:12px;
margin:18px 0;
}
.ok{
border-left:4px solid var(--ok);
background:rgba(4,120,87,.08);
padding:14px;
border-radius:12px;
margin:18px 0;
}
.warn{
border-left:4px solid var(--warn);
background:rgba(180,83,9,.10);
padding:14px;
border-radius:12px;
margin:18px 0;
}
.danger{
border-left:4px solid var(--danger);
background:rgba(185,28,28,.08);
padding:14px;
border-radius:12px;
margin:18px 0;
}
code,pre{font-family:var(--mono);font-size:13px}
pre{
background:rgba(2,6,23,.05);
padding:14px;
border-radius:12px;
overflow:auto;
}
table{
width:100%;
border-collapse:collapse;
margin-top:16px;
}
th,td{
border:1px solid var(--border);
padding:10px;
font-size:13px;
}
th{background:rgba(15,23,42,.04)}
footer{
text-align:center;
margin-top:50px;
font-size:12px;
color:var(--muted);
}
</style>
</head>
<body>
<div class="layout">
<header>
<h1>Billing — Arquitetura Oficial v1.1</h1>
<p>Versão 1.1 inclui procedimento formal de migração controlada para planos core, mantendo guardrails ativos e auditáveis.</p>
</header>
<div class="section">
<h2>1. Fundamentos do Domínio</h2>
<p>Billing define recursos e limites do produto. Não é camada de UI. É camada estrutural.</p>
<div class="rule"><strong>Princípio:</strong> Role (RBAC) ≠ Plano (Billing). Plano dirige features e limites; role dirige acesso.</div>
</div>
<div class="section">
<h2>2. Planos Core (MVP)</h2>
<ul>
<li>clinic_free</li>
<li>clinic_pro</li>
<li>therapist_free</li>
<li>therapist_pro</li>
</ul>
<div class="ok"><strong>Política:</strong> Planos core são estruturalmente protegidos por triggers.</div>
</div>
<div class="section">
<h2>3. Governança de Guardrails</h2>
<ul>
<li>Impedem alterar key de plano core</li>
<li>Impedem alterar target de plano core</li>
<li>Impedem deletar plano com subscription ativa</li>
</ul>
<div class="danger"><strong>Proibido:</strong> desabilitar triggers diretamente em produção.</div>
</div>
<div class="section">
<h2>4. Procedimento Oficial de Correção de Plano Core</h2>
<p>Correções estruturais devem ocorrer via função administrativa controlada.</p>
<pre>
create or replace function admin_fix_plan_target(
p_plan_key text,
p_new_target text
) returns void
language plpgsql
security definer
as $$
declare
v_plan_id uuid;
begin
select id into v_plan_id
from plans
where key = p_plan_key
for update;
if v_plan_id is null then
raise exception 'Plano não encontrado.';
end if;
if exists (
select 1 from subscriptions where plan_id = v_plan_id
) then
raise exception 'Plano possui subscriptions ativas.';
end if;
update plans
set target = p_new_target
where id = v_plan_id;
end;
$$;
</pre>
<div class="warn">
Esta função deve ser executada apenas por role administrativa e registrada em log de auditoria.
</div>
</div>
<div class="section">
<h2>5. Entitlements (Contrato Oficial)</h2>
<p>Entitlements são derivados exclusivamente de <code>plan_features</code>.</p>
<pre>
plan_features (
plan_id uuid,
feature_id uuid,
enabled boolean,
limits jsonb
)
</pre>
<div class="rule">
Formato oficial de limits:
{"max": 30}
{"per_month": 40}
{"max_users": 1}
</div>
</div>
<div class="section">
<h2>6. Preço Vigente</h2>
<pre>
create unique index uq_plan_price_active
on plan_prices (plan_id, interval, currency)
where is_active = true and active_to is null;
</pre>
</div>
<div class="section">
<h2>7. Onboarding</h2>
<ul>
<li>Tenant clinic → clinic_free</li>
<li>Tenant therapist → therapist_free</li>
</ul>
</div>
<footer>
Agência PSI — Billing Arquitetura Oficial v1.1
</footer>
</div>
</body>
</html>