[sub-spm-optional-products] Add LCECryptoKit and LCFeatureControl as optional sub-SPM products
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.
This commit is contained in:
@@ -0,0 +1,417 @@
|
||||
{
|
||||
"ABIRoot": {
|
||||
"kind": "Root",
|
||||
"name": "LCECryptoKit",
|
||||
"printedName": "LCECryptoKit",
|
||||
"children": [
|
||||
{
|
||||
"kind": "Import",
|
||||
"name": "Foundation",
|
||||
"printedName": "Foundation",
|
||||
"declKind": "Import",
|
||||
"moduleName": "LCECryptoKit"
|
||||
},
|
||||
{
|
||||
"kind": "Import",
|
||||
"name": "CommonCrypto",
|
||||
"printedName": "CommonCrypto",
|
||||
"declKind": "Import",
|
||||
"moduleName": "LCECryptoKit"
|
||||
},
|
||||
{
|
||||
"kind": "TypeDecl",
|
||||
"name": "LCECryptoKit",
|
||||
"printedName": "LCECryptoKit",
|
||||
"children": [
|
||||
{
|
||||
"kind": "Function",
|
||||
"name": "generateRandomAESKeyString",
|
||||
"printedName": "generateRandomAESKeyString()",
|
||||
"children": [
|
||||
{
|
||||
"kind": "TypeNominal",
|
||||
"name": "String",
|
||||
"printedName": "Swift.String",
|
||||
"usr": "s:SS"
|
||||
}
|
||||
],
|
||||
"declKind": "Func",
|
||||
"usr": "s:12LCECryptoKitAAV26generateRandomAESKeyStringSSyFZ",
|
||||
"mangledName": "$s12LCECryptoKitAAV26generateRandomAESKeyStringSSyFZ",
|
||||
"moduleName": "LCECryptoKit",
|
||||
"static": true,
|
||||
"declAttributes": [
|
||||
"AccessControl"
|
||||
],
|
||||
"funcSelfKind": "NonMutating"
|
||||
},
|
||||
{
|
||||
"kind": "Function",
|
||||
"name": "encodeSeed",
|
||||
"printedName": "encodeSeed(email:password:)",
|
||||
"children": [
|
||||
{
|
||||
"kind": "TypeNominal",
|
||||
"name": "Optional",
|
||||
"printedName": "Swift.String?",
|
||||
"children": [
|
||||
{
|
||||
"kind": "TypeNominal",
|
||||
"name": "String",
|
||||
"printedName": "Swift.String",
|
||||
"usr": "s:SS"
|
||||
}
|
||||
],
|
||||
"usr": "s:Sq"
|
||||
},
|
||||
{
|
||||
"kind": "TypeNominal",
|
||||
"name": "String",
|
||||
"printedName": "Swift.String",
|
||||
"usr": "s:SS"
|
||||
},
|
||||
{
|
||||
"kind": "TypeNominal",
|
||||
"name": "String",
|
||||
"printedName": "Swift.String",
|
||||
"usr": "s:SS"
|
||||
}
|
||||
],
|
||||
"declKind": "Func",
|
||||
"usr": "s:12LCECryptoKitAAV10encodeSeed5email8passwordSSSgSS_SStFZ",
|
||||
"mangledName": "$s12LCECryptoKitAAV10encodeSeed5email8passwordSSSgSS_SStFZ",
|
||||
"moduleName": "LCECryptoKit",
|
||||
"static": true,
|
||||
"declAttributes": [
|
||||
"AccessControl"
|
||||
],
|
||||
"funcSelfKind": "NonMutating"
|
||||
},
|
||||
{
|
||||
"kind": "Function",
|
||||
"name": "encodeSeed",
|
||||
"printedName": "encodeSeed(email:password:hashKey:)",
|
||||
"children": [
|
||||
{
|
||||
"kind": "TypeNominal",
|
||||
"name": "Optional",
|
||||
"printedName": "Swift.String?",
|
||||
"children": [
|
||||
{
|
||||
"kind": "TypeNominal",
|
||||
"name": "String",
|
||||
"printedName": "Swift.String",
|
||||
"usr": "s:SS"
|
||||
}
|
||||
],
|
||||
"usr": "s:Sq"
|
||||
},
|
||||
{
|
||||
"kind": "TypeNominal",
|
||||
"name": "String",
|
||||
"printedName": "Swift.String",
|
||||
"usr": "s:SS"
|
||||
},
|
||||
{
|
||||
"kind": "TypeNominal",
|
||||
"name": "String",
|
||||
"printedName": "Swift.String",
|
||||
"usr": "s:SS"
|
||||
},
|
||||
{
|
||||
"kind": "TypeNominal",
|
||||
"name": "String",
|
||||
"printedName": "Swift.String",
|
||||
"usr": "s:SS"
|
||||
}
|
||||
],
|
||||
"declKind": "Func",
|
||||
"usr": "s:12LCECryptoKitAAV10encodeSeed5email8password7hashKeySSSgSS_S2StFZ",
|
||||
"mangledName": "$s12LCECryptoKitAAV10encodeSeed5email8password7hashKeySSSgSS_S2StFZ",
|
||||
"moduleName": "LCECryptoKit",
|
||||
"static": true,
|
||||
"declAttributes": [
|
||||
"AccessControl"
|
||||
],
|
||||
"funcSelfKind": "NonMutating"
|
||||
},
|
||||
{
|
||||
"kind": "Function",
|
||||
"name": "decodeSeed",
|
||||
"printedName": "decodeSeed(otpKey:)",
|
||||
"children": [
|
||||
{
|
||||
"kind": "TypeNominal",
|
||||
"name": "Optional",
|
||||
"printedName": "Swift.String?",
|
||||
"children": [
|
||||
{
|
||||
"kind": "TypeNominal",
|
||||
"name": "String",
|
||||
"printedName": "Swift.String",
|
||||
"usr": "s:SS"
|
||||
}
|
||||
],
|
||||
"usr": "s:Sq"
|
||||
},
|
||||
{
|
||||
"kind": "TypeNominal",
|
||||
"name": "String",
|
||||
"printedName": "Swift.String",
|
||||
"usr": "s:SS"
|
||||
}
|
||||
],
|
||||
"declKind": "Func",
|
||||
"usr": "s:12LCECryptoKitAAV10decodeSeed6otpKeySSSgSS_tFZ",
|
||||
"mangledName": "$s12LCECryptoKitAAV10decodeSeed6otpKeySSSgSS_tFZ",
|
||||
"moduleName": "LCECryptoKit",
|
||||
"static": true,
|
||||
"declAttributes": [
|
||||
"AccessControl"
|
||||
],
|
||||
"funcSelfKind": "NonMutating"
|
||||
},
|
||||
{
|
||||
"kind": "Function",
|
||||
"name": "decodeSeed",
|
||||
"printedName": "decodeSeed(otpKey:hashKey:)",
|
||||
"children": [
|
||||
{
|
||||
"kind": "TypeNominal",
|
||||
"name": "Bool",
|
||||
"printedName": "Swift.Bool",
|
||||
"usr": "s:Sb"
|
||||
},
|
||||
{
|
||||
"kind": "TypeNominal",
|
||||
"name": "String",
|
||||
"printedName": "Swift.String",
|
||||
"usr": "s:SS"
|
||||
},
|
||||
{
|
||||
"kind": "TypeNominal",
|
||||
"name": "String",
|
||||
"printedName": "Swift.String",
|
||||
"usr": "s:SS"
|
||||
}
|
||||
],
|
||||
"declKind": "Func",
|
||||
"usr": "s:12LCECryptoKitAAV10decodeSeed6otpKey04hashF0SbSS_SStFZ",
|
||||
"mangledName": "$s12LCECryptoKitAAV10decodeSeed6otpKey04hashF0SbSS_SStFZ",
|
||||
"moduleName": "LCECryptoKit",
|
||||
"static": true,
|
||||
"declAttributes": [
|
||||
"AccessControl"
|
||||
],
|
||||
"funcSelfKind": "NonMutating"
|
||||
},
|
||||
{
|
||||
"kind": "Function",
|
||||
"name": "generateSalt",
|
||||
"printedName": "generateSalt()",
|
||||
"children": [
|
||||
{
|
||||
"kind": "TypeNominal",
|
||||
"name": "String",
|
||||
"printedName": "Swift.String",
|
||||
"usr": "s:SS"
|
||||
}
|
||||
],
|
||||
"declKind": "Func",
|
||||
"usr": "s:12LCECryptoKitAAV12generateSaltSSyFZ",
|
||||
"mangledName": "$s12LCECryptoKitAAV12generateSaltSSyFZ",
|
||||
"moduleName": "LCECryptoKit",
|
||||
"static": true,
|
||||
"declAttributes": [
|
||||
"AccessControl",
|
||||
"RawDocComment"
|
||||
],
|
||||
"funcSelfKind": "NonMutating"
|
||||
},
|
||||
{
|
||||
"kind": "Function",
|
||||
"name": "computeClientHash",
|
||||
"printedName": "computeClientHash(email:password:salt:)",
|
||||
"children": [
|
||||
{
|
||||
"kind": "TypeNominal",
|
||||
"name": "String",
|
||||
"printedName": "Swift.String",
|
||||
"usr": "s:SS"
|
||||
},
|
||||
{
|
||||
"kind": "TypeNominal",
|
||||
"name": "String",
|
||||
"printedName": "Swift.String",
|
||||
"usr": "s:SS"
|
||||
},
|
||||
{
|
||||
"kind": "TypeNominal",
|
||||
"name": "String",
|
||||
"printedName": "Swift.String",
|
||||
"usr": "s:SS"
|
||||
},
|
||||
{
|
||||
"kind": "TypeNominal",
|
||||
"name": "String",
|
||||
"printedName": "Swift.String",
|
||||
"usr": "s:SS"
|
||||
}
|
||||
],
|
||||
"declKind": "Func",
|
||||
"usr": "s:12LCECryptoKitAAV17computeClientHash5email8password4saltS2S_S2StFZ",
|
||||
"mangledName": "$s12LCECryptoKitAAV17computeClientHash5email8password4saltS2S_S2StFZ",
|
||||
"moduleName": "LCECryptoKit",
|
||||
"static": true,
|
||||
"declAttributes": [
|
||||
"AccessControl",
|
||||
"RawDocComment"
|
||||
],
|
||||
"funcSelfKind": "NonMutating"
|
||||
},
|
||||
{
|
||||
"kind": "Function",
|
||||
"name": "computeLoginBearerToken",
|
||||
"printedName": "computeLoginBearerToken(userId:clientHash:)",
|
||||
"children": [
|
||||
{
|
||||
"kind": "TypeNominal",
|
||||
"name": "Optional",
|
||||
"printedName": "Swift.String?",
|
||||
"children": [
|
||||
{
|
||||
"kind": "TypeNominal",
|
||||
"name": "String",
|
||||
"printedName": "Swift.String",
|
||||
"usr": "s:SS"
|
||||
}
|
||||
],
|
||||
"usr": "s:Sq"
|
||||
},
|
||||
{
|
||||
"kind": "TypeNominal",
|
||||
"name": "String",
|
||||
"printedName": "Swift.String",
|
||||
"usr": "s:SS"
|
||||
},
|
||||
{
|
||||
"kind": "TypeNominal",
|
||||
"name": "String",
|
||||
"printedName": "Swift.String",
|
||||
"usr": "s:SS"
|
||||
}
|
||||
],
|
||||
"declKind": "Func",
|
||||
"usr": "s:12LCECryptoKitAAV23computeLoginBearerToken6userId10clientHashSSSgSS_SStFZ",
|
||||
"mangledName": "$s12LCECryptoKitAAV23computeLoginBearerToken6userId10clientHashSSSgSS_SStFZ",
|
||||
"moduleName": "LCECryptoKit",
|
||||
"static": true,
|
||||
"declAttributes": [
|
||||
"AccessControl",
|
||||
"RawDocComment"
|
||||
],
|
||||
"funcSelfKind": "NonMutating"
|
||||
},
|
||||
{
|
||||
"kind": "Function",
|
||||
"name": "otpEncode",
|
||||
"printedName": "otpEncode(_:)",
|
||||
"children": [
|
||||
{
|
||||
"kind": "TypeNominal",
|
||||
"name": "Optional",
|
||||
"printedName": "Swift.String?",
|
||||
"children": [
|
||||
{
|
||||
"kind": "TypeNominal",
|
||||
"name": "String",
|
||||
"printedName": "Swift.String",
|
||||
"usr": "s:SS"
|
||||
}
|
||||
],
|
||||
"usr": "s:Sq"
|
||||
},
|
||||
{
|
||||
"kind": "TypeNominal",
|
||||
"name": "String",
|
||||
"printedName": "Swift.String",
|
||||
"usr": "s:SS"
|
||||
}
|
||||
],
|
||||
"declKind": "Func",
|
||||
"usr": "s:12LCECryptoKitAAV9otpEncodeySSSgSSFZ",
|
||||
"mangledName": "$s12LCECryptoKitAAV9otpEncodeySSSgSSFZ",
|
||||
"moduleName": "LCECryptoKit",
|
||||
"static": true,
|
||||
"declAttributes": [
|
||||
"AccessControl",
|
||||
"RawDocComment"
|
||||
],
|
||||
"funcSelfKind": "NonMutating"
|
||||
},
|
||||
{
|
||||
"kind": "Function",
|
||||
"name": "otpDecode",
|
||||
"printedName": "otpDecode(_:)",
|
||||
"children": [
|
||||
{
|
||||
"kind": "TypeNominal",
|
||||
"name": "Optional",
|
||||
"printedName": "Swift.String?",
|
||||
"children": [
|
||||
{
|
||||
"kind": "TypeNominal",
|
||||
"name": "String",
|
||||
"printedName": "Swift.String",
|
||||
"usr": "s:SS"
|
||||
}
|
||||
],
|
||||
"usr": "s:Sq"
|
||||
},
|
||||
{
|
||||
"kind": "TypeNominal",
|
||||
"name": "String",
|
||||
"printedName": "Swift.String",
|
||||
"usr": "s:SS"
|
||||
}
|
||||
],
|
||||
"declKind": "Func",
|
||||
"usr": "s:12LCECryptoKitAAV9otpDecodeySSSgSSFZ",
|
||||
"mangledName": "$s12LCECryptoKitAAV9otpDecodeySSSgSSFZ",
|
||||
"moduleName": "LCECryptoKit",
|
||||
"static": true,
|
||||
"declAttributes": [
|
||||
"AccessControl"
|
||||
],
|
||||
"funcSelfKind": "NonMutating"
|
||||
}
|
||||
],
|
||||
"declKind": "Struct",
|
||||
"usr": "s:12LCECryptoKitAAV",
|
||||
"mangledName": "$s12LCECryptoKitAAV",
|
||||
"moduleName": "LCECryptoKit",
|
||||
"declAttributes": [
|
||||
"AccessControl"
|
||||
],
|
||||
"conformances": [
|
||||
{
|
||||
"kind": "Conformance",
|
||||
"name": "Copyable",
|
||||
"printedName": "Copyable",
|
||||
"usr": "s:s8CopyableP",
|
||||
"mangledName": "$ss8CopyableP"
|
||||
},
|
||||
{
|
||||
"kind": "Conformance",
|
||||
"name": "Escapable",
|
||||
"printedName": "Escapable",
|
||||
"usr": "s:s9EscapableP",
|
||||
"mangledName": "$ss9EscapableP"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"json_format_version": 8
|
||||
},
|
||||
"ConstValues": []
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
// swift-interface-format-version: 1.0
|
||||
// swift-compiler-version: Apple Swift version 6.3.3 effective-5.10 (swiftlang-6.3.3.1.3 clang-2100.1.1.101)
|
||||
// swift-module-flags: -target arm64-apple-ios13.0 -enable-objc-interop -enable-library-evolution -swift-version 5 -O -enable-experimental-feature DebugDescriptionMacro -enable-bare-slash-regex -module-name LCECryptoKit
|
||||
// swift-module-flags-ignorable: -no-verify-emitted-module-interface -formal-cxx-interoperability-mode=off -interface-compiler-version 6.3.3
|
||||
import CommonCrypto
|
||||
import Foundation
|
||||
import Swift
|
||||
import _Concurrency
|
||||
import _StringProcessing
|
||||
import _SwiftConcurrencyShims
|
||||
public struct LCECryptoKit {
|
||||
public static func generateRandomAESKeyString() -> Swift.String
|
||||
public static func encodeSeed(email: Swift.String, password: Swift.String) -> Swift.String?
|
||||
public static func encodeSeed(email: Swift.String, password: Swift.String, hashKey: Swift.String) -> Swift.String?
|
||||
public static func decodeSeed(otpKey: Swift.String) -> Swift.String?
|
||||
public static func decodeSeed(otpKey: Swift.String, hashKey: Swift.String) -> Swift.Bool
|
||||
public static func generateSalt() -> Swift.String
|
||||
public static func computeClientHash(email: Swift.String, password: Swift.String, salt: Swift.String) -> Swift.String
|
||||
public static func computeLoginBearerToken(userId: Swift.String, clientHash: Swift.String) -> Swift.String?
|
||||
public static func otpEncode(_ plainText: Swift.String) -> Swift.String?
|
||||
public static func otpDecode(_ otpEncoded: Swift.String) -> Swift.String?
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,22 @@
|
||||
// swift-interface-format-version: 1.0
|
||||
// swift-compiler-version: Apple Swift version 6.3.3 effective-5.10 (swiftlang-6.3.3.1.3 clang-2100.1.1.101)
|
||||
// swift-module-flags: -target arm64-apple-ios13.0 -enable-objc-interop -enable-library-evolution -swift-version 5 -O -enable-experimental-feature DebugDescriptionMacro -enable-bare-slash-regex -module-name LCECryptoKit
|
||||
// swift-module-flags-ignorable: -no-verify-emitted-module-interface -formal-cxx-interoperability-mode=off -interface-compiler-version 6.3.3
|
||||
import CommonCrypto
|
||||
import Foundation
|
||||
import Swift
|
||||
import _Concurrency
|
||||
import _StringProcessing
|
||||
import _SwiftConcurrencyShims
|
||||
public struct LCECryptoKit {
|
||||
public static func generateRandomAESKeyString() -> Swift.String
|
||||
public static func encodeSeed(email: Swift.String, password: Swift.String) -> Swift.String?
|
||||
public static func encodeSeed(email: Swift.String, password: Swift.String, hashKey: Swift.String) -> Swift.String?
|
||||
public static func decodeSeed(otpKey: Swift.String) -> Swift.String?
|
||||
public static func decodeSeed(otpKey: Swift.String, hashKey: Swift.String) -> Swift.Bool
|
||||
public static func generateSalt() -> Swift.String
|
||||
public static func computeClientHash(email: Swift.String, password: Swift.String, salt: Swift.String) -> Swift.String
|
||||
public static func computeLoginBearerToken(userId: Swift.String, clientHash: Swift.String) -> Swift.String?
|
||||
public static func otpEncode(_ plainText: Swift.String) -> Swift.String?
|
||||
public static func otpDecode(_ otpEncoded: Swift.String) -> Swift.String?
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
framework module LCECryptoKit {
|
||||
header "LCECryptoKit-Swift.h"
|
||||
}
|
||||
Reference in New Issue
Block a user