Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
6d0ea14
fix(sync): grava expires_at em ISO e testStatus 'active' no OmniRoute
elielsousa-pathbit Sep 12, 2026
8d24161
feat: dashboard server-side, i18n, log persistente e credencial de re…
elielsousa-pathbit Sep 12, 2026
38d7be9
refactor: alinha comentarios e codigos de status ao ingles adotado pe…
elielsousa-pathbit Sep 12, 2026
6237061
docs: wiki versionada no repo com publicacao automatica
elielsousa-pathbit Sep 12, 2026
08bdc01
feat(providers): descobre os modelos da instancia local e detecta qua…
elielsousa-pathbit Sep 12, 2026
1084aab
fix: valida credenciais de verdade, corrige deteccao de instancia loc…
elielsousa-pathbit Sep 12, 2026
058e24c
merge: integra master mantendo a gravacao ISO documentada e coberta p…
elielsousa-pathbit Sep 12, 2026
5ff7cc8
feat: senha com politica de forca gravada como hash no sqlite e refre…
elielsousa-pathbit Sep 12, 2026
3e76635
fix: healthz voltou a quebrar no merge, e credenciais vivas sumiram d…
elielsousa-pathbit Sep 12, 2026
24e36e1
fix: elimina a senha de fabrica e a retencao de packages que apagava …
elielsousa-pathbit Sep 12, 2026
38aaf4b
fix: cura o formato de expires_at mesmo quando a renovacao OAuth falha
elielsousa-pathbit Sep 12, 2026
06b4dd7
fix(ci): remove input inexistente da politica de retencao
elielsousa-pathbit Sep 12, 2026
f5fa658
chore(security): retencao ciente de multi-arch e fim das senhas de ex…
elielsousa-pathbit Sep 12, 2026
e7b28d5
fix(auth): senha vazia no ambiente nao pode travar a troca pela tela
elielsousa-pathbit Sep 12, 2026
a052b68
fix: despacho de providers, persistencia da sondagem e armazenamento …
elielsousa-pathbit Sep 12, 2026
b5fd38b
feat: saida de rede por conta (leitura) e documentacao de multi-sessao
elielsousa-pathbit Sep 12, 2026
34a80ce
fix: cabecalho de autenticacao, Ollama hospedado, CSP das bandeiras e…
elielsousa-pathbit Sep 12, 2026
90f6d3e
test: stack de teste propria do repositorio, sem depender de artigo
elielsousa-pathbit Sep 12, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
106 changes: 79 additions & 27 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,64 +1,116 @@
# ==============================================================================
# OminiRoute Universal Token & Connection Synchronizer (OminiRTKSync)
# Environment Variable Configuration Template
# Modelo de Configuracao de Variaveis de Ambiente
# ==============================================================================
# To configure your local or container environment
# 1. Copy this file to .env (cp .env.example .env)
# 2. Adjust values for your infrastructure and credentials
# 3. The .env file is strictly ignored by version control (.gitignore)
# Para configurar seu ambiente local ou container:
# 1. Copie este arquivo para .env: cp .env.example .env
# 2. Ajuste os valores conforme sua infraestrutura e credenciais
# 3. O arquivo .env e estritamente ignorado pelo controle de versao (.gitignore)
# ==============================================================================

# ------------------------------------------------------------------------------
# 1. Storage and Token Discovery
# 1. Armazenamento e Descoberta de Tokens
# ------------------------------------------------------------------------------
# Host base directory mounted inside container (e.g. /root/host when mounted ${HOME}:/root/host:ro)
# Diretorio base do host montado no container (ex: /root/host quando montado $HOME:/root/host:ro)
HOST_HOME=/root/host

# Absolute path to OmniRoute SQLite storage file
# Default inside OmniRoute container: /app/data/storage.sqlite
# Caminho absoluto para o banco de dados SQLite do OmniRoute
# Padrao no container OmniRoute: /app/data/storage.sqlite
DB_PATH=/app/data/storage.sqlite

# Optional custom path to direct Antigravity OAuth credentials
# Caminho opcional para credenciais OAuth diretas do Antigravity
# ANTIGRAVITY_TOKEN_PATH=/root/host/.gemini/oauth_creds.json

# Diretorio base de tudo que este container escreve: o banco de preferencias do
# painel, a credencial de recuperacao e o diretorio de log. Por padrao e o
# diretorio do DB_PATH. Defina quando o banco do gateway estiver em um lugar
# onde o sincronizador nao deve escrever.
# DATA_DIR=/app/data

# Cliente OAuth do Google usado para renovar credenciais Antigravity / Gemini
# CLI. Deixe AMBOS vazios para que o sincronizador os leia do arquivo de
# credencial que encontra no host. Preencha apenas em implantacao isolada, sem
# credencial do host montada. Sao segredos: o lugar deles e o seu .env, que
# nunca e versionado, jamais este arquivo de exemplo.
# GOOGLE_CLIENT_ID=
# GOOGLE_CLIENT_SECRET=

# ------------------------------------------------------------------------------
# 2. OmniRoute Gateway Connectivity
# 2. Conectividade com o Gateway OmniRoute
# ------------------------------------------------------------------------------
# OmniRoute gateway base URL for connectivity tests and diagnostics
# URL base do gateway OmniRoute para testes de conexao e diagnosticos
OMNIROUTE_URL=http://127.0.0.1:20128

# ------------------------------------------------------------------------------
# 3. Synchronization Parameters and Cron Scheduler
# 3. Parametros de Sincronizacao e Agendador Cron
# ------------------------------------------------------------------------------
# Interval in seconds between synchronization passes and cron renewals (default 300s / 5min)
# Intervalo em segundos entre as execucoes do sincronizador e do cron de renovacao (padrao: 300s / 5min)
SYNC_INTERVAL=300

# Margin in seconds before expiration to trigger proactive renewal (default 900s / 15min)
# Margem em segundos antes da expiracao para renovar tokens proativamente (padrao: 900s / 15min)
REFRESH_MARGIN=900

# Intervalo exclusivo do agendador cron. Se omitido, herda o valor de SYNC_INTERVAL.
# CRON_INTERVAL=300

# Liga/desliga o agendador automatico (1=ligado, 0=desligado).
# Com 0, a sincronizacao so acontece por disparo manual (--once ou POST /api/sync).
CRON_ENABLED=1

# ------------------------------------------------------------------------------
# 4. Web Server and Administrative Dashboard
# 4. Servidor Web e Dashboard Administrativo
# ------------------------------------------------------------------------------
# Enable administrative web dashboard (1=enabled, 0=disabled)
# Ativa o dashboard web administrativo (1=ativado, 0=desativado)
ENABLE_WEB_DASHBOARD=1

# Network binding interface for internal web server
# Host de escuta do servidor web interno
WEB_HOST=0.0.0.0

# HTTP port for the OminiRTKSync web dashboard (default 9191)
WEB_PORT=9191
# Porta INTERNA do servidor web dentro do container (padrao: 9090).
# Ela e igual nos dois sincronizadores; o que muda e a porta publicada no host
# (9091 para o 9RTKSync, 9092 para o OminiRTKSync).
WEB_PORT=9090

# HTTP Basic Auth credentials for dashboard access
# IMPORTANT Update these credentials upon first login via web interface or via .env
# Credenciais de acesso HTTP Basic Auth do painel.
# IMPORTANTE: Altere estas credenciais no primeiro acesso via interface web ou via .env!
#
# Modo headless: quando DASHBOARD_USER e/ou DASHBOARD_PASSWORD estao definidas, elas
# passam a ser a fonte de verdade e o arquivo .dashboard_auth.json gravado pela tela
# e ignorado. A troca de senha pelo painel passa a responder 409 Conflict. Basta
# comentar as duas linhas abaixo para devolver o controle ao dashboard.
DASHBOARD_USER=admin
DASHBOARD_PASSWORD=pathbit
# DASHBOARD_PASSWORD= # vazio: usa a credencial de recuperacao do primeiro boot

# Credencial de recuperacao (break-glass). Entre com o usuario 'admin' e este valor
# como senha caso a senha do painel seja esquecida. Se ficar vazia, um valor aleatorio
# e gerado no primeiro boot, salvo em .dashboard_recovery (0600) e registrado no log.
# DASHBOARD_RECOVERY_HASH=

# ------------------------------------------------------------------------------
# Log persistente em arquivo
# ------------------------------------------------------------------------------
LOG_DIR=/app/data/logs
LOG_RETENTION_DAYS=30
LOG_LEVEL=INFO
LOG_TO_STDOUT=1

# ------------------------------------------------------------------------------
# 5. OmniRoute Stack Integration (Docker Compose)
# 5. Integracao com a Stack OmniRoute (Docker Compose)
# ------------------------------------------------------------------------------
# Initial password and JWT secret for OmniRoute
INITIAL_PASSWORD=PathbitDevs2026!
JWT_SECRET=omniroute-jwt-secret-key-pathbit
# Senha inicial e segredo JWT do OmniRoute.
# Ambos sao OBRIGATORIOS e vem vazios de proposito: um valor publicado em
# arquivo de exemplo e uma credencial publica, e vira a senha real de toda
# implantacao que copiou o arquivo. O `docker compose up` recusa subir
# enquanto nao forem preenchidos.
# INITIAL_PASSWORD -> no minimo 12 caracteres, gerados, nao digitados
# JWT_SECRET -> openssl rand -hex 32
INITIAL_PASSWORD=
JWT_SECRET=
REQUIRE_API_KEY=false
REQUIRE_LOGIN=false

# --- Validacao viva de credenciais -----------------------------------------
# Pergunta a cada provedor se a chave/token ainda e aceito, em vez de assumir
# que uma conexao esta saudavel so por carregar uma credencial.
CREDENTIAL_CHECK_ENABLED=1
CREDENTIAL_CHECK_TIMEOUT=8
27 changes: 13 additions & 14 deletions .github/ISSUE_TEMPLATE/bug_report.yml
Original file line number Diff line number Diff line change
@@ -1,39 +1,38 @@
name: Bug Report
description: Report a defect or synchronization issue in OminiRTKSync
name: Relato de Bug
description: Reporte um problema ou falha de sincronização no OminiRTKSync
title: "[BUG] "
labels: ["bug"]
body:
- type: markdown
attributes:
value: |
Thank you for helping improve OminiRTKSync! Please provide details about the issue so we can reproduce and fix it promptly.
Obrigado por ajudar a aprimorar o OminiRTKSync! Forneça detalhes sobre a falha para podermos reproduzir e corrigir rapidamente.
- type: input
id: provider
attributes:
label: Affected Provider
description: Which OmniRoute connection failed? (e.g., Antigravity, Claude, Groq, Mistral, Ollama)
placeholder: e.g., Antigravity / Google OAuth
label: Provedor Afetado
description: Qual conexão do OmniRoute apresentou falha? (ex: Antigravity, Claude, Groq, Mistral, Ollama)
placeholder: ex: Antigravity / Google OAuth
validations:
required: true
- type: textarea
id: description
attributes:
label: Problem Description
description: What happened and what was the expected behavior?
label: Descrição do Problema
description: O que aconteceu e qual era o comportamento esperado?
validations:
required: true
- type: textarea
id: logs
attributes:
label: Logs and Error Messages
description: Paste relevant container logs or command output
label: Logs e Mensagens de Erro
description: Cole os logs do container ou do comando OminiRTKSync
render: shell
- type: input
id: version
attributes:
label: OminiRTKSync Version and Environment
description: Docker version, container image tag, or local Python version
placeholder: e.g., ghcr.io/pathbit/ominirtksync:latest on macOS / Linux
label: Versão do OminiRTKSync e Ambiente
description: Versão do Docker, imagem utilizada ou Python local
placeholder: ex: ghcr.io/pathbit/ominirtksync:latest no macOS Sequoia
validations:
required: true

15 changes: 7 additions & 8 deletions .github/ISSUE_TEMPLATE/feature_request.yml
Original file line number Diff line number Diff line change
@@ -1,22 +1,21 @@
name: Feature Request / Provider Suggestion
description: Suggest a new feature, connection provider, or enhancement for OminiRTKSync
name: Sugestão de Melhoria / Provedor
description: Sugira uma nova funcionalidade, provedor ou melhoria para o OminiRTKSync
title: "[FEAT] "
labels: ["enhancement"]
body:
- type: markdown
attributes:
value: |
Thank you for proposing improvements for OminiRTKSync!
Obrigado por propor melhorias para o OminiRTKSync!
- type: textarea
id: idea
attributes:
label: Suggestion Description
description: Explain in detail your use case or requested enhancement
label: Descrição da Sugestão
description: Explique detalhadamente o caso de uso ou a melhoria desejada
validations:
required: true
- type: textarea
id: context
attributes:
label: OmniRoute Context
description: How does OmniRoute manage this connection and how should OminiRTKSync interact with it?

label: Contexto no OmniRoute
description: Como o OmniRoute gerencia essa conexão e de que forma o OminiRTKSync deve interagir?
25 changes: 12 additions & 13 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
## Description of Changes
## Descrição das Alterações

Explain clearly what this Pull Request resolves, enhances, or adds to `OminiRTKSync`.
Explique de forma clara e objetiva o que este Pull Request resolve, aprimora ou adiciona ao `OminiRTKSync`.

## Change Type
## Tipo de Alteração

- [ ] Bug fix
- [ ] New feature or provider support
- [ ] Refactoring or performance optimization
- [ ] Documentation update
- [ ] Testing or CI pipeline improvements
- [ ] Correção de bug (bug fix)
- [ ] Nova funcionalidade ou suporte a novo provedor
- [ ] Refatoração de código sem impacto em comportamento
- [ ] Atualização de documentação
- [ ] Melhorias em testes ou pipeline de CI

## Verification Checklist

- [ ] Code executed and validated in local virtual environment (`source .venv/bin/activate`).
- [ ] Unit test suite passing (`python3 -m unittest discover -s tests` or `./run_tests.sh`).
- [ ] No conflicts with the `master` branch.
## Checklist de Validação

- [ ] Código executado e validado em virtual environment local (`source .venv/bin/activate`).
- [ ] Suíte de testes unitários passando (`python3 -m unittest discover -s tests`).
- [ ] Sem conflitos com a branch `master`.
86 changes: 72 additions & 14 deletions .github/workflows/cleanup-packages.yml
Original file line number Diff line number Diff line change
@@ -1,29 +1,87 @@
name: Purge Packages
name: Package Retention

# Mantem o registro enxuto sem nunca derrubar o que esta em uso.
#
# Historico: a primeira versao deste arquivo nao era limpeza. Com
# min-versions-to-keep: 0 e delete-only-untagged-versions: false ela apagava
# TODAS as versoes e em seguida removia o proprio package via API. Quem
# estivesse puxando ghcr.io/pathbit/ominirtksyncatest ficava sem imagem.
#
# A segunda versao corrigia isso, mas usava actions/delete-package-versions,
# que trata cada manifesto como uma versao independente. O build e multi-arch
# (linux/amd64 + linux/arm64): o buildx publica um manifest list com a tag e um
# manifesto SEM TAG por plataforma. Descartar "versoes sem tag" apaga
# justamente as camadas que a tag referencia, e o pull passa a falhar com
# "manifest unknown" mesmo com a tag intacta no registro.
#
# Por isso a limpeza aqui usa uma action que resolve o manifest list antes de
# apagar: um manifesto sem tag so e descartado se nenhuma tag preservada
# apontar para ele.

on:
workflow_dispatch:
inputs:
keep:
description: "Quantas versoes marcadas manter"
required: false
default: "3"
dry-run:
description: "Simular: lista o que seria apagado sem apagar"
required: false
default: "false"
schedule:
# Semanal, domingo 04:00 UTC: o acumulo vem dos builds, nao do relogio.
- cron: "0 4 * * 0"
workflow_run:
workflows: ["Release and Docker Package"]
types: [completed]

permissions:
packages: write

concurrency:
group: package-retention-ominirtksync
cancel-in-progress: false

jobs:
purge:
retention:
name: Apply retention policy
runs-on: ubuntu-latest
# Depois de um release, so faz sentido limpar se o release funcionou.
if: >-
github.event_name != 'workflow_run' ||
github.event.workflow_run.conclusion == 'success'
steps:
- name: Purge package versions
uses: actions/delete-package-versions@v5
- name: Apply retention policy
uses: dataaxiom/ghcr-cleanup-action@v1.2.2
with:
package-name: 'ominirtksync'
package-type: 'container'
min-versions-to-keep: 0
delete-only-untagged-versions: 'false'
continue-on-error: true
token: ${{ secrets.GITHUB_TOKEN }}
owner: ${{ github.repository_owner }}
packages: ominirtksync
# Guarda as N imagens marcadas mais recentes, com as camadas de
# plataforma de cada uma. 'latest' fica de fora da contagem por
# seguranca, ainda que por construcao ela aponte para a mais nova.
keep-n-tagged: ${{ github.event.inputs.keep || '3' }}
exclude-tags: latest
# Apaga apenas manifestos orfaos de verdade: os que sobraram de
# builds ja aposentados e nao pertencem a nenhuma tag preservada.
delete-untagged: true
# Restos de execucoes anteriores: manifest list cujas camadas de
# plataforma ja nao existem (nao ha o que puxar delas).
delete-ghost-images: true
delete-partial-images: true
delete-orphaned-images: true
# Confere no registro se cada digest referenciado existe mesmo, e
# registra o resultado no log da execucao.
validate: true
dry-run: ${{ github.event.inputs.dry-run || 'false' }}

- name: Force delete package via GitHub API
- name: Report what survived
if: always()
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
curl -X DELETE \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer $GH_TOKEN" \
https://api.github.com/orgs/pathbit/packages/container/ominirtksync || true
echo "### Versoes mantidas em ominirtksync" >> "$GITHUB_STEP_SUMMARY"
gh api "/orgs/${{ github.repository_owner }}/packages/container/ominirtksync/versions" \
--jq '.[] | "- \(.name[0:19]) tags: \(.metadata.container.tags | join(", "))"' \
>> "$GITHUB_STEP_SUMMARY" || echo "- (nao foi possivel listar)" >> "$GITHUB_STEP_SUMMARY"
Loading
Loading