Skip to content

feat(subplat): add free access program to billing-and-subscriptions API#20859

Open
StaberindeZA wants to merge 1 commit into
mainfrom
pay-3790-support-billing-api
Open

feat(subplat): add free access program to billing-and-subscriptions API#20859
StaberindeZA wants to merge 1 commit into
mainfrom
pay-3790-support-billing-api

Conversation

@StaberindeZA

Copy link
Copy Markdown
Contributor

Because

  • Relying parties fetch current subscriptions via GET v1/billing-and-subscriptions, but Free Access Program grants were not represented.

This pull request

  • Adds a free_access subscription type sourcing product identity from the related offering.
  • Filters grants by the projection's per-client capabilities.
  • Gates the code behind a FreeAccessProgramConfig feature flag (default off).

Issue that this pull request solves

Closes: #PAY-3790

Checklist

Put an x in the boxes that apply

  • My commit is GPG signed.
  • If applicable, I have modified or added tests which pass locally.
  • I have added necessary documentation (if appropriate).
  • I have verified that my changes render correctly in RTL (if appropriate).
  • I have manually reviewed all AI generated code.

How to review (Optional)

  • Key files/areas to focus on:
  • Suggested review order:
  • Risky or complex parts:

Screenshots (Optional)

Please attach the screenshots of the changes made in case of change in user interface.

Other information (Optional)

Any other information that is important to this pull request.

Because:

 * Relying parties fetch current subscriptions via GET v1/billing-and-subscriptions,
   but Free Access Program grants were not represented.

This commit:

 * Adds a `free_access` subscription type sourcing product identity from the
   related offering.
 * Filters grants by the projection's per-client capabilities.
 * Gates the code behind a FreeAccessProgramConfig feature flag (default off).

Closes #PAY-3790
@StaberindeZA StaberindeZA force-pushed the pay-3790-support-billing-api branch from 0f461d2 to 9d11d75 Compare July 15, 2026 13:32
@StaberindeZA StaberindeZA marked this pull request as ready for review July 15, 2026 13:33
@StaberindeZA StaberindeZA requested a review from a team as a code owner July 15, 2026 13:33
Copilot AI review requested due to automatic review settings July 15, 2026 13:33

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR extends the Payments “billing-and-subscriptions” response model to include Free Access Program (FAP) grants as a new free_access subscription type, gated behind a feature flag so relying parties can see non-Stripe access entitlements when enabled.

Changes:

  • Add free_access subscription schema + transformer, and append FAP-derived subscriptions to /v1/billing-and-subscriptions output when enabled.
  • Add Free Access Program feature-flag configuration and wire the FAP projection manager into the Payments API.
  • Add account-layer support to fetch a user’s current primary email (used to look up FAP membership), with tests.

Reviewed changes

Copilot reviewed 14 out of 14 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
libs/shared/account/account/src/lib/account.repository.ts Adds repository query to fetch the current primary email row by uid.
libs/shared/account/account/src/lib/account.manager.ts Exposes getPrimaryEmailByUid on AccountManager for service-layer use.
libs/shared/account/account/src/lib/account.manager.in.spec.ts Integration tests for primary-email lookup behavior.
libs/payments/api-server/src/lib/util/transformToFreeAccessSubscription.ts Adds mapping utility to build a free_access subscription record.
libs/payments/api-server/src/lib/util/transformToFreeAccessSubscription.spec.ts Unit tests for the free-access subscription transformer.
libs/payments/api-server/src/lib/free-access-program.config.ts Introduces feature-flag config class + mock provider for tests.
libs/payments/api-server/src/lib/billing-and-subscriptions.service.ts Integrates FAP projection lookup and emits free_access subscriptions.
libs/payments/api-server/src/lib/billing-and-subscriptions.service.spec.ts Adds test coverage for FAP-only and mixed subscription scenarios + flag gating.
libs/payments/api-server/src/lib/billing-and-subscriptions.schema.ts Extends Zod discriminated union to include free_access subscriptions.
libs/payments/api-server/src/lib/billing-and-subscriptions.controller.spec.ts Updates controller test module wiring for new dependencies/config.
libs/payments/api-server/src/index.ts Exports the new Free Access Program config type/provider.
apps/payments/api/src/config/index.ts Adds nested freeAccessProgramConfig to the Payments API root config schema.
apps/payments/api/src/app/app.module.ts Registers FreeAccessProgramConfigurationManager in the Payments API module.
apps/payments/api/.env Adds the env var scaffold for the feature flag (default false).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +285 to +304
// Free Access Program grants have no Stripe subscription or Price. The
// projection already maps client ids to the capabilities granted for this
// customer, so filter on it directly rather than re-deriving from Stripe
// prices. Product identity is sourced from the related offering; price data
// is dummy since there is no real subscription price.
if (freeAccessEntry && clientId.toLowerCase() in freeAccessEntry.capabilities) {
for (const apiIdentifier of freeAccessEntry.offeringApiIdentifiers) {
const offering = (
await this.productConfigurationManager.getEligibilityContentByOffering(
apiIdentifier
)
).getOffering();
subscriptions.push(
transformToFreeAccessSubscription({
offeringApiIdentifier: apiIdentifier,
productId: offering.stripeProductId,
})
);
}
}
Comment on lines +104 to +107
@Type(() => FreeAccessProgramConfig)
@ValidateNested()
@IsDefined()
public readonly freeAccessProgramConfig!: Partial<FreeAccessProgramConfig>;
Comment on lines +9 to +17
export class FreeAccessProgramConfig {
@Transform(({ value }) => {
if (value === 'true' || value === true) return true;
if (value === 'false' || value === false) return false;
return value;
})
@IsBoolean()
public readonly enabled: boolean;
}
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.

2 participants