@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/acting-principal.d.ts +82 -0
- package/dist/acting-principal.d.ts.map +1 -0
- package/dist/acting-principal.test.d.ts +2 -0
- package/dist/acting-principal.test.d.ts.map +1 -0
- package/dist/commands/onboarding-preflight.d.ts +86 -0
- package/dist/commands/onboarding-preflight.d.ts.map +1 -0
- package/dist/commands/onboarding-preflight.test.d.ts +2 -0
- package/dist/commands/onboarding-preflight.test.d.ts.map +1 -0
- package/dist/commands/onboarding.d.ts +6 -1
- package/dist/commands/onboarding.d.ts.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +465 -31
- package/dist/index.js.map +4 -4
- package/package.json +1 -1
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-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
71280
|
-
io.stdout.write(`${
|
|
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
|
-
|
|
71301
|
-
io.stdout.write(`${
|
|
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
|
-
|
|
71315
|
-
io.stdout.write(`${
|
|
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`,
|