fix(02-review): audit and set explicit persist on every useCachedResource call site
Demo images / Build & push demo images (push) Successful in 3m36s

Now that persist is required (no default) on useCachedResource()/refresh(),
every call site that previously relied on the implicit persist:true default
needs an explicit decision. Full audit, decision rule: money/identity/
peer-identity payloads -> false; static/aggregate/non-identifying data ->
true; ambiguous cases fail safe to false and are called out below.

persist:false (financial / identity / peer-identity payload):
- LightningChannelsPanel.vue: lnd.channels, lnd.closed-channels (open/closed
  Lightning channel balances — wallet data, same class as CR-01's lnd-info)
- Cloud.vue: cloud.paid-items (carries paid_sats + purchase history),
  cloud.peer-nodes (PeerNode carries did/pubkey/onion)
- Cloud.vue/PeerFiles.vue: cloud.my-files — not a clean money/identity/
  peer-identity case, but a private per-user file listing; chosen false as
  the fail-safe default per the audit rule, flagged here for review
- Credentials.vue: credentials.identities, credentials.list
- Federation.vue: federation.nodes (FederatedNode carries did — matches
  Mesh.vue's already-persist:false federation.nodes decision)
- FipsSeedAnchorsCard.vue: server.fips-seed-anchors (SeedAnchor carries npub)
- Server.vue + FipsNetworkCard.vue: server.fips-summary corrected from
  persist:true to persist:false — this shared cache key's real fips.status
  response carries npub (this node's own FIPS identity key), which
  Server.vue's narrower local type didn't surface but FipsNetworkCard.vue's
  fuller FipsStatus type does; both call sites must agree since a mismatch
  trips the dev-only entry() persist-consistency warning. Found during this
  audit, not part of the originally-scoped call-site list — corrected as a
  same-class T-02-01 violation. serverTabCache.test.ts updated to match.

persist:true (aggregate/status/public data, no identity or money):
- AppDetails.vue: app-details:bitcoin-sync (block height/sync progress)
- Cloud.vue: cloud.section-counts (bare per-section item counts);
  cloud.peer-browse (browsePeer()/loadCatalog()'s direct resources.refresh()
  calls now pass { persist: true } explicitly, matching the pre-existing
  decision already documented at peerBrowseEntry())
- Federation.vue: federation.dwn-status (sync status/counters only)
- MarketplaceAppDetails.vue: app-details:versions (public catalog metadata)
- Monitoring.vue: monitoring.current/history/alerts/alert-rules (system
  metrics and alert metadata only)
- OpenWrtGateway.vue: server.openwrt-status (network/router status, matches
  sibling server.* resources)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
archipelago
2026-07-31 06:49:16 -04:00
co-authored by Claude Opus 5
parent 5bfe608893
commit b839111571
13 changed files with 51 additions and 8 deletions
@@ -139,9 +139,14 @@ interface FipsStatus {
// Shares `server.fips-summary` with the Local Network card's FIPS row, so
// both paint from the same cache instantly on revisit and never disagree.
// persist:false (T-02-01) — the response carries `npub`, this node's own
// FIPS identity public key; must match Server.vue's persist decision for
// this same key exactly (a mismatch would trip the dev-only entry() warning
// and leave it ambiguous which decision actually governs the shared cache).
const statusRes = useCachedResource<FipsStatus>({
key: 'server.fips-summary',
ttlMs: 15_000,
persist: false,
fetcher: (signal) => rpcClient.call<FipsStatus>({ method: 'fips.status', signal, dedup: true, maxRetries: 1 }),
})
const status = computed<FipsStatus>(() => statusRes.data.value ?? {
@@ -116,6 +116,7 @@ const anchorsRes = useCachedResource<SeedAnchor[]>({
})
return res.seed_anchors
},
persist: false, // SeedAnchor carries an npub (peer identity key material) — T-02-01
})
const anchors = computed(() => anchorsRes.data.value ?? [])
const adding = ref(false)
@@ -93,6 +93,7 @@ const routerResource = useCachedResource<RouterStatus>({
maxRetries: 1,
}),
ttlMs: 30_000,
persist: true, // router/network status (host/uptime/wifi/wan) — no identity/money payload
immediate: false, // initial fetch is gated explicitly in onMounted below
})
const status = computed(() => routerResource.data.value)