From b3858392044b6843028c459d6c48e433c6b76ac2 Mon Sep 17 00:00:00 2001 From: Till JS Date: Sat, 25 Apr 2026 15:52:37 +0200 Subject: [PATCH] feat(augur): SharedLinkControls + setUnlistedExpiry/regenerate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Augur's unlisted-share backend was already wired (mana-api ALLOWED_COLLECTIONS, blob resolver, /share/[token] dispatcher, SharedAugurEntryView), but the DetailView didn't show the share controls — flipping an entry to 'unlisted' generated a token the user couldn't see, copy, regenerate, or expire. Closes the loop: - augurStore gains setUnlistedExpiry + regenerateUnlistedToken (same pattern as calendar/library/places M8.5). - DetailView's visibility section now renders SharedLinkControls when the entry is 'unlisted' — URL + copy + QR + regenerate + revoke + expiry picker. This makes augur the 4th collection with full unlisted-share support (events / library / places / augur). My previous commit's "deferred until clear demand" note was wrong — the heavy lift (backend + view component) was already done by the augur module PR; only the DetailView wiring + 2 store methods were missing. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../modules/augur/stores/entries.svelte.ts | 74 +++++++++++++ .../lib/modules/augur/views/DetailView.svelte | 102 ++++++++++-------- 2 files changed, 132 insertions(+), 44 deletions(-) diff --git a/apps/mana/apps/web/src/lib/modules/augur/stores/entries.svelte.ts b/apps/mana/apps/web/src/lib/modules/augur/stores/entries.svelte.ts index 16f02b840..37a706e15 100644 --- a/apps/mana/apps/web/src/lib/modules/augur/stores/entries.svelte.ts +++ b/apps/mana/apps/web/src/lib/modules/augur/stores/entries.svelte.ts @@ -196,4 +196,78 @@ export const augurStore = { await augurEntriesTable.update(id, patch); }, + + /** + * Force-regenerate the unlisted token. Revoke + republish — server + * gives back a new token because the prior row is marked revoked. + * UI intent: "the old link is leaked or I want a clean slate". + * Preserves the existing expiry so a rotation doesn't extend the + * link's lifetime. + */ + async regenerateUnlistedToken(id: string) { + const existing = await augurEntriesTable.get(id); + if (!existing || existing.visibility !== 'unlisted') return null; + const jwt = await authStore.getValidToken(); + if (!jwt) return null; + try { + await revokeUnlistedSnapshot({ + apiUrl: getManaApiUrl(), + jwt, + collection: 'augurEntries', + recordId: id, + }); + const blob = await buildUnlistedBlob('augurEntries', id); + const spaceId = + (existing as unknown as { spaceId?: string }).spaceId ?? getActiveSpace()?.id ?? ''; + const { token } = await publishUnlistedSnapshot({ + apiUrl: getManaApiUrl(), + jwt, + collection: 'augurEntries', + recordId: id, + spaceId, + blob, + expiresAt: existing.unlistedExpiresAt ? new Date(existing.unlistedExpiresAt) : undefined, + }); + await augurEntriesTable.update(id, { + unlistedToken: token, + updatedAt: new Date().toISOString(), + }); + return token; + } catch (e) { + console.error('[augur] regenerate failed', e); + return null; + } + }, + + /** + * Set or clear the unlisted-share expiry. Re-publishes with the new + * `expiresAt` and mirrors locally so the picker stays in sync. + * Same pattern as calendar/library/places (M8.5). + */ + async setUnlistedExpiry(id: string, expiresAt: Date | null) { + const existing = await augurEntriesTable.get(id); + if (!existing || existing.visibility !== 'unlisted') return; + const jwt = await authStore.getValidToken(); + if (!jwt) return; + try { + const blob = await buildUnlistedBlob('augurEntries', id); + const spaceId = + (existing as unknown as { spaceId?: string }).spaceId ?? getActiveSpace()?.id ?? ''; + await publishUnlistedSnapshot({ + apiUrl: getManaApiUrl(), + jwt, + collection: 'augurEntries', + recordId: id, + spaceId, + blob, + expiresAt, + }); + await augurEntriesTable.update(id, { + unlistedExpiresAt: expiresAt ? expiresAt.toISOString() : null, + updatedAt: new Date().toISOString(), + }); + } catch (e) { + console.error('[augur] setUnlistedExpiry failed', e); + } + }, }; diff --git a/apps/mana/apps/web/src/lib/modules/augur/views/DetailView.svelte b/apps/mana/apps/web/src/lib/modules/augur/views/DetailView.svelte index a0e0e448e..1098abc7b 100644 --- a/apps/mana/apps/web/src/lib/modules/augur/views/DetailView.svelte +++ b/apps/mana/apps/web/src/lib/modules/augur/views/DetailView.svelte @@ -11,6 +11,7 @@ -->