Repository navigation
feat: a free plan of 5 hours of audio a month, with monthly limits instead of a lock - #1311
Merged
Merged
Conversation
…usage meter - @dembrane/allowance: who is free, the pooled allowance account and its period, staff-editable limits (tier_limit, cached 60 s over defaults) and a lock-protected monthly usage ledger (free_usage) - staff can edit the free limits in admin settings; free workspaces see a free plan allowance meter in Usage and billing - the legacy lifetime over-cap lock is retired and existing stamps cleared
- one project and one free organisation per account; create, clone and move into a full free account open the upgrade wall - a recording project per free account; other projects pause recordings and uploads, with a switch - uploads are decoded to measure their real length, reserved against the month and refused before transcription; the dashboard pre-checks lengths - live chunks are metered once, the portal stops at the conversation limit and on the server's signal with "That's a wrap", and live checks fail open - the portal says it isn't taking recordings when the account is out of hours or the project isn't the recording project - owners and admins get one email and in-app notice when the hours run out
…h backfill - 2 chats a month with 20 turns each, on the classic and agentic chat; last month's chats are read-only - 1 report and 1 map a month, refunded when they fail to start or produce nothing; Present's map counts toward the month's map - 12 popcorn analyses a month with a 5 minute live floor; crash recovery charges once; the audience screen never shows limits - walls and banners for every limit; sample projects are never walled - limit keys renamed to turns per chat and popcorn analyses per month - migration 0035 fills this month's usage from existing rows
- no surface shows a 1 h free cap; free caps read the live monthly limit and the usage ledger, and staff at-risk lists free accounts at their cap again - staff tier moves stamp and clear downgraded_at like the tenancy tier change - the retired over-cap lock is never honoured, even if old pods re-stamp it - a free popcorn analysis that read nothing gives its count back - Present shows a host-only notice once the month's free map is used - frozen chats say "earlier free period"; the meter rounds like the usage card
- Walls, banners and the meter use live limits; a limit of 0 gets number-free copy - Org usage rollup reads the ledger and dedupes pooled accounts; snapshot scope - Staff limits panel shows who changed a limit and edits audio in minutes - Upload measuring failures return 503; refused live chunks are skipped by prepare, metering and merge - Portal hides name, tags and Continue after a recording refusal - Reports: reschedule and draft moves charge correctly, stuck free drafts fail and refund, cancelling an unrun scheduled report gives it back once, cancel/reschedule/scheduler races closed - Report page refreshes the free allowance after cancel and update
- Reports: deleting an unrun scheduled free report gives it back; an errored report is charged exactly once across refund, reschedule and cancel; a failed failRun sends no notice - Orgs: org create cap re-checked under a per-user lock; the org wall targets the blocking free org; pooled client workspaces are not billed separately and count once at the cap - Recording project name and id hidden from members who can't open it - A refused live chunk's audio is never served; dead measureSeconds option removed - Launch backfill skips retranscribe copies; billing expiry stamps downgraded_at - Portal: refusal hides the heading, Back and the PIN toast; upload modal disables Upload and Try again when every file is refused; map banner waits for the first map - Shared allowanceForCountedProject replaces six sample checks; unused tier matrix removed - Translations for the new strings; tests for the open gaps
- Audio: free live chunks and uploads are copied to a server-only key, measured and counted at confirm under the account lock; confirm is idempotent per chunk; tiny uploads frozen too; live copy failure fails open only under 1 MB; uploads respect the 1 h conversation limit and the recording project; voice transcription refused on free - Orgs: onboarding creates orgs under the org-create lock; the last owner or manager cannot step down or leave - Chats: a failed turn gives the slot back only when the chat has no other turns; template_key capped before admit - Analysis route charges maps and popcorn analyses once per request; Analysis page opens the wall - Popcorn: an analysis that made a view counts; a conversation that keeps failing is not re-read on free automatic ticks - Reports and popcorn refunds go only to the charged account (migration 0036 free_account_id); a free report cannot be moved back to draft - Allowance lock keyed by account only
The swap protection is left open for now; live chunks are still measured and counted at confirm.
- Audio: a retried confirm never deletes audio a chunk points at (re-check inside the lock); chunks whose measuring failed don't count against live limits, so a media outage never stops a recording; measuring at confirm times out (uploads 120 s retryable 503, live 15 s); a started recording's first chunk gets the stop signal and grace instead of a 402 - Popcorn: stuck runs that read nothing are given back by a sweep, judged only up to the loop's next run; a map-only refresh takes no popcorn analysis - Migrations: runner sets lock_timeout 5s and retries a lock timeout up to 3 times - Portal keeps the wrap-up after a stop with no chunk; voice input shows the free wall only for the free-tier 402; "hours used" notice sends with under a minute left
- Measuring an upload gives up at 200 s and now actually stops the media decode - Stakeholder and tension runs from the analysis route give their analysis back once when they fail; a retry nets one charge (migration 0037: charge stamp on analysis_run, indexes for the popcorn run sweep) - Popcorn stuck-run sweep only touches runs charged on free; paid runs untouched - Frontend: one duration formatter with translated units, meter only shows full when under a minute is left, shared sample and reset-date helpers, every free-limit wall names its tier
…imes out under load
…x (code scanning)
…olynomial ReDoS) Trailing slashes use a shared withoutTrailingSlashes loop from core, closing code fences use withoutClosingFence from llm, trailing whitespace uses trimEnd, and the timestamp, quote, article and list-item patterns are rewritten without backtracking. Outputs are unchanged (fuzzed against the old regexes) and pinned by tests.
Contributor
|
Now on staging, deployed 2026-10-21 16:40 UTC. |
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.