Vouch for a funding.json manifest, when this relay is configured to
funding.json is how FLOSS/fund takes applications: a manifest in the repository rather than a proposal, submitted to their directory by URL. Its provenance rule is that a manifest served from a code host while claiming a hostname needs that hostname to confirm it, which is what .well-known/funding-manifest-urls is for. FN_FUNDING_MANIFESTS holds the URLs, whitespace or comma separated, and anything not beginning with https:// is dropped at config time. Unset means the route 404s, for the same reason the contact addresses render as nothing when unconfigured: a relay somebody else runs must never tell a funder that donations for it reach us. The manifest itself carries a legal name, a contact address and bank details, so it stays in the repository and out of this binary. Verified against a local relay: 404 with the variable unset, 200 with it set, and an http:// entry passed alongside an https:// one was filtered out rather than served. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
41580da291
commit
a3675e49c6
@@ -22,6 +22,17 @@ struct Config: Sendable {
|
||||
let reportsTo: String?
|
||||
/// Who runs this relay, for the pages and security.txt that say so.
|
||||
var contact: ContactAddresses = ContactAddresses(env: [:], fallback: nil)
|
||||
/// The funding.json manifests this domain vouches for, from
|
||||
/// `FN_FUNDING_MANIFESTS`, whitespace or comma separated.
|
||||
///
|
||||
/// funding.json carries an operator's legal name, contact address and bank
|
||||
/// details, so it lives in the repository rather than in this binary, and a
|
||||
/// manifest hosted somewhere else needs the domain it claims to say it is
|
||||
/// genuine. That is what `.well-known/funding-manifest-urls` is for. Unset
|
||||
/// means the route 404s, for the same reason the contact addresses above
|
||||
/// render as nothing when unconfigured: a self-hosted relay must never
|
||||
/// advertise somebody else's funding.
|
||||
let fundingManifests: [String]
|
||||
let donateProvider: String?
|
||||
let donateSecret: String?
|
||||
/// The Stripe connected account donations are taken on, or nil to take them
|
||||
@@ -274,6 +285,10 @@ struct Config: Sendable {
|
||||
smtp: SMTPConfig(env: env),
|
||||
reportsTo: env["FN_REPORTS_TO"].flatMap { $0.isEmpty ? nil : $0 },
|
||||
contact: ContactAddresses(env: env, fallback: env["FN_REPORTS_TO"]),
|
||||
fundingManifests: (env["FN_FUNDING_MANIFESTS"] ?? "")
|
||||
.split(whereSeparator: { $0 == "," || $0.isWhitespace })
|
||||
.map(String.init)
|
||||
.filter { $0.hasPrefix("https://") },
|
||||
donateProvider: env["FN_DONATE_PROVIDER"].flatMap { $0.isEmpty ? nil : $0 },
|
||||
donateSecret: env["FN_DONATE_SECRET"].flatMap { $0.isEmpty ? nil : $0 },
|
||||
donateAccount: env["FN_DONATE_ACCOUNT"].flatMap { $0.isEmpty ? nil : $0 },
|
||||
|
||||
@@ -1249,6 +1249,21 @@ func register(routes r: Routes, on app: Application) throws {
|
||||
app.get(".well-known", "assetlinks.json") { _ -> Response in
|
||||
try AppLinks.json(AppLinks.android)
|
||||
}
|
||||
// The manifests this domain vouches for, one URL per line, per the
|
||||
// funding.json provenance rule: a manifest served from a code host claims
|
||||
// this hostname, so this hostname has to confirm it.
|
||||
//
|
||||
// Unset configuration means 404, like security.txt above. A relay somebody
|
||||
// else runs must not tell a funder that donations for it reach us.
|
||||
app.get(".well-known", "funding-manifest-urls") { _ -> Response in
|
||||
let urls = r.config.fundingManifests
|
||||
guard !urls.isEmpty else { throw Abort(.notFound) }
|
||||
return Response(
|
||||
status: .ok,
|
||||
headers: ["Content-Type": "text/plain; charset=utf-8"],
|
||||
body: .init(string: urls.joined(separator: "\n") + "\n"))
|
||||
}
|
||||
|
||||
app.get(".well-known", "security.txt") { req -> Response in
|
||||
// RFC 9116 requires Expires, and a stale one is worse than none: it
|
||||
// tells a researcher the file is abandoned.
|
||||
|
||||
Reference in New Issue
Block a user