Add trust features: history, trash, export, and collection sharing
release gate / check (push) Failing after 6m36s

Implement Notion-like upgrade phase 4: append-only page revisions with restore-as-a-new-version; recoverable bookmark/page/collection deletions whose restores never resurrect public flags or shares; owner-scoped JSON export; and explicit, revocable read-only collection sharing with owner-only mutations and no transitive third-party bookmark leaks. Add migration 009, API/docs, integration coverage, and page/collections/trash UI.
This commit is contained in:
Andrew S Erwin
2026-10-19 23:07:38 -05:00
parent 9db69efe4b
commit 5eab58f99c
22 changed files with 1496 additions and 76 deletions
+1 -1
View File
@@ -176,7 +176,7 @@ export function BookmarksClient({ initialSearch = null, initialOpen = null }: {
<div className="flex gap-1" onClick={(e: React.MouseEvent) => e.stopPropagation()}>
<a href={b.url} target="_blank" rel="noopener noreferrer"><ExternalLink className="h-4 w-4 text-muted-foreground hover:text-primary" /></a>
{tab === 'mine' && (
<button onClick={async () => { if (!confirm('Delete?')) return; try { const res = await fetch(`/api/bookmarks/${b.id}`, { method: 'DELETE' }); if (res.ok) { toast.success('Deleted'); load() } else toast.error('Could not delete bookmark') } catch { toast.error('Could not delete bookmark') } }}><Trash2 className="h-4 w-4 text-muted-foreground hover:text-destructive" /></button>
<button onClick={async () => { if (!confirm('Move this bookmark to the trash? It can be restored.')) return; try { const res = await fetch(`/api/bookmarks/${b.id}`, { method: 'DELETE' }); if (res.ok) { toast.success('Moved to trash'); load() } else toast.error('Could not move bookmark to trash') } catch { toast.error('Could not move bookmark to trash') } }}><Trash2 className="h-4 w-4 text-muted-foreground hover:text-destructive" /></button>
)}
</div>
</td>