feat(ios): device enrollment flow + silent cert rotation (B3)

Wire the SecureEnclave enroll library into a real flow (login->bearer->CSR->
/device/enroll->keychain identity), presented on the existing mTLS path; add a
rotation scheduler. Atomic keychain replace (add-before-delete); renew body is
{csr}-only; renewal-failing surfaced in the UI. ClientTLS 48 tests pass.
This commit is contained in:
Yaojia Wang
2026-07-18 13:32:05 +02:00
parent 9a5909f672
commit 07bcbf0c08
19 changed files with 1549 additions and 32 deletions

View File

@@ -54,6 +54,12 @@ struct AdaptiveRootView: View {
.sheet(isPresented: $coordinator.isDeviceCertPresented) {
deviceCertSheet
}
.sheet(
isPresented: $coordinator.isEnrollmentPresented,
onDismiss: { coordinator.enrollmentDismissed() }
) {
enrollmentSheet
}
}
// MARK: - Layout branch (the SOLE size-class consumer)
@@ -126,4 +132,21 @@ struct AdaptiveRootView: View {
}
}
}
// MARK: - Device enrollment sheet (B3, zero-.p12 auto-cert)
/// NavigationStack + VM coordinator
/// `presentEnrollment` `enrollmentDismissed` VM
@ViewBuilder private var enrollmentSheet: some View {
if let viewModel = coordinator.enrollmentViewModel {
NavigationStack {
EnrollmentScreen(model: viewModel)
.toolbar {
ToolbarItem(placement: .topBarTrailing) {
Button(RootCopy.done) { coordinator.isEnrollmentPresented = false }
}
}
}
}
}
}