diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 03bef03..3da88a6 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -82,5 +82,10 @@ jobs:
with:
user: ${{ secrets.NUGET_USER }}
+ # No --skip-duplicate: a version that is already on NuGet must fail this
+ # job, not be skipped over as though the release had published. Had 0.9.0
+ # been tagged again on 29 Oct, under a number live since 19 Oct, this job
+ # would have gone green and published nothing
+ # (macula-io/macula-codebase-checks#37).
- name: Push to NuGet
- run: dotnet nuget push ./artifacts/Macula.*.nupkg --api-key ${{ steps.login.outputs.NUGET_API_KEY }} --source https://api.nuget.org/v3/index.json --skip-duplicate
+ run: dotnet nuget push ./artifacts/Macula.*.nupkg --api-key ${{ steps.login.outputs.NUGET_API_KEY }} --source https://api.nuget.org/v3/index.json
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1ea8d0a..daba101 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,19 +7,24 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
-## [0.9.0] - 2026-10-29
+## [0.10.0] - 2026-10-29
-The wire 1.0 release, for the fleet's flag day (19 Oct 2026, 18:03 UTC): from
-then on every live station speaks wire 1.0 (macula 15) and nothing older, and
-0.8.0 can no longer connect. libmacula is macula-go v0.29.0, the release that
-carries the A0 contract (v0.27.0 at the flag day); this package's code is
-0.9.0-rc.5's. The entries for rc.1 to rc.5 below are what changed since 0.8.0.
+The A0 release: libmacula is macula-go v0.29.0, the release that carries the A0
+contract where 0.9.0 shipped v0.27.0, and a call a keyed provider refuses
+`sealed_required` is now resealed and answered. No wire change: this package's
+code is 0.9.0-rc.5's plus the entries below.
-### Changed since this entry was written
+### Changed
- **A call a keyed provider refuses `sealed_required` is resealed and answered**, instead of the
caller failing on a stale keyless candidate: the caller seals again to the key in the refusal's
signed tbs, which is the key the provider holds now (macula-go v0.29.0, macula-dotnet#21).
+- **The release workflow fails on a duplicate version instead of skipping it** (`release.yml`): the
+ NuGet push no longer passes `--skip-duplicate`, so a version already published fails the job
+ rather than reporting success over a publish that never happened. That flag never ran on this
+ week's miss: had 0.9.0 been tagged again on 29 Oct, under a number live since 19 Oct, the job
+ would have gone green and published nothing (macula-io/macula-codebase-checks#37). No library
+ code changes.
### What this release does not change
@@ -33,6 +38,14 @@ carries the A0 contract (v0.27.0 at the flag day); this package's code is
`ServeStream` take the policy as an optional parameter, and omitting it serves any caller
(macula-dotnet#24 for streams, macula-dotnet#25 for unary).
+## [0.9.0] - 2026-10-19
+
+The wire 1.0 release, for the fleet's flag day (19 Oct 2026, 18:03 UTC): from
+then on every live station speaks wire 1.0 (macula 15) and nothing older, and
+0.8.0 can no longer connect. libmacula is macula-go v0.27.0, whose code is
+v0.27.0-rc.8's; this package's code is 0.9.0-rc.5's. The entries for rc.1 to
+rc.5 below are what changed since 0.8.0.
+
## [0.9.0-rc.5] - 2026-10-17
### Added
diff --git a/README.md b/README.md
index bfce791..abb1e0f 100644
--- a/README.md
+++ b/README.md
@@ -20,11 +20,19 @@
---
+> **A0, 0.10.0 (2026-10-29):** over libmacula from macula-go v0.29.0. A call a
+> keyed provider refuses `sealed_required` is now resealed to the key that
+> refusal carries and answered, instead of failing on a stale keyless candidate.
+> Sealing is still the default only where the provider names a KEM key, and a
+> procedure served with no policy is still open; refusing a clear call unless the
+> caller opts out is not in this release. A plain `dotnet add package Macula`
+> resolves 0.10.0.
+
> **Wire 1.0, 0.9.0 (2026-10-19):** built on libmacula from macula-go v0.27.0,
> it speaks wire 1.0 (macula 15) and nothing older, so it reaches only a wire
> 1.0 station. The fleet moved to wire 1.0 on 19 Oct 2026 at 18:03 UTC, and
> from then on 0.8.0 and everything before it can no longer connect. A plain
-> `dotnet add package Macula` resolves 0.9.0.
+> `dotnet add package Macula` resolved 0.9.0 until 0.10.0.
> **Status of 0.8.0, 2026-09-29:** on the **macula 12** wire: TLS 1.3 with a hybrid
> post-quantum key exchange, ML-DSA-87 identities (as the ML-DSA-87 +
diff --git a/src/Macula/Macula.csproj b/src/Macula/Macula.csproj
index 472718f..4c4f2f9 100644
--- a/src/Macula/Macula.csproj
+++ b/src/Macula/Macula.csproj
@@ -14,7 +14,7 @@
Macula
Macula
Macula
- 0.9.0
+ 0.10.0
.NET client for the Macula mesh: TLS 1.3 with a hybrid post-quantum key exchange, ML-DSA-87 identities, signed calls, replies and publications, handshake v5 (sessions bound to their TLS channel), and end-to-end sealing of calls, streams and realm groups with the caller's seal report. Node keys, a pool of station links, calls and streams by direct dial, serving in a node's own namespace or under an org, publish/subscribe and sealed group publish/subscribe, node-served content and the DHT. Built on libmacula, macula-go behind a C ABI, shipped in the package for Linux (x64, arm64), macOS (x64, arm64) and Windows (x64).
Macula
Apache-2.0