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: 1 addition & 1 deletion CHRONICLE.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ The CLI resolves the server connection in this order:

```bash
# Set up a named context
cratis context create dev --server chronicle://localhost:35000/?disableTls=true
cratis context create dev --server chronicle://localhost:35000
cratis context set dev
```

Expand Down
6 changes: 3 additions & 3 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
</PropertyGroup>
<ItemGroup>
<!-- Cratis -->
<PackageVersion Include="Cratis.Chronicle.Connections" Version="15.40.0" />
<PackageVersion Include="Cratis.Chronicle.Contracts" Version="15.40.0" />
<PackageVersion Include="Cratis.Chronicle.Connections" Version="16.0.1" />
<PackageVersion Include="Cratis.Chronicle.Contracts" Version="16.0.1" />
<PackageVersion Include="Cratis.Fundamentals" Version="7.16.2" />
<!-- CLI -->
<PackageVersion Include="MongoDB.Driver" Version="3.10.0" />
Expand All @@ -30,7 +30,7 @@
<!-- Testing -->
<PackageVersion Include="Cratis.Specifications" Version="3.0.5" />
<PackageVersion Include="Cratis.Specifications.XUnit" Version="3.0.5" />
<PackageVersion Include="Cratis.Chronicle.XUnit.Integration" Version="15.40.0" />
<PackageVersion Include="Cratis.Chronicle.XUnit.Integration" Version="16.0.1" />
<PackageVersion Include="xunit" Version="2.9.3" />
<PackageVersion Include="xunit.runner.visualstudio" Version="3.1.5" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="18.7.0" />
Expand Down
2 changes: 1 addition & 1 deletion Documentation/chronicle/event-stores.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ cratis chronicle event-stores list

### Options

This command accepts only the global flags and the `--server` / `--management-port` connection flags. It does not accept `-e` or `-n` because it operates above the event store level.
This command accepts only the global flags and the `--server` connection flag. It does not accept `-e` or `-n` because it operates above the event store level.

### Output

Expand Down
3 changes: 1 addition & 2 deletions Documentation/chronicle/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,11 @@ The `cratis chronicle` command group provides the primary interface for interact

## Connection Flags

Most commands accept the following connection flags:
Most commands accept the following connection flag:

| Flag | Description |
|---|---|
| `--server <CONNECTION_STRING>` | Chronicle server connection string. Overrides the active context and the `CHRONICLE_CONNECTION_STRING` environment variable. |
| `--management-port <PORT>` | Management API port. Defaults to the port embedded in the connection string. |

For the full connection string format, see the [Connection](../reference/connection.md) reference page.

Expand Down
13 changes: 6 additions & 7 deletions Documentation/context/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ When the CLI resolves which server to connect to, it checks in this order:
1. `--server` flag on the current command
2. `CHRONICLE_CONNECTION_STRING` environment variable
3. Active context in `~/.cratis/config.json`
4. Default: `chronicle://localhost:35000/?disableTls=true`
4. Default: `chronicle://localhost:35000`

## Commands

Expand All @@ -34,7 +34,7 @@ cratis context list -o plain
Example output:

```
* dev chronicle://localhost:35000/?disableTls=true
* dev chronicle://localhost:35000
prod chronicle://prod.example.com:35000/
```

Expand All @@ -56,10 +56,10 @@ cratis context create <NAME> --server <CONNECTION_STRING>
| `--event-store` | `-e` | Default event store for this context (default: `default`) |
| `--namespace` | `-n` | Default namespace for this context (default: `Default`) |

**Example — local development server with TLS disabled:**
**Example — local development server:**

```bash
cratis context create dev --server chronicle://localhost:35000/?disableTls=true
cratis context create dev --server chronicle://localhost:35000
```

**Example — staging server with a specific event store and namespace:**
Expand Down Expand Up @@ -108,7 +108,7 @@ cratis context show -o json
Example output (plain):

```
Server: chronicle://localhost:35000/?disableTls=true
Server: chronicle://localhost:35000
Event store: default
Namespace: Default
Client ID: (not set)
Expand Down Expand Up @@ -182,12 +182,11 @@ cratis context set-value <KEY> <VALUE>
| `namespace` | Default namespace name |
| `client-id` | OAuth client ID for authenticated servers |
| `client-secret` | OAuth client secret (masked in output) |
| `management-port` | HTTP management port (default: `8080`) |

**Example — update the server URL:**

```bash
cratis context set-value server chronicle://localhost:35000/?disableTls=true
cratis context set-value server chronicle://localhost:35000
```

**Example — set credentials for an authenticated server:**
Expand Down
33 changes: 9 additions & 24 deletions Documentation/reference/connection.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Connection

This page documents how the `cratis` CLI connects to a Chronicle server: the connection string format, how the server address is resolved, and the management port used for HTTP operations.
This page documents how the `cratis` CLI connects to a Chronicle server: the connection string format and how the server address is resolved.

## Connection String Format

Expand All @@ -13,15 +13,19 @@ chronicle://<host>:<port>/?<options>
**Examples:**

```
chronicle://localhost:35000/?disableTls=true
chronicle://localhost:35000
chronicle://prod.example.com:35000/
```

Chronicle serves gRPC and the OAuth/HTTP API over a single TLS port (default `35000`). TLS is mandatory on that port: in development, the server auto-generates a self-signed certificate for `localhost` and the CLI trusts it automatically — no certificate setup is required to connect to a local server.

### Options

| Option | Values | Description |
|---|---|---|
| `disableTls` | `true` / `false` | Disables TLS for the gRPC connection. Required for local servers that do not have a certificate configured. |
| `disableTls` | `true` / `false` | Disables TLS for the connection. Only needed when connecting through a plaintext-terminating proxy — the Chronicle server itself always serves TLS. |
| `certificatePath` | path | Path to a client certificate file, for pinning a specific expected server certificate. |
| `certificatePassword` | string | Password for the certificate file. |

## Resolution Order

Expand All @@ -30,7 +34,7 @@ When the CLI determines which server to connect to, it checks sources in this or
1. `--server` flag on the current command
2. `CHRONICLE_CONNECTION_STRING` environment variable
3. Active context in `~/.cratis/config.json`
4. Default: `chronicle://localhost:35000/?disableTls=true`
4. Default: `chronicle://localhost:35000`

The `--server` flag always wins. The default applies only when none of the other sources provide a value.

Expand All @@ -45,32 +49,13 @@ cratis chronicle event-stores list

The variable is checked after `--server` but before the active context, so a context always overrides it when both are present unless `--server` is used explicitly.

## Management Port

Some Chronicle operations — including authentication token exchange and certain HTTP management APIs — use a separate HTTP port rather than the gRPC port in the connection string.

The default management port is `8080`.

Override it with the `--management-port` flag, which is available on all `cratis` subcommands that communicate with the server:

```bash
cratis chronicle auth status --management-port 9090
```

You can also persist the management port in a context so you do not need to specify it on every command:

```bash
cratis context set-value management-port 9090
```

## Per-Command Server Options

Every subcommand that communicates with Chronicle accepts these options directly, which take precedence over context and environment variable values:
Every subcommand that communicates with Chronicle accepts this option directly, which takes precedence over context and environment variable values:

| Option | Description |
|---|---|
| `--server <CONNECTION_STRING>` | Chronicle server connection string |
| `--management-port <PORT>` | HTTP management port (default: `8080`) |

**Example — connect to a specific server for a single command without changing the active context:**

Expand Down
1 change: 0 additions & 1 deletion Documentation/reference/global-options.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@ The debug panel includes:
- Config file path
- Active context name
- Connection string (credentials are redacted)
- Management port
- Resolved output format
- RPC timing for each gRPC call

Expand Down
2 changes: 1 addition & 1 deletion Documentation/reference/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ This section documents the cross-cutting mechanics of the `cratis` CLI: the flag

- [Global Options](global-options.md) — Flags such as `--output`, `--quiet`, `--yes`, and `--debug` that apply to every command.
- [Output Formats](output-formats.md) — The four output formats (`table`, `plain`, `json`, `json-compact`) with guidance on when to use each and token cost comparisons.
- [Connection](connection.md) — Connection string format, resolution order, management port, and environment variable configuration.
- [Connection](connection.md) — Connection string format, resolution order, and environment variable configuration.
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ namespace Cratis.Cli.Integration.Chronicle;
/// </summary>
/// <remarks>
/// <para>
/// The CLI connects to the Chronicle server externally via gRPC. The management
/// port is mapped to host port 8081 (instead of the default 8080) to avoid
/// conflicts with a locally running Chronicle instance used during development.
/// Tests pass <c>--management-port 8081</c> to the CLI so that the
/// <c>OAuthTokenProvider</c> reaches <c>https://localhost:8081/connect/token</c>.
/// The CLI connects to the Chronicle server externally via gRPC. The single Chronicle
/// port is mapped to host port 35001 (instead of the default 35000) to avoid conflicts
/// with a locally running Chronicle instance used during development. The OAuth token
/// endpoint is served on that same port, so the <c>OAuthTokenProvider</c> reaches
/// <c>https://localhost:35001/connect/token</c> without any extra configuration.
/// </para>
/// <para>
/// TLS is configured using a self-signed certificate generated at test startup.
Expand Down Expand Up @@ -78,13 +78,12 @@ public ChronicleOutOfProcessFixtureWithLocalImage()
protected override IContainer BuildContainer(INetwork network)
{
var waitStrategy = Wait.ForUnixContainer()
.AddCustomWaitStrategy(new HttpsHealthWait(8080), s => s.WithTimeout(TimeSpan.FromSeconds(15)));
.AddCustomWaitStrategy(new HttpsHealthWait(35000), s => s.WithTimeout(TimeSpan.FromSeconds(15)));

var builder = new ContainerBuilder(ChronicleImageName);
builder = ConfigureImage(builder)
.WithEnvironment("Storage__ConnectionDetails", "mongodb://localhost:27017")
.WithPortBinding(MongoDBPort, 27017)
.WithPortBinding(8081, 8080)
.WithPortBinding(35001, 35000)
.WithHostname(HostName)
.WithBindMount(Path.Combine(Directory.GetCurrentDirectory(), "backups"), "/backups")
Expand Down
4 changes: 2 additions & 2 deletions Integration/Chronicle/given/a_connected_cli.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@ protected static string ConnectionString
/// <summary>
/// Runs a CLI command against the live server with JSON output format.
/// </summary>
/// <param name="args">The command arguments (without --server, --management-port, and --output flags).</param>
/// <param name="args">The command arguments (without --server and --output flags).</param>
/// <returns>The command execution result.</returns>
protected static Task<CliCommandResult> RunCliAsync(params string[] args)
{
var allArgs = new List<string>(args) { "--server", ConnectionString, "--management-port", "8081", "--output", "json" };
var allArgs = new List<string>(args) { "--server", ConnectionString, "--output", "json" };
return CliCommandRunner.RunAsync([.. allArgs]);
}
}
32 changes: 16 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,21 +104,21 @@ cratis get-started
If no context is configured yet, the command will walk you through the setup:

```
╭─ Getting Started ───────────────────────────────────────────────
│ No configuration found. Set up a context to get started:
│ 1. Create a context pointing at your server:
│ cratis context create dev \
│ --server chronicle://localhost:35000/?disableTls=true
│ 2. Verify the connection:
│ cratis get-started
│ 3. Start exploring:
│ cratis chronicle event-stores list
╰─────────────────────────────────────────────────────────────────
╭─ Getting Started ──────────────────────────────────────────╮
│ │
No configuration found. Set up a context to get started: │
│ │
1. Create a context pointing at your server: │
cratis context create dev \ │
--server chronicle://localhost:35000
│ │
2. Verify the connection: │
cratis get-started │
│ │
3. Start exploring: │
cratis chronicle event-stores list │
│ │
╰────────────────────────────────────────────────────────────╯
```

Once a context is configured, `get-started` shows your active context, connection status, and a curated list of commands to explore and debug your event store.
Expand All @@ -130,7 +130,7 @@ A context stores a named connection to a Chronicle server:
```shell
# Create a context for local development
cratis context create dev \
--server chronicle://localhost:35000/?disableTls=true
--server chronicle://localhost:35000

# Make it the active context
cratis context set dev
Expand Down
5 changes: 0 additions & 5 deletions Source/Cli/CliContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,6 @@ public class CliContext
/// </summary>
public string? ClientSecret { get; set; }

/// <summary>
/// Gets or sets the management port for the HTTP API and token endpoint.
/// </summary>
public int? ManagementPort { get; set; }

/// <summary>
/// Gets or sets the cached access token from a previous login.
/// </summary>
Expand Down
3 changes: 1 addition & 2 deletions Source/Cli/Commands/Chronicle/Auth/LoginCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,7 @@ protected override async Task<int> ExecuteAsync(CommandContext context, LoginSet
var connectionString = new ChronicleConnectionString(settings.ResolveConnectionString());
var disableTls = connectionString.DisableTls;
var scheme = disableTls ? "http" : "https";
var managementPort = settings.ResolveManagementPort();
var tokenEndpoint = $"{scheme}://{connectionString.ServerAddress.Host}:{managementPort}/connect/token";
var tokenEndpoint = $"{scheme}://{connectionString.ServerAddress.Host}:{connectionString.ServerAddress.Port}/connect/token";

using var handler = CreateHandler();
using var httpClient = new HttpClient(handler);
Expand Down
17 changes: 7 additions & 10 deletions Source/Cli/Commands/Chronicle/ChronicleCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,7 @@ protected sealed override async Task<int> ExecuteAsync(CommandContext context, T
try
{
var connectionString = new ChronicleConnectionString(settings.ResolveConnectionString());
var managementPort = settings.ResolveManagementPort();
using var client = await CliChronicleConnection.Connect(connectionString, managementPort, cancellationToken);
using var client = await CliChronicleConnection.Connect(connectionString, cancellationToken);

int exitCode;
var sw = settings.Debug ? Stopwatch.StartNew() : null;
Expand Down Expand Up @@ -125,18 +124,16 @@ static void WriteDebugInfo(ChronicleSettings settings)
var configPath = CliConfiguration.GetConfigPath();
var config = CliConfiguration.Load();
var connectionString = settings.ResolveConnectionString();
var managementPort = settings.ResolveManagementPort();

Console.Error.WriteLine($"[debug] config: {configPath}");
Console.Error.WriteLine($"[debug] context: {config.ActiveContextName}");
Console.Error.WriteLine($"[debug] server: {RedactConnectionString(connectionString)}");
Console.Error.WriteLine($"[debug] management-port: {managementPort}");
Console.Error.WriteLine($"[debug] output: {settings.ResolveOutputFormat()}");
Console.Error.WriteLine($"[debug] config: {configPath}");
Console.Error.WriteLine($"[debug] context: {config.ActiveContextName}");
Console.Error.WriteLine($"[debug] server: {RedactConnectionString(connectionString)}");
Console.Error.WriteLine($"[debug] output: {settings.ResolveOutputFormat()}");

if (settings is EventStoreSettings ess)
{
Console.Error.WriteLine($"[debug] event-store: {ess.ResolveEventStore()}");
Console.Error.WriteLine($"[debug] namespace: {ess.ResolveNamespace()}");
Console.Error.WriteLine($"[debug] event-store: {ess.ResolveEventStore()}");
Console.Error.WriteLine($"[debug] namespace: {ess.ResolveNamespace()}");
}
}

Expand Down
32 changes: 1 addition & 31 deletions Source/Cli/Commands/Chronicle/ChronicleSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,6 @@ public class ChronicleSettings : GlobalSettings
[Description("Chronicle server connection string (e.g. chronicle://localhost:35000)")]
public string? Server { get; set; }

/// <summary>
/// Gets or sets the management port for the HTTP API and token endpoint.
/// </summary>
[CommandOption("--management-port <PORT>")]
[Description("Management port for the HTTP API and token endpoint (default: 8080)")]
public int? ManagementPort { get; set; }

/// <summary>
/// Resolves the effective connection string by checking flag, environment variable, current context, then default.
/// When the resolved connection string has no embedded credentials, client credentials from the context are composed in.
Expand All @@ -48,36 +41,13 @@ public string ResolveConnectionString()
var ctx = config.GetCurrentContext();
connectionString = !string.IsNullOrWhiteSpace(ctx.Server)
? ctx.Server
: "chronicle://localhost:35000/?disableTls=true";
: "chronicle://localhost:35000";
}
}

return ComposeCredentials(connectionString);
}

/// <summary>
/// Resolves the effective management port by checking flag, environment variable, current context, then default.
/// </summary>
/// <returns>The resolved management port.</returns>
public int ResolveManagementPort()
{
if (ManagementPort.HasValue)
{
return ManagementPort.Value;
}

var envVar = Environment.GetEnvironmentVariable(CliDefaults.ManagementPortEnvVar);
if (!string.IsNullOrWhiteSpace(envVar) && int.TryParse(envVar, out var envPort))
{
return envPort;
}

var config = CliConfiguration.Load();
var ctx = config.GetCurrentContext();

return ctx.ManagementPort ?? CliDefaults.DefaultManagementPort;
}

static string ComposeCredentials(string connectionString)
{
// Avoid calling the ChronicleConnectionString constructor here — it throws when no
Expand Down
Loading
Loading