LCEssentials installs standalone; each sub target-depends on it so linking a
sub's product always pulls LCEssentials in too, without the consumer having to
declare it separately.
- LCECryptoKit: internalized from the remote LCECryptoKitBinary git dependency
(embedded token URL removed) into a local binaryTarget vendoring
Frameworks/LCECryptoKit.xcframework. LCECryptoKitManager moved out of
LCEssentials core into its own LCECryptoKitManager target/product; the
no-op fallback for when the binary wasn't linked is gone (breaking change
for existing consumers, see decisions/2026-09-15-sub-spm-optional-products.md).
- LCFeatureControl: new product wrapping Atomenta's Feature Control API
(flag evaluation with TTL cache + safe-degrade fallback to defaults,
notifications inbox, batched exposure telemetry). 45 new tests.
- Package.swift: .iOS(.v13) -> .iOS(.v15), .watchOS(.v6) -> .v8
(README already stated iOS 15; watchOS 8 needed for URLSession.upload(for:fromFile:))
- drop the iOS-13 uploadTask continuation bridge; both upload overloads now
share one runUpload using session.upload(for:fromFile:delegate:)
- remove now-redundant @available(iOS 15) from the progress overload and test
- Documentation/API.md: drop iOS-version caveats
- upload<T>(url:method:form:pathParams:headers:debug:timeoutInterval:networkServiceType:)
serialises MultipartForm to a temp file, streams it via uploadTask(with:fromFile:)
bridged to async (works on iOS 13+, unlike URLSession.upload(for:fromFile:))
- temp body file always removed via defer (success and throw)
- move requestLOG/responseLOG to LCEssentials+API+Logging.swift; extract
logResponseError helper; keeps API file at 473 lines
- APIUploadTests: 4 cases
- progress-reporting overload deferred (no stub seam for didSendBodyData)