From 75d704ad0a377b4a13f727a0efb3d3fc03ac46e7 Mon Sep 17 00:00:00 2001 From: itecnologys Date: Wed, 7 Oct 2026 09:37:50 +0000 Subject: [PATCH] docs: Rently session 2026-10-06 + handoff 2026-10-07 Co-Authored-By: Claude Opus 5.5 --- Infra-Network/HANDOFF-RENTLY-2026-10-07.md | 62 ++++++ Infra-Network/SPEC-SESSION-2026-10-06.md | 235 +++++++++++++++++++++ 2 files changed, 297 insertions(+) create mode 100644 Infra-Network/HANDOFF-RENTLY-2026-10-07.md create mode 100644 Infra-Network/SPEC-SESSION-2026-10-06.md diff --git a/Infra-Network/HANDOFF-RENTLY-2026-10-07.md b/Infra-Network/HANDOFF-RENTLY-2026-10-07.md new file mode 100644 index 0000000..da99acf --- /dev/null +++ b/Infra-Network/HANDOFF-RENTLY-2026-10-07.md @@ -0,0 +1,62 @@ +# HANDOFF — Rently / RentCharge (2026-10-07) + +**Operador:** Roger · **Assistente:** Claude (sessão no laptop C:\LAPTOP\remitly-p2p) +**Objectivo:** continuar o trabalho noutra máquina sem perder contexto. +**Sem segredos neste ficheiro** — chaves SSH e passwords ficam fora do vault. + +Detalhe completo da sessão: [[SPEC-SESSION-2026-10-06]]. + +--- + +## 1. Onde está tudo (VM500 · `ssh vm500` via big-myvexx/Tailscale) + +| Ambiente | Onde | URL | +|----------|------|-----| +| **PRD** | Docker `rently-prod` · compose `/home/mini/rently-prod/docker-compose.prod.yml` · Postgres `rently-prod-db-1` · :8000/:3000 | https://rently.myvexx.com | +| **TEST** | Docker `rently-test` · compose `/home/mini/rentcharge-test/docker/docker-compose.test.yml` · Postgres `rently-test-db-1` · :8010/:3010 | https://rently-test.myvexx.com | +| **Código** | `/home/mini/rentcharge` · Forgejo `myvexx/rently` · `main` = o que corre em PRD | git.itecnologys.com/myvexx/rently | +| **Backups** | `/home/mini/rently-backups/` (pg_dump antes de cada deploy) | — | + +- `/home/mini/rentcharge` (systemd SQLite) é a instalação **antiga e inactiva** — não é PRD. +- Fonte usada para gerar imagens TEST/PRD: `/home/mini/rentcharge-test/{backend,frontend}`; contexto backend `docker/build/backend-ctx/app`. +- Push para Forgejo a partir da VM já funciona sem prompt (credential store do utilizador `mini`). + +## 2. Regras de trabalho (Roger) + +1. Alterar **só em TEST**; Roger testa; **PRD só com "pode aplicar na PRD"**. +2. Antes de PRD: backup Postgres, tag `:pre-` das imagens, paragem ~1 min. +3. Entregar a funcionalidade a funcionar (não planos). UI nova reutiliza o design existente (ex.: modal Credit settlement). +4. Se pedido, congelar utilizador durante correcções (`is_active=false` + revogar sessões) e reactivar logo a seguir. + +## 3. Feito em 2026-10-06/07 (em PRD) + +| Commit | O quê | +|--------|-------| +| `ffa801f` | Balance Import + Credit Payout (modal "Credit Book balance") | +| `985c5b4` | Payout v2: créditos em aberto, uso parcial, encontro de contas automático, tabela `credit_payout_allocations` | +| `9be3065` | Repo sincronizado com o código que corre em PRD (+ `docker/`) | +| `3ea7a34` | Credit Book: payouts em todas as vistas (`credit_book_delta`); HO Remittance report já não rebenta com adjustment/payout | + +- Conta da casa **SA-FAC "Facilities - Salvation Army"** (id 211, sem renda, BANK_ACCOUNT) para Cash sales **DONATION** / **LAUNDRY_TILL**. Não usar quarto "SA" (é o balde do Staff Credit Book, id 209). + +## 4. Pendente + +- [ ] **Regras Closing Till / Cycle Start** — Roger enviou o bloco 1 e pediu para **aguardar o próximo bloco** antes de mexer: + - todo o **Save statement** diário deve aparecer em *Week EOD files (Cycle Start)* e nunca ficar imutável; + - quinta-feira, **Save EOD for Closing Till** marca a hora e separa antes/depois do corte; + - o Cycle Start lista todos os dias + after-cut da semana anterior + before-cut do dia actual. + - Dúvidas em aberto: vários saves no mesmo dia; imutabilidade depois do Freeze; save depois do corte; segundo clique na mesma quinta. + - Hoje em PRD: regra `2026-10-01-r1`; after-cut **EOD-20261001-37722C (€129)** aparece "used · immutable"; dias 02–06/10 gravados com `for_eow=0` não aparecem. + - `.cursor/rules/eow-cycle-start-rules.mdc` contradiz `SPEC-CLOSING-TILL-FREEZE-ARCHIVE.md`. +- [ ] Branch `wip/closing-till-after-cut-011` (trabalho de terceiros, não publicado): corrigir risco de libertar after-cut já usado noutro freeze antes de publicar. +- [ ] **Segurança:** trocar passwords que apareceram em chat/ficheiros (conta Forgejo, root/mini das VMs, comentários em `~/.ssh/config`, `docs/HANDOFF-VM500-RENTLY-ACCESS.md`, `ACCESS-CT130-OBSIDIAN.md`). Deploy key `vm500-rently-deploy` sem uso (SSH do Forgejo inacessível). + +## 5. Retomar noutra máquina + +1. Instalar Claude desktop (mesma conta) e **Tailscale** (rede itecnologys). +2. Copiar por pendrive (nunca por email/chat), **para os mesmos caminhos**: + - `C:\Users\roger\.ssh\` (config + chaves `big_myvexx_id_rsa`, `vm500_rentcharge`, …) + - `C:\Users\roger\.claude\projects\C--LAPTOP-remitly-p2p\` (memória + histórico) + - `C:\LAPTOP\remitly-p2p\` +3. Testar `ssh vm500 hostname` → `PROJETOS`. +4. Abrir o Claude em `C:\LAPTOP\remitly-p2p` e dizer "continuar o Rently — ler HANDOFF-RENTLY-2026-10-07". diff --git a/Infra-Network/SPEC-SESSION-2026-10-06.md b/Infra-Network/SPEC-SESSION-2026-10-06.md new file mode 100644 index 0000000..35bb5bc --- /dev/null +++ b/Infra-Network/SPEC-SESSION-2026-10-06.md @@ -0,0 +1,235 @@ +# SPEC-SESSION — 2026-10-06 Rently (Balance Import + Credit Payout · reconstrução TEST2 · incidente de login) + +**Operador:** Roger +**Executor:** Claude (assistente) +**Ambiente:** VM500 — **apenas TEST** (`/home/mini/rentcharge-test`, :3010 / :8010, `https://rently-test.myvexx.com`) +**PRD:** não alterado. Ficheiros de PRD foram apenas **lidos/copiados**. +**Relacionados:** `SPEC-ENV-TEST-PROD.md` · `AUTH-USERS-SPEC.md` · `SPEC-IMPORTED-BALANCE.md` · `SPEC-ACCOUNT-RECEIVABLES.md` + +--- + +## 1. Objectivo da sessão + +Entregar em TEST, para validação antes de qualquer rollout a PRD: + +1. **Balance Import** — importar saldo credor de abertura (data retroactiva permitida), sem impacto em till / EOD / EOW. `channel=adjustment`, conta `BAL_IMPORT`, txn `ADJ-AAAAMMDD-…` + `txn_hash` (16 chars). +2. **Credit Payout** — residente levanta crédito do till; aparece no EOD como cash-out. `channel=credit_payout`, txn `CP-AAAAMMDD-…`. +3. Modais na página **Account Receivables** (`/receivables`): botões **📥 Balance Import** e **💰 Credit Payout**. + +--- + +## 2. Cronologia resumida + +| # | Evento | Resultado | +|---|--------|-----------| +| 1 | Backend + modais implementados no TEST antigo | Frontend TEST instável (porta, build, 502) | +| 2 | Decisão do operador: destruir TEST, recriar **TEST2** como cópia de PRD, reaplicar só o código novo | Código guardado em `/tmp/backup-codigo/` | +| 3 | `rm -rf /home/mini/rentcharge-test` + `cp -r /home/mini/rentcharge /home/mini/rentcharge-test` | **Config do TEST antigo perdida** (não estava em backup) | +| 4 | Backend não arrancava: `Failed to load environment files` | `config/rentcharge-test.env` copiado de PRD `config/` | +| 5 | Frontend não arrancava: `EADDRINUSE :3000`, `node: No such file or directory`, sem `.next`, dependências em falta | Corrigido (ver §4) | +| 6 | Login TEST2 falha: `Unauthorized` e depois `Too many attempts` em todos os utilizadores | Várias tentativas erradas (ver §3) | +| 7 | Causa real encontrada: DB errada + utilizador inexistente + rate limit em DB | Login OK (HTTP 200) | +| 8 | Login OK mas o browser voltava ao ecrã de login | Causa: nome do cookie de sessão diferente entre backend e frontend → corrigido | +| 9 | Operador confirma login correcto | ✅ | + +--- + +## 3. Incidente de login — causas raiz + +### 3.1 A DB que o TEST usa não era a DB que estava a ser alterada + +- `config/rentcharge-test.env` define: + `DATABASE_URL=sqlite:////home/mini/rentcharge/backend/data/arrears-test.db` + (a DB de teste vivia **dentro da pasta de PRD**). +- As alterações de password foram feitas em `/home/mini/rentcharge-test/backend/data/arrears.db`, que é **uma cópia da DB de PRD** que o processo TEST **nunca abre**. +- Verificação correcta (a fazer **sempre** antes de mexer em dados): + ```bash + PID=$(systemctl show -p MainPID --value rentcharge-test-backend) + tr '\0' '\n' < /proc/$PID/environ | grep DATABASE_URL + ls -l /proc/$PID/fd | grep '\.db' + ``` + +### 3.2 O utilizador `rodger` não existia na DB de teste + +- `arrears-test.db` (datada de 2026-09-21) só tinha `admin`, `teresa`, `natalie`. +- Qualquer password dava `401 Incorrect username or password` → UI mostra **Unauthorized**. + +### 3.3 "Too many attempts" é guardado em DB, por IP — reiniciar não limpa + +- `app/modules/users/service.py` → `enforce_rate_limit()` conta linhas em **`auth_events`** (`login_failed`, `login_locked`) nos últimos 15 min, por **IP do cliente OU actor**; limite 8 → HTTP 429. +- Por ser por IP, bloqueou também utilizadores nunca tentados (ex.: `teresa`). +- Reiniciar o backend **não tem efeito**. Limpar `users.failed_login_count/locked_until` também não chega. +- Opções correctas: esperar 15 min, ou (só em TEST) apagar os `auth_events` de falha. + +### 3.4 Hashes de password — tem de ser bcrypt + +- `app/auth.py`: `hash_password()` = `bcrypt.hashpw(..., gensalt(rounds=12))`; `verify_password()` = `bcrypt.checkpw`. +- Uma tentativa usou formato `pbkdf2:sha256:…` (Werkzeug) → nunca valida neste sistema. +- Werkzeug não está instalado nem é usado. + +### 3.5 Login OK mas sessão ignorada — nome do cookie + +- Backend TEST (env): `SESSION_COOKIE_NAME=rentcharge_test_session` (conforme `SPEC-ENV-TEST-PROD.md` §4). +- Frontend copiado de PRD: `frontend/src/middleware.ts:5` tem **fixo** `const SESSION_COOKIE = "rentcharge_session";` +- Resultado: `POST /api/auth/login-json` → 200 com cookie, mas o middleware não encontra o cookie esperado e redirecciona para `/login`. +- Nota: o TEST antigo funcionava porque o seu frontend não era uma cópia literal do de PRD. Essa diferença perdeu-se no passo 3. + +--- + +## 4. Correcções aplicadas (só TEST2) + +| Área | Alteração | +|------|-----------| +| DB | `arrears-test.db` copiada (SQLite backup API, origem aberta **read-only**) para `/home/mini/rentcharge-test/backend/data/arrears-test.db` | +| Env | `DATABASE_URL=sqlite:////home/mini/rentcharge-test/backend/data/arrears-test.db` — TEST2 deixa de escrever na pasta de PRD | +| Env | `SESSION_COOKIE_NAME=rentcharge_session` (ver §5 — desvio) | +| Env backup | `config/rentcharge-test.env.bak` (estado antes destas duas mudanças) | +| Utilizadores | `rodger` criado na DB TEST2 (id 4, Roger F, `sysadmin`, perfil copiado da cópia de PRD em `rentcharge-test/backend/data/arrears.db`), password bcrypt-12 definida pelo operador | +| Rate limit | 16 linhas `auth_events` (`login_failed`/`login_locked`) apagadas na DB TEST2 | +| Permissões | `chown -R mini:mini /home/mini/rentcharge-test` (o `cp -r` como root deixou tudo root; serviço corre como `mini`) | +| Frontend | `npm install` (faltavam `@tabler/icons-react`, `lucide-react`); `npm run build` | +| Frontend systemd | `ExecStart=/home/mini/rentcharge-test/frontend/start.sh` (wrapper com `PATH=/home/admin/node/bin` e `PORT=3010`). Backup: `/etc/systemd/system/rentcharge-test-frontend.service.bak` | +| Código novo | `backend/app/services/ledger.py`, `backend/app/modules/ledger/router.py`, `frontend/src/components/BalanceImportPayoutModals.tsx`, `frontend/src/lib/api.ts`, `frontend/src/app/receivables/page.tsx` (backup `page.tsx.bak`) | + +Validação: `POST /api/auth/login-json` (rodger) → **200** com `Set-Cookie: rentcharge_session=…; HttpOnly; Secure; SameSite=strict`; login no browser confirmado pelo operador. + +--- + +## 5. Desvios à SPEC e riscos conhecidos + +1. **Cookie de sessão** — TEST2 usa `rentcharge_session` (igual a PRD), contra a tabela de `SPEC-ENV-TEST-PROD.md` §4. O cookie não tem `Domain` (host-only em `rently-test.myvexx.com`), por isso **não colide** com PRD (`rently.myvexx.com`). Mesmo assim é um desvio. + **Correcção definitiva:** pôr o nome do cookie em `middleware.ts` a ler variável de ambiente e voltar a `rentcharge_test_session` no TEST. +2. **Dados de teste antigos** — `arrears-test.db` é de 2026-09-21 e muito menor que PRD. Os residentes e saldos podem não corresponder ao que se vê em PRD. +3. **Ficheiro não usado com hashes alterados** — em `/home/mini/rentcharge-test/backend/data/arrears.db` (cópia de PRD, **não usada** pelo TEST2), as passwords de `admin`, `teresa` e `rodger` foram alteradas durante as tentativas. Não tem efeito em PRD nem no TEST2. Pode ser apagado ou ignorado. +4. **Unit file do frontend TEST** foi alterado (wrapper `start.sh`). Rever se deve passar para o formato padrão do projecto. +5. **Config do TEST antigo perdida** — não existe cópia do `.env` e do frontend do TEST anterior. + +--- + +## 6. Lições / regras para próximas sessões + +1. **Antes de destruir um ambiente:** backup completo de `config/`, ficheiros `.env*`, unit files systemd e DB (`tar` da pasta inteira). +2. **Antes de alterar dados:** confirmar no **processo em execução** qual a `DATABASE_URL` e que `.db` está aberta (§3.1). Não assumir pelo nome da pasta. +3. **Passwords:** usar sempre `app.auth.hash_password()` (bcrypt-12). Nunca outro formato. +4. **Rate limit de login:** está em `auth_events`, por IP. Restart não limpa. +5. **Após copiar PRD → TEST:** rever tudo o que difere por ambiente: DB, `SECRET_KEY`, cookie (backend **e** `middleware.ts`), portas, `APP_PUBLIC_URL`, `node_modules`/build. +6. **Diagnóstico primeiro:** ler logs do backend (`journalctl -u rentcharge-test-backend`) e o código do módulo antes de tentar correcções às cegas. + +--- + +## 7. Pendente + +- [ ] Operador testar **Balance Import** (incluindo data retroactiva) e **Credit Payout** em `/receivables`. +- [ ] Validar `ADJ-…` / `CP-…` + `txn_hash`, saldo disponível, e EOD (import fora do till; payout como cash-out). +- [ ] Cookie: tornar `middleware.ts` configurável e repor `rentcharge_test_session` no TEST (§5.1). +- [ ] Decidir se a DB TEST2 deve ser refrescada a partir de PRD (cópia anonimizada / regras da `SPEC-ENV-TEST-PROD.md`). +- [ ] **Sem rollout para PRD** até sign-off do operador. + +--- + +## 8. Correcção posterior — TEST voltou a ser container Docker (2026-10-06 ~19:00 UTC) + +### 8.1 O que estava errado na reconstrução TEST2 (§2–§4) + +- O TEST oficial **era** o stack Docker `rently-test` (Postgres `rently-test-db-1`, backend :8010/:8011, frontend :3010/:3011), igual ao PRD (`/home/mini/rently-prod`, Postgres). +- `/home/mini/rentcharge` é a instalação **antiga em SQLite** (serviço systemd PRD inactivo). Copiar essa pasta não é "copiar PRD". +- O `rm -rf /home/mini/rentcharge-test` apagou `docker/` (compose, Dockerfiles) do TEST oficial. Os containers TEST ficaram em loop / Created desde 16:25 UTC; o systemd TEST2 ocupou as portas 3010/8010. +- A DB SQLite de teste não tinha residentes → busca de residente vazia nos modais. + +### 8.2 Reconstrução feita (PRD apenas lido) + +| Passo | Detalhe | +|-------|---------| +| systemd TEST2 | `rentcharge-test-backend` / `rentcharge-test-frontend` **parados** (já estavam disabled). Pasta SQLite fica sem uso. | +| Compose | `/home/mini/rentcharge-test/docker/docker-compose.test.yml` recriado a partir da config dos containers sobreviventes (mesmas portas, rede, volume `rently-test_rently_test_pgdata`). Segredos em `docker/.env` (600), copiados do container TEST antigo. | +| Backend image | `docker/backend.Dockerfile`: `FROM rently-prod-backend:latest` + `COPY app`. Contexto `docker/build/backend-ctx` = código da imagem PRD + **só** `services/ledger.py`, `modules/ledger/router.py` e 4 linhas `credit_payout` em `services/eod_report.py`. | +| Frontend image | `docker/frontend.Dockerfile` (Next standalone, node:22-alpine). Contexto = `rentcharge-test/frontend` (fonte igual à usada no build PRD de 05/10 23:34 + `CreditBookToolsModal`). | +| Rollback imagens | `rently-test-backend:pre-20261006`, `rently-test-frontend:pre-20261006` | +| Backup TEST PG | `/home/mini/rently-backups/rently-test-pre-prd-restore-20261006T184000Z.dump` (+ .sha256, 30 tabelas) | +| Dados | `pg_dump` PRD (read-only) → `/home/mini/rently-backups/rently-prod-for-test-20261006T184113Z.dump` → DB `rently` de TEST recriada e restaurada. 206 residentes, D48 = id 73. | +| Login | `rodger` no PG de TEST com password definida pelo operador (bcrypt via `app.auth.hash_password`). Cookie `rentcharge_session` (default do backend Docker, igual ao middleware). | +| Verificação | `https://rently-test.myvexx.com/api/health` → env=test; login 200; `balance-available` D48 → 200 (0.00). | + +### 8.3 Achados a rever pelo operador + +- `/home/mini/rentcharge` (fonte PRD) tem alterações **não commitadas de outra pessoa/agente** hoje: `eod_report.py` (closing till split / after-cut) e `eow_report.py` (CYCLE_START_RULES 2026-10-06-r1). Não levadas para TEST. +- Em `/home/mini/rentcharge/backend/app/services/` ficaram `ledger.py.backup` e `ledger.py.bak-20261006_164242` (meus) e `ledger.py` com permissão 666. Conteúdo de `ledger.py` sem código da feature. +- Backend PRD reiniciou 1× às 16:06 UTC logo após um `POST /balance-import` 404 contra a porta PRD (teste da sessão). Sem escrita de dados; imagem PRD inalterada. +- `/home/mini/rently-pg-stage/docker-compose.dev.yml` alterado às 17:43 com `.bak-prerevert` — não foi esta sessão. +- O compose/Dockerfiles de TEST **nunca estiveram em git**. Recomendação: commitar `docker/` (sem `.env`) no Forgejo. + +### 8.4 Pendente (substitui §7) + +- [ ] Operador testar Balance Import + Credit Payout em `https://rently-test.myvexx.com/receivables` (dados PRD de 06/10). +- [ ] Validar EOD (payout como cash-out, import fora do till) em TEST. +- [ ] Commitar `docker/` de TEST no Forgejo. +- [ ] **Sem rollout PRD** até sign-off. + +--- + +## 9. Rollout PRD — 2026-10-06 19:24 UTC (aprovado pelo operador após teste em TEST) + +| Item | Detalhe | +|------|---------| +| Backup PRD (antes) | `/home/mini/rently-backups/rently-prod-pre-creditbook-20261006T191601Z.dump` (+ .sha256, 30 tabelas) | +| Backend | `rently-prod-backend:20261006-creditbook` = **mesma imagem testada em TEST** (id 5b5e22c0…), base PRD ddc7479e… + 3 ficheiros | +| Frontend | `rently-prod-frontend:20261006-creditbook` (build `NEXT_PUBLIC_APP_ENV=prod`, mesma fonte testada) | +| Rollback | imagens `rently-prod-backend:pre-20261006` / `rently-prod-frontend:pre-20261006` → `docker tag … :latest` + `docker compose -f /home/mini/rently-prod/docker-compose.prod.yml up -d --no-deps --force-recreate backend frontend` | +| Deploy | `docker compose … up -d --no-deps --force-recreate backend frontend` — DB PRD não tocada. Paragem ≈ 36 s (19:24:24 → 19:25:00). | +| Verificação | health env=prod; `/login` 200 local e público; `balance-available` sem sessão → 401 (rota existe); 0 erros nos logs; 0 restarts. | +| Git | commit local `ffa801f` em `/home/mini/rentcharge` (7 ficheiros testados). **Push Forgejo pendente** — VM sem credenciais. `eod_report.py` em disco mantém o trabalho after-cut de terceiros (cópia: `/home/mini/rently-backups/eod_report.py.wip-terceiros-20261006`). | + +--- + +## 10. Credit payout v2 — créditos em aberto + encontro de contas (PRD 2026-10-06 21:38 UTC) + +Regra (Roger): payout lista créditos a favor em aberto — balance imports, over-settlements, credit adjustments — com selecção e uso parcial; credit sales em aberto são abatidas automaticamente (sem till); só o líquido sai do till. Um CP único; vínculos em `credit_payout_allocations` (tabela nova, criada por `create_all`). + +| Item | Detalhe | +|------|---------| +| Backend | `ledger.open_credit_lines()` (replay FIFO), `available_balance_for_payout()` = crédito líquido do Credit Book; `POST /api/ledger/credit-payout` aceita `allocations`; `GET /api/ledger/residents/{id}/open-credits` | +| Frontend | `CreditBookToolsModal`: tabela Open credits, Amount paid out editável (distribui pelos créditos marcados), Use € por crédito | +| Testes | 15/15 `tests/test_balance_import_payout.py` | +| TEST | validado pelo operador (A06 Anna M, CP-20261006-D3E19C €50 de ADJ-20260930-FBA6D9) | +| Backup PRD | `/home/mini/rently-backups/rently-prod-pre-creditbook2-20261006T213509Z.dump` | +| Imagens | `rently-prod-*:20261006-creditbook2`; rollback `rently-prod-*:pre-20261006b` | +| Paragem | 21:38:29 → 21:39:23 (~54 s) | +| Git | commit local `985c5b4` (6 ficheiros). Push Forgejo pendente (sem credenciais na VM). | + +--- + +## 11. Repositório Git sincronizado com PRD (2026-10-06 ~22:30 UTC) + +### 11.1 Situação encontrada + +- `myvexx/rently` (Forgejo) parado em `bec4c90` (2026-09-26); `ligbox/rentcharge` (antigo, remote `forgejo-legacy`) em `b36c3bd` (2026-09-11). +- PRD era publicado a partir do working tree de `/home/mini/rentcharge` sem commits: 63 ficheiros de código em produção existiam só no disco da VM e nas imagens Docker. Nenhum repositório reconstruía o PRD. +- Compose/Dockerfiles do TEST nunca estiveram em git (perderam-se em §8). + +### 11.2 Commits publicados (`git push forgejo main wip/closing-till-after-cut-011`, feito pelo operador) + +| Ref | Commit | Conteúdo | +|-----|--------|----------| +| `main` | `ffa801f` | Balance Import + Credit Payout v1 | +| `main` | `985c5b4` | Credit payout v2: créditos em aberto, uso parcial, encontro de contas, `credit_payout_allocations`, 15 testes | +| `main` | `9be3065` | Retrato do PRD: backend = código da imagem PRD em execução (`e55732d9`, 55 ficheiros, incl. `jobs/`, `previous_day_till`, `weekly_rent_status`); frontend = fonte do build PRD + `package-lock.json`; `docker/` (compose + Dockerfiles TEST, cópia do compose PRD sem segredos); specs em vigor | +| `wip/closing-till-after-cut-011` | `6f7bf31` | Trabalho after-cut 011.2026 de terceiros, **tal como estava, NÃO publicado em PRD** (`eod_report`, `eow_report`, `sage_import`, template, teste cycle-start, VERSION 011.2026, docs). Rever e testar em TEST antes de merge. | + +Regra seguida: `main` = o que corre em PRD. O working tree da VM não foi alterado (commits feitos por index/`commit-tree`); o WIP continua no disco. + +### 11.3 Fora do git de propósito + +- `docs/HANDOFF-VM500-RENTLY-ACCESS.md` — contém password da VM em texto. +- `config/*.env` (segredos), `backups/`, `backend/_check_a06*.py` (diagnóstico). + +### 11.4 Acesso ao Forgejo + +- VM sem credenciais HTTPS guardadas; push feito pelo operador com a sua conta. +- SSH do Forgejo inacessível a partir da VM (porta 22 e alternativas: timeout). Deploy key `vm500-rently-deploy` (Read/Write) criada mas sem uso enquanto o SSH não estiver disponível; chave privada em `/home/mini/.ssh/id_ed25519_forgejo_rently`. + +### 11.5 Segurança — acções recomendadas ao operador + +- [ ] Trocar a password da conta Forgejo usada hoje (foi exposta em captura de ecrã na sessão). +- [ ] Trocar a password root/mini da VM se for a mesma, e retirá-la de `docs/HANDOFF-VM500-RENTLY-ACCESS.md`. +- [ ] Decidir: remover a deploy key ou habilitar SSH no Forgejo. +- [ ] Arquivar `ligbox/rentcharge` (desactualizado).