isCloud() predicate beside isCloudBilling() — the cloud-build flag, with a single-reader guard test
Opened by Zhu Yue ·
Add the cloud-build predicate isCloud() to lib/billing/availability.ts, beside the existing isCloudBilling(). Both read the explicit MOTIR_CLOUD flag (default false), but they answer different questions and must stay separate functions (ADR docs/decisions/billing-tiering.md §6): isCloudBilling() answers "is this a billing build?", isCloud() answers "is this a cloud build?". The public-projects gate consumes isCloud(), never isCloudBilling(), and never a raw process.env read.
Approach: isCloud() returns process.env['MOTIR_CLOUD'] === 'true', documented as the cloud-vs-self-host predicate distinct from isCloudBilling(). Add a single-reader guard test in the shape of tests/hosting/appUrlSeam.test.ts: it asserts that no non-billing surface calls isCloudBilling() (they call isCloud()), and that MOTIR_CLOUD is read only through the one named predicate.
Acceptance criteria
isCloud()is exported fromlib/billing/availability.ts, readsMOTIR_CLOUD(explicit, defaultfalse), and is documented as the cloud-vs-self-host predicate distinct fromisCloudBilling().- A single-reader guard test (shape of
tests/hosting/appUrlSeam.test.ts) asserts: every caller ofisCloudBilling()outsidelib/billing/is a billing surface, and the public-projects gate callsisCloud()— the test fails if a non-billing surface starts callingisCloudBilling(). - No existing non-billing caller of
isCloudBilling()is left, and no new one is introduced. - ≥90% coverage on the touched files.
Context refs
lib/billing/availability.ts—isCloudBilling(),MOTIR_CLOUD, the explicit-flag disciplinedocs/decisions/billing-tiering.md§6 — the two-questions-two-functions rulelib/ai/planningConfig.ts—isAiPlanningConfigured(), the OTHER flag this must not be confused withtests/hosting/appUrlSeam.test.ts— the single-reader test shape
Discussion
No comments yet.
Adding to this discussion signs you in on app.motir.co and brings you back to this request.