# attest-reconciler Periodic worker that re-signs `per_diem_rates` rows missing a `rate_change_attestation_ref`. Mirrors `admin-api`'s Signer + TLog orchestrator (ADR-0005). Leans on the Transparency Log's idempotency guarantee so re-runs land on the same `log_index` and never produce a second entry. ## Layout - `cmd/attest-reconciler/` — entry point; wires store, orchestrator, metrics, and scheduler, handles `SIGINT`/`SIGTERM`. - `internal/reconcile/` — `RunOnce` (per-tick work) and `Scheduler` (parses `@every ` or a bare Go duration and drives `RunOnce`). - `internal/attest/` — Statement, Envelope, Orchestrator, `HTTPSigner`. Byte parity with `admin-api/internal/attest`; split out until a 3rd consumer justifies a shared module (see parent issue note). - `internal/tlog/` — `HTTPSubmitter` for `POST /api/v1/log/entries`. - `internal/store/` — `PendingRateStore` interface + Postgres skeleton. - `internal/metrics/` — dependency-free Prometheus text-format exporter for `attest_reconciler_dirty_rows_total`, `attest_reconciler_reconciliation_attempts_total`, `attest_reconciler_reconciliation_failures_total`, `attest_reconciler_idempotent_noop_total`. ## Running ``` attest-reconciler \ -spec="@every 1m" \ -signer-url="https://trust.basicstack.de" \ -tlog-url="https://tlog.basicstack.de" \ -bearer="$POCKET_ID_TOKEN" \ -metrics-addr=":9090" ``` Production replaces `-bearer` with the `client_credentials` TokenSource built in DEV-602. ## Tests ``` go test ./... ``` Covers: - Pending rows get signed, logged, and attached (happy path). - Rows that already have an attestation ref are **not** re-signed (`TestReconciler_SkipsAlreadyAttestedRows`). - Re-signing the same row yields the same TLog entry (`TestReconciler_TLogIdempotencyOnReRun`) — proves "kein Doppelsignieren". - TLog failures bump the failure counter and leave the row pending. - Pre-cancelled context aborts the per-row loop. - `ParseSpec` accepts `@every` and bare durations, rejects crontab lines. - Metrics exposition format matches `# HELP` + `# TYPE` headers.