mirror of
https://github.com/Such-Software/smirk-backend-core.git
synced 2026-10-17 07:21:32 +02:00
capabilities: nip05_domain must keep the handle domain users already have
Deploying the previous version showed nip05_domain = api.smirk.cash, but handles are name@smirk.cash: that is what v0.2 used, what the wallet derived by stripping 'api.' client-side, and what the kind-0 profiles already on relays carry. Since the wallet now PREFERS this field, shipping it would have silently re-rendered every handle as @api.smirk.cash and disagreed with the published profiles. Caught by checking the deployed output rather than assuming the change was inert. Default is now PUBLIC_API_URL's host with a leading 'api.' removed, preserving the established behaviour, and NIP05_DOMAIN overrides it for operators whose well-known lives elsewhere. Still explicit where it matters; the default just stops being a regression.
This commit is contained in:
+17
-6
@@ -249,16 +249,27 @@ pub fn effective_capabilities(config: &Config) -> CapabilitiesResponse {
|
|||||||
enabled: on,
|
enabled: on,
|
||||||
network: Some(net.to_string()),
|
network: Some(net.to_string()),
|
||||||
};
|
};
|
||||||
// The handle domain is the HOST of the operator's public API URL. No
|
// The handle domain. `NIP05_DOMAIN` wins when set; otherwise derive it from
|
||||||
// `api.` stripping here: if the operator wants handles at the bare domain,
|
// PUBLIC_API_URL's host with a leading `api.` removed.
|
||||||
// they say so by setting PUBLIC_API_URL to the host that actually serves
|
//
|
||||||
// /.well-known/nostr.json. Guessing is what produced unverifiable handles.
|
// The stripping is deliberate and load-bearing: handles have been
|
||||||
let nip05_domain = config
|
// `name@smirk.cash` (not `name@api.smirk.cash`) since v0.2, the wallet
|
||||||
|
// stripped `api.` client-side for exactly that reason, and published kind-0
|
||||||
|
// profiles already carry the bare form. Advertising the raw API host would
|
||||||
|
// silently re-render every existing handle and disagree with what is already
|
||||||
|
// on relays.
|
||||||
|
//
|
||||||
|
// It is still only a default. An operator whose well-known lives somewhere
|
||||||
|
// else sets NIP05_DOMAIN explicitly rather than being second-guessed.
|
||||||
|
let nip05_domain = config.identity.nip05_domain.clone().or_else(|| {
|
||||||
|
config
|
||||||
.identity
|
.identity
|
||||||
.public_api_url
|
.public_api_url
|
||||||
.as_deref()
|
.as_deref()
|
||||||
.and_then(|u| url::Url::parse(u).ok())
|
.and_then(|u| url::Url::parse(u).ok())
|
||||||
.and_then(|u| u.host_str().map(|h| h.to_ascii_lowercase()));
|
.and_then(|u| u.host_str().map(|h| h.to_ascii_lowercase()))
|
||||||
|
.map(|h| h.strip_prefix("api.").unwrap_or(&h).to_string())
|
||||||
|
});
|
||||||
CapabilitiesResponse {
|
CapabilitiesResponse {
|
||||||
version: env!("CARGO_PKG_VERSION").to_string(),
|
version: env!("CARGO_PKG_VERSION").to_string(),
|
||||||
contract_version: CAPABILITIES_CONTRACT_VERSION,
|
contract_version: CAPABILITIES_CONTRACT_VERSION,
|
||||||
|
|||||||
@@ -215,6 +215,11 @@ pub struct IdentityConfig {
|
|||||||
/// Required when Nostr identity is enabled: it is the canonical value the
|
/// Required when Nostr identity is enabled: it is the canonical value the
|
||||||
/// NIP-98 `u` tag is verified against — never the request `Host` header.
|
/// NIP-98 `u` tag is verified against — never the request `Host` header.
|
||||||
pub public_api_url: Option<String>,
|
pub public_api_url: Option<String>,
|
||||||
|
/// The domain handles live at (`name@<domain>`), advertised in
|
||||||
|
/// `/capabilities`. Defaults to `public_api_url`'s host with a leading
|
||||||
|
/// `api.` removed, which is what the wallet used to derive client-side.
|
||||||
|
/// Set explicitly when your `/.well-known/nostr.json` lives elsewhere.
|
||||||
|
pub nip05_domain: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// HMAC peppers and salts. Fail-closed: required and length-checked. These make
|
/// HMAC peppers and salts. Fail-closed: required and length-checked. These make
|
||||||
@@ -756,6 +761,7 @@ impl Config {
|
|||||||
},
|
},
|
||||||
identity: IdentityConfig {
|
identity: IdentityConfig {
|
||||||
public_api_url: env_opt("PUBLIC_API_URL"),
|
public_api_url: env_opt("PUBLIC_API_URL"),
|
||||||
|
nip05_domain: env_opt("NIP05_DOMAIN"),
|
||||||
},
|
},
|
||||||
secrets: SecretConfig {
|
secrets: SecretConfig {
|
||||||
seed_fingerprint_pepper: env_or("SEED_FINGERPRINT_PEPPER", ""),
|
seed_fingerprint_pepper: env_or("SEED_FINGERPRINT_PEPPER", ""),
|
||||||
@@ -1442,6 +1448,7 @@ mod tests {
|
|||||||
},
|
},
|
||||||
identity: IdentityConfig {
|
identity: IdentityConfig {
|
||||||
public_api_url: Some("https://backend.example.org/api/v1".into()),
|
public_api_url: Some("https://backend.example.org/api/v1".into()),
|
||||||
|
nip05_domain: None,
|
||||||
},
|
},
|
||||||
secrets: SecretConfig {
|
secrets: SecretConfig {
|
||||||
seed_fingerprint_pepper: "p".repeat(32),
|
seed_fingerprint_pepper: "p".repeat(32),
|
||||||
|
|||||||
Reference in New Issue
Block a user