Test mode
identsphere-server can run in a sandbox / test mode that mirrors how Stripe's
test environment behaves: the same binary, the same Postgres schema, the
same license — but no real email is delivered, and responses are tagged so
callers can tell at a glance which environment they're hitting.
This is intended for two use cases:
- CI and integration tests — your test suite needs registration, password reset, and email-OTP flows to work end-to-end without ever sending a real email.
- Customer-facing sandboxes — give customers a sandbox URL where they can poke around their integration with their real license and real data shape, without risk of leaking notification mail.
Enabling test mode
Set the env var when you start the server:
IDENTSPHERE_TEST_MODE=true \
DATABASE_URL=postgres://... \
IDENTSPHERE_JWT_SECRET=$(openssl rand -base64 48) \
identsphere-server
Accepted truthy values: 1, true, TRUE, yes. Anything else (including
unset) keeps test mode off — production deployments need no action.
On start-up the server logs a WARN-level line:
IDENTSPHERE_TEST_MODE=true — outbound email is suppressed and responses are tagged test_mode.
Do not use this configuration in production.
What changes when test mode is on
Outbound email is silently swallowed
Every email the SDK would have sent — registration verification, password
reset, magic-link, MFA recovery — is short-circuited at the
EmailSender layer. The configured transport is wrapped
in TestModeSender, which logs a "test mode: would have sent ..." line
and returns success without invoking the wrapped transport.
This holds even if you have SMTP credentials configured. The intent is that a misconfigured sandbox can never accidentally leak mail to real customer addresses.
Webhooks fall back to test endpoints
If IDENTSPHERE_TEST_MODE=true and a webhook target is not in your sandbox
configuration, the delivery is logged but not dispatched. Configure
test-only webhook targets per-webhook if you need to exercise that flow
in CI.
Audit logs are tagged
Audit entries written while test mode is on carry mode = "test" in the
JSONB metadata column. This lets you keep test traffic in the same audit
table as production traffic if you choose, and filter by mode at query
time:
select * from identsphere_audit_log
where metadata ->> 'mode' = 'test'
order by created_at desc;
Response envelopes include meta.test_mode
A handful of high-signal endpoints (the session response, the user
profile response, and the audit log read endpoint) include a
meta.test_mode = true field in the JSON envelope. Client SDKs can
surface a "Sandbox" banner in the UI based on that flag without having
to track which environment they pointed at separately.
License verification still runs
The license check happens exactly as it does in production. Test mode is
not a way to bypass license verification — customers are expected to
validate that their license works in test mode the same way it would in
production. A trial license issued by scripts/issue-trial-license.sh
works in either mode.
The test+*@example.com short-circuit
Independent of the IDENTSPHERE_TEST_MODE toggle, any recipient address
matching the pattern test+*@example.com (e.g. test+alice@example.com,
test+anything+else@example.com) is always routed to fake delivery. The
match is case-insensitive.
This is the seam test suites hook into: a test that needs to drive the
"forgot password" flow can pass test+suite+pwreset@example.com as the
recipient and assert against the "test mode: would have sent ..." log
line without having to flip a global flag on the sender.
Verifying test mode
After starting the server with IDENTSPHERE_TEST_MODE=true, register a user
and hit GET /v1/auth/session. The response envelope should include:
{
"user": { "...": "..." },
"meta": {
"test_mode": true
}
}
If meta.test_mode is missing or false, the env var didn't take —
check capitalization and the server start-up log line.
Going back to production
Unset the env var (or set it to anything that isn't a truthy value) and
restart the server. There is no on-disk state associated with test mode;
the toggle is purely a run-time flag. Audit rows previously tagged
mode = "test" remain in the database — they're a permanent record of
what ran in which mode and are not retroactively cleared.
Related
- Environment variables — full list, including
IDENTSPHERE_TEST_MODE. - Trial license — how to issue a Scale-tier trial license for sandbox evaluation.
- Email senders — how to wire SMTP or a custom
transport. Both are wrapped in
TestModeSenderwhenIDENTSPHERE_TEST_MODEis on.