@rosthq/cli 0.7.156 → 0.7.157

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/dist/index.js CHANGED
@@ -53026,6 +53026,121 @@ async function recordImplementationRunClosed(store, status, fields, closedAt = /
53026
53026
  });
53027
53027
  }
53028
53028
 
53029
+ // src/acting-principal.ts
53030
+ var ACTING_PRINCIPAL_KINDS = [
53031
+ "none",
53032
+ "unknown",
53033
+ "user_session",
53034
+ "implementation_bootstrap"
53035
+ ];
53036
+ var actingPrincipalSchema = external_exports.object({
53037
+ kind: external_exports.enum(ACTING_PRINCIPAL_KINDS),
53038
+ // The human subject or run identity behind the credential: the email for a
53039
+ // user session, the implementation-run id for the bounded credential.
53040
+ subject: external_exports.string().nullable(),
53041
+ email: external_exports.string().nullable(),
53042
+ tenant_id: external_exports.string().nullable(),
53043
+ // Resolving the tenant NAME requires a server round-trip, so it is null on
53044
+ // the offline hot path — the id below is the proven fact.
53045
+ tenant_name: external_exports.string().nullable(),
53046
+ // The authority label. `null` for a user session (owner vs steward is a
53047
+ // server-side fact this offline projection refuses to fake), the literal
53048
+ // "implementation credential" for the bounded principal.
53049
+ role: external_exports.string().nullable(),
53050
+ // The credential store the credential was read from (store.describe()).
53051
+ source: external_exports.string().nullable(),
53052
+ // A note naming the selected principal when it was chosen while another
53053
+ // credential was also available — the exact silent fall-through the defect
53054
+ // was about. Null when there was no competing credential.
53055
+ principal_switch: external_exports.string().nullable(),
53056
+ note: external_exports.string().nullable()
53057
+ }).strict();
53058
+ function decodeSessionIdentity(accessToken) {
53059
+ if (typeof accessToken !== "string" || accessToken.length === 0) {
53060
+ return { email: null, tenantId: null };
53061
+ }
53062
+ const segments = accessToken.split(".");
53063
+ if (segments.length < 2) {
53064
+ return { email: null, tenantId: null };
53065
+ }
53066
+ const payloadSegment = segments[1];
53067
+ if (payloadSegment === void 0 || payloadSegment.length === 0) {
53068
+ return { email: null, tenantId: null };
53069
+ }
53070
+ try {
53071
+ const json2 = Buffer.from(payloadSegment, "base64url").toString("utf8");
53072
+ const claims = JSON.parse(json2);
53073
+ if (typeof claims !== "object" || claims === null) {
53074
+ return { email: null, tenantId: null };
53075
+ }
53076
+ const record2 = claims;
53077
+ const email3 = typeof record2.email === "string" && record2.email.length > 0 ? record2.email : null;
53078
+ const appMetadata = typeof record2.app_metadata === "object" && record2.app_metadata !== null ? record2.app_metadata : {};
53079
+ const tenantId = typeof appMetadata.tenant_id === "string" && appMetadata.tenant_id.length > 0 ? appMetadata.tenant_id : null;
53080
+ return { email: email3, tenantId };
53081
+ } catch {
53082
+ return { email: null, tenantId: null };
53083
+ }
53084
+ }
53085
+ function userSessionActingPrincipal(params) {
53086
+ const identity = decodeSessionIdentity(params.accessToken);
53087
+ return {
53088
+ kind: "user_session",
53089
+ subject: identity.email,
53090
+ email: identity.email,
53091
+ tenant_id: identity.tenantId,
53092
+ tenant_name: params.tenantName ?? null,
53093
+ role: null,
53094
+ source: params.source,
53095
+ principal_switch: null,
53096
+ note: null
53097
+ };
53098
+ }
53099
+ function implementationActingPrincipal(params) {
53100
+ const other = params.otherCredential ?? null;
53101
+ return {
53102
+ kind: "implementation_bootstrap",
53103
+ subject: params.implementationRunId,
53104
+ email: null,
53105
+ tenant_id: params.tenantId,
53106
+ tenant_name: null,
53107
+ role: "implementation credential",
53108
+ source: params.source,
53109
+ principal_switch: other === null ? null : `selected over ${other}`,
53110
+ note: null
53111
+ };
53112
+ }
53113
+ function tenantClause(principal) {
53114
+ if (principal.tenant_name !== null) {
53115
+ return ` \xB7 tenant ${principal.tenant_name}`;
53116
+ }
53117
+ if (principal.tenant_id !== null) {
53118
+ return ` \xB7 tenant ${principal.tenant_id}`;
53119
+ }
53120
+ return " \xB7 no tenant selected";
53121
+ }
53122
+ function renderActingPrincipalHeader(principal) {
53123
+ if (principal.kind === "none") {
53124
+ return "acting as: none";
53125
+ }
53126
+ if (principal.kind === "unknown") {
53127
+ return "acting as: unknown";
53128
+ }
53129
+ if (principal.kind === "implementation_bootstrap") {
53130
+ const sourceClause2 = principal.source === null ? "" : ` \xB7 via ${principal.source}`;
53131
+ const switchClause = principal.principal_switch === null ? "" : ` \xB7 ${principal.principal_switch}`;
53132
+ return `acting as implementation credential${tenantClause(principal)}${sourceClause2}${switchClause}`;
53133
+ }
53134
+ const sourceClause = principal.source === null ? "" : ` \xB7 via ${principal.source}`;
53135
+ if (principal.email === null) {
53136
+ return `acting as user session (identity unresolved)${tenantClause(principal)}${sourceClause}`;
53137
+ }
53138
+ return `acting as ${principal.email} (user session)${tenantClause(principal)}${sourceClause}`;
53139
+ }
53140
+ function actingPrincipalEnvelope(principal, output) {
53141
+ return { acting_principal: principal, output };
53142
+ }
53143
+
53029
53144
  // src/cli-version.ts
53030
53145
  import { readFile as readFile4 } from "node:fs/promises";
53031
53146
  import { dirname, resolve } from "node:path";
@@ -54524,7 +54639,7 @@ External connectors are being rolled out provider by provider, conservatively (r
54524
54639
  order: 48,
54525
54640
  title: "CLI and MCP installation guide",
54526
54641
  summary: "Install the public CLI, register remote token-backed MCP clients, and find the full command and tool catalog.",
54527
- version: "2026-08-04.4",
54642
+ version: "2026-08-05.1",
54528
54643
  public: true,
54529
54644
  audiences: ["human", "cli", "mcp", "in_app_agent"],
54530
54645
  stages: ["company_setup", "staffing"],
@@ -55064,6 +55179,7 @@ These are the security posture rules for operating after install \u2014 a checkl
55064
55179
  ### Onboarding
55065
55180
 
55066
55181
  \`\`\`text
55182
+ {{cli}} onboard preflight [--json]
55067
55183
  {{cli}} onboard status
55068
55184
  {{cli}} onboard resume
55069
55185
  {{cli}} onboard run
@@ -55077,6 +55193,7 @@ Every tenant-scoped \`onboard\` verb (\`status\`, \`resume\`, \`source-ingest\`,
55077
55193
 
55078
55194
  | Command | Purpose | Scope | Safe example |
55079
55195
  |---|---|---|---|
55196
+ | \`{{cli}} onboard preflight\` | Print one pass/fail/unknown line per readiness condition (acting principal, implementation credential, CLI version, deployment reachability, pre-existing onboarding state) and exit nonzero on any fail or unknown. Runs before the session gate, so it works with no credentials. | Public (reports on whatever credential resolves) | \`{{cli}} onboard preflight --json\` |
55080
55197
  | \`{{cli}} onboard status\` | Return onboarding progress, graph summary, and next actions. | Tenant | \`{{cli}} onboard status\` |
55081
55198
  | \`{{cli}} onboard resume\` | Resume the guided onboarding flow where it left off. | Tenant | \`{{cli}} onboard resume\` |
55082
55199
  | \`{{cli}} onboard run\` | Print the deterministic agent onboarding prompt. | Public reference | \`{{cli}} onboard run\` |
@@ -59666,12 +59783,23 @@ ${onboardingUsage()}
59666
59783
  return 1;
59667
59784
  }
59668
59785
  const client = await deps.makeClient();
59669
- return executeOnboardingInvocation(invocation, io, client);
59786
+ return executeOnboardingInvocation(invocation, io, client, {
59787
+ ...deps.actingPrincipal === void 0 ? {} : { actingPrincipal: deps.actingPrincipal }
59788
+ });
59670
59789
  }
59671
59790
  async function executeOnboardingInvocation(invocation, io, client, options = {}) {
59791
+ const actingPrincipal = options.actingPrincipal;
59672
59792
  try {
59673
59793
  const result = await client.execute(invocation.commandId, invocation.body);
59674
- const rendered = invocation.json ? JSON.stringify(result.output, null, 2) : formatOnboardingOutput(invocation.action, result.output);
59794
+ if (actingPrincipal !== void 0 && !invocation.json) {
59795
+ io.stderr.write(`${renderActingPrincipalHeader(actingPrincipal)}
59796
+ `);
59797
+ }
59798
+ const rendered = invocation.json ? JSON.stringify(
59799
+ actingPrincipal === void 0 ? result.output : actingPrincipalEnvelope(actingPrincipal, result.output),
59800
+ null,
59801
+ 2
59802
+ ) : formatOnboardingOutput(invocation.action, result.output);
59675
59803
  io.stdout.write(`${rendered}
59676
59804
  `);
59677
59805
  return 0;
@@ -59956,6 +60084,7 @@ function parseSetupInvocation(action, args) {
59956
60084
  function onboardingUsage() {
59957
60085
  return [
59958
60086
  `Usage: ${cliBrand.binName} onboard status|resume [--json]`,
60087
+ ` ${cliBrand.binName} onboard preflight [--json]`,
59959
60088
  ` ${SOURCE_INGEST_USAGE}`,
59960
60089
  ` ${SETUP_USAGE}`,
59961
60090
  ` The plan's first seat (seats[0]) must be the single parentless root Seat and adopt the provisioned root Seat; its name must match the provisioned root seat's name after whitespace/case normalization.`,
@@ -60101,6 +60230,139 @@ function printCommandError(io, error51) {
60101
60230
  throw error51;
60102
60231
  }
60103
60232
 
60233
+ // src/commands/onboarding-preflight.ts
60234
+ var preflightCheckSchema = external_exports.object({
60235
+ name: external_exports.string(),
60236
+ status: external_exports.enum(["pass", "fail", "unknown"]),
60237
+ detail: external_exports.string()
60238
+ }).strict();
60239
+ var preflightResultSchema = external_exports.object({
60240
+ ok: external_exports.boolean(),
60241
+ acting_principal: actingPrincipalSchema,
60242
+ checks: external_exports.array(preflightCheckSchema)
60243
+ }).strict();
60244
+ function checkActingPrincipal(principal, sessionRefreshError, serverRejectedSession) {
60245
+ if (principal.kind === "none") {
60246
+ return {
60247
+ name: "acting principal",
60248
+ status: "fail",
60249
+ detail: "no credential resolved; run login or start an implementation run"
60250
+ };
60251
+ }
60252
+ if (principal.kind === "unknown") {
60253
+ return {
60254
+ name: "acting principal",
60255
+ status: "unknown",
60256
+ detail: "a credential is present but its identity could not be projected"
60257
+ };
60258
+ }
60259
+ if (sessionRefreshError !== null) {
60260
+ return {
60261
+ name: "acting principal",
60262
+ status: "fail",
60263
+ detail: `${renderActingPrincipalHeader(principal).replace(/^acting as:? /, "")} \u2014 but the session could not be refreshed (${sessionRefreshError}); run login again`
60264
+ };
60265
+ }
60266
+ if (serverRejectedSession) {
60267
+ return {
60268
+ name: "acting principal",
60269
+ status: "fail",
60270
+ detail: `${renderActingPrincipalHeader(principal).replace(/^acting as:? /, "")} \u2014 but the deployment rejected this session (HTTP 401); run login again`
60271
+ };
60272
+ }
60273
+ return {
60274
+ name: "acting principal",
60275
+ status: "pass",
60276
+ detail: renderActingPrincipalHeader(principal).replace(/^acting as:? /, "")
60277
+ };
60278
+ }
60279
+ function checkImplementationCredential(credential, principal) {
60280
+ const name = "implementation credential";
60281
+ if (credential.kind === "error") {
60282
+ return { name, status: "fail", detail: credential.detail };
60283
+ }
60284
+ if (credential.kind === "present") {
60285
+ if (credential.expired) {
60286
+ return { name, status: "fail", detail: `present but expired, stored_in ${credential.storedIn}` };
60287
+ }
60288
+ return { name, status: "pass", detail: `present and valid, stored_in ${credential.storedIn}` };
60289
+ }
60290
+ if (principal.kind === "user_session") {
60291
+ return { name, status: "pass", detail: "absent; not required \u2014 acting via the user session" };
60292
+ }
60293
+ return { name, status: "unknown", detail: "no implementation credential found" };
60294
+ }
60295
+ async function checkCliVersion(deps) {
60296
+ const name = "cli version";
60297
+ const current = deps.cliVersion ?? "unknown";
60298
+ const latest = await deps.fetchLatestVersion();
60299
+ if (latest === null) {
60300
+ return {
60301
+ name,
60302
+ status: "unknown",
60303
+ detail: `local ${current}; deployment provenance not verifiable without a version/git endpoint`
60304
+ };
60305
+ }
60306
+ if (deps.cliVersion !== null && deps.cliVersion === latest) {
60307
+ return { name, status: "pass", detail: `local ${current} matches the latest published ${latest}` };
60308
+ }
60309
+ return {
60310
+ name,
60311
+ status: "unknown",
60312
+ detail: `local ${current} differs from the latest published ${latest}; deployment build not proven`
60313
+ };
60314
+ }
60315
+ function renderDeploymentReachability(probe2) {
60316
+ const status = probe2.status === null ? "no HTTP status" : `HTTP ${probe2.status}`;
60317
+ return {
60318
+ name: "deployment reachability",
60319
+ // Both the HTTP status AND the command outcome must have held; a printed
60320
+ // 200 with a nonzero command exit is a fail.
60321
+ status: probe2.ok ? "pass" : "fail",
60322
+ detail: `${status} \u2014 ${probe2.detail}`
60323
+ };
60324
+ }
60325
+ async function checkOnboardingState(deps) {
60326
+ const name = "onboarding state";
60327
+ if (deps.readOnboardingState === null) {
60328
+ return { name, status: "unknown", detail: "skipped \u2014 no acting principal to resolve tenant state" };
60329
+ }
60330
+ const state = await deps.readOnboardingState();
60331
+ if (!state.ok) {
60332
+ return { name, status: "unknown", detail: state.detail };
60333
+ }
60334
+ return {
60335
+ name,
60336
+ status: "pass",
60337
+ detail: state.alreadyOnboarded ? `already onboarded \u2014 ${state.detail}` : state.detail
60338
+ };
60339
+ }
60340
+ async function runOnboardingPreflight(io, deps) {
60341
+ const probe2 = await deps.probeDeployment();
60342
+ const serverRejectedSession = !probe2.ok && probe2.status === 401 && deps.principal.kind === "user_session";
60343
+ const checks = [
60344
+ checkActingPrincipal(deps.principal, deps.sessionRefreshError, serverRejectedSession),
60345
+ checkImplementationCredential(deps.implementationCredential, deps.principal),
60346
+ await checkCliVersion(deps),
60347
+ renderDeploymentReachability(probe2),
60348
+ await checkOnboardingState(deps)
60349
+ ];
60350
+ const ok2 = checks.every((check2) => check2.status === "pass");
60351
+ const result = { ok: ok2, acting_principal: deps.principal, checks };
60352
+ if (deps.json) {
60353
+ io.stdout.write(`${JSON.stringify(result, null, 2)}
60354
+ `);
60355
+ } else {
60356
+ io.stdout.write(`${renderActingPrincipalHeader(deps.principal)}
60357
+ `);
60358
+ for (const check2 of checks) {
60359
+ io.stdout.write(`${check2.status}: ${check2.name} \u2014 ${check2.detail}
60360
+ `);
60361
+ }
60362
+ }
60363
+ return ok2 ? 0 : 1;
60364
+ }
60365
+
60104
60366
  // src/commands/implementation-access.ts
60105
60367
  var implementationCredentialSchema = external_exports.object({
60106
60368
  token: external_exports.string().regex(/^rost_impl_[A-Za-z0-9_-]+$/),
@@ -70464,7 +70726,7 @@ function createImplementationLifecycleHooks(reader, tombstoneStore, credential)
70464
70726
  }
70465
70727
  };
70466
70728
  }
70467
- function createImplementationBootstrapRun(io, outcome, lifecycle) {
70729
+ function createImplementationBootstrapRun(io, outcome, lifecycle, actingPrincipal) {
70468
70730
  return async (client, commandId, body, format, options) => {
70469
70731
  try {
70470
70732
  const result = await client.execute(commandId, body, options ?? {});
@@ -70483,7 +70745,11 @@ function createImplementationBootstrapRun(io, outcome, lifecycle) {
70483
70745
  return 1;
70484
70746
  }
70485
70747
  }
70486
- const rendered = format ? format(result.output) : JSON.stringify(result.output, null, 2);
70748
+ if (actingPrincipal !== void 0 && format !== void 0) {
70749
+ io.stderr.write(`${renderActingPrincipalHeader(actingPrincipal)}
70750
+ `);
70751
+ }
70752
+ const rendered = actingPrincipal !== void 0 && format === void 0 ? JSON.stringify(actingPrincipalEnvelope(actingPrincipal, result.output), null, 2) : format ? format(result.output) : JSON.stringify(result.output, null, 2);
70487
70753
  io.stdout.write(`${rendered}
70488
70754
  `);
70489
70755
  return 0;
@@ -70794,6 +71060,40 @@ async function main(argv = process.argv.slice(2), options = {}) {
70794
71060
  }
70795
71061
  const implCredentialReader = createImplementationCredentialReader(options.implementationCredentialStore);
70796
71062
  const tombstoneStore = (options.implementationRunTombstoneStore ?? createImplementationRunTombstoneStore)();
71063
+ if (command === "onboard" && args[0] === "preflight") {
71064
+ let sessionRefreshError = null;
71065
+ const implCredentialPresent = (await implCredentialReader.read()).kind === "present";
71066
+ if (session && !implCredentialPresent) {
71067
+ try {
71068
+ const refreshed2 = await refreshSession(config2, session);
71069
+ if (refreshed2 !== session) {
71070
+ session = refreshed2;
71071
+ try {
71072
+ await store.write(session);
71073
+ } catch (error51) {
71074
+ io.stderr.write(
71075
+ `Session refreshed, but storing it failed: ${redactForLog(error51 instanceof Error ? error51.message : String(error51))}
71076
+ Run ${cliBrand.binName} login --device again if the next command asks you to authenticate.
71077
+ `
71078
+ );
71079
+ }
71080
+ }
71081
+ } catch (error51) {
71082
+ sessionRefreshError = redactForLog(error51 instanceof Error ? error51.message : String(error51));
71083
+ }
71084
+ }
71085
+ return executeOnboardPreflight({
71086
+ io,
71087
+ json: args.includes("--json"),
71088
+ session,
71089
+ sessionRefreshError,
71090
+ appUrl: config2.appUrl,
71091
+ storeSource: store.describe(),
71092
+ CommandClientCtor: options.commandClient ?? CommandClient,
71093
+ implCredentialReader,
71094
+ env: process.env
71095
+ });
71096
+ }
70797
71097
  if (command === "onboard" && (args[0] === "status" || args[0] === "resume" || args[0] === "rehearse" || args[0] === "activate" || args[0] === "source-ingest" || args[0] === "setup" || args[0] === "setup-status")) {
70798
71098
  const credentialResolution = await resolveImplementationCredential(
70799
71099
  implCredentialReader,
@@ -70829,6 +71129,12 @@ ${onboardingUsage()}
70829
71129
  });
70830
71130
  let unusable = false;
70831
71131
  let denied = false;
71132
+ const implPrincipal = implementationActingPrincipal({
71133
+ tenantId: implCredential.tenant_id,
71134
+ implementationRunId: implCredential.implementation_run_id,
71135
+ source: implCredentialReader.describe(),
71136
+ otherCredential: session ? "your logged-in user session" : null
71137
+ });
70832
71138
  const exit = await executeOnboardingInvocation(invocation, io, implClient, {
70833
71139
  onError: (error51) => {
70834
71140
  if (error51 instanceof ImplementationBootstrapDeniedError) {
@@ -70840,7 +71146,8 @@ ${onboardingUsage()}
70840
71146
  return "handled";
70841
71147
  }
70842
71148
  return "print";
70843
- }
71149
+ },
71150
+ actingPrincipal: implPrincipal
70844
71151
  });
70845
71152
  if (exit !== "fall-through") {
70846
71153
  if (exit === 0 && !invocation.json && (invocation.action === "status" || invocation.action === "resume")) {
@@ -70876,6 +71183,12 @@ ${onboardingUsage()}
70876
71183
  if (credentialResolution.kind === "usable") {
70877
71184
  const implCredential = credentialResolution.credential;
70878
71185
  const outcome = { unusable: false, denied: false, cleanupFailed: false };
71186
+ const implPrincipal = implementationActingPrincipal({
71187
+ tenantId: implCredential.tenant_id,
71188
+ implementationRunId: implCredential.implementation_run_id,
71189
+ source: implCredentialReader.describe(),
71190
+ otherCredential: session ? "your logged-in user session" : null
71191
+ });
70879
71192
  const exit = await runOperation("seat", args, {
70880
71193
  io,
70881
71194
  client: createImplementationBootstrapClient(options.commandClient ?? CommandClient, {
@@ -70883,7 +71196,7 @@ ${onboardingUsage()}
70883
71196
  token: implCredential.token
70884
71197
  }),
70885
71198
  binName: cliBrand.binName,
70886
- run: createImplementationBootstrapRun(io, outcome)
71199
+ run: createImplementationBootstrapRun(io, outcome, void 0, implPrincipal)
70887
71200
  });
70888
71201
  if (!outcome.unusable && !outcome.denied && !outcome.cleanupFailed) {
70889
71202
  return exit;
@@ -70938,7 +71251,15 @@ ${onboardingUsage()}
70938
71251
  credentialResolution.credential
70939
71252
  ),
70940
71253
  hasUserSession: Boolean(session),
70941
- CommandClientCtor: options.commandClient ?? CommandClient
71254
+ CommandClientCtor: options.commandClient ?? CommandClient,
71255
+ // DER-2812: name the bounded principal; a co-resident session means
71256
+ // it was selected over the owner's own session for this command.
71257
+ actingPrincipal: implementationActingPrincipal({
71258
+ tenantId: credentialResolution.credential.tenant_id,
71259
+ implementationRunId: credentialResolution.credential.implementation_run_id,
71260
+ source: implCredentialReader.describe(),
71261
+ otherCredential: session ? "your logged-in user session" : null
71262
+ })
70942
71263
  });
70943
71264
  if (routed !== "fall-through") {
70944
71265
  return routed;
@@ -70982,6 +71303,10 @@ Run ${cliBrand.binName} login --device again if the next command asks you to aut
70982
71303
  token: session.accessToken,
70983
71304
  credentialKind: "user_session"
70984
71305
  });
71306
+ const actingPrincipal = userSessionActingPrincipal({
71307
+ accessToken: session.accessToken,
71308
+ source: store.describe()
71309
+ });
70985
71310
  if (justLoggedIn) {
70986
71311
  await maybePrintSignupBootstrap(io, client, config2.appUrl);
70987
71312
  }
@@ -70992,16 +71317,16 @@ Run ${cliBrand.binName} login --device again if the next command asks you to aut
70992
71317
  return runTenantCreate(io, client, args, (tenantIo, tenantClient, commandId, body) => executeCommandWithResult(tenantIo, tenantClient, commandId, body));
70993
71318
  }
70994
71319
  if (command === "whoami") {
70995
- return printCommandOutput(io, client, "user.whoami");
71320
+ return printCommandOutput(io, client, "user.whoami", {}, void 0, {}, actingPrincipal);
70996
71321
  }
70997
71322
  if (command === "tenants") {
70998
- return printCommandOutput(io, client, "user.tenants");
71323
+ return printCommandOutput(io, client, "user.tenants", {}, void 0, {}, actingPrincipal);
70999
71324
  }
71000
71325
  if (command === "command") {
71001
- return executeDirectCommand(io, client, args);
71326
+ return executeDirectCommand(io, client, args, void 0, actingPrincipal);
71002
71327
  }
71003
71328
  if (command === "onboard") {
71004
- return runOnboarding(args, io, { makeClient: async () => client });
71329
+ return runOnboarding(args, io, { makeClient: async () => client, actingPrincipal });
71005
71330
  }
71006
71331
  if (command === "mcp") {
71007
71332
  return executeMcp(io, client, config2.appUrl, args);
@@ -71012,18 +71337,18 @@ Run ${cliBrand.binName} login --device again if the next command asks you to aut
71012
71337
  io,
71013
71338
  client,
71014
71339
  binName: cliBrand.binName,
71015
- run: (wrapperClient, commandId, body, format, options2) => printCommandOutput(io, wrapperClient, commandId, body, format, options2)
71340
+ run: (wrapperClient, commandId, body, format, options2) => printCommandOutput(io, wrapperClient, commandId, body, format, options2, actingPrincipal)
71016
71341
  });
71017
71342
  }
71018
71343
  return runSkills({
71019
71344
  io,
71020
71345
  client,
71021
71346
  binName: cliBrand.binName,
71022
- run: (wrapperClient, commandId, body, format, options2) => printCommandOutput(io, wrapperClient, commandId, body, format, options2)
71347
+ run: (wrapperClient, commandId, body, format, options2) => printCommandOutput(io, wrapperClient, commandId, body, format, options2, actingPrincipal)
71023
71348
  }, args);
71024
71349
  }
71025
71350
  if (command === "init") {
71026
- return executeInit(io, client, config2.appUrl, args);
71351
+ return executeInit(io, client, config2.appUrl, args, actingPrincipal);
71027
71352
  }
71028
71353
  if (isOperationGroup(command)) {
71029
71354
  return runOperation(command, args, {
@@ -71032,7 +71357,7 @@ Run ${cliBrand.binName} login --device again if the next command asks you to aut
71032
71357
  binName: cliBrand.binName,
71033
71358
  // Single execution path: wrappers route through printCommandOutput, the
71034
71359
  // same helper `rost command <id> --json` uses (shared client + redaction).
71035
- run: (wrapperClient, commandId, body, format, options2) => printCommandOutput(io, wrapperClient, commandId, body, format, options2)
71360
+ run: (wrapperClient, commandId, body, format, options2) => printCommandOutput(io, wrapperClient, commandId, body, format, options2, actingPrincipal)
71036
71361
  });
71037
71362
  }
71038
71363
  const tenant = args[0];
@@ -71041,7 +71366,7 @@ Run ${cliBrand.binName} login --device again if the next command asks you to aut
71041
71366
  `);
71042
71367
  return 1;
71043
71368
  }
71044
- return printCommandOutput(io, client, "user.use_tenant", { tenant });
71369
+ return printCommandOutput(io, client, "user.use_tenant", { tenant }, void 0, {}, actingPrincipal);
71045
71370
  }
71046
71371
  function resolveRoutableCommandId(command, args) {
71047
71372
  if (command === "command") {
@@ -71077,7 +71402,7 @@ async function runImplementationBootstrapCommand(params) {
71077
71402
  token: params.token
71078
71403
  });
71079
71404
  const outcome = { unusable: false, denied: false, cleanupFailed: false };
71080
- const run2 = createImplementationBootstrapRun(io, outcome, params.lifecycle);
71405
+ const run2 = createImplementationBootstrapRun(io, outcome, params.lifecycle, params.actingPrincipal);
71081
71406
  let exit;
71082
71407
  try {
71083
71408
  if (command === "command") {
@@ -71108,7 +71433,103 @@ async function runImplementationBootstrapCommand(params) {
71108
71433
  }
71109
71434
  return exit;
71110
71435
  }
71111
- async function executeDirectCommand(io, client, args, send = (sendClient, commandId, body, format, options) => printCommandOutput(io, sendClient, commandId, body, format, options)) {
71436
+ async function executeOnboardPreflight(params) {
71437
+ const { io, session, appUrl: appUrl2, CommandClientCtor, implCredentialReader } = params;
71438
+ const implResult = await implCredentialReader.read();
71439
+ const implExpired = implResult.kind === "present" && isImplementationCredentialExpired(implResult.credential.expires_at);
71440
+ const implementationCredential = implResult.kind === "present" ? { kind: "present", expired: implExpired, storedIn: implCredentialReader.describe() } : implResult.kind === "error" ? { kind: "error", detail: `unable to read the implementation credential from ${implCredentialReader.describe()}` } : { kind: "absent" };
71441
+ const presentImpl = implResult.kind === "present" ? implResult.credential : null;
71442
+ const principal = presentImpl ? implementationActingPrincipal({
71443
+ tenantId: presentImpl.tenant_id,
71444
+ implementationRunId: presentImpl.implementation_run_id,
71445
+ source: implCredentialReader.describe(),
71446
+ otherCredential: session ? "your logged-in user session" : null
71447
+ }) : session ? userSessionActingPrincipal({ accessToken: session.accessToken, source: params.storeSource }) : { kind: "none", subject: null, email: null, tenant_id: null, tenant_name: null, role: null, source: null, principal_switch: null, note: null };
71448
+ const probeWith = async (client, commandId, label) => {
71449
+ try {
71450
+ await client.execute(commandId);
71451
+ return { ok: true, status: 200, detail: `${label} succeeded` };
71452
+ } catch (error51) {
71453
+ const status = error51 instanceof CommandClientError ? error51.status : null;
71454
+ return { ok: false, status, detail: `${label} did not complete` };
71455
+ }
71456
+ };
71457
+ const probeDeployment = async () => {
71458
+ if (presentImpl) {
71459
+ const client = createImplementationBootstrapClient(CommandClientCtor, { appUrl: appUrl2, token: presentImpl.token });
71460
+ return probeWith(client, "onboarding.status", "implementation-credential round-trip");
71461
+ }
71462
+ if (session) {
71463
+ const client = new CommandClientCtor({ appUrl: appUrl2, token: session.accessToken, credentialKind: "user_session" });
71464
+ return probeWith(client, "user.whoami", "authenticated user-session round-trip");
71465
+ }
71466
+ try {
71467
+ const response = await fetch(appUrl2, { method: "GET" });
71468
+ return {
71469
+ ok: response.ok,
71470
+ status: response.status,
71471
+ detail: `unauthenticated GET ${response.ok ? "reachable" : "not reachable"}`
71472
+ };
71473
+ } catch (error51) {
71474
+ return {
71475
+ ok: false,
71476
+ status: null,
71477
+ detail: `unauthenticated GET failed: ${redactForLog(error51 instanceof Error ? error51.message : String(error51))}`
71478
+ };
71479
+ }
71480
+ };
71481
+ const stateClient = presentImpl ? createImplementationBootstrapClient(CommandClientCtor, { appUrl: appUrl2, token: presentImpl.token }) : session ? new CommandClientCtor({ appUrl: appUrl2, token: session.accessToken, credentialKind: "user_session" }) : null;
71482
+ const readOnboardingState = stateClient === null ? null : async () => {
71483
+ try {
71484
+ const result = await stateClient.execute("onboarding.status");
71485
+ const record2 = asRecord5(result.output);
71486
+ const onboarded = record2.onboarded === true;
71487
+ return {
71488
+ ok: true,
71489
+ alreadyOnboarded: onboarded,
71490
+ detail: onboarded ? "onboarding.status reports onboarded" : "onboarding.status reports not yet onboarded"
71491
+ };
71492
+ } catch {
71493
+ return { ok: false, alreadyOnboarded: false, detail: "onboarding.status could not be read for this principal" };
71494
+ }
71495
+ };
71496
+ return runOnboardingPreflight(io, {
71497
+ json: params.json,
71498
+ principal,
71499
+ // Only meaningful for a session-backed principal; a present implementation
71500
+ // credential skips the refresh entirely, so this is null on that path.
71501
+ sessionRefreshError: presentImpl ? null : params.sessionRefreshError,
71502
+ implementationCredential,
71503
+ cliVersion: await readCliVersion(),
71504
+ fetchLatestVersion: () => fetchLatestCliVersion(params.env),
71505
+ probeDeployment,
71506
+ readOnboardingState
71507
+ });
71508
+ }
71509
+ async function fetchLatestCliVersion(env) {
71510
+ if (env.CI || env.VITEST || env[`${cliBrand.envPrefix}_CLI_NO_UPDATE_CHECK`] === "1") {
71511
+ return null;
71512
+ }
71513
+ const controller = new AbortController();
71514
+ const timeout = setTimeout(() => controller.abort(), 750);
71515
+ try {
71516
+ const response = await fetch(`https://registry.npmjs.org/${encodeURIComponent(cliBrand.packageName)}/latest`, {
71517
+ headers: { accept: "application/json" },
71518
+ signal: controller.signal
71519
+ });
71520
+ if (!response.ok) {
71521
+ return null;
71522
+ }
71523
+ const body = await response.json();
71524
+ return typeof body.version === "string" ? body.version : null;
71525
+ } catch {
71526
+ return null;
71527
+ } finally {
71528
+ clearTimeout(timeout);
71529
+ }
71530
+ }
71531
+ async function executeDirectCommand(io, client, args, send, actingPrincipal) {
71532
+ const sendCommand = send ?? ((sendClient, commandId2, body2, format, options) => printCommandOutput(io, sendClient, commandId2, body2, format, options, actingPrincipal));
71112
71533
  const first = args[0];
71113
71534
  if (first === "schema") {
71114
71535
  const id = args[1];
@@ -71118,11 +71539,11 @@ async function executeDirectCommand(io, client, args, send = (sendClient, comman
71118
71539
  return 1;
71119
71540
  }
71120
71541
  const json2 = args.includes("--json");
71121
- return send(client, "command.describe", { id }, json2 ? void 0 : formatCommandSchema);
71542
+ return sendCommand(client, "command.describe", { id }, json2 ? void 0 : formatCommandSchema);
71122
71543
  }
71123
71544
  if (first === "list") {
71124
71545
  const json2 = args.includes("--json");
71125
- return send(client, "command.list", {}, json2 ? void 0 : formatCommandList);
71546
+ return sendCommand(client, "command.list", {}, json2 ? void 0 : formatCommandList);
71126
71547
  }
71127
71548
  const commandId = first;
71128
71549
  if (isSecretBlockedCommand(commandId)) {
@@ -71155,7 +71576,7 @@ async function executeDirectCommand(io, client, args, send = (sendClient, comman
71155
71576
  `);
71156
71577
  return 1;
71157
71578
  }
71158
- return send(client, commandId, body, void 0, {
71579
+ return sendCommand(client, commandId, body, void 0, {
71159
71580
  ...seat === void 0 ? {} : { targetSeatId: seat },
71160
71581
  autoConfirm
71161
71582
  });
@@ -71233,10 +71654,10 @@ async function executeMcp(io, client, appUrl2, args) {
71233
71654
  return 1;
71234
71655
  }
71235
71656
  }
71236
- async function executeInit(io, client, appUrl2, args) {
71657
+ async function executeInit(io, client, appUrl2, args, actingPrincipal) {
71237
71658
  const { tenant, mcpArgs } = parseInitArgs(args);
71238
71659
  if (tenant) {
71239
- const tenantExitCode = await printCommandOutput(io, client, "user.use_tenant", { tenant });
71660
+ const tenantExitCode = await printCommandOutput(io, client, "user.use_tenant", { tenant }, void 0, {}, actingPrincipal);
71240
71661
  if (tenantExitCode !== 0) {
71241
71662
  return tenantExitCode;
71242
71663
  }
@@ -71273,11 +71694,23 @@ function parseInitArgs(args) {
71273
71694
  mcpArgs: hasScope || isRotate ? baseArgs : [...baseArgs, "--scope", "tenant-admin"]
71274
71695
  };
71275
71696
  }
71276
- async function printCommandOutput(io, client, commandId, body = {}, format, options = {}) {
71697
+ async function printCommandOutput(io, client, commandId, body = {}, format, options = {}, actingPrincipal) {
71698
+ const emitHeader = () => {
71699
+ if (actingPrincipal !== void 0 && format !== void 0) {
71700
+ io.stderr.write(`${renderActingPrincipalHeader(actingPrincipal)}
71701
+ `);
71702
+ }
71703
+ };
71704
+ const renderResult = (output) => {
71705
+ if (actingPrincipal !== void 0 && format === void 0) {
71706
+ return JSON.stringify(actingPrincipalEnvelope(actingPrincipal, output), null, 2);
71707
+ }
71708
+ return format ? format(output) : JSON.stringify(output, null, 2);
71709
+ };
71277
71710
  try {
71278
71711
  const result = await client.execute(commandId, body, options);
71279
- const rendered = format ? format(result.output) : JSON.stringify(result.output, null, 2);
71280
- io.stdout.write(`${rendered}
71712
+ emitHeader();
71713
+ io.stdout.write(`${renderResult(result.output)}
71281
71714
  `);
71282
71715
  return 0;
71283
71716
  } catch (error51) {
@@ -71297,8 +71730,8 @@ async function printCommandOutput(io, client, commandId, body = {}, format, opti
71297
71730
  reviewed: true
71298
71731
  });
71299
71732
  const approvedOutput = asRecord5(approvedResult.output).output ?? approvedResult.output;
71300
- const rendered = format ? format(approvedOutput) : JSON.stringify(approvedOutput, null, 2);
71301
- io.stdout.write(`${rendered}
71733
+ emitHeader();
71734
+ io.stdout.write(`${renderResult(approvedOutput)}
71302
71735
  `);
71303
71736
  return 0;
71304
71737
  } catch (approvalError) {
@@ -71311,8 +71744,8 @@ async function printCommandOutput(io, client, commandId, body = {}, format, opti
71311
71744
  try {
71312
71745
  const approvedResult = await client.execute("confirmation.approve", { confirmation_id: pending.confirmationId });
71313
71746
  const approvedOutput = asRecord5(approvedResult.output).output ?? approvedResult.output;
71314
- const rendered = format ? format(approvedOutput) : JSON.stringify(approvedOutput, null, 2);
71315
- io.stdout.write(`${rendered}
71747
+ emitHeader();
71748
+ io.stdout.write(`${renderResult(approvedOutput)}
71316
71749
  `);
71317
71750
  return 0;
71318
71751
  } catch (approvalError) {
@@ -71435,6 +71868,7 @@ function printUsage(io) {
71435
71868
  `${cliBrand.binName} command list [--json]`,
71436
71869
  `${cliBrand.binName} doctor`,
71437
71870
  ...operationUsageLines(cliBrand.binName),
71871
+ `${cliBrand.binName} onboard preflight [--json]`,
71438
71872
  `${cliBrand.binName} onboard status`,
71439
71873
  `${cliBrand.binName} onboard resume`,
71440
71874
  `${cliBrand.binName} onboard run`,