+1 overall.
As an implementation detail:
public final class Package {
...
/// This disallows any binary dependency or any transitive binary dependency.
public var disallowsBinaryDependencies: Bool
...
}
Why not just have allowsBinaryDependencies: Bool with a default value of true? Reading true to disable a something is a bit awkward.
Also, what about trust chains for packages? Meaning I may want to allow binary dependencies from packages X, Y, Z (maybe company packages), but not from A, B, C (maybe public repositories)?
Using the playing card deck example, I'd imagine something like this:
let package = Package(
name: "DeckOfPlayingCards",
products: [
.library(name: "DeckOfPlayingCards", targets: ["DeckOfPlayingCards"]),
],
dependencies: [
.package(url: "https://github.com/apple/example-package-fisheryates.git", from: "2.0.0"),
.package(url: "https://github.com/apple/example-package-playingcard.git", from: "3.0.0", allowsBinaryPackages: false),
],
targets: [
.target(
name: "DeckOfPlayingCards",
dependencies: ["FisherYates", "PlayingCard"]),
.testTarget(
name: "DeckOfPlayingCardsTests",
dependencies: ["DeckOfPlayingCards"]),
]
)
The point of this is to allow the use of something like Firebase from my package without allowing anything else from the other dependencies I'm pulling in. I don't believe this is captured with the opt-in/opt-out Whitelist discussion in the proposal. While it is true that one is extending the same level of trust to both source and binary packages, sources can be audited and pinned to specific versions. I'm also doing it as a consumer of package dependencies vs. the package author.
Again, I think this can come later, but it should probably be mentioned in the proposal as something to consider (or reject outright for a different approach).