Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/security-gate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
8 changes: 7 additions & 1 deletion application/src/Nexo.CLI/Program.CommandRegistration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,12 @@ namespace Nexo.CLI;
/// <summary>Program.</summary>
static partial class Program
{
private static RootCommand BuildRootCommand()
/// <summary>
/// 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).
/// </summary>
internal static RootCommand BuildRootCommand()
{
var root = new RootCommand("Nexo command-line interface")
{
Expand Down Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using System.CommandLine;
using FluentAssertions;
using Xunit;

namespace Nexo.Tests.CLI.Tests.Commands;

/// <summary>
/// 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.
/// </summary>
[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");
}
}
Loading