@rosthq/cli 0.7.113 → 0.7.115

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
@@ -38708,6 +38708,14 @@ function accessLevelForScope(scopeTier) {
38708
38708
  return "admin";
38709
38709
  }
38710
38710
  }
38711
+ var RUNNER_WIRED_CONNECTOR_IDS = /* @__PURE__ */ new Set([
38712
+ "gmail.read",
38713
+ "gmail.draft",
38714
+ "gmail.send",
38715
+ "sheets.read",
38716
+ "sheets.write",
38717
+ "slack.post_message"
38718
+ ]);
38711
38719
  function providerRequirementFor(entry) {
38712
38720
  if (!entry.credential_required) {
38713
38721
  return entry.provider === "rost" || entry.provider === "web" ? "platform_managed" : "none";
@@ -38730,6 +38738,12 @@ function trustedRequiredMetadataFor(entry) {
38730
38738
  "authorization_revoked_at"
38731
38739
  ];
38732
38740
  }
38741
+ function laneSupportFor(entry) {
38742
+ if (providerRequirementFor(entry) === "connection" && !RUNNER_WIRED_CONNECTOR_IDS.has(entry.id)) {
38743
+ return ["cloud"];
38744
+ }
38745
+ return ["cloud", "runner", "mcp"];
38746
+ }
38733
38747
  function enrichCatalogEntry(entry) {
38734
38748
  const accessLevels = [...new Set(entry.scope_tiers.map(accessLevelForScope))];
38735
38749
  return {
@@ -38738,7 +38752,7 @@ function enrichCatalogEntry(entry) {
38738
38752
  default_access_level: accessLevelForScope(entry.default_scope_tier),
38739
38753
  provider_requirement: providerRequirementFor(entry),
38740
38754
  cost_class: entry.id === "script.run" || entry.id === "secret.broker" || entry.id === "baserow.read" || entry.id === "baserow.write" ? "metered_standard" : entry.id === "web.search" || entry.id === "web.fetch" || entry.id === "browser.read" ? "metered_low" : "included",
38741
- lane_support: ["cloud", "runner", "mcp"],
38755
+ lane_support: laneSupportFor(entry),
38742
38756
  trusted_required_metadata: trustedRequiredMetadataFor(entry)
38743
38757
  };
38744
38758
  }
@@ -39856,6 +39870,8 @@ var tenantCapabilityGrantDtoSchema = external_exports.object({
39856
39870
  default_agent_access_level: capabilityGrantAccessLevelSchema,
39857
39871
  compile_status: capabilityGrantCompileStatusSchema
39858
39872
  }).strict();
39873
+ var capabilityGrantGrantSourceSchema = external_exports.enum(["charter", "template"]);
39874
+ var capabilityGrantCeilingSourceSchema = external_exports.enum(["tenant_policy", "unset"]);
39859
39875
  var agentEffectiveCapabilityGrantDtoSchema = external_exports.object({
39860
39876
  tool_grant_id: uuidSchema5,
39861
39877
  agent_tool_grant_id: uuidSchema5.nullable(),
@@ -39865,6 +39881,8 @@ var agentEffectiveCapabilityGrantDtoSchema = external_exports.object({
39865
39881
  availability: capabilityGrantAvailabilitySchema,
39866
39882
  source: capabilityGrantSourceSchema,
39867
39883
  selection_source: capabilityGrantSourceSchema.nullable(),
39884
+ grant_source: capabilityGrantGrantSourceSchema.nullable(),
39885
+ ceiling_source: capabilityGrantCeilingSourceSchema,
39868
39886
  max_access_level: capabilityGrantAccessLevelSchema,
39869
39887
  default_agent_access_level: capabilityGrantAccessLevelSchema,
39870
39888
  selected_access_level: capabilityGrantAccessLevelSchema,
@@ -48681,7 +48699,7 @@ Use the lower-level commands after health names a finding: \`agent.get_run\` for
48681
48699
  order: 46,
48682
48700
  title: "Tool access and vault",
48683
48701
  summary: "How to give agents access to tools without exposing raw credentials or expanding authority by accident.",
48684
- version: "2026-07-19.1",
48702
+ version: "2026-07-21.1",
48685
48703
  public: true,
48686
48704
  audiences: ["human", "cli", "mcp", "in_app_agent"],
48687
48705
  stages: ["staffing"],
@@ -48737,6 +48755,10 @@ The native Gmail handlers run inside the same broker boundary as the REST and Sl
48737
48755
 
48738
48756
  Google can be connected from Settings once the workspace OAuth app is configured. The connection flow requests offline access for Gmail read/compose/send and Sheets, stores the returned credential in the vault, and records only account, scope, and capability-availability metadata in the integration row. Partial grants are accepted when at least one connector capability is usable; missing or revoked scopes reduce the affected capability instead of granting more authority. The test action refreshes the vaulted credential and performs a minimal Gmail profile read. Gmail read/draft/send, bounded Sheets read, and approval-held Sheets write handlers run through the guarded broker when Google is connected; connecting Google still does not bypass the signed Charter manifest, tenant policy ceiling, credential vault, or tool-call audit. Sheet grants should use exact signed argument bindings for approved spreadsheet ids and ranges.
48739
48757
 
48758
+ ## Connectors work the same on either lane
48759
+
48760
+ A seat's governed connectors are available whether its agent runs on the cloud lane or the runner lane. {{brand}} projects each connector the seat's signed Charter grants onto the seat's own MCP surface and executes it server-side \u2014 so a runner-lane agent calls the same Gmail, Sheets, and Slack connectors a cloud-lane agent does, with identical governance: the same server guard, the same held-write approval for send/write tiers, and the same tool-call audit row. The OAuth or vaulted credential is resolved and bound only on the server inside the credential closure and never travels to the runner. Because this projection is derived from the Charter manifest and the connected integration, connecting a new integration makes its capabilities available to an already-live runner seat with no charter re-sign or code change. Connectors without a server-side handler yet stay cloud-only and are shown on the seat's Tools tab as not available on the runner lane until one ships.
48761
+
48740
48762
  A connected Baserow REST integration (\`integration.connect_rest\`) derives a \`baserow.read\` tenant capability ceiling the same way: a live connection surfaces read, and a disconnected/revoked one collapses to off. The derivation is read-only by design \u2014 \`baserow.write\` is never inferred from the connection and is granted only through an explicit per-seat brokered secret grant, matching the conservative-by-default rule for every connection-backed ceiling.
48741
48763
 
48742
48764
  CLI and MCP can inspect connector readiness without seeing secrets: \`integration.list\` / \`rost_list_integrations\` lists connected providers and health metadata, \`integration.status\` / \`rost_get_integration_status\` reads one provider by id or name, and \`integration.test\` / \`rost_test_integration_connection\` runs the installed provider-specific health check. For Google, the test refreshes the vaulted OAuth credential and reads the Gmail profile, then records only account, scope, and health metadata.
@@ -48835,7 +48857,7 @@ External connectors are being rolled out provider by provider, conservatively (r
48835
48857
  order: 48,
48836
48858
  title: "CLI and MCP installation guide",
48837
48859
  summary: "Install the public CLI, register remote token-backed MCP clients, and find the full command and tool catalog.",
48838
- version: "2026-07-20.1",
48860
+ version: "2026-07-21.1",
48839
48861
  public: true,
48840
48862
  audiences: ["human", "cli", "mcp", "in_app_agent"],
48841
48863
  stages: ["company_setup", "staffing"],
@@ -49575,7 +49597,7 @@ Several rows here are seat-operating commands (\`task.create\`, the \`signal.*\`
49575
49597
  | \`rost_list_tool_catalog\` | \`tool.catalog\` | List the discoverable tool catalog the agent builder reads \u2014 id, prescriptive description, scope tiers, credential requirement, access policy, and execution-boundary guidance. | Tenant | Call with \`{}\` or \`{"provider":"google"}\`. |
49576
49598
  | \`rost_list_tenant_capability_grants\` | \`tool_grants.tenant.list\` | List tenant capability ceilings/defaults with connection, availability, source, and compile status. | Tenant | Call with \`{}\`; no secrets or vault refs. |
49577
49599
  | \`rost_update_tenant_capability_policy\` | \`tool_grants.tenant.update\` | Change tenant-wide capability ceilings/defaults with optimistic policy version or digest protection. | Tenant-admin | Human-gated; call with \`expected_policy_version\` or \`expected_policy_digest\`, \`mode\`, and grant ceiling changes. Returns changed grants, clamped defaults, and affected live agents. |
49578
- | \`rost_list_agent_effective_capability_grants\` | \`tool_grants.agent.effective\` | Read one agent's effective capability grants after tenant ceilings, agent selections, and compile availability are applied. | Tenant | Call with \`{"agent_id":"<agent-id>"}\`. |
49600
+ | \`rost_list_agent_effective_capability_grants\` | \`tool_grants.agent.effective\` | Read one agent's effective capability grants as a projection of the signed Charter manifest clamped by the tenant ceiling. Each grant carries provenance: \`grant_source\` (\`charter\` when the selected access comes from the signed manifest, else \`null\`) and \`ceiling_source\` (\`tenant_policy\`). This is the same computation the seat's Tools tab and the activation receipt project from, so the three agree \u2014 a charter-granted capability reads as granted, never a bare \`off\`. | Tenant | Call with \`{"agent_id":"<agent-id>"}\`. |
49579
49601
  | \`rost_update_agent_capability_grants\` | \`tool_grants.agent.update\` | Compile a Charter supersession proposal for agent capability grant reductions or expansions. | Tenant | Human steward/admin only; call with \`{"agent_id":"<agent-id>","grants":[{"tool_grant_id":"<grant-id>","access_level":"read"}]}\`; active authority changes only after the signed Charter is superseded. |
49580
49602
  | \`rost_build_agent_activation_receipt\` | \`agent.activation_receipt\` | Build the current activation receipt for an agent: capabilities, connection metadata, digest, budget, and always-human boundary. | Seat or tenant-admin | Call with \`{"agent_id":"<agent-id>"}\`; rebuild after Charter, connection, lane, schedule, or grant changes. |
49581
49603
  | \`rost_sign_agent_activation_receipt\` | \`agent.activation_sign\` | Human steward/admin sign-off for the exact activation receipt digest. | Tenant | Human-gated; call with \`{"agent_id":"<agent-id>","expected_scope_digest":"sha256:...","budget_cents":2500}\`. |
@@ -56032,6 +56054,20 @@ function forgeBuildUnsupportedReason(platform2) {
56032
56054
  }
56033
56055
  return `Forge build execution is unsupported on this host: no macOS seatbelt (sandbox-exec) confinement is available on '${platform2}', so this runner cannot prove filesystem/egress isolation for an untrusted build turn. The server will not offer Forge-phase work to this runner \u2014 unless its tenant is on the narrow, operator-established trust allowlist (FORGE_SANDBOX_TRUSTED_TENANT_IDS) \u2014 until real Linux confinement (namespaces/Landlock, tracked as a DER-1343 follow-up) ships.`;
56034
56056
  }
56057
+ function sandboxRequiredTurnRefusal(input) {
56058
+ if (input.spec.kind === "seatbelt") {
56059
+ return null;
56060
+ }
56061
+ if (input.mode === "off") {
56062
+ return null;
56063
+ }
56064
+ const postureLabel = input.mode === "strict" ? "strict" : "guard";
56065
+ const override = "Set RUNNER_SANDBOX=off only on a trusted, founder-authorized host to override.";
56066
+ if (input.platform !== "darwin") {
56067
+ return `Refusing to run this turn unconfined: sandbox mode is '${postureLabel}', but macOS seatbelt confinement does not exist on this host ('${input.platform}') \u2014 seatbelt is macOS-only, and Linux confinement is a DER-1343 follow-up. The runner refuses rather than running an attacker-influenceable build turn unconfined. ${override}`;
56068
+ }
56069
+ return `Refusing to run this turn unconfined: sandbox mode is '${postureLabel}', but sandbox-exec is unavailable on this macOS host, so filesystem/egress confinement cannot be applied (${input.spec.reason}). The runner refuses rather than silently degrading to no sandbox. ${override}`;
56070
+ }
56035
56071
  function wrapCommandWithSandbox(spec, command, args, profilePath) {
56036
56072
  if (spec.kind === "none" || profilePath === null) {
56037
56073
  return { command, args, profilePath: null };
@@ -59005,6 +59041,17 @@ async function spawnRunnerTurn(ctx, workOrder, runtime, kind) {
59005
59041
  if (execution?.profile === "forge_merge") {
59006
59042
  return runForgeMergeTurn(ctx, workOrder, execution, runtime);
59007
59043
  }
59044
+ const requiresSandbox = Boolean(execution?.needs_repo) || execution?.local_tools === "workspace_write";
59045
+ if (requiresSandbox) {
59046
+ const refusal = sandboxRequiredTurnRefusal({
59047
+ mode: ctx.config.sandboxMode,
59048
+ platform: process.platform,
59049
+ spec: ctx.config.sandbox
59050
+ });
59051
+ if (refusal) {
59052
+ return { ok: false, summary: refusal };
59053
+ }
59054
+ }
59008
59055
  let forgePrep = null;
59009
59056
  if (execution?.needs_repo) {
59010
59057
  const prepared = await prepareForgeTurn(ctx, workOrder, execution);
@@ -59206,6 +59253,11 @@ async function resolveMergeConflictTurn(ctx, input) {
59206
59253
  ],
59207
59254
  allowNetwork: ctx.config.sandboxAllowNetwork
59208
59255
  });
59256
+ const sandboxRefusal = sandboxRequiredTurnRefusal({ mode: ctx.config.sandboxMode, platform: process.platform, spec: sandbox });
59257
+ if (sandboxRefusal) {
59258
+ await removeWorkspace(workspace).catch(() => void 0);
59259
+ return { pushed: false, result: { ok: false, summary: sandboxRefusal.slice(0, MERGE_CONFLICT_SUMMARY_MAX) } };
59260
+ }
59209
59261
  const modelResult = await spawnMergeConflictModel(ctx, {
59210
59262
  workOrder: input.workOrder,
59211
59263
  execution: input.execution,