Add gateway implementation planning docs

This commit is contained in:
Joseph Doherty
2026-04-26 15:19:17 -04:00
parent 1d8a6fe3db
commit 81339633d9
25 changed files with 6069 additions and 11 deletions
+76
View File
@@ -0,0 +1,76 @@
# C# Style Guide
This guide defines C# conventions for the gateway, worker, .NET client, test
CLIs, and C# tests.
## Baseline
- Use the latest stable C# version supported by the target runtime.
- Enable nullable reference types in new projects.
- Treat compiler warnings as actionable. Suppress only with a narrow reason.
- Prefer file-scoped namespaces.
- Prefer `sealed` classes unless inheritance is required.
- Keep public APIs explicit and small. Do not expose generated or transport
internals through handwritten abstractions unless raw access is intentional.
## Source Documentation
- Maintain the existing documentation style in the file, project, and
surrounding component.
- Write comments that include business-specific or domain-specific context when
that context is available from the code, surrounding docs, or naming.
- Prefer XML documentation on public APIs when the behavior is not obvious from
the signature.
- Avoid comments that restate syntax or control flow.
## Naming
- Use PascalCase for public types, methods, properties, events, and enum
members.
- Use camelCase for local variables, parameters, and private fields.
- Prefix private fields with `_` only when that pattern is already established
in the project.
- Use `Async` suffixes for methods that return `Task`, `Task<T>`,
`ValueTask`, or `ValueTask<T>`.
- Keep names aligned with MXAccess terms: `MxStatusProxy`, `ServerHandle`,
`ItemHandle`, `HResult`, and event family names should match the contract.
## Async And Cancellation
- Accept `CancellationToken` on public async methods that perform I/O or wait.
- Pass cancellation tokens through to called APIs.
- Do not use `Task.Run` to hide blocking COM calls. MXAccess calls belong on
the worker STA.
- Use `ConfigureAwait(false)` in reusable libraries. It is optional in ASP.NET
Core request handling where no synchronization context exists.
- Dispose async resources with `await using` when the type implements
`IAsyncDisposable`.
## Errors
- Preserve protocol, gateway, worker, COM HRESULT, and MXAccess status details.
- Use typed exceptions at API boundaries, but prefer result DTOs when callers
need method-specific MXAccess output.
- Do not log API keys, passwords, secured write values, or full tag values by
default.
- Include correlation id and session id in diagnostics when available.
## Protobuf And Generated Code
- Do not hand-edit generated protobuf or gRPC files.
- Keep generated code in a clearly named `Generated` namespace or directory.
- Keep mapping code outside gRPC handlers so it can be unit tested.
## Formatting
- Run `dotnet format` when a solution or project is available.
- Use four spaces for indentation.
- Keep one public type per file unless a small nested type is clearer.
- Avoid region-heavy files. Split large responsibilities into focused types.
## Tests
- Use test names that describe behavior, condition, and result.
- Prefer fake workers, fake transports, or fake gRPC services over live
MXAccess in unit tests.
- Mark live MXAccess tests as opt-in integration tests.
+68
View File
@@ -0,0 +1,68 @@
# Go Style Guide
This guide defines Go conventions for the MXAccess Gateway Go client module,
test CLI, and tests.
## Baseline
- Use idiomatic Go and keep package APIs small.
- Run `gofmt` on every changed Go file.
- Run `go vet` for non-trivial changes when the module is available.
- Keep generated protobuf code under `internal/generated` unless the public API
intentionally exposes it.
## Source Documentation
- Maintain the existing documentation style in the file, package, and
surrounding component.
- Write comments that include business-specific or domain-specific context when
that context is available from the code, surrounding docs, or naming.
- Document exported names when they are part of the public client API.
- Avoid comments that restate syntax or control flow.
## Packages
- Use short, lowercase package names without underscores.
- Keep the reusable library separate from CLI code.
- Keep generated code separate from handwritten wrappers.
- Prefer internal packages for implementation details that callers should not
import.
## Naming
- Use exported names only for public API.
- Use initialisms consistently: `APIKey`, `TLS`, `HTTP`, `ID`.
- Keep MXAccess terms explicit: `ServerHandle`, `ItemHandle`, `MxStatusProxy`,
and `HResult`.
- Avoid generic helper names such as `Do` or `Process` for command-specific
MXAccess behavior.
## Context And Cancellation
- Accept `context.Context` as the first parameter for operations that can block.
- Do not store contexts in structs.
- Respect context cancellation, but document that canceling a client call does
not abort an in-flight worker COM call.
- Close streams and connections deterministically.
## Errors
- Return errors instead of panicking.
- Wrap errors with useful context using `%w`.
- Support `errors.Is` and `errors.As` for typed gateway, command, and MXAccess
errors.
- Preserve raw command replies on command errors when available.
- Redact API keys and credential-bearing values in error messages.
## Concurrency
- Avoid unbounded goroutines and unbounded channels.
- Close channels exactly once from the sending side.
- Propagate stream errors through explicit result types such as `EventResult`.
- Use the race detector for concurrency-heavy changes when practical.
## Tests
- Use table-driven tests for conversion and error mapping.
- Use `bufconn` or fake generated clients for unit tests.
- Keep integration tests behind `MXGATEWAY_INTEGRATION=1` or build tags.
+65
View File
@@ -0,0 +1,65 @@
# Java Style Guide
This guide defines Java conventions for the MXAccess Gateway Java client
library, CLI, and tests.
## Baseline
- Target the Java version defined by the client build, with Java 21 preferred.
- Use Gradle unless the repository standardizes on Maven.
- Apply a formatter such as Spotless or Google Java Format when configured.
- Keep generated protobuf code separate from handwritten wrappers.
## Source Documentation
- Maintain the existing documentation style in the file, package, and
surrounding component.
- Write comments that include business-specific or domain-specific context when
that context is available from the code, surrounding docs, or naming.
- Use Javadoc for public APIs when behavior, parity constraints, or security
requirements are not obvious from the signature.
- Avoid comments that restate syntax or control flow.
## Packages
- Use lowercase package names under `com.dohertylan.mxgateway`.
- Keep client library code separate from CLI code.
- Keep generated protobuf classes in a generated package.
- Do not expose implementation-only transport helpers as public API.
## Naming
- Use `PascalCase` for classes, records, interfaces, and enums.
- Use `camelCase` for methods, fields, parameters, and local variables.
- Use `UPPER_SNAKE_CASE` for constants.
- Use MXAccess terms consistently: `serverHandle`, `itemHandle`,
`mxStatusProxy`, and `hResult`.
## API Design
- Prefer immutable options objects with builders for public configuration.
- Implement `AutoCloseable` for clients and sessions that own resources.
- Provide async methods with `CompletableFuture` where useful, but keep a
blocking API for simple CLI workflows.
- Expose raw generated protobuf messages where parity tests need them.
## Errors
- Use typed exceptions for gateway, authentication, authorization, session,
worker, command, and MXAccess failures.
- Preserve raw command replies in command exceptions when available.
- Redact API keys, passwords, and secured write values in `toString`, logs, and
CLI output.
## Streaming
- Cancel gRPC calls explicitly when callers stop consuming streams.
- Do not reorder, coalesce, or drop events in client code.
- Avoid unbounded queues in async stream helpers.
## Tests
- Use JUnit 5.
- Use in-process gRPC servers for unit tests.
- Keep live gateway tests behind `MXGATEWAY_INTEGRATION=1` and JUnit
assumptions.
+64
View File
@@ -0,0 +1,64 @@
# Protobuf Style Guide
This guide defines protobuf conventions for MXAccess Gateway public gRPC and
gateway-to-worker IPC contracts.
## Baseline
- Use `proto3`.
- Keep public gateway contracts and worker IPC contracts in separate `.proto`
files.
- Treat field numbers as permanent once released.
- Do not reuse removed field numbers or enum values. Reserve them.
- Keep generated code reproducible from checked-in `.proto` files.
## Source Documentation
- Maintain the existing documentation style in the `.proto` file and
surrounding contract docs.
- Write comments that include business-specific or domain-specific context when
that context is available from the contract, surrounding docs, or naming.
- Comment fields that carry MXAccess parity details, credential-sensitive data,
raw HRESULT/status information, or compatibility constraints.
- Avoid comments that restate field types or message nesting.
## Naming
- Use `snake_case` for package names, file names, field names, and enum values.
- Use `PascalCase` for message, enum, and service names.
- Prefix enum values with the enum name or a clear abbreviation to avoid name
collisions in generated languages.
- Keep MXAccess event family and command names recognizable in enum values.
## Compatibility
- Add fields instead of changing field meaning.
- Use `oneof` for command payloads, reply payloads, value unions, and event
bodies.
- Add explicit `UNKNOWN` or `UNSPECIFIED` enum zero values.
- Preserve raw HRESULT, MXAccess status, and diagnostic metadata in replies and
events.
- Use protocol version fields in worker IPC envelopes.
## Field Rules
- Do not use required semantics in application code for newly added optional
fields unless compatibility behavior is documented.
- Prefer explicit wrapper messages for repeated structured values.
- Use signed or unsigned integer types based on the actual semantic range.
- Represent timestamps with `google.protobuf.Timestamp` unless the source value
is not a real timestamp.
- Represent durations with `google.protobuf.Duration`.
## Security
- Do not define fields that require clients or workers to log secrets.
- Mark credential-bearing request fields clearly in comments.
- Keep raw values out of diagnostics unless an explicit redacted or opt-in path
exists.
## Generated Code
- Do not hand-edit generated code.
- Keep generation commands documented near the contracts project.
- Regenerate all affected language outputs when a contract changes.
+68
View File
@@ -0,0 +1,68 @@
# Python Style Guide
This guide defines Python conventions for the MXAccess Gateway Python package,
CLI, and tests.
## Baseline
- Target modern supported Python versions defined by `pyproject.toml`.
- Use `pyproject.toml` for package metadata and tool configuration.
- Use type hints for public APIs and non-trivial internal functions.
- Run the configured formatter and linter when the package is available.
- Keep generated protobuf code separate from handwritten modules.
## Source Documentation
- Maintain the existing documentation style in the file, package, and
surrounding component.
- Write comments that include business-specific or domain-specific context when
that context is available from the code, surrounding docs, or naming.
- Use docstrings for public classes, functions, and modules when behavior,
parity constraints, or security requirements are not obvious from the name and
type hints.
- Avoid comments that restate syntax or control flow.
## Package Structure
- Put library code under `src/mxgateway/`.
- Put CLI entry points under `src/mxgateway_cli/`.
- Keep generated protobuf modules under a clearly named `generated` package.
- Avoid import side effects that open channels, read environment variables, or
start background tasks.
## Naming
- Use `snake_case` for functions, variables, modules, and methods.
- Use `PascalCase` for classes and exceptions.
- Use `UPPER_SNAKE_CASE` for constants.
- Keep MXAccess names recognizable in public APIs, even when Python wrappers
use idiomatic method names.
## Async
- Make the client async-first.
- Use async context managers for clients and sessions when practical.
- Cancel gRPC streams when async iteration is canceled.
- Document that canceling a Python task does not abort an in-flight MXAccess
COM call inside the worker.
## Errors
- Use typed exceptions for transport, authentication, authorization, session,
worker, command, and MXAccess failures.
- Attach raw protobuf replies to command exceptions when available.
- Redact API keys, passwords, and secured write values in exception messages and
CLI output.
## CLI
- Keep CLI output deterministic for tests.
- Support JSON output for automation.
- Load API keys from explicit flags or named environment variables. Do not read
secrets implicitly during module import.
## Tests
- Use `pytest` and `pytest-asyncio`.
- Use fake generated stubs or an in-process test gRPC server for unit tests.
- Keep live integration tests behind `MXGATEWAY_INTEGRATION=1`.
+65
View File
@@ -0,0 +1,65 @@
# Rust Style Guide
This guide defines Rust conventions for the MXAccess Gateway Rust client crate,
CLI, and tests.
## Baseline
- Run `cargo fmt` on every changed Rust file.
- Run `cargo clippy` for non-trivial changes when the crate is available.
- Use the current stable Rust toolchain unless the project pins a version.
- Keep generated protobuf modules isolated from handwritten API wrappers.
## Source Documentation
- Maintain the existing documentation style in the file, crate, and surrounding
component.
- Write comments that include business-specific or domain-specific context when
that context is available from the code, surrounding docs, or naming.
- Use `///` documentation for public APIs when behavior, parity constraints, or
security requirements are not obvious from the type signature.
- Avoid comments that restate syntax or control flow.
## Crate Structure
- Keep the reusable client library separate from the CLI binary.
- Use small modules for `client`, `session`, `options`, `auth`, `value`, and
`error`.
- Re-export public types intentionally from `lib.rs`.
- Keep generated modules private unless raw protobuf access is part of the API.
## Naming
- Use `snake_case` for functions, variables, modules, and fields.
- Use `UpperCamelCase` for types, traits, and enum variants.
- Use `SCREAMING_SNAKE_CASE` for constants.
- Keep protocol names aligned with the protobuf contract where exactness
matters.
## Async And Ownership
- Use `async` APIs with `tokio` for network operations.
- Prefer explicit `close` methods for sessions. Do not rely on `Drop` for async
cleanup.
- Avoid unbounded channels and background tasks without a shutdown path.
- Use borrowed parameters such as `&str` where ownership is not needed.
## Errors
- Use `thiserror` for library error enums.
- Preserve `tonic::Status`, transport errors, command replies, HRESULTs, and
MXAccess status details.
- Redact API keys and secured values in `Debug`, `Display`, and tracing output.
- Avoid string-only errors for public API failures.
## Security
- Use a secret wrapper for API keys when adding a dependency is acceptable.
- Do not derive `Debug` on types that contain unredacted secrets.
- Prefer explicit redacted display implementations for options and errors.
## Tests
- Use `#[tokio::test]` for async tests.
- Use fake `tonic` services or trait-backed clients for unit tests.
- Keep live gateway tests behind `MXGATEWAY_INTEGRATION=1`.