Submissions: make the resolved-set durable so handled items stay handled

Resolved submissions were resurfacing (most visibly after a cache clear)
because the admin resolved-set wasn't durable: it was never mirrored (relays
pruned it) and the read-modify-write could republish a SHRUNK replaceable
list when a cold-load read missed the current set.

- Device-local resolved-id cache (localStorage): grows only, backs up the
  relay list. Hides handled items even if a relay read momentarily misses,
  and makes markSubmissionResolved loss-proof — it folds every locally-known
  resolved id into each republish, so a missed read can't drop entries.
- Mirror the resolved-set on each fetch (re-broadcast) so relays keep it
  alive, same as we do for pending submissions.
- Persist relay-known resolved ids into the local cache on fetch.
- Belt-and-suspenders: an application whose applicant is already whitelisted
  is treated as handled even if the resolved-set were lost entirely
  (callers now pass accessControl.getWhitelist()).
- tests: whitelist-hide, local-hide after a cold read, and loss-proof
  republish (earlier id carried forward despite a missed read).

Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
thePR0M3TH3ANandClaude Opus 4.8 committed 2026-07-07 17:02:20 -04:00
1 parent 6134a6bb78
commit 55db677637
4 files changed
+194 -20

No files matched your search

+6 -1
View File
@@ -973,7 +973,12 @@ export default class ApplicationBootstrap {
const editorHexes = Array.from(accessControl.getEditors?.() || [])
.map((npub) => app.safeDecodeNpub(npub))
.filter(Boolean);
const list = await fetchPendingSubmissions({ adminHex, editorHexes });
const whitelistNpubs = Array.from(accessControl.getWhitelist?.() || []);
const list = await fetchPendingSubmissions({
adminHex,
editorHexes,
whitelistNpubs,
});
pending = Array.isArray(list) && list.length > 0;
}
}