With the new bulldozer rework we dont support default products anymore. Users are encouraged to currently manually handle granting products to their end users. We block api requests and new product creations that attempt to set no price, and we remove any options to set include-by-default. We also migrate users' existing product snapshots in `Subscriptions`, `OneTimePurchases`, and `ProductVersions` to have no price set if it's an include-by-default product. This will make it so that next time a user goes onto their products page, they will be informed that the pricing is invalid and it is no longer delivered by default. Note, however, that these products will still be providing items and the like to the users who have them. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Migrated legacy product snapshots so missing included-items no longer break readers. * Removed deprecated "include-by-default" pricing sentinel; pricing now requires explicit price entries and write validation rejects the old sentinel. * **Chores** * Simplified dashboard pricing flows: create/edit/save now use explicit prices and surface an alert when a formerly implicit free plan needs an explicit $0 price. * Config overrides and stored data are auto-normalized to explicit price objects. * **Tests** * Updated and added tests covering migration, validation, and switching behavior for explicit prices. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: mantrakp04 <mantrakp@gmail.com> Co-authored-by: Mantra <87142457+mantrakp04@users.noreply.github.com> |
||
|---|---|---|
| .. | ||
| db-sync-mappings.ts | ||
| format.ts | ||
| migrate-catalogs-to-product-lines.ts | ||
| README.md | ||
| schema-fuzzer.test.ts | ||
| schema.ts | ||
Some notes on configs
The language in this file is very technical, if you're struggling, put it into ChatGPT and see if it can help you (with the usual hallucination disclaimer).
Generic format vs. Stack Auth
The config format is generally usable and not specific to Stack Auth.
All the logic required for generic usage of the config format are in format/. The other files in this folder are specific to Stack Auth's usage of it.
Terminology
Generic config format:
- Config: Any config, as described in stack-info
- Normalized config: A config without
nullfields and dot notation
Stack Auth: There are four levels, project, branch, environment, organization.
- Base config: The defaults that come with Stack Auth
$Levelconfig override: Overrides that are applied to the base config (in the following order: project -> branch -> environment -> organization)$Levelincomplete config: The base config after some overrides have been applied$Levelrendered config: An incomplete config with those fields removed that can be overridden by a future override, deeply merged into the defaults and sanitized (usingapply{$Level}DefaultsAndSanitize), and then normalized- Complete config: The organization rendered config.
$Levelconfig override override: An override that overrides the$Levelconfig override. This is most often used eg. in the REST API to let users make changes to the branch-level config, without overwriting the entire branch-level config override. Note that, since config overrides (unlike configs) distinguish betweennulland a property missing (undefined), it is currently not possible to say "this property in the config override should be unset" (setting a property tonullin the override override will simply also set it tonullin the override). In the future, we'll have to think about how we handle this, probably with a sentinel value.$Levelconfig: Could refer to any of the above, depending on the context; if it's not clear, specify it.
Examples
Base config:
{
organizations: {},
createTeamOnSignUp: false,
sourceOfTruthConnectionString: null
}
Project config override:
{
sourceOfTruthConnectionString: 'postgresql://...',
}
Project incomplete config:
// note: `organizations` and `createTeamOnSignUp` may be overridden by branch, environment, or organization configs! They are not final
{
organizations: {},
createTeamOnSignUp: false,
sourceOfTruthConnectionString: 'postgresql://...',
}
Project rendered config:
// since `organizations` and `createTeamOnSignUp` may change later, they are not included in the rendered config
{
sourceOfTruthConnectionString: 'postgresql://...',
}
Branch config override:
{
organizations: {
'my-org': {
name: 'My Org',
}
}
}
Branch incomplete config:
{
organizations: {
'my-org': {
name: 'My Org',
}
},
createTeamOnSignUp: true,
sourceOfTruthConnectionString: 'postgresql://...',
}
Branch rendered config:
// as above, `organizations` and `createTeamOnSignUp` are not included in the rendered config, as they may change later
{
sourceOfTruthConnectionString: 'postgresql://...',
}
Environment config override:
// no change from branch config
{}
Environment incomplete config:
// no change from branch config
{
organizations: {
'my-org': {
name: 'My Org',
}
},
createTeamOnSignUp: true,
sourceOfTruthConnectionString: 'postgresql://...',
}
Environment rendered config:
// organizations can no longer change after this point, so they are included in the rendered config
{
organizations: {
'my-org': {
name: 'My Org',
}
},
createTeamOnSignUp: true,
sourceOfTruthConnectionString: 'postgresql://...',
}
Organization config override:
{
createTeamOnSignUp: true,
}
Organization incomplete config = organization rendered config = complete config:
{
createTeamOnSignUp: true,
sourceOfTruthConnectionString: 'postgresql://...',
}