@nebulr-group/bridge-cli 0.6.6 → 1.0.0-alpha.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 (293) hide show
  1. package/README.md +93 -460
  2. package/dist/api/accounts.d.ts +69 -0
  3. package/dist/api/accounts.d.ts.map +1 -0
  4. package/dist/api/accounts.js +42 -0
  5. package/dist/api/accounts.js.map +1 -0
  6. package/dist/api/apps.d.ts +50 -0
  7. package/dist/api/apps.d.ts.map +1 -0
  8. package/dist/api/apps.js +62 -0
  9. package/dist/api/apps.js.map +1 -0
  10. package/dist/api/billing.d.ts +131 -0
  11. package/dist/api/billing.d.ts.map +1 -0
  12. package/dist/api/billing.js +42 -0
  13. package/dist/api/billing.js.map +1 -0
  14. package/dist/api/flags.d.ts +73 -0
  15. package/dist/api/flags.d.ts.map +1 -0
  16. package/dist/api/flags.js +108 -0
  17. package/dist/api/flags.js.map +1 -0
  18. package/dist/api/keys.d.ts +48 -0
  19. package/dist/api/keys.d.ts.map +1 -0
  20. package/dist/api/keys.js +87 -0
  21. package/dist/api/keys.js.map +1 -0
  22. package/dist/auth/browser-open.d.ts +21 -4
  23. package/dist/auth/browser-open.d.ts.map +1 -1
  24. package/dist/auth/browser-open.js +45 -65
  25. package/dist/auth/browser-open.js.map +1 -1
  26. package/dist/auth/lock.d.ts +8 -0
  27. package/dist/auth/lock.d.ts.map +1 -0
  28. package/dist/auth/lock.js +43 -0
  29. package/dist/auth/lock.js.map +1 -0
  30. package/dist/auth/loopback.d.ts +8 -12
  31. package/dist/auth/loopback.d.ts.map +1 -1
  32. package/dist/auth/loopback.js +40 -45
  33. package/dist/auth/loopback.js.map +1 -1
  34. package/dist/auth/session.d.ts +61 -0
  35. package/dist/auth/session.d.ts.map +1 -0
  36. package/dist/auth/session.js +142 -0
  37. package/dist/auth/session.js.map +1 -0
  38. package/dist/auth/sign-in.d.ts +67 -0
  39. package/dist/auth/sign-in.d.ts.map +1 -0
  40. package/dist/auth/sign-in.js +113 -0
  41. package/dist/auth/sign-in.js.map +1 -0
  42. package/dist/auth/store.d.ts +89 -0
  43. package/dist/auth/store.d.ts.map +1 -0
  44. package/dist/auth/store.js +214 -0
  45. package/dist/auth/store.js.map +1 -0
  46. package/dist/bin.js +0 -2
  47. package/dist/bin.js.map +1 -1
  48. package/dist/cli.d.ts +1 -2
  49. package/dist/cli.d.ts.map +1 -1
  50. package/dist/cli.js +13 -17
  51. package/dist/cli.js.map +1 -1
  52. package/dist/client.d.ts +31 -0
  53. package/dist/client.d.ts.map +1 -0
  54. package/dist/client.js +67 -0
  55. package/dist/client.js.map +1 -0
  56. package/dist/commands/accounts.command.d.ts +4 -0
  57. package/dist/commands/accounts.command.d.ts.map +1 -0
  58. package/dist/commands/accounts.command.js +116 -0
  59. package/dist/commands/accounts.command.js.map +1 -0
  60. package/dist/commands/app.command.d.ts +3 -2
  61. package/dist/commands/app.command.d.ts.map +1 -1
  62. package/dist/commands/app.command.js +132 -233
  63. package/dist/commands/app.command.js.map +1 -1
  64. package/dist/commands/auth.command.d.ts +2 -12
  65. package/dist/commands/auth.command.d.ts.map +1 -1
  66. package/dist/commands/auth.command.js +147 -20
  67. package/dist/commands/auth.command.js.map +1 -1
  68. package/dist/commands/billing.command.d.ts +4 -0
  69. package/dist/commands/billing.command.d.ts.map +1 -0
  70. package/dist/commands/billing.command.js +185 -0
  71. package/dist/commands/billing.command.js.map +1 -0
  72. package/dist/commands/check.command.d.ts +2 -1
  73. package/dist/commands/check.command.d.ts.map +1 -1
  74. package/dist/commands/check.command.js +11 -14
  75. package/dist/commands/check.command.js.map +1 -1
  76. package/dist/commands/context.d.ts +58 -0
  77. package/dist/commands/context.d.ts.map +1 -0
  78. package/dist/commands/context.js +78 -0
  79. package/dist/commands/context.js.map +1 -0
  80. package/dist/commands/flag.command.d.ts +3 -62
  81. package/dist/commands/flag.command.d.ts.map +1 -1
  82. package/dist/commands/flag.command.js +181 -864
  83. package/dist/commands/flag.command.js.map +1 -1
  84. package/dist/commands/key.command.d.ts +4 -0
  85. package/dist/commands/key.command.d.ts.map +1 -0
  86. package/dist/commands/key.command.js +44 -0
  87. package/dist/commands/key.command.js.map +1 -0
  88. package/dist/commands/plan.command.d.ts +3 -203
  89. package/dist/commands/plan.command.d.ts.map +1 -1
  90. package/dist/commands/plan.command.js +200 -759
  91. package/dist/commands/plan.command.js.map +1 -1
  92. package/dist/config.d.ts +19 -101
  93. package/dist/config.d.ts.map +1 -1
  94. package/dist/config.js +51 -364
  95. package/dist/config.js.map +1 -1
  96. package/dist/core/discovery.d.ts +27 -0
  97. package/dist/core/discovery.d.ts.map +1 -0
  98. package/dist/core/discovery.js +97 -0
  99. package/dist/core/discovery.js.map +1 -0
  100. package/dist/core/errors.d.ts +26 -0
  101. package/dist/core/errors.d.ts.map +1 -0
  102. package/dist/core/errors.js +33 -0
  103. package/dist/core/errors.js.map +1 -0
  104. package/dist/core/http.d.ts +23 -0
  105. package/dist/core/http.d.ts.map +1 -0
  106. package/dist/core/http.js +153 -0
  107. package/dist/core/http.js.map +1 -0
  108. package/dist/core/private-files.d.ts +6 -0
  109. package/dist/core/private-files.d.ts.map +1 -0
  110. package/dist/core/private-files.js +96 -0
  111. package/dist/core/private-files.js.map +1 -0
  112. package/dist/core/routes.d.ts +94 -0
  113. package/dist/core/routes.d.ts.map +1 -0
  114. package/dist/core/routes.js +91 -0
  115. package/dist/core/routes.js.map +1 -0
  116. package/dist/core/urls.d.ts +15 -0
  117. package/dist/core/urls.d.ts.map +1 -0
  118. package/dist/core/urls.js +55 -0
  119. package/dist/core/urls.js.map +1 -0
  120. package/dist/gate-rules.d.ts +1 -2
  121. package/dist/gate-rules.d.ts.map +1 -1
  122. package/dist/gate-rules.js +4 -5
  123. package/dist/gate-rules.js.map +1 -1
  124. package/dist/index.d.ts +23 -3
  125. package/dist/index.d.ts.map +1 -1
  126. package/dist/index.js +18 -3
  127. package/dist/index.js.map +1 -1
  128. package/dist/io.d.ts +21 -0
  129. package/dist/io.d.ts.map +1 -0
  130. package/dist/io.js +59 -0
  131. package/dist/io.js.map +1 -0
  132. package/dist/money.d.ts +42 -0
  133. package/dist/money.d.ts.map +1 -0
  134. package/dist/money.js +112 -0
  135. package/dist/money.js.map +1 -0
  136. package/dist/program.d.ts +5 -24
  137. package/dist/program.d.ts.map +1 -1
  138. package/dist/program.js +25 -113
  139. package/dist/program.js.map +1 -1
  140. package/package.json +7 -8
  141. package/dist/auth/api-client.d.ts +0 -50
  142. package/dist/auth/api-client.d.ts.map +0 -1
  143. package/dist/auth/api-client.js +0 -109
  144. package/dist/auth/api-client.js.map +0 -1
  145. package/dist/auth/relative-time.d.ts +0 -2
  146. package/dist/auth/relative-time.d.ts.map +0 -1
  147. package/dist/auth/relative-time.js +0 -27
  148. package/dist/auth/relative-time.js.map +0 -1
  149. package/dist/auth/scopes.d.ts +0 -30
  150. package/dist/auth/scopes.d.ts.map +0 -1
  151. package/dist/auth/scopes.js +0 -39
  152. package/dist/auth/scopes.js.map +0 -1
  153. package/dist/auth/workspace-client.d.ts +0 -70
  154. package/dist/auth/workspace-client.d.ts.map +0 -1
  155. package/dist/auth/workspace-client.js +0 -105
  156. package/dist/auth/workspace-client.js.map +0 -1
  157. package/dist/commands/auth/config.command.d.ts +0 -8
  158. package/dist/commands/auth/config.command.d.ts.map +0 -1
  159. package/dist/commands/auth/config.command.js +0 -60
  160. package/dist/commands/auth/config.command.js.map +0 -1
  161. package/dist/commands/auth/login.command.d.ts +0 -46
  162. package/dist/commands/auth/login.command.d.ts.map +0 -1
  163. package/dist/commands/auth/login.command.js +0 -166
  164. package/dist/commands/auth/login.command.js.map +0 -1
  165. package/dist/commands/auth/logout.command.d.ts +0 -21
  166. package/dist/commands/auth/logout.command.d.ts.map +0 -1
  167. package/dist/commands/auth/logout.command.js +0 -97
  168. package/dist/commands/auth/logout.command.js.map +0 -1
  169. package/dist/commands/auth/methods.command.d.ts +0 -68
  170. package/dist/commands/auth/methods.command.d.ts.map +0 -1
  171. package/dist/commands/auth/methods.command.js +0 -91
  172. package/dist/commands/auth/methods.command.js.map +0 -1
  173. package/dist/commands/auth/status.command.d.ts +0 -18
  174. package/dist/commands/auth/status.command.d.ts.map +0 -1
  175. package/dist/commands/auth/status.command.js +0 -104
  176. package/dist/commands/auth/status.command.js.map +0 -1
  177. package/dist/commands/auth/use.command.d.ts +0 -17
  178. package/dist/commands/auth/use.command.d.ts.map +0 -1
  179. package/dist/commands/auth/use.command.js +0 -47
  180. package/dist/commands/auth/use.command.js.map +0 -1
  181. package/dist/commands/branding.command.d.ts +0 -3
  182. package/dist/commands/branding.command.d.ts.map +0 -1
  183. package/dist/commands/branding.command.js +0 -42
  184. package/dist/commands/branding.command.js.map +0 -1
  185. package/dist/commands/event.command.d.ts +0 -3
  186. package/dist/commands/event.command.d.ts.map +0 -1
  187. package/dist/commands/event.command.js +0 -27
  188. package/dist/commands/event.command.js.map +0 -1
  189. package/dist/commands/flag-init.command.d.ts +0 -13
  190. package/dist/commands/flag-init.command.d.ts.map +0 -1
  191. package/dist/commands/flag-init.command.js +0 -463
  192. package/dist/commands/flag-init.command.js.map +0 -1
  193. package/dist/commands/guide.command.d.ts +0 -61
  194. package/dist/commands/guide.command.d.ts.map +0 -1
  195. package/dist/commands/guide.command.js +0 -655
  196. package/dist/commands/guide.command.js.map +0 -1
  197. package/dist/commands/info.command.d.ts +0 -3
  198. package/dist/commands/info.command.d.ts.map +0 -1
  199. package/dist/commands/info.command.js +0 -70
  200. package/dist/commands/info.command.js.map +0 -1
  201. package/dist/commands/integration.command.d.ts +0 -35
  202. package/dist/commands/integration.command.d.ts.map +0 -1
  203. package/dist/commands/integration.command.js +0 -290
  204. package/dist/commands/integration.command.js.map +0 -1
  205. package/dist/commands/journeys.d.ts +0 -43
  206. package/dist/commands/journeys.d.ts.map +0 -1
  207. package/dist/commands/journeys.js +0 -221
  208. package/dist/commands/journeys.js.map +0 -1
  209. package/dist/commands/ops.command.d.ts +0 -17
  210. package/dist/commands/ops.command.d.ts.map +0 -1
  211. package/dist/commands/ops.command.js +0 -129
  212. package/dist/commands/ops.command.js.map +0 -1
  213. package/dist/commands/privilege.command.d.ts +0 -16
  214. package/dist/commands/privilege.command.d.ts.map +0 -1
  215. package/dist/commands/privilege.command.js +0 -86
  216. package/dist/commands/privilege.command.js.map +0 -1
  217. package/dist/commands/role.command.d.ts +0 -3
  218. package/dist/commands/role.command.d.ts.map +0 -1
  219. package/dist/commands/role.command.js +0 -101
  220. package/dist/commands/role.command.js.map +0 -1
  221. package/dist/commands/runtime-dir.d.ts +0 -16
  222. package/dist/commands/runtime-dir.d.ts.map +0 -1
  223. package/dist/commands/runtime-dir.js +0 -18
  224. package/dist/commands/runtime-dir.js.map +0 -1
  225. package/dist/commands/setup.command.d.ts +0 -63
  226. package/dist/commands/setup.command.d.ts.map +0 -1
  227. package/dist/commands/setup.command.js +0 -148
  228. package/dist/commands/setup.command.js.map +0 -1
  229. package/dist/commands/stripe.command.d.ts +0 -29
  230. package/dist/commands/stripe.command.d.ts.map +0 -1
  231. package/dist/commands/stripe.command.js +0 -99
  232. package/dist/commands/stripe.command.js.map +0 -1
  233. package/dist/commands/tenant.command.d.ts +0 -3
  234. package/dist/commands/tenant.command.d.ts.map +0 -1
  235. package/dist/commands/tenant.command.js +0 -135
  236. package/dist/commands/tenant.command.js.map +0 -1
  237. package/dist/commands/token.command.d.ts +0 -3
  238. package/dist/commands/token.command.d.ts.map +0 -1
  239. package/dist/commands/token.command.js +0 -54
  240. package/dist/commands/token.command.js.map +0 -1
  241. package/dist/commands/user.command.d.ts +0 -3
  242. package/dist/commands/user.command.d.ts.map +0 -1
  243. package/dist/commands/user.command.js +0 -117
  244. package/dist/commands/user.command.js.map +0 -1
  245. package/dist/credentials.d.ts +0 -141
  246. package/dist/credentials.d.ts.map +0 -1
  247. package/dist/credentials.js +0 -348
  248. package/dist/credentials.js.map +0 -1
  249. package/dist/flag-coherence.d.ts +0 -42
  250. package/dist/flag-coherence.d.ts.map +0 -1
  251. package/dist/flag-coherence.js +0 -103
  252. package/dist/flag-coherence.js.map +0 -1
  253. package/dist/output.d.ts +0 -17
  254. package/dist/output.d.ts.map +0 -1
  255. package/dist/output.js +0 -107
  256. package/dist/output.js.map +0 -1
  257. package/dist/preview.d.ts +0 -9
  258. package/dist/preview.d.ts.map +0 -1
  259. package/dist/preview.js +0 -63
  260. package/dist/preview.js.map +0 -1
  261. package/dist/product-decisions.d.ts +0 -40
  262. package/dist/product-decisions.d.ts.map +0 -1
  263. package/dist/product-decisions.js +0 -52
  264. package/dist/product-decisions.js.map +0 -1
  265. package/dist/prompt-urls.d.ts +0 -31
  266. package/dist/prompt-urls.d.ts.map +0 -1
  267. package/dist/prompt-urls.js +0 -35
  268. package/dist/prompt-urls.js.map +0 -1
  269. package/dist/prompts/auth-master-integration-prompt.md +0 -255
  270. package/dist/prompts/billing/master.md +0 -332
  271. package/dist/prompts/decisions/feature-control.md +0 -131
  272. package/dist/prompts/decisions/going-live.md +0 -60
  273. package/dist/prompts/decisions/login.md +0 -71
  274. package/dist/prompts/decisions/look-and-feel.md +0 -68
  275. package/dist/prompts/decisions/payments.md +0 -97
  276. package/dist/prompts/decisions/roles.md +0 -78
  277. package/dist/prompts/decisions/teams.md +0 -61
  278. package/dist/prompts/fit-together.md +0 -97
  279. package/dist/prompts/flags/master.md +0 -220
  280. package/dist/prompts/guide-coverage.json +0 -17
  281. package/dist/prompts/integration-success.md +0 -106
  282. package/dist/prompts/mcp-tools.json +0 -90
  283. package/dist/prompts/mechanisms.md +0 -304
  284. package/dist/prompts/orientation.md +0 -42
  285. package/dist/prompts/product-decisions.json +0 -338
  286. package/dist/resolve.d.ts +0 -110
  287. package/dist/resolve.d.ts.map +0 -1
  288. package/dist/resolve.js +0 -260
  289. package/dist/resolve.js.map +0 -1
  290. package/dist/shape.d.ts +0 -25
  291. package/dist/shape.d.ts.map +0 -1
  292. package/dist/shape.js +0 -74
  293. package/dist/shape.js.map +0 -1
@@ -1,117 +0,0 @@
1
- import { getManagementClient, resolveTenantId } from '../config.js';
2
- import { outputSuccess, outputError } from '../output.js';
3
- import { resolveUserId } from '../resolve.js';
4
- import { dryRunPreview } from '../preview.js';
5
- import { DecisionNeededError, decisionField } from '../product-decisions.js';
6
- /**
7
- * TBP-713 — the role an invitee gets is the developer's decision. Without
8
- * --role the API would apply the app's default role (Member on a new app, often
9
- * Owner on older ones), so
10
- * stop and offer the role keys instead, naming the current default.
11
- */
12
- async function roleDecision() {
13
- const field = decisionField('invite_user', 'role', '--role <key>');
14
- try {
15
- const roles = (await getManagementClient().roles.list());
16
- const keys = roles.map((r) => r.key).filter((k) => typeof k === 'string');
17
- const fallback = roles.find((r) => r.isDefault)?.key;
18
- return new DecisionNeededError('bridge user invite', [keys.length ? { ...field, type: 'enum', options: keys } : field], fallback ? `The app's default role is ${fallback}; pass it explicitly if that is what the developer wants.` : undefined);
19
- }
20
- catch {
21
- return new DecisionNeededError('bridge user invite', [field], '`bridge role list` shows the role keys.');
22
- }
23
- }
24
- export function registerUserCommands(program) {
25
- const user = program.command('user').description('Manage tenant users');
26
- user.command('list')
27
- .description('List users in a tenant')
28
- .option('--tenant-id <id>', 'Tenant ID (or set BRIDGE_TENANT_ID)')
29
- .action(async (opts) => {
30
- try {
31
- const tenantId = resolveTenantId(opts);
32
- outputSuccess(await getManagementClient().users.list(tenantId));
33
- }
34
- catch (err) {
35
- outputError(err);
36
- }
37
- });
38
- user.command('get')
39
- .description('Get user details by --email or --user-id')
40
- .option('--email <email>', 'User email to address (alternative to --user-id)')
41
- .option('--user-id <id>', 'User ID to address (alternative to --email)')
42
- .option('--tenant-id <id>', 'Tenant ID (or set BRIDGE_TENANT_ID)')
43
- .action(async (opts) => {
44
- try {
45
- const tenantId = resolveTenantId(opts);
46
- const userId = await resolveUserId({ id: opts.userId, key: opts.email }, tenantId);
47
- outputSuccess(await getManagementClient().users.get(tenantId, userId));
48
- }
49
- catch (err) {
50
- outputError(err);
51
- }
52
- });
53
- user.command('invite')
54
- .description('Invite a user to a tenant')
55
- .requiredOption('--email <email>', 'User email')
56
- .option('--role <role>', 'Role key (see `bridge role list`). Required: which role invitees get is the developer\'s decision')
57
- .option('--first-name <name>', 'First name')
58
- .option('--last-name <name>', 'Last name')
59
- .option('--tenant-id <id>', 'Tenant ID (or set BRIDGE_TENANT_ID)')
60
- .action(async (opts) => {
61
- try {
62
- const tenantId = resolveTenantId(opts);
63
- if (opts.role === undefined)
64
- throw await roleDecision();
65
- outputSuccess(await getManagementClient().users.invite(tenantId, {
66
- username: opts.email,
67
- role: opts.role,
68
- firstName: opts.firstName,
69
- lastName: opts.lastName,
70
- }));
71
- }
72
- catch (err) {
73
- outputError(err);
74
- }
75
- });
76
- user.command('update')
77
- .description('Update a user by --email or --user-id')
78
- .option('--email <email>', 'User email to address (alternative to --user-id)')
79
- .option('--user-id <id>', 'User ID to address (alternative to --email)')
80
- .option('--role <role>', 'Role key')
81
- .option('--enabled <bool>', 'Enable/disable user', (v) => v === 'true')
82
- .option('--tenant-id <id>', 'Tenant ID (or set BRIDGE_TENANT_ID)')
83
- .action(async (opts) => {
84
- try {
85
- const tenantId = resolveTenantId(opts);
86
- const userId = await resolveUserId({ id: opts.userId, key: opts.email }, tenantId);
87
- const data = Object.fromEntries(Object.entries({ role: opts.role, enabled: opts.enabled })
88
- .filter(([, v]) => v !== undefined));
89
- outputSuccess(await getManagementClient().users.update(tenantId, userId, data));
90
- }
91
- catch (err) {
92
- outputError(err);
93
- }
94
- });
95
- user.command('remove')
96
- .description('Remove a user from a tenant by --email or --user-id')
97
- .option('--email <email>', 'User email to address (alternative to --user-id)')
98
- .option('--user-id <id>', 'User ID to address (alternative to --email)')
99
- .option('--tenant-id <id>', 'Tenant ID (or set BRIDGE_TENANT_ID)')
100
- .option('--dry-run', 'Show whether their login account goes too and whether they are the last owner, and remove nothing')
101
- .action(async (opts) => {
102
- try {
103
- const tenantId = resolveTenantId(opts);
104
- const userId = await resolveUserId({ id: opts.userId, key: opts.email }, tenantId);
105
- if (opts.dryRun) {
106
- outputSuccess(await dryRunPreview(`/v1/account/tenant/user/${encodeURIComponent(userId)}`, { 'x-tenant-id': tenantId }));
107
- return;
108
- }
109
- await getManagementClient().users.remove(tenantId, userId);
110
- outputSuccess({ removed: true, userId });
111
- }
112
- catch (err) {
113
- outputError(err);
114
- }
115
- });
116
- }
117
- //# sourceMappingURL=user.command.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"user.command.js","sourceRoot":"","sources":["../../src/commands/user.command.ts"],"names":[],"mappings":"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"}
@@ -1,141 +0,0 @@
1
- export interface StoredCredentials {
2
- /** The JWT to send as `x-api-key`. Same shape as `BRIDGE_API_KEY`. */
3
- apiKey: string;
4
- /** ISO 8601 timestamp at which `apiKey` becomes invalid. */
5
- expiresAt: string;
6
- /** ISO 8601 timestamp the token was issued (for diagnostics). */
7
- issuedAt: string;
8
- /** App the token is scoped to. */
9
- app: {
10
- id: string;
11
- name: string;
12
- };
13
- /** User who authorized the token. */
14
- user: {
15
- id: string;
16
- email: string;
17
- };
18
- /** Base URL of the bridge-api this token is valid against. */
19
- baseUrl: string;
20
- /** Optional human-friendly label set via `bridge auth login --label`. */
21
- label?: string;
22
- /**
23
- * TBP-769 — what the login covers, as chosen on the consent screen:
24
- * `workspace` = every app of the workspace (`app` above is the HOME app),
25
- * `app` = only `app`. Absent on credentials stored before TBP-769; those are
26
- * treated as `app` until the server says otherwise.
27
- */
28
- appAccess?: 'app' | 'workspace';
29
- /**
30
- * TBP-769 — the app commands act on by default within a workspace login,
31
- * set by `bridge app use`. Absent = the home app. Only ever an id + name:
32
- * per-app tokens are fetched per run and never written to disk.
33
- */
34
- currentApp?: {
35
- id: string;
36
- name: string;
37
- };
38
- }
39
- /** Current on-disk shape. See the module docstring for why it is a map. */
40
- export interface CredentialsFile {
41
- version: 2;
42
- /** App id of the credential commands use by default. `null` when empty. */
43
- active: string | null;
44
- /** All stored credentials, keyed by `app.id`. */
45
- credentials: Record<string, StoredCredentials>;
46
- }
47
- /** One entry, as `bridge auth status` and the selector logic see it. */
48
- export interface CredentialEntry {
49
- /** The map key — always `creds.app.id`. */
50
- key: string;
51
- creds: StoredCredentials;
52
- isActive: boolean;
53
- }
54
- /**
55
- * Returns the absolute path to the credentials file based on the current
56
- * environment. Does not create directories or files — pure path resolution.
57
- *
58
- * Resolution (per XDG Base Directory spec):
59
- * 1. `$XDG_CONFIG_HOME/bridge/credentials.json` if XDG_CONFIG_HOME is set.
60
- * 2. `$HOME/.config/bridge/credentials.json` otherwise.
61
- * 3. `os.homedir()/.config/bridge/credentials.json` if HOME is unset
62
- * (Windows / corner cases).
63
- *
64
- * We deliberately prefer `process.env.HOME` over `os.homedir()` because (a)
65
- * the XDG spec is defined in terms of `$HOME`, and (b) Node's `os.homedir()`
66
- * on some test runners (jest) bypasses the `HOME` env var via libuv, which
67
- * makes overriding it for tests impossible without a wrapper like this.
68
- */
69
- export declare function credentialsPath(): string;
70
- /**
71
- * Read the whole store, migrating a v1 file in memory. `null` if no file.
72
- *
73
- * Throws if the file exists but is unreadable or malformed — a corrupt store is
74
- * not the same as an absent one, and silently treating it as absent would make
75
- * `bridge auth status` report "not logged in" to somebody who very much is.
76
- */
77
- export declare function readCredentialsFile(): CredentialsFile | null;
78
- /**
79
- * The credential commands act on by default: the active one.
80
- *
81
- * Kept with its original name and signature because every existing caller wants
82
- * exactly this, and because "which credential is in force" is a question with
83
- * one answer whether the file holds one app or ten.
84
- */
85
- export declare function readCredentials(): StoredCredentials | null;
86
- /** Every stored credential, active one first, then by app name. */
87
- export declare function listCredentials(): CredentialEntry[];
88
- /** Raised when a selector matches nothing, or matches more than one entry. */
89
- export declare class CredentialSelectorError extends Error {
90
- constructor(message: string);
91
- }
92
- /**
93
- * Find one stored credential by label, app id, or app name.
94
- *
95
- * Label first: users think in environments, not in 24-character object ids, and
96
- * `--label` exists precisely so they can name one. App id is exact and always
97
- * works. App name is last because two apps may share one.
98
- *
99
- * An ambiguous selector is an ERROR, never a first match. Picking one of two
100
- * candidate apps silently is the whole failure mode this ticket is about.
101
- */
102
- export declare function findCredential(selector: string): CredentialEntry;
103
- /**
104
- * Upsert a credential by app id and make it active.
105
- *
106
- * Same name and signature as before: `bridge auth login` still ends with one
107
- * call, and still leaves the app it just authorised in force.
108
- */
109
- export declare function writeCredentials(creds: StoredCredentials): void;
110
- /** Point the persisted default at an already-stored credential. Offline. */
111
- export declare function setActiveCredential(key: string): void;
112
- /**
113
- * Update fields of ONE stored credential in place (TBP-769: `currentApp`,
114
- * `appAccess`). `undefined` values remove the field. Does not move `active`.
115
- */
116
- export declare function updateCredential(key: string, patch: Partial<Pick<StoredCredentials, 'currentApp' | 'appAccess'>>): StoredCredentials;
117
- /** Persist the store atomically with mode 0600, dir 0700. */
118
- export declare function writeCredentialsFile(file: CredentialsFile): void;
119
- /**
120
- * Remove ONE credential. Deletes the file entirely when it was the last.
121
- *
122
- * Returns the remaining count so a caller can tell the user what is left.
123
- * Removing the active one moves `active` to another entry rather than leaving a
124
- * dangling pointer — with credentials still stored, "logged out of everything"
125
- * would be a lie.
126
- */
127
- export declare function removeCredential(key: string): number;
128
- /** Delete the whole credentials file. No-op if it does not exist. */
129
- export declare function deleteAllCredentials(): void;
130
- /**
131
- * Back-compat alias for the single-app era: remove the active credential.
132
- *
133
- * @deprecated Prefer `removeCredential(key)` or `deleteAllCredentials()`, which
134
- * say which of the two things they do.
135
- */
136
- export declare function deleteCredentials(): void;
137
- /**
138
- * True if the credentials' `expiresAt` is in the past relative to `now`.
139
- */
140
- export declare function isExpired(creds: StoredCredentials, now?: Date): boolean;
141
- //# sourceMappingURL=credentials.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"credentials.d.ts","sourceRoot":"","sources":["../src/credentials.ts"],"names":[],"mappings":"AA6CA,MAAM,WAAW,iBAAiB;IAChC,sEAAsE;IACtE,MAAM,EAAE,MAAM,CAAC;IACf,4DAA4D;IAC5D,SAAS,EAAE,MAAM,CAAC;IAClB,iEAAiE;IACjE,QAAQ,EAAE,MAAM,CAAC;IACjB,kCAAkC;IAClC,GAAG,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAClC,qCAAqC;IACrC,IAAI,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IACpC,8DAA8D;IAC9D,OAAO,EAAE,MAAM,CAAC;IAChB,yEAAyE;IACzE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;OAKG;IACH,SAAS,CAAC,EAAE,KAAK,GAAG,WAAW,CAAC;IAChC;;;;OAIG;IACH,UAAU,CAAC,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;CAC3C;AAED,2EAA2E;AAC3E,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,CAAC,CAAC;IACX,2EAA2E;IAC3E,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,iDAAiD;IACjD,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;CAChD;AAED,wEAAwE;AACxE,MAAM,WAAW,eAAe;IAC9B,2CAA2C;IAC3C,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,iBAAiB,CAAC;IACzB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,eAAe,IAAI,MAAM,CAQxC;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,IAAI,eAAe,GAAG,IAAI,CAyB5D;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,IAAI,iBAAiB,GAAG,IAAI,CAU1D;AAED,mEAAmE;AACnE,wBAAgB,eAAe,IAAI,eAAe,EAAE,CASnD;AAED,8EAA8E;AAC9E,qBAAa,uBAAwB,SAAQ,KAAK;gBACpC,OAAO,EAAE,MAAM;CAI5B;AAED;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,eAAe,CAmChE;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,iBAAiB,GAAG,IAAI,CAK/D;AAED,4EAA4E;AAC5E,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAOrD;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,iBAAiB,EAAE,YAAY,GAAG,WAAW,CAAC,CAAC,GAClE,iBAAiB,CAcnB;AAED,6DAA6D;AAC7D,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,eAAe,GAAG,IAAI,CA4BhE;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAWpD;AAED,qEAAqE;AACrE,wBAAgB,oBAAoB,IAAI,IAAI,CAQ3C;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,IAAI,IAAI,CAOxC;AAsBD;;GAEG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,iBAAiB,EAAE,GAAG,GAAE,IAAiB,GAAG,OAAO,CAInF"}
@@ -1,348 +0,0 @@
1
- /**
2
- * Credentials file management for bridge-cli.
3
- *
4
- * Stores the long-lived CLI JWT obtained via `bridge auth login` so subsequent
5
- * commands can authenticate without `BRIDGE_API_KEY`. The token is sent to
6
- * bridge-api as `x-api-key: <jwt>` (same path as `BRIDGE_API_KEY`).
7
- *
8
- * Path resolution (XDG-compliant, RFC 8252-friendly):
9
- * 1. `$XDG_CONFIG_HOME/bridge/credentials.json` if env is set
10
- * 2. `~/.config/bridge/credentials.json` otherwise
11
- *
12
- * File mode: 0600 (owner read/write only). Containing dir created with 0700.
13
- *
14
- * ## The file holds MANY apps (TBP-628)
15
- *
16
- * It used to hold exactly one. Anyone running the same product as several apps
17
- * — one appId per environment — had to `logout` + `login` through the browser
18
- * to move between them, even though the token they already held had days left
19
- * on it. Worse, nothing in a read command's output said which app answered, so
20
- * a session holding a prod token could run `role list` believing it described
21
- * local, and the next step would have rewritten production roles.
22
- *
23
- * So the on-disk shape is now a map keyed by app id, plus a pointer at the
24
- * active one:
25
- *
26
- * ```json
27
- * {
28
- * "version": 2,
29
- * "active": "606b4416fabdc800087d09ec",
30
- * "credentials": { "606b4416fabdc800087d09ec": { …StoredCredentials } }
31
- * }
32
- * ```
33
- *
34
- * Keyed by app id, not by label: the label is optional and user-chosen, so it
35
- * is a fine way to SELECT a credential and a bad way to key one.
36
- *
37
- * A v1 file (a bare `StoredCredentials` object) is migrated on read, in memory
38
- * only. Reading never rewrites the file — a read command must not mutate state
39
- * another process is reading. The v2 shape is persisted the next time
40
- * something writes.
41
- */
42
- import * as fs from 'node:fs';
43
- import * as path from 'node:path';
44
- import * as os from 'node:os';
45
- /**
46
- * Returns the absolute path to the credentials file based on the current
47
- * environment. Does not create directories or files — pure path resolution.
48
- *
49
- * Resolution (per XDG Base Directory spec):
50
- * 1. `$XDG_CONFIG_HOME/bridge/credentials.json` if XDG_CONFIG_HOME is set.
51
- * 2. `$HOME/.config/bridge/credentials.json` otherwise.
52
- * 3. `os.homedir()/.config/bridge/credentials.json` if HOME is unset
53
- * (Windows / corner cases).
54
- *
55
- * We deliberately prefer `process.env.HOME` over `os.homedir()` because (a)
56
- * the XDG spec is defined in terms of `$HOME`, and (b) Node's `os.homedir()`
57
- * on some test runners (jest) bypasses the `HOME` env var via libuv, which
58
- * makes overriding it for tests impossible without a wrapper like this.
59
- */
60
- export function credentialsPath() {
61
- const xdg = process.env.XDG_CONFIG_HOME?.trim();
62
- if (xdg && xdg.length > 0) {
63
- return path.join(xdg, 'bridge', 'credentials.json');
64
- }
65
- const home = process.env.HOME?.trim();
66
- const base = home && home.length > 0 ? home : os.homedir();
67
- return path.join(base, '.config', 'bridge', 'credentials.json');
68
- }
69
- /**
70
- * Read the whole store, migrating a v1 file in memory. `null` if no file.
71
- *
72
- * Throws if the file exists but is unreadable or malformed — a corrupt store is
73
- * not the same as an absent one, and silently treating it as absent would make
74
- * `bridge auth status` report "not logged in" to somebody who very much is.
75
- */
76
- export function readCredentialsFile() {
77
- const filePath = credentialsPath();
78
- if (!fs.existsSync(filePath))
79
- return null;
80
- const raw = fs.readFileSync(filePath, 'utf-8');
81
- let parsed;
82
- try {
83
- parsed = JSON.parse(raw);
84
- }
85
- catch {
86
- throw new Error(`Credentials file at ${filePath} is not valid JSON.`);
87
- }
88
- // v2 — the current shape.
89
- if (isCredentialsFile(parsed))
90
- return parsed;
91
- // v1 — a bare StoredCredentials object. Migrate in memory; do NOT write.
92
- if (isStoredCredentials(parsed)) {
93
- return {
94
- version: 2,
95
- active: parsed.app.id,
96
- credentials: { [parsed.app.id]: parsed },
97
- };
98
- }
99
- throw new Error(`Credentials file at ${filePath} is missing required fields.`);
100
- }
101
- /**
102
- * The credential commands act on by default: the active one.
103
- *
104
- * Kept with its original name and signature because every existing caller wants
105
- * exactly this, and because "which credential is in force" is a question with
106
- * one answer whether the file holds one app or ten.
107
- */
108
- export function readCredentials() {
109
- const file = readCredentialsFile();
110
- if (!file)
111
- return null;
112
- if (file.active && file.credentials[file.active])
113
- return file.credentials[file.active];
114
- // A pointer at a credential that is gone. Fall back to the only entry if
115
- // there is exactly one — otherwise there is no defensible default, and
116
- // guessing would pick an app on the user's behalf, which is the failure this
117
- // ticket exists to stop.
118
- const keys = Object.keys(file.credentials);
119
- return keys.length === 1 ? file.credentials[keys[0]] : null;
120
- }
121
- /** Every stored credential, active one first, then by app name. */
122
- export function listCredentials() {
123
- const file = readCredentialsFile();
124
- if (!file)
125
- return [];
126
- return Object.entries(file.credentials)
127
- .map(([key, creds]) => ({ key, creds, isActive: key === file.active }))
128
- .sort((a, b) => {
129
- if (a.isActive !== b.isActive)
130
- return a.isActive ? -1 : 1;
131
- return a.creds.app.name.localeCompare(b.creds.app.name);
132
- });
133
- }
134
- /** Raised when a selector matches nothing, or matches more than one entry. */
135
- export class CredentialSelectorError extends Error {
136
- constructor(message) {
137
- super(message);
138
- this.name = 'CredentialSelectorError';
139
- }
140
- }
141
- /**
142
- * Find one stored credential by label, app id, or app name.
143
- *
144
- * Label first: users think in environments, not in 24-character object ids, and
145
- * `--label` exists precisely so they can name one. App id is exact and always
146
- * works. App name is last because two apps may share one.
147
- *
148
- * An ambiguous selector is an ERROR, never a first match. Picking one of two
149
- * candidate apps silently is the whole failure mode this ticket is about.
150
- */
151
- export function findCredential(selector) {
152
- const needle = selector.trim();
153
- if (!needle)
154
- throw new CredentialSelectorError('Empty profile selector.');
155
- const entries = listCredentials();
156
- if (entries.length === 0) {
157
- throw new CredentialSelectorError('No stored credentials. Run `bridge auth login` first.');
158
- }
159
- const lower = needle.toLowerCase();
160
- const byLabel = entries.filter((e) => e.creds.label?.toLowerCase() === lower);
161
- const byId = entries.filter((e) => e.key === needle);
162
- const byName = entries.filter((e) => e.creds.app.name.toLowerCase() === lower);
163
- for (const [what, matches] of [
164
- ['label', byLabel],
165
- ['app id', byId],
166
- ['app name', byName],
167
- ]) {
168
- if (matches.length === 1)
169
- return matches[0];
170
- if (matches.length > 1) {
171
- throw new CredentialSelectorError(`"${needle}" matches ${matches.length} stored credentials by ${what} ` +
172
- `(${matches.map((m) => m.key).join(', ')}). Select by app id instead.`);
173
- }
174
- }
175
- throw new CredentialSelectorError(`No stored credential matches "${needle}". Known: ` +
176
- entries.map((e) => e.creds.label ?? e.creds.app.name).join(', ') +
177
- '. Run `bridge auth status` to see them all.');
178
- }
179
- /**
180
- * Upsert a credential by app id and make it active.
181
- *
182
- * Same name and signature as before: `bridge auth login` still ends with one
183
- * call, and still leaves the app it just authorised in force.
184
- */
185
- export function writeCredentials(creds) {
186
- const file = readCredentialsFileOrEmpty();
187
- file.credentials[creds.app.id] = creds;
188
- file.active = creds.app.id;
189
- writeCredentialsFile(file);
190
- }
191
- /** Point the persisted default at an already-stored credential. Offline. */
192
- export function setActiveCredential(key) {
193
- const file = readCredentialsFileOrEmpty();
194
- if (!file.credentials[key]) {
195
- throw new CredentialSelectorError(`No stored credential with app id ${key}.`);
196
- }
197
- file.active = key;
198
- writeCredentialsFile(file);
199
- }
200
- /**
201
- * Update fields of ONE stored credential in place (TBP-769: `currentApp`,
202
- * `appAccess`). `undefined` values remove the field. Does not move `active`.
203
- */
204
- export function updateCredential(key, patch) {
205
- const file = readCredentialsFileOrEmpty();
206
- const existing = file.credentials[key];
207
- if (!existing) {
208
- throw new CredentialSelectorError(`No stored credential with app id ${key}.`);
209
- }
210
- const next = { ...existing };
211
- for (const [k, v] of Object.entries(patch)) {
212
- if (v === undefined)
213
- delete next[k];
214
- else
215
- next[k] = v;
216
- }
217
- file.credentials[key] = next;
218
- writeCredentialsFile(file);
219
- return next;
220
- }
221
- /** Persist the store atomically with mode 0600, dir 0700. */
222
- export function writeCredentialsFile(file) {
223
- const filePath = credentialsPath();
224
- const dir = path.dirname(filePath);
225
- // Create dir with restrictive perms. mkdirSync `mode` is masked by umask, so
226
- // we explicitly chmod after to guarantee 0700 regardless of inherited umask.
227
- fs.mkdirSync(dir, { recursive: true, mode: 0o700 });
228
- try {
229
- fs.chmodSync(dir, 0o700);
230
- }
231
- catch {
232
- // chmod fails on Windows for non-NTFS fs — non-fatal there.
233
- }
234
- // Write to a tmp file then rename for atomicity. Open with mode 0600 from
235
- // the start so the JWT is never world-readable, even briefly.
236
- const tmpPath = `${filePath}.${process.pid}.tmp`;
237
- const fd = fs.openSync(tmpPath, 'w', 0o600);
238
- try {
239
- fs.writeFileSync(fd, JSON.stringify(file, null, 2) + '\n');
240
- }
241
- finally {
242
- fs.closeSync(fd);
243
- }
244
- try {
245
- fs.chmodSync(tmpPath, 0o600);
246
- }
247
- catch {
248
- // best-effort; openSync's mode arg already set perms.
249
- }
250
- fs.renameSync(tmpPath, filePath);
251
- }
252
- /**
253
- * Remove ONE credential. Deletes the file entirely when it was the last.
254
- *
255
- * Returns the remaining count so a caller can tell the user what is left.
256
- * Removing the active one moves `active` to another entry rather than leaving a
257
- * dangling pointer — with credentials still stored, "logged out of everything"
258
- * would be a lie.
259
- */
260
- export function removeCredential(key) {
261
- const file = readCredentialsFileOrEmpty();
262
- delete file.credentials[key];
263
- const remaining = Object.keys(file.credentials);
264
- if (remaining.length === 0) {
265
- deleteAllCredentials();
266
- return 0;
267
- }
268
- if (file.active === key)
269
- file.active = remaining[0];
270
- writeCredentialsFile(file);
271
- return remaining.length;
272
- }
273
- /** Delete the whole credentials file. No-op if it does not exist. */
274
- export function deleteAllCredentials() {
275
- const filePath = credentialsPath();
276
- try {
277
- fs.unlinkSync(filePath);
278
- }
279
- catch (err) {
280
- if (err.code === 'ENOENT')
281
- return;
282
- throw err;
283
- }
284
- }
285
- /**
286
- * Back-compat alias for the single-app era: remove the active credential.
287
- *
288
- * @deprecated Prefer `removeCredential(key)` or `deleteAllCredentials()`, which
289
- * say which of the two things they do.
290
- */
291
- export function deleteCredentials() {
292
- const file = readCredentialsFileOrEmpty();
293
- if (file.active) {
294
- removeCredential(file.active);
295
- return;
296
- }
297
- deleteAllCredentials();
298
- }
299
- /** The store, or an empty one — for the write paths, which create on demand. */
300
- function readCredentialsFileOrEmpty() {
301
- try {
302
- return readCredentialsFile() ?? { version: 2, active: null, credentials: {} };
303
- }
304
- catch {
305
- // A corrupt file must not wedge `login` — overwriting it is how the user
306
- // gets unstuck, and the token in it is unusable anyway.
307
- return { version: 2, active: null, credentials: {} };
308
- }
309
- }
310
- function isCredentialsFile(value) {
311
- if (!value || typeof value !== 'object')
312
- return false;
313
- const v = value;
314
- if (v.version !== 2)
315
- return false;
316
- if (v.active !== null && typeof v.active !== 'string')
317
- return false;
318
- if (!v.credentials || typeof v.credentials !== 'object')
319
- return false;
320
- return Object.values(v.credentials).every(isStoredCredentials);
321
- }
322
- /**
323
- * True if the credentials' `expiresAt` is in the past relative to `now`.
324
- */
325
- export function isExpired(creds, now = new Date()) {
326
- const expiry = Date.parse(creds.expiresAt);
327
- if (Number.isNaN(expiry))
328
- return true;
329
- return expiry <= now.getTime();
330
- }
331
- function isStoredCredentials(value) {
332
- if (!value || typeof value !== 'object')
333
- return false;
334
- const v = value;
335
- return (typeof v.apiKey === 'string' &&
336
- typeof v.expiresAt === 'string' &&
337
- typeof v.issuedAt === 'string' &&
338
- typeof v.baseUrl === 'string' &&
339
- typeof v.app === 'object' &&
340
- v.app !== null &&
341
- typeof v.app.id === 'string' &&
342
- typeof v.app.name === 'string' &&
343
- typeof v.user === 'object' &&
344
- v.user !== null &&
345
- typeof v.user.id === 'string' &&
346
- typeof v.user.email === 'string');
347
- }
348
- //# sourceMappingURL=credentials.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"credentials.js","sourceRoot":"","sources":["../src/credentials.ts"],"names":[],"mappings":"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"}