diff --git a/CHANGELOG.md b/CHANGELOG.md index dbd2516..f16bf74 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ One line per change, grouped by the release that shipped it. Newest first. A release is a Cargo.toml bump plus a `v` tag; the content repos pin the tag they run (see the end of this file). +## 0.6.23 (2026-10-07) + +- A configuration profile's per-payload `PayloadVersion` is an integer, as the plist key is typed; it was a string, which iOS may refuse. + ## 0.6.22 (2026-10-07) - `/profile.mobileconfig` renders an Apple configuration profile from the mail server's own PACC document (`profile.pacc` in `site.yaml`), so iOS can be set up in one install instead of probing for ports it cannot reach. Mail, CalDAV and CardDAV in one profile; every host, port and path from PACC, never written down twice; no address, username or password in the document, so one profile serves everyone and iOS asks at install; identifiers derived from the site, so reinstalling replaces the accounts rather than duplicating them (docs: content-reference, "A configuration profile"). diff --git a/Cargo.lock b/Cargo.lock index 9dbdad8..f0b569c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3357,7 +3357,7 @@ dependencies = [ [[package]] name = "portal" -version = "0.6.22" +version = "0.6.23" dependencies = [ "anyhow", "arc-swap", diff --git a/Cargo.toml b/Cargo.toml index 84b56b4..db247af 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "portal" -version = "0.6.22" +version = "0.6.23" edition = "2021" [lib] diff --git a/src/profile.rs b/src/profile.rs index 33c22ba..1b19055 100644 --- a/src/profile.rs +++ b/src/profile.rs @@ -148,7 +148,7 @@ pub fn render(pacc: &str, domain: &str, cfg: &ProfileConfig) -> anyhow::Result\n"); payloads.push_str(&string("PayloadType", "com.apple.mail.managed")); - payloads.push_str(&string("PayloadVersion", "1")); + payloads.push_str(&integer("PayloadVersion", 1)); payloads.push_str(&string("PayloadIdentifier", &format!("{base}.mail"))); payloads.push_str(&string( "PayloadUUID", @@ -207,7 +207,7 @@ pub fn render(pacc: &str, domain: &str, cfg: &ProfileConfig) -> anyhow::Result\n"); payloads.push_str(&string("PayloadType", kind)); - payloads.push_str(&string("PayloadVersion", "1")); + payloads.push_str(&integer("PayloadVersion", 1)); payloads.push_str(&string("PayloadIdentifier", &format!("{base}.{proto}"))); payloads.push_str(&string( "PayloadUUID", @@ -338,6 +338,14 @@ mod tests { fn every_value_comes_from_the_pacc_document() { let p = render(PACC, "example.no", &cfg()).unwrap(); assert!(p.contains("com.apple.mail.managed")); + // PayloadVersion is an integer everywhere, top level and in each + // payload: iOS reads the profile as a plist and the key is typed. + assert_eq!( + p.matches("PayloadVersion\n\t\t\t1") + .count(), + 3 + ); + assert!(!p.contains("PayloadVersion\n\t\t\t")); assert!(p.contains("com.apple.caldav.account")); assert!(p.contains("com.apple.carddav.account")); assert!(p.contains(