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
24 changes: 24 additions & 0 deletions .changeset/born-dedicated-acceptor-export.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
---
"@germ-network/two-mls-pq": minor
---

`TwoMlsPqSession.migrationExport()` now exports every reachable session state instead of
refusing unsettled ones: pre-establishment initiators, born-dedicated acceptors at any point,
staged rotation candidates, lagging leaves, and parked or wedged PQ rounds. It fails only on
corrupt data (`ArchiveInvalid`). The export carries per-group signing keys (`leafKeys`), the
rotation candidate, an own-offer window with its leaf secrets, and deployed-engine flags
(`deployedState`). A pre-A.3 acceptor's `leafKeys.sendPq` is empty, since A.3 founding mints
its own key, and `leafKeys.sendClassical` carries `current` only. Minting requires
twomlspq-swift 0.3.0 or later. `BINDING_CONTRACT_VERSION` bumps 35 → 36.

`SessionMigrator.mintArchive(kind:from:classicalProvider:pqProvider:)` is removed.
`SessionMigrator.mint(kind:from:classicalProvider:pqProvider:)` returns a `MintResult`: the
session archive plus, when present, the minted own-offer window, which the caller must persist
before the archive.

`SessionError.Code.misroutedFrame` now has disposition `.discardFrame` (was `.callerBug`): an
ill-timed side-band re-send is normal traffic. This shifts app-side handling and any analytics
bucketed by disposition.

Also corrects the 0.17.0 changelog's claim that pre-v35 group state no longer loads: it does,
and sessions written by v0.15.0 and v0.16.0 restore and migrate, pinned by fixtures.
14 changes: 7 additions & 7 deletions Package.resolved

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 7 additions & 13 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -78,19 +78,14 @@ let package = Package(
url: "https://github.com/germ-network/autonomous-comm-protocol.git",
from: "1.13.0"
),
// The native-side migrator dependency (GER-2372): twomlspq-swift carries R1's
// `InvitationMigration.mintArchive` + `MigratedIdentity` and R2's
// `SessionMigration.mintArchive` + `MigratedSession`, which `TwoMLSPQMigrate`
// maps the Rust migration exports onto. 0.1.1 is the first tag carrying R2
// (SessionMigration + the ML-KEM `hpkeSecretKeySize`); its transitive deps
// (swift-mls, swift-secret-bytes, swift-crypto, GermConvenience) resolve
// The native engine `TwoMLSPQMigrate` mints into (`InvitationMigration`,
// `SessionMigration`). 0.3.0 is the first release that takes the per-group
// signing keys and deployed-state inputs this export carries; its transitive
// deps (swift-mls, swift-secret-bytes, swift-crypto, GermConvenience) resolve
// automatically.
// Temporary revision pin to twomlspq-swift's swift-crypto-5 branch
// (germ-network/twomlspq-swift#60); replace with the released version
// once it cuts.
.package(
url: "https://github.com/germ-network/twomlspq-swift.git",
from: "0.2.1"
from: "0.3.0"
),
// Declared directly (not just transitively through twomlspq-swift) because
// the migrate targets import their products. Library deps stay ranged
Expand All @@ -99,9 +94,6 @@ let package = Package(
// conflicts against a consumer's own tighter pin; twomlspq-swift's own
// swift-mls requirement is ranged the same way (the 0.1.1 floor carries
// the C0 `Nsk` length check). Exactness belongs to the app-level repo.
// Temporary revision pin to swift-mls's swift-crypto-5 branch
// (germ-network/swift-mls#103); replace with the released version once
// it cuts.
.package(
url: "https://github.com/germ-network/swift-mls.git",
from: "0.1.4"
Expand Down Expand Up @@ -179,6 +171,8 @@ let package = Package(
.product(name: "TwoMLSPQSession", package: "twomlspq-swift"),
.product(name: "TwoMLSPQCrypto", package: "twomlspq-swift"),
.product(name: "MLSCrypto", package: "swift-mls"),
.product(name: "MLSCodec", package: "swift-mls"),
.product(name: "MLSProfileRFC9420", package: "swift-mls"),
],
resources: [.copy("Fixtures")]
),
Expand Down
7 changes: 6 additions & 1 deletion Sources/TwoMLSPQ/PQSession.swift
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,12 @@ public typealias SideBandSealing = TwoMLSPQTypes.SideBandSealing
// `TwoMlsPqSession.migrationExport()`. The consumer lives in `TwoMLSPQMigrate`
// (`SessionMigrator`), mapping onto twomlspq-swift's `SessionMigration.mintArchive`.
// No wire, API, or error-variant change beyond the new symbols.
private let expectedBindingContract: UInt64 = 35
// v36: the session migration export admits every reachable deployed session instead of
// refusing unsettled state, erroring only on corrupt or impossible data. New records
// carry per-group leaf keys, the rotation candidate, the own-offer window, and
// deployed-engine flags, appended to `SessionMigrationExport`'s memberwise init. No
// wire or error-variant change.
private let expectedBindingContract: UInt64 = 36

enum TwoMLSPQBindingContract {
static let verified: Void = {
Expand Down
Loading
Loading