feat(#45): Pricing: raise delivered-issue rate to $5.00 (rate_minor 500) #46

Merged
pbwraith merged 1 commits from issue-45 into main 2026-09-03 11:05:29 +02:00
Owner

Closes #45

Summary

Owner pricing decision (2026-09-01): the delivered-issue rate is now $5.00 (rate_minor 500) for both gold and standard; free stays 0. Defaults-only change:

  • gitea_saas/config.py: DEFAULT_TIERS gold/standard rate_minor 100/25 -> 500/500; auto_merge untouched.
  • gitea_saas/delivery.py: mirror DEFAULT_TIERS 100/25 -> 500/500, and the SAAS_RATE_MINOR fallback (DEFAULT_RATE_MINOR) 100 -> 500 so the per-delivery default matches the new rate everywhere.
  • SAAS_TIERS_JSON override path unchanged (still merges over defaults and wins).

Acceptance coverage

  1. Defaults 500/500/0 asserted by literal value (new test_default_tier_rates_are_500_500_0, plus existing behavior tests updated to 500).
  2. SAAS_TIERS_JSON override still wins — covered by test_rate_from_tier_config_override and test_load_review_config_merges_saas_tiers_json (already asserted gold 500 via env).
  3. One delivery = one 500-unit debit; a replay = no second debit. Already covered by test_merge_webhook_one_debit_at_tier_rate_with_receipt (exactly one 500-unit debit, idempotency key deliver:<repo>:<pr>:<head_sha> = repo + issue number + merge sha) and test_duplicate_webhook_no_second_debit_no_second_comment / test_gold_double_delivery_never_double_debits (replayed -> still exactly one debit row). Per the issue: invariant was already covered, so nothing added beyond updating the expected amounts.
  4. Full suite: 236 passed, 1 skipped.

Test evidence

python3 -m pytest tests/ -q
236 passed, 1 skipped in 34.52s

git diff --check clean.

Closes #45 ## Summary Owner pricing decision (2026-09-01): the delivered-issue rate is now **$5.00** (rate_minor `500`) for both `gold` and `standard`; `free` stays `0`. Defaults-only change: - `gitea_saas/config.py`: `DEFAULT_TIERS` gold/standard `rate_minor` 100/25 -> 500/500; `auto_merge` untouched. - `gitea_saas/delivery.py`: mirror `DEFAULT_TIERS` 100/25 -> 500/500, and the `SAAS_RATE_MINOR` fallback (`DEFAULT_RATE_MINOR`) 100 -> 500 so the per-delivery default matches the new rate everywhere. - `SAAS_TIERS_JSON` override path unchanged (still merges over defaults and wins). ## Acceptance coverage 1. Defaults 500/500/0 asserted by literal value (new `test_default_tier_rates_are_500_500_0`, plus existing behavior tests updated to 500). 2. `SAAS_TIERS_JSON` override still wins — covered by `test_rate_from_tier_config_override` and `test_load_review_config_merges_saas_tiers_json` (already asserted gold 500 via env). 3. One delivery = one 500-unit debit; a replay = no second debit. Already covered by `test_merge_webhook_one_debit_at_tier_rate_with_receipt` (exactly one 500-unit debit, idempotency key `deliver:<repo>:<pr>:<head_sha>` = repo + issue number + merge sha) and `test_duplicate_webhook_no_second_debit_no_second_comment` / `test_gold_double_delivery_never_double_debits` (replayed -> still exactly one debit row). Per the issue: invariant was already covered, so nothing added beyond updating the expected amounts. 4. Full suite: `236 passed, 1 skipped`. ## Test evidence ``` python3 -m pytest tests/ -q 236 passed, 1 skipped in 34.52s ``` `git diff --check` clean.
pbwraith added 1 commit 2026-09-01 13:14:23 +02:00
Owner pricing decision 2026-09-01: gold and standard now default to
rate_minor 500 ($5.00) per delivered issue; free stays 0. Defaults
only — SAAS_TIERS_JSON overrides still win, auto_merge untouched.

Also align the SAAS_RATE_MINOR fallback (DEFAULT_RATE_MINOR) to 500 so
the per-delivery default matches the new rate everywhere.

Tests updated to the literal 500/500/0 values and the $5.00 debits;
idempotent single-debit + replay-no-double-charge coverage already
existed (deliver:<repo>:<pr>:<head_sha> key) and now asserts 500.
pbwraith added the
in-review
label 2026-09-01 13:14:40 +02:00
Author
Owner

Implemented on issue-45, pushed as PR #46 (Closes #45).

Commit e085457: gold/standard rate_minor 100/25 -> 500/500 in config.py and delivery.py; SAAS_RATE_MINOR fallback aligned to 500; free stays 0; auto_merge untouched; SAAS_TIERS_JSON override path unchanged.

Test evidence: python3 -m pytest tests/ -q -> 236 passed, 1 skipped; git diff --check clean. One delivery debits exactly 500 minor units once (test_merge_webhook_one_debit_at_tier_rate_with_receipt, idempotency key deliver:<repo>:<pr>:<head_sha> = repo + issue number + merge sha); replay does not double-charge (test_duplicate_webhook_no_second_debit_no_second_comment, test_gold_double_delivery_never_double_debits). Defaults asserted as literal 500/500/0 (test_default_tier_rates_are_500_500_0).

Implemented on `issue-45`, pushed as PR #46 (Closes #45). Commit `e085457`: gold/standard `rate_minor` 100/25 -> 500/500 in `config.py` and `delivery.py`; `SAAS_RATE_MINOR` fallback aligned to 500; `free` stays 0; `auto_merge` untouched; `SAAS_TIERS_JSON` override path unchanged. Test evidence: `python3 -m pytest tests/ -q` -> 236 passed, 1 skipped; `git diff --check` clean. One delivery debits exactly 500 minor units once (`test_merge_webhook_one_debit_at_tier_rate_with_receipt`, idempotency key `deliver:<repo>:<pr>:<head_sha>` = repo + issue number + merge sha); replay does not double-charge (`test_duplicate_webhook_no_second_debit_no_second_comment`, `test_gold_double_delivery_never_double_debits`). Defaults asserted as literal 500/500/0 (`test_default_tier_rates_are_500_500_0`).
Author
Owner

Held — main is red, and it is not this PR's fault

Gated against the real merge result. The comparison that matters:

tree pytest
origin/main @ 71cc263 (no PR) 10 failed, 225 passed
main + this PR 10 failed, 226 passed

The same 10 failures, and this PR adds 1 passing tests and zero new
failures.
Every failure is in tests/test_review_workspace.py /
tests/test_reviewer.py — files this PR does not touch.

So this is not a bounce and nothing is being asked of you. The work is good; it
is queued behind a pre-existing defect filed as #48: on Windows the shell
eats the ^ in git rev-parse --verify <sha>^{commit}, so ReviewWorkspace
cannot build a synthetic merge on the review box at all.

I will not merge onto a red main — with the baseline broken there is no way to
tell a genuine regression from the existing noise, which is exactly how
botmanager shipped a broken master last week. Once #48 is green I will
re-gate and merge.

## Held — `main` is red, and it is not this PR's fault Gated against the real merge result. The comparison that matters: | tree | pytest | |---|---| | `origin/main` @ `71cc263` (**no PR**) | **10 failed**, 225 passed | | `main` + this PR | **10 failed**, 226 passed | **The same 10 failures, and this PR adds 1 passing tests and zero new failures.** Every failure is in `tests/test_review_workspace.py` / `tests/test_reviewer.py` — files this PR does not touch. So this is not a bounce and nothing is being asked of you. The work is good; it is queued behind a pre-existing defect filed as #48: on Windows the shell eats the `^` in `git rev-parse --verify <sha>^{commit}`, so `ReviewWorkspace` cannot build a synthetic merge on the review box at all. I will not merge onto a red `main` — with the baseline broken there is no way to tell a genuine regression from the existing noise, which is exactly how botmanager shipped a broken `master` last week. Once #48 is green I will re-gate and merge.
Author
Owner

Merged — verified against green main

237 passed, 1 skipped, 0 failed; main after !49 is 236 passed. 0 conflicts, confirmed with a real git merge after Gitea briefly reported this unmergeable — that was stale metadata from main moving, not a genuine conflict.

This PR was held, never bounced: it was queued behind the Windows caret defect (#48). Owner pricing decision. auto_merge deliberately untouched — that flag does not move until #42 produces a measured false-approve rate.

## Merged — verified against green `main` **237 passed, 1 skipped, 0 failed**; `main` after !49 is 236 passed. **0 conflicts**, confirmed with a real `git merge` after Gitea briefly reported this unmergeable — that was stale metadata from `main` moving, not a genuine conflict. This PR was *held*, never bounced: it was queued behind the Windows caret defect (#48). Owner pricing decision. `auto_merge` deliberately untouched — that flag does not move until #42 produces a measured false-approve rate.
pbwraith merged commit 9da95125f6 into main 2026-09-03 11:05:29 +02:00
pbwraith removed the
in-review
label 2026-09-03 11:05:31 +02:00
Sign in to join this conversation.
No reviewers
No Milestone
No project
No Assignees
1 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: pbwraith/gitea-saas-core#46
No description provided.