feat(billing): prompt the reconcile shim after tier_pro changes #533

Öppen
supernaut vill sammanfoga 1 incheckning från feat/billing-reconcile-trigger in i main
Ägare

What

  • billing.env.j2 renders RECONCILE_TRIGGER_URL and RECONCILE_TRIGGER_TOKEN only when vault_payments_webhook_token is non-empty. The billing service then prompts the reconcile shim after each tier_pro change, so a grant applies at once instead of on the next 5-minute tick.
  • Runbook "Billing service": one paragraph on the trigger and the vault value.
  • Refs #496.

How

  • Token: the shim role already renders payment=<token> from the same vault_payments_webhook_token (reconcile-shim.env.j2). One vault value serves both ends.
  • URL: reconcile_shim_internal_url is a reconciler role default. site.yml lists all roles in one play, so the default resolves in a --tags billing run (the forgejo role already relies on this). No copy added.
  • No Caddy route or nftables change: billing and the shim share the bitborg podman network on one host.

Tested

  • ansible-playbook site.yml --check --diff --limit bitborg-prod --tags billing,reconciler: ok=27 changed=0 failed=0 skipped=17, empty diff. Inert today: billing_enabled: false skips the role, and the token is empty.
  • The billing role is skipped there, so the template was also rendered offline with Jinja (trim_blocks): empty token gives the file as before, with no new lines. A non-empty token appends the comment and the two lines at the end.
  • pnpm format:check, pnpm mdlint, pnpm ansible:check (syntax), ansible-lint roles/billing: clean. Pre-commit hooks passed.

Operator steps

  1. Set the vault value: pnpm ansible-vault:edit, vault_payments_webhook_token: <openssl rand -hex 32>.

  2. Dry-run, then apply (shim first, so it accepts the source before billing sends it):

    cd ansible
    ansible-playbook site.yml --check --diff --limit bitborg-prod --tags reconciler,billing
    ansible-playbook site.yml --limit bitborg-prod --tags reconciler,billing
    

    Expect the shim env file to change and the shim to restart. If billing_enabled is true, expect the billing env file to change and the service to restart. Tag order does not set role order: site.yml runs billing before reconciler. Run --tags reconciler first, then --tags billing, if the order matters to you.

  3. Verify: grant a test tier_pro membership through the billing service. The shim log (podman logs bitborg-reconcile-trigger, or Loki) shows kick reason=payment. The reconciler runs within seconds, not 5 minutes.

Alerting gap

ReconcileEventPathSilent counts only [reconcile-trigger] kick lines from the web container, then expects bitborg-reconcile-kick.service to start. Kicks from the billing service are not counted, so a dead billing-to-shim path raises no alert. The 5-minute timer still applies every change. Not built here: it needs a decision on which log to count (the shim logs kick reason=<source>).

Open questions

  • Should ReconcileEventPathSilent also count kick reason=payment shim lines? Follow-up issue if yes.
  • #496 stays open until the apply lands.
## What - `billing.env.j2` renders `RECONCILE_TRIGGER_URL` and `RECONCILE_TRIGGER_TOKEN` only when `vault_payments_webhook_token` is non-empty. The billing service then prompts the reconcile shim after each `tier_pro` change, so a grant applies at once instead of on the next 5-minute tick. - Runbook "Billing service": one paragraph on the trigger and the vault value. - Refs #496. ## How - Token: the shim role already renders `payment=<token>` from the same `vault_payments_webhook_token` (`reconcile-shim.env.j2`). One vault value serves both ends. - URL: `reconcile_shim_internal_url` is a `reconciler` role default. `site.yml` lists all roles in one play, so the default resolves in a `--tags billing` run (the forgejo role already relies on this). No copy added. - No Caddy route or nftables change: billing and the shim share the `bitborg` podman network on one host. ## Tested - `ansible-playbook site.yml --check --diff --limit bitborg-prod --tags billing,reconciler`: `ok=27 changed=0 failed=0 skipped=17`, empty diff. Inert today: `billing_enabled: false` skips the role, and the token is empty. - The billing role is skipped there, so the template was also rendered offline with Jinja (`trim_blocks`): empty token gives the file as before, with no new lines. A non-empty token appends the comment and the two lines at the end. - `pnpm format:check`, `pnpm mdlint`, `pnpm ansible:check` (syntax), `ansible-lint roles/billing`: clean. Pre-commit hooks passed. ## Operator steps 1. Set the vault value: `pnpm ansible-vault:edit`, `vault_payments_webhook_token: <openssl rand -hex 32>`. 2. Dry-run, then apply (shim first, so it accepts the source before billing sends it): ```bash cd ansible ansible-playbook site.yml --check --diff --limit bitborg-prod --tags reconciler,billing ansible-playbook site.yml --limit bitborg-prod --tags reconciler,billing ``` Expect the shim env file to change and the shim to restart. If `billing_enabled` is true, expect the billing env file to change and the service to restart. Tag order does not set role order: `site.yml` runs billing before reconciler. Run `--tags reconciler` first, then `--tags billing`, if the order matters to you. 3. Verify: grant a test `tier_pro` membership through the billing service. The shim log (`podman logs bitborg-reconcile-trigger`, or Loki) shows `kick reason=payment`. The reconciler runs within seconds, not 5 minutes. ## Alerting gap `ReconcileEventPathSilent` counts only `[reconcile-trigger] kick` lines from the web container, then expects `bitborg-reconcile-kick.service` to start. Kicks from the billing service are not counted, so a dead billing-to-shim path raises no alert. The 5-minute timer still applies every change. Not built here: it needs a decision on which log to count (the shim logs `kick reason=<source>`). ## Open questions - Should `ReconcileEventPathSilent` also count `kick reason=payment` shim lines? Follow-up issue if yes. - #496 stays open until the apply lands.
supernaut lade till 1 incheckning 2026-10-03 00:10:44 +00:00
feat(billing): prompt the reconcile shim after tier_pro changes
Alla kontroller lyckades
ci / ci (pull_request) Successful in 2m4s
0c3a381451
The billing service can post to the reconcile shim so a grant applies
at once instead of on the next 5-minute tick. Render the trigger URL
and token into billing.env only when vault_payments_webhook_token is
set. The shim already accepts the payment source on the same value.
Empty token renders the file unchanged.

Refs #496
supernaut schemalade den här ändringsförfrågan för automatisk sammanfogning när alla kontroller lyckas 2026-10-03 00:11:39 +00:00
Alla kontroller lyckades
ci / ci (pull_request) Successful in 2m4s
Obligatorisk
Detaljer
den här ändringsförfrågan är blockerad eftersom den är föråldrad.
Den här grenen är föråldrad gentemot basgrenen
Du är inte behörig att sammanfoga den här ändringsförfrågan.
Visa kommandoradsinstruktioner

Checka ut

Checka ut en ny gren från din projektkatalog och testa ändringarna.
git fetch -u origin feat/billing-reconcile-trigger:feat/billing-reconcile-trigger
git switch feat/billing-reconcile-trigger
Logga in för att delta i denna konversation.
Inga granskare
Ingen milstolpe
Inget projekt
Inga tilldelade
1 deltagare
Notiser
Förfallodatum
Förfallodatumet är ogiltigt eller utanför gränserna. Använd formatet "åååå-mm-dd".

Inget förfallodatum satt.

Beroenden

Inga beroenden satta

Referens
bitborg/bitborg-infra!533
Ingen beskrivning angiven.