chore: establish project baseline

This commit is contained in:
OpenCode
2026-09-21 15:51:47 -03:00
commit 9dcc263217
459 changed files with 447890 additions and 0 deletions
+18
View File
@@ -0,0 +1,18 @@
# GTI Fiscal Hub — production environment (copy to .env, never commit .env)
GTI_FISCAL_VERSION=1.0.0-rc1
# REQUIRED. URL-safe secret (used inside a connection URL): openssl rand -hex 24
POSTGRES_PASSWORD=
# REQUIRED. Public HTTPS URL that Agents use (TLS terminates in the reverse proxy in front of the Hub).
BASE_URL=https://fiscal.example.gti
# Interface the Hub listens on. Keep 127.0.0.1 when a reverse proxy runs on the same host; use the LAN IP only behind a firewall.
HUB_BIND=127.0.0.1
HUB_PORT=8000
LOG_LEVEL=INFO
AGENT_ONLINE_THRESHOLD_SECONDS=120
# Directory (host) where pg_dump backups are written by backup.sh
BACKUP_DIR=./backups
+13
View File
@@ -0,0 +1,13 @@
#!/usr/bin/env sh
# PostgreSQL backup of the GTI Fiscal Hub (custom format, restorable with restore.sh). Run from deploy/hub.
# ./backup.sh -> ./backups/gti_fiscal_YYYYmmdd_HHMMSS.dump (last 14 kept)
set -eu
COMPOSE="docker compose -f docker-compose.prod.yml --env-file .env"
DIR="${BACKUP_DIR:-./backups}"
mkdir -p "$DIR"
STAMP="$(date +%Y%m%d_%H%M%S)"
FILE="gti_fiscal_${STAMP}.dump"
$COMPOSE exec -T postgres pg_dump -U gti -d gti_fiscal -Fc -f "/backups/${FILE}"
[ -s "$DIR/$FILE" ] || { echo "backup empty or missing: $DIR/$FILE" >&2; exit 1; }
ls -1t "$DIR"/gti_fiscal_*.dump | tail -n +15 | xargs -r rm -f
echo "backup ok: $DIR/$FILE"
+68
View File
@@ -0,0 +1,68 @@
# GTI Fiscal Hub — production compose (RC1). Only two containers: PostgreSQL + Hub. No Kubernetes/Redis/RabbitMQ.
#
# cd deploy/hub && cp .env.example .env && (edit .env) && docker compose -f docker-compose.prod.yml --env-file .env up -d --build
#
# PostgreSQL is on an internal network only: it publishes NO port and is not reachable from the LAN/internet.
# The Hub binds to HUB_BIND (default 127.0.0.1): put a TLS reverse proxy (HTTPS) in front of it for the Agents.
# Migrations run automatically at Hub start (Dockerfile CMD: alembic upgrade head).
name: gti-fiscal-hub
x-logging: &logging
driver: json-file
options:
max-size: "10m"
max-file: "5"
services:
postgres:
image: postgres:16-alpine
restart: unless-stopped
environment:
POSTGRES_DB: gti_fiscal
POSTGRES_USER: gti
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?POSTGRES_PASSWORD is required (URL-safe, e.g. openssl rand -hex 24)}
volumes:
- postgres_data:/var/lib/postgresql/data
- ${BACKUP_DIR:-./backups}:/backups
networks: [internal]
healthcheck:
test: ["CMD-SHELL", "pg_isready -U gti -d gti_fiscal"]
interval: 10s
timeout: 5s
retries: 12
logging: *logging
fiscal-hub:
build:
context: ../..
dockerfile: central/Dockerfile
image: gti-fiscal-hub:${GTI_FISCAL_VERSION:-1.0.0-rc1}
restart: unless-stopped
depends_on:
postgres:
condition: service_healthy
environment:
APP_ENV: production
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?POSTGRES_PASSWORD is required}
LOG_LEVEL: ${LOG_LEVEL:-INFO}
BASE_URL: ${BASE_URL:?BASE_URL is required (public HTTPS URL of the Hub)}
AGENT_ONLINE_THRESHOLD_SECONDS: ${AGENT_ONLINE_THRESHOLD_SECONDS:-120}
# AGENT_DEV_TOKEN is intentionally NOT set: real Agents are registered with central/scripts/register_agent.py.
ports:
- "${HUB_BIND:-127.0.0.1}:${HUB_PORT:-8000}:8000"
networks: [internal, edge]
healthcheck:
test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:8000/health')"]
interval: 15s
timeout: 5s
retries: 10
start_period: 30s
logging: *logging
networks:
internal:
internal: true # no route to the outside: PostgreSQL is never exposed
edge: {}
volumes:
postgres_data:
+12
View File
@@ -0,0 +1,12 @@
#!/usr/bin/env sh
# Run on the machine that holds the validated fiscal datasets (development Hub). Exports ONLY the reference tables
# (datasets + fiscal entries), never tenants/agents/jobs/classification data, so a fresh production Hub can be seeded:
#
# ./export_datasets_seed.sh projeto-postgres-1 > gti_datasets_seed.dump
# (copy to the production host, then) ./seed_datasets.sh gti_datasets_seed.dump
set -eu
CONTAINER="${1:-projeto-postgres-1}"
TABLES="datasets ncm_entries legacy_ncm_entries cest_entries cest_ncm_entries tipi_entries ba_st_mva_entries ba_st_mva_ncm_sh fiscal_code_entries cfop_entries fcp_rates anp_product_codes ncm_utrib_entries rtc_biofuel_index_entries rtc_cred_pres_entries rtc_cclasstrib_entries rtc_cst_ibscbs_entries rtc_cbs_rate_entries"
ARGS=""
for t in $TABLES; do ARGS="$ARGS -t $t"; done
docker exec "$CONTAINER" pg_dump -U gti -d gti_fiscal -Fc --data-only $ARGS
+15
View File
@@ -0,0 +1,15 @@
#!/usr/bin/env sh
# Restore a Hub backup into PostgreSQL. DESTRUCTIVE for the current data: asks for confirmation.
# ./restore.sh ./backups/gti_fiscal_20260919_120000.dump
set -eu
[ $# -eq 1 ] || { echo "usage: $0 <backup.dump>" >&2; exit 2; }
FILE="$(basename "$1")"
COMPOSE="docker compose -f docker-compose.prod.yml --env-file .env"
[ -s "${BACKUP_DIR:-./backups}/$FILE" ] || { echo "backup not found in ${BACKUP_DIR:-./backups}: $FILE" >&2; exit 1; }
printf "This REPLACES the current Hub database with %s. Type RESTORE to continue: " "$FILE"
read -r answer
[ "$answer" = "RESTORE" ] || { echo "aborted"; exit 1; }
$COMPOSE stop fiscal-hub
$COMPOSE exec -T postgres pg_restore -U gti -d gti_fiscal --clean --if-exists --no-owner "/backups/$FILE"
$COMPOSE up -d fiscal-hub # migrations run at start (alembic upgrade head)
echo "restore ok: $FILE"
+10
View File
@@ -0,0 +1,10 @@
#!/usr/bin/env sh
# Seed a NEW production Hub (already migrated: the Hub container ran `alembic upgrade head`) with the validated fiscal datasets.
# ./seed_datasets.sh gti_datasets_seed.dump
set -eu
[ $# -eq 1 ] || { echo "usage: $0 <gti_datasets_seed.dump>" >&2; exit 2; }
COMPOSE="docker compose -f docker-compose.prod.yml --env-file .env"
EXISTING="$($COMPOSE exec -T postgres psql -U gti -d gti_fiscal -At -c 'select count(*) from datasets')"
[ "$EXISTING" = "0" ] || { echo "refusing: datasets table is not empty ($EXISTING rows)" >&2; exit 1; }
$COMPOSE exec -T postgres pg_restore -U gti -d gti_fiscal --data-only --no-owner --disable-triggers < "$1"
$COMPOSE exec -T postgres psql -U gti -d gti_fiscal -At -c "select kind, status, record_count from datasets where status='ACTIVE' order by kind"