diff --git a/.github/workflows/security-gate.yml b/.github/workflows/security-gate.yml
index dae330d76..afec0004a 100644
--- a/.github/workflows/security-gate.yml
+++ b/.github/workflows/security-gate.yml
@@ -13,6 +13,8 @@ on:
- "src/Nexo.Tests.Infrastructure/Tests/Safety/**"
- "application/src/Nexo.API/Security/**"
- "application/src/Nexo.CLI/Commands/TrustCommand.cs"
+ - "application/src/Nexo.CLI/Program.TrustCommands.cs"
+ - "application/src/Nexo.CLI/Program.CommandRegistration.cs"
- "scripts/security-gate*.sh"
- "Makefile"
- ".github/workflows/security-gate.yml"
diff --git a/application/src/Nexo.CLI/Program.CommandRegistration.cs b/application/src/Nexo.CLI/Program.CommandRegistration.cs
index 59b08e005..d2c5c42e3 100644
--- a/application/src/Nexo.CLI/Program.CommandRegistration.cs
+++ b/application/src/Nexo.CLI/Program.CommandRegistration.cs
@@ -10,7 +10,12 @@ namespace Nexo.CLI;
/// Program.
static partial class Program
{
- private static RootCommand BuildRootCommand()
+ ///
+ /// Builds the CLI root command tree. Internal so Nexo.Tests.CLI can assert the
+ /// registered top-level commands without spawning the host (guards against a
+ /// built-but-never-added command, which is how `trust` went missing in #162).
+ ///
+ internal static RootCommand BuildRootCommand()
{
var root = new RootCommand("Nexo command-line interface")
{
@@ -609,6 +614,7 @@ private static RootCommand BuildRootCommand()
var meshCmd = new MeshCommand();
root.AddCommand(meshCmd);
root.AddCommand(backgroundAgentCmd);
+ root.AddCommand(trustCmd);
root.AddCommand(testCmd);
root.AddCommand(escalateCmd);
root.AddCommand(metricsCmd);
diff --git a/application/src/Nexo.Tests.CLI/Tests/Commands/RootCommandRegistrationTests.cs b/application/src/Nexo.Tests.CLI/Tests/Commands/RootCommandRegistrationTests.cs
new file mode 100644
index 000000000..c77d805ac
--- /dev/null
+++ b/application/src/Nexo.Tests.CLI/Tests/Commands/RootCommandRegistrationTests.cs
@@ -0,0 +1,39 @@
+using System.CommandLine;
+using FluentAssertions;
+using Xunit;
+
+namespace Nexo.Tests.CLI.Tests.Commands;
+
+///
+/// Guards the root command registration list in Program.CommandRegistration.cs.
+/// A command can be built (BuildXxxCommand) and then silently never added to the root;
+/// that is how `nexo trust` disappeared in #162 while README/GettingStarted and the
+/// Tier C security gate kept invoking it.
+///
+[Trait("Category", "CLI")]
+public sealed class RootCommandRegistrationTests
+{
+ [Fact(Timeout = 15000)]
+ public async Task RootCommand_RegistersTrustCommand()
+ {
+ await Task.CompletedTask;
+ var root = Nexo.CLI.Program.BuildRootCommand();
+ var subcommands = root.Subcommands.Select(s => s.Name).ToList();
+
+ subcommands.Should().Contain("trust");
+ }
+
+ [Fact(Timeout = 15000)]
+ public async Task TrustCommand_HasDocumentedSubcommands()
+ {
+ await Task.CompletedTask;
+ var root = Nexo.CLI.Program.BuildRootCommand();
+ var trust = root.Subcommands.Single(s => s.Name == "trust");
+ var subcommands = trust.Subcommands.Select(s => s.Name).ToList();
+
+ // Named by README.md, docs/GettingStarted.md and scripts/security-gate-tier-c.sh.
+ subcommands.Should().Contain(new[] { "dashboard", "boundary", "pause", "resume", "pack" });
+ trust.Subcommands.Single(s => s.Name == "pack").Subcommands.Select(s => s.Name)
+ .Should().Contain("apply");
+ }
+}