From 8d1377602bb6dc8a90072445db6ecbe878174e13 Mon Sep 17 00:00:00 2001 From: "Sven A. Schmidt" Date: Fri, 2 May 2025 11:52:15 +0200 Subject: [PATCH 1/6] Revert "Drop PackageCollectionsSigning" This reverts commit 75679ea5ce6fd7581508da667bb438bcc7edc11b. # Conflicts: # Tests/AppTests/ApiTests.swift --- .../API/API+PackageCollectionController.swift | 9 +- .../PackageCollectionController.swift | 8 +- .../Core/Dependencies/EnvironmentClient.swift | 8 +- .../App/Core/PackageCollection+signing.swift | 84 +++++++++++ Tests/AppTests/ApiTests.swift | 141 +++++++++--------- Tests/AppTests/PackageCollectionTests.swift | 132 ++++++++-------- 6 files changed, 238 insertions(+), 144 deletions(-) create mode 100644 Sources/App/Core/PackageCollection+signing.swift diff --git a/Sources/App/Controllers/API/API+PackageCollectionController.swift b/Sources/App/Controllers/API/API+PackageCollectionController.swift index d5478dad8..a52a92147 100644 --- a/Sources/App/Controllers/API/API+PackageCollectionController.swift +++ b/Sources/App/Controllers/API/API+PackageCollectionController.swift @@ -14,6 +14,7 @@ import Fluent import PackageCollectionsModel +import PackageCollectionsSigning import Vapor @@ -22,14 +23,14 @@ extension API { enum PackageCollectionController { @Sendable - static func generate(req: Request) async throws -> PackageCollection { + static func generate(req: Request) async throws -> SignedCollection { AppMetrics.apiPackageCollectionGetTotal?.inc() let dto = try req.content.decode(PostPackageCollectionDTO.self) switch dto.selection { case let .author(author): - return try await PackageCollection.generate( + return try await SignedCollection.generate( db: req.db, filterBy: .author(author), authorName: dto.authorName ?? "Swift Package Index", @@ -43,7 +44,7 @@ extension API { guard packageURLs.count <= 20 else { throw Abort(.badRequest) } - return try await PackageCollection.generate( + return try await SignedCollection.generate( db: req.db, filterBy: .urls(packageURLs), authorName: dto.authorName ?? "Swift Package Index", @@ -60,7 +61,7 @@ extension API { } -extension PackageCollectionModel.V1.Collection: Vapor.Content {} +extension PackageCollectionSigning.Model.SignedCollection: Vapor.Content {} extension API { diff --git a/Sources/App/Controllers/PackageCollectionController.swift b/Sources/App/Controllers/PackageCollectionController.swift index 17a15f8ce..dabbcf4ee 100644 --- a/Sources/App/Controllers/PackageCollectionController.swift +++ b/Sources/App/Controllers/PackageCollectionController.swift @@ -17,7 +17,7 @@ import Vapor enum PackageCollectionController { @Sendable - static func generate(req: Request) async throws -> PackageCollection { + static func generate(req: Request) async throws -> SignedCollection { AppMetrics.packageCollectionGetTotal?.inc() guard let collectionType = getCollectionType(req: req) else { @@ -27,13 +27,13 @@ enum PackageCollectionController { do { switch collectionType { case let .author(owner): - return try await PackageCollection.generate( + return try await SignedCollection.generate( db: req.db, filterBy: .author(owner), authorName: "\(owner) via the Swift Package Index" ) case let .keyword(keyword): - return try await PackageCollection.generate( + return try await SignedCollection.generate( db: req.db, filterBy: .keyword(keyword), authorName: "Swift Package Index", @@ -45,7 +45,7 @@ enum PackageCollectionController { case let .custom(key): let collection = try await CustomCollection.find(on: req.db, key: key) .unwrap(or: Abort(.notFound)) - return try await PackageCollection.generate( + return try await SignedCollection.generate( db: req.db, filterBy: .customCollection(key), authorName: "Swift Package Index", diff --git a/Sources/App/Core/Dependencies/EnvironmentClient.swift b/Sources/App/Core/Dependencies/EnvironmentClient.swift index 8e7bcf625..46d00bcfe 100644 --- a/Sources/App/Core/Dependencies/EnvironmentClient.swift +++ b/Sources/App/Core/Dependencies/EnvironmentClient.swift @@ -100,7 +100,13 @@ extension EnvironmentClient: DependencyKey { .flatMap(Double.init) ?? 1.0 }, - collectionSigningCertificateChain: { [] }, + collectionSigningCertificateChain: { + [ + "package_collections.cer", + "AppleWWDRCAG3.cer", + "AppleIncRootCertificate.cer", + ].map { SignedCollection.certsDir.appendingPathComponent($0) } + }, collectionSigningPrivateKey: { Environment.get("COLLECTION_SIGNING_PRIVATE_KEY").map { Data($0.utf8) } }, diff --git a/Sources/App/Core/PackageCollection+signing.swift b/Sources/App/Core/PackageCollection+signing.swift new file mode 100644 index 000000000..d52aadfaf --- /dev/null +++ b/Sources/App/Core/PackageCollection+signing.swift @@ -0,0 +1,84 @@ +// Copyright Dave Verwer, Sven A. Schmidt, and other contributors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import Basics +import Dependencies +import Fluent +import Vapor +@preconcurrency import PackageCollectionsModel +@preconcurrency import PackageCollectionsSigning + + +typealias SignedCollection = PackageCollectionSigning.Model.SignedCollection + + +extension SignedCollection { + + static func generate(db: Database, + filterBy filter: PackageCollection.Filter, + authorName: String? = nil, + collectionName: String? = nil, + keywords: [String]? = nil, + overview: String? = nil, + revision: Int? = nil, + limit maxResults: Int? = nil) async throws -> SignedCollection { + let collection = try await PackageCollection.generate(db: db, + filterBy: filter, + authorName: authorName, + collectionName: collectionName, + keywords: keywords, + overview: overview, + revision: revision, + limit: maxResults) + return try await sign(collection: collection) + } + + static func sign(collection: PackageCollection) async throws -> SignedCollection { + @Dependency(\.environment) var environment + + guard let privateKey = environment.collectionSigningPrivateKey() else { + throw AppError.envVariableNotSet("COLLECTION_SIGNING_PRIVATE_KEY") + } + + return try await signer.sign(collection: collection, + certChainPaths: environment.collectionSigningCertificateChain(), + privateKeyPEM: privateKey) + } + + static func validate(signedCollection: SignedCollection) async throws -> Bool { + try await signer.validate(signedCollection: signedCollection) + return true + } + + static var certsDir: URL { + @Dependency(\.fileManager) var fileManager + return URL(fileURLWithPath: fileManager.workingDirectory()) + .appendingPathComponent("Resources") + .appendingPathComponent("Certs") + } + + static let signer = PackageCollectionSigning( + trustedRootCertsDir: certsDir, + additionalTrustedRootCerts: nil, + observabilityScope: .ignored + ) + +} + + +private extension ObservabilityScope { + static var ignored: ObservabilityScope { + ObservabilitySystem { _, _ in }.topScope + } +} diff --git a/Tests/AppTests/ApiTests.swift b/Tests/AppTests/ApiTests.swift index 3799bab3a..632b11a6c 100644 --- a/Tests/AppTests/ApiTests.swift +++ b/Tests/AppTests/ApiTests.swift @@ -15,6 +15,7 @@ @testable import App import Dependencies +import PackageCollectionsSigning import SnapshotTesting import Testing import VaporTesting @@ -844,76 +845,76 @@ extension AllTests.ApiTests { } } -// @Test(.disabled(if: !isRunningInCI() && EnvironmentClient.liveValue.collectionSigningPrivateKey() == nil, -// "Skip test for local user due to unset COLLECTION_SIGNING_PRIVATE_KEY env variable")) -// func package_collections_owner() async throws { -// let event = App.ActorIsolated(nil) -// try await withDependencies { -// $0.date.now = .t0 -// $0.environment.apiSigningKey = { "secret" } -// $0.environment.collectionSigningCertificateChain = EnvironmentClient.liveValue.collectionSigningCertificateChain -// $0.environment.collectionSigningPrivateKey = EnvironmentClient.liveValue.collectionSigningPrivateKey -// $0.httpClient.postPlausibleEvent = { @Sendable kind, path, _ in -// await event.setValue(.init(kind: kind, path: path)) -// } -// } operation: { -// try await withSPIApp { app in -// // setup -// let p1 = Package(id: .id1, url: "1") -// try await p1.save(on: app.db) -// try await Repository(package: p1, -// defaultBranch: "main", -// name: "name 1", -// owner: "foo", -// summary: "foo bar package").save(on: app.db) -// let v = try Version(package: p1, -// latest: .release, -// packageName: "Foo", -// reference: .tag(1, 2, 3), -// toolsVersion: "5.0") -// try await v.save(on: app.db) -// try await Product(version: v, type: .library(.automatic), name: "lib") -// .save(on: app.db) -// -// do { // MUT -// let body: ByteBuffer = .init(string: """ -// { -// "revision": 3, -// "authorName": "author", -// "keywords": [ -// "a", -// "b" -// ], -// "selection": { -// "author": { -// "_0": "foo" -// } -// }, -// "collectionName": "my collection", -// "overview": "my overview" -// } -// """) -// -// try await app.testing().test(.POST, "api/package-collections", -// headers: .bearerApplicationJSON(try .apiToken(secretKey: "secret", tier: .tier3)), -// body: body, -// afterResponse: { res async throws in -// // validation -// #expect(res.status == .ok) -// let container = try res.content.decode(SignedCollection.self) -// #expect(!container.signature.signature.isEmpty) -// // more details are tested in PackageCollectionTests -// #expect(container.collection.name == "my collection") -// }) -// } -// -// // ensure API event has been reported -// await event.withValue { -// #expect($0 == .some(.init(kind: .pageview, path: .packageCollections))) -// } -// } -// } -// } + @Test(.disabled(if: !isRunningInCI() && EnvironmentClient.liveValue.collectionSigningPrivateKey() == nil, + "Skip test for local user due to unset COLLECTION_SIGNING_PRIVATE_KEY env variable")) + func package_collections_owner() async throws { + let event = App.ActorIsolated(nil) + try await withDependencies { + $0.date.now = .t0 + $0.environment.apiSigningKey = { "secret" } + $0.environment.collectionSigningCertificateChain = EnvironmentClient.liveValue.collectionSigningCertificateChain + $0.environment.collectionSigningPrivateKey = EnvironmentClient.liveValue.collectionSigningPrivateKey + $0.httpClient.postPlausibleEvent = { @Sendable kind, path, _ in + await event.setValue(.init(kind: kind, path: path)) + } + } operation: { + try await withSPIApp { app in + // setup + let p1 = Package(id: .id1, url: "1") + try await p1.save(on: app.db) + try await Repository(package: p1, + defaultBranch: "main", + name: "name 1", + owner: "foo", + summary: "foo bar package").save(on: app.db) + let v = try Version(package: p1, + latest: .release, + packageName: "Foo", + reference: .tag(1, 2, 3), + toolsVersion: "5.0") + try await v.save(on: app.db) + try await Product(version: v, type: .library(.automatic), name: "lib") + .save(on: app.db) + + do { // MUT + let body: ByteBuffer = .init(string: """ + { + "revision": 3, + "authorName": "author", + "keywords": [ + "a", + "b" + ], + "selection": { + "author": { + "_0": "foo" + } + }, + "collectionName": "my collection", + "overview": "my overview" + } + """) + + try await app.testing().test(.POST, "api/package-collections", + headers: .bearerApplicationJSON(try .apiToken(secretKey: "secret", tier: .tier3)), + body: body, + afterResponse: { res async throws in + // validation + #expect(res.status == .ok) + let container = try res.content.decode(SignedCollection.self) + #expect(!container.signature.signature.isEmpty) + // more details are tested in PackageCollectionTests + #expect(container.collection.name == "my collection") + }) + } + + // ensure API event has been reported + await event.withValue { + #expect($0 == .some(.init(kind: .pageview, path: .packageCollections))) + } + } + } + } @Test(.disabled(if: !isRunningInCI() && EnvironmentClient.liveValue.collectionSigningPrivateKey() == nil, "Skip test for local user due to unset COLLECTION_SIGNING_PRIVATE_KEY env variable")) diff --git a/Tests/AppTests/PackageCollectionTests.swift b/Tests/AppTests/PackageCollectionTests.swift index 7c1a4479f..fb1483694 100644 --- a/Tests/AppTests/PackageCollectionTests.swift +++ b/Tests/AppTests/PackageCollectionTests.swift @@ -14,7 +14,9 @@ @testable import App +import Basics import Dependencies +import PackageCollectionsSigning import SnapshotTesting import Testing import Vapor @@ -829,71 +831,71 @@ extension AllTests.PackageCollectionTests { } } -// @Test( -// .disabled( -// if: !isRunningInCI() && EnvironmentClient.liveValue.collectionSigningPrivateKey() == nil, -// "Skip test for local user due to unset COLLECTION_SIGNING_PRIVATE_KEY env variable" -// ) -// ) -// func sign_collection() async throws { -// try await withDependencies { -// $0.environment.collectionSigningCertificateChain = EnvironmentClient.liveValue.collectionSigningCertificateChain -// $0.environment.collectionSigningPrivateKey = EnvironmentClient.liveValue.collectionSigningPrivateKey -// } operation: { -// // setup -// let collection: PackageCollection = .mock -// -// // MUT -// let signedCollection = try await SignedCollection.sign(collection: collection) -// -// // validate signed collection content -// #expect(!signedCollection.signature.signature.isEmpty) -// assertSnapshot(of: signedCollection, as: .json(encoder)) -// -// // validate signature -// let validated = try await SignedCollection.validate(signedCollection: signedCollection) -// #expect(validated) -// } -// } - -// @Test( -// .disabled("Skipping until issue is resolved"), -// .bug("https://github.com/SwiftPackageIndex/SwiftPackageIndex-Server/issues/1583#issuecomment-1066592057") -// ) -// func sign_collection_revoked_key() async throws { -// // setup -// let collection: PackageCollection = .mock -// // get cert and key and make sure the inputs are valid (apart from being revoked) -// // so we don't fail for that reason -// let revokedUrl = fixtureUrl(for: "revoked.cer") -// #expect(Foundation.FileManager.default.fileExists(atPath: revokedUrl.path)) -// let revokedKey = try fixtureData(for: "revoked.pem") -// -// await withDependencies { -// $0.environment.collectionSigningCertificateChain = { -// [ -// revokedUrl, -// SignedCollection.certsDir.appendingPathComponent("AppleWWDRCAG3.cer"), -// SignedCollection.certsDir.appendingPathComponent("AppleIncRootCertificate.cer") -// ] -// } -// $0.environment.collectionSigningPrivateKey = { revokedKey } -// } operation: { -// do { -// // MUT -// let signedCollection = try await SignedCollection.sign(collection: collection) -// // NB: signing _can_ succeed in case of reachability issues to verify the cert -// // in this case we need to check the signature -// // https://github.com/SwiftPackageIndex/SwiftPackageIndex-Server/issues/1583#issuecomment-1048408400 -// let validated = try await SignedCollection.validate(signedCollection: signedCollection) -// #expect(!validated) -// } catch PackageCollectionSigningError.invalidCertChain { -// // ok -// } catch { -// Issue.record("unexpected signing error: \(error)") -// } -// } -// } + @Test( + .disabled( + if: !isRunningInCI() && EnvironmentClient.liveValue.collectionSigningPrivateKey() == nil, + "Skip test for local user due to unset COLLECTION_SIGNING_PRIVATE_KEY env variable" + ) + ) + func sign_collection() async throws { + try await withDependencies { + $0.environment.collectionSigningCertificateChain = EnvironmentClient.liveValue.collectionSigningCertificateChain + $0.environment.collectionSigningPrivateKey = EnvironmentClient.liveValue.collectionSigningPrivateKey + } operation: { + // setup + let collection: PackageCollection = .mock + + // MUT + let signedCollection = try await SignedCollection.sign(collection: collection) + + // validate signed collection content + #expect(!signedCollection.signature.signature.isEmpty) + assertSnapshot(of: signedCollection, as: .json(encoder)) + + // validate signature + let validated = try await SignedCollection.validate(signedCollection: signedCollection) + #expect(validated) + } + } + + @Test( + .disabled("Skipping until issue is resolved"), + .bug("https://github.com/SwiftPackageIndex/SwiftPackageIndex-Server/issues/1583#issuecomment-1066592057") + ) + func sign_collection_revoked_key() async throws { + // setup + let collection: PackageCollection = .mock + // get cert and key and make sure the inputs are valid (apart from being revoked) + // so we don't fail for that reason + let revokedUrl = fixtureUrl(for: "revoked.cer") + #expect(Foundation.FileManager.default.fileExists(atPath: revokedUrl.path)) + let revokedKey = try fixtureData(for: "revoked.pem") + + await withDependencies { + $0.environment.collectionSigningCertificateChain = { + [ + revokedUrl, + SignedCollection.certsDir.appendingPathComponent("AppleWWDRCAG3.cer"), + SignedCollection.certsDir.appendingPathComponent("AppleIncRootCertificate.cer") + ] + } + $0.environment.collectionSigningPrivateKey = { revokedKey } + } operation: { + do { + // MUT + let signedCollection = try await SignedCollection.sign(collection: collection) + // NB: signing _can_ succeed in case of reachability issues to verify the cert + // in this case we need to check the signature + // https://github.com/SwiftPackageIndex/SwiftPackageIndex-Server/issues/1583#issuecomment-1048408400 + let validated = try await SignedCollection.validate(signedCollection: signedCollection) + #expect(!validated) + } catch PackageCollectionSigningError.invalidCertChain { + // ok + } catch { + Issue.record("unexpected signing error: \(error)") + } + } + } } From 6707f587991f17d24b3e4ca1f4123b4e00899b97 Mon Sep 17 00:00:00 2001 From: "Sven A. Schmidt" Date: Fri, 2 May 2025 11:52:22 +0200 Subject: [PATCH 2/6] Revert "Add PackageCollections dependency" This reverts commit 87733959a85e4a9d3d4c62edec205f8abfc11a85. --- Package.resolved | 11 +---------- Package.swift | 4 +--- 2 files changed, 2 insertions(+), 13 deletions(-) diff --git a/Package.resolved b/Package.resolved index 5f4fd7a4a..7c9800887 100644 --- a/Package.resolved +++ b/Package.resolved @@ -1,5 +1,5 @@ { - "originHash" : "164d58b993750ebc70c5988d01cb84a4e748196f26cab9a6869dcce591a1640e", + "originHash" : "3578d992e547a3d093812cf1621c88bd9b0016a88e71411d9a40922ba1167c14", "pins" : [ { "identity" : "async-http-client", @@ -127,15 +127,6 @@ "version" : "4.7.1" } }, - { - "identity" : "packagecollections", - "kind" : "remoteSourceControl", - "location" : "https://github.com/SwiftPackageIndex/PackageCollections.git", - "state" : { - "branch" : "main", - "revision" : "158a19b90e3a8daa051c1e9378a74356b409a54b" - } - }, { "identity" : "plot", "kind" : "remoteSourceControl", diff --git a/Package.swift b/Package.swift index 5dc2d78dc..62b24c577 100644 --- a/Package.swift +++ b/Package.swift @@ -29,10 +29,9 @@ let package = Package( dependencies: [ .package(url: "https://github.com/JohnSundell/Ink.git", from: "0.5.1"), .package(url: "https://github.com/swift-server/swift-prometheus.git", from: "1.0.0"), + .package(url: "https://github.com/SwiftPackageIndex/Plot.git", branch: "main"), .package(url: "https://github.com/SwiftPackageIndex/CanonicalPackageURL.git", from: "1.0.0"), .package(url: "https://github.com/SwiftPackageIndex/DependencyResolution.git", from: "1.1.2"), - .package(url: "https://github.com/SwiftPackageIndex/PackageCollections.git", branch: "main"), - .package(url: "https://github.com/SwiftPackageIndex/Plot.git", branch: "main"), .package(url: "https://github.com/SwiftPackageIndex/SPIManifest.git", from: "1.2.0"), .package(url: "https://github.com/SwiftPackageIndex/SemanticVersion.git", from: "0.3.0"), .package(url: "https://github.com/SwiftPackageIndex/ShellOut.git", from: "3.1.4"), @@ -68,7 +67,6 @@ let package = Package( .product(name: "DependencyResolution", package: "DependencyResolution"), .product(name: "Fluent", package: "fluent"), .product(name: "FluentPostgresDriver", package: "fluent-postgres-driver"), - .product(name: "PackageCollections", package: "PackageCollections"), .product(name: "Parsing", package: "swift-parsing"), .product(name: "Redis", package: "redis"), .product(name: "ShellOut", package: "ShellOut"), From 5fb007399ad2bd06ee14ee2790c5c019548469ed Mon Sep 17 00:00:00 2001 From: "Sven A. Schmidt" Date: Fri, 2 May 2025 11:58:04 +0200 Subject: [PATCH 3/6] Revert "Drop SwiftPM dependency" This reverts commit c1c97b6d2dbe0da83de5efd16c3c3ecb6b913132. # Conflicts: # Package.resolved --- Package.resolved | 66 +++++++++++++++++++++++++++++++++++++++++++----- Package.swift | 3 +++ 2 files changed, 63 insertions(+), 6 deletions(-) diff --git a/Package.resolved b/Package.resolved index 7c9800887..117e0d1d4 100644 --- a/Package.resolved +++ b/Package.resolved @@ -1,5 +1,5 @@ { - "originHash" : "3578d992e547a3d093812cf1621c88bd9b0016a88e71411d9a40922ba1167c14", + "originHash" : "b0eea6b76ecf34a26f9a304f3f2715eedc4657c786d6fdb7206238336b2d2678", "pins" : [ { "identity" : "async-http-client", @@ -271,6 +271,15 @@ "version" : "1.2.1" } }, + { + "identity" : "swift-argument-parser", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-argument-parser.git", + "state" : { + "revision" : "41982a3656a71c768319979febd796c6fd111d5c", + "version" : "1.5.0" + } + }, { "identity" : "swift-asn1", "kind" : "remoteSourceControl", @@ -304,7 +313,16 @@ "location" : "https://github.com/pointfreeco/swift-case-paths", "state" : { "revision" : "41b89b8b68d8c56c622dbb7132258f1a3e638b25", - "version" : "1.7.0" + "version" : "1.6.1" + } + }, + { + "identity" : "swift-certificates", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-certificates.git", + "state" : { + "revision" : "2f797305c1b5b982acaa6005d8a9f970cc4e97ff", + "version" : "1.5.0" } }, { @@ -370,6 +388,15 @@ "version" : "1.2.0" } }, + { + "identity" : "swift-driver", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-driver.git", + "state" : { + "branch" : "release/6.1", + "revision" : "a7f8f9fabc79f86cc4f089316bffe564da29e0b9" + } + }, { "identity" : "swift-http-structured-headers", "kind" : "remoteSourceControl", @@ -388,6 +415,15 @@ "version" : "1.4.0" } }, + { + "identity" : "swift-llbuild", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-llbuild.git", + "state" : { + "branch" : "release/6.1", + "revision" : "4fc005bfb0849f17e6a79ad02ba27f4f539ca6b9" + } + }, { "identity" : "swift-log", "kind" : "remoteSourceControl", @@ -460,6 +496,15 @@ "version" : "1.0.3" } }, + { + "identity" : "swift-package-manager", + "kind" : "remoteSourceControl", + "location" : "https://github.com/swiftlang/swift-package-manager.git", + "state" : { + "branch" : "release/6.1", + "revision" : "01e7c310cc3e8d76dceb2ea3f29913f87ae14d22" + } + }, { "identity" : "swift-parsing", "kind" : "remoteSourceControl", @@ -510,8 +555,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/swiftlang/swift-syntax", "state" : { - "revision" : "f99ae8aa18f0cf0d53481901f88a0991dc3bd4a2", - "version" : "601.0.1" + "branch" : "release/6.1", + "revision" : "cbd0366a54a9f8fdaa33834652fb2e80f2948573" } }, { @@ -523,13 +568,22 @@ "version" : "1.4.2" } }, + { + "identity" : "swift-toolchain-sqlite", + "kind" : "remoteSourceControl", + "location" : "https://github.com/swiftlang/swift-toolchain-sqlite", + "state" : { + "revision" : "4ee66b3ab1c40d20176045e61d8276242e73b01d", + "version" : "1.0.3" + } + }, { "identity" : "swift-tools-support-core", "kind" : "remoteSourceControl", "location" : "https://github.com/apple/swift-tools-support-core.git", "state" : { - "revision" : "b464fcd8d884e599e3202d9bd1eee29a9e504069", - "version" : "0.7.2" + "branch" : "release/6.1", + "revision" : "5cd61a77866b110bb222c38073627d2703c750e6" } }, { diff --git a/Package.swift b/Package.swift index 62b24c577..e29326d29 100644 --- a/Package.swift +++ b/Package.swift @@ -35,6 +35,7 @@ let package = Package( .package(url: "https://github.com/SwiftPackageIndex/SPIManifest.git", from: "1.2.0"), .package(url: "https://github.com/SwiftPackageIndex/SemanticVersion.git", from: "0.3.0"), .package(url: "https://github.com/SwiftPackageIndex/ShellOut.git", from: "3.1.4"), + .package(url: "https://github.com/swiftlang/swift-package-manager.git", branch: "release/6.1"), .package(url: "https://github.com/pointfreeco/swift-custom-dump.git", from: "1.0.0"), .package(url: "https://github.com/pointfreeco/swift-dependencies", from: "1.8.0"), .package(url: "https://github.com/pointfreeco/swift-parsing.git", from: "0.12.0"), @@ -70,6 +71,8 @@ let package = Package( .product(name: "Parsing", package: "swift-parsing"), .product(name: "Redis", package: "redis"), .product(name: "ShellOut", package: "ShellOut"), + .product(name: "SwiftPMDataModel-auto", package: "swift-package-manager"), + .product(name: "SwiftPMPackageCollections", package: "swift-package-manager"), .product(name: "Vapor", package: "vapor"), .product(name: "SotoCognitoAuthentication", package: "soto-cognito-authentication"), .product(name: "JWTKit", package: "jwt-kit") From eb34680c39783b37faebb6a88792d363b801641c Mon Sep 17 00:00:00 2001 From: "Sven A. Schmidt" Date: Fri, 2 May 2025 11:59:02 +0200 Subject: [PATCH 4/6] Package update --- Package.resolved | 76 ++++++++++++++++++++++++------------------------ 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/Package.resolved b/Package.resolved index 117e0d1d4..0275c34a0 100644 --- a/Package.resolved +++ b/Package.resolved @@ -1,5 +1,5 @@ { - "originHash" : "b0eea6b76ecf34a26f9a304f3f2715eedc4657c786d6fdb7206238336b2d2678", + "originHash" : "c2a3dc302e76c540d06ab4501e4d518278f4c507599b8d925a73be6e0d838533", "pins" : [ { "identity" : "async-http-client", @@ -177,8 +177,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/vapor/routing-kit.git", "state" : { - "revision" : "8c9a227476555c55837e569be71944e02a056b72", - "version" : "4.9.1" + "revision" : "93f7222c8e195cbad39fafb5a0e4cc85a8def7ea", + "version" : "4.9.2" } }, { @@ -249,8 +249,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/SwiftPackageIndex/SPIManifest.git", "state" : { - "revision" : "b4fa843a4f21a80ef8d58eca7daae39892b30a48", - "version" : "1.8.0" + "revision" : "df8dfd0295c5ec9840c2987f8adec20381243109", + "version" : "1.8.2" } }, { @@ -285,8 +285,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/apple/swift-asn1.git", "state" : { - "revision" : "ae33e5941bb88d88538d0a6b19ca0b01e6c76dcf", - "version" : "1.3.1" + "revision" : "a54383ada6cecde007d374f58f864e29370ba5c3", + "version" : "1.3.2" } }, { @@ -294,8 +294,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/apple/swift-async-algorithms.git", "state" : { - "revision" : "4c3ea81f81f0a25d0470188459c6d4bf20cf2f97", - "version" : "1.0.3" + "revision" : "042e1c4d9d19748c9c228f8d4ebc97bb1e339b0b", + "version" : "1.0.4" } }, { @@ -313,7 +313,7 @@ "location" : "https://github.com/pointfreeco/swift-case-paths", "state" : { "revision" : "41b89b8b68d8c56c622dbb7132258f1a3e638b25", - "version" : "1.6.1" + "version" : "1.7.0" } }, { @@ -357,8 +357,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/apple/swift-crypto.git", "state" : { - "revision" : "e8d6eba1fef23ae5b359c46b03f7d94be2f41fed", - "version" : "3.12.3" + "revision" : "629f0b679d0fd0a6ae823d7f750b9ab032c00b80", + "version" : "3.0.0" } }, { @@ -375,8 +375,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/pointfreeco/swift-dependencies", "state" : { - "revision" : "fee6aa29908a75437506ddcbe7434c460605b7e6", - "version" : "1.9.1" + "revision" : "4c90d6b2b9bf0911af87b103bb40f41771891596", + "version" : "1.9.2" } }, { @@ -394,7 +394,7 @@ "location" : "https://github.com/apple/swift-driver.git", "state" : { "branch" : "release/6.1", - "revision" : "a7f8f9fabc79f86cc4f089316bffe564da29e0b9" + "revision" : "20cd624311cb835f7a61c0103404fc191d392a38" } }, { @@ -402,14 +402,14 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/apple/swift-http-structured-headers.git", "state" : { - "revision" : "8e769facea6b7d46ea60e5e93635a384fd573480", - "version" : "1.2.1" + "revision" : "f280fc7676b9940ff2c6598642751ea333c6544f", + "version" : "1.2.2" } }, { "identity" : "swift-http-types", "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-http-types.git", + "location" : "https://github.com/apple/swift-http-types", "state" : { "revision" : "a0a57e949a8903563aba4615869310c0ebf14c03", "version" : "1.4.0" @@ -438,8 +438,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/apple/swift-metrics.git", "state" : { - "revision" : "44491db7cc66774ab930cf15f36324e16b06f425", - "version" : "2.6.1" + "revision" : "4c83e1cdf4ba538ef6e43a9bbd0bcc33a0ca46e3", + "version" : "2.7.0" } }, { @@ -447,8 +447,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/apple/swift-nio.git", "state" : { - "revision" : "c51907a839e63ebf0ba2076bba73dd96436bd1b9", - "version" : "2.81.0" + "revision" : "0f54d58bb5db9e064f332e8524150de379d1e51c", + "version" : "2.82.1" } }, { @@ -456,8 +456,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/apple/swift-nio-extras.git", "state" : { - "revision" : "00f3f72d2f9942d0e2dc96057ab50a37ced150d4", - "version" : "1.25.0" + "revision" : "f1f6f772198bee35d99dd145f1513d8581a54f2c", + "version" : "1.26.0" } }, { @@ -465,8 +465,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/apple/swift-nio-http2.git", "state" : { - "revision" : "170f4ca06b6a9c57b811293cebcb96e81b661310", - "version" : "1.35.0" + "revision" : "4281466512f63d1bd530e33f4aa6993ee7864be0", + "version" : "1.36.0" } }, { @@ -474,8 +474,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/apple/swift-nio-ssl.git", "state" : { - "revision" : "0cc3528ff48129d64ab9cab0b1cd621634edfc6b", - "version" : "2.29.3" + "revision" : "6df102a39c8da5fdc2eae29a0f63546d660866fc", + "version" : "2.30.0" } }, { @@ -483,8 +483,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/apple/swift-nio-transport-services.git", "state" : { - "revision" : "3c394067c08d1225ba8442e9cffb520ded417b64", - "version" : "1.23.1" + "revision" : "cd1e89816d345d2523b11c55654570acd5cd4c56", + "version" : "1.24.0" } }, { @@ -502,7 +502,7 @@ "location" : "https://github.com/swiftlang/swift-package-manager.git", "state" : { "branch" : "release/6.1", - "revision" : "01e7c310cc3e8d76dceb2ea3f29913f87ae14d22" + "revision" : "45c31f1b35ef8599898f61c26e7518bcf14b3eb5" } }, { @@ -537,8 +537,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/swift-server/swift-service-lifecycle.git", "state" : { - "revision" : "7ee57f99fbe0073c3700997186721e74d925b59b", - "version" : "2.7.0" + "revision" : "e7187309187695115033536e8fc9b2eb87fd956d", + "version" : "2.8.0" } }, { @@ -553,7 +553,7 @@ { "identity" : "swift-syntax", "kind" : "remoteSourceControl", - "location" : "https://github.com/swiftlang/swift-syntax", + "location" : "https://github.com/swiftlang/swift-syntax.git", "state" : { "branch" : "release/6.1", "revision" : "cbd0366a54a9f8fdaa33834652fb2e80f2948573" @@ -609,8 +609,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/vapor/websocket-kit.git", "state" : { - "revision" : "4232d34efa49f633ba61afde365d3896fc7f8740", - "version" : "2.15.0" + "revision" : "014ccd52891b8c098d7e1033d5e72ed76fef7a86", + "version" : "2.16.0" } }, { @@ -627,8 +627,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/jpsim/Yams.git", "state" : { - "revision" : "b4b8042411dc7bbb696300a34a4bf3ba1b7ad19b", - "version" : "5.3.1" + "revision" : "0d9ee7ea8c4ebd4a489ad7a73d5c6cad55d6fed3", + "version" : "5.0.6" } } ], From 46fc0ac397b6751eb9385da2a91ac681721706d7 Mon Sep 17 00:00:00 2001 From: "Sven A. Schmidt" Date: Fri, 2 May 2025 12:25:59 +0200 Subject: [PATCH 5/6] Fix Sendable error --- .../App/Controllers/API/API+PackageCollectionController.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/App/Controllers/API/API+PackageCollectionController.swift b/Sources/App/Controllers/API/API+PackageCollectionController.swift index a52a92147..8e788d8b2 100644 --- a/Sources/App/Controllers/API/API+PackageCollectionController.swift +++ b/Sources/App/Controllers/API/API+PackageCollectionController.swift @@ -61,7 +61,7 @@ extension API { } -extension PackageCollectionSigning.Model.SignedCollection: Vapor.Content {} +extension PackageCollectionSigning.Model.SignedCollection: @retroactive @unchecked Sendable, Vapor.Content {} extension API { From 6fc3d3f1826ed999fabbb5ecf17c7a24d4d0b7a4 Mon Sep 17 00:00:00 2001 From: "Sven A. Schmidt" Date: Fri, 2 May 2025 14:55:42 +0200 Subject: [PATCH 6/6] Revert "Merge pull request #3772 from SwiftPackageIndex/collection-signing-note" This reverts commit 545d844c3e3a4c9d460f10799e3d4375fcb407fa, reversing changes made to 21101b777f4b7963503323b850c9f766dad8f7a8. --- Sources/App/Views/Author/AuthorShow+View.swift | 4 ---- Sources/App/Views/Keyword/KeywordShow+View.swift | 4 ---- .../WebpageSnapshotTests/AuthorShow_document.1.html | 3 --- .../WebpageSnapshotTests/KeywordShow_document.1.html | 3 --- 4 files changed, 14 deletions(-) diff --git a/Sources/App/Views/Author/AuthorShow+View.swift b/Sources/App/Views/Author/AuthorShow+View.swift index 95c859f30..c666cc87c 100644 --- a/Sources/App/Views/Author/AuthorShow+View.swift +++ b/Sources/App/Views/Author/AuthorShow+View.swift @@ -57,10 +57,6 @@ enum AuthorShow { ), .text(".") ), - .p( - .strong("Note:"), - .text(" Package collection signing is temporarily disabled. Package collections generated by Swift Package Index will still work, but you may get a certificate or security warning when using them."), - ), .copyableInputForm(buttonName: "Copy Package Collection URL", eventName: "Copy Package Collection URL Button", valueToCopy: SiteURL.packageCollectionAuthor(.value(model.owner)).absoluteURL()), diff --git a/Sources/App/Views/Keyword/KeywordShow+View.swift b/Sources/App/Views/Keyword/KeywordShow+View.swift index f3124064b..64dcae58a 100644 --- a/Sources/App/Views/Keyword/KeywordShow+View.swift +++ b/Sources/App/Views/Keyword/KeywordShow+View.swift @@ -56,10 +56,6 @@ enum KeywordShow { ), .text(".") ), - .p( - .strong("Note:"), - .text(" Package collection signing is temporarily disabled. Package collections generated by Swift Package Index will still work, but you may get a certificate or security warning when using them."), - ), .copyableInputForm(buttonName: "Copy Package Collection URL", eventName: "Copy Package Collection URL Button", valueToCopy: SiteURL.packageCollectionKeyword(.value(model.keyword)).absoluteURL()), diff --git a/Tests/AppTests/__Snapshots__/WebpageSnapshotTests/AuthorShow_document.1.html b/Tests/AppTests/__Snapshots__/WebpageSnapshotTests/AuthorShow_document.1.html index 1ebe49686..47637f9dd 100644 --- a/Tests/AppTests/__Snapshots__/WebpageSnapshotTests/AuthorShow_document.1.html +++ b/Tests/AppTests/__Snapshots__/WebpageSnapshotTests/AuthorShow_document.1.html @@ -86,9 +86,6 @@

Packages authored by Test Author

These packages are available as a package collection, usable in Xcode or SwiftPM.

-

- Note: Package collection signing is temporarily disabled. Package collections generated by Swift Package Index will still work, but you may get a certificate or security warning when using them. -

diff --git a/Tests/AppTests/__Snapshots__/WebpageSnapshotTests/KeywordShow_document.1.html b/Tests/AppTests/__Snapshots__/WebpageSnapshotTests/KeywordShow_document.1.html index 23a74dec7..d04869ed6 100644 --- a/Tests/AppTests/__Snapshots__/WebpageSnapshotTests/KeywordShow_document.1.html +++ b/Tests/AppTests/__Snapshots__/WebpageSnapshotTests/KeywordShow_document.1.html @@ -86,9 +86,6 @@

Packages for keyword “networking”

These packages are available as a package collection, usable in Xcode or SwiftPM.

-

- Note: Package collection signing is temporarily disabled. Package collections generated by Swift Package Index will still work, but you may get a certificate or security warning when using them. -