@rosthq/cli 0.7.79 → 0.7.80

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
@@ -44234,6 +44234,11 @@ var READ_SAFE_METHODS = /* @__PURE__ */ new Set(["GET", "HEAD", "OPTIONS"]);
44234
44234
  var brokerScopeTierSchema = external_exports.enum(["read", "write"]);
44235
44235
  var brokerInjectionModeSchema = external_exports.enum(["header_bearer", "header", "query"]);
44236
44236
  var brokerInjectionNameSchema = external_exports.string().min(1).max(100).regex(/^[A-Za-z0-9._-]+$/, "injection_name may contain only letters, digits, . _ -");
44237
+ var brokerInjectionPrefixSchema = external_exports.string().min(1).max(32).refine((value) => ![...value].some((ch) => ch.charCodeAt(0) < 32 || ch.charCodeAt(0) === 127), {
44238
+ message: "injection_prefix must not contain control characters"
44239
+ }).refine((value) => !hasSecretShapedValue(value), {
44240
+ message: 'injection_prefix must be config (e.g. "Token "), never raw secret material'
44241
+ });
44237
44242
  var brokerAllowedMethodsSchema = external_exports.array(brokerHttpMethodSchema).min(1, "at least one allowed method is required").max(7).refine((methods) => new Set(methods).size === methods.length, { message: "allowed_methods must not contain duplicates" });
44238
44243
  var brokerGrantStatusSchema = external_exports.enum(["active", "revoked"]);
44239
44244
  function refineGrantShape(value, ctx) {
@@ -44279,6 +44284,9 @@ var secretGrantGrantInputSchema = external_exports.object({
44279
44284
  scope_tier: brokerScopeTierSchema,
44280
44285
  injection_mode: brokerInjectionModeSchema.default("header_bearer"),
44281
44286
  injection_name: brokerInjectionNameSchema.optional(),
44287
+ // DER-1785: prepended to the secret for header/query grants; invalid for
44288
+ // header_bearer (whose `Bearer ` prefix is implicit — see the refine below).
44289
+ injection_prefix: brokerInjectionPrefixSchema.optional(),
44282
44290
  // ISO-8601; absent = no expiry.
44283
44291
  expires_at: external_exports.string().datetime({ offset: true }).optional()
44284
44292
  }).strict().superRefine((value, ctx) => {
@@ -44291,6 +44299,13 @@ var secretGrantGrantInputSchema = external_exports.object({
44291
44299
  message: "provide exactly one of vault_ref or credential_id"
44292
44300
  });
44293
44301
  }
44302
+ if (value.injection_mode === "header_bearer" && value.injection_prefix !== void 0) {
44303
+ ctx.addIssue({
44304
+ code: "custom",
44305
+ path: ["injection_prefix"],
44306
+ message: "injection_prefix is not valid for header_bearer mode (its Bearer prefix is implicit)"
44307
+ });
44308
+ }
44294
44309
  });
44295
44310
  var secretGrantGrantOutputSchema = external_exports.object({
44296
44311
  grant_id: uuid10,
@@ -44317,6 +44332,7 @@ var secretGrantSummarySchema = external_exports.object({
44317
44332
  scope_tier: brokerScopeTierSchema,
44318
44333
  injection_mode: brokerInjectionModeSchema,
44319
44334
  injection_name: external_exports.string().nullable(),
44335
+ injection_prefix: external_exports.string().nullable(),
44320
44336
  status: brokerGrantStatusSchema,
44321
44337
  granted_by_user_id: uuid10,
44322
44338
  granted_at: external_exports.string(),
@@ -47441,7 +47457,7 @@ Use the lower-level commands after health names a finding: \`agent.get_run\` for
47441
47457
  order: 46,
47442
47458
  title: "Tool access and vault",
47443
47459
  summary: "How to give agents access to tools without exposing raw credentials or expanding authority by accident.",
47444
- version: "2026-07-13.1",
47460
+ version: "2026-07-14.1",
47445
47461
  public: true,
47446
47462
  audiences: ["human", "cli", "mcp", "in_app_agent"],
47447
47463
  stages: ["staffing"],
@@ -47497,6 +47513,8 @@ The native Gmail handlers run inside the same broker boundary as the REST and Sl
47497
47513
 
47498
47514
  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.
47499
47515
 
47516
+ 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.
47517
+
47500
47518
  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.
47501
47519
 
47502
47520
  \`integration.connect_rest\` creates or rotates the supported Baserow REST integration through the credential flow. It stores the token in the vault, persists only endpoint/account metadata plus a tenant-scoped integration row, marks the adapter as \`rest\`, and returns no vault ref or secret. Because the input includes a raw secret, generated CLI argv refuses the command and it is deliberately not exposed as an agent-callable MCP tool; run it from Settings or the command API credential flow instead of shell arguments.
@@ -47587,7 +47605,7 @@ External connectors are being rolled out provider by provider, conservatively (r
47587
47605
  order: 48,
47588
47606
  title: "CLI and MCP installation guide",
47589
47607
  summary: "Install the public CLI, register remote token-backed MCP clients, and find the full command and tool catalog.",
47590
- version: "2026-07-13.8",
47608
+ version: "2026-07-14.1",
47591
47609
  public: true,
47592
47610
  audiences: ["human", "cli", "mcp", "in_app_agent"],
47593
47611
  stages: ["company_setup", "staffing"],
@@ -48380,11 +48398,11 @@ Preview deployment creation is a governed command. \`software_factory.vercel.dep
48380
48398
 
48381
48399
  #### Secret broker grants (tenant-level)
48382
48400
 
48383
- Generalized brokered-secret egress beyond Forge (DER-1738). A human grants an agent seat a scoped secret the \`secret.broker\` egress tool and the \`baserow.read\`/\`baserow.write\` tools (DER-1739) resolve server-side; Postgres stores only a vault-ref pointer, never secret material. A seat agent asks for and lists its own grants through the seat-scoped \`secret_grant.request\` / \`secret_grant.list\` tools (in Seat-scoped operating tools below); a human grants and revokes here. To grant, pass \`credential_id\` (from \`credential.list\`, DER-1777) instead of a raw \`vault_ref\` \u2014 the command resolves the ref server-side so no product flow ever exposes it. Baserow authenticates with an \`Authorization: Token <key>\` header, so a Baserow grant uses \`injection_mode: "header"\`, \`injection_name: "Authorization"\`, and stores the full \`Token <key>\` string as its vault secret.
48401
+ Generalized brokered-secret egress beyond Forge (DER-1738). A human grants an agent seat a scoped secret the \`secret.broker\` egress tool and the \`baserow.read\`/\`baserow.write\` tools (DER-1739) resolve server-side; Postgres stores only a vault-ref pointer, never secret material. A seat agent asks for and lists its own grants through the seat-scoped \`secret_grant.request\` / \`secret_grant.list\` tools (in Seat-scoped operating tools below); a human grants and revokes here. To grant, pass \`credential_id\` (from \`credential.list\`, DER-1777) instead of a raw \`vault_ref\` \u2014 the command resolves the ref server-side so no product flow ever exposes it. Baserow authenticates with an \`Authorization: Token <key>\` header, so a Baserow grant uses \`injection_mode: "header"\`, \`injection_name: "Authorization"\`, and \`injection_prefix: "Token "\` (DER-1785) \u2014 the broker prepends the prefix to the raw key at render time, so the credential's vault secret stays the RAW key and granting it by \`credential_id\` renders \`Authorization: Token <key>\` correctly. (\`injection_prefix\` is non-secret config, capped at 32 chars, rejects control characters, and is invalid for \`injection_mode: "header_bearer"\`, whose \`Bearer \` prefix is implicit.) Older grants that instead stored the full \`Token <key>\` string as the vault secret with no prefix still work \u2014 the broker injects that verbatim.
48384
48402
 
48385
48403
  | Tool | Command | What it does | Scope | Notes |
48386
48404
  |---|---|---|---|---|
48387
- | \`rost_grant_a_brokered_secret\` | \`secret_grant.grant\` | A human grants a seat scoped brokered-secret access. Supply exactly one of credential_id (from credential.list / credential.ingress \u2014 resolved to its vault ref server-side, so a human never handles a ref) or vault_ref directly. Postgres stores only the pointer, never secret material. Owner-only and human-gated; the secret.broker and baserow.* tools resolve it server-side and the secret never enters agent context. | Tenant-admin | Call with {"seat_id":"<seat-id>","grant_key":"baserow","provider":"baserow","allowed_host":"baserow.example.com","allowed_path_prefix":"/api/database/rows/","allowed_methods":["GET","POST","PATCH"],"scope_tier":"write","injection_mode":"header","injection_name":"Authorization","credential_id":"<credential-id>"} (or "vault_ref":"infisical://prod/baserow-token" instead of credential_id). |
48405
+ | \`rost_grant_a_brokered_secret\` | \`secret_grant.grant\` | A human grants a seat scoped brokered-secret access. Supply exactly one of credential_id (from credential.list / credential.ingress \u2014 resolved to its vault ref server-side, so a human never handles a ref) or vault_ref directly. Postgres stores only the pointer, never secret material. Owner-only and human-gated; the secret.broker and baserow.* tools resolve it server-side and the secret never enters agent context. | Tenant-admin | Call with {"seat_id":"<seat-id>","grant_key":"baserow","provider":"baserow","allowed_host":"baserow.example.com","allowed_path_prefix":"/api/database/rows/","allowed_methods":["GET","POST","PATCH"],"scope_tier":"write","injection_mode":"header","injection_name":"Authorization","injection_prefix":"Token ","credential_id":"<credential-id>"} (or "vault_ref":"infisical://prod/baserow-token" instead of credential_id). injection_prefix is optional; use it (DER-1785) when the credential stores a RAW key so the broker renders "Token <key>". |
48388
48406
  | \`rost_revoke_a_brokered_secret_grant\` | \`secret_grant.revoke\` | Revoke a brokered secret grant (teardown \u2014 cut a compromised or over-scoped seat egress immediately; the next broker call fails closed). Owner-only and human-gated. | Tenant-admin | Call with {"grant_id":"<grant-id>"}; non-interactive callers receive a confirmation handoff. |
48389
48407
  | \`rost_list_stored_credentials\` | \`credential.list\` | List the tenant's stored credentials as metadata only \u2014 credential id, provider, label, seat, status, and created/rotated/revoked dates. NEVER returns the vault ref or any secret. Use the returned credential_id with secret_grant.grant. | Tenant-admin | Call with {}. |
48390
48408
 
@@ -49240,7 +49258,7 @@ Keep agent scope tight at first. Approve more autonomy only after evidence. Use
49240
49258
  order: 71,
49241
49259
  title: "Confirmations and human gates guide",
49242
49260
  summary: "How {{brand}} routes authority-changing work through human confirmation, and why agents never approve their own requests.",
49243
- version: "2026-07-13.1",
49261
+ version: "2026-07-14.1",
49244
49262
  public: true,
49245
49263
  audiences: ["human", "cli", "mcp", "in_app_agent"],
49246
49264
  stages: ["graph_design", "charter_design", "staffing", "operating_rhythm"],
@@ -49288,7 +49306,7 @@ Approval replays are validated again before execution. If the stored confirmatio
49288
49306
 
49289
49307
  ## The approvals queue
49290
49308
 
49291
- The \`/approvals\` page is one place a human clears every pending decision across the company. It unions still-pending confirmations with open steward escalations into a single queue, each item shown with its risk, the source seat, and redacted arguments \u2014 secret material is never displayed. You see only items for seats you have authority over: an owner sees all of them; a member sees confirmations for the seats they occupy and escalations routed to their steward chain, and nothing else. Approve and reject route through the same \`confirmation.approve\` / \`confirmation.reject\` and escalation decision commands the CLI and per-seat surfaces use, so the audit trail and the agents-recommend-humans-decide rule are identical wherever you act.
49309
+ The \`/approvals\` page is one place a human clears every pending decision across the company. It unions still-pending confirmations with open steward escalations into a single queue, each item shown with its risk, the source seat, and redacted arguments \u2014 secret material is never displayed. You see only items for seats you have authority over: an owner sees all of them; a member sees confirmations for the seats they occupy and escalations routed to their steward chain, and nothing else. Approve and reject route through the same \`confirmation.approve\` / \`confirmation.reject\` and escalation decision commands the CLI and per-seat surfaces use, so the audit trail and the agents-recommend-humans-decide rule are identical wherever you act. The queue also unions pending Forge software-credential requests (owner-scoped, read-only, deep-linking to \`/forge\`) \u2014 it surfaces the ask and links to the vault-backed fulfillment flow, never collecting the secret itself. A confirmation that fails on approval shows the actual execution error inline as a \`failed\` card instead of a dead generic banner, and its Retry re-runs \`confirmation.approve\` against current state; re-minting the same request supersedes the older card instead of leaving a duplicate behind.
49292
49310
 
49293
49311
  ## The rule for agents
49294
49312
 
@@ -49412,7 +49430,7 @@ Do not claim that a live charge happened unless Stripe test/live evidence proves
49412
49430
  order: 72,
49413
49431
  title: "Settings guide",
49414
49432
  summary: "How to use Settings as the control plane for company access, channels, providers, tokens, and operating defaults.",
49415
- version: "2026-07-11.1",
49433
+ version: "2026-07-14.1",
49416
49434
  public: true,
49417
49435
  audiences: ["human", "cli", "mcp", "in_app_agent"],
49418
49436
  stages: ["company_setup", "staffing"],
@@ -49435,7 +49453,7 @@ Start with members and invites, then provider and channel connections, then MCP
49435
49453
 
49436
49454
  ## Navigating Settings
49437
49455
 
49438
- Settings is reached from the footer gear in the left sidebar (the nav collapse moved it out of the primary item list). It is a left-rail master\u2013detail layout: a grouped rail (General, Team & Access, Billing, AI & Agents, Connections, Advanced) selects one section at a time, shown in the detail pane. The active section is a URL search param, so \`/settings?section=<id>\` is linkable and survives a refresh. The Connections section is the workspace-level provider surface: Google, Slack, QuickBooks, local runners, seat-scoped agent tokens, and stored secrets appear as provider cards with status, used-for chips, actions, and the shared Access language (**Off / Read / Draft / Act with approval**). Detailed management forms for tokens, channels, runners, provider links, and stored vault entries remain reachable from those cards.
49456
+ Settings is reached from the footer gear in the left sidebar (the nav collapse moved it out of the primary item list). It is a left-rail master\u2013detail layout: a grouped rail (General, Team & Access, Billing, AI & Agents, Connections, Advanced) selects one section at a time, shown in the detail pane. The active section is a URL search param, so \`/settings?section=<id>\` is linkable and survives a refresh. The Connections section is the workspace-level provider surface: Google, Slack, QuickBooks, local runners, seat-scoped agent tokens, and stored secrets appear as provider cards with status, used-for chips, actions, and the shared Access language (**Off / Read / Draft / Act with approval**). Any other \`integrations\` row \u2014 e.g. a Baserow REST/custom connection created through \`integration.connect_rest\` \u2014 renders as a generic connection card alongside the stock providers, so a non-stock connector is never invisible on this page. Detailed management forms for tokens, channels, runners, provider links, and stored vault entries remain reachable from those cards.
49439
49457
 
49440
49458
  Section state is fully server-side: every in-app link, redirect, and save uses \`?section=<id>\`, never a \`#anchor\` \u2014 there is no client-side hash shim to desync from. Documented shortcut pages redirect straight to the right section instead of a dead end: \`/settings/integrations\` and \`/readiness\` redirect to \`?section=connections\` (connector readiness lives inside the Connections overview, not on a standalone page), \`/settings/members\` redirects to \`?section=members\`, \`/settings/policy\` redirects to \`?section=guardrails\`, and MCP/CLI access tokens live in the Agent access tokens section (not a separate \`/mcp\` page \u2014 \`/mcp\` is the MCP protocol endpoint itself, not a browsable settings screen). The Advanced group links out to \`/migration/ninety\`, the one settings-adjacent page with no home in the grouped rail. Every settings form carries the section it lives in, so saving a change redirects back to that same section with no flash, instead of returning to the top.
49441
49459
 
@@ -49574,7 +49592,7 @@ When a user asks to add a person, clarify whether they mean app access, seat occ
49574
49592
  order: 74,
49575
49593
  title: "Notifications guide",
49576
49594
  summary: "How {{brand}} should notify humans about decisions, escalations, stale work, and agent boundaries.",
49577
- version: "2026-07-09.1",
49595
+ version: "2026-07-14.1",
49578
49596
  public: true,
49579
49597
  audiences: ["human", "cli", "mcp", "in_app_agent"],
49580
49598
  stages: ["operating_rhythm"],
@@ -49605,6 +49623,10 @@ Notifications should move decisions to the right human without turning {{brand}}
49605
49623
 
49606
49624
  \`{{cli}} notification errors --limit 10\` / \`notification.list_errors\` / \`rost_list_notification_errors\` returns recent failed deliveries. When a failed notification links to a product error, it includes \`error_log_id\`, \`source\`, and any linked \`seat_id\` / \`run_id\`; \`source=run\` means the notification is tied to an agent run and can be followed with \`agent.get_run\` for the transcript reference and run errors.
49607
49625
 
49626
+ ## Telegram channel
49627
+
49628
+ Telegram is an opt-in delivery channel that sits alongside email. A workspace admin connects a Telegram bot once (create it with @BotFather, paste the token in Settings \u2192 Notifications; the token is stored in the vault as a credential reference, never in env or logs). Each person then opts in from the same page: {{brand}} shows a one-time deep link, you start the bot, and {{brand}} verifies your chat. Once verified, held approvals, escalations, briefs, and the daily digest are delivered to Telegram, with email as the fallback. Messages are bounded and secret-free and link back to the relevant {{brand}} item. Opt out any time from Settings \u2192 Notifications.
49629
+
49608
49630
  ## Keep notifications useful
49609
49631
 
49610
49632
  Every notification should include the seat, cause, evidence, and requested decision. Avoid status-only messages when no action is needed.`
@@ -51671,7 +51693,7 @@ var COMMAND_MANIFEST = [
51671
51693
  { "id": "seat.rename", "namespace": "seat", "action": "rename", "title": "Rename seat", "description": "Rename a Responsibility Graph seat.", "requiredScope": "seat", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "seat_id", "flag": "seat-id", "type": "string", "required": true }, { "name": "name", "flag": "name", "type": "string", "required": true }], "hasComplexInput": false, "help": "Seat names should describe the function and accountability clearly." },
51672
51694
  { "id": "seat.reparent", "namespace": "seat", "action": "reparent", "title": "Reparent seat", "description": "Move a Responsibility Graph seat under a new parent.", "requiredScope": "seat", "confirmation": "human_required", "exposeOverMcp": true, "fields": [{ "name": "seat_id", "flag": "seat-id", "type": "string", "required": true }, { "name": "new_parent_seat_id", "flag": "new-parent-seat-id", "type": "string", "required": true }], "hasComplexInput": false, "help": "Reparent seats only when it clarifies accountable structure and preserves a clean graph." },
51673
51695
  { "id": "seat.set_type", "namespace": "seat", "action": "set_type", "title": "Set seat type", "description": "Set a Responsibility Graph seat type.", "requiredScope": "seat", "confirmation": "human_required", "exposeOverMcp": true, "fields": [{ "name": "seat_id", "flag": "seat-id", "type": "string", "required": true }, { "name": "seat_type", "flag": "seat-type", "type": "enum", "required": true, "enumValues": ["human", "agent", "hybrid"] }], "hasComplexInput": false, "help": "Seat type should follow the work, risk, measurable, and stewardship model." },
51674
- { "id": "secret_grant.grant", "namespace": "secret_grant", "action": "grant", "title": "Grant a brokered secret", "description": "A human grants a seat scoped access to a brokered secret by CREDENTIAL ID (from credential.list / credential.ingress \u2014 resolved to its vault ref server-side) or by VAULT REF directly (exactly one). Postgres stores only the pointer \u2014 never secret material (invariant #5). Owner-only, human-gated. The secret.broker/baserow.* tools resolve this grant server-side; the secret never enters agent context.", "requiredScope": "tenant_admin", "confirmation": "human_required", "exposeOverMcp": true, "fields": [{ "name": "seat_id", "flag": "seat-id", "type": "string", "required": true }, { "name": "grant_key", "flag": "grant-key", "type": "string", "required": true }, { "name": "vault_ref", "flag": "vault-ref", "type": "string", "required": false }, { "name": "credential_id", "flag": "credential-id", "type": "string", "required": false }, { "name": "provider", "flag": "provider", "type": "string", "required": true }, { "name": "allowed_host", "flag": "allowed-host", "type": "string", "required": true }, { "name": "allowed_path_prefix", "flag": "allowed-path-prefix", "type": "string", "required": false }, { "name": "allowed_methods", "flag": "allowed-methods", "type": "array", "required": true, "itemType": "string" }, { "name": "scope_tier", "flag": "scope-tier", "type": "enum", "required": true, "enumValues": ["read", "write"] }, { "name": "injection_mode", "flag": "injection-mode", "type": "enum", "required": false, "enumValues": ["header_bearer", "header", "query"] }, { "name": "injection_name", "flag": "injection-name", "type": "string", "required": false }, { "name": "expires_at", "flag": "expires-at", "type": "string", "required": false }], "hasComplexInput": false, "help": "A human grants a seat a scoped brokered secret by vault ref (host + path prefix + methods + injection). Postgres stores only the pointer, never secret material. Owner-only and human-gated; the secret.broker/baserow.* tools resolve it server-side." },
51696
+ { "id": "secret_grant.grant", "namespace": "secret_grant", "action": "grant", "title": "Grant a brokered secret", "description": "A human grants a seat scoped access to a brokered secret by CREDENTIAL ID (from credential.list / credential.ingress \u2014 resolved to its vault ref server-side) or by VAULT REF directly (exactly one). Postgres stores only the pointer \u2014 never secret material (invariant #5). Owner-only, human-gated. The secret.broker/baserow.* tools resolve this grant server-side; the secret never enters agent context.", "requiredScope": "tenant_admin", "confirmation": "human_required", "exposeOverMcp": true, "fields": [{ "name": "seat_id", "flag": "seat-id", "type": "string", "required": true }, { "name": "grant_key", "flag": "grant-key", "type": "string", "required": true }, { "name": "vault_ref", "flag": "vault-ref", "type": "string", "required": false }, { "name": "credential_id", "flag": "credential-id", "type": "string", "required": false }, { "name": "provider", "flag": "provider", "type": "string", "required": true }, { "name": "allowed_host", "flag": "allowed-host", "type": "string", "required": true }, { "name": "allowed_path_prefix", "flag": "allowed-path-prefix", "type": "string", "required": false }, { "name": "allowed_methods", "flag": "allowed-methods", "type": "array", "required": true, "itemType": "string" }, { "name": "scope_tier", "flag": "scope-tier", "type": "enum", "required": true, "enumValues": ["read", "write"] }, { "name": "injection_mode", "flag": "injection-mode", "type": "enum", "required": false, "enumValues": ["header_bearer", "header", "query"] }, { "name": "injection_name", "flag": "injection-name", "type": "string", "required": false }, { "name": "injection_prefix", "flag": "injection-prefix", "type": "string", "required": false }, { "name": "expires_at", "flag": "expires-at", "type": "string", "required": false }], "hasComplexInput": false, "help": "A human grants a seat a scoped brokered secret by vault ref (host + path prefix + methods + injection). Postgres stores only the pointer, never secret material. Owner-only and human-gated; the secret.broker/baserow.* tools resolve it server-side." },
51675
51697
  { "id": "secret_grant.list", "namespace": "secret_grant", "action": "list", "title": "List brokered secret grants", "description": "List brokered secret grants for the tenant (or one seat). Returns the egress allowlist metadata only (host, path prefix, methods, scope, status) \u2014 never the vault ref or any secret. An agent sees only its own seat's grants.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "seat_id", "flag": "seat-id", "type": "string", "required": false }, { "name": "include_revoked", "flag": "include-revoked", "type": "boolean", "required": false }], "hasComplexInput": false, "help": "List brokered secret grants for the tenant (or one seat). Returns the egress allowlist metadata only \u2014 host, path prefix, methods, scope, status \u2014 never the vault ref or any secret." },
51676
51698
  { "id": "secret_grant.request", "namespace": "secret_grant", "action": "request", "title": "Request a brokered secret grant", "description": "An agent or user REQUESTS a scoped brokered-secret grant by naming the egress it needs (grant key, host, path prefix, methods, scope). No secret and no vault ref are ever accepted (invariant #5) \u2014 this only records a durable ask for a human to grant.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "seat_id", "flag": "seat-id", "type": "string", "required": true }, { "name": "grant_key", "flag": "grant-key", "type": "string", "required": true }, { "name": "provider", "flag": "provider", "type": "string", "required": true }, { "name": "allowed_host", "flag": "allowed-host", "type": "string", "required": true }, { "name": "allowed_path_prefix", "flag": "allowed-path-prefix", "type": "string", "required": false }, { "name": "allowed_methods", "flag": "allowed-methods", "type": "array", "required": true, "itemType": "string" }, { "name": "scope_tier", "flag": "scope-tier", "type": "enum", "required": true, "enumValues": ["read", "write"] }, { "name": "reason", "flag": "reason", "type": "string", "required": false }], "hasComplexInput": false, "help": "An agent or user requests a brokered-secret egress grant by naming the host, path prefix, methods, and scope it needs. Draft-and-confirm: no secret or vault ref is accepted; a human grants it." },
51677
51699
  { "id": "secret_grant.revoke", "namespace": "secret_grant", "action": "revoke", "title": "Revoke a brokered secret grant", "description": "Revoke a brokered secret grant \u2014 a compromised or over-scoped seat's egress access can be cut immediately; the next broker call resolves no grant and fails closed. Owner-only, human-gated.", "requiredScope": "tenant_admin", "confirmation": "human_required", "exposeOverMcp": true, "fields": [{ "name": "grant_id", "flag": "grant-id", "type": "string", "required": true }], "hasComplexInput": false, "help": "Revoke a brokered secret grant (teardown \u2014 cut a compromised or over-scoped seat's egress immediately; the next broker call fails closed). Owner-only and human-gated." },