Files
GTI_GERENCIADOR_FISCAL/central/templates/agent_new_installation.html
T
gtiandClaude Sonnet 5 e7d77beb26 feat: GTI Gerenciador as the single source of truth for clients; bump to 1.1.2
Tenant gains source (LOCAL|GTI_GERENCIADOR), external_client_id, external_code,
active and synced_at (migration 0024). central/app/client_sync.py fetches from
the panel's new GET /internal/fiscal/clients (dedicated bearer token, never
MySQL credentials) and upserts Tenant rows, never touching a LOCAL row.
/agents/new now offers only active GTI_GERENCIADOR tenants, with a client-side
search box; the POST validates the same rule server-side, not just in the
dropdown. central/scripts/sync_clients_from_gerenciador.py is the operator-run
sync + reconciliation report.

GTI_FISCAL_VERSION/AGENT_VERSION bumped to 1.1.2 (release/VERSION single
source of truth), incorporating the installation_id persistence fix. Rebuilt
the EXE installer trio at 1.1.2 (scripts/build_windows_installer.ps1).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-23 22:38:58 -03:00

44 lines
2.4 KiB
HTML

{% extends "base.html" %}
{% block title %}Nova instalação | GTI Fiscal{% endblock %}
{% block content %}
<div class="page-heading"><div><p class="eyebrow">DISTRIBUIÇÃO DO AGENT</p><h1>Nova instalação</h1><p class="muted">Cria uma instalação pendente; o pacote e o vínculo de enrollment só existem depois de gerados aqui.</p></div><div><a href="/agents" class="secondary">Voltar</a></div></div>
<section class="panel" style="max-width:560px">
{% if error %}<p class="error" role="alert">{{ error }}</p>{% endif %}
{% if not releases %}
<p class="muted">Nenhuma versão do Agent está publicada ainda. Publique uma release primeiro (<code>python central/scripts/publish_agent_release.py</code>) e ela aparecerá aqui.</p>
{% elif not tenants %}
<p class="muted">Nenhum cliente ativo encontrado no GTI Gerenciador. Verifique o cadastro por lá, ou rode a sincronização (<code>python central/scripts/sync_clients_from_gerenciador.py</code>).</p>
{% else %}
<form method="post" action="/agents/new">
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
<label>Cliente
<input type="text" id="filtro-cliente" placeholder="Buscar cliente..." autocomplete="off" oninput="filtrarClientes(this.value)">
<select name="tenant_id" id="select-cliente" size="8" required>
{% for tenant in tenants %}<option value="{{ tenant.id }}">{{ tenant.name }}</option>{% endfor %}
</select>
</label>
<label>Nome da instalação
<input name="display_name" placeholder="ex. Servidor Principal" maxlength="160" required>
</label>
<label>Hostname esperado (opcional)
<input name="expected_hostname" placeholder="ex. SRV-CONSTRUCAO" maxlength="255">
</label>
<label>Versão do Agent
<select name="release_id" required>
{% for release in releases %}<option value="{{ release.id }}" {% if loop.first %}selected{% endif %}>{{ release.version }} ({{ release.platform }}/{{ release.architecture }})</option>{% endfor %}
</select>
</label>
<p><button type="submit">Criar instalação</button></p>
</form>
<script>
function filtrarClientes(termo) {
var alvo = termo.trim().toLowerCase();
document.querySelectorAll("#select-cliente option").forEach(function (opcao) {
opcao.hidden = alvo.length > 0 && opcao.textContent.toLowerCase().indexOf(alvo) === -1;
});
}
</script>
{% endif %}
</section>
{% endblock %}