O cadastro normal do Treino Livre é confirmado pelo
Telegram — o que exclui quem não pode ter a conta no
mensageiro, tipicamente menores de idade. A
conta gerida é a resposta: criada por um
.admin responsável, sem nenhum vínculo com
Telegram, e com travas de privacidade que caem automaticamente
aos 18 anos.
| Conta normal | Conta GERIDA (menor) | |
|---|---|---|
| Nasce | cadastro web + Telegram | aba 🧒 Contas geridas do
/treino/admin/ |
| Senha | por DM do bot | gerada e mostrada UMA vez ao admin |
| Esqueci a senha | /trocarsenha no bot |
só o admin (🔑 na aba) |
| Perfil público | opcional (padrão público) | sempre privado (o servidor recusa tornar público) |
| Telegram | opcional | bloqueado |
| Aos 18 | — | as travas caem sozinhas: pode vincular Telegram e abrir o perfil |
A marca fica no account.json do usuário:
"managed": { "by": "prof.admin", "note": "turma A, Escola X",
"birthdate": "2011-03-14", "expires_at": null, "created_at": 1785000000 }Menor é calculado da data de nascimento a cada
acesso — nada é "virado" aos 18; os gates simplesmente deixam de valer.
A marca managed permanece (histórico/listagem, com o badge
18+), e o perfil continua privado até o próprio usuário
abri-lo.
profile_is_public corta no servidor; a conta não aparece no
top-10 nem no "resolvido recentemente" da home, e o perfil dos outros
pontos de vista é o cadeado 🔒 (mesma regra do perfil privado
comum);POST /treino/telegram/link-start responde 403
managed_minor.expires_at
vencido o login responde 403 account_expired ("fale com o
responsável"). Renovar = editar/limpar a data na aba./treino/admin/)nome.sobrenome, com dedup), nota livre e
expiração opcional.Nome Completo;AAAA-MM-DD, com nota e expiração comuns —
ideal para uma turma./contest/badges recusa contest=treino de
propósito, para não despejar a base inteira em claro)..removed-users/, submissões
preservadas).managed-create/reset/update/remove entram no audit-log com
o admin autor (aba 📜 Atividade)..admin)| Rota | Uso |
|---|---|
GET /treino/admin/managed-users |
lista
{login,fullname,by,note,birthdate,minor,expires_at,disabled} |
POST /treino/admin/managed-create |
{users:[{fullname,birthdate,login?,note?,expires_at?}]}
(1..500) → {created:[{login,password,…}], skipped} |
POST /treino/admin/managed-reset |
{login} → senha nova (uma vez) |
POST /treino/admin/managed-update |
{login, note?, birthdate?, expires_at?|null, disabled?} |
POST /treino/admin/managed-remove |
{login} |
account.json (modelo padrão da
plataforma) e só transita na resposta de criação/reset.managed_json / is_managed_minor
em server/api/v1/lib/profile.sh —
is_managed_minor é o gate usado por
profile_is_public, pelo POST do
/treino/profile e pelo link-start. Data
ilegível = trata como menor (fail-safe).web/treino/perfil/perfil.js) esconde o
vínculo Telegram e trava o checkbox de privacidade quando
GET /treino/profile devolve
managed.minor:true.POST /contest/admin/users-set-password recusa
contest=treino (um POST resetaria todas as contas
da plataforma).MANUAL-TREINO.md — o
manual do aluno (cadastro normal, login).PERFIL.md — o perfil público
e as conquistas.API.md — contratos completos das
rotas.