- Dockerfile: multi-stage (golang:1.23-alpine3.21 → distroless/static:nonroot),
CGO off, trimpath, stripped, UID/GID 65532, read-only rootfs friendly.
- deploy/signing-service/: ServiceAccount, Deployment (2 replicas, probes,
tight SecurityContext), ClusterIP Service on :8081, NetworkPolicy
(ingress from agent-trust, DNS egress), example Secret, and README with
the full dev + prod secret convention.
- .forgejo/workflows/build-images.yml: builds image on push + PR,
pushes :<git-sha> + :main to harbor.basicstack.de on main pushes only.
Clone pattern matches validate.yml (sha256 repo, manual git clone).
- README updates: service README gains Deployment section; repo README
layout now mentions services/signing-service, services/transparency-log,
deploy/, and the new workflow.
Scope matches DEV-605. OpenBao, OPA and Pocket-ID JWKS stay stubs and move
in their own follow-up subtasks; the prod secret shape is documented so
those subtasks can plug in without reshaping the Deployment.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
- services/attest-reconciler/ as its own go.mod (admin-api internal/ is not importable; shared code gets extracted when a 3rd consumer appears).
- Scheduler accepts "@every <dur>" or a bare Go duration; context-cancellation stops the loop cleanly.
- Store client defines PendingRateStore + Postgres skeleton for SELECT ... WHERE rate_change_attestation_ref IS NULL.
- Orchestrator + HTTPSigner + tlog.HTTPSubmitter mirror admin-api byte-for-byte so the TLog idempotency key collides on resubmits (kein Doppelsignieren).
- Prometheus text-format /metrics endpoint, dependency-free: attest_reconciler_dirty_rows_total, _reconciliation_attempts_total, _reconciliation_failures_total, _idempotent_noop_total.
- Tests with fake store + fake signer + fake submitter cover: happy path, already-attested rows are NOT re-signed, TLog idempotency across ticks, TLog-down failure path, pre-cancelled ctx.
- Top-level README reflects the new service; CI auto-discovers services/*/go.mod so no workflow change needed.
Co-Authored-By: Paperclip <noreply@paperclip.ing>