feat(content): owned-content persistence + Fedimint paid downloads, fmcd caps fix, FIPS warm-path perf
Buyer-side paid downloads now persist: purchases are cached on disk (content_owned.rs) keyed by (seller onion, content_id), the gallery shows an "Owned" badge unblurred, and items view/play in-app from the local cache with no re-payment or reliance on a browser download (which silently failed on the mobile companion). New RPCs content.owned-list / content.owned-get. Validated e2e .116<-.198 (paid 100 sats via Fedimint, 166KB jpeg returns, survives restart). fedimint-clientd manifest: restore the standard container capability set (CHOWN/DAC_OVERRIDE/FOWNER/SETUID/SETGID) so fmcd's startup chown of an existing-federation /data succeeds instead of dying EPERM (#7). Confirmed the orchestrator applies these to the running container. FIPS perf: tighten the supervisor warm-path keepalive 45s -> 25s so peer paths stay inside the ~30-60s NAT cold window. Dials now reliably land on FIPS instead of re-punching and falling back to Tor. Measured to the same peer: cloud browse 18-22s -> 0.4s; full Fedimint paid download 29s -> 11s (residual is the seller-side guardian reissue round-trip). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
b0c9bd2a0c
commit
db7d424bff
@@ -169,6 +169,34 @@ pub async fn ensure_default_federation(data_dir: &Path) -> Result<()> {
|
||||
Ok(c) => c,
|
||||
Err(_) => return Ok(()), // clientd not configured yet
|
||||
};
|
||||
|
||||
// Fast path: if fmcd already reports a joined federation, do NOT re-issue the
|
||||
// POST /v2/admin/join. That call re-syncs federation config against the
|
||||
// guardians and adds seconds of latency — and ensure_default_federation runs
|
||||
// on every wallet.fedimint-list / spend / reissue, so the join was being paid
|
||||
// on each balance refresh (the "mints take ages to load" report). The cheap
|
||||
// GET /v2/admin/info is enough to confirm membership; just reconcile the local
|
||||
// registry against the live joined set and return.
|
||||
let joined = client.joined_federation_ids().await;
|
||||
if !joined.is_empty() {
|
||||
let mut reg = load_registry(data_dir).await?;
|
||||
let mut changed = false;
|
||||
for id in joined {
|
||||
if !reg.federations.iter().any(|f| f.federation_id == id) {
|
||||
reg.federations.push(JoinedFederation {
|
||||
federation_id: id,
|
||||
name: Some("Archipelago Federation".to_string()),
|
||||
});
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
if changed {
|
||||
save_registry(data_dir, ®).await?;
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// Cold start only: nothing joined yet, so join the default federation once.
|
||||
let federation_id = match client.join(DEFAULT_FEDERATION_INVITE).await {
|
||||
Ok(id) => id,
|
||||
Err(e) => {
|
||||
|
||||
Reference in New Issue
Block a user