Define paid features and quotas. Cover access near the limit, at the limit, and after a downgrade.
Add "Product entitlements" from ntent to this repo.
Fetch https://ntent.app/r/f/entitlements as plain text. Merge it into contract.json, at the top level. A plan is not an entity, without disturbing what is already there.
Then check it: Every gate names what a person who has not paid sees. Ask the model which journeys have a paywall in them and get an answer before QA does.Reads https://ntent.app/r/f/entitlements
Read the code
contract.json · at the top level. A plan is not an entity
20 lines
"entitlements": {
"plans": ["free", "team", "business"],
"gates": [
{
"id": "ENT-001",
"capability": "custom_invoice_branding",
"type": "feature",
"plans": ["business"],
"gates": ["journey:create-invoice"],
"locked_ui": "The branding panel renders with an upgrade CTA where the controls would be. Not hidden: a feature nobody can see is a feature nobody upgrades for."
},
{
"id": "ENT-002",
"capability": "seats",
"type": "quota",
"limits": { "free": 1, "team": 10, "business": null },
"at_limit": "Invite button disabled, tooltip naming the count and the plan ceiling. See OQ-009 for what a seat removal does."
}
]
}Success check: Every gate names what a person who has not paid sees. Ask the model which journeys have a paywall in them and get an answer before QA does.