Testing mode
A new app is in testing. You and up to 100 testers can sign in. How to add testers, what everyone else sees, and how to get an app verified.
A new app is in testing. Only you and up to 100 testers can sign in to it, and it is not shown in the marketplace. You can sign in as yourself with no setup. Verification, which opens the app to everyone, is by email to support@northlight.ai.
Add testers
On the app's page in the console at https://account.northlight.ai/console, open the Testers tab, enter the Email or phone number on the person's Northlight account, and choose Add tester. An email matches only while it is verified on that account. The person can sign in right away. Nobody gets a message, so tell them. The tab lists everyone on the list and lets you remove them.
Removing a tester stops their access at once, including their refresh tokens, and keeps their data. Adding them back and having them sign in again restores it.
What a person who is not a tester sees
The directory shows "app name is still in testing" and redirects to your redirectUri with error=access_denied, error_description=app_in_testing and your state instead of a code. authorizationRefusalOf reads it from the callback's query and returns {code: 'app_in_testing', error: 'access_denied', state}. A person who pressed Cancel (access_denied with no description) returns null.
if (url.pathname === '/auth/callback') {
if (authorizationRefusalOf(url)?.code === 'app_in_testing') {
return page(res, 403, '<h1>This app is still in testing</h1><p>Ask its owner to add you on the Testers tab in the console.</p>');
}
const state = url.searchParams.get('state') ?? '';
const code = url.searchParams.get('code');
const saved = pending.get(state);
if (!saved || !code) return page(res, 400, '<p>Start sign-in again at <a href="/auth/login">/auth/login</a>.</p>');
pending.delete(state);
const connection = await oauth.exchangeCode({code, codeVerifier: saved.codeVerifier, state, expectedState: state, nonce: saved.nonce});
await store.save(connection);
const sid = randomBytes(16).toString('base64url');
sessions.set(sid, connection.userId);
return void res.writeHead(303, {location: '/', 'set-cookie': `sid=${sid}; HttpOnly; SameSite=Lax; Path=/`}).end();
}The quickstart server shows "This app is still in testing" and asks the person to contact the owner. Check refused.state against the saved state before showing anything.
A person already connected who is later removed as a tester has their grant revoked, not removed. Their next refresh is refused with app_in_testing (kind: 'paused'). Keep their data and show the app as paused. See Connections.
Go public
Email support@northlight.ai to have the app verified. Only Northlight staff can verify an app, and registering never sets it. Include the app name and what it does. A testing app also stays out of the marketplace listing, even once you turn on Listed on the Profile tab. Apps that existed before testing mode are already verified.
Test the refusal in code
@north-light/sdk/testing has a fake directory that can refuse a sign-in as an app in testing, so you can test this path without a second account. See Test your app.
Checked and not checked
From the SDK source, the console source and the testing-mode specification. Adding a tester, a second person signing in, the app_in_testing redirect and removing a tester have not been run on production (not yet checked on production). Those steps need a second account.
Runs
A run is an agent working on the person's runtime, with their AI subscription, under the grant's scopes. Status, outcome, result, activity, and how to bound one.
Providers
A provider is a service the person's runtime calls for your app. Provider scopes, providers.tools, providers.call, and apps that require a provider.