@antasphere/chassis-cli 1.0.1 → 1.1.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.
@@ -1,5 +1,5 @@
1
1
  import { describe, expect, it } from 'vitest';
2
- import { HUB_TOOL, saveConfig as saveCoreConfig } from '@antasphere/cli-core';
2
+ import { HUB_TOOL, loadConfig as loadCoreConfig, saveConfig as saveCoreConfig } from '@antasphere/cli-core';
3
3
  import { routedHarness, tempConfigEnv, type Route } from '@antasphere/chassis-cli/testing';
4
4
  import { cli, run } from '@chassis-cli-test/host';
5
5
  import {
@@ -45,7 +45,9 @@ async function cachedEnv(): Promise<Record<string, string>> {
45
45
  seedHubLogin(env);
46
46
  saveConfig(env, {
47
47
  activeProfile: 'work',
48
- profiles: { work: { baseUrl: 'http://tool', connectKeys: { default: { apiKey: OLD } } } }
48
+ profiles: {
49
+ work: { baseUrl: 'http://tool', connectKeys: { default: { apiKey: OLD, email: 'ada@x.co' } } }
50
+ }
49
51
  });
50
52
  return env;
51
53
  }
@@ -319,19 +321,52 @@ describe('a cached key of another Antasphere account (PRDCT-3032)', () => {
319
321
  expect(JSON.stringify(loadConfig(env))).not.toContain(OLD);
320
322
  });
321
323
 
322
- it('a cache entry with no email, or a hub login with none, is trusted as before', async () => {
323
- for (const [cached, hubEmail] of [
324
- [{ apiKey: OLD }, 'bob@x.co'],
325
- [{ apiKey: OLD, email: 'ada@x.co' }, undefined]
326
- ] as const) {
324
+ it.each([
325
+ [
326
+ 'a cache entry with no address',
327
+ { apiKey: OLD },
328
+ 'bob@x.co',
329
+ 'cached for an unknown login is retired: the Antasphere login is now bob@x.co.\n'
330
+ ],
331
+ [
332
+ 'a hub login with no address',
333
+ { apiKey: OLD, email: 'ada@x.co' },
334
+ undefined,
335
+ 'cached for ada@x.co is retired: the Antasphere login carries no address to match it with.\n'
336
+ ]
337
+ ] as const)(
338
+ '%s is never served: the key is retired and revoked, the exchange mints anew, the hub profile carries the address after (verifier round 1, F1 and F5)',
339
+ async (_label, cached, hubEmail, retired) => {
327
340
  const env = await switchedEnv(cached, hubEmail);
328
341
  const h = routedHarness(routesFor([OLD, NEW]), env);
329
342
  expect(await run(['whoami'], h.io)).toBe(0);
330
- expect(trace(h)).toEqual([`GET http://tool/api/v1/me Bearer ${OLD}`]);
331
- expect(h.err()).not.toContain('is retired');
332
- expect(loadConfig(env).profiles.work?.connectKeys?.default?.apiKey).toBe(OLD);
343
+ expect(trace(h)).toEqual([
344
+ `DELETE http://tool/api/v1/cli/auth/key Bearer ${OLD}`,
345
+ 'GET http://tool/api/v1/instance -',
346
+ `POST ${HUB}/api/v1/sso/tool-token Bearer ${BOB_HUB_KEY}`,
347
+ 'POST http://tool/api/v1/sso/cli-connect -',
348
+ `GET http://tool/api/v1/me Bearer ${NEW}`
349
+ ]);
350
+ expect(h.wire.filter((c) => c.auth === `Bearer ${OLD}`).map((c) => c.method)).toEqual(['DELETE']);
351
+ expect(h.err()).toContain(`The ${displayName} key ${retired}`);
352
+ const work = loadConfig(env).profiles.work;
353
+ expect(Object.keys(work?.connectKeys ?? {})).toEqual(['default']);
354
+ expect(work?.connectKeys?.default).toMatchObject({ apiKey: NEW, email: 'bob@x.co' });
355
+ expect(JSON.stringify(loadConfig(env))).not.toContain(OLD);
356
+ // The hub profile is healed with the address the exchange answered
357
+ // (when it had none), and nothing else of it moves.
358
+ expect(loadCoreConfig(env, HUB_TOOL)).toEqual({
359
+ activeProfile: 'default',
360
+ profiles: { default: { apiKey: BOB_HUB_KEY, baseUrl: HUB, email: 'bob@x.co' } }
361
+ });
362
+
363
+ // The next command is served from the cache: zero hub calls.
364
+ const next = routedHarness(routesFor([NEW]), env);
365
+ expect(await run(['whoami'], next.io)).toBe(0);
366
+ expect(trace(next)).toEqual([`GET http://tool/api/v1/me Bearer ${NEW}`]);
367
+ expect(next.err()).toBe('');
333
368
  }
334
- });
369
+ );
335
370
 
336
371
  it('the same account in another case is the same account: the cached key is served (verifier M3)', async () => {
337
372
  const env = await switchedEnv({ apiKey: OLD, email: 'ada@x.co' }, 'ADA@X.CO');
@@ -95,7 +95,12 @@ describe('whoami', () => {
95
95
  seedHubLogin(env);
96
96
  saveConfig(env, {
97
97
  activeProfile: 'work',
98
- profiles: { work: { baseUrl: 'http://tool', connectKeys: { default: { apiKey: key('cached') } } } }
98
+ profiles: {
99
+ work: {
100
+ baseUrl: 'http://tool',
101
+ connectKeys: { default: { apiKey: key('cached'), email: 'ada@x.co' } }
102
+ }
103
+ }
99
104
  });
100
105
  const h = routedHarness([meRoute()], env);
101
106
  expect(await run(['whoami'], h.io)).toBe(0);
@@ -133,7 +138,12 @@ describe('whoami', () => {
133
138
  seedHubLogin(env);
134
139
  saveConfig(env, {
135
140
  activeProfile: 'work',
136
- profiles: { work: { baseUrl: 'http://tool', connectKeys: { default: { apiKey: key('cached') } } } }
141
+ profiles: {
142
+ work: {
143
+ baseUrl: 'http://tool',
144
+ connectKeys: { default: { apiKey: key('cached'), email: 'ada@x.co' } }
145
+ }
146
+ }
137
147
  });
138
148
  const h = routedHarness([meRoute()], env);
139
149
  expect(await run(['whoami', '--json', '--workspace', 'w1'], h.io)).toBe(0);