Skip to content

Commit

Permalink
Added Billing integration, IBillingProvider and the Subscription API. C…
Browse files Browse the repository at this point in the history
…loses #29.
  • Loading branch information
jezzsantos committed Jun 23, 2024
1 parent 47ed531 commit 2428738
Show file tree
Hide file tree
Showing 179 changed files with 11,872 additions and 607 deletions.
51 changes: 51 additions & 0 deletions docs/decisions/0160-billing-integration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Billing Integration

* status: accepted
* date: 2024-06-11
* deciders: jezzsantos

# Context and Problem Statement

Most SaaS products charge their customers for use of the product and they receive revenue.

> The rest does not apply to businesses that don't charge for their products
There is a universe of options and possibilities when it comes to:

1. How much to charge,
2. What to charge for (e.g., seats, tenancies, services, etc),
3. Whether there are recurring charges for some things and fixed charges for others,
4. Whether to charge on some schedule (e.g., daily, monthly, annually) and/or usage charges (e.g., per API call, per transaction, storage capacity) etc.

There are infinite possibilities and variations of some or all of the aspects above and more.

At the end of the day, managing these "policies" and keeping them up to date for existing and new customers, and correctly charging the correct amounts at the correct times for the
*actual* service delivered for those customers is (or becomes) extremely complicated for any small, medium or large business venture. For that very reason alone, no product company should be rolling their own Billing Management Systems (BMS) or Payment Gateways (PG). These services are now provided by several vendors all around the world, to such a degree that this is a well-solved and supported solution that should be adopted by all SaaS businesses.

The challenge that SaaS businesses
*should* face instead is how to integrate with these BMS systems to automate as much of this stuff as possible so that a business removes the need to manually provision, manage, apply, or modify any of these policies. The goal for these businesses is for customers to self-serve the management of their usage and charges of the service they desire at every opportunity until manual intervention is absolutely necessary.

> Manual intervention is frequently required and usually performed by some Support/Success function of the SaaS business in response to individual customer interaction.
To make this experience seamless and reliable for customers of SaaS products, those products are required to integrate with BMS systems to facilitate self-service. In many cases, products themselves will be required to gate-keep and govern when it comes to enforcing quotas and limits defined by these billing policies. This requires the products to have up-to-date definitions of each customer's billing policy and enact the constraints defined within it.

Furthermore, the SaaS business's customer support/success functions will be required to centrally manage their customers' data and billing policies, and they will need comprehensive tools to do that effectively and efficiently, when required. These tools are already provided by the BMS vendors themselves as table-stakes for all SaaS products to use. (whether they integrate their products or not).

Thus we have a situation where both the SaaS product and the BMS system are sharing the same set of data and acting upon it. Given each party can change that data, there is a case here for bi-direction syncing of that data to some reasonable timeframe. This is a challenge the SaaS product needs to resolve.

## Considered Options

The options are:

1. Full, 2-way sync with BMS
2. One-way sync with BMS (product -> BMS)
3. No integration with a BMS
4. No BMS

## Decision Outcome

`2-way sync`

- With 2-way sync, data can be easily kept up to date in the SaaS product by means of webhooks and caches, with some acceptable latency period. (i.e. within 1 minute). Data for each tenant in the product can be changed either in-app or in the management portal of the BMS, and these changes will be "eventually consistent" with the customers' experience in-app.
- With 2 way sync, we can employ the use of the mature BMS toolsets, that can be used by non-technical roles (such as finance or customer success) and can be easily cross-referenced by the product (using well-known identifiers in the product)
- With 2 way sync, we can fully automate the self-serve experience for customers in-app. Rather than having to talk to a customer success agent that just uses the BMS tools.
51 changes: 44 additions & 7 deletions docs/design-principles/0000-all-use-cases.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,34 +33,48 @@ These are the main use cases of this product that are exposed via "public" APIs

#### Audits

For permanently recording compliance and business critical events that are performed on the platform.

1. [Asynchronously] persist an audit to permanent storage

#### Emails

For delivering emails to 3rd party services

1. [Asynchronously] deliver an email to an email gateway
2. Find all delivered emails

#### Feature Flags

For controlling feature flags for software releases

1. Fetch a specific flag
2. Fetch all feature flags (for the current deployment environment)
3. Fetch a specific flag for a specific user

#### Provisioning

Used for registering new tenants on the platform, when provisioning physical cloud infrastructure for individual tenants.

1. [Asynchronously] notify the provisioning of a new tenant

#### Recording

Recording combines, logging, auditing, metrics and usages in a single concept.

1. Record a new measurement event (from a Frontend)
2. Record a new usage event (from a Frontend)

#### Usages (Product)

Usages are the means to record the usage of a product by a user.

1. [Asynchronously] deliver a usage event to product usage service

### Users (End User)

These are the end users on the platform.

1. Assign [platform] roles to an existing user
2. Unassign [platform] roles to an existing user (except `Standard` role)
3. Invite a guest to register on the platform (a referral)
Expand All @@ -73,21 +87,29 @@ These are the main use cases of this product that are exposed via "public" APIs

#### API Keys

API Key are the way a user (person or machine) can authenticate with the platform using an API key.

1. Create a new API key for the current user
2. List all API keys of the current (Authenticated) user
3. Delete an API Key

#### Auth Tokens

Auth Tokens are the way that a user can authenticate with the platform using one or more tokens.

1. Refresh an access token
2. Revoke an existing access token

#### Machines

Machines are the way that non-human entities can operate on the platform.

1. Register a new machine (anonymously or by authenticated user)

#### Password Credentials

Is the way a user can authenticate with the platform using a username and password.

1. Authenticate the current user (with a password)
2. Register a new person (with a password and with optional invitation)
3. Confirm registration of a person (from email)
Expand All @@ -98,10 +120,14 @@ These are the main use cases of this product that are exposed via "public" APIs

#### Single-Sign On

Is the way that a user can authenticate with the platform using an external OAuth2 provider (like Google, Facebook, etc.)

1. Authenticate and (auto-register) a person from another OAuth2 provider (with an optional invitation)

### Images

Provides a simple image service for uploading and downloading images.

1. Upload a new image (supported image types: jpeg,png, gif, maximum size: 100MB)
2. Update the metadata about an image (i.e. Description)
3. Delete an image
Expand All @@ -110,6 +136,8 @@ These are the main use cases of this product that are exposed via "public" APIs

### Organizations

Organizations are the primary way that users are grouped together on the platform. An organization can be a "personal" organization (for a single user) or a "shared" organization (for multiple users). An organization is the manifestation of a tenant on the platform.

1. Create a new (shared) organization for the current user
2. Inspect a specific organization
3. Change the organization's details
Expand All @@ -122,17 +150,26 @@ These are the main use cases of this product that are exposed via "public" APIs
10. List all members of the organization
11. Delete the organization (must be no remaining members)

### EventNotifications

Event Notifications are the way that subdomains can listen to each other in a loosely-coupled way. A "producing" subdomain produces "domain_events" which are stored on a message bus. This API provides an endpoint to consume those "domain_events".

1. Handle a domain_event published to a message bus

### Subscriptions

A billing subscription is created for every `Organization` (personal and shared) on the platform (person and machine). It represents the billing subscription plan for that tenant/organization (i.e., pricing and cost). The subscription plan determines the `Features` each user has access to on the platform, and it defines the fiscal responsibilities that each `EndUser` has an obligation for (i.e., scheduled payments).
A billing subscription is created for every `Organization` (personal and shared) on the platform for any (person or machine). It represents the billing subscription plan for that tenant/organization (i.e., pricing and cost, and features). The subscription plan determines the `Features` each user has access to on the platform, and it defines the fiscal responsibilities that each `EndUser` has an obligation for (i.e., scheduled payments).

Every `Organization` must have a single `EndUser` that owns the fiscal responsibility of the `Organization`, and who can control the extent of that responsibility.
Every `Organization` must have a single `EndUser` that owns the fiscal responsibility of the `Organization` (called the "buyer"), who can control the extent of that responsibility.

1. (coming soon) Inspect the subscription for the current (Authenticated) user
2. (coming soon) Change the subscription plan
3. (coming soon) Cancel the subscription plan
4. (coming soon) Migrate the billing provider data (from one provider to the next)
5. (coming soon) Transfer fiscal responsibility for the organization
1. Inspect the subscription for the current (Authenticated) user
2. Upgrade/Downgrade the plan, or transfer the subscription to another authorized buyer (in the case of the buyer leaving the platform)
3. Cancel the subscription plan
4. List all the available pricing plans
5. Search the billing history for a subscription
6. Transfer the subscription to another authorized buyer
7. List all subscriptions that could be migrated (when migrating off of an existing billing provider)
8. Migrate the billing provider data (from one billing provider to a new one)

### User Profiles

Expand Down
8 changes: 5 additions & 3 deletions docs/design-principles/0090-authentication-authorization.md
Original file line number Diff line number Diff line change
Expand Up @@ -185,9 +185,9 @@ API keys do not support refreshing issued API keys. When issuing the API key the

### Declarative Authorization Syntax

Authorization is both declarative (at the API layer), and enforced programmatically downstream in other layers.
Authorization is enforced at a coarse-grained level declaratively in the API layer, as well as being enforced at fine-grained level downstream in the Domain Layer.

> In the Application layer, the current users authorization can be viewed and checked using data on the `ICallerContext` object.
> In the Application layer, the current users' roles and features can be accessed through the `ICallerContext` object.
In the API layer, authorization is declarative, using the `[Authorize]` attribute.

Expand All @@ -202,11 +202,13 @@ public class GetCarRequest : TenantedRequest<GetCarResponse>
}
```

> Incidentally, the syntax used here, uses `enums` that are source generated for you at compile time.
There are two kinds of aspects to authorize, Roles and Features.

### Role-Based Authorization

In this system, there are two sets of "roles" to manage access to any APIs and underlying subdomains.
In this mechanism, there are two sets of "roles" to manage access to any APIs and underlying subdomains.

This is commonly referred to as [RBAC](https://en.wikipedia.org/wiki/Role-based_access_control).

Expand Down
Loading

0 comments on commit 2428738

Please sign in to comment.