Copyright - License Notice -------------------------- "AIShell-Gate" Copyright (c) 2026 AIShell Labs LLC Winston-Salem NC. USA. All Rights Reserved. Author: Sean T. Gilley Use of this Software requires a valid license obtained from AIShell Labs LLC. This notice summarizes the license terms. The controlling agreement is the license document issued upon payment. In the event of any conflict between this notice and that document, the issued license document governs. For license information and purchase: www.aishell.org/aishellgate AIShell Labs LLC — we are an integrity company. EVALUATION AND BETA COPIES Unlicensed evaluation and beta copies of this Software expire 30 days from the date of download. After expiration, continued use requires a purchased license. No evaluation or beta copy may be used in a production environment. FIXED-HOST LICENSE A per-host license covers installation and use on a single, fixed physical or virtual machine, identified at the time of purchase. This license is perpetual for that host. Use on any additional host requires a separate license. CLOUD AND EPHEMERAL DEPLOYMENTS For cloud, containerized, or other ephemeral deployments where the host identity is not fixed, licensing is based on the average number of concurrently running instances. See cloud-licensing.txt included with this distribution. SOURCE CODE ACCESS Source code is made available exclusively to licensees who have executed a Non-Disclosure Agreement with AIShell Labs LLC, for the sole purpose of security review and audit. No other use of the source code is permitted. The source code may not be modified, redistributed, or disclosed. ALL RIGHTS RESERVED You may not redistribute, sublicense, resell, or transfer this Software or any license to any third party. You may not modify, adapt, or create derivative works. You may not remove or alter any copyright or attribution notices. NO WARRANTY THIS SOFTWARE IS PROVIDED "AS IS," WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. LIMITATION OF LIABILITY TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, AISHELL LABS LLC SHALL NOT BE LIABLE FOR ANY INDIRECT, INCIDENTAL, SPECIAL, CONSEQUENTIAL, OR PUNITIVE DAMAGES ARISING FROM USE OR INABILITY TO USE THIS SOFTWARE. aishell-gate-exec(1) ==================== NAME ---- aishell-gate-exec -- execution gateway for aishell-gate-policy (v0.35.0) SYNOPSIS -------- aishell-gate-exec [executor-flags] [policy-flags] [-- other-policy-flags] aishell-gate-exec --policy-binary ./aishell-gate-policy --plan plan.json aishell-gate-exec --policy-preset ops_safe --jail-root /work --plan plan.json echo '{"goal":"check repo","actions":[{"type":"command","cmd":"git status"}]}' \ | aishell-gate-exec --policy-binary ./aishell-gate-policy --policy-preset dev_sandbox DESCRIPTION ----------- aishell-gate-exec is the execution harness that sits between a JSON action plan (from an AI agent or operator) and the Unix system. It has no policy logic of its own. Its job is to: Interactive mode (--interactive or auto-detected when stdin is a TTY): Reads commands one at a time from /dev/tty, assesses each through the policy engine, enforces the appropriate confirmation gate, and executes allowed and confirmed commands. Full audit trail throughout. Source identity defaults to "human" unless --source is set. JSON plan mode (default when stdin is not a TTY): 1. Read a structured JSON action plan from stdin or --plan FILE. 2. Submit the plan to aishell-gate-policy for policy evaluation. 3. Display the evaluation summary to the operator. 4. Collect human confirmation for any action that requires it. 5. Execute allowed and confirmed actions via execve() with a resolved absolute binary path and a sanitised environment. 6. Write a structured audit trail of every step. aishell-gate-exec enforces a strict separation between evaluation and execution. The policy engine is a separate process invoked via fork/execve across a hard OS boundary. The executor reads only the JSON output of that process; it never parses the human-readable trace text that the engine also emits. Commands are never passed through a shell. The pre-tokenised argv[] array from the policy engine's JSON response is passed directly to execve(), eliminating the class of shell-injection vulnerabilities that arise when a command string is re-evaluated at execution time. INPUT FORMAT ------------ The input is a JSON object, read from stdin by default or from a file with --plan. The following fields are recognised: goal (required) Human-readable description of intent. Included in the audit log and displayed in the evaluation banner. Maximum 511 characters. source (not read from plan) Source identity is a deployer-set CLI flag (--source), not a plan field. Any "source" field in the input JSON is silently ignored. This prevents an AI agent from self-reporting its own trust level. See --source under OPTIONS. strategy (optional) Multi-action failure policy. Values: "fail_fast" Stop at the first action that exits non-zero. Remaining confirmed actions are skipped and logged. The first non-zero exit code is returned. Default. "best_effort" Attempt all allowed and confirmed actions regardless of prior failures. Returns the first non-zero exit code encountered (preserves root cause, not last error). actions (required) Array of action objects. Each action may be: { "type": "command", "cmd": "git status" } or a bare string shorthand: "git status" Only type "command" is currently supported. Maximum 32 actions. Example: { "goal": "inspect repository state", "source": "ai", "strategy": "fail_fast", "actions": [ { "type": "command", "cmd": "git status" }, { "type": "command", "cmd": "git diff --stat" } ] } OPTIONS ------- Executor flags: --policy-binary Path to the aishell-gate-policy binary. Resolved to an absolute path at startup via realpath(3) and verified executable before any plan is read. Must contain a '/' character — bare names are rejected to prevent PATH-based substitution. Default: ./aishell-gate-policy --interactive Activate human terminal mode. Commands are read one at a time from /dev/tty, assessed by the policy engine, confirmed through the appropriate gate, and executed. Session continues until EOF or 'quit'. Auto-detected when stdin is a TTY and --plan FILE is not given. Source identity defaults to "human" when --interactive is active and no explicit --source flag was given. Meta-commands available in interactive mode: help Show available meta-commands and confirmation level meanings. status Session statistics: commands executed vs. denied. policy Show policy engine path and source identity. quit/exit End the session cleanly. Note: aishell-confirm is not used in interactive mode. Confirmations are collected directly from /dev/tty by the executor. aishell-confirm is for remote deployments where the AI agent and operator are in separate SSH sessions. --plan Read the input JSON plan from file instead of stdin. --eval-timeout Kill the policy engine process with SIGKILL if evaluation takes longer than this many seconds. Execution fails closed on timeout. Default: 30. Set to 0 to disable. --input-timeout Fail if no input plan data arrives on stdin within this many seconds. Prevents the binary from blocking indefinitely when invoked without a piped plan (e.g. interactively at a terminal or from an AI that stalls before writing the plan). On expiry the binary emits a diagnostic to stderr and exits 5. Has no effect when --plan FILE is used, since file reads do not block. Default: 30. Set to 0 to disable. --max-response-bytes Kill the policy engine process and fail closed if its JSON response exceeds n bytes. Buffer growth is capped before the limit to prevent memory exhaustion. Default: 8388608 (8 MiB). Set to 0 to disable. --audit-log Write a structured JSON Lines audit log to file. Default: $AISHELL_EXEC_AUDIT_LOG environment variable, or /var/log/aishell/audit.log if the variable is unset. Note: this is the EXEC audit log only. It uses a different internal format from the policy engine audit log and can only be verified with --audit-verify on this binary. See AUDIT LOGGING below. If --audit-log is given explicitly, failure to open the file is fatal. If using the default path, a failure produces a warning but does not abort execution. --confirm-tty Single-session interactive use only. Read confirmation prompts from PATH instead of /dev/tty. Use this when running a single AI session on a machine you are logged into and want to redirect prompts to a specific device. Not suitable for multi-session remote deployments — use --confirm-pipe instead. When neither flag is given the default is /dev/tty, which works correctly in any session that has a controlling terminal. --confirm-lock Serialise concurrent confirmation prompts. Only one aishell-gate-exec session may be in the confirmation phase at a time; others block on an exclusive flock(2) until the current session finishes and releases the lock. The lock is released before any execve(2) call so command execution across sessions proceeds in parallel. The lock file is created automatically if it does not exist. Required when --confirm-pipe is in use and multiple AI sessions may connect simultaneously. Default path: /run/aishell-gate/confirm.lock The lock is only acquired when --confirm-lock or --confirm-pipe is explicitly set; single-session deployments using /dev/tty are not affected. --confirm-pipe Secure pipe-based operator confirmation relay for remote multi-session deployments. BASEPATH.req and BASEPATH.resp must be named FIFOs created by the aishell-confirm(1) companion tool, which owns them and runs as the operator. aishell-gate-exec writes a JSON request to BASEPATH.req containing the full command context: session_id, action index, confirm level, cmd, goal, source, risk_score, blast_radius, reason, and for typed confirmations the challenge code. aishell-confirm reads it, displays all context on the operator's own terminal, reads the operator's response, and writes it back through BASEPATH.resp. aishell-gate-exec never opens any PTY device in this path. Use with --confirm-lock for multi-session safety. Default base path: /run/aishell-gate/confirm --verbose Print internal diagnostics to stderr: envelope contents, response JSON, policy engine exit code, response byte cap, and execution path resolution. --help / -h Print a usage summary and exit. --version Print the version string and exit. Common policy engine flags (no -- required): The six policy engine flags that appear on most invocations may be given directly alongside executor flags, without a -- separator: --policy-preset Built-in policy preset: read_only, dev_sandbox, ops_safe (default), danger_zone. Forwarded to the policy engine. Presets replace the builtin layer cmd_allow and cmd_deny lists while preserving arg_rules, path_rules, and net_rules. Some presets are more permissive than the default (danger_zone); some are more restrictive (read_only). Omitting this flag uses the full builtin policy (ops_safe). Upper layers (--policy-user, --policy-project, --policy-base) can override any preset on a per-rule basis. --policy-base Base policy override file. Forwarded to the policy engine. --policy-project Project policy override file. Forwarded to the policy engine. --policy-user User policy override file. Forwarded to the policy engine. --jail-root Restrict write-like commands to this path tree. Forwarded to the policy engine. --sandbox Sandbox mode hint: none, cwd_jail, chroot, container, userns. Forwarded to the policy engine. Other policy engine flags (pass after --): Any flag not listed above that needs to reach the policy engine must appear after a -- separator. Everything after -- is forwarded verbatim. Maximum 64 total forwarded flags (including the six above). Less-common policy engine flags: --audit-log Policy engine audit log (separate from the executor audit log written by exec's --audit-log; these two logs use incompatible internal formats — never point them at the same file) --mode Session mode: auto, interactive, batch, daemon --source Taint source override See aishell-gate-policy(1) for the full list. EXECUTION MODEL --------------- Evaluation pipeline aishell-gate-exec submits the plan to the policy engine subprocess as a JSON envelope over a pipe. The subprocess receives the envelope on its stdin and writes its JSON decision report to stdout. aishell-gate-exec reads this report with a configurable deadline (--eval-timeout) and byte cap (--max-response-bytes). If either limit is exceeded, the subprocess is sent SIGKILL and execution fails closed. Three deadline layers protect against indefinite blocking throughout the pipeline: Input deadline (--input-timeout) Applied to the initial stdin read before any policy engine subprocess is spawned. If no plan data arrives within the timeout, the binary emits a diagnostic and exits 5. This prevents indefinite blocking when the binary is invoked without a piped plan — for example, at an interactive terminal, or from an AI agent that stalls before writing the action plan. Not active when --plan FILE is used. Envelope write deadline (--eval-timeout, write phase) When writing the JSON envelope to the policy engine's stdin pipe, the same eval-timeout deadline applies. If the policy engine does not read its stdin within the timeout — for example because it exited early, blocked, or was given as a bare non-compliant binary — the entire policy engine process group is sent SIGKILL and execution fails closed. Response read deadline (--eval-timeout, read phase) After the envelope is written, the response is read with the same deadline and an optional byte cap (--max-response-bytes). Both limits send SIGKILL to the process group and fail closed on breach. Process group kill The policy engine subprocess is placed in its own process group at fork time. All SIGKILL signals are sent to the entire process group (kill(-pgid, SIGKILL)) so that any grandchildren spawned by the policy engine (e.g. sub-shells or helper processes) are terminated along with the engine itself, preventing orphaned processes from holding pipes open after the engine is killed. The JSON report is the sole authoritative source of policy decisions. Any human-readable text the policy engine emits alongside the JSON is for operator display only and is never parsed. Confirmation collection All human confirmations are collected before any command is executed. This prevents a partially-executed plan when an operator refuses a mid-sequence action. The confirmation window is serialised across concurrent sessions via --confirm-lock (see OPTIONS). Two confirmation paths are available: TTY path (single-session interactive use) Prompts are read from /dev/tty (or --confirm-tty PATH). This is the correct path for a single operator running a single AI session on a machine they are logged into. The executor opens the TTY device directly. Pipe path (remote multi-session deployments) When --confirm-pipe is set, the executor writes a JSON request to the named FIFO and reads the response from the paired FIFO. aishell-confirm(1) owns both FIFOs and runs as the operator, displaying full command context on their terminal and relaying the response. The executor never opens any PTY device. The typed challenge code is sent only through the pipe — it never reaches the AI's stderr channel. Confirmation levels: none No prompt; proceed immediately. plan "Proceed? [y/N]" — review the step before execution. action "Approve? [yes/NO]" — explicit operator approval required. typed Command-specific challenge must be typed back exactly. The typed challenge is an 8-character alphanumeric code derived from the command text using FNV-1a hashing. Visually ambiguous characters (0, 1, i, l, o) are excluded. The challenge changes with every unique command, proving the operator read the specific command being authorised rather than muscle-memorying a fixed word. 31^8 ≈ 852 billion combinations. Execution Each allowed and confirmed command is executed via fork+exec. All plans use fork+wait so the parent process always survives to write closing audit entries (EXEC_COMPLETE, SESSION_END) before exiting. The parent then exits with the child's exit code, so the exit code visible to the caller is identical to the child's. Absolute binary path The command name is resolved against a compile-time safe path list: /usr/local/bin, /usr/bin, /bin, /usr/sbin, /sbin The inherited $PATH is never consulted. A binary not found in the safe path list fails with exit code 6 rather than silently proceeding. Sanitised environment A minimal environment is constructed from an explicit allowlist of variables: HOME, USER, LOGNAME, TERM, COLORTERM, LANG, LC_ALL, LC_CTYPE, LC_MESSAGES, LC_TIME, LC_NUMERIC, LC_COLLATE, TZ, TMPDIR. PATH is always set to the safe path list above. All other variables from the calling environment are silently dropped, including LD_PRELOAD, DYLD_INSERT_LIBRARIES, PYTHONPATH, GIT_EXEC_PATH, and any other interpreter or dynamic-linker injection vectors. Pre-tokenised argv[] The argv[] array comes directly from the policy engine JSON response. aishell-gate-exec never re-parses or re-splits a command string at execution time. Multi-action plans Actions are run sequentially. The strategy field controls behaviour on non-zero exit: fail_fast stops at the first failure and logs how many confirmed actions were skipped; best_effort continues through all actions and returns the first non-zero exit code encountered. STARTUP SECURITY CHECKS ----------------------- Two checks run at startup, before argument parsing and before any file is opened: Setuid / setgid refusal If the real and effective UID (or GID) differ, the OS elevated this process via the setuid or setgid bit. aishell-gate-exec refuses to run with borrowed privileges because the confirmation UI reads from /dev/tty, environment variables affect the safe path search, and any bug in the executor binary becomes a local privilege escalation path. Fix: chmod u-s aishell-gate-exec (or chmod g-s). Binary writable by group or others If an attacker can overwrite the executor binary, the policy engine is never consulted and policy is bypassed entirely. The binary's permissions are checked via stat(). On Linux, /proc/self/exe is used to obtain the real path, immune to argv[0] spoofing. If the stat fails, a warning is emitted and this check is skipped. Fix: chmod go-w aishell-gate-exec. A security violation fails with exit code 5. If an audit log is accessible, a SECURITY_VIOLATION event is written before exit. AUDIT LOGGING ------------- aishell-gate-exec writes one JSON Lines entry to the audit log per event. Entries are HMAC-SHA256 chained: each record contains the HMAC of the previous entry, so a gap or modification is detectable by any holder of the key. TWO-LOG ARCHITECTURE aishell-gate uses two separate, independent audit logs: exec log: written by this binary; format identified by "chain_hmac" field policy log: written by aishell-gate-policy; format identified by "entry_hash" These logs use incompatible internal formats and are verified by different binaries. Do not mix them: aishell-gate-exec --audit-verify FILE (exec logs only) aishell-gate-policy --audit-verify FILE (policy logs only) Passing a policy log to exec's --audit-verify (or vice versa) will produce an error or an incorrect broken-chain result. The policy engine has no default audit log path. Its log is only written when --audit-log is explicitly passed to aishell-gate-policy. Log path (checked in this order): 1. --audit-log FILE command-line flag 2. AISHELL_EXEC_AUDIT_LOG environment variable 3. /var/log/aishell/audit.log HMAC key (checked in this order): 1. AISHELL_AUDIT_KEY environment variable (64 ASCII hex characters = 32 bytes) 2. /etc/aishell/audit.key (64 ASCII hex characters on the first line) 3. Per-session random key from /dev/urandom (ephemeral; chain cannot be verified across sessions in this mode — a warning is emitted to stderr at startup; the warning text contains the word "ephemeral" to aid grep-based monitoring) Key file format (exec only): The exec HMAC key file contains 64 ASCII hex characters (representing 32 raw bytes of key material) on the first line. Generate with: dd if=/dev/urandom bs=32 count=1 | xxd -p | tr -d '\n' \ > /etc/aishell/audit.key && chmod 640 /etc/aishell/audit.key WARNING: aishell-gate-policy uses a different key file format (64 raw binary bytes). The two key files are NOT interchangeable. Concurrent write safety: flock(LOCK_EX) is acquired on the log file descriptor before each write. The HMAC chain anchor and sequence counter are updated while the lock is held to prevent a forked chain if two processes race on the same log file. Multi-session audit note: each aishell-gate-exec invocation is an independent process with its own in-memory chain state. When multiple sessions write to the same log file, the file contains one internally consistent HMAC chain per session_id, not a single global sequence. Verify chains per session_id; treating the entire log as a single linear sequence will produce false verification failures when sessions are concurrent. Event types written to the audit log: SESSION_START Executor started; policy engine path, version, key mode (persistent or ephemeral). SESSION_END Session closed; exit code, actions executed, policy-denied count. PLAN_RECEIVED Goal, source, strategy, action count. POLICY_DECISION Per-action: cmd, allow/deny, reason, layer, risk score, policy version. CONFIRMATION_REQUESTED Operator prompted for a specific action. CONFIRMATION_RESULT Whether the operator approved or refused. EXEC_START Command about to be exec'd; resolved absolute path. EXEC_COMPLETE Command finished; exit code. EXEC_DENIED Execution blocked at the executor level (empty argv, binary not found in safe path). SECURITY_VIOLATION Startup security check failed, or policy engine response was missing required fields. ENVIRONMENT ----------- AISHELL_EXEC_AUDIT_LOG Default exec audit log path when --audit-log is not specified. Setting this variable is treated as an explicit audit request; failure to open the path is fatal. This variable controls ONLY the exec audit log. The policy engine has no equivalent env var; its log path is set via --audit-log passed directly to aishell-gate-policy. AISHELL_AUDIT_KEY 64-character ASCII hex HMAC key for the exec audit chain. Takes priority over /etc/aishell/audit.key. Format: exactly 64 lowercase hex characters (= 32 raw bytes). This format differs from the policy engine key file (64 raw binary bytes). EXIT STATUS ----------- 0 All actions allowed, confirmed, and executed (all exited 0). 1 Policy DENY on one or more actions; no commands were executed. 2 Human confirmation refused; no commands were executed. 3 Policy engine process error (spawn failed, timeout, byte limit, killed by signal, or bad exit code from the policy engine). 4 JSON parse error (input plan or policy engine response). 5 Usage or argument error, startup security check failed, or confirmation lock/pipe could not be opened. 6 execve() failure after confirmed ALLOW: binary not found in the safe path list, or exec returned an error. BUILD ----- cc -std=c11 -Wall -Wextra -o aishell-gate-exec aishell-gate-exec.c No external libraries are required. JSMN (JSON tokenizer) and SHA-256 are embedded. pipe2(2) is used for O_CLOEXEC pipe creation; it is a Linux extension available on Linux 2.6.27+ and glibc 2.9+. Requires a POSIX.1-2008 compatible system. USAGE EXAMPLES -------------- Human operator interactive mode (auto-detected when stdin is a TTY): ./aishell-gate-exec --policy-preset ops_safe # Or with explicit flag: ./aishell-gate-exec --interactive --policy-preset ops_safe \ --audit-log /var/log/aishell/exec.log # Sample session: # exec> git status <- ALLOW, confirm=none, executes immediately # exec> rm -rf /tmp/old <- ALLOW, confirm=typed, challenge code presented # exec> quit <- ends session, audit closed Learn about a command before running it (policy educational mode): ./aishell-gate-policy --preset ops_safe # policy> chmod +s /usr/bin/myapp # ALLOW chmod +s /usr/bin/myapp # Confirmation required: typed (gateway requires typed challenge code) # Flag analysis: # [danger] +s -- set suid/sgid bit; creates privilege escalation vector # To execute through the gateway: # echo 'chmod +s /usr/bin/myapp' | aishell-gate-exec --source human Run a JSON plan from stdin: echo '{ "goal": "check repository status", "actions": [{"type":"command","cmd":"git status"}] }' | ./aishell-gate-exec --policy-binary ./aishell-gate-policy Read plan from a file with a read-only preset: ./aishell-gate-exec --policy-binary ./aishell-gate-policy \ --plan plan.json --policy-preset read_only Multi-action plan with best_effort strategy and exec audit log: ./aishell-gate-exec --plan multi.json --policy-preset dev_sandbox \ --audit-log /var/log/aishell/exec.log Pass a project policy file and a jail root: ./aishell-gate-exec --plan plan.json \ --policy-project ./aishell-gate-policy_project.json \ --jail-root /home/ci/workspace Custom evaluation timeout: ./aishell-gate-exec --eval-timeout 10 --plan plan.json Strict input deadline (fail fast if AI stalls before writing the plan): ./aishell-gate-exec --input-timeout 5 --policy-binary ./aishell-gate-policy Pass a less-common policy engine flag (-- required): ./aishell-gate-exec --plan plan.json --policy-preset ops_safe -- --mode batch Verbose diagnostics for troubleshooting: ./aishell-gate-exec --verbose --plan plan.json Remote multi-session deployment (operator runs aishell-confirm in a second SSH session): ./aishell-gate-exec --policy-binary /usr/local/bin/aishell-gate-policy \ --policy-preset ops_safe \ --confirm-pipe /run/aishell-gate/confirm \ --confirm-lock /run/aishell-gate/confirm.lock \ --audit-log /var/log/aishell/audit.log \ --plan plan.json Print version: ./aishell-gate-exec --version LIMITS ------ Maximum actions per plan: 32 Maximum policy engine flags: 64 JSON token budget: 4096 tokens per parse Maximum goal length: 511 characters Maximum command length: 4095 characters Typed challenge length: 8 characters (FNV-1a derived, 31^8 combinations) DESIGN NOTES ------------ AIShell Labs LLC — we are an integrity company. aishell-gate-exec deliberately has no policy logic. Policy belongs entirely to aishell-gate-policy, which is a separate binary evaluated in a separate process. This separation means the executor can be audited for a single concern: does it faithfully interpret and execute what the policy engine decided, with correct confirmation and a clean environment? The JSON channel between the two programs is the trust boundary. aishell-gate-exec trusts the JSON decision report produced by the policy engine subprocess and nothing else. It does not accept policy overrides from the calling environment, from the input plan, or from any source other than that report. The two binaries serve two user populations: AI agents: submit a JSON plan; the executor gates it, collects human confirmation, and executes allowed commands. Human operators: run aishell-gate-exec --interactive (or just run it at a terminal). Commands are read from /dev/tty, assessed, confirmed at the appropriate gate, and executed. The same flag catalog reasoning and confirmation machinery used for AI plans applies equally to every human-typed command. The audit trail is identical. Confirmations are collected in a single pass before any command runs. This makes the operator's intent atomic: either everything is confirmed and then executed, or nothing is executed. A mid-plan refusal cannot leave the system in a partially-modified state that the operator did not consciously authorise. In interactive mode, confirmations are collected from /dev/tty directly, not from stdin. This keeps stdin available for any automation wrapper while the human operator handles confirmation at their terminal. All execution uses fork+wait so that the parent process always survives to write closing audit entries. The exit code visible to the caller is the child's exit code propagated through the parent's return value. The exec audit log is independent of the policy engine audit log. The policy engine records what it evaluated and decided (entry_hash chain format); aishell-gate-exec records what it confirmed and executed (chain_hmac format). Together they provide end-to-end traceability from intent through evaluation, confirmation, and execution. Each log is verified only by the binary that wrote it; see AUDIT LOGGING for details. SEE ALSO -------- aishell-gate-policy(1) -- policy evaluation engine aishell-confirm(1) -- operator confirmation relay for remote deployments execve(2) -- used for all command execution flock(2) -- advisory locking used by the audit subsystem and confirmation serialisation lock fnmatch(3) -- used internally by policy engine rule evaluation AUTHOR ------ Sean T. Gilley VERSION ------- aishell-gate-exec 0.35.0 aishell-gate-policy 1.00.0 aishell-confirm 0.5.0