Commit Graph
145 Commits
Author SHA1 Message Date
github-actions[bot] 3e004506d1 chore: geelen has signed the dco in #$pullRequestNo 2026-03-18 23:08:19 +00:00
github-actions[bot] fd93fed649 chore: Manoj-engineer has signed the dco in #$pullRequestNo 2026-03-18 23:05:04 +00:00
github-actions[bot] 4ff348ea90 chore: areporeporepo has signed the dco in #$pullRequestNo 2026-03-18 17:18:23 +00:00
github-actions[bot] 36756753cd chore: tyeth has signed the dco in #$pullRequestNo 2026-03-18 15:07:43 +00:00
github-actions[bot] ffae4eeddb chore: Kh4L has signed the dco in #$pullRequestNo 2026-03-18 08:09:44 +00:00
github-actions[bot] c65503ca55 chore: leoshi01 has signed the dco in #$pullRequestNo 2026-03-18 06:49:36 +00:00
github-actions[bot] f57a9799e9 chore: will-lms has signed the dco in #$pullRequestNo 2026-03-16 23:57:00 +00:00
github-actions[bot] 44aa1305e1 chore: ParthSareen has signed the dco in #$pullRequestNo 2026-03-16 21:04:41 +00:00
github-actions[bot] cb9ba0a16b chore: benfrank241 has signed the dco in #$pullRequestNo 2026-03-16 20:42:14 +00:00
github-actions[bot] ac5c209383 chore: mikemckiernan has signed the dco in #$pullRequestNo 2026-03-15 15:29:04 +00:00
github-actions[bot] 1590b22dc6 chore: zredlined has signed the dco in #$pullRequestNo 2026-03-12 22:25:34 +00:00
github-actions[bot] b4e344a5ba chore: kirit93 has signed the dco in #$pullRequestNo 2026-03-09 17:23:43 +00:00
github-actions[bot] f0bbc25986 chore: pimlock has signed the dco in #$pullRequestNo 2026-03-04 22:22:26 +00:00
github-actions[bot] f7051f5fb4 chore: miyoungc has signed the dco in #$pullRequestNo 2026-03-04 21:31:46 +00:00
github-actions[bot] 2440a6d91a chore: drew has signed the dco in #$pullRequestNo 2026-03-04 20:51:50 +00:00
github-actions[bot] d4fbf9cf7b chore: johntmyers has signed the dco in #$pullRequestNo 2026-03-04 19:14:57 +00:00
github-actions[bot] 1f5f8a5559 chore: create file to store dco signatures 2026-03-04 19:13:54 +00:00
John T. MyersandJohn Myers 05b868b935 fix(ci): replace deleted gsactions/dco-check with contributor-assistant (#98)
The gsactions/dco-check action repository was deleted, causing every DCO
workflow run to fail with startup_failure. Replace it with
contributor-assistant/github-action pinned to a commit SHA, matching the
pattern used by NVIDIA-NeMo/DataDesigner.

Signed-off-by: John Myers <johntmyers@users.noreply.github.com>
Co-authored-by: John Myers <johntmyers@users.noreply.github.com>
2026-03-04 11:11:48 -08:00
John T. MyersandJohn Myers af8fe4d1d5 refactor(policy): consolidate duplicated YAML struct hierarchies (#97)
* refactor(policy): consolidate duplicated YAML struct hierarchies into navigator-policy

Closes #96

Merge the Deserialize-only input structs and Serialize-only output structs
into a single set of types in navigator-policy that derive both Serialize
and Deserialize. This eliminates the duplicate PolicyYaml hierarchy in
navigator-cli and fixes three round-trip issues:

- filesystem_policy vs filesystem field name mismatch
- allowed_ips silently dropped on proto-to-YAML conversion
- network policy name field silently dropped on proto-to-YAML conversion

Also adds api_patterns support to the inference YAML schema and switches
network_policies from HashMap to BTreeMap for deterministic output ordering.

* fix(e2e): update non-CONNECT test assertion from 405 to 403

Align test_l4_non_connect_method_rejected with the proxy behavior
change in c06117e which intentionally returns 403 for non-CONNECT
requests.

---------

Co-authored-by: John Myers <johntmyers@users.noreply.github.com>
2026-03-04 10:35:54 -08:00
John T. MyersandJohn Myers 1d81fb187b feat(skills): create nemoclaw-cli agent skill (#85)
* feat(skills): create nemoclaw-cli agent skill and fix generate-sandbox-policy schema drift

Closes #83

Create a new nemoclaw-cli agent skill with tiered workflow guidance (basic
through advanced) and a supplementary CLI reference. The skill covers provider
management, sandbox lifecycle, policy iteration loops, BYOC pipelines, and
agent-assisted sandbox sessions. It cross-references generate-sandbox-policy
for policy content authoring and includes --help self-teaching as a fallback.

Fix critical schema drift in generate-sandbox-policy: rename
allowed_routing_hints to allowed_routes (matching the actual proto/serde
field name). Update default read_only paths to match dev-sandbox-policy.yaml.
Fix the same field name error in architecture/security-policy.md.

* policy updates

* fix(test): update OPA tests for renamed github_ssh_over_https policy key

---------

Co-authored-by: John Myers <johntmyers@users.noreply.github.com>
2026-03-04 09:52:55 -08:00
Piotr Mlocek 11f19a9176 fix(sandbox): fix data corruption in sync --down and hang in sync --up (#93)
The sandbox SSH server used tokio::spawn fire-and-forget for each stdout/stderr
chunk, which provided no ordering guarantee under tokio's work-stealing scheduler.
Under load, chunks arrived out-of-order, corrupting tar streams during download.

Replace tokio::spawn with runtime.block_on() to ensure each chunk is fully sent
before reading the next. Remove AsyncWriteExt::shutdown() from the SSH proxy's
copy helper to prevent gateways from treating TCP half-close as full-close and
truncating in-flight downloads.

Implement channel_eof handler on the sandbox SSH server to close the child
process stdin when the client signals EOF. Without this, commands like
'cat | tar xf -' used by sync --up would hang waiting for stdin EOF
indefinitely. Add ValueHint::AnyPath to the --up argument for shell completion.
2026-03-04 08:35:04 -08:00
Piotr Mlocek 4b8ca74da8 fix(cli): add path hints for file-valued flags (#86) 2026-03-03 21:40:57 -08:00
John T. MyersandJohn Myers 66df9f7614 feat(tui): add port forwarding support to Gator (#81)
* feat(tui): add port forwarding support to Gator (#80)

Extract forward PID management, resolve_ssh_gateway, and shell_escape from
navigator-cli into navigator-core::forward as a shared module. Add a Ports
field to the TUI create sandbox modal, a NOTES column to the sandbox table,
and a Forwards row to the sandbox detail view. On creation with ports, Gator
polls for Ready state then spawns background SSH tunnels. Forward cleanup
runs automatically on sandbox delete.

Closes #80

* fix(tui): fix Ports field invisible due to modal height overflow

The modal height calculation used content_height + 3 but block chrome
(borders + padding) is 4 rows, not 3. Combined with the 3-row Ports
field layout, the input line was clipped to zero height on standard
24-row terminals. Switch Ports to a compact single-line inline layout
and fix the chrome arithmetic.

* wip: BYOC example with port forwarding and TUI command field fix

- Move examples/bring-your-own-container.md into its own directory
- Add example Dockerfile and app.py (Python REST API with /hello endpoint)
- Rewrite README with full CLI and TUI port-forward workflows
- Change TUI Command field default from /bin/bash to empty so custom
  image entrypoints run without manual clearing

* feat(tui): wire up Command field to SSH exec after sandbox creation

When a command is specified in the create sandbox modal, the TUI now
waits for the sandbox to reach Ready (with the pacman animation),
starts any port forwards, then suspends the TUI and executes the
command via SSH — matching the CLI's post-creation flow.

- Refactor spawn_create_sandbox to poll for Ready inline when ports
  or command are set, keeping the animation visible throughout
- Add start_port_forwards() helper called within the create task
- Add handle_exec_command() to suspend TUI and run SSH exec
- Remove unused ForwardResult event variant (forwards are now started
  within the create task, not as a separate event)

* fix(tui): fix command exec, forward timeouts, and create modal UX

- Fix handle_exec_command to suspend TUI and run SSH attached (matching
  CLI behavior) so the process stays alive for the session duration
- Fix shell_escape double-quoting: escape each word individually
- Add ConnectTimeout and 20s spawn timeout to forward SSH so a stalled
  auth doesn't freeze the create flow forever
- Remove dead ForwardResult event variant
- Add cluster_name to start_port_forwards for ProxyCommand
- Add spacer between Providers and Ports in create modal
- Fix Command placeholder: 'runs /bin/bash if empty' (not image entrypoint)
- Update BYOC README: document that CMD is replaced by supervisor,
  command must be passed explicitly, remove TUI-specific sections

* fix(sandbox): demote Landlock fallback log from warn to debug

The Landlock filesystem sandbox emits a noisy warning when a policy
path does not exist (e.g. /app in custom images). Since BestEffort
mode intentionally continues without Landlock, demote to debug.

* docs: fix BYOC Dockerfile comments for supervisor CMD override

---------

Co-authored-by: John Myers <johntmyers@users.noreply.github.com>
2026-03-03 17:31:44 -08:00
John T. MyersandJohn Myers c06117eb15 fix(proxy): return 403 for non-CONNECT requests, add deny logging, and revise error messages (#79)
Closes #42

- Change non-CONNECT proxy response from 405 to 403 to align with
  how CONNECT denials are surfaced
- Add structured deny logging for non-CONNECT requests with hostname
  extraction from absolute-form URIs
- Revise 7 user-facing error messages across proxy.rs and
  dev-sandbox-policy.rego to follow consistent principle: generic
  policy-deny messages for non-inference requests, descriptive messages
  for recognized inference endpoints
- Update E2E test assertion to match new error message
- Update architecture docs to reflect new behavior

Co-authored-by: John Myers <johntmyers@users.noreply.github.com>
2026-03-03 13:06:17 -08:00
Drew Newberry 9099bc3972 chore: rename Navigator to NemoClaw across user facing contracts (#73) 2026-03-03 11:41:19 -08:00
Drew Newberry 46381e65cf fix(ci): harden cargo build retry by wiping target dir and disabling sccache (#77)
The multi-arch publish job fails with 'extern location does not exist'
errors for version_check when BuildKit cache mounts contain stale
artifacts. The existing retry logic (cargo clean + retry) was
ineffective because:

1. cargo clean relies on its own metadata to decide what to remove,
   which can itself be stale on BuildKit cache mounts shared across
   different build profiles (debug vs release).

2. sccache remained enabled during the retry, so a corrupt memcached
   cache entry would reproduce the same failure even after cleaning.

Replace cargo clean with rm -rf /build/target/* for a thorough wipe,
and unset RUSTC_WRAPPER on retry so cargo falls back to raw rustc.
2026-03-03 11:32:07 -08:00
Drew Newberry 9977a94226 fix(ci): pin Python to 3.12.12 to avoid broken 3.12.13 source build (#74)
Python 3.12.13 has no precompiled binary for the CI runner platform,
causing mise to fall back to python-build which fails during ensurepip.
2026-03-03 10:23:56 -08:00
John T. MyersandJohn Myers fc745f824c docs: add system architecture diagram and update arch-doc-writer agent (#72)
Add a top-level Mermaid architecture diagram (architecture/system-architecture.md)
covering all deployable components, external systems, communication protocols,
and security boundaries. Update the arch-doc-writer agent to maintain this
diagram as part of its documentation workflow.

Co-authored-by: John Myers <johntmyers@users.noreply.github.com>
2026-03-03 10:04:38 -08:00
Alexander Watson 1d7909cb38 chore: add open-source compliance files and SPDX headers (#71)
Add Apache 2.0 licensing, SPDX copyright headers on all source files,
DCO enforcement, third-party notices, and CI enforcement.

- LICENSE: Apache License 2.0 full text
- DCO: Developer Certificate of Origin 1.1
- SPDX headers on all 176 source files (.rs, .py, .proto, .rego, .sh,
  .toml, .yaml, Dockerfiles)
- scripts/update_license_headers.py: header management with --check mode
- scripts/generate_third_party_notices.py: dependency license aggregation
- THIRD-PARTY-NOTICES: generated listing of all Rust and Python deps
- build/license.toml: mise tasks for license:check and license:update
- CI: license-headers job in checks.yml, DCO check workflow
- CONTRIBUTING.md: DCO sign-off requirement and license header docs
- Cargo.toml: license changed to Apache-2.0, repository URL updated
- pyproject.toml: license field added

Closes #58
2026-03-03 09:30:56 -08:00
Drew Newberry a17959f76e fix(sandbox): eliminate SSH transport race causing flaky E2E tests (#69) 2026-03-03 01:24:57 -08:00
Drew Newberry 53899f92f9 chore(ci): switch sccache from local disk to memcached backend (#68) 2026-03-03 00:20:31 -08:00
Drew Newberry 3c732ee21b Update README.md (#67) 2026-03-02 20:48:06 -08:00
Drew Newberry 4e3660ee5b docs(readme): add cluster deploy, upgrading, and sandbox tooling sections (#66)
* Update README.md

* docs(readme): add cluster deploy, upgrading, and sandbox tooling sections
2026-03-02 20:43:36 -08:00
Drew Newberry 36e5b4e231 chore: move tui-development skill to .agents directory (#65) 2026-03-02 20:37:24 -08:00
Drew Newberry ec5443893b chore: Update README.md to use nemoclaw registry (#63) 2026-03-02 20:23:25 -08:00
Drew Newberry 9cd00bbfa3 fix(cluster): fully release resources on destroy to prevent port conflicts (#64) 2026-03-02 20:21:56 -08:00
John T. MyersandJohn Myers ff52643237 feat(sandbox): allow egress to private IP space via allowed_ips policy field (#60)
* feat(sandbox): allow egress to private IP space via allowed_ips policy field

Add an allowed_ips field to NetworkEndpoint that accepts CIDR notation and
exact IPs, enabling sandboxes to reach private IP space under policy control
while maintaining SSRF protections for loopback and link-local addresses.

Three modes are supported:
- Default (no allowed_ips): all private IPs blocked (existing behavior)
- Host + allowlist: domain must resolve to an IP in allowed_ips
- Hostless allowlist (no host): any domain allowed if resolved IP matches



Co-authored-by: John Myers <johntmyers@users.noreply.github.com>
2026-03-02 19:29:34 -08:00
Drew Newberry fc29a30bc7 fix(ci,publish): harden publish flow and cache nemoclaw wheel builds (#55) 2026-03-02 18:41:58 -08:00
Drew Newberry 2f8645dd76 refactor(cli): remove global --tls-ca, --tls-cert, --tls-key flags (#62)
TLS certificates are always resolved automatically from cluster metadata,
making the explicit CLI flags unnecessary. The TlsOptions struct and
auto-resolution logic remain intact for programmatic and test use.
2026-03-02 18:07:49 -08:00
Drew Newberry e102808e0a fix(cli): pass cluster name to ssh-proxy child process for correct TLS path resolution (#52) 2026-03-02 13:52:44 -08:00
John T. Myers c0547c500e feat(gator): interactive TUI for Navigator (#57)
Initial TUI aka Gator
2026-03-02 09:56:42 -08:00
Piotr Mlocek d0e10e97cb fix: inference routing improvements (#56)
* fix(router): use protocol-aware auth headers for inference proxying

The router always sent `Authorization: Bearer` when proxying to backends,
which breaks Anthropic endpoints that require `x-api-key`. Thread the
source_protocol through to proxy_to_backend and set the appropriate auth
header based on protocol family.

* fix(server): remove noisy inference bundle log

The "serving inference bundle" info log fired every 30s per sandbox on
each route refresh poll. Remove it since there is no equivalent log for
policy serving.

* fix(sandbox): keep inference routing active when cluster bundle is initially empty

In cluster mode, if GetSandboxInferenceBundle returned zero routes at
sandbox startup, build_inference_context() returned None, disabling
inference routing for the sandbox lifetime and preventing
spawn_route_refresh() from starting. Routes created after sandbox
startup were never picked up.

Keep inference interception active with an empty cache in cluster mode
so background refresh can activate routes created later. File-mode
semantics are unchanged.
2026-03-02 07:48:00 -08:00
Drew Newberry a6155f9a5b chore: remove unnecessary cache config (#54) 2026-03-01 23:36:53 -08:00
Drew Newberry 0b713f76b1 ci: add publish workflow and refactor e2e into reusable workflow (#53) 2026-03-01 23:20:53 -08:00
Drew Newberry e0909850e9 test: bring back e2e tests on Github CI (#48) 2026-03-01 22:48:51 -08:00
Drew Newberry 91dd2e196a fix(providers): use name instead of type on lookup (#46) 2026-02-27 16:12:09 -08:00
Piotr Mlocek 7ca7dd3012 refactor(agents): update agents context after the migration (#45)
Replace all GitLab-specific skill workflows with GitHub equivalents:
- create-gitlab-mr -> create-github-pr (gh pr create)
- review-gitlab-mr -> review-github-pr (gh pr diff/view)
- create-gitlab-issue -> create-github-issue (gh issue create)
- watch-gitlab-pipeline -> watch-github-actions (gh run)
- Update review-security-issue, fix-security-issue, build-from-issue
  to use gh CLI and GitHub API patterns
- Update CONTRIBUTING.md references
2026-02-27 12:35:50 -08:00
Piotr Mlocek 3015375208 feat(cli): add runtime completers for sandbox/cluster/provider names (#44)
Add tab-completion for positional name arguments across sandbox, cluster,
and provider commands. Completers fetch live data on tab-press: cluster
names from local metadata files (no network), sandbox and provider names
via gRPC to the active cluster's gateway with a 2s timeout.

Key implementation details:
- Move rustls crypto provider init before CompleteEnv::complete() so TLS
  works inside completers
- Spawn a dedicated OS thread for async gRPC calls to avoid nested tokio
  runtime panic (completers run synchronously inside #[tokio::main]'s
  block_on)
- All completers fail silently (return empty vec) on any error
2026-02-27 10:57:04 -08:00
Drew Newberry a71f2a5e7d ci: add GitHub Actions CI workflow with lint, test, and image build (#1) 2026-02-27 10:10:28 -08:00
John Myers 7070264ad7 fix(logs): reduce log noise and add reconnect observability (!62)
## Summary
- Downgrade `GetSandboxPolicy served from policy history` from INFO to DEBUG — this was firing every 30s per sandbox and filling the 2000-line in-memory log buffer with noise, drowning out real events
- Add `"navigator: log push reconnected (attempt N)"` eprintln on successful reconnect in the sandbox log push loop, so operators can confirm recovery after a gateway restart

## Test Plan
- Deployed to local cluster, created sandbox, verified no policy polling spam in `nav sandbox logs`
- Restarted gateway, confirmed sandbox stderr shows reconnect success message: `navigator: log push reconnected (attempt 5)`
- Verified sandbox log push re-establishes after gateway restart
2026-02-27 09:54:59 -08:00