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
15 changes: 15 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,21 @@ the version on nuget.org, which is why it trails `VERSION` between releases rath

### Changed

- **Automatic redirects on Ashlar HTTP clients are followed by Ashlar, one hop at a time (SPEC-007 PR 4.3).**
Still report-only: `EgressDecision.Refused` stays false and a decision does not stop a send. On every
`HttpClientHandler` or `SocketsHttpHandler` Ashlar builds or binds, `AllowAutoRedirect` reads false. The
per-hop behaviour is Ashlar's follower, using the primary's own previous settings (whether it followed, and
its maximum): a relative `Location` is resolved and keeps the fragment; HTTPS to HTTP and any scheme other
than http or https is returned; 301, 302 and 303 on POST become GET and drop the content (303 keeps HEAD);
307 and 308 keep the method and content; `Authorization` is cleared on a followed redirect. An `EgressHttp`
client follows only a same-host redirect (P2) and returns a cross-host 3xx without requesting the second
host. Every factory client follows a cross-host redirect and each hop is evaluated again (P1). A primary
type Ashlar cannot flip is left alone; if the response URI's authority is not the one evaluated before the
send, that authority is evaluated after the response and a warning says the body may already have gone.
The SNS signing clients (`ashlar-sns-signing` on the API host and the commercial fleet host) set
`AllowAutoRedirect` false on the existing primary and do not follow. The Bedrock runtime client sets
`AmazonBedrockRuntimeConfig.AllowAutoRedirect` false; the SDK still owns that HTTP stack, so a redirect it
followed anyway is not re-evaluated inside the SDK. The default MEAI Ollama client is unchanged from PR 4.1.
- **AirGapped stays on local execution, and AirGapped and SecureWorkstation inbound listeners must bind loopback (SPEC-007 PR 4.10).**
The egress guard is still report-only. Responses on inbound connections are not mediated until PR 5's CanRead
at the server seams. What this release enforces at boot and at routing:
Expand Down
9 changes: 8 additions & 1 deletion application/src/Ashlar.API/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,14 @@
builder.Services.AddSingleton<ITool, RepoFsListTool>();

builder.Services.AddSingleton<IAshlarIngressAccessor, HttpAshlarIngressAccessor>();
builder.Services.AddHttpClient("ashlar-sns-signing", c => c.Timeout = TimeSpan.FromSeconds(15));
builder.Services.AddHttpClient("ashlar-sns-signing", c => c.Timeout = TimeSpan.FromSeconds(15))
.ConfigurePrimaryHttpMessageHandler(static (handler, _) =>
{
if (handler is HttpClientHandler httpClientHandler)
httpClientHandler.AllowAutoRedirect = false;
else if (handler is SocketsHttpHandler socketsHttpHandler)
socketsHttpHandler.AllowAutoRedirect = false;
});
builder.Services.AddSingleton<ISnsSignatureVerifier, SnsRsaSignatureVerifier>();
builder.Services.AddRateLimiter(static o =>
{
Expand Down
8 changes: 4 additions & 4 deletions ci/cert-gate-assertions.md

Large diffs are not rendered by default.

10 changes: 5 additions & 5 deletions ci/egress-inventory.tsv
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
# ids: EG-... rows of docs/EgressInventory.md, comma-separated, or -. F1, F2 and F3 print the observed rows in this form when they fail.
application/src/Ashlar.API/Endpoints/IdeEndpoints.cs http.new 1 1 Wrapped - EG-MDL-14 IDE tags endpoint: the fallback client when no IHttpClientFactory is registered, built by EgressHttp.CreateClient (:193)
application/src/Ashlar.API/Middleware/Ingress/AwsSnsSmsWebhook.cs http.param 1 0 - Factory EG-HTTP-03 SNS confirm/verify helper (:107) is called only with the ashlar-sns-signing factory client (:72)
application/src/Ashlar.API/Program.cs http.register 1 1 Factory - EG-HTTP-03 named client ashlar-sns-signing (:171); AddAshlarEgressGuard follows AddAshlar in the same top-level block (:232)
application/src/Ashlar.API/Program.cs http.register 1 1 Factory - EG-HTTP-03 named client ashlar-sns-signing (:171); AddAshlarEgressGuard follows AddAshlar in the same top-level block (:239)
application/src/Ashlar.API/Program.cs telemetry 2 2 Precedes - EG-TEL-01 OTLP metrics and traces exporters (:252, :259); the EG-TEL-01 guard opens their block (:247), decided once at registration
application/src/Ashlar.CLI/Commands/BackgroundAgent/MeshAutoPullService.cs http.new 2 2 Wrapped - EG-MESH-04 static mTLS SocketsHttpHandler (:57), handed to EgressHttp.CreateClient for the pull client (:72)
application/src/Ashlar.CLI/Commands/BackgroundAgent/MeshAutoPullService.cs http.param 1 0 - Upstream:application/src/Ashlar.CLI/Commands/BackgroundAgent/MeshAutoPullService.cs EG-MESH-04 PullPeerOnceAsync takes the static EgressHttp pull client; its only production call is in this file (:166)
Expand All @@ -31,15 +31,15 @@ application/src/Ashlar.CLI/Commands/TestPortableCommand.cs process 4 0 - Exempt:
application/src/Ashlar.CLI/Commands/WorkflowCommand.cs http.new 1 1 Wrapped - EG-HTTP-05 orchestrate client to discovered mesh peers, built by EgressHttp.CreateClient (:535)
application/src/Ashlar.CLI/Commands/WorkflowCommand.cs process 2 0 - Exempt:Operator EG-PROC-04 ollama pull for a workflow's model (:337-339)
commercial/src/Ashlar.Commercial.Fleet.Api/CommercialFleetEndpoints.cs door 1 0 - Exempt:Inbound EG-SRV-06 task-result download response (Results.File :499), a read-side decision
commercial/src/Ashlar.Commercial.Fleet.Host/Program.cs http.register 1 1 Factory - EG-HTTP-03 named client ashlar-sns-signing (:79); AddAshlarEgressGuard follows AddAshlar in the same top-level block (:131)
commercial/src/Ashlar.Commercial.Fleet.Host/Program.cs http.register 1 1 Factory - EG-HTTP-03 named client ashlar-sns-signing (:79); AddAshlarEgressGuard follows AddAshlar in the same top-level block (:138)
commercial/src/Ashlar.Commercial.Fleet.Infrastructure/FleetServiceCollectionExtensions.cs http.register 1 0 - Upstream:commercial/src/Ashlar.Commercial.Fleet.Host/Program.cs EG-EXE-05,EG-LAT-01,EG-LAT-04 MeshLab worker client (:116); the Fleet's factory also serves the knowledge-sync, network-bus and peer-pull clients; this project cannot reach Ashlar.Infrastructure, and Fleet.Host, the one executable that composes it, installs the guard
commercial/src/Ashlar.Commercial.Fleet.Infrastructure/MeshLab/MeshLabWorkerExecutorClient.cs http.param 3 0 - Factory EG-EXE-05 commercial copy: director and peer calls take the named factory client
commercial/src/Ashlar.Commercial.MeshDirector/MeshDirectorCommand.cs http.new 1 1 Wrapped - EG-HTTP-07 mesh director fleet client, built by EgressHttp.CreateClient (:415)
src/Ashlar.AI.Pipeline/Clients/AwsBedrockChatClientFactory.cs sdk.client 3 0 - Governance EG-MDL-02 AmazonBedrockRuntimeClient (:39, :40) and AsIChatClient (:42); the SDK owns the HTTP; reached only through the governed cloud:bedrock registration, whose outermost layer is EgressGuardChatClient
src/Ashlar.AI.Pipeline/Clients/AwsBedrockChatClientFactory.cs sdk.client 3 0 - Governance EG-MDL-02 AmazonBedrockRuntimeClient (:40, :41) and AsIChatClient (:47); AllowAutoRedirect false on AmazonBedrockRuntimeConfig (SPEC-007 PR 4.3); the SDK owns the HTTP; reached only through the governed cloud:bedrock registration, whose outermost layer is EgressGuardChatClient
src/Ashlar.AI.Pipeline/Clients/OllamaHttpChatClient.cs http.new 2 0 - Governance EG-MDL-01 default client to the resolved Ollama base URL and its HttpClientHandler with AllowAutoRedirect off (:170, SPEC-007 PR 4.1); reached only through the governed local:ollama registration, whose outermost layer is EgressGuardChatClient
src/Ashlar.AI.Pipeline/Clients/OllamaHttpChatClient.cs http.param 1 0 - Governance EG-MDL-01 constructor taking a caller's client (:34); built only inside the governed registrations F5 holds
src/Ashlar.AI.Pipeline/MeaiPipelineServiceCollectionExtensions.cs chat.register 7 0 - Governance EG-MDL-01,EG-MDL-02 keyed ollama/onnx/governed/Bedrock-tier registrations, the router, and the two leaf clients; F5 holds the four keyed registrations under UseAshlarGovernance (outermost EgressGuardChatClient), and the router dispatches only to them
src/Ashlar.Abstractions/Security/Egress/EgressHttp.cs http.new 3 0 - Exempt:GuardImpl - the guard's own constructions: a raw client and handler behind EgressGuardHandler (:57, :78)
src/Ashlar.Abstractions/Security/Egress/EgressHttp.cs http.new 3 0 - Exempt:GuardImpl - the guard's own constructions: a raw client and handler behind EgressGuardHandler (:61, :82)
src/Ashlar.Abstractions/Security/Egress/SynchronousSendRefusedOnNetstandard20Asset.cs http.new 1 0 - Exempt:GuardImpl - the guard's own construction on the netstandard2.0 asset: the invoker the synchronous-send hop forwards SendAsync through, below EgressGuardHandler (:46)
src/Ashlar.Agents.TestKit/StubHttpMessageHandler.cs http.new 1 0 - Exempt:TestDouble - shipped test double: a client over its own stub handler (:183)
src/Ashlar.BackgroundAgents.HostRunners/SelfExtendAdmissionBridge.cs door 2 2 Precedes - EG-MESH-01 auto-share Pack and Publish (:289, :290), after the EG-MESH-01 guard on the resolved store (:288)
Expand Down Expand Up @@ -88,5 +88,5 @@ src/Ashlar.Mcp.Client/McpClientConnectionManager.cs sdk.client 2 2 Wrapped - EG-
src/Ashlar.Tools.Dev/DotnetRunner.cs process 2 2 Precedes - EG-PROC-01 dotnet.build/test/forge.build runner (:20, :28), after the EG-PROC-01 guard that opens RunAsync (:16)
src/Ashlar.Transport.A2A/A2AAgentTransport.cs http.new 1 1 Wrapped - EG-XPT-01,EG-XPT-02 per-authority client under the A2A SDK, built by EgressHttp.CreateClient (:169)
src/Ashlar.Transport.A2A/A2AAgentTransport.cs sdk.client 2 2 Wrapped - EG-XPT-01,EG-XPT-02 A2AClient (:82) and A2ACardResolver (:148) over the EgressHttp per-authority client
src/Ashlar.Transport.Grpc/DefaultGrpcChannelFactory.cs http.new 2 2 Wrapped - EG-XPT-03,EG-XPT-04,EG-XPT-05 gRPC channel handler: EgressHttp.Wrap over the configured new HttpClientHandler() (:76)
src/Ashlar.Transport.Grpc/DefaultGrpcChannelFactory.cs http.new 2 2 Wrapped - EG-XPT-03,EG-XPT-04,EG-XPT-05 gRPC channel handler: EgressHttp.Wrap over the configured new HttpClientHandler() (:77)
src/Ashlar.Transport.Grpc/DefaultGrpcChannelFactory.cs sdk.client 1 1 Wrapped - EG-XPT-03,EG-XPT-04,EG-XPT-05 GrpcChannel.ForAddress over the wrapped handler (:67)
9 changes: 8 additions & 1 deletion commercial/src/Ashlar.Commercial.Fleet.Host/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,14 @@
builder.Services.AddAshlarRuntimeRouting(builder.Configuration);

builder.Services.AddSingleton<IAshlarIngressAccessor, HttpAshlarIngressAccessor>();
builder.Services.AddHttpClient("ashlar-sns-signing", c => c.Timeout = TimeSpan.FromSeconds(15));
builder.Services.AddHttpClient("ashlar-sns-signing", c => c.Timeout = TimeSpan.FromSeconds(15))
.ConfigurePrimaryHttpMessageHandler(static (handler, _) =>
{
if (handler is HttpClientHandler httpClientHandler)
httpClientHandler.AllowAutoRedirect = false;
else if (handler is SocketsHttpHandler socketsHttpHandler)
socketsHttpHandler.AllowAutoRedirect = false;
});
builder.Services.AddSingleton<ISnsSignatureVerifier, SnsRsaSignatureVerifier>();
builder.Services.AddRateLimiter(static o =>
{
Expand Down
Loading
Loading