diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 84b9ebe..767de06 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -20,12 +20,11 @@ dotnet format tests/BinaryLane.Api.Tests/BinaryLane.Api.Tests.csproj --verify-no dotnet format examples/BinaryLane.Api.Demo/BinaryLane.Api.Demo.csproj --verify-no-changes --no-restore ``` -Run these commands sequentially. Do not run separate restore, build, test, or -pack commands concurrently on the same checkout. +Run these commands one at a time. The serial options keep local build resource +use predictable on a shared checkout. -The tracked demo application lives in -`examples/BinaryLane.Api.Demo`. Configure a personal API token with user -secrets; never put it in a file, test fixture, issue, pull request, or commit. +The tracked demo application lives in `examples/BinaryLane.Api.Demo`. It reads +`BinaryLane:ApiToken` from its configuration providers, including user secrets. ```bash dotnet user-secrets set \ diff --git a/README.md b/README.md index e9edf84..8cabf1f 100644 --- a/README.md +++ b/README.md @@ -10,8 +10,8 @@ balancers, VPCs, and other v2 resources. See the [BinaryLane API reference](https://api.binarylane.com.au/reference/) for provider-specific API behaviour. -BinaryLane describes its API as a developer preview. Pin the package version -used by production applications and review release notes before upgrading. +BinaryLane describes its API as a developer preview. SDK releases track the +committed upstream contract independently of the provider's reference version. > This project is not affiliated with, endorsed by, or supported by BinaryLane. > For account or infrastructure support, use @@ -27,8 +27,8 @@ Remove `--prerelease` once a stable package version is available. ## Quick start -Keep the API token in a secret store, user secrets, or an environment variable. -Do not commit it to configuration or source control. +The registration below reads `BinaryLane:ApiToken` from application +configuration and otherwise uses `BINARYLANE_API_TOKEN`. ```csharp using BinaryLane.Api.V2; @@ -65,8 +65,7 @@ static async Task ListServersAsync( } ``` -List methods support `CancellationToken`. Mutating calls are sent once; add a -retry policy only when the operation is known to be safe to repeat. +All asynchronous resource methods accept a `CancellationToken`. ## Documentation @@ -76,7 +75,7 @@ retry policy only when the operation is known to be safe to repeat. | [Configuration](https://github.com/alexhopeoconnor/binarylane-dotnet/blob/main/docs/configuration.md) | Tokens, timeouts, direct construction, and HTTP configuration. | | [Pagination](https://github.com/alexhopeoconnor/binarylane-dotnet/blob/main/docs/pagination.md) | Working with pages or async enumeration. | | [Actions](https://github.com/alexhopeoconnor/binarylane-dotnet/blob/main/docs/actions-and-polling.md) | Submitting and optionally waiting for server actions. | -| [Error handling](https://github.com/alexhopeoconnor/binarylane-dotnet/blob/main/docs/errors.md) | Handling API failures safely. | +| [Error handling](https://github.com/alexhopeoconnor/binarylane-dotnet/blob/main/docs/errors.md) | HTTP exceptions and diagnostic information. | | [Demo](https://github.com/alexhopeoconnor/binarylane-dotnet/tree/main/examples/BinaryLane.Api.Demo) | Running the included read-only console app. | ## Compatibility diff --git a/docs/actions-and-polling.md b/docs/actions-and-polling.md index a51ff45..b790efe 100644 --- a/docs/actions-and-polling.md +++ b/docs/actions-and-polling.md @@ -43,6 +43,3 @@ if (action.Status == BinaryLaneValues.ActionStatus.Completed) // Continue with the next step. } ``` - -If an action request has an uncertain outcome, retrieve the action or server -state before submitting it again. diff --git a/docs/api-coverage.md b/docs/api-coverage.md index f816ba9..e4b8fa3 100644 --- a/docs/api-coverage.md +++ b/docs/api-coverage.md @@ -10,8 +10,8 @@ version change. The raw document contains virtual paths such as `/v2/servers/{server_id}/actions#PowerOn`. These are API-reference aliases for -action payload variants, not real HTTP routes. Coverage and generated-code -checks must use the normalized contract and count only the real +action payload variants, not real HTTP routes. Coverage checks and route +reviews use the normalized contract and count only the real `POST /v2/servers/{server_id}/actions` route. | API area | Public resource boundary | diff --git a/docs/configuration.md b/docs/configuration.md index 73c2aa1..4432909 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -3,24 +3,25 @@ ## Standard registration In an ASP.NET Core or generic-host application, `AddBinaryLaneApi` configures -`IBinaryLaneClient` and the individual resource interfaces. +`IBinaryLaneClient`, individual resource interfaces, and the underlying typed +`HttpClient`. ```csharp builder.Services.AddBinaryLaneApi(options => { options.ApiToken = builder.Configuration["BinaryLane:ApiToken"]; - options.RequestTimeoutSeconds = 100; }); ``` | Setting | Default | Description | | --- | --- | --- | -| `BaseUrl` | `https://api.binarylane.com.au/` | API base address. Leave unchanged for BinaryLane's public API. | +| `BaseUrl` | `https://api.binarylane.com.au/` | Root URI used for API requests. | | `ApiToken` | none | Bearer token used by the default provider. | | `RequestTimeoutSeconds` | `100` | Timeout for an individual HTTP request. | -The base URL must be an HTTPS URL without credentials, a query string, or a -fragment. Options are validated when the application starts. +`BaseUrl` must be an HTTPS URL without credentials, a query string, or a +fragment. `BaseUrl` and `RequestTimeoutSeconds` are validated when the host +starts; request timeouts can range from 1 to 300 seconds. ## Rotating tokens @@ -36,7 +37,7 @@ builder.Services.AddSingleton(); builder.Services.AddBinaryLaneApi(options => options.RequestTimeoutSeconds = 100); ``` -The provider is called for every request. Do not log the returned token. +The provider is called for every outgoing request. ## Use without dependency injection @@ -63,10 +64,10 @@ var client = new BinaryLaneClient( telemetry, or other application-specific handlers. ```csharp -builder.Services.AddBinaryLaneApi(options => options.ApiToken = token) +builder.Services.AddBinaryLaneApi(options => + options.ApiToken = builder.Configuration["BinaryLane:ApiToken"]) .ConfigureHttpClient(client => client.DefaultRequestHeaders.Add("X-App", "my-service")); ``` -Only add automatic retries when the request is safe to repeat. In particular, -POST, PUT, PATCH, and DELETE requests may have already been applied when a -network failure is reported. +The client does not apply retries itself. Applications can add their own +handlers through the returned `IHttpClientBuilder`. diff --git a/docs/errors.md b/docs/errors.md index 01b4d6c..1f41cae 100644 --- a/docs/errors.md +++ b/docs/errors.md @@ -1,13 +1,15 @@ # Error handling -All API failures derive from `BinaryLaneApiException`. +`BinaryLaneApiException` represents a non-success response from the BinaryLane +API. Network, timeout, cancellation, and client-configuration failures use +their standard .NET exception types. | Exception | When it is used | | --- | --- | -| `BinaryLaneUnauthorizedException` | The token is missing, invalid, or expired. | -| `BinaryLaneForbiddenException` | The token does not have access to the resource. | -| `BinaryLaneNotFoundException` | The requested resource does not exist or is not visible to the token. | -| `BinaryLaneValidationException` | BinaryLane rejected the request payload. | +| `BinaryLaneUnauthorizedException` | BinaryLane returned HTTP 401. | +| `BinaryLaneForbiddenException` | BinaryLane returned HTTP 403. | +| `BinaryLaneNotFoundException` | BinaryLane returned HTTP 404. | +| `BinaryLaneValidationException` | BinaryLane returned HTTP 400 or 422. | | `BinaryLaneApiException` | Any other non-success HTTP response. | ```csharp @@ -32,9 +34,9 @@ catch (BinaryLaneApiException exception) ``` Each exception provides `StatusCode`, `RequestUri`, `Headers`, and, when -available, `Problem` and `ResponseBody`. Provider detail text can contain user -data. Do not write `Problem`, `Headers`, or `ResponseBody` to application logs -without appropriate redaction. +available, `Problem` and `ResponseBody`. `ResponseBody` contains at most the +first 32,768 characters of diagnostic text, followed by an ellipsis when +truncated. -Successful JSON responses are limited to 16 MiB. A larger response throws +Successful response bodies are limited to 16 MiB. A larger response throws `HttpRequestException` before the client buffers it in memory. diff --git a/docs/getting-started.md b/docs/getting-started.md index ea3516d..9ef5512 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -9,25 +9,24 @@ dotnet add package BinaryLane.Api --prerelease ``` -## 2. Store the token safely +## 2. Configure the API token -For local development, initialise user secrets for your application and add -the token: +For local development, .NET user secrets can provide the +`BinaryLane:ApiToken` configuration value: ```bash dotnet user-secrets init dotnet user-secrets set "BinaryLane:ApiToken" "your-token" ``` -For hosted applications, use the platform's secret store or supply -`BINARYLANE_API_TOKEN` at runtime. +The registration below reads that value first, then falls back to +`BINARYLANE_API_TOKEN`. ## 3. Register the client ```csharp using BinaryLane.Api.V2; using BinaryLane.Api.V2.DependencyInjection; -using BinaryLane.Api.V2.Models; builder.Services.AddBinaryLaneApi(options => { @@ -42,6 +41,9 @@ builder.Services.AddBinaryLaneApi(options => Inject `IBinaryLaneClient`, then select the resource you need: ```csharp +using BinaryLane.Api.V2; +using BinaryLane.Api.V2.Models; + public sealed class ServerReader(IBinaryLaneClient binaryLane) { public IAsyncEnumerable ListAsync(CancellationToken cancellationToken) => diff --git a/docs/pagination.md b/docs/pagination.md index 068ef41..157c526 100644 --- a/docs/pagination.md +++ b/docs/pagination.md @@ -27,5 +27,4 @@ await foreach (var server in client.Servers.ListAllAsync(cancellationToken: canc } ``` -Pass a cancellation token from the calling request, worker, or command so a -stopped operation does not continue fetching pages. +The cancellation token is carried across page requests made by `ListAllAsync`. diff --git a/docs/releasing.md b/docs/releasing.md index 2599b83..304f140 100644 --- a/docs/releasing.md +++ b/docs/releasing.md @@ -57,7 +57,8 @@ section for release notes. ## Recovery -NuGet packages cannot be overwritten. If a release has a packaging defect, -unlist it if appropriate, publish a new version, and document the correction -in the changelog. Do not retag a version or attempt to reuse a published -package version. +NuGet packages cannot be overwritten. If a published release has a packaging +defect, unlist it if appropriate, publish a new version, and document the +correction in the changelog. A tag can be replaced only before the workflow +publishes its matching NuGet version; published package versions are never +reused. diff --git a/docs/upstream-contract.md b/docs/upstream-contract.md index 62fe376..47d723f 100644 --- a/docs/upstream-contract.md +++ b/docs/upstream-contract.md @@ -28,8 +28,7 @@ snapshot makes those changes visible during SDK maintenance. The raw document includes virtual `#ActionName` paths for individual server action variants. They exist to improve the provider's reference UI but are not HTTP paths. `eng/normalize-openapi.sh` strips them when producing a normalized -document for code generation or coverage checks. Do not issue requests to -those virtual paths. +document for route and coverage validation. ## Monitoring and updating diff --git a/examples/BinaryLane.Api.Demo/Program.cs b/examples/BinaryLane.Api.Demo/Program.cs index 27db7fb..a5e3575 100644 --- a/examples/BinaryLane.Api.Demo/Program.cs +++ b/examples/BinaryLane.Api.Demo/Program.cs @@ -44,7 +44,7 @@ internal static class DemoProgram { Console.Error.WriteLine( "No API token is configured. Use user secrets or set BINARYLANE_API_TOKEN. " - + "Run with --help for a safe setup command."); + + "Run with --help for a setup command."); return 2; } @@ -104,8 +104,7 @@ internal static class DemoProgram } catch (BinaryLaneApiException exception) { - // Provider details may contain user data. Do not print Problem, headers, - // or ResponseBody in a sample application. + // The sample prints the response status and path only. Console.Error.WriteLine( $"BinaryLane request failed with HTTP {(int)exception.StatusCode} " + $"({exception.StatusCode}) at {exception.RequestUri.AbsolutePath}."); @@ -160,8 +159,7 @@ internal static class DemoProgram server regions - You can also set BINARYLANE_API_TOKEN for one process. Never commit - a token or add it to appsettings.json. + You can also set BINARYLANE_API_TOKEN for one process. """); } } diff --git a/examples/BinaryLane.Api.Demo/README.md b/examples/BinaryLane.Api.Demo/README.md index fac778b..f7df107 100644 --- a/examples/BinaryLane.Api.Demo/README.md +++ b/examples/BinaryLane.Api.Demo/README.md @@ -13,8 +13,7 @@ dotnet user-secrets set \ --project examples/BinaryLane.Api.Demo ``` -Alternatively, set `BINARYLANE_API_TOKEN` for one process. Do not add a token -to `appsettings.json`. +Alternatively, start the process with `BINARYLANE_API_TOKEN` set. ## Run it diff --git a/src/BinaryLane.Api/Configuration/BinaryLaneOptions.cs b/src/BinaryLane.Api/Configuration/BinaryLaneOptions.cs index 218f31d..f8cee72 100644 --- a/src/BinaryLane.Api/Configuration/BinaryLaneOptions.cs +++ b/src/BinaryLane.Api/Configuration/BinaryLaneOptions.cs @@ -11,10 +11,7 @@ public sealed class BinaryLaneOptions /// The BinaryLane API root URL. public string BaseUrl { get; set; } = "https://api.binarylane.com.au/"; - /// - /// The bearer token to use when the default token provider is registered. Prefer a secret store, - /// user secrets, or environment-variable based configuration rather than committing this value. - /// + /// The bearer token used by the default token provider. public string? ApiToken { get; set; } /// Timeout applied to individual HTTP requests. diff --git a/src/BinaryLane.Api/DependencyInjection/ServiceCollectionExtensions.cs b/src/BinaryLane.Api/DependencyInjection/ServiceCollectionExtensions.cs index cd94fdd..816c17d 100644 --- a/src/BinaryLane.Api/DependencyInjection/ServiceCollectionExtensions.cs +++ b/src/BinaryLane.Api/DependencyInjection/ServiceCollectionExtensions.cs @@ -13,8 +13,8 @@ namespace BinaryLane.Api.V2.DependencyInjection; public static class ServiceCollectionExtensions { /// - /// Registers a typed BinaryLane client. The returned builder lets an application compose its - /// own proxy, telemetry, and safe GET-only resilience handlers. + /// Registers a typed BinaryLane client. The returned builder supports application-specific + /// HTTP client configuration. /// public static IHttpClientBuilder AddBinaryLaneApi( this IServiceCollection services, diff --git a/src/BinaryLane.Api/Errors/BinaryLaneApiException.cs b/src/BinaryLane.Api/Errors/BinaryLaneApiException.cs index 9353c48..5ef44e4 100644 --- a/src/BinaryLane.Api/Errors/BinaryLaneApiException.cs +++ b/src/BinaryLane.Api/Errors/BinaryLaneApiException.cs @@ -32,10 +32,7 @@ public class BinaryLaneApiException : Exception /// Structured problem details, when BinaryLane supplied them. public BinaryLaneApiProblem? Problem { get; } - /// - /// Bounded raw response text for diagnostics. It omits request headers, but can contain - /// provider-supplied or user-provided data; avoid logging it indiscriminately. - /// + /// Bounded raw response text for diagnostics. public string? ResponseBody { get; } /// Response and content headers.