Skip to content

tenon v0.7.0

Choose a tag to compare

@tenon-code-eu tenon-code-eu released this 24 Oct 00:48
· 121 commits to main since this release

tenon v0.7.0

The compliance and sovereignty release. It gives you evidence an auditor can check, rules an organisation can enforce, system confinement for commands, data that stays on your machine when it is classified, a Cyber Resilience Act assistant, and tenon in your CI.

Site and documentation (EN/FR): https://tenon-code-eu.github.io/tenon/

New

System sandbox

  • Shell commands and stdio MCP servers run confined by the operating system: Landlock and user/network namespaces on Linux, sandbox-exec on macOS.
  • Writes are limited to the project, temporary files, caches and [sandbox] write. Credentials directories (~/.ssh, ~/.aws, the Keychain on macOS…), tenon's configuration and its audit data are unreadable. The network is closed unless a network = true rule or your answer ("Allow with network") opens it.
  • [sandbox] mode = "auto" | "required" | "off". required refuses to start without confinement, and strict-local implies it. A project can only tighten; an organisation policy can impose required.
  • Secret environment variables (api_key_env of every provider and preset, MCP bearer_env and env_from) are never passed to commands, in every mode.
  • The limits are documented, including Unix sockets on Landlock ABI < 9 (a notice names docker.sock and the D-Bus bus when reachable), UDP under the TCP-only fallback, and .git protection (best effort on macOS, none on Linux).

Data-sensitivity routing

  • [classification] paths and markers (DIFFUSION RESTREINTE, EU RESTRICTED or your own) make a session sensitive. From then on it is sent only to the local model set in [routing] local.
  • Without a local provider, classified content is not read, or is withheld.
  • [routing] fallback gives an ordered list of providers for the rest, on network errors, 429 and 5xx. Each candidate still goes through the profile, allowlist and policy checks.
  • The audit log proves every decision, and the compliance export flags any violation.

Cyber Resilience Act assistant

  • tenon cra keeps an SBOM, a VEX, the article 14 reporting deadlines and an exportable technical dossier in the repository.
  • It runs an offline OSV vulnerability scan, usable in CI with tenon cra scan --fail-on open, and the OSV database can be downloaded from a mirror.
  • Four built-in skills are included. Nothing is sent to ENISA.

Compliance export

  • tenon audit export writes an HTML (FR/EN) and JSON report from the audit log: providers, consents, permissions, modified files, sub-agents, hooks, rewinds, incidents, regulatory mapping and a timeline.
  • The report includes profiles, policies, timestamps, sandbox use, routing and the CRA section. It contains no conversation content unless you ask for it.

Compliance profiles, provider allowlist, signed organisation policy

  • profile = "eu-only" | "secnumcloud" | "strict-local" is checked at startup and before each send. secnumcloud relies on a declared qualification, which tenon never verifies.
  • [provider_allowlist] restricts provider hosts.
  • A system policy signed with minisign (tenon policy check) acts as a floor nobody can loosen. It covers the profile, provider hosts, permission and redaction rules, audit level, MCP servers, timestamp authority, sandbox and classification.

RFC 3161 timestamping

  • [audit.timestamp] has a timestamp authority sign the head of the audit chain at the end of each session, or on demand with tenon audit timestamp. Only a SHA-256 hash leaves the machine.
  • tenon audit verify and the export check the tokens offline (--tsa-ca). A log rewritten after a timestamp is detected.

CI integration

  • --strict exits with code 4 when a non-interactive turn does not end cleanly.
  • --config <file> names the global configuration.
  • install.sh supports TENON_DOWNLOAD_BASE for sovereign mirrors (pinned version, https, hash and signature unchanged).
  • Copy-ready templates for GitLab CI, Forgejo/Gitea Actions and GitHub Actions are in docs/ci/.

Providers and interface

  • New presets: albert (Albert API, French public sector) and codestral.
  • TUI scrolling: mouse wheel, Shift+arrows, half-page, Home/End.
  • Approval panel: "Allow with network" for confined commands; "Network granted by rule" when a rule opens it.

Changes

  • tenon config check prints the configuration path, the sandbox status and the timestamp authority.
  • New configuration keys: profile, [provider_allowlist], [audit.timestamp], [sandbox], [classification], [routing], qualifications, and network on shell rules.
  • On upgrade, commands now run confined by default (mode = "auto"). Tools that write outside the project, for example ~/go/pkg/mod, ~/.cargo or ~/.m2, need [sandbox] write (~/.npm is writable by default). A stdio MCP server's risk now also decides its confinement: an empty risk means no network and a read-only project.
  • Built with Go 1.26.10, which fixes GO-2026-6809 in the standard library. golang.org/x/* dependencies are updated.

Known limits

  • The sandbox confines; it is not a complete isolation. Reads elsewhere stay open, and so do UDP under the TCP fallback, Unix sockets on Landlock ABI < 9, .git on Linux, and hooks, which run unconfined. See docs/security.md.
  • Routing relies on declared paths and markers. Content without a marker that is not under a classified path is not detected.
  • The provider allowlist and the policy do not restrict network access made by unconfined commands. An administrator of the machine can remove the policy.
  • RFC 3161 tokens are not checked for revocation.
  • Linux and macOS only.

Verify

minisign -Vm SHA256SUMS -p tenon.pub
sha256sum -c SHA256SUMS --ignore-missing   # macOS: shasum -a 256 -c SHA256SUMS --ignore-missing