docs: design for completing 93 stub features (config binding + auth implementation)

This commit is contained in:
Joseph Doherty
2026-02-26 16:54:05 -05:00
parent a58e8e2572
commit 63715f256a
3 changed files with 224 additions and 1 deletions

View File

@@ -0,0 +1,185 @@
# Stub Features Implementation Design
**Date:** 2026-02-26
**Scope:** Complete the 93 remaining `stub` features in Phase 6
**Approach:** Two parallel sessions (Config + Auth)
## Overview
After Phase 6's 23 porting sessions, 93 features remain at `stub` status. They fall into two
independent concerns that can be implemented in parallel:
| Group | Go File | Stubs | Go LOC | Concern |
|-------|---------|-------|--------|---------|
| Config | `server/opts.go` | 67 | ~4,876 | Configuration file parsing / binding |
| Auth | `server/auth.go` | 19 | ~1,296 | Authentication dispatch |
| Auth | `server/auth_callout.go` | 3 | ~456 | External auth callout |
| Auth | `server/jwt.go` | 3 | ~137 | Operator JWT validation |
| Signals | `server/signal.go` | 1 | ~46 | OS signal handling |
---
## Session A: Configuration Binding (67 stubs, opts.go)
### Decision
Map all NATS server configuration to **`appsettings.json`** via
`Microsoft.Extensions.Configuration`. The Go `conf` package tokenizer and the 765-line
`processConfigFileLine` dispatch loop are **not ported** — JSON deserialization replaces them.
### New Files
**`Config/ServerOptionsConfiguration.cs`**
```csharp
public static class ServerOptionsConfiguration
{
public static ServerOptions ProcessConfigFile(string path);
public static ServerOptions ProcessConfigString(string json);
public static void BindConfiguration(IConfiguration config, ServerOptions target);
}
```
- `ProcessConfigFile` uses `new ConfigurationBuilder().AddJsonFile(path).Build()`
- `ProcessConfigString` uses `AddJsonStream(new MemoryStream(Encoding.UTF8.GetBytes(json)))`
- `BindConfiguration` calls `config.Bind(target)` with custom converters registered
**`Config/NatsJsonConverters.cs`**
Custom `JsonConverter<T>` for non-trivial types:
| Converter | Input | Output | Mirrors |
|-----------|-------|--------|---------|
| `DurationJsonConverter` | `"2s"`, `"100ms"`, `"1h30m"` | `TimeSpan` | `parseDuration` |
| `TlsVersionJsonConverter` | `"1.2"`, `"TLS12"` | `SslProtocols` | `parseTLSVersion` |
| `NatsUrlJsonConverter` | `"nats://host:port"` | validated `string` | `parseURL` |
| `StorageSizeJsonConverter` | `"1GB"`, `"512mb"` | `long` (bytes) | `getStorageSize` |
### ServerOptions.cs Changes
Add `[JsonPropertyName("...")]` attributes for fields whose JSON key names differ from C# names.
JSON key names follow NATS server conventions (lowercase, underscore-separated):
```json
{
"port": 4222,
"host": "0.0.0.0",
"tls": { "cert_file": "...", "key_file": "...", "ca_file": "..." },
"cluster": { "port": 6222, "name": "my-cluster" },
"gateway": { "port": 7222, "name": "my-gateway" },
"jetstream": { "store_dir": "/data/jetstream", "max_memory": "1GB" },
"leafnodes": { "port": 7422 },
"mqtt": { "port": 1883 },
"websocket": { "port": 8080 },
"accounts": [ { "name": "A", "users": [ { "user": "u1", "password": "p1" } ] } ]
}
```
### DB Outcome
All 67 opts.go stubs → `complete`:
- Feature IDs 25052574, 2580, 2584 (+ `configureSystemAccount` 2509, `setupUsersAndNKeysDuplicateCheckMap` 2515)
- `parse*` functions have no C# equivalent — their logic is subsumed by converters and JSON binding
---
## Session B: Auth Implementation (26 stubs)
### New Files
**`NatsServer.Auth.cs`** — `partial class NatsServer` with:
| Method | Go Equivalent | Notes |
|--------|--------------|-------|
| `ConfigureAuthorization()` | `configureAuthorization` | Builds `_nkeys`/`_users` dicts from `_opts` |
| `BuildNkeysAndUsersFromOptions()` | `buildNkeysAndUsersFromOptions` | Creates typed lookup maps |
| `CheckAuthforWarnings()` | `checkAuthforWarnings` | Validates auth config consistency |
| `AssignGlobalAccountToOrphanUsers()` | `assignGlobalAccountToOrphanUsers` | — |
| `CheckAuthentication(ClientConnection)` | `checkAuthentication` | Entry point |
| `IsClientAuthorized(ClientConnection)` | `isClientAuthorized` | Check user credentials |
| `ProcessClientOrLeafAuthentication(ClientConnection, ServerOptions)` | `processClientOrLeafAuthentication` | Main 554-line auth dispatch |
| `IsRouterAuthorized(ClientConnection)` | `isRouterAuthorized` | Route-specific auth |
| `IsGatewayAuthorized(ClientConnection)` | `isGatewayAuthorized` | Gateway-specific auth |
| `RegisterLeafWithAccount(ClientConnection, string)` | `registerLeafWithAccount` | — |
| `IsLeafNodeAuthorized(ClientConnection)` | `isLeafNodeAuthorized` | Leaf-specific auth |
| `ProcessProxiesTrustedKeys()` | `processProxiesTrustedKeys` | Proxy key setup |
| `ProxyCheck(ClientConnection, ServerOptions)` | `proxyCheck` | Validate proxy headers |
**Auth dispatch flow in `ProcessClientOrLeafAuthentication`:**
```
if callout configured → ProcessClientOrLeafCallout()
else if JWT bearer → JwtProcessor.ValidateAndRegisterUser()
else if NKey → verify NKey signature (NATS.NKeys NuGet)
else if user+password → BCrypt.Net.BCrypt.Verify() (BCrypt.Net-Next NuGet)
else if TLS cert map → CheckClientTlsCertSubject()
else if no-auth mode → allow (if opts.NoAuth)
→ set client account, permissions, labels
```
**`Auth/AuthCallout.cs`** — `partial class NatsServer` with:
- `ProcessClientOrLeafCallout(ClientConnection, ServerOptions)` — publishes to `$SYS.REQ.USER.AUTH`, waits for signed JWT response, validates it
- `FillClientInfo(AuthorizationRequestClaims, ClientConnection)` — populate auth request payload
- `FillConnectOpts(AuthorizationRequestClaims, ClientConnection)` — populate connect opts in payload
**`Auth/JwtProcessor.cs` additions:**
- `ReadOperatorJwt(string path)` — read operator JWT from file, decode `OperatorClaims`
- `ReadOperatorJwtInternal(string jwtString)` — decode from string
- `ValidateTrustedOperators(ServerOptions opts)` — walk operator → account → user signing key chain
**`Auth/AuthHandler.cs` additions:**
- `ProcessUserPermissionsTemplate(UserPermissionLimits, UserClaims, Account)` — expand `{{account}}`, `{{tag.*}}` template variables in JWT user permissions
- `GetTlsAuthDcs(X509DistinguishedName)` — extract DC= components from TLS cert RDN
- `CheckClientTlsCertSubject(ClientConnection, Func<string, bool>)` — TLS cert subject matching
- `ValidateProxies(ServerOptions)` — validate proxy configuration
- `GetAuthErrClosedState(ClientConnection)` — map auth failure to client closed state enum
### New NuGet Packages
| Package | Version | Purpose |
|---------|---------|---------|
| `BCrypt.Net-Next` | ≥4.0 | bcrypt password hashing and comparison |
| `NATS.NKeys` | ≥2.0 | NKey keypair creation, signature verify |
### `NatsServer.Signals.cs`
New partial class file:
```csharp
// Registers OS signal handlers via PosixSignalRegistration (cross-platform).
// SIGHUP → server.Reload()
// SIGTERM → server.Shutdown()
// SIGINT → server.Shutdown()
// Windows fallback: Console.CancelKeyPress → Shutdown()
```
### DB Outcome
All 26 auth/jwt/callout/signal stubs → `complete`:
- Feature IDs 354383, 19731976, 2584, 3156
---
## File Summary
| File | Action |
|------|--------|
| `Config/ServerOptionsConfiguration.cs` | CREATE |
| `Config/NatsJsonConverters.cs` | CREATE |
| `NatsServer.Auth.cs` | CREATE (partial) |
| `NatsServer.Signals.cs` | CREATE (partial) |
| `Auth/AuthCallout.cs` | CREATE (partial) |
| `Auth/JwtProcessor.cs` | MODIFY (add 3 methods) |
| `Auth/AuthHandler.cs` | MODIFY (add 5 methods) |
| `ServerOptions.cs` | MODIFY (add JsonPropertyName attrs) |
| `ZB.MOM.NatsNet.Server.csproj` | MODIFY (add 2 NuGet packages) |
---
## Testing
Unit tests in `ZB.MOM.NatsNet.Server.Tests/`:
- `Config/ServerOptionsConfigurationTests.cs` — round-trip JSON bind tests for each major option group
- `Auth/AuthHandlerTests.cs` additions — bcrypt comparison, NKey verify, TLS cert subject matching
- `Auth/JwtProcessorTests.cs` additions — operator JWT read/validate
No new test IDs needed — these are implementations of already-tracked Phase 6 features.
After implementation, relevant test IDs in Phase 7 will be marked complete.

View File

@@ -1,6 +1,6 @@
# NATS .NET Porting Status Report
Generated: 2026-02-26 21:31:42 UTC
Generated: 2026-02-26 21:54:06 UTC
## Modules (12 total)

38
reports/report_a58e8e2.md Normal file
View File

@@ -0,0 +1,38 @@
# NATS .NET Porting Status Report
Generated: 2026-02-26 21:54:06 UTC
## Modules (12 total)
| Status | Count |
|--------|-------|
| complete | 11 |
| not_started | 1 |
## Features (3673 total)
| Status | Count |
|--------|-------|
| complete | 3503 |
| n_a | 77 |
| stub | 93 |
## Unit Tests (3257 total)
| Status | Count |
|--------|-------|
| complete | 319 |
| n_a | 181 |
| not_started | 2533 |
| stub | 224 |
## Library Mappings (36 total)
| Status | Count |
|--------|-------|
| mapped | 36 |
## Overall Progress
**4091/6942 items complete (58.9%)**