Bypass mode (owner opt-in, default off): storebound settings bypass on|off|status and a one-time question in init; MCP owner_step (owner-only commands, dry run first), owner-only api operations with --yes --confirm, console plans may press buttons.final; every action logged to .storebound/owner-actions.log; docs/bypass.md, agent rules, tests
This commit is contained in:
parent
2598c4953a
commit
9bd17c401d
21 changed files with 218 additions and 13 deletions
|
|
@ -2,6 +2,7 @@
|
|||
// Rules: one tool per CLI command; every tool that writes anything has `dry_run` defaulting to true; nothing that
|
||||
// submits for review, releases to the public, resumes / completes a rollout, cancels a submission or deletes is
|
||||
// exposed. Those stay terminal commands the owner runs (they also ask for confirmation there).
|
||||
import { OWNER_COMMANDS } from './lib/bypass';
|
||||
|
||||
export interface JsonSchema { type: string; description?: string; enum?: (string | number)[]; default?: unknown; items?: JsonSchema; minimum?: number; maximum?: number; pattern?: string; additionalProperties?: JsonSchema | boolean }
|
||||
|
||||
|
|
@ -479,8 +480,17 @@ export const OUTPUT_SCHEMA = {
|
|||
required: ['exitCode', 'command', 'output'],
|
||||
} as const;
|
||||
|
||||
export function listTools(): Record<string, unknown>[] {
|
||||
return TOOLS.map(t => ({
|
||||
/** Bypass mode only (storebound settings bypass on): one owner-only command, dry run by default. */
|
||||
export const OWNER_STEP: ToolDef = {
|
||||
name: 'owner_step', title: 'Owner step (bypass mode)', write: true, destructive: true, network: true,
|
||||
description: `Bypass mode is on: run one owner-only command yourself (${OWNER_COMMANDS.join(', ')}). Pass the CLI words as command and the rest as args (ids, build numbers, --track, --percent ...). Always call it with dry_run: true first and read the plan; then dry_run: false runs it with --yes. Every call is logged to .storebound/owner-actions.log. Legal agreements, passwords and 2FA stay with the owner.`,
|
||||
command: [], props: { command: { type: 'string', enum: [...OWNER_COMMANDS], description: 'The owner-only command' }, args: { type: 'array', items: { type: 'string' }, description: 'Its arguments and options' } },
|
||||
required: ['command'],
|
||||
args: i => [...String(i.command).split(' '), ...(Array.isArray(i.args) ? i.args.map(String) : [])],
|
||||
};
|
||||
|
||||
export function listTools(bypass = false): Record<string, unknown>[] {
|
||||
return [...TOOLS, ...(bypass ? [OWNER_STEP] : [])].map(t => ({
|
||||
name: t.name, title: t.title, description: t.description,
|
||||
inputSchema: inputSchema(t), outputSchema: OUTPUT_SCHEMA,
|
||||
annotations: { title: t.title, readOnlyHint: !t.write, destructiveHint: t.write ? !!t.destructive : false, idempotentHint: !!t.idempotent || !t.write, openWorldHint: t.network },
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue