Files
fuj-management/docs/plans/2026-10-08-1026-pre-feature-cleanup-tasks.md
T
kacerrandClaude Opus 5.5 2c2db60fe7 feat(go): scheduled bank sync (Go only)
The Go server now runs sync -> infer -> flush-cache by itself at the
times in SYNC_SCHEDULE (comma-separated HH:MM, default 04:00, "off"
disables), read in SYNC_TZ (default Europe/Prague). Nothing runs at
startup; an invalid value stops the server with an error.

- internal/scheduler: time-of-day parsing, Next, and the run loop
- banksync.Runner: one lock shared by /sync-bank and the scheduler so
  runs never overlap, plus the status of the last run
- footer shows the last sync since start and the next scheduled run
- binary embeds time/tzdata because the Alpine image has no zone data

Deliberately not implemented in the legacy Python app, which is being
phased out; recorded in CLAUDE.md under "Deliberately Go-only features".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 12:17:15 +02:00

8.9 KiB
Raw Blame History

Pre-feature cleanup — task list

Findings from a full repo audit on 2026-10-08, written up as tasks to clear before new feature work starts. Companion to the Go rewrite tracker, 2026-05-03-2349-go-backend-rewrite-progress.md.

State at audit time

  • Two full implementations live side by side: Flask (app.py, scripts/, templates/) and Go (go/). Recent changes were made in both.
  • Update 2026-10-08: the Python code was moved to legacy/ after this audit. Python paths below are relative to legacy/ (build/Dockerfile is now legacy/build/Dockerfile).
  • Python tests pass (32 tests). Go unit tests and the parity suite pass. Go lint could not run (see T7).
  • The gitops workflow bumps the cluster deployment to the -go image, so Go appears to be what is deployed. This was not verified against the cluster.
  • CLAUDE.md and all docs outside docs/plans/ describe a Python-only project. The rewrite tracker stops at M6; M7 and M8 are untouched.

How to use

  • Tick a checkbox when the task's PR or commit lands and append the SHA.
  • Tasks in "Fix first" are small and independent of each other and of the cutover decision. Do them in any order.
  • T5 is a decision. Several cleanup tasks become unnecessary once it is made; they are marked "moot if Python is retired".

Fix first

  • T1 Remove the secret leak in .gitea/workflows/kubernetes-deploy.yaml. Workflow deleted on 2026-10-08. Still open for the owner: rotate the credentials and remove the now-unused repo secrets (see below).
    • It runs on every push to every branch and deploys nothing.
    • It echoes the raw Vault login response, the Kanidm token response and the OIDC token response body to the log, and dumps the environment twice.
    • It uses --insecure-skip-tls-verify=true.
    • Delete or disable the workflow. Rotate the Vault AppRole secret and the Kanidm API token if anyone else can read the CI logs.
    • After deletion the repo secrets VAULT_ROLE_ID, VAULT_SECRET_ID and K8S_CA_CERT are unused and can be removed. Old job logs still contain the leaked tokens until they are deleted or expire.
  • T2 Confirm the fee rates for 2026-09 onward. Done 2026-10-08: adult default 600, 2026-07/08 at 0, 2026-09 to 2026-12 at 600. Junior rates were not changed.
    • ADULT_FEE_MONTHLY_RATE ends at 2026-08 in scripts/attendance.py and go/internal/domain/fees/fees.go.
    • September and October 2026 are billed at the defaults: 700 CZK adults, 500 CZK juniors.
    • If those are not the intended rates, add the months in both files.
  • T3 Done 2026-10-08, extended: both dashboards now sync the current year plus November–December of the previous one. Original task: remove the hardcoded 2026 window from Python /sync-bank (app.py, the sync_to_sheets call with 2026-01-01 / 2026-12-31).
    • It stops picking up transactions on 2027-01-01. Go already uses the current year.
    • Same applies to the sync-2026 Makefile target.
    • Moot if Python is retired before then.
  • T4 Remove member names from tracked files (PII rule in CLAUDE.md).
    • CHANGELOG.md line 29 names a member in a fix description.
    • tests/test_match_payments.py, tests/test_reconcile_exceptions.py and go/internal/domain/reconcile/reconcile_test.go use names that may be real. Check them and replace with obviously fictional ones.
    • Three files in docs/plans/ contain the same names: 2026-05-05-1717-payment-person-name-canonicalization.md, 2026-05-06-1626-infer-payments-junior-roster.md, 2026-05-11-2353-fill-first-multi-month-allocation.md.
    • The parity fixtures under go/tests/fixtures/ are scrubbed and need no change.
    • Decide whether the names also need removing from git history.

Decide before new features

  • T5 Decide how to finish the Python → Go cutover (M7 and M8 in the rewrite tracker).
    • Recommended: declare Go primary now, freeze Python, run one month-end comparison of the balance report on both sides, then delete Python.
    • Until this is done, every feature has to be written twice.
    • Confirm first that the cluster really runs the -go image.
  • T6 Add a test job to CI.
    • .gitea/workflows/build.yaml only builds images on tag push. Nothing runs tests.
    • Run go test -race ./..., the parity suite (-tags=parity) and golangci-lint on pull requests.
    • Stop building the Python image on every tag once Python is retired.
  • T7 Fix make go-lint.
    • go/.golangci.yml is in the v1 config format. golangci-lint 2.12 refuses to load it ("unsupported version of the configuration").
    • Migrate the config to v2 and pin the linter version used in CI.
  • T8 Protect the side-effectful routes.
    • Neither app has any authentication.
    • GET /sync-bank writes to the payments sheet, so a link prefetcher or crawler can trigger a sync. Change it to POST with a confirmation page, as /flush-cache already does.
    • Confirm that the ingress enforces access control, or add it in the app.
    • The Go server uses http.ListenAndServe with no read, write or idle timeouts (go/internal/web/server.go). Use an http.Server with timeouts.
  • T9 Move fee rates and merged months out of code.
    • Today a rate change needs a code change in two languages and a release.
    • Candidate: a tab in the payments sheet, read the same way as exceptions.
    • This also removes the cause of T2.

Cleanup

  • T10 Rewrite CLAUDE.md for the current state: Go commands, architecture and key modules, and which backend is primary. Done with the move of Python to legacy/.
  • T11 Collapse the documentation into one set.
    • docs/by-claude-opus/, docs/by-gemini/ and the top-level docs overlap, date from February–March 2026 and predate the Go rewrite.
    • Update docs/_sidebar.md and docs/README.md to match.
  • T12 Update the rewrite tracker.
    • M6.7 is unchecked although the changelog records it as done.
    • M7.1 and M8.4 refer to a docker-compose.yml that does not exist.
  • T13 Remove leftovers: .agent/rules.md (Antigravity config) and prompts/.
  • T14 Prune merged branches: 42 local and 44 remote branches are fully merged into main.
  • T15 Clean up .claude/settings.json.
    • It is tracked and contains absolute paths under one user's home directory and one-off commands.
    • Keep only shared, generic permissions there; move the rest to .claude/settings.local.json, which is already ignored.
  • T16 Align versions.
    • pyproject.toml says 0.10; git tags are at 0.39.
    • build/Dockerfile pip-installs unpinned packages and ignores uv.lock.
    • go.mod and go/build/Dockerfile are on Go 1.26; the local toolchain is 1.27.
    • Dependencies on both sides are a few months behind.
    • The Python items are moot if Python is retired.
  • T17 Stop the Python tests from calling live Google APIs.
    • warmup_cache() runs at import of app.py, so make test makes real Drive and Sheets read calls and needs the credentials file.
    • Moot if Python is retired.
  • T18 Set the time zone in the Go container. Partly addressed 2026-10-08: the binary now embeds the zone database and the scheduled sync uses SYNC_TZ; the "current month" logic below is still open.
    • The image has no time zone configured, so time.Now() is UTC and the "current month" flips one to two hours late at month boundaries.
    • The Python image sets Europe/Prague.
  • T19 Decide where fujarna/ lives.
    • fujarna/project.md is untracked. It is a brief for a separate tournament website and shares almost nothing with this codebase.
    • Options: its own repository, or a clearly separate Go module here.
  • T20 Add tests for the untested Go packages: cmd/fuj, internal/io/sheets, internal/io/drive, internal/config (about 590 lines in total).

Found during validation of the legacy/ move

Plan: 2026-10-08-1103-api-parity-vs-months-to-show.md.

  • T21 Go rendered numeric VS cells in exponent form (2.609767878e+09). Sheet text cells now go through sheets.CellString.
  • T22 Python /api/adults and /api/juniors did not return months_to_show. Backported; make parity reports 3/3 routes matching.
  • T23 Write VS to the payments sheet as text. Both sync implementations use USER_ENTERED, so Sheets stored VS as a number and dropped leading zeros. New rows now carry a text marker; existing rows are left as they are and are read correctly either way.

Features added since the audit

Notes & decisions

(Add entries as you go. Format: YYYY-MM-DD — short note.)