@atlasauth/cli 0.7.0 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/dist/args.d.ts +155 -0
  3. package/dist/args.js +66 -1
  4. package/dist/args.js.map +1 -1
  5. package/dist/commands/auth.js +5 -1
  6. package/dist/commands/auth.js.map +1 -1
  7. package/dist/commands/config.d.ts +56 -1
  8. package/dist/commands/config.js +188 -29
  9. package/dist/commands/config.js.map +1 -1
  10. package/dist/commands/csp.d.ts +32 -0
  11. package/dist/commands/csp.js +180 -0
  12. package/dist/commands/csp.js.map +1 -0
  13. package/dist/commands/import-better-auth.d.ts +3 -0
  14. package/dist/commands/import-better-auth.js +164 -0
  15. package/dist/commands/import-better-auth.js.map +1 -0
  16. package/dist/commands/import.js +7 -0
  17. package/dist/commands/import.js.map +1 -1
  18. package/dist/commands/info.js +1 -1
  19. package/dist/commands/info.js.map +1 -1
  20. package/dist/commands/init.js +26 -2
  21. package/dist/commands/init.js.map +1 -1
  22. package/dist/commands/integrations.d.ts +8 -0
  23. package/dist/commands/integrations.js +112 -0
  24. package/dist/commands/integrations.js.map +1 -0
  25. package/dist/commands/listen.d.ts +17 -0
  26. package/dist/commands/listen.js +223 -0
  27. package/dist/commands/listen.js.map +1 -0
  28. package/dist/commands/migrate.js +40 -1
  29. package/dist/commands/migrate.js.map +1 -1
  30. package/dist/commands/move-origin.d.ts +11 -0
  31. package/dist/commands/move-origin.js +95 -0
  32. package/dist/commands/move-origin.js.map +1 -0
  33. package/dist/commands/operator.d.ts +26 -0
  34. package/dist/commands/operator.js +198 -0
  35. package/dist/commands/operator.js.map +1 -0
  36. package/dist/commands/project-commands.d.ts +12 -0
  37. package/dist/commands/project-commands.js +130 -30
  38. package/dist/commands/project-commands.js.map +1 -1
  39. package/dist/commands/referrals.d.ts +4 -4
  40. package/dist/commands/referrals.js +203 -33
  41. package/dist/commands/referrals.js.map +1 -1
  42. package/dist/commands/shared.d.ts +6 -0
  43. package/dist/commands/shared.js +10 -1
  44. package/dist/commands/shared.js.map +1 -1
  45. package/dist/commands/status.d.ts +3 -0
  46. package/dist/commands/status.js +77 -0
  47. package/dist/commands/status.js.map +1 -0
  48. package/dist/commands/webhooks.d.ts +29 -2
  49. package/dist/commands/webhooks.js +257 -24
  50. package/dist/commands/webhooks.js.map +1 -1
  51. package/dist/config.d.ts +14 -0
  52. package/dist/config.js.map +1 -1
  53. package/dist/context.d.ts +13 -0
  54. package/dist/context.js.map +1 -1
  55. package/dist/help.d.ts +1 -1
  56. package/dist/help.js +221 -17
  57. package/dist/help.js.map +1 -1
  58. package/dist/index.d.ts +4 -0
  59. package/dist/index.js +10 -1
  60. package/dist/index.js.map +1 -1
  61. package/dist/migrate/better-auth/integration.d.ts +59 -0
  62. package/dist/migrate/better-auth/integration.js +81 -0
  63. package/dist/migrate/better-auth/integration.js.map +1 -0
  64. package/dist/migrate/better-auth/orchestrator.d.ts +43 -0
  65. package/dist/migrate/better-auth/orchestrator.js +525 -0
  66. package/dist/migrate/better-auth/orchestrator.js.map +1 -0
  67. package/dist/migrate/better-auth/output.d.ts +20 -0
  68. package/dist/migrate/better-auth/output.js +146 -0
  69. package/dist/migrate/better-auth/output.js.map +1 -0
  70. package/dist/migrate/better-auth/translate.d.ts +77 -0
  71. package/dist/migrate/better-auth/translate.js +1989 -0
  72. package/dist/migrate/better-auth/translate.js.map +1 -0
  73. package/dist/run.js +14 -0
  74. package/dist/run.js.map +1 -1
  75. package/package.json +5 -4
package/dist/help.js CHANGED
@@ -12,27 +12,44 @@ Usage: atlas <command> [subcommand] [arguments] [options]
12
12
 
13
13
  Commands:
14
14
  login Authenticate and store a profile credential
15
+ (--device: operator sign-in in the browser, no key stored)
16
+ token --resource <id> A one-hour token for one instance/app from your operator sign-in
17
+ keys whoami|list|create|rotate|revoke|revoke-leaked
18
+ Scoped secret keys; new secrets go sealed into 0600 files
15
19
  logout Remove a stored profile credential
16
20
  whoami Show the active profile and instance
17
21
  users list|get|create|delete
18
22
  orgs list|get|members
19
23
  api-keys list|create|revoke
20
- webhooks list|create
24
+ webhooks list|create|upsert|update|test|deliveries|redeliver|replay|rotate|reveal
25
+ listen --forward-to <url> Forward live events to your local server, signed (no tunnel)
26
+ move-origin --from --to Move an app to a new domain in one step (--dry-run first)
27
+ csp --framework next|express|nginx
28
+ Print the Content Security Policy sources Atlas needs
29
+ integrations list|get|set|remove|deliveries Identity integrations (chat, docs, consent, referrals, custom)
21
30
  sessions revoke
22
- config export|import Config-as-code: round-trip the instance's config
31
+ config export|import|plan Config-as-code: round-trip the instance's config; plan = drift diff
23
32
  actions list|deploy|test|logs|gallery|show|install|installs|update|publish
24
33
  init Create or complete an app's setup (idempotent); secrets to 0600 files
25
34
  preflight Check an instance's setup; non-zero exit on errors (for CI)
35
+ doctor Integration health: webhooks, logout, referrals, email, consent (exit 1 on a failure)
26
36
  env Print deploy variables: public values + secret file paths
27
37
  client rotate Rotate an OAuth client secret straight into its file
28
38
  referrals connect|backfill|status
29
39
  Connect a referral platform, backfill, check the connection
40
+ status Atlas status, incidents that concern the instance and its
41
+ upstream status pages; non-zero exit on an outage
30
42
  import --from <vendor> <file>
31
43
  Move users from Auth0, Clerk, Supabase, Firebase, Cognito,
32
44
  Auth.js, WorkOS or Better Auth (resumable; --dry-run first)
33
45
  migrate code --from <vendor> [path]
34
46
  Rewrite an app's auth code onto Atlas (Clerk, Auth.js,
35
47
  Supabase, Auth0, Better Auth); a dry run with a diff unless --yes
48
+ migrate better-auth [path] Move a Better Auth app to Atlas end to end: config, users,
49
+ sessions and code, resumable (--dry-run, --resume, --yes)
50
+ migrate better-auth config [path]
51
+ Translate the app's betterAuth({...}) options into Atlas
52
+ config files plus a report (offline)
36
53
  info [path] Print the environment for a support ticket (versions, SDKs,
37
54
  instance, API latency, preflight); secrets redacted
38
55
  mcp install Add the Atlas MCP server (docs search) to Cursor, Claude Code,
@@ -48,10 +65,12 @@ Global options:
48
65
 
49
66
  Environment overrides:
50
67
  ATLAS_SECRET_KEY Secret key to use instead of the stored one
51
- ATLAS_API_URL API URL to use instead of the stored one
68
+ ATLAS_API_BASE API URL to use instead of the stored one
69
+ ATLAS_API_URL Same (the older name); ATLAS_API_BASE wins when both are set
52
70
  ATLAS_PLATFORM_KEY Platform key (psk_) for atlas init
53
- REFERALLY_BASE_URL Referalli base URL for atlas referrals connect
54
- REFERALLY_API_KEY Referalli merchant key for atlas referrals connect (never stored)
71
+ REFERALLI_BASE_URL Referalli base URL for atlas referrals connect
72
+ REFERALLI_API_KEY Referalli merchant key for atlas referrals connect (never stored)
73
+ (the old REFERALLY_BASE_URL / REFERALLY_API_KEY still work, with a notice)
55
74
 
56
75
  Secrets: a command that receives a secret writes it to a 0600 file under
57
76
  ~/.config/<product>/ and prints only the path. --print-secret prints it instead.
@@ -59,10 +78,38 @@ Secrets: a command that receives a secret writes it to a 0600 file under
59
78
  Run 'atlas <command> --help' for command-specific help.`;
60
79
  /** Per-command help, keyed by the resource word. */
61
80
  exports.COMMAND_HELP = {
62
- migrate: `atlas migrate code — rewrite an app's auth code onto Atlas
81
+ migrate: `atlas migrate — move an app's auth onto Atlas
63
82
 
64
83
  Usage:
65
84
  atlas migrate code --from <vendor> [path] [--yes] [--json]
85
+ atlas migrate better-auth config [path] [--dir <dir>] [--format json|yaml] [--entry <file>] [--json]
86
+ atlas migrate better-auth [path] [--dry-run] [--yes] [--resume] [--force] [--json]
87
+ [--dir <dir>] [--state-file <file>] [--entry <file>] [--bundle <file>] [--run-export]
88
+ [--confirm-conflicts] [--bridge-days <n>] [--skip <step,...>]
89
+
90
+ migrate better-auth config reads your betterAuth({...}) setup statically (it
91
+ follows imports and resolves env vars by NAME, never their values) and writes
92
+ Atlas config-as-code files (the 'atlas config import' format) plus
93
+ better-auth-report.md: what maps 1:1, what maps with a difference, and what
94
+ needs a manual step, each with file:line. Default --dir: atlas-migrate/config.
95
+
96
+ migrate better-auth runs the whole program, checkpointing each step in
97
+ atlas-migrate/state.json (--state-file):
98
+ preflight instance and key, CLI version, the betterAuth() call
99
+ translate the config files and report (as above)
100
+ apply review the diff, confirm, push the config (env placeholders are
101
+ filled from the environment and the app's .env files)
102
+ export run the exporter in the app (prints the command; --run-export runs it)
103
+ import upload the bundle, dry-run report, confirm, import (conflicts with
104
+ existing Atlas users need --confirm-conflicts; a stopped import resumes)
105
+ bridge accept Better Auth sessions for --bridge-days (default 30): no forced logout
106
+ code atlas migrate code --from better-auth, after a confirmation
107
+ verify counts, preflight and a sign-in checklist
108
+ --dry-run walks every step without changing the instance or the code. --yes
109
+ answers every confirmation. --resume continues a stopped run. --json prints the
110
+ step summary (with --json and no --yes it stops at the first confirmation).
111
+
112
+ Code rewrite (migrate code):
66
113
 
67
114
  Vendors:
68
115
  clerk @clerk/* SDKs
@@ -71,6 +118,10 @@ Vendors:
71
118
  Supabase client itself stays for your database
72
119
  auth0 @auth0/auth0-react, @auth0/nextjs-auth0 (v3 and v4), @auth0/auth0-spa-js
73
120
  better-auth better-auth (client, server, Next.js handler, cookies)
121
+ openid-client openid-client (Issuer.discover, authorizationUrl, callback, endSessionUrl)
122
+ jose jose used to verify OIDC ID tokens (jwtVerify + createRemoteJWKSet)
123
+ generic-oidc a hand-rolled relying party (discovery, PKCE, code exchange, JWKS) found
124
+ by its code; replaced by oidc.start / oidc.callback / oidc.logoutUrl
74
125
 
75
126
  What it rewrites: imports, providers, hooks, server session helpers, middleware,
76
127
  sign-in/out calls and env var names, onto native Atlas APIs and the drop-in
@@ -100,6 +151,9 @@ reported, not fatal. Anything shaped like a secret is redacted.`,
100
151
 
101
152
  Usage:
102
153
  atlas import --from <vendor> <export-file> [--dry-run]
154
+ atlas import --from better-auth --bundle <file> [--dry-run] [--yes]
155
+ atlas import --from better-auth --import <id> [--confirm-conflicts]
156
+ atlas import --from better-auth (prints the import key and export command)
103
157
 
104
158
  Vendors and the file each one reads:
105
159
  auth0 the user export job (NDJSON/JSON); --hashes <file> merges the password export
@@ -120,6 +174,13 @@ Options:
120
174
  --create-orgs Create organizations that memberships name but that do not exist yet
121
175
  --json Machine-readable summary
122
176
 
177
+ Better Auth bundle (npx atlas-better-auth-export --out <file> --public-key <key>):
178
+ --bundle <file> Upload the sealed bundle, show the dry run, then apply
179
+ --import <id> Continue an uploaded import (apply it, or resume a failed one)
180
+ --confirm-conflicts Apply although the dry run found conflicts with existing users
181
+ --options <json|@file> Import options, e.g. '{"import_sessions":false}'
182
+ --yes Apply without asking
183
+
123
184
  Batches are sent with upsert, so a resumed or repeated run never duplicates a
124
185
  user or a membership. Exit code 2 means some rows were reported as issues.`,
125
186
  mcp: `atlas mcp — connect AI coding agents to Atlas
@@ -138,20 +199,47 @@ agent can search and read the Atlas docs. Servers already in the file are kept.
138
199
 
139
200
  No key is written. To also manage your instance from the agent, add
140
201
  ATLAS_SECRET_KEY to the server's env yourself.`,
202
+ status: `atlas status — is it Atlas, a service you depend on, or you?
203
+
204
+ Usage:
205
+ atlas status [--json]
206
+
207
+ Shows Atlas's components (with their regions), the open Atlas incidents that
208
+ concern this instance (its status subscription's regions, components and
209
+ minimum impact), the subscription itself, and the state of every upstream
210
+ status page the instance declared (POST /v1/instance/status_dependencies).
211
+
212
+ Exit code 1 when Atlas reports a major outage or an open major / critical
213
+ incident concerns the instance, or an enabled upstream status page reports a
214
+ partial or major outage; 0 otherwise.`,
141
215
  referrals: `atlas referrals — referral attribution
142
216
 
143
217
  Usage:
144
- atlas referrals connect --provider referally --program <prg_…> --base-url <url>
145
- [--referally-key-file <path|-> | --referally-key <rk_…>]
218
+ atlas referrals connect --provider referalli --program <prg_…> --base-url <url>
219
+ [--referalli-key-file <path|-> | --referalli-key <rk_…>]
146
220
  [--auto-enroll] [--destination <url>] [--tracking-token <token>] [--enable]
147
221
  [--no-sync] [--allow-mode-mismatch]
222
+ atlas referrals connect --oauth [--preset <id>] [--enable] (default preset: referalli)
148
223
  atlas referrals connect --provider webhook --endpoint <https-url>
149
224
  [--secret-file <path|->] [--program <id>] [--auto-enroll] [--enable]
150
225
  atlas referrals backfill --since <YYYY-MM-DD> [--map <file.csv>]
151
226
  [--metadata-path public_metadata.referral_code] [--wait]
152
227
  atlas referrals status
228
+ atlas referrals conformance [--protocol webhook|connection] [--base-url <url>] [--connection-id <id>] --secret-file <path|->
229
+ [--only <case ids or areas>] [--simulate]
153
230
 
154
- connect --provider referally creates the Atlas connection on Referalli with
231
+ connect --provider referalli --oauth is one-click: it prints a Referalli link, you choose the
232
+ organization and program there, and Referalli hands Atlas the connection secret directly (nothing to
233
+ copy). It needs no key, --program or --base-url, and waits until the connection appears. Where the
234
+ deployment does not offer it yet, use a key as below.
235
+
236
+ conformance runs the referral protocol conformance suite (@atlasauth/referral-conformance) against
237
+ any platform (--protocol webhook: the generic Atlas referral protocol; connection: the Referalli dialect): signed calls with the answers a conforming server must give (401 for a bad signature,
238
+ an empty export for an unknown customer, nulls accepted, …). It defaults to the connected Referalli;
239
+ the secret is read from --secret-file because Atlas never shows it. --simulate also sends Atlas's own
240
+ simulated sign-up. It exits 1 on any failed case.
241
+
242
+ connect --provider referalli creates the Atlas connection on Referalli with
155
243
  your merchant key (bring your own key: used for this one call, never stored or
156
244
  printed), saves the connection id and secret on the instance, and runs a ping.
157
245
  It requires v2 signatures on the connection from the start and registers a
@@ -159,9 +247,10 @@ Referalli webhook that sends referral changes (voided, approved, reassigned…)
159
247
  back to Atlas; --no-sync skips the webhook. A test key (rk_test_) belongs with a
160
248
  development instance and a live key with production: a mismatch is refused
161
249
  unless --allow-mode-mismatch. --auto-enroll and --destination are passed to
162
- Referalli. --enable turns referrals on when the ping passes. Prefer --referally-key-file (or
163
- REFERALLY_API_KEY) to --referally-key: a key on the command line can end up in
164
- your shell history.
250
+ Referalli. --enable turns referrals on when the ping passes. Prefer --referalli-key-file (or
251
+ REFERALLI_API_KEY) to --referalli-key: a key on the command line can end up in
252
+ your shell history. The old names (--provider referally, --referally-key-file,
253
+ --referally-key, REFERALLY_*) still work and print a notice.
165
254
 
166
255
  connect --provider webhook points the instance at a platform that speaks the
167
256
  Atlas referral protocol. Without --secret-file, a signing secret is generated
@@ -180,7 +269,34 @@ Usage: atlas login [--profile <name>] [--url <api-url>] [--secret-key <sk_...>]
180
269
 
181
270
  Prompts for an API URL and a secret key, validates the key with one Backend
182
271
  call, then stores it (0600) under the profile. --url / --secret-key skip the
183
- prompts for non-interactive setup.`,
272
+ prompts for non-interactive setup.
273
+
274
+ Operator sign-in (no key on disk):
275
+ atlas login --device [--resource <ins_…|app_…>] [--scope "<scopes>"]
276
+ Opens Atlas's sign-in (passkey, multi-factor) with a device code. Only
277
+ short-lived tokens are stored: the operator token, and with --resource a
278
+ one-hour token bound to that instance or app (scope "read" by default).
279
+ Creating apps or instances and minting keys need a multi-factor sign-in
280
+ within the last 5 minutes.`,
281
+ token: `atlas token — a one-hour token bound to one instance or app
282
+
283
+ Usage: atlas token --resource <ins_…|app_…|acct_…> [--scope "<scopes>"] [--json]
284
+
285
+ Swaps your operator sign-in (atlas login --device) for an Atlas token (RFC 8693
286
+ token exchange). "read" = every read scope.`,
287
+ keys: `atlas keys — the instance's secret keys
288
+
289
+ Usage:
290
+ atlas keys whoami What the current key is and can do
291
+ atlas keys list Every credential on the instance
292
+ atlas keys create --scopes "<scopes>" [--name n] [--owner o] [--expires-at <ISO>] [--allowed-ips <cidr,…>] [--out <file>]
293
+ atlas keys rotate <id> [--overlap <seconds>] [--out <file>]
294
+ atlas keys revoke <id>
295
+ atlas keys revoke-leaked [<secret>] Revoke a leaked Atlas credential (no login needed)
296
+
297
+ New secrets come back sealed to a key pair made on this machine and are
298
+ written to a 0600 file (default .atlas/secret-key-<id>.env); --print-secret
299
+ prints them instead.`,
184
300
  logout: `atlas logout — remove a stored profile credential
185
301
 
186
302
  Usage: atlas logout [--profile <name>]`,
@@ -212,8 +328,76 @@ Usage:
212
328
  Usage:
213
329
  atlas webhooks list [--json]
214
330
  atlas webhooks create --url <https-url> [--events a,b] [--product <name>] [--print-secret] [--json]
331
+ atlas webhooks upsert --url <https-url> [--events a,b] one endpoint per URL; idempotent
332
+ atlas webhooks update <id> [--url <u>] [--events a,b] [--active | --inactive]
333
+ atlas webhooks test <id> [--timeout 10s] [--no-wait] [--json]
334
+ atlas webhooks deliveries <id> [--status failed] [--event-type user.created]
335
+ [--since <iso|2h|7d>] [--until <iso>] [--limit <n>] [--starting-after <id>] [--json]
336
+ atlas webhooks redeliver <id> --delivery <delivery-id>
337
+ atlas webhooks redeliver <id> --since <iso|2h|7d> [--until <iso>] [--status failed]
338
+ atlas webhooks replay <id> [--since failing_since] re-send what a disabled endpoint missed
339
+ atlas webhooks rotate <id> [--now | --overlap <seconds>]
340
+ atlas webhooks reveal <id>
341
+
342
+ create, upsert, rotate and reveal write the signing secret to a 0600 file and
343
+ print only its path (--print-secret prints it instead; --force replaces a file).
344
+ test sends a signed webhook.test event and waits for your endpoint's answer;
345
+ the exit code is 1 when it did not answer 2xx. rotate --overlap keeps the old
346
+ secret signing alongside the new one for that many seconds.`,
347
+ listen: `atlas listen — forward live events to your local server
348
+
349
+ Usage:
350
+ atlas listen --forward-to <url> [--events user.*,session.created] [--count <n>] [--timeout <dur>] [--json]
351
+ atlas listen --no-forward [--events ...] only print events
352
+
353
+ Opens a signed event stream from your instance and POSTs each event to
354
+ --forward-to with the same atlas-id, atlas-timestamp and atlas-signature headers a
355
+ real delivery carries, then prints the status your server returned. No tunnel
356
+ and no second endpoint. The signing secret belongs to this session only and is
357
+ written to a 0600 file (webhook-listen.env): point your verifier at it. --events
358
+ takes names or patterns (user.*, *.created). The session lasts up to an hour;
359
+ Ctrl-C stops it. --count n exits after n events (exit 1 if any forward failed).`,
360
+ 'move-origin': `atlas move-origin — move an app to a new domain
361
+
362
+ Usage: atlas move-origin --from <origin> --to <origin> [--dry-run] [--yes] [--json]
363
+
364
+ Rewrites every field that points at the old origin: allowed origins, branding
365
+ links, OAuth client redirect and logout URIs, webhook URLs, the redirect-URL
366
+ allowlist and your Sign in with Atlas apps. Shows the before and after of every
367
+ field first and asks before writing (--yes skips the question). After a real
368
+ move it sends a signed test delivery to each webhook endpoint that moved.
369
+ --dry-run prints the diff and writes nothing; running it twice changes nothing.`,
370
+ csp: `atlas csp — the Content Security Policy sources Atlas needs
371
+
372
+ Usage: atlas csp [--framework next|express|nginx] [--shape redirect|panel|button]
373
+ [--instance <id> | --product <name> [--instance-env <env>]] [--origin <url>]
374
+ [--manifest <url|file>]... [--no-atlas] [--json]
375
+
376
+ Reads your instance's embed manifest (including a custom Frontend API host) and
377
+ prints the script-src, connect-src, img-src and frame-src sources for your
378
+ setup, as a next.config.ts headers() block, a helmet() config or an nginx
379
+ add_header line. Read-only. --shape redirect (hosted sign-in) needs none.
380
+ With --origin, warns when that origin is not one of the instance's allowed origins.
381
+
382
+ Any provider that publishes the open embed-manifest format ({surfaces:{name:{csp:{directive:[sources]}}}},
383
+ usually at /.well-known/atlas-embed.json) can be merged in with --manifest <url|file>
384
+ (repeatable): a consent platform, chat widget, captcha or analytics vendor. --no-atlas
385
+ skips the Atlas instance and uses only the manifests you list.`,
386
+ integrations: `atlas integrations — identity integrations (presets and custom)
215
387
 
216
- create writes the signing secret to a 0600 file and prints only its path.`,
388
+ Usage:
389
+ atlas integrations list [--json]
390
+ atlas integrations get <id>
391
+ atlas integrations set <id> --audience <aud> [--name <n>] [--events-url <url|none>]
392
+ [--backchannel-logout-url <url|none>] [--oauth-client-id <client_id|none>]
393
+ [--disable] [--dry-run] [--json]
394
+ atlas integrations remove <id> [--json]
395
+ atlas integrations deliveries <id> [--trace <id>] [--json]
396
+
397
+ <id> is a preset (chatly, forumulate, cookiemunch, referalli) or your own id.
398
+ --oauth-client-id names the first-party OAuth client the service signs users in
399
+ with: while no --backchannel-logout-url is set, its backchannel_logout_uri is the
400
+ integration's back-channel receiver.`,
217
401
  init: `atlas init — create or complete an app's setup, idempotently
218
402
 
219
403
  Usage:
@@ -223,13 +407,16 @@ Usage:
223
407
  [--email managed|development|none] [--email-from <address>]
224
408
  [--email-provider resend|brevo --email-key-file <path|->]
225
409
  [--client-redirect <url>]... [--webhook-url <url>]
410
+ [--backchannel <url>]
226
411
  [--yes] [--force] [--rotate-secret] [--json]
227
412
 
228
413
  Needs a platform key (ATLAS_PLATFORM_KEY, or a psk_ profile from atlas login).
229
414
  Finds the app by name and environment, or creates it, then sets strategies, the
230
415
  email sender, the custom domain (auth.<domain> unless --auth-host; prints the
231
416
  CNAME), a first-party OAuth client and a webhook. Re-running only fills what is
232
- missing.
417
+ missing. --backchannel <url> sets the client's back-channel logout URI (your
418
+ route that ends the app session when Atlas ends one; @atlasauth/backend has
419
+ ready-made handlers).
233
420
 
234
421
  Email always goes through YOUR provider account (Atlas lends none):
235
422
  managed Atlas sets your domain up on your Resend or Brevo account and
@@ -250,14 +437,26 @@ Usage: atlas preflight [--instance <id> | --product <name> [--instance-env <env>
250
437
 
251
438
  Prints every finding (severity, code, message, fix). Exits 1 when there is an
252
439
  error, or with --fail-on warning also on a warning.`,
440
+ doctor: `atlas doctor — integration health (a CI / deploy gate)
441
+
442
+ Usage: atlas doctor [--instance <id> | --product <name> [--instance-env <env>]]
443
+ [--only <source,...>] [--no-probe] [--json]
444
+
445
+ Prints every check: setup findings, webhook receivers (with the failing hop:
446
+ dns, tls, http, challenge or auth), back-channel logout, the referral
447
+ platform, email, the consent manager and SDK versions. Exits 1 when a check
448
+ fails. --no-probe uses recorded deliveries only (no live calls).`,
253
449
  env: `atlas env — print deploy variables without secrets
254
450
 
255
- Usage: atlas env --product <name> [--instance-env <env>] [--format dotenv|coolify|vercel] [--json]
451
+ Usage: atlas env [--product <name> [--instance-env <env>]] [--format dotenv|coolify|vercel|k8s] [--json]
256
452
 
257
453
  Public values (publishable key, Frontend API, issuer, discovery and JWKS URLs,
258
454
  OAuth client id) are printed as-is. Secrets are printed as references to their
259
455
  0600 files: *_FILE=<path> (dotenv), KEY=@<path> (coolify), or a vercel env add
260
- command that pipes the value from the file (vercel).`,
456
+ command that pipes the value from the file (vercel). k8s prints a ConfigMap plus
457
+ kubectl create secret commands that read each file. Without --product it reads
458
+ the public values from the instance your key belongs to (no secret references).
459
+ Both ATLAS_API_BASE and ATLAS_API_URL are printed.`,
261
460
  client: `atlas client — OAuth clients
262
461
 
263
462
  Usage: atlas client rotate <client-id> [--now | --overlap <seconds>]
@@ -276,6 +475,7 @@ Usage:
276
475
  Usage:
277
476
  atlas config export [--dir <path>] [--format json|yaml]
278
477
  atlas config import [--dir <path>] [--format json|yaml] [--dry-run] [--prune]
478
+ atlas config plan [--dir <path>] [--format json|yaml] [--prune] [--exit-code] [--json]
279
479
 
280
480
  export Read the instance's current config (instance/auth config, OAuth clients
281
481
  and providers, SSO connections, resource servers, JWT templates, roles,
@@ -290,6 +490,10 @@ import Diff the directory against live config and apply creates/updates
290
490
  --dir config directory (default: ./atlas-config)
291
491
  --format json (default) or yaml
292
492
 
493
+ plan A Terraform-style, read-only diff of the directory against the live
494
+ instance: field-by-field before -> after for updates. --exit-code exits 2
495
+ when there is drift (for CI); --json for tooling.
496
+
293
497
  Secrets never live on disk. Inject a credential at import with a \${ENV_VAR}
294
498
  placeholder in a file (e.g. a provider "client_secret": "\${GOOGLE_SECRET}").`,
295
499
  actions: `atlas actions — manage Actions (tenant code run in the auth pipeline)
package/dist/help.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"help.js","sourceRoot":"","sources":["../src/help.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;;AAEU,QAAA,QAAQ,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;wDAkDgC,CAAC;AAEzD,oDAAoD;AACvC,QAAA,YAAY,GAA2B;IAClD,OAAO,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;8CAyBmC;IAC5C,IAAI,EAAE;;;;;;;;;;gEAUwD;IAC9D,MAAM,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;2EAyBiE;IACzE,GAAG,EAAE;;;;;;;;;;;;;;;+CAewC;IAC7C,SAAS,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yEAmC4D;IAEvE,KAAK,EAAE;;;;;;mCAM0B;IAEjC,MAAM,EAAE;;uCAE6B;IAErC,MAAM,EAAE;;gDAEsC;IAE9C,KAAK,EAAE;;;;;;wCAM+B;IAEtC,IAAI,EAAE;;;;;uCAK+B;IAErC,UAAU,EAAE;;;;;;8CAMgC;IAE5C,QAAQ,EAAE;;;;;;0EAM8D;IAExE,IAAI,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;yEA4BiE;IAEvE,SAAS,EAAE;;;;;;oDAMuC;IAElD,GAAG,EAAE;;;;;;;qDAO8C;IAEnD,MAAM,EAAE;;;;;;;;wDAQ8C;IAEtD,QAAQ,EAAE;;;8CAGkC;IAE5C,MAAM,EAAE;;;;;;;;;;;;;;;;;;;;8EAoBoE;IAC5E,OAAO,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;qEA0B0D;CACpE,CAAC"}
1
+ {"version":3,"file":"help.js","sourceRoot":"","sources":["../src/help.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;;AAEU,QAAA,QAAQ,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;wDAqEgC,CAAC;AAEzD,oDAAoD;AACvC,QAAA,YAAY,GAA2B;IAClD,OAAO,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8CAyDmC;IAC5C,IAAI,EAAE;;;;;;;;;;gEAUwD;IAC9D,MAAM,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2EAmCiE;IACzE,GAAG,EAAE;;;;;;;;;;;;;;;+CAewC;IAC7C,MAAM,EAAE;;;;;;;;;;;;sCAY4B;IACpC,SAAS,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yEAkD4D;IAEvE,KAAK,EAAE;;;;;;;;;;;;;;2BAckB;IAEzB,KAAK,EAAE;;;;;4CAKmC;IAE1C,IAAI,EAAE;;;;;;;;;;;;qBAYa;IAEnB,MAAM,EAAE;;uCAE6B;IAErC,MAAM,EAAE;;gDAEsC;IAE9C,KAAK,EAAE;;;;;;wCAM+B;IAEtC,IAAI,EAAE;;;;;uCAK+B;IAErC,UAAU,EAAE;;;;;;8CAMgC;IAE5C,QAAQ,EAAE;;;;;;;;;;;;;;;;;;;;4DAoBgD;IAC1D,MAAM,EAAE;;;;;;;;;;;;gFAYsE;IAC9E,aAAa,EAAE;;;;;;;;;gFAS+D;IAC9E,GAAG,EAAE;;;;;;;;;;;;;;;+DAewD;IAE7D,YAAY,EAAE;;;;;;;;;;;;;;qCAcqB;IAEnC,IAAI,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yEA+BiE;IAEvE,SAAS,EAAE;;;;;;oDAMuC;IAElD,MAAM,EAAE;;;;;;;;iEAQuD;IAE/D,GAAG,EAAE;;;;;;;;;;mDAU4C;IAEjD,MAAM,EAAE;;;;;;;;wDAQ8C;IAEtD,QAAQ,EAAE;;;8CAGkC;IAE5C,MAAM,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;8EAyBoE;IAC5E,OAAO,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;qEA0B0D;CACpE,CAAC"}
package/dist/index.d.ts CHANGED
@@ -25,3 +25,7 @@ export { preflight, envCommand, client } from './commands/project-commands';
25
25
  export { referrals } from './commands/referrals';
26
26
  export { writeSecretFile, readEnvFile, parseDotenv, renderDotenv, productDir, deliverSecret, } from './secrets';
27
27
  export { readManifest, writeManifest, manifestPath, type ProjectManifest, type ProjectInstance, type InstanceEnv, } from './project';
28
+ export { migrate } from './commands/migrate';
29
+ export { planConfigImport, type ConfigPlan, type PlannedChange } from './commands/config';
30
+ export { translateBetterAuth, type Translation, type ReportEntry, type ConfigDocument } from './migrate/better-auth/translate';
31
+ export { migrateBetterAuth, STEPS as BETTER_AUTH_MIGRATION_STEPS } from './migrate/better-auth/orchestrator';
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.manifestPath = exports.writeManifest = exports.readManifest = exports.deliverSecret = exports.productDir = exports.renderDotenv = exports.parseDotenv = exports.readEnvFile = exports.writeSecretFile = exports.referrals = exports.client = exports.envCommand = exports.preflight = exports.init = exports.actions = exports.config = exports.sessions = exports.webhooks = exports.apiKeys = exports.orgs = exports.users = exports.whoami = exports.logout = exports.login = exports.getVersion = exports.defaultPrompter = exports.defaultConfigPath = exports.MemoryConfigStore = exports.FileConfigStore = exports.captureIO = exports.defaultIO = exports.CliError = exports.isNotFound = exports.createConfigHttp = exports.defaultContext = exports.run = void 0;
3
+ exports.BETTER_AUTH_MIGRATION_STEPS = exports.migrateBetterAuth = exports.translateBetterAuth = exports.planConfigImport = exports.migrate = exports.manifestPath = exports.writeManifest = exports.readManifest = exports.deliverSecret = exports.productDir = exports.renderDotenv = exports.parseDotenv = exports.readEnvFile = exports.writeSecretFile = exports.referrals = exports.client = exports.envCommand = exports.preflight = exports.init = exports.actions = exports.config = exports.sessions = exports.webhooks = exports.apiKeys = exports.orgs = exports.users = exports.whoami = exports.logout = exports.login = exports.getVersion = exports.defaultPrompter = exports.defaultConfigPath = exports.MemoryConfigStore = exports.FileConfigStore = exports.captureIO = exports.defaultIO = exports.CliError = exports.isNotFound = exports.createConfigHttp = exports.defaultContext = exports.run = void 0;
4
4
  /**
5
5
  * Library surface of `@atlasauth/cli`. The package ships a bin (`atlas`), but
6
6
  * exporting the pieces lets the handlers be unit-tested with injected deps and
@@ -65,4 +65,13 @@ var project_1 = require("./project");
65
65
  Object.defineProperty(exports, "readManifest", { enumerable: true, get: function () { return project_1.readManifest; } });
66
66
  Object.defineProperty(exports, "writeManifest", { enumerable: true, get: function () { return project_1.writeManifest; } });
67
67
  Object.defineProperty(exports, "manifestPath", { enumerable: true, get: function () { return project_1.manifestPath; } });
68
+ var migrate_1 = require("./commands/migrate");
69
+ Object.defineProperty(exports, "migrate", { enumerable: true, get: function () { return migrate_1.migrate; } });
70
+ var config_3 = require("./commands/config");
71
+ Object.defineProperty(exports, "planConfigImport", { enumerable: true, get: function () { return config_3.planConfigImport; } });
72
+ var translate_1 = require("./migrate/better-auth/translate");
73
+ Object.defineProperty(exports, "translateBetterAuth", { enumerable: true, get: function () { return translate_1.translateBetterAuth; } });
74
+ var orchestrator_1 = require("./migrate/better-auth/orchestrator");
75
+ Object.defineProperty(exports, "migrateBetterAuth", { enumerable: true, get: function () { return orchestrator_1.migrateBetterAuth; } });
76
+ Object.defineProperty(exports, "BETTER_AUTH_MIGRATION_STEPS", { enumerable: true, get: function () { return orchestrator_1.STEPS; } });
68
77
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA;;;;;GAKG;AACH,6BAA0C;AAAjC,0FAAA,GAAG,OAAA;AACZ,qCAAmF;AAA1E,yGAAA,cAAc,OAAA;AACvB,6CAA8E;AAArE,+GAAA,gBAAgB,OAAA;AAAE,yGAAA,UAAU,OAAA;AACrC,mCAAoC;AAA3B,kGAAA,QAAQ,OAAA;AACjB,2BAAqE;AAA5D,+FAAA,SAAS,OAAA;AAAE,+FAAA,SAAS,OAAA;AAC7B,mCAOkB;AANhB,yGAAA,eAAe,OAAA;AACf,2GAAA,iBAAiB,OAAA;AACjB,2GAAA,iBAAiB,OAAA;AAKnB,mCAA0D;AAAjD,yGAAA,eAAe,OAAA;AACxB,qCAAuC;AAA9B,qGAAA,UAAU,OAAA;AAEnB,0EAA0E;AAC1E,wCAAwD;AAA/C,6FAAA,KAAK,OAAA;AAAE,8FAAA,MAAM,OAAA;AAAE,8FAAA,MAAM,OAAA;AAC9B,0CAAyC;AAAhC,8FAAA,KAAK,OAAA;AACd,wCAAuC;AAA9B,4FAAA,IAAI,OAAA;AACb,gDAA8C;AAArC,mGAAA,OAAO,OAAA;AAChB,gDAA+C;AAAtC,oGAAA,QAAQ,OAAA;AACjB,gDAA+C;AAAtC,oGAAA,QAAQ,OAAA;AACjB,4CAA2C;AAAlC,gGAAA,MAAM,OAAA;AACf,8CAA6C;AAApC,kGAAA,OAAO,OAAA;AAChB,wCAAuC;AAA9B,4FAAA,IAAI,OAAA;AACb,gEAA4E;AAAnE,6GAAA,SAAS,OAAA;AAAE,8GAAA,UAAU,OAAA;AAAE,0GAAA,MAAM,OAAA;AACtC,kDAAiD;AAAxC,sGAAA,SAAS,OAAA;AAClB,qCAOmB;AANjB,0GAAA,eAAe,OAAA;AACf,sGAAA,WAAW,OAAA;AACX,sGAAA,WAAW,OAAA;AACX,uGAAA,YAAY,OAAA;AACZ,qGAAA,UAAU,OAAA;AACV,wGAAA,aAAa,OAAA;AAEf,qCAOmB;AANjB,uGAAA,YAAY,OAAA;AACZ,wGAAA,aAAa,OAAA;AACb,uGAAA,YAAY,OAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA;;;;;GAKG;AACH,6BAA0C;AAAjC,0FAAA,GAAG,OAAA;AACZ,qCAAmF;AAA1E,yGAAA,cAAc,OAAA;AACvB,6CAA8E;AAArE,+GAAA,gBAAgB,OAAA;AAAE,yGAAA,UAAU,OAAA;AACrC,mCAAoC;AAA3B,kGAAA,QAAQ,OAAA;AACjB,2BAAqE;AAA5D,+FAAA,SAAS,OAAA;AAAE,+FAAA,SAAS,OAAA;AAC7B,mCAOkB;AANhB,yGAAA,eAAe,OAAA;AACf,2GAAA,iBAAiB,OAAA;AACjB,2GAAA,iBAAiB,OAAA;AAKnB,mCAA0D;AAAjD,yGAAA,eAAe,OAAA;AACxB,qCAAuC;AAA9B,qGAAA,UAAU,OAAA;AAEnB,0EAA0E;AAC1E,wCAAwD;AAA/C,6FAAA,KAAK,OAAA;AAAE,8FAAA,MAAM,OAAA;AAAE,8FAAA,MAAM,OAAA;AAC9B,0CAAyC;AAAhC,8FAAA,KAAK,OAAA;AACd,wCAAuC;AAA9B,4FAAA,IAAI,OAAA;AACb,gDAA8C;AAArC,mGAAA,OAAO,OAAA;AAChB,gDAA+C;AAAtC,oGAAA,QAAQ,OAAA;AACjB,gDAA+C;AAAtC,oGAAA,QAAQ,OAAA;AACjB,4CAA2C;AAAlC,gGAAA,MAAM,OAAA;AACf,8CAA6C;AAApC,kGAAA,OAAO,OAAA;AAChB,wCAAuC;AAA9B,4FAAA,IAAI,OAAA;AACb,gEAA4E;AAAnE,6GAAA,SAAS,OAAA;AAAE,8GAAA,UAAU,OAAA;AAAE,0GAAA,MAAM,OAAA;AACtC,kDAAiD;AAAxC,sGAAA,SAAS,OAAA;AAClB,qCAOmB;AANjB,0GAAA,eAAe,OAAA;AACf,sGAAA,WAAW,OAAA;AACX,sGAAA,WAAW,OAAA;AACX,uGAAA,YAAY,OAAA;AACZ,qGAAA,UAAU,OAAA;AACV,wGAAA,aAAa,OAAA;AAEf,qCAOmB;AANjB,uGAAA,YAAY,OAAA;AACZ,wGAAA,aAAa,OAAA;AACb,uGAAA,YAAY,OAAA;AAKd,8CAA6C;AAApC,kGAAA,OAAO,OAAA;AAChB,4CAA0F;AAAjF,0GAAA,gBAAgB,OAAA;AACzB,6DAA+H;AAAtH,gHAAA,mBAAmB,OAAA;AAC5B,mEAA6G;AAApG,iHAAA,iBAAiB,OAAA;AAAE,2HAAA,KAAK,OAA+B"}
@@ -0,0 +1,59 @@
1
+ import { type BetterAuthImport, type BetterAuthImportOptions } from '@atlasauth/backend';
2
+ import type { ConfigHttp } from '../../config-http';
3
+ /**
4
+ * Every call the Better Auth migration makes into the import and session-bridge
5
+ * APIs lives in this one module:
6
+ *
7
+ * - the export/import pair: the `@atlasauth/better-auth-migrate` exporter seals
8
+ * a bundle to the instance's import key (`GET /v1/better_auth_imports/public_key`),
9
+ * which is uploaded in line-split parts, finalized (which runs the dry run)
10
+ * and applied under `/v1/better_auth_imports`, and
11
+ * - the session bridge (`/v1/migrations/better_auth/bridge`), which lets a live
12
+ * Better Auth session become an Atlas session during the cutover window.
13
+ */
14
+ /** The exporter's documented command line. */
15
+ export declare const EXPORTER_BIN = "atlas-better-auth-export";
16
+ export declare const EXPORTER_PACKAGE = "@atlasauth/better-auth-migrate";
17
+ /** `publicKey` is the key's compact `kid:public_key` form. */
18
+ export declare function exporterCommand(opts: {
19
+ out: string;
20
+ publicKey: string;
21
+ }): {
22
+ cmd: string;
23
+ args: string[];
24
+ display: string;
25
+ };
26
+ /** The import key the exporter seals the bundle to (the private half stays with Atlas), as `kid:public_key`. */
27
+ export declare function getImportPublicKey(http: ConfigHttp): Promise<string>;
28
+ export type ImportJob = BetterAuthImport;
29
+ /** Statuses an import rests in; anything else is still being worked on. */
30
+ export declare const RESTING_STATUSES: readonly string[];
31
+ /**
32
+ * Upload a sealed bundle: create the import, send it in line-split parts of at
33
+ * most 8 MiB, then finalize (which checks the parts and the key and runs the
34
+ * dry run; a large bundle comes back `analyzing` and finishes in the background).
35
+ */
36
+ export declare function uploadBundle(http: ConfigHttp, opts: {
37
+ bundle: string;
38
+ options?: BetterAuthImportOptions;
39
+ onPart?: (n: number, of: number) => void;
40
+ }): Promise<ImportJob>;
41
+ export declare function getImport(http: ConfigHttp, id: string): Promise<ImportJob>;
42
+ /** Finalize an import whose upload finished but was never finalized. */
43
+ export declare function finalizeImport(http: ConfigHttp, id: string): Promise<ImportJob>;
44
+ /** Apply a dry-run-ready import, or resume a failed one from where it stopped. */
45
+ export declare function applyImport(http: ConfigHttp, id: string, opts: {
46
+ confirmConflicts: boolean;
47
+ }): Promise<ImportJob>;
48
+ export interface BridgeSettings {
49
+ /** Better Auth's `advanced.cookiePrefix` (default `better-auth`). */
50
+ cookiePrefix: string;
51
+ /** When the bridge stops accepting Better Auth sessions (epoch ms). */
52
+ endsAt: number;
53
+ }
54
+ /**
55
+ * Turn the Better Auth session bridge on for a window. The old app's Better
56
+ * Auth secret is stored write-only so Atlas can check the cookie signature
57
+ * (the live fallback to the old app stays off unless set up separately).
58
+ */
59
+ export declare function enableSessionBridge(http: ConfigHttp, settings: BridgeSettings, secret: string): Promise<void>;
@@ -0,0 +1,81 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RESTING_STATUSES = exports.EXPORTER_PACKAGE = exports.EXPORTER_BIN = void 0;
4
+ exports.exporterCommand = exporterCommand;
5
+ exports.getImportPublicKey = getImportPublicKey;
6
+ exports.uploadBundle = uploadBundle;
7
+ exports.getImport = getImport;
8
+ exports.finalizeImport = finalizeImport;
9
+ exports.applyImport = applyImport;
10
+ exports.enableSessionBridge = enableSessionBridge;
11
+ const backend_1 = require("@atlasauth/backend");
12
+ /**
13
+ * Every call the Better Auth migration makes into the import and session-bridge
14
+ * APIs lives in this one module:
15
+ *
16
+ * - the export/import pair: the `@atlasauth/better-auth-migrate` exporter seals
17
+ * a bundle to the instance's import key (`GET /v1/better_auth_imports/public_key`),
18
+ * which is uploaded in line-split parts, finalized (which runs the dry run)
19
+ * and applied under `/v1/better_auth_imports`, and
20
+ * - the session bridge (`/v1/migrations/better_auth/bridge`), which lets a live
21
+ * Better Auth session become an Atlas session during the cutover window.
22
+ */
23
+ /** The exporter's documented command line. */
24
+ exports.EXPORTER_BIN = 'atlas-better-auth-export';
25
+ exports.EXPORTER_PACKAGE = '@atlasauth/better-auth-migrate';
26
+ /** `publicKey` is the key's compact `kid:public_key` form. */
27
+ function exporterCommand(opts) {
28
+ const args = ['--yes', exports.EXPORTER_BIN, '--out', opts.out, '--public-key', opts.publicKey];
29
+ return { cmd: 'npx', args, display: `npx ${exports.EXPORTER_BIN} --out ${opts.out} --public-key ${opts.publicKey}` };
30
+ }
31
+ /** The import key the exporter seals the bundle to (the private half stays with Atlas), as `kid:public_key`. */
32
+ async function getImportPublicKey(http) {
33
+ const key = await http.get('/v1/better_auth_imports/public_key');
34
+ if (!key?.compact)
35
+ throw new Error('The instance did not return an import key.');
36
+ return key.compact;
37
+ }
38
+ /** Statuses an import rests in; anything else is still being worked on. */
39
+ exports.RESTING_STATUSES = ['uploading', 'ready', 'invalid', 'completed', 'failed'];
40
+ const importPath = (id, sub = '') => `/v1/better_auth_imports/${encodeURIComponent(id)}${sub}`;
41
+ /**
42
+ * Upload a sealed bundle: create the import, send it in line-split parts of at
43
+ * most 8 MiB, then finalize (which checks the parts and the key and runs the
44
+ * dry run; a large bundle comes back `analyzing` and finishes in the background).
45
+ */
46
+ async function uploadBundle(http, opts) {
47
+ const parts = (0, backend_1.splitBundleParts)(opts.bundle);
48
+ if (parts.length === 0)
49
+ throw new Error('The bundle is empty.');
50
+ const created = await http.post('/v1/better_auth_imports', opts.options ? { options: opts.options } : {});
51
+ for (let i = 0; i < parts.length; i++) {
52
+ await http.put(importPath(created.id, `/parts/${i + 1}`), { data: parts[i] });
53
+ opts.onPart?.(i + 1, parts.length);
54
+ }
55
+ return http.post(importPath(created.id, '/finalize'), {});
56
+ }
57
+ async function getImport(http, id) {
58
+ return http.get(importPath(id));
59
+ }
60
+ /** Finalize an import whose upload finished but was never finalized. */
61
+ async function finalizeImport(http, id) {
62
+ return http.post(importPath(id, '/finalize'), {});
63
+ }
64
+ /** Apply a dry-run-ready import, or resume a failed one from where it stopped. */
65
+ async function applyImport(http, id, opts) {
66
+ return http.post(importPath(id, '/apply'), opts.confirmConflicts ? { confirm_conflicts: true } : {});
67
+ }
68
+ /**
69
+ * Turn the Better Auth session bridge on for a window. The old app's Better
70
+ * Auth secret is stored write-only so Atlas can check the cookie signature
71
+ * (the live fallback to the old app stays off unless set up separately).
72
+ */
73
+ async function enableSessionBridge(http, settings, secret) {
74
+ await http.put('/v1/migrations/better_auth/bridge', {
75
+ enabled: true,
76
+ ends_at: settings.endsAt,
77
+ cookie_prefix: settings.cookiePrefix,
78
+ live_fallback: { secret },
79
+ });
80
+ }
81
+ //# sourceMappingURL=integration.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"integration.js","sourceRoot":"","sources":["../../../src/migrate/better-auth/integration.ts"],"names":[],"mappings":";;;AAoBA,0CAGC;AAGD,gDAIC;AAcD,oCAYC;AAED,8BAEC;AAGD,wCAEC;AAGD,kCAEC;AAcD,kDAOC;AA3FD,gDAAqI;AAGrI;;;;;;;;;;GAUG;AAEH,8CAA8C;AACjC,QAAA,YAAY,GAAG,0BAA0B,CAAC;AAC1C,QAAA,gBAAgB,GAAG,gCAAgC,CAAC;AAEjE,8DAA8D;AAC9D,SAAgB,eAAe,CAAC,IAAwC;IACtE,MAAM,IAAI,GAAG,CAAC,OAAO,EAAE,oBAAY,EAAE,OAAO,EAAE,IAAI,CAAC,GAAG,EAAE,cAAc,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;IACxF,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,oBAAY,UAAU,IAAI,CAAC,GAAG,iBAAiB,IAAI,CAAC,SAAS,EAAE,EAAE,CAAC;AAC/G,CAAC;AAED,gHAAgH;AACzG,KAAK,UAAU,kBAAkB,CAAC,IAAgB;IACvD,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,GAAG,CAAsB,oCAAoC,CAAC,CAAC;IACtF,IAAI,CAAC,GAAG,EAAE,OAAO;QAAE,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;IACjF,OAAO,GAAG,CAAC,OAAO,CAAC;AACrB,CAAC;AAID,2EAA2E;AAC9D,QAAA,gBAAgB,GAAsB,CAAC,WAAW,EAAE,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,QAAQ,CAAC,CAAC;AAE5G,MAAM,UAAU,GAAG,CAAC,EAAU,EAAE,GAAG,GAAG,EAAE,EAAE,EAAE,CAAC,2BAA2B,kBAAkB,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC;AAEvG;;;;GAIG;AACI,KAAK,UAAU,YAAY,CAChC,IAAgB,EAChB,IAAqG;IAErG,MAAM,KAAK,GAAG,IAAA,0BAAgB,EAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC5C,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAC;IAChE,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,IAAI,CAAY,yBAAyB,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACrH,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,MAAM,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,EAAE,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAC9E,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IACrC,CAAC;IACD,OAAO,IAAI,CAAC,IAAI,CAAY,UAAU,CAAC,OAAO,CAAC,EAAE,EAAE,WAAW,CAAC,EAAE,EAAE,CAAC,CAAC;AACvE,CAAC;AAEM,KAAK,UAAU,SAAS,CAAC,IAAgB,EAAE,EAAU;IAC1D,OAAO,IAAI,CAAC,GAAG,CAAY,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC;AAC7C,CAAC;AAED,wEAAwE;AACjE,KAAK,UAAU,cAAc,CAAC,IAAgB,EAAE,EAAU;IAC/D,OAAO,IAAI,CAAC,IAAI,CAAY,UAAU,CAAC,EAAE,EAAE,WAAW,CAAC,EAAE,EAAE,CAAC,CAAC;AAC/D,CAAC;AAED,kFAAkF;AAC3E,KAAK,UAAU,WAAW,CAAC,IAAgB,EAAE,EAAU,EAAE,IAAmC;IACjG,OAAO,IAAI,CAAC,IAAI,CAAY,UAAU,CAAC,EAAE,EAAE,QAAQ,CAAC,EAAE,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAAE,iBAAiB,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;AAClH,CAAC;AASD;;;;GAIG;AACI,KAAK,UAAU,mBAAmB,CAAC,IAAgB,EAAE,QAAwB,EAAE,MAAc;IAClG,MAAM,IAAI,CAAC,GAAG,CAAC,mCAAmC,EAAE;QAClD,OAAO,EAAE,IAAI;QACb,OAAO,EAAE,QAAQ,CAAC,MAAM;QACxB,aAAa,EAAE,QAAQ,CAAC,YAAY;QACpC,aAAa,EAAE,EAAE,MAAM,EAAE;KAC1B,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,43 @@
1
+ import { type ParsedArgs } from '../../args';
2
+ import type { RunContext } from '../../context';
3
+ import { type Json } from '../../serialize';
4
+ /**
5
+ * `atlas migrate better-auth [path]` — the whole Better Auth → Atlas program as
6
+ * one resumable run:
7
+ *
8
+ * preflight → translate → apply (review the diff, confirm, config push) →
9
+ * export (the exporter runs in the app) → import (dry run, confirm, apply) →
10
+ * bridge (no forced logout) → code (the codemod) → verify (checklist).
11
+ *
12
+ * Each finished step is checkpointed in the state file, so `--resume` carries
13
+ * on where a run stopped (a confirmation declined, an env var missing, the
14
+ * export not run yet). `--dry-run` walks every step without changing the
15
+ * instance or the code; `--yes` answers every confirmation.
16
+ */
17
+ export declare const STEPS: readonly ["preflight", "translate", "apply", "export", "import", "bridge", "code", "verify"];
18
+ export type StepId = (typeof STEPS)[number];
19
+ type StepStatus = 'done' | 'skipped' | 'planned' | 'action_needed' | 'awaiting_confirmation' | 'blocked';
20
+ interface StepRecord {
21
+ status: StepStatus;
22
+ at?: number;
23
+ detail?: Record<string, unknown>;
24
+ message?: string;
25
+ }
26
+ export interface MigrationState {
27
+ version: 1;
28
+ project: string;
29
+ instance_id: string | null;
30
+ environment: string | null;
31
+ started_at: number;
32
+ steps: Partial<Record<StepId, StepRecord>>;
33
+ }
34
+ /** `${NAME}` placeholders in the config files that the environment does not set. */
35
+ export declare function missingPlaceholders(dir: string, env: NodeJS.ProcessEnv): Set<string>;
36
+ /** Leaves of `desired` that differ from `live` (arrays compare as a whole). */
37
+ export declare function leafDiff(desired: Json, live: Json, prefix?: string): Array<{
38
+ path: string;
39
+ from: Json | undefined;
40
+ to: Json;
41
+ }>;
42
+ export declare function migrateBetterAuth(ctx: RunContext, args: ParsedArgs, projectArg: string | undefined): Promise<number>;
43
+ export {};