@tokenoftrust/cli 1.3.4-rc.5 → 1.4.0-rc.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.
package/README.md CHANGED
@@ -40,10 +40,24 @@ The same `tot` does the right thing wherever you run it (walks up like `git`):
40
40
 
41
41
  ## Auth
42
42
 
43
- `tot` talks to the Token of Trust MCP (default `https://mcp.tokenoftrust.com`, override with `--mcp` or `MCP_BASE_URL`). It authenticates as one of two identities, transparently:
43
+ `tot` talks to the Token of Trust MCP (default `https://mcp.tokenoftrust.com`, override with `--mcp` or `MCP_BASE_URL`). It is **single-plane**: the only identity is **you**, signed in against the MCP over OAuth.
44
44
 
45
- - **developer**you, signed in against the MCP (the real invited-developer path). Depends on entitlement-derived MCP access; until that ships, `tot` reports it clearly and points you at operator creds.
46
- - **operator** `TOT_API_KEY` / `TOT_SECRET_KEY` / `TOT_APP_DOMAIN` in the environment (how we dogfood the CLI and how CI exercises it).
45
+ - Run `tot login` once it opens your browser (or falls back to a device code on a headless box), you sign in as yourself, and the session is cached at `~/.tot/credentials.json` and refreshed silently. Every later command (`tot checkout`, `tot start`, `tot submit`, …) runs as you, with no re-auth. Entitlement is derived server-side from your ToT memberships.
46
+ - Not signed in? On a terminal, `tot start` / `tot checkout` **offer to sign you in right there** and continue in-flow no "run `tot login`, then re-run".
47
+ - The old operator env-triple (`TOT_API_KEY` / `TOT_SECRET_KEY` / `TOT_APP_DOMAIN`) **no longer signs the CLI in** — tot-mcp went OAuth-first on 2026-07-23. If those vars are set, `tot` prints a one-line advisory and uses your `tot login` session anyway; it never reads them for auth.
48
+
49
+ ### Multiple identities at once (`TOT_PROFILE`)
50
+
51
+ One credential file = one active identity, so a plain `tot login` replaces the previous session. To keep **different identities live in different terminals** — e.g. a staff `@tokenoftrust.com` sign-in in one shell and a plain developer identity in another — set a profile per shell:
52
+
53
+ ```
54
+ # terminal A
55
+ export TOT_PROFILE=staff && tot login
56
+ # terminal B
57
+ export TOT_PROFILE=dev && tot login
58
+ ```
59
+
60
+ Each profile gets its own `~/.tot/credentials.<profile>.json` (the renderer cache and everything else stay shared). Unset → the default session, unchanged. `tot whoami` shows the active profile.
47
61
 
48
62
  ## Design notes
49
63
 
package/bin/tot.mjs CHANGED
@@ -8,6 +8,7 @@
8
8
  * tot login sign in to Token of Trust (OAuth) ← built (MCP OAuth PKCE loopback; caches ~/.tot/credentials.json)
9
9
  * tot logout sign out (clear the cached session) ← built (deletes ~/.tot/credentials.json; local-only, no server revoke)
10
10
  * tot whoami who you're signed in as ← built
11
+ * tot grants capability/tier/expiry per store you can act on ← built (introspection diagnostics)
11
12
  * tot checkout [<tenant>] clone a store you can build on ← built
12
13
  * tot validate lint your store before you submit ← built
13
14
  * tot dev run your store locally with save→reload ← built (monorepo: host astro; standalone: runs the published runner image)
@@ -52,6 +53,7 @@ tot — Token of Trust developer CLI
52
53
  tot login sign in to Token of Trust
53
54
  tot logout sign out (clear the cached session)
54
55
  tot whoami show who you're signed in as
56
+ tot grants capability/tier/expiry per store you can act on
55
57
  tot checkout [<tenant>] clone a store you can build on
56
58
  tot validate lint your store before you submit
57
59
  tot dev run your store locally with save→reload
@@ -112,6 +114,11 @@ async function dispatch(cmd, rest, ctx) {
112
114
  return run(rest, ctx);
113
115
  }
114
116
 
117
+ if (cmd === "grants") {
118
+ const { run } = await import("../src/commands/grants.mjs");
119
+ return run(rest, ctx);
120
+ }
121
+
115
122
  if (cmd === "ideas") {
116
123
  const { run } = await import("../src/commands/ideas.mjs");
117
124
  return run(rest, ctx);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tokenoftrust/cli",
3
- "version": "1.3.4-rc.5",
3
+ "version": "1.4.0-rc.0",
4
4
  "description": "Token of Trust developer CLI — check out a tenant store, run it locally with save→reload, and submit it for preview. Installs the `tot` command.",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Token of Trust",
package/src/auth.mjs CHANGED
@@ -1,33 +1,28 @@
1
1
  /**
2
- * Auth providers for `tot` — how we establish a VALIDATED MCP session before a
3
- * privileged tool call (tenant_checkout, client_switch, …).
2
+ * Auth for `tot` — how we establish a VALIDATED MCP session before a privileged
3
+ * tool call (tenant_checkout, client_switch, …).
4
4
  *
5
- * There are two identities that can drive `tot`, and the whole point of this
6
- * seam is that every command calls `resolveSession(client)` and never cares
7
- * which one answered:
5
+ * SINGLE PLANE: there is exactly one identity that drives `tot` the human
6
+ * developer, signed in as THEMSELVES against the MCP via OAuth (the same identity
7
+ * `claude mcp add … tot` + `/mcp` establishes). `tot login` runs the MCP OAuth
8
+ * PKCE loopback and caches the token (~/.tot/credentials.json via token-store.mjs);
9
+ * this provider reads it back, silently refreshing when expired, and attaches it as
10
+ * the client's Bearer. Entitlement is derived server-side from the developer's ToT
11
+ * memberships — no local check. Every command calls `establishSession(client)`.
8
12
  *
9
- * operator TOT_API_KEY / TOT_SECRET_KEY / TOT_APP_DOMAIN in the env →
10
- * credential_validate. This is a STOREFRONT-OPERATOR (or CI)
11
- * identity, resolved from SSM in our tooling. It is NOT what an
12
- * invited external developer has it's how WE dogfood the CLI
13
- * end-to-end today, and how CI exercises it.
14
- *
15
- * developer — the invited developer, signed in as THEMSELVES against the MCP
16
- * via OAuth (the same identity `claude mcp add … tot` + `/mcp`
17
- * establishes). `tot login` runs the MCP OAuth PKCE loopback and
18
- * caches the token (~/.tot/credentials.json via token-store.mjs);
19
- * this provider reads it back, silently refreshing when expired,
20
- * and attaches it as the client's Bearer. Entitlement is derived
21
- * server-side from the developer's ToT memberships — no local check.
22
- *
23
- * Selection: operator creds win when present (explicit, deterministic, what CI
24
- * sets); otherwise we fall to the developer provider.
13
+ * The old `operator` provider (a TOT_API_KEY / TOT_SECRET_KEY / TOT_APP_DOMAIN
14
+ * env-triple → `credential_validate`) is GONE. tot-mcp went OAuth-first on
15
+ * 2026-07-23: `credential_validate` was retired to a stateless key-liveness probe
16
+ * that establishes NO human identity and sets NO tenant scope, so the operator
17
+ * path can no longer sign the CLI in to anything. The env-triple is now treated as
18
+ * DETECTION ONLY — if it's set we print a one-line advisory and proceed on the
19
+ * OAuth session (see hasLegacyOperatorEnv / legacyOperatorEnvAdvisory). We never
20
+ * read or transmit the secret.
25
21
  */
26
22
  import {
27
23
  defaultCredentialsPath, readCredentials, writeCredentials, isExpired,
28
24
  } from "./token-store.mjs";
29
25
  import { refreshAccessToken, credentialsFromToken } from "./oauth.mjs";
30
- import { recordServerPolicy } from "./update-check.mjs";
31
26
 
32
27
  /** Thrown when no provider can authenticate — carries actionable guidance. */
33
28
  export class AuthUnavailableError extends Error {
@@ -99,42 +94,29 @@ export function developerCredentialRecoveryHint(creds) {
99
94
  return "run `tot login` to sign in again.";
100
95
  }
101
96
 
102
- /** True when a full operator credential triple is present in the environment. */
103
- export function hasOperatorCreds(env = process.env) {
97
+ /**
98
+ * True when the RETIRED operator env-triple (TOT_API_KEY / TOT_SECRET_KEY /
99
+ * TOT_APP_DOMAIN) is fully set. Detection only — these keys no longer sign the
100
+ * CLI in to the MCP (OAuth-first since 2026-07-23); we use it purely to emit an
101
+ * advisory so a stale env setup self-explains instead of silently doing nothing.
102
+ * We never read the secret values.
103
+ */
104
+ export function hasLegacyOperatorEnv(env = process.env) {
104
105
  return Boolean(env.TOT_API_KEY && env.TOT_SECRET_KEY && env.TOT_APP_DOMAIN);
105
106
  }
106
107
 
108
+ /** One quiet line shown when the retired operator env-triple is present. */
109
+ export const legacyOperatorEnvAdvisory =
110
+ "note: ToT API keys in this shell no longer sign the CLI in — using your `tot login` session instead.";
111
+
107
112
  /**
108
- * Establish a validated session on `client`.
109
- *
110
- * @param {ReturnType<import("./mcp.mjs").createMcpClient>} client
111
- * @param {{ env?: NodeJS.ProcessEnv, prefer?: "operator"|"developer" }} [opts]
112
- * @returns {Promise<{ identity: "operator"|"developer", appDomain: string|null }>}
113
+ * Emit the legacy-env advisory to stderr when the retired operator triple is set.
114
+ * A no-op otherwise. `warn` is injectable for tests; never touches the secret.
115
+ * @param {NodeJS.ProcessEnv} [env]
116
+ * @param {(msg: string) => void} [warn]
113
117
  */
114
- export async function resolveSession(client, opts = {}) {
115
- const env = opts.env || process.env;
116
- const prefer = opts.prefer || (hasOperatorCreds(env) ? "operator" : "developer");
117
-
118
- if (prefer === "operator") {
119
- if (!hasOperatorCreds(env)) {
120
- throw new AuthUnavailableError(
121
- "operator auth requested but TOT_API_KEY / TOT_SECRET_KEY / TOT_APP_DOMAIN are not all set.",
122
- { hint: "source apps/storefront/lib/resolve-tot-credentials.sh (from a storefront checkout), or unset --identity to use developer sign-in." },
123
- );
124
- }
125
- const validated = await client.callTool("credential_validate", {
126
- totApiKey: env.TOT_API_KEY,
127
- totSecretKey: env.TOT_SECRET_KEY,
128
- appDomain: env.TOT_APP_DOMAIN,
129
- });
130
- // Update-awareness Layer 2: the MCP may attach a version-support policy to the
131
- // authed response (wire contract: `cliPolicy`). Safe no-op when absent.
132
- recordServerPolicy(validated?.cliPolicy, env);
133
- return { identity: "operator", appDomain: env.TOT_APP_DOMAIN };
134
- }
135
-
136
- // developer provider — the real invited-dev path.
137
- return resolveDeveloperSession(client, env);
118
+ export function warnLegacyOperatorEnv(env = process.env, warn = (m) => console.error(m)) {
119
+ if (hasLegacyOperatorEnv(env)) warn(legacyOperatorEnvAdvisory);
138
120
  }
139
121
 
140
122
  /**
@@ -221,39 +203,35 @@ export async function resolveDeveloperSession(client, env, deps = {}) {
221
203
  * Establish a validated session on `client`, attaching auth in the CORRECT order
222
204
  * relative to the MCP handshake — the one thing every command must get right:
223
205
  *
224
- * developer → attach the cached bearer via setToken() BEFORE client.initialize(),
225
- * so the server binds the session to this identity AT initialize time.
226
- * An init-then-attach order leaves the session anonymous for its whole
227
- * life on a server that only binds identity at initialize — this is the
228
- * invited-developer "no stores you can build on" dead-end.
229
- * operator → client.initialize() FIRST, then credential_validate, which is an
230
- * in-session tool call that requires a completed handshake.
206
+ * attach the cached developer bearer via setToken() BEFORE client.initialize(),
207
+ * so the server binds the session to this identity AT initialize time. An
208
+ * init-then-attach order leaves the session anonymous for its whole life on a
209
+ * server that only binds identity at initialize — this is the invited-developer
210
+ * "no stores you can build on" dead-end. This ordering is load-bearing.
231
211
  *
232
- * Every command calls THIS instead of hand-ordering initialize() + resolveSession(),
233
- * so the ordering rule lives in exactly one place. `opts.initialize` lets a caller
234
- * inject its own handshake (to wrap the unreachable-MCP error, or pass custom
235
- * clientInfo); it defaults to `() => client.initialize()`.
212
+ * Every command calls THIS instead of hand-ordering initialize() + the developer
213
+ * resolver, so the ordering rule lives in exactly one place. `opts.initialize`
214
+ * lets a caller inject its own handshake (to wrap the unreachable-MCP error, or
215
+ * pass custom clientInfo); it defaults to `() => client.initialize()`.
216
+ *
217
+ * If the retired operator env-triple is set it emits a one-line advisory (see
218
+ * warnLegacyOperatorEnv) and proceeds on the OAuth session regardless — the keys
219
+ * are never read for auth.
236
220
  *
237
221
  * @param {ReturnType<import("./mcp.mjs").createMcpClient>} client
238
- * @param {{ env?: NodeJS.ProcessEnv, prefer?: "operator"|"developer",
239
- * initialize?: () => Promise<any> }} [opts]
240
- * @returns {Promise<{ identity: "operator"|"developer", appDomain: string|null, email?: string|null }>}
222
+ * @param {{ env?: NodeJS.ProcessEnv, initialize?: () => Promise<any> }} [opts]
223
+ * @returns {Promise<{ identity: "developer", appDomain: null, token: string, email?: string|null }>}
241
224
  */
242
225
  export async function establishSession(client, opts = {}) {
243
226
  const env = opts.env || process.env;
244
- const prefer = opts.prefer || (hasOperatorCreds(env) ? "operator" : "developer");
245
227
  const initialize = opts.initialize || (() => client.initialize());
246
228
 
247
- if (prefer === "developer") {
248
- // Attach the bearer, THEN handshake — the handshake carries the Authorization
249
- // header so the server binds this identity at initialize time.
250
- const session = await resolveDeveloperSession(client, env);
251
- await initialize();
252
- return session;
253
- }
254
- // Operator: handshake FIRST, then credential_validate (an in-session tool call).
229
+ warnLegacyOperatorEnv(env);
230
+ // Attach the bearer, THEN handshake — the handshake carries the Authorization
231
+ // header so the server binds this identity at initialize time.
232
+ const session = await resolveDeveloperSession(client, env);
255
233
  await initialize();
256
- return resolveSession(client, { env, prefer });
234
+ return session;
257
235
  }
258
236
 
259
237
  /**
@@ -6,15 +6,15 @@
6
6
  * tot checkout <tenant> show the checkout for <tenant>
7
7
  * tot checkout <tenant> --clone DIR clone it to DIR with an authed remote
8
8
  *
9
- * This is the SAME MCP code path a developer/operator gets when they switch to a
10
- * tenant: credential/sign-in → client_switch(tenant) → tenant_checkout, where
11
- * the MCP derives your per-tenant Git user and mints a FRESH, single-active,
12
- * repo-scoped push credential (a later checkout for the same tenant rotates it).
13
- * `tot` performs NO privileged forge work itself — the MCP owns that.
9
+ * This is the SAME MCP code path a developer gets when they switch to a tenant:
10
+ * sign-in → client_switch(tenant) → tenant_checkout, where the MCP derives your
11
+ * per-tenant Git user and mints a FRESH, single-active, repo-scoped push
12
+ * credential (a later checkout for the same tenant rotates it). `tot` performs NO
13
+ * privileged forge work itself — the MCP owns that.
14
14
  *
15
- * Auth is resolved through src/auth.mjs: operator creds (our dogfooding / CI) or
16
- * the developer's own ToT identity. This command doesn't care
17
- * whichit just needs a validated session.
15
+ * Auth is the developer's own ToT identity (the cached `tot login` session,
16
+ * resolved via src/auth.mjs). When there's no session yet and we're on a TTY, we
17
+ * offer to sign in right here and retry no "run tot login, then re-run".
18
18
  *
19
19
  * Dependency-free (global fetch + `git` via child_process).
20
20
  */
@@ -22,6 +22,7 @@ import { execFile } from "node:child_process";
22
22
  import { promisify } from "node:util";
23
23
  import { createMcpClient } from "../mcp.mjs";
24
24
  import { establishSession, AuthUnavailableError } from "../auth.mjs";
25
+ import { offerSignIn } from "./login.mjs";
25
26
  import { CliError, fail, formatError } from "../errors.mjs";
26
27
  import { writeNvmrc } from "../sample.mjs";
27
28
  import { emitObstacle } from "../obstacle.mjs";
@@ -36,7 +37,6 @@ function parseArgs(argv) {
36
37
  tag: "main",
37
38
  clone: null,
38
39
  mcp: null,
39
- identity: null, // "operator" | "developer" — override auto-selection
40
40
  printRemote: false,
41
41
  help: false,
42
42
  };
@@ -45,7 +45,6 @@ function parseArgs(argv) {
45
45
  if (t === "--tag") a.tag = argv[++i];
46
46
  else if (t === "--clone") a.clone = argv[++i];
47
47
  else if (t === "--mcp") a.mcp = argv[++i];
48
- else if (t === "--identity") a.identity = argv[++i];
49
48
  else if (t === "--print-remote") a.printRemote = true;
50
49
  else if (t === "--help" || t === "-h") a.help = true;
51
50
  else if (!t.startsWith("--") && !a.tenant) a.tenant = t;
@@ -64,7 +63,6 @@ Options:
64
63
  --clone <dir> git clone the authenticated remote into <dir>.
65
64
  --mcp <url> MCP base URL. Default: env MCP_BASE_URL / TOT_MCP_URL, else
66
65
  ${DEFAULT_MCP_URL}.
67
- --identity <who> force "operator" or "developer" auth (default: auto).
68
66
  --print-remote also print the authenticated remote (contains a live token!).`;
69
67
 
70
68
  /** Redact known secrets from any string before it hits the terminal. */
@@ -100,12 +98,21 @@ export async function run(argv, ctx) {
100
98
 
101
99
  try {
102
100
  // Attach auth in the right order relative to the handshake (developer bearer
103
- // BEFORE initialize; operator credential_validate after) — see establishSession.
104
- const session = await establishSession(client, {
105
- env,
106
- prefer: args.identity || undefined,
107
- });
108
- console.error(`~ signed in (${session.identity}) → ${client.mcpUrl}`);
101
+ // BEFORE initialize) — see establishSession. When there's no session yet and
102
+ // we're on a TTY, offer to sign in inline and retry once, so a not-signed-in
103
+ // developer isn't dead-ended at "run tot login, then re-run".
104
+ try {
105
+ await establishSession(client, { env });
106
+ } catch (e) {
107
+ if (e instanceof AuthUnavailableError && e.reason === "missing") {
108
+ const signedIn = await offerSignIn(client.mcpUrl, env, {});
109
+ if (!signedIn) throw e; // declined/non-TTY → the crisp error below
110
+ await establishSession(client, { env }); // retry once, in-flow
111
+ } else {
112
+ throw e;
113
+ }
114
+ }
115
+ console.error(`~ signed in → ${client.mcpUrl}`);
109
116
 
110
117
  // No tenant → list the stores this identity can build on and stop.
111
118
  if (!args.tenant) {
@@ -651,7 +651,7 @@ export async function resolveEntitledRendererSource(args, { client: providedClie
651
651
  *
652
652
  * Exported + accepts an already-authenticated `client` (C1/F3 integration:
653
653
  * `tot start` reuses its own session and overlaps this with the checkout clone
654
- * instead of paying for a second client.initialize()+resolveSession() — same
654
+ * instead of paying for a second client.initialize()+establishSession() — same
655
655
  * pattern as ensureRegistryLogin's `providedClient`). `tot dev` standalone
656
656
  * omits it and this establishes its own, as before.
657
657
  * @returns {Promise<string>} the cached, installed runner tree's root directory.
@@ -1355,7 +1355,7 @@ export function isPrivateRegistryImage(image) {
1355
1355
  *
1356
1356
  * Exported + accepts an already-authenticated `client` (C1: `tot start` reuses
1357
1357
  * its own session and overlaps this with the checkout clone instead of paying
1358
- * for a second client.initialize()+resolveSession() serially afterward).
1358
+ * for a second client.initialize()+establishSession() serially afterward).
1359
1359
  * `tot dev` standalone omits it and this establishes its own, as before.
1360
1360
  */
1361
1361
  export async function ensureRegistryLogin(image, args, { client: providedClient } = {}) {
@@ -22,7 +22,7 @@ import { spawnSync } from "node:child_process";
22
22
  import { existsSync, mkdirSync } from "node:fs";
23
23
  import { homedir } from "node:os";
24
24
  import { join } from "node:path";
25
- import { hasOperatorCreds } from "../auth.mjs";
25
+ import { hasLegacyOperatorEnv, legacyOperatorEnvAdvisory } from "../auth.mjs";
26
26
  import { MIN_NODE, nodeMeetsFloor } from "../ensure-node.mjs";
27
27
  import { clientPackages, osLabel } from "../mcp.mjs";
28
28
  import { defaultCredentialsPath, readCredentials, isExpired } from "../token-store.mjs";
@@ -110,28 +110,34 @@ export function collectChecks(_ctx, env = process.env) {
110
110
  blocking: false,
111
111
  });
112
112
 
113
- const operator = hasOperatorCreds(env);
114
- const devCreds = operator ? null : readCredentials(defaultCredentialsPath(env));
113
+ const devCreds = readCredentials(defaultCredentialsPath(env));
115
114
  const devUsable = !!devCreds?.accessToken && (!isExpired(devCreds) || !!devCreds.refreshToken);
116
115
  checks.push({
117
116
  name: "auth identity",
118
- pass: operator || devUsable,
119
- detail: operator
120
- ? "operator creds present (TOT_API_KEY/TOT_SECRET_KEY/TOT_APP_DOMAIN)"
121
- : devUsable
122
- ? "signed in as a developer"
123
- : "not signed in — run `tot login`",
117
+ pass: devUsable,
118
+ detail: devUsable ? "signed in as a developer" : "not signed in — run `tot login`",
124
119
  blocking: false,
125
120
  });
126
121
 
122
+ // A stale operator env-triple no longer signs the CLI in (OAuth-first since
123
+ // 2026-07-23) — surface it as an informational note, never a failure.
124
+ if (hasLegacyOperatorEnv(env)) {
125
+ checks.push({
126
+ name: "legacy keys",
127
+ pass: true,
128
+ detail: legacyOperatorEnvAdvisory,
129
+ blocking: false,
130
+ });
131
+ }
132
+
127
133
  return checks;
128
134
  }
129
135
 
130
136
  /**
131
137
  * Auto-remediate the checks that are safely fixable without human judgment
132
138
  * (F2) — announcing each one as it runs. A stale-but-refreshable sign-in isn't
133
- * handled here because it isn't a failing check: resolveSession() refreshes it
134
- * silently the next time it's actually used (B4).
139
+ * handled here because it isn't a failing check: the developer session refreshes
140
+ * it silently the next time it's actually used (B4).
135
141
  */
136
142
  async function applyFixes(checks, env) {
137
143
  const totDir = join(env.TOT_HOME || homedir(), ".tot");
@@ -144,7 +150,7 @@ async function applyFixes(checks, env) {
144
150
  if (docker && !docker.pass) await tryStartDocker();
145
151
 
146
152
  const auth = checks.find((c) => c.name === "auth identity");
147
- if (auth && !auth.pass && !hasOperatorCreds(env)) {
153
+ if (auth && !auth.pass) {
148
154
  const mcpUrl = env.MCP_BASE_URL || env.TOT_MCP_URL || DEFAULT_MCP_URL;
149
155
  console.log(" ~ not signed in — opening the browser to sign in…");
150
156
  try {
@@ -9,8 +9,8 @@
9
9
  * the developer copy-pasting anything.
10
10
  *
11
11
  * Auth: the MCP feedback tool is authenticated, so this reuses the signed-in session
12
- * (`resolveSession` operator creds if present, else the `tot login` developer
13
- * token). Not signed in → a clear "run `tot login`" instead of a stack trace.
12
+ * (the `tot login` developer token, via `establishSession`). Not signed in a
13
+ * clear "run `tot login`" instead of a stack trace.
14
14
  *
15
15
  * Sending publishes to Token of Trust, so we PREVIEW the report and ask before
16
16
  * sending (skippable with --yes; required in a non-interactive shell).
@@ -179,8 +179,8 @@ export async function run(argv) {
179
179
  const client = createMcpClient(mcpUrl);
180
180
  try {
181
181
  // Attach auth in the right order relative to the handshake (developer bearer
182
- // pre-initialize, operator credential_validate post-initialize). We keep the
183
- // feedback-specific clientInfo by injecting our own initialize.
182
+ // pre-initialize). We keep the feedback-specific clientInfo by injecting our
183
+ // own initialize.
184
184
  await establishSession(client, {
185
185
  env,
186
186
  initialize: () => client.initialize({ name: "tot-cli", version: "feedback" }),