All checks were successful
Deleting a pond already had a strict prompt — typing the pond name, stricter than a confirm dialog. That was never the gap. The gap is that the person who deletes it loses access the moment they do: the pond leaves their view, only a Site Admin can bring it back, and the export is no longer reachable for them. So the archive is offered INSIDE the deletion flow, before the button. What it contains, and why it is not the existing export: - Every page the requester may read, as Markdown, as before. - **Every attachment of the pond**, not only the embedded ones. An attachment nobody put on a page would otherwise vanish unnoticed — which is the whole reason this issue exists. - `manifest.json`: pond settings (EFFECTIVE, defaults filled in — a preservation format must not require its reader to know Dorfteich's defaults), labels, the page hierarchy and sort keys, comments, and attachment metadata including the #199 hash so a reader can verify bytes. It extends the #210 manifest rather than adding a second descriptor, and carries an explicit `formatVersion`. - `README.txt`, because the manifest is for machines: whoever unpacks a folder of Markdown a year from now must not believe they hold a one-click restore. Decisions worth naming: - **"Complete" describes the RESULT, not the route.** A pond admin who may read every page gets `complete: true`; only an archive that actually leaves pages out is incomplete. The Site-Admin route skips the read filter (an archive taken before an irreversible purge must not depend on which ponds the operator happens to be a member of) — those are two different questions and the first version of this conflated them. - **The omission is named before the download**, with its number, in the UI and in the manifest. An archive silently missing content is worse than no archive, because it ends the search. - **Not downloading stays allowed.** A pond of test pages should not require one, and the server cannot tell whether a file arrived anyway — so the finality is stated in text instead of enforced. - **A plain link, not fetch-into-a-blob.** The api streams the ZIP; buffering a whole pond in the tab to draw a progress bar would trade memory for cosmetics. The browser reports progress and completion; what it cannot say — that the archive is being BUILT — is announced in a live region. - Read trail unchanged in kind (ADR 0023): one `export` event per classified page before any classified byte enters the stream. Attachments never travel without their page, so the same events cover them. - New audit action `pond.archived` (catalogue v1.7) with page and attachment counts, omitted pages, and completeness. Format documented in `docs/architecture/pond-archive-format.md`, including what is deliberately NOT in it (history, permissions, trash). Verified by hand, not only asserted: a real pond's archive downloaded and unpacked — README, manifest, three page files, the media file; the manifest's effective settings, per-page classification, the VS-NfD frontmatter and marking preserved in the classified page's Markdown, and the attachment's sha256 present. Plus six api tests (including that an unembedded attachment travels and that a Site Admin gets a complete archive without membership) and the a11y pack 11/11 in both schemes, which now also scans the pond settings screen. Not done, because there is nothing to attach it to: the Site Admin's purge dialog (#193) exists only as an api endpoint — there is no pond-trash UI in the web app. The api half is here and tested, so it becomes a link when that screen is built.
114 lines
4.2 KiB
JSON
114 lines
4.2 KiB
JSON
{
|
||
"statusbar": {
|
||
"label": "Page information",
|
||
"updated": "Updated {{date}}",
|
||
"words_one": "{{count}} word",
|
||
"words_other": "{{count}} words",
|
||
"readingTime": "~{{minutes}} min read"
|
||
},
|
||
"layout": {
|
||
"sidebar": {
|
||
"expand": "Show sidebar",
|
||
"collapse": "Hide sidebar",
|
||
"resize": "Resize sidebar",
|
||
"label": "Pages",
|
||
"placeholder": "Your ponds and pages will appear here.",
|
||
"empty": "No pages yet.",
|
||
"sortLabel": "Sort pages",
|
||
"sortMode": {
|
||
"alpha": "A–Z",
|
||
"created": "Creation date",
|
||
"manual": "Manual order"
|
||
},
|
||
"reorder": {
|
||
"up": "Move up",
|
||
"down": "Move down",
|
||
"dragHint": "Drag to reorder",
|
||
"moved": "Moved {{title}} to position {{position}} of {{count}}.",
|
||
"reparented": "Moved {{title}} under {{parent}}."
|
||
},
|
||
"newPage": "+ New page",
|
||
"newPageHint": "New page",
|
||
"newPageTitle": "Title",
|
||
"newPageUnder": "Will be created under “{{title}}”.",
|
||
"create": "Create",
|
||
"cancel": "Cancel",
|
||
"view": {
|
||
"toggleLabel": "Sidebar view",
|
||
"folders": "Folders",
|
||
"labels": "Labels",
|
||
"unlabeled": "Unlabeled",
|
||
"expand": "Expand subpages",
|
||
"collapseNode": "Collapse subpages",
|
||
"defaultTitle": "Sidebar view",
|
||
"defaultLabel": "Default view",
|
||
"defaultHint": "The default for all members; everyone can switch their own sidebar locally.",
|
||
"saved": "Saved."
|
||
},
|
||
"favorites": {
|
||
"filter": "Favorites",
|
||
"empty": "No favorites in this pond yet."
|
||
}
|
||
},
|
||
"pondSwitcher": {
|
||
"label": "Switch pond",
|
||
"trigger": "Select a pond"
|
||
},
|
||
"user": {
|
||
"anonymous": "Not signed in"
|
||
},
|
||
"skipToContent": "Skip to content"
|
||
},
|
||
"pondHome": {
|
||
"empty": "This pond doesn't have any pages yet — create one from the sidebar."
|
||
},
|
||
"home": {
|
||
"title": "Welcome to Dorfteich",
|
||
"intro": "Dorfteich is an open-source wiki with real-time collaboration. This instance is being set up.",
|
||
"api": {
|
||
"checking": "Checking API …",
|
||
"ok": "API reachable",
|
||
"error": "API not reachable"
|
||
}
|
||
},
|
||
"notFound": {
|
||
"title": "Page not found",
|
||
"body": "The address you opened does not exist.",
|
||
"home": "Back to the start page"
|
||
},
|
||
"pond": {
|
||
"create": {
|
||
"menuItem": "+ New pond",
|
||
"title": "Create a shared pond",
|
||
"nameLabel": "Name",
|
||
"descriptionLabel": "Description (optional)",
|
||
"submit": "Create pond",
|
||
"cancel": "Cancel",
|
||
"quotaHint": "Shared ponds count against your quota — ask a site admin if creation is rejected."
|
||
},
|
||
"delete": {
|
||
"title": "Delete pond",
|
||
"hint": "Moves this pond with all of its pages to the site-level trash. A site admin can restore it. Your personal pond cannot be deleted.",
|
||
"confirmLabel": "Type the pond name to confirm: {{name}}",
|
||
"submit": "Delete pond",
|
||
"deleted": "Pond deleted."
|
||
},
|
||
"archive": {
|
||
"intro": "Before you delete: download a full archive of this pond here. It contains every page as Markdown, ALL attachments — including those no page embeds — plus settings, labels, comments and the page structure in a manifest.json.",
|
||
"omitted_one": "Careful: there is one page in this pond you cannot read, so it is missing from the archive.",
|
||
"omitted_other": "Careful: there are {{count}} pages in this pond you cannot read, so they are missing from the archive.",
|
||
"noImport": "The archive is a preservation format: it cannot currently be imported back. The format is documented so an importer can be written later — so do not rely on it to bring the pond back at the push of a button.",
|
||
"download": "Download the full archive",
|
||
"started": "The archive is being built; the download starts as soon as it is ready.",
|
||
"finality": "You do not have to download it. But without an archive: once the trash retention period is over the pond is removed for good — after that nothing of it remains, neither pages nor files."
|
||
}
|
||
},
|
||
"settingsNav": {
|
||
"label": "Sections"
|
||
},
|
||
"tableActions": "Actions",
|
||
"classification": {
|
||
"label": "Classification"
|
||
}
|
||
}
|