docs: design for completing 93 stub features (config binding + auth implementation)
This commit is contained in:
185
docs/plans/2026-02-26-stub-features-design.md
Normal file
185
docs/plans/2026-02-26-stub-features-design.md
Normal 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 2505–2574, 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 354–383, 1973–1976, 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.
|
||||
@@ -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
38
reports/report_a58e8e2.md
Normal 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%)**
|
||||
Reference in New Issue
Block a user