JSO AI deployment notes
Use this page when preparing a JSO AI environment for live use. The current product shape is BYO-key first: account-level OpenAI or Claude keys can enable live AI even when managed JSO AI billing is disabled.
What is already shipped
- AI endpoints:
/v1/ai/preset-suggest.ashx, /v1/ai/compat-check.ashx, /v1/ai/explain-error.ashx, and /v1/ai/usage.ashx.
- Dashboard pages: AI settings, AI usage, and AI order.
- Encrypted account provider keys in
AIAccountKey.
- Managed billing endpoints for environments where billing is enabled: checkout, portal, and Stripe webhook.
- Preview pages that work without authentication.
1. Provision the AI schema
Run App_Data/CreateAITables.sql against the target database with a migration identity. The script is idempotent and creates the AI subscription (including the unique Stripe customer mapping), usage, disable, provider-key, webhook-idempotency ledger, and monthly-usage objects. The application identity should not need CREATE TABLE or ALTER TABLE after provisioning.
Verify by opening AI usage as a signed-in account. The page should show account state instead of a missing-schema warning.
2. Enable BYO provider keys
BYO key setup is the recommended activation path when managed billing is not enabled for an account. A user saves an OpenAI or Claude key in AI settings. JSO encrypts the key and uses it only for that account's AI requests.
With BYO keys, provider billing stays with the OpenAI or Claude account that owns the key. JSO still tracks usage so the dashboard can show limits and activity.
3. Configure optional site-managed AI
Site-managed provider keys are optional. If configured, use app settings such as:
<add key="JSOAI.Provider" value="claude" />
<add key="JSOAI.ClaudeApiKey" value="sk-ant-..." />
For OpenAI, use JSOAI.Provider=openai and JSOAI.OpenAIApiKey. If no site-managed key is present, accounts with BYO keys can still run live AI.
4. Gate managed billing separately
Do not expose managed checkout until Stripe products, prices, and webhook verification are ready.
<add key="JSOAI.ManagedBillingEnabled" value="false" />
When this value is false, /v1/ai/checkout-create.ashx returns managed_billing_disabled. Dashboard pages should point users to BYO key setup or support.
When managed billing is ready, set the flag true and configure the Stripe secret, optional AI Price IDs, and webhook secret.
5. Smoke test
Run the mock smoke locally after content or endpoint changes:
cd packages/jso-protector
npm run verify:ai
For a live target, use the live harness with the target base URL and a real account. Confirm preset-suggest, compat-check, explain-error, usage, checkout disabled/enabled behavior, and rate limiting.
Rollback
- For one account: remove the provider key or insert an
AIDisable row.
- For managed billing: set
JSOAI.ManagedBillingEnabled=false.
- For site-managed AI: remove the site provider key or set
JSOAI.Enabled=false.
- For preview-only behavior: leave provider keys unset and keep managed billing disabled.
Operational checks
- AI config check shows configured provider and billing settings.
- The same protected operator page performs read-only checks for AI, runtime incident, Enterprise governance, and Web Integrity migrations and warns when MachineKey is automatic. Use explicit secret-managed MachineKey values that remain identical across recycles and nodes before storing encrypted credentials.
- AI usage shows account state and counters.
- The usage endpoint can feed customer monitoring.
- AI quick start explains the user-facing setup path.
Short version: provision the schema, let users save BYO provider keys, keep managed billing disabled until Stripe is ready, run the smoke checks, and use account-level disables for account-specific rollback.
Frequently asked questions
Do we need managed billing enabled before anyone can use JSO AI?
No. The current product shape is BYO-key first, so an account that saves its own OpenAI or Claude key in AI settings can run live AI while managed JSO AI billing stays switched off. With JSOAI.ManagedBillingEnabled set to false the checkout-create endpoint returns managed_billing_disabled, and dashboard pages should route users to BYO key setup or support rather than to a checkout they cannot complete. Keep the flag false until Stripe products, prices and webhook verification are all ready.
With a BYO provider key, who pays the provider bill?
The OpenAI or Claude account that owns the key. JSO encrypts the key and uses it only for that account's AI requests, so provider charges stay with the key holder rather than passing through JSO. Usage is still recorded on the JSO side, which is what lets the AI usage dashboard show limits and activity for the account. That separation is the reason BYO is the recommended activation path in environments where managed billing has not been turned on.
Is the schema script safe to run more than once?
Yes, it is written to be idempotent. Run App_Data/CreateAITables.sql against the target database using a migration identity; it creates the AI subscription objects including the unique Stripe customer mapping, plus the usage, disable, provider-key, webhook-idempotency ledger and monthly-usage objects. After provisioning, the application identity should not require CREATE TABLE or ALTER TABLE permissions. Verify by opening AI usage while signed in and confirming the page shows account state rather than a missing-schema warning.
How do we disable AI for one account without affecting anyone else?
Two options, both account-scoped. Remove that account's stored provider key, or insert an AIDisable row for the account. Either one takes effect without touching site-wide configuration, which is what makes them the right tool for a single-customer rollback. The broader switches are separate: set JSOAI.ManagedBillingEnabled to false to withdraw managed billing, remove the site provider key or set JSOAI.Enabled to false to withdraw site-managed AI, and leave provider keys unset with managed billing disabled to fall back to preview-only behaviour.
Do we have to configure a site-managed provider key at all?
No, it is optional. If you want one, set JSOAI.Provider together with JSOAI.ClaudeApiKey for Claude, or JSOAI.Provider set to openai together with JSOAI.OpenAIApiKey. If no site-managed key is present, accounts that have saved their own keys can still run live AI, and accounts without keys fall back to the preview surface. Deciding not to hold a site key is a legitimate configuration rather than an incomplete one.
What should we confirm before storing encrypted provider keys in production?
Check how MachineKey is configured, because the provider keys are stored encrypted and that encryption is tied to it. The AI config check operator page performs read-only checks across AI, runtime incident, Enterprise governance and Web Integrity migrations, and it warns when MachineKey is set to automatic. Use explicit, secret-managed MachineKey values that stay identical across application recycles and across every node before you store encrypted credentials, otherwise previously saved keys stop decrypting after a recycle or a deployment.