Skip to content

release: cron freshness readout + the ADR-011 commission amendment - #215

Merged
mahmutkaya merged 4 commits into
mainfrom
develop
Sep 4, 2026
Merged

mahmutkaya merged 4 commits into
mainfrom
develop

Conversation

@mahmutkaya

Copy link
Copy Markdown
Contributor

Summary

Release developmain. 4 commits. Rollout is manual — merging does not deploy sofra.

Payload

Deploy notes

Manual: on the box, compose pull sofra && up -d sofra. No migration. No new env vars.

🤖 Generated with Claude Code

mahmutkaya and others added 4 commits September 2, 2026 19:38
Release #210 merged as a merge commit, so main's tip is not on develop and the
`main-develop` ruleset's strict up-to-date rule would refuse the next release PR
before anyone read it — which is what #210 itself hit today, costing a
back-merge (#211) mid-release.

Content-clean: no main-only files, `git diff --stat origin/develop origin/main`
empty. A real merge commit, not a squash — the ancestry link is the whole point.

This changes nothing running: sofrapiwas.com still serves 663fba9. #210
publishes images only; the hand-roll that applies the partner-brand migration is
a separate decision and has not been taken.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
chore: back-merge the #210 release into develop
GitHub refused to START every scheduled job on this repo for six days in August
2026 — an Actions billing block — and nothing surfaced it. It was found because a
release coordinator happened to open the Actions tab. This is the page that would
have said so.

THE ISSUE'S PROPOSED DESIGN DOES NOT WORK, and the reason is the feature itself.
It asked for this to be derived from the audit rows the sweeps already write, with
no new write path. But a sweep only writes an audit row when it SENDS something:
`runTrialWarningSweep` returns early on `todo.length === 0` and writes nothing,
and the go-live marker is written inside the per-candidate loop.

During those six days every sweep had nothing to send anyway — the incident report
records both hand-dispatched sweeps returning `considered: 0`. So a readout built
on those rows would have looked EXACTLY THE SAME whether the crons ran or not. It
would have been green for all six days. A freshness signal that cannot tell "ran
and found nothing" from "never ran" is not a freshness signal.

So each sweep now records a heartbeat on EVERY run, whatever it found. It goes in
`AuditLog`, which already exists — no schema change, and therefore no Prisma
migration against the database holding partner, billing and CRM records, which is
an owner decision this should not quietly make.

`never` is its own status rather than a very large age: "no heartbeat ever" and "a
heartbeat six days old" send a reader to different places.

Each sweep is held to ITS OWN budget, roughly two-and-a-bit missed runs — 2h for
the quarter-hourly go-live, 30h for the daily ones. A single shared threshold has
to be wrong for one of them, and a budget of one interval would cry on ordinary
GitHub schedule drift. An alarm that fires most days is the one nobody reads,
which is the failure mode this whole issue is about.

Tested against the incident itself: with heartbeats six days old, all four sweeps
read `overdue`. Mutating the verdict to always-`fresh` reddens exactly the
six-day test and the per-budget test — so the page is provably able to go red,
which is the only property that matters here. The drift control (25h on a daily
sweep, 36min on the quarter-hourly one) stays green.

914 tests pass; `tsc --noEmit` and `eslint --max-warnings=0` are clean. The nav
entry and the `cron` namespace are added to all six locales — with English copy in
the five non-English ones, which is a translation pass, not a gap in the feature.

The companion is the box-side redundant TRIGGER, so the sweeps keep running when
Actions cannot start them at all: piwas-21/restaurant-app-deploy#165.

Closes #209

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
…zero (#214)

Amends ADR-011 Job B: application_fee_amount now exists as a per-tenant,
basis-point mechanism on the unchanged Connect Standard direct charge
(Stripe:Commission:Bps / registry payments_commission_bps, default 0), plus
what was measured against a real NL platform + CH connected account (fee
lands in CHF, an oversized fee is capped not rejected, checkout validates
nothing) and the two open gaps — refunds don't return the fee, and there is
no per-tenant reporting surface — that must close before any tenant goes
non-zero. The module catalog gets a pointer comment; the "no commission"
marketing copy (12 strings, 6 locales) is untouched because it is still true.

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
@sonarqubecloud

sonarqubecloud Bot commented Sep 4, 2026

Copy link
Copy Markdown

@mahmutkaya
mahmutkaya merged commit b22b690 into main Sep 4, 2026
26 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant