Production Authorization
After TradeScript registers the deployment described in the license model, your backend exchanges its credential for a signed deployment lease. The browser receives only that lease and uses it to create the SDK before the first licensed surface starts.
Keep the permanent credential on the server
| Value | Where it belongs | Treat it as |
|---|---|---|
| Credential ID and secret | Backend secret manager only | Permanent server credential |
| SDK version and customer build fingerprint | Backend deployment configuration | Release identifiers |
| Deployment lease | Backend cache, then browser bootstrap response | Browser-deliverable, time-limited bearer value |
| Application user and account permissions | Your application and broker backend | Your authorization policy |
The lease authorizes the customer SDK build and its signed capability policy. It does not replace your user authentication, tenant authorization, market-data permissions, storage access, broker risk checks, or account permissions. Avoid persistent browser storage and never log the complete lease value.
1. Exchange the credential on your backend
Only your backend calls the TradeScript authorization service:
type DeploymentLeaseResponse = {
lease: string;
leaseType: 'TradeScript-Deployment-Lease';
expiresAt: string;
expiresIn: number;
renewAfter: string;
renewAfterIn: number;
catalogVersion: string;
};
const basicCredential = Buffer.from(
`${process.env.CHART_CREDENTIAL_ID}:${process.env.CHART_CREDENTIAL_SECRET}`,
).toString('base64');
const response = await fetch(
'https://chart-authorization.tradescript.dev/api/chart-authorization/v1/deployment-leases',
{
method: 'POST',
headers: {
authorization: `Basic ${basicCredential}`,
'content-type': 'application/json',
},
body: JSON.stringify({
sdkVersion: process.env.CHART_SDK_VERSION,
customerBuildFingerprint: process.env.CHART_CUSTOMER_BUILD_FINGERPRINT,
}),
},
);
if (!response.ok) {
throw new Error(`TradeScript lease exchange failed: ${response.status}`);
}
const lease = await response.json() as DeploymentLeaseResponse;
Read the version and fingerprint confirmed during onboarding from trusted deployment configuration. Do not accept either value from browser-controlled request data.
2. Cache and renew the lease
Cache one successful response per active customer build fingerprint. A lease is
valid for no more than seven days. Schedule renewal from the returned
renewAfter value and keep the current lease until a replacement succeeds or
the signed expiresAt time is reached.
During a blue-green deployment, keep a separate cache entry for each active build fingerprint. Do not exchange a new lease for every page load, chart, or end user.
Recommended failure behavior:
| Condition | Backend behavior |
|---|---|
| Renewal succeeds | Replace the cached lease atomically. |
| Renewal temporarily fails | Retry with bounded backoff and continue serving the still-valid cached lease. |
| Credential is rejected | Stop retries that cannot succeed, alert the deployment owner, and keep the last lease only until its expiry. |
| Lease expires without replacement | Stop serving it and return an unavailable response to new browser sessions. |
3. Deliver the lease through application bootstrap
Return the matching cached lease through your normal application bootstrap. Do not return the credential ID, secret, or allow a browser to select the build fingerprint used for exchange.
import { createTradeScriptSdk } from '@tradescript/pro/sdk/core';
declare const chartBootstrap: {
deploymentLease: string;
};
const sdk = await createTradeScriptSdk({
lease: chartBootstrap.deploymentLease,
});
const mounted = sdk.chart.mount({
mount: '#chart',
symbol: 'AAPL',
interval: '1D',
datafeed,
});
await mounted.ready();
The SDK validates the lease signature, issuer, audience, deployed build, browser origin, SDK version, time window, entitlement catalog, and licensed capabilities before it mounts the chart.
4. Refresh long-running browser sessions
Most pages receive the latest lease on their next load. If a terminal can stay open beyond the lease lifetime, use your existing same-origin configuration channel to deliver the replacement and install it without recreating the SDK:
await sdk.replaceLease(nextDeploymentLease);
The SDK validates the replacement before accepting it. If the signed policy changes, recreate affected surfaces under the new policy. If no valid lease is installed before expiry, the SDK closes the surfaces it owns.
Native mobile and WebView hosts
React Native may bundle the signed customer SDK as self-contained HTML and load it directly into a local WebView. The native app owns symbol, bars, theme, and actions and sends them through its versioned bridge; no public chart page is required.
Install a native lease with the runtime identity expected by the app:
const sdk = await createTradeScriptSdk({
lease: deploymentLease,
nativeRuntimeContext: {
type: 'ios',
appleTeamId: 'A1B2C3D4E5',
appleBundleId: 'com.customer.app',
},
});
Android uses type: 'android', the package name, and signing-certificate
SHA-256. Development uses type: 'native-development'; its lease carries a
signed customer-specific watermark which the chart paints in its final WebGL
pass, Canvas 2D fallback, and exported images. The surrounding DOM contains
only the matching screen-reader label.
Native and browser claims are mutually exclusive. Bundle/package identifiers
are registered constraints, not secrets or cryptographic proof. Version 1
records native identity assurance explicitly as declared; the customer
backend authenticates the normal customer session and keeps the permanent
chart credential server-side. Lease replacement remains sdk.replaceLease(...).
The Admin Console's Operational status proves the customer distribution, authorization link, credential, and exact lease issuance. It does not deploy the mobile binary, generate its local WebView asset, or implement customer login.
Expected authorization failures
Treat these as deployment or licensing failures, not chart-data failures:
| Failure | Check |
|---|---|
| Missing lease | Application bootstrap did not include the current cached value. |
| Expired lease | Backend renewal failed or the browser stayed open past expiry. |
| Origin mismatch | The deployed browser origin is not approved for this credential. |
| Native deployment mismatch | The signed native claim does not exactly match the app runtime context. |
| Native identity mismatch | The signed native claim does not match the installed package/bundle identity or declared assurance. |
| Version or fingerprint mismatch | The lease was issued for a different deployed SDK build. |
| Capability denied | The integration requested a feature or limit not included in the signed policy. |
Log the structured SDK error code, affected build, browser origin, and lease expiry. Never log the permanent credential or the complete lease value.
Production checklist
- The credential ID and secret exist only in the backend secret manager.
- The backend caches by customer build fingerprint and renews from
renewAfter. - Browser bootstrap contains the deployment lease but no permanent credential.
- Missing, expired, wrong-origin, and wrong-build leases fail before chart mount.
- Long-running terminals can receive and install a replacement lease.
- User, tenant, account, and broker authorization remain enforced by your own application and backend.
Next steps
- Production deployment — bundle assets, serve workers, and configure Content Security Policy.
- Monitoring and error handling — handle authorization failures without exposing credentials or leases.