code wiki / (root) / nx_tool_exec_allow.nx

nx_tool_exec_allow.nx

buildroot/runtime/nx_tool_exec_allow.nx

26716 B480 linesdepth 5pulls 5 transitivereach 89 importersview sourcekind librarytopic tool
docsdependenciesstructsconstsfunctions

about

nx_tool_exec_allow.nx -- R1 of the executable-API rung: the EXECUTION allowlist that gates R0's raw exec+capture primitive (nx_tool_run) so /mcp tools/call can only ever run VETTED, gate-GREEN organs. This is the never-brick + no-confused-deputy boundary: a caller passes a tool NAME (already capability- authorized upstream in ta_mcp_call); this layer maps that name -> an absolute ELF path ONLY if the name matches an explicit allowlist row whose gate-status is the literal "GREEN". A caller can NEVER supply a path, a "..", or a shell string -- those simply do not resolve. SEPARATE from nx_tool_registry.nx (the DISCOVERY registry that feeds /api/tools + tools/list): discovery answers "what tools exist"; this answers "which of them may be EXECUTED, and from which exact ELF". Kept apart on purpose -- listing a tool must never imply it is runnable. Data-driven (rule 11): the operator curates `tool_allowlist.conf`, so vetting a tool for execution is a config edit + a gate run, not a code change. Missing file / missing row / non-GREEN row -> refused (fail-closed). Row format (TAB-separated; '#' comment lines and blank lines ignored): <tool_name>\t<absolute_elf_path>\t<gate_status> license_tier: ORIGINAL

dependencies 1 imports · 24 importers

nx_tool_run.nx nx_tool_exec_allow.nx nx_cr_exec_proof.nx nx_crew_contract_audit.nx nx_job_concurrent_canonical_gate_t nx_job_concurrent_gate_t182.nx nx_job_reservation_canonical_gate_ nx_job_reservation_gate_t182.nx nx_mgmt_api.nx nx_mgmt_api.pre-toolchain-20260910 nx_mgmt_api_search_candidate_t330. nx_mgmt_api_toolchain_session_2026

diagram shows first 10 each side; +0 more imports, +14 more importers in the complete lists below.

imports: nx_tool_run.nx

imported by: nx_cr_exec_proof.nxnx_crew_contract_audit.nxnx_job_concurrent_canonical_gate_t182.nxnx_job_concurrent_gate_t182.nxnx_job_reservation_canonical_gate_t182.nxnx_job_reservation_gate_t182.nxnx_mgmt_api.nxnx_mgmt_api.pre-toolchain-20260910.nxnx_mgmt_api_search_candidate_t330.nxnx_mgmt_api_toolchain_session_20260910.nxnx_mgmt_cap_candidate_t186.nxnx_mgmt_deploy_candidate_t185.nxnx_sync_promote_gate.nxnx_tea_pinned_gate.nxnx_tool_exec_allow_gate.nxnx_tools_api.nxnx_tools_api_candidate_t182.nxnx_tools_api_canonical_candidate_t182.nxnx_tools_api_idem_candidate_t190.nxnx_tools_api_recovery_candidate_t316.nxnx_tools_api_recovery_candidate_v2_t316.nxnx_tools_api_recovery_candidate_v3_t316.nxnx_vizsla_mcp_gate.nxnx_vizsla_notify_mcp_gate.nx

structs

none

consts

17const TEA_MAGIC_4096: i64 = 4096
18const TEA_MAGIC_262144: i64 = 262144
20const TEA_CONF: *u8 = "tool_allowlist.conf" as *u8 // relative to the server CWD (same convention as cap_revoked.list)
23const TEA_OK: i64 = 1 // allowlisted AND gate-GREEN -> out_path filled, runnable
24const TEA_BLOCKED: i64 = 0 // allowlisted but gate-status != GREEN -> present, NOT runnable
25const TEA_NOTFOUND: i64 = 0 - 1 // no such tool in the allowlist
26const TEA_NOCONF: i64 = 0 - 2 // allowlist file absent/unreadable (fail-closed)
129const TEA_EXEC_TIMEOUT_MS: i64 = 120000
150const TEA_EDGE_WINDOW_MS: i64 = 15000
151const TEA_EXEC_TIMEOUT_SYNC_MS: i64 = TEA_EDGE_WINDOW_MS - 1000
392const TEA_WINDOW_CONF: *u8 = "knowledge/edge_window.conf" as *u8
393const TEA_WINDOW_KEY: *u8 = "edge_window_ms" as *u8
394const TEA_RESERVE_KEY: *u8 = "reply_reserve_ms" as *u8
395const TEA_REPLY_RESERVE_DEFAULT_MS: i64 = TEA_EDGE_WINDOW_MS - TEA_EXEC_TIMEOUT_SYNC_MS
396const TEA_CONF_CAP: i64 = TEA_MAGIC_4096 // a two-row conf; a full read of it fits with 40x headroom
397const TEA_SRC_DEFAULT: i64 = 0
398const TEA_SRC_CONF: i64 = 1
399const TEA_NL: i64 = 10
400const TEA_D0: i64 = 48
401const TEA_D9: i64 = 57

functions

29func tea_field_eq(buf: *u8, s: i64, e: i64, key: *u8) -> i64
40func tea_field_eq_n(buf: *u8, s: i64, e: i64, name: *u8, nlen: i64) -> i64
50func tea_name_ok(name: *u8, nlen: i64) -> i64
70func tea_resolve_from(conf: *u8, name: *u8, nlen: i64, out_path: *u8, out_cap: i64) -> i64
115func tea_resolve(name: *u8, nlen: i64, out_path: *u8, out_cap: i64) -> i64
157func tea_run_from(conf: *u8, name: *u8, nlen: i64, arg: *u8, out: *u8, out_cap: i64, outlen: *i64, rc: *i64) -> i64
166func tea_run(name: *u8, nlen: i64, arg: *u8, out: *u8, out_cap: i64, outlen: *i64, rc: *i64) -> i64
calls 1: tea_run_from
175func tea_run_argv_from(conf: *u8, name: *u8, nlen: i64, argv: *i64, out: *u8, out_cap: i64, outlen: *i64, rc: *i64) -> i64
185func tea_run_argv(name: *u8, nlen: i64, argv: *i64, out: *u8, out_cap: i64, outlen: *i64, rc: *i64) -> i64
197func tea_read_conf(path: *u8, out_len: *i64) -> *u8
220func tea_tokenize(s: *u8, argv: *i64, base: i64, scratch: *u8, scap: i64) -> i64
241func tea_tokenize_checked(s:*u8, argv:*i64, base:i64, argv_cap:i64, scratch:*u8, scap:i64)->i64
262func tea_resolve_pinned_from(conf: *u8, name: *u8, nlen: i64, out_path: *u8, out_cap: i64, out_pin: *u8, pin_cap: i64, out_haspin: *i64) -> i64
328func tea_run_pinned_from_to(conf: *u8, name: *u8, nlen: i64, callerargv: *i64, out: *u8, out_cap: i64, outlen: *i64, rc: *i64, tmo: i64) -> i64
349func tea_run_pinned_from(conf: *u8, name: *u8, nlen: i64, callerargv: *i64, out: *u8, out_cap: i64, outlen: *i64, rc: *i64) -> i64
called by 2: mainmain calls 1: tea_run_pinned_from_to
352func tea_run_pinned_to(name: *u8, nlen: i64, callerargv: *i64, out: *u8, out_cap: i64, outlen: *i64, rc: *i64, tmo: i64) -> i64
355func tea_run_pinned(name: *u8, nlen: i64, callerargv: *i64, out: *u8, out_cap: i64, outlen: *i64, rc: *i64) -> i64
363func tea_run_pinned_deadline_from(conf: *u8, name: *u8, nlen: i64, callerargv: *i64, out: *u8, out_cap: i64, outlen: *i64, rc: *i64, deadline_ms: i64, out_pid: *i64, out_rfd: *i64) -> i64
382func tea_run_pinned_deadline(name: *u8, nlen: i64, callerargv: *i64, out: *u8, out_cap: i64, outlen: *i64, rc: *i64, deadline_ms: i64, out_pid: *i64, out_rfd: *i64) -> i64
406func tea_conf_read(path: *u8, buf: *u8, cap: i64) -> i64
420func tea_conf_int(buf: *u8, n: i64, key: *u8, dflt: i64) -> i64
450func tea_edge_window_ms_from(conf: *u8, out_src: *i64) -> i64
460func tea_edge_window_ms(out_src: *i64) -> i64 { return tea_edge_window_ms_from(TEA_WINDOW_CONF, out_src) }
461func tea_reply_reserve_ms_from(conf: *u8) -> i64
469func tea_reply_reserve_ms() -> i64 { return tea_reply_reserve_ms_from(TEA_WINDOW_CONF) }
473func tea_sync_promote_ms_from(conf: *u8, out_src: *i64) -> i64
480func tea_sync_promote_ms(out_src: *i64) -> i64 { return tea_sync_promote_ms_from(TEA_WINDOW_CONF, out_src) }