mirror of
https://github.com/yusufipk/OpenFrame.git
synced 2026-09-11 17:46:06 +00:00
The per-file ceiling was a flat 5 GiB from the environment, which is both too small for a paying account with 200 GB of storage and unaware of what an upload actually costs. The provider derives its own renditions from the file (1080p, 720p and down) and bills them to the same account, so a file allowed to fill the quota exactly is over it by the time it finishes processing. The ceiling is now 80% of whatever limit the account is held to: 160 GB on the plan, 2.4 GB on a cardless trial, and it moves on its own when either number changes. OPENFRAME_MAX_VIDEO_UPLOAD_BYTES keeps working as an absolute cap for a host that wants one, where the lower of the two applies, and an instance running without billing has no quota to divide and falls back to the flat 5 GiB. The refusal now names the ceiling, which the old one left the client to guess. Finalize re-checks only the host cap. Re-deriving the account's ceiling there would delete a finished upload over a plan that lapsed while the bytes were in flight, and an upload larger than what was declared is already caught by the declared-size check beside it.
38 lines
1.8 KiB
TypeScript
38 lines
1.8 KiB
TypeScript
// What a cardless trial is allowed to consume.
|
|
//
|
|
// The trial exists to let somebody run one real review cycle before paying: upload
|
|
// a cut, share it, collect feedback, upload the revision. Everything that costs us
|
|
// nothing (YouTube and Vimeo embeds, share links, guests, comments, approvals) is
|
|
// therefore unlimited, and the caps sit only on the two things that do cost money
|
|
// or invite abuse: how much we store, and how many workspaces one unpaid account
|
|
// can hold open.
|
|
//
|
|
// These take a plain `isPaid` boolean rather than a user row so this module stays
|
|
// free of imports from `lib/billing.ts`, which imports the limits back.
|
|
|
|
/** One workspace, so an unpaid account cannot park a whole agency here. */
|
|
export const TRIAL_WORKSPACE_LIMIT = 1;
|
|
|
|
/**
|
|
* One project at a time. There is no archive flag on Project, so "active" means
|
|
* "exists": deleting a project frees the slot.
|
|
*/
|
|
export const TRIAL_PROJECT_LIMIT = 1;
|
|
|
|
/**
|
|
* 3 GiB of direct uploads. Enough for a first cut plus two revisions at a real
|
|
* bitrate, small enough that a farm of throwaway accounts is not worth running.
|
|
* Anyone who hits it can still work through YouTube imports, which cost nothing.
|
|
*/
|
|
export const TRIAL_STORAGE_LIMIT_BYTES = BigInt(3) * BigInt(1024) * BigInt(1024) * BigInt(1024);
|
|
|
|
// There is deliberately no separate per-file ceiling for trials. The per-file
|
|
// ceiling is a share of whatever limit applies to the account (see
|
|
// `getMaxVideoUploadBytesForUser`), so a trial is already held to 80% of these
|
|
// 3 GiB without a second number to keep in step with this one.
|
|
|
|
export function getStorageLimitBytes(isPaid: boolean, planLimitBytes: bigint): bigint {
|
|
if (isPaid) return planLimitBytes;
|
|
return planLimitBytes < TRIAL_STORAGE_LIMIT_BYTES ? planLimitBytes : TRIAL_STORAGE_LIMIT_BYTES;
|
|
}
|