← all branches

feat/subscription-gating

needs attentionviewing older commit
6305b3c · incrementalPR #234reviewed 2026-07-04 03:53 UTC0H · 1M · 4L · 3I
The branch
Purpose
Gate cost-incurring CFE downloads for organizations whose Stripe subscription is unpaid/canceled, while keeping reads, the billing page, and payment-status checks open.
Goal
Enforce subscription access policy at the download chokepoints using the existing organizations.subscription_status field — no new tables, sync, or migrations.
Sub-goals
  • SG-1: domain pure logic — decideFeatureAccess + SubscriptionInactiveError (402)
  • SG-2: requireActiveSubscription middleware + tests
  • SG-3: enforcement on cfe-jobs handler + public POST /v1/jobs + subscriber Lambda sweep filter
  • SG-4: SubscriptionBanner UI (amber past_due / red canceled, CTA → billing)
  • SG-5 (this commit): review nits — drop non-null assertion, add PaymentRequiredCode, harden log fallback
The changes (whole branch)
What
Single refactor commit: (1) replace org! non-null assertion with explicit !org guard in requireActiveSubscription — same behavior, no assertion; (2) export PaymentRequiredCode = CodesForStatus<402> alongside existing code aliases; (3) change subscription-access.ts fallback from raw UUID to '[unknown-org]' to prevent UUID leakage.
Why
Review nits from the prior review pass (f00e3ca0): drop the non-null assertion, add the missing type alias, make the log fallback safe against UUID leakage.
Areas
domains/core/src/billing+30apps/platform+50packages/api+50services/utility/bills/cfe+41docs/development+10
Blast
24 files, +870/-5 cumulative vs main. Enforcement touches download endpoints only; reads, payment-status, and billing page are unaffected.
fail-open: null org → allowed (never block on read hiccup) billingExempt override: metadata.billingExempt=true always passes past_due = grace (downloads still work, banner only)
CI / typecheck· CI checks not accessible via token in this runcoderabbit· no .coderabbit.yaml present

Findings · 8

correctness1

low

Comment claims null is handled via isOrgAllowed, but it is not

packages/api/src/middleware/require-active-subscription.ts:34

The comment reads 'Fail-open (null org → allowed) + exempt override, both via isOrgAllowed.' After the refactor, the `!org` short-circuit handles null before isOrgAllowed is called at all — isOrgAllowed never sees null in this path. The behaviour is correct but the comment misleads: a future reader would expect isOrgAllowed to be the null gate. Should read: null handled by explicit `!org`; exempt check via isOrgAllowed.

conventions2

medium

Unreachable fallback '?? [unknown-org]' violates CLAUDE.md 'don't handle scenarios that can't happen'

services/utility/bills/cfe/src/domain/subscription-access.ts:43

The comment itself admits the fallback is unreachable ('Every blocked id was written to publicIdById in the same loop'). CLAUDE.md explicitly prohibits adding fallbacks or error handling for scenarios that cannot happen. The '?? "[unknown-org]"' branch, plus the three-line comment justifying it as a 'future refactor' guard, should be removed. Use a non-null assertion (publicIdById.get(id)!) or restructure to let TypeScript prove non-nullability, with no comment.

low

Comment misdescribes control flow: null is no longer handled via isOrgAllowed

packages/api/src/middleware/require-active-subscription.ts:34

The comment says 'Fail-open (null org → allowed) ... both via isOrgAllowed' but after the refactor the null case is caught by the explicit `!org` guard before isOrgAllowed is ever called. isOrgAllowed now handles only the exempt-override path for non-null orgs. The comment should reflect the actual split: `!org` → fail-open, `isOrgAllowed(org)` → exempt override.

tests3

info

Refactor preserves behavior — existing tests sufficient

packages/api/src/middleware/require-active-subscription.ts:34

The !org short-circuit is logically equivalent to the prior isOrgAllowed(null)===true path. Existing tests cover null-org, exempt, active, and inactive paths. No new tests needed.

info

PaymentRequiredCode is a pure type export — untestable at runtime

packages/api/src/responses/codes.ts:206

Type aliases have no runtime surface. No test needed.

info

Fallback sentinel '[unknown-org]' is on a structurally unreachable branch — no test needed

services/utility/bills/cfe/src/domain/subscription-access.ts:43

The blocked set and publicIdById map are populated in the same loop, so the ?? branch cannot fire with well-formed input.

improvement2

low

Unreachable fallback should be an invariant assertion, not a silent sentinel

services/utility/bills/cfe/src/domain/subscription-access.ts:40

The comment admits the fallback '[unknown-org]' is unreachable. A silent sentinel will silently corrupt log data if the invariant is ever broken by a refactor. Replace with an explicit invariant throw: `const pub = publicIdById.get(id); if (!pub) throw new Error('invariant: no publicId for orgId ' + id); return pub;` — this is the correct pattern for an impossible-at-runtime branch.

low

Comment explains the TypeScript compiler, not the business rule

packages/api/src/middleware/require-active-subscription.ts:34

The new comment documents TypeScript narrowing mechanics ('The `!org` short-circuit narrows org to non-null') rather than the non-obvious WHY. Per conventions, comments should explain why, not what. A one-liner like `// Null org is allowed (fail-open); exempt orgs are also allowed.` is sufficient.

History · 7 commits

  1. c807731needs attentionincremental0H · 6M · 8L2026-07-30 17:24
  2. 372882bneeds attentionincremental0H · 1M · 2L2026-07-21 17:31
  3. 1fac5adneeds attentionincremental0H · 5M · 4L2026-07-07 02:50
  4. 99bf169safeincremental0H · 0M · 1L2026-07-04 04:01
  5. 6305b3cneeds attentionincremental0H · 1M · 4L2026-07-04 03:53current
  6. f00e3caneeds attentionincremental0H · 7M · 16L2026-07-04 03:15
  7. 1ae74bdneeds attentionfull6H · 9M · 8L2026-07-04 02:36