@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 +56 -4
- package/dist/index.js.map +2 -2
- package/dist/runner-sandbox.d.ts +50 -0
- package/dist/runner-sandbox.d.ts.map +1 -1
- package/dist/runner-serve.d.ts.map +1 -1
- package/package.json +1 -1
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:
|
|
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-
|
|
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-
|
|
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
|
|
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,
|