Add --dry-run flag to server

When active, action invocations are logged (action name, caller, params)
but no handler is executed. Applies to both auto-accept and approved queue
entries. Startup message confirms the mode is active.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-17 22:41:09 +00:00
parent 19e57f4e3e
commit 9668bae220
2 changed files with 20 additions and 5 deletions

View File

@@ -66,6 +66,7 @@ Server flags:
| `--secrets <path>` | — | Path to secrets file (required) | | `--secrets <path>` | — | Path to secrets file (required) |
| `--bind <addr>` | `CONDUIT_BIND` | Address to bind to (default `127.0.0.1`) | | `--bind <addr>` | `CONDUIT_BIND` | Address to bind to (default `127.0.0.1`) |
| `--mail-perms <path>` | `CONDUIT_MAIL_PERMS` | File to persist mail permissions (optional; in-memory only if omitted) | | `--mail-perms <path>` | `CONDUIT_MAIL_PERMS` | File to persist mail permissions (optional; in-memory only if omitted) |
| `--dry-run` | — | Log all action invocations but do not execute them |
Server environment variables: Server environment variables:
| Variable | Default | Description | | Variable | Default | Description |

View File

@@ -15,9 +15,10 @@ function ts() {
return new Date().toLocaleTimeString(); return new Date().toLocaleTimeString();
} }
const PORT = process.env.CONDUIT_PORT || 3015; const PORT = process.env.CONDUIT_PORT || 3015;
const BIND = get_arg(process.argv, '--bind') || process.env.CONDUIT_BIND || '127.0.0.1'; const BIND = get_arg(process.argv, '--bind') || process.env.CONDUIT_BIND || '127.0.0.1';
const VERBOSE = process.argv.includes('--verbose'); const VERBOSE = process.argv.includes('--verbose');
const DRY_RUN = process.argv.includes('--dry-run');
const secrets_path = get_arg(process.argv, '--secrets'); const secrets_path = get_arg(process.argv, '--secrets');
const mail_perms_path = get_arg(process.argv, '--mail-perms') || process.env.CONDUIT_MAIL_PERMS || null; const mail_perms_path = get_arg(process.argv, '--mail-perms') || process.env.CONDUIT_MAIL_PERMS || null;
@@ -61,6 +62,16 @@ app.use((req, _res, next) => {
next(); next();
}); });
async function run_action(def, action, params, ctx) {
if (DRY_RUN) {
console.log(`[${ts()}] [DRY-RUN] action: ${action}`);
console.log(`[${ts()}] [DRY-RUN] caller: ${ctx.caller}`);
console.log(`[${ts()}] [DRY-RUN] params: ${JSON.stringify(params, null, 2)}`);
return { dry_run: true, action, params };
}
return def.handler(params, ctx);
}
function validate_params(action_def, params) { function validate_params(action_def, params) {
const errors = []; const errors = [];
for (const p of action_def.params) { for (const p of action_def.params) {
@@ -97,7 +108,7 @@ app.post('/action', async (req, res) => {
if (def.policy === 'auto-accept') { if (def.policy === 'auto-accept') {
try { try {
const result = await def.handler(params, ctx); const result = await run_action(def, action, params, ctx);
return res.json({ status: 'accepted', result }); return res.json({ status: 'accepted', result });
} catch (err) { } catch (err) {
return res.status(500).json({ status: 'error', error: err.message }); return res.status(500).json({ status: 'error', error: err.message });
@@ -134,7 +145,7 @@ app.post('/queue/:id/approve', async (req, res) => {
const ctx = { caller: entry.submitted_by, users, mail_perm_store, mailer_send }; const ctx = { caller: entry.submitted_by, users, mail_perm_store, mailer_send };
const def = actions[entry.action]; const def = actions[entry.action];
try { try {
const result = await def.handler(entry.params, ctx); const result = await run_action(def, entry.action, entry.params, ctx);
res.json({ status: 'approved', result }); res.json({ status: 'approved', result });
} catch (err) { } catch (err) {
res.status(500).json({ status: 'error', error: err.message }); res.status(500).json({ status: 'error', error: err.message });
@@ -162,4 +173,7 @@ app.post('/queue/:id/deny', (req, res) => {
app.listen(PORT, BIND, () => { app.listen(PORT, BIND, () => {
console.log(`claude-code-conduit server running on ${BIND}:${PORT}`); console.log(`claude-code-conduit server running on ${BIND}:${PORT}`);
console.log(`Workspace root: ${process.env.CONDUIT_ROOT || '/workspace'}`); console.log(`Workspace root: ${process.env.CONDUIT_ROOT || '/workspace'}`);
if (DRY_RUN) {
console.log('DRY-RUN mode enabled — actions will be logged but not executed');
}
}); });