From 3fd8c97f0dc0680933a4bde5a123e8f59ddd046b Mon Sep 17 00:00:00 2001 From: bntvllnt <32437578+bntvllnt@users.noreply.github.com> Date: Sat, 3 Oct 2026 23:16:54 +0200 Subject: [PATCH 1/2] chore(design): track recoverable Penpot snapshots --- design/penpot/.gitignore | 5 + design/penpot/README.md | 106 ++ design/penpot/STATUS.md | 92 ++ design/penpot/snapshots/2026-10-03/SHA256SUMS | 2 + .../penpot/snapshots/2026-10-03/complete.json | 1104 +++++++++++++++++ .../penpot/snapshots/2026-10-03/partial.json | 373 ++++++ .../snapshots/2026-10-03/verification.json | 303 +++++ scripts/penpot_snapshot.py | 157 +++ scripts/test_penpot_snapshot.py | 124 ++ 9 files changed, 2266 insertions(+) create mode 100644 design/penpot/.gitignore create mode 100644 design/penpot/README.md create mode 100644 design/penpot/STATUS.md create mode 100644 design/penpot/snapshots/2026-10-03/SHA256SUMS create mode 100644 design/penpot/snapshots/2026-10-03/complete.json create mode 100644 design/penpot/snapshots/2026-10-03/partial.json create mode 100644 design/penpot/snapshots/2026-10-03/verification.json create mode 100644 scripts/penpot_snapshot.py create mode 100644 scripts/test_penpot_snapshot.py diff --git a/design/penpot/.gitignore b/design/penpot/.gitignore new file mode 100644 index 00000000..dab26745 --- /dev/null +++ b/design/penpot/.gitignore @@ -0,0 +1,5 @@ +# Native exports live in versioned GitHub release assets. +*.penpot +*.zip +downloads/ +__pycache__/ diff --git a/design/penpot/README.md b/design/penpot/README.md new file mode 100644 index 00000000..b8c4730d --- /dev/null +++ b/design/penpot/README.md @@ -0,0 +1,106 @@ +# Penpot design snapshots + +Native, editable Penpot exports are stored as GitHub release assets. Git tracks +their exact SHA-256 checksums, file inventories, revisions, library links and +qualification notes. This saves the design outside the Penpot server without +putting hundreds of megabytes into every clone. No Git LFS or Python packages +are required. The checker requires Python 3.9 or newer. + +[Initial recovery release](https://github.com/vllnt/ui/releases/tag/penpot-snapshot-2026-10-03) +— [migration status and remaining work](STATUS.md). + +## Current recovery points + +| Receipt | Native export | Coverage | Qualification | +| --- | --- | --- | --- | +| [complete.json](snapshots/2026-10-03/complete.json) | 2026-10-02; 300,739,780 bytes | 39 canonical modules + Starter; 1,854 component definitions | Historical complete backup. Native recovery/reopen was previously checked; later corrections are absent. | +| [partial.json](snapshots/2026-10-03/partial.json) | 2026-10-03; 68,988,603 bytes | 15 modules; 873 component definitions | Newer saved state for the listed files only. Combined archive has not undergone a native reimport/reopen test. | + +These are two separate recovery points, not an automatically merged latest +backup. Importing the partial archive on top of the full one is **not** a proven +update procedure: native imports can create new IDs and library relationships. +Use separate recovery projects and check the complete dependency graph before +promoting any recovered copy. + +The per-file `filePayloadSha256` is computed over sorted file-owned ZIP member +paths and their byte hashes. It stays stable across ZIP repacking/compression, +but changes when saved file content or metadata changes. The archive hash also +protects shared media and thumbnails. Counts exclude the synthetic page roots. +An inventory describes saved data; it is not a visual or runtime acceptance test. + +## Download and verify + +From the repository root (GitHub CLI required only for the download): + +```sh +mkdir -p design/penpot/downloads/2026-10-03 +gh release download penpot-snapshot-2026-10-03 --repo vllnt/ui \ + --pattern '*.penpot' --dir design/penpot/downloads/2026-10-03 +python3 scripts/penpot_snapshot.py verify \ + design/penpot/snapshots/2026-10-03/complete.json \ + design/penpot/snapshots/2026-10-03/partial.json \ + --asset-dir design/penpot/downloads/2026-10-03 +``` + +The checker reads every ZIP member to check CRC integrity and compares the +archive size, SHA-256, and full inventory with the committed receipt. It does not +extract archives, contact Penpot, or modify any design. A missing, corrupt or +mismatched archive fails with a nonzero exit code. + +## Recover safely in Penpot + +1. Verify the downloaded archive with the command above. +2. Create a separate recovery project in the `vllnt` team, then use Penpot's + dashboard file import for the native `.penpot` export. +3. Compare the imported file names/counts, library links and component catalog + with the receipt. Imports may assign different IDs. Open every imported file, + run native validation, and save/reopen it. Check media, fonts and layout. +4. Test a component from the recovered shared libraries in a separate consumer + file, including a source update and an instance override. +5. Promote only after those checks. Keep the original Pen source, current + canonical files and previous snapshots until recovery and consumers pass. + +This is a file-level recovery mechanism, not a backup of the entire self-hosted +server. Accounts, permissions, history, comments, database and service +configuration require the server's own backup system. + +## Save the next design batch + +1. Confirm the exact file ID and that its content is saved. In Penpot, create a + named version before a risky edit. The public plugin API also supports + `await penpot.currentFile.saveVersion("Before ")`; always verify the + expected file ID first. Versions are local to the server and do not replace + off-server exports. +2. Export native `.penpot` files with their linked libraries. Prefer a complete + canonical-project export plus the Starter. Clearly label any smaller export + as partial. Never assume the currently focused trial covers all 39 modules. +3. Use a new tag and receipt path, without replacing an earlier release asset: + +```sh +python3 scripts/penpot_snapshot.py record /path/to/export.penpot \ + --output design/penpot/snapshots//.json \ + --exported-on \ + --scope 'PARTIAL: list the included modules and exclusions' \ + --release-tag penpot-snapshot-- \ + --note 'Saved archive; native reopen/visual/consumer checks: state actual results' +``` + +4. Review the inventory and its Git diff. Scope and export date are operator + declarations; the tool cannot establish that an export is current or complete. +5. Commit the receipt and qualification notes, then attach the native export to + a versioned GitHub release targeting that commit. Keep design snapshots out + of the software “Latest” release (`gh release create ... --latest=false`). + The repository is public: publish only reviewed design assets, never auth + state, environment files, server backups or raw browser diagnostics. +6. Download the uploaded assets into a fresh directory and run `verify` against + the committed receipts. Record native reimport/reopen separately. Never + describe hash verification alone as a successful native restore. + +No scheduled exports are configured. Future saves require a native export and +a new receipt/release; the Git records do not continuously mirror live Penpot. + +## Check the tracking tool + +```sh +python3 -m unittest discover -s scripts -p 'test_penpot_snapshot.py' -v +``` diff --git a/design/penpot/STATUS.md b/design/penpot/STATUS.md new file mode 100644 index 00000000..14d9161e --- /dev/null +++ b/design/penpot/STATUS.md @@ -0,0 +1,92 @@ +# Penpot migration status — 2026-10-03 + +The full design has been imported, but migration acceptance is still open. +Keep the original `design/vllnt-ui.pen`, legacy content and all previous recovery +points. A successful import or checksum is not proof that every component looks +and behaves correctly. + +## Destination and authority + +- Team: `vllnt` (`922b72d2-2185-8146-8008-b95add9df3c4`). +- Canonical project: `503b8235-8be1-80bf-8008-ba5ff4e2d3b6`. +- Starter consumer: `503b8235-8be1-80bf-8008-ba83182b5131`. +- The 39 canonical file IDs/names are in [complete.json](snapshots/2026-10-03/complete.json), alongside the Starter. +- Files prefixed `[Validation]` or `[Recovery]` are trials or restore copies. + They must not be mistaken for canonical libraries. + +## Verified evidence + +- The historical complete archive contains 39 canonical modules plus Starter: + **210 source boards, 245,024 shapes, 1,854 component definitions, 159 library + relationships**. Source coverage checks found no missing boards, shapes, + components or token bindings. The strict 39-file checker flags the additional + Starter; the known 40-file scope was separately qualified and the original + finding is retained in [verification.json](snapshots/2026-10-03/verification.json). +- The newer partial export covers **15 modules, 129 source boards, 55,001 shapes, + 873 component definitions and 45 relationships**. Within that scope, no source + objects/components/token bindings are missing. It is not a fresh full backup. +- The live catalog check found **29 canonical shared libraries and 1,844 visible + entries**. Atoms 02 groups 13 states into 3 variant families, explaining the + difference from 1,854 saved definitions. No canonical library is missing. +- Six connected libraries expose seven token sets, 1,439 token entries and four + themes. This proves availability; it does not prove propagation or appearance + in every consumer. Older saved archives contain earlier token states. +- Saved effect conservation matched 8,205 shapes, 9,236 shadows and 892 background + blurs. Media metadata and both JPEG payload hashes matched the source cache. + These checks do not establish every crop or visual rendering. +- Native MCP access worked during the audit. Its focused document was a private + glyph validation trial at revision 16, with zero native validation errors. + This says nothing about native validation of all 39 canonical files. + +## Remaining work, in dependency order + +1. **Baseline and recovery:** obtain a fresh full export of all canonical files + and current consumers; validate each file, reimport into a separate recovery + project, save/reopen, and compare dependency links. The latest combined + partial archive still needs this native restore test. +2. **Engine qualification:** qualify the consolidated Penpot fixes in the + optimized Linux build before deployment. Isolated lab checks passed, but + deployment, rollback and the complete optimized-bundle test matrix are not + proven. Ordinary MCP work does not require a new Docker deployment. +3. **Tokens and themes:** prove safe updates and all four theme contexts through + representative consumers, then cover every component family. Keep the + tokens → atoms → molecules → organisms → templates → pages dependency order. +4. **Fonts:** historical evidence minus accepted canonical fixes leaves **1,311 + regular aliases, six italic aliases and one unavailable IBM Plex Mono 800 + style**. The newer partial archive directly contains 1,263 regular aliases, + six italic aliases and that unavailable style; the other 48 are based on + older saved evidence. Re-audit before editing. Private trials are not fixes + to canonical files. +5. **Atoms and glyphs:** complete 182 glyph uses across nine modules, including + 106 hidden uses. The 31-item private trial remains unreceived: its saved + geometry/order checks passed, but 148 reflected descendants remain. Preserve + it as a trial until rendering, replacement and consumer behavior pass. +6. **Paint fidelity:** resolve six angular-gradient cases (two fill, four + border). Review the queues of 675 cap/join, 271 per-side stroke, 96 arc and 79 + gradient records; these are review candidates, not proven corrupt counts. +7. **Variants and molecules:** extend native variant/override/swap/update proof + beyond the three Selection families. Molecules 07 has a historical 3,773 + outside-subtree difference set. Its private update trial lost 596 sizing + attributes; a workaround protects 536 and leaves 60 open. The engine + candidate passed 596/596 in isolation, not in canonical acceptance. +8. **Organisms and templates:** finish mixed-font/layout review. Molecules 01 + has 58 source dimensions changed by up to 9 px in the lab; Organisms 01 has + a small geometry reservation; Templates 01's protected paragraph difference + remains unreceived. Then verify page composition and source propagation. +9. **Final acceptance:** visual review, complete shared-library consumer proof, + native full recovery/reopen, and a final off-server snapshot. Only then + update repository authority from Pen to Penpot and retire individual legacy + replacements whose consumers are proven. No bulk deletion. + +The older design-system ledger (315 modules: 122 partial, 193 pending) measures +broader design acceptance, not 315 missing imports. Keyboard, touch, voice, +dynamic states, reduced motion and actual AR-runtime checks remain separate +implementation evidence; a Penpot canvas does not prove them. + +## Snapshot policy + +Use [the recovery workflow](README.md) after each accepted design batch. Keep +native named versions for quick rollback and native exports outside the server +for disaster recovery. The initial release preserves the historical full and +newer partial archives without claiming an automatic merge or continuous sync. +No scheduled automation has been restarted. diff --git a/design/penpot/snapshots/2026-10-03/SHA256SUMS b/design/penpot/snapshots/2026-10-03/SHA256SUMS new file mode 100644 index 00000000..0586a58b --- /dev/null +++ b/design/penpot/snapshots/2026-10-03/SHA256SUMS @@ -0,0 +1,2 @@ +e2086dfe1b6f53be182ef83513115787833e4f86b27cad6b2a5ef6948c1b38b7 vllnt-ui-native-complete-with-starter-2026-10-02.penpot +854731617ba8df4294d3374d6096548103bd98d0a0a99b48e4ca2c9282c764c1 vllnt-ui-partial-native-refresh-2026-10-03.penpot diff --git a/design/penpot/snapshots/2026-10-03/complete.json b/design/penpot/snapshots/2026-10-03/complete.json new file mode 100644 index 00000000..131486aa --- /dev/null +++ b/design/penpot/snapshots/2026-10-03/complete.json @@ -0,0 +1,1104 @@ +{ + "schemaVersion": 1, + "exportedOn": "2026-10-02", + "scope": "HISTORICAL COMPLETE: 39 canonical modules plus the Starter consumer", + "note": "Preserves 210 source boards and 1854 component definitions. Prior native recovery/reopen was checked on 2026-10-02. Later corrections are absent. Saved structure and CRC/SHA were rechecked on 2026-10-03; visual and runtime acceptance remain incomplete.", + "release": "https://github.com/vllnt/ui/releases/tag/penpot-snapshot-2026-10-03", + "asset": { + "name": "vllnt-ui-native-complete-with-starter-2026-10-02.penpot", + "bytes": 300739780, + "sha256": "e2086dfe1b6f53be182ef83513115787833e4f86b27cad6b2a5ef6948c1b38b7" + }, + "inventory": { + "generatedBy": "penpot/2.18.0", + "archiveMembers": 247926, + "totals": { + "files": 40, + "sharedLibraries": 29, + "pages": 41, + "shapes": 245024, + "components": 1854, + "libraryRelations": 159 + }, + "files": [ + { + "id": "503b8235-8be1-80bf-8008-ba6ae7797c76", + "name": "VLLNT UI — 00 Guide · 01", + "revision": 1, + "modifiedAt": "2026-10-02T12:40:48.313313Z", + "sharedLibrary": false, + "pages": 1, + "shapes": 78, + "components": 0, + "filePayloadSha256": "db95e63653225ffd11d906d13f925ec13b8f5cd2200c460a505d281cd7f04258" + }, + { + "id": "503b8235-8be1-80bf-8008-ba6ae7797c77", + "name": "VLLNT UI — 01 Foundations · 01", + "revision": 1, + "modifiedAt": "2026-10-02T12:42:25.770742Z", + "sharedLibrary": false, + "pages": 1, + "shapes": 237, + "components": 0, + "filePayloadSha256": "6ab474f5fb5c4d5ba8379cb68c098eed0c72b8fc197c0becda22e8b392e59906" + }, + { + "id": "503b8235-8be1-80bf-8008-ba6ae7797c78", + "name": "VLLNT UI — 02 Atoms · 01", + "revision": 4, + "modifiedAt": "2026-10-02T14:33:26.165379Z", + "sharedLibrary": true, + "pages": 1, + "shapes": 434, + "components": 43, + "filePayloadSha256": "d051ad2380f2a029450b2075996913757333dbd0bf91015a4ba3eec028be9289" + }, + { + "id": "503b8235-8be1-80bf-8008-ba6ae7797c79", + "name": "VLLNT UI — 00 Guide · 02", + "revision": 1, + "modifiedAt": "2026-10-02T12:42:38.660553Z", + "sharedLibrary": false, + "pages": 1, + "shapes": 1863, + "components": 0, + "filePayloadSha256": "b892f45a67a5bd82d77a233138d803b05f812712093d99c4b457fa59ea28a1e7" + }, + { + "id": "503b8235-8be1-80bf-8008-ba6ae7797c7a", + "name": "VLLNT UI — 01 Foundations · 02", + "revision": 1, + "modifiedAt": "2026-10-02T12:43:41.914443Z", + "sharedLibrary": false, + "pages": 1, + "shapes": 32, + "components": 0, + "filePayloadSha256": "141073a4aee49d62c2a0023732ac9018609fe55746c4fc9377dd197b0dbe7c77" + }, + { + "id": "503b8235-8be1-80bf-8008-ba6ae7797c7b", + "name": "VLLNT UI — 02 Atoms · 02", + "revision": 0, + "modifiedAt": "2026-10-02T14:12:39.858378Z", + "sharedLibrary": true, + "pages": 1, + "shapes": 4682, + "components": 184, + "filePayloadSha256": "1a3a351ebf45ef6a01c2288b11b98a2fa1827f5a7b7bb68b63b6e78b9b809edf" + }, + { + "id": "503b8235-8be1-80bf-8008-ba6ae7797c7c", + "name": "VLLNT UI — 03 Molecules · 01", + "revision": 1, + "modifiedAt": "2026-10-02T14:12:41.427709Z", + "sharedLibrary": true, + "pages": 1, + "shapes": 2850, + "components": 140, + "filePayloadSha256": "649b7bc049f479338419599c2761c1325f34bcce15f4fcd9928b4a7260275e1f" + }, + { + "id": "503b8235-8be1-80bf-8008-ba6ae7797c7d", + "name": "VLLNT UI — 04 Organisms · 01", + "revision": 2, + "modifiedAt": "2026-10-02T14:12:43.276232Z", + "sharedLibrary": true, + "pages": 1, + "shapes": 5755, + "components": 112, + "filePayloadSha256": "e79e10aff938753f01e04fd20a7a9bde86bf53b6b9eb6926d1178d833bc5efd2" + }, + { + "id": "503b8235-8be1-80bf-8008-ba6ae7797c7e", + "name": "VLLNT UI — 05 Templates · 01", + "revision": 1, + "modifiedAt": "2026-10-02T14:14:33.854304Z", + "sharedLibrary": true, + "pages": 1, + "shapes": 196, + "components": 1, + "filePayloadSha256": "6b182e441b3fc42940d64096b18a01f5e2848afa002ce7ef3e45c2b3df3aedc9" + }, + { + "id": "503b8235-8be1-80bf-8008-ba6ae7797c7f", + "name": "VLLNT UI — 07 Reference contexts", + "revision": 1, + "modifiedAt": "2026-10-02T12:45:33.965216Z", + "sharedLibrary": false, + "pages": 1, + "shapes": 178, + "components": 0, + "filePayloadSha256": "735e89e823cd46f8fb4bbc9390b7962ddea0454c80e3d2661eb5b0c6f1cd3e01" + }, + { + "id": "503b8235-8be1-80bf-8008-ba6ae7797c80", + "name": "VLLNT UI — 08 Review evidence · 01", + "revision": 1, + "modifiedAt": "2026-10-02T12:45:42.177588Z", + "sharedLibrary": false, + "pages": 1, + "shapes": 26, + "components": 0, + "filePayloadSha256": "66d556f168ad8700e98e489ab0df3d332149ba78916e6494ec2d937aed267c57" + }, + { + "id": "503b8235-8be1-80bf-8008-ba6ae7797c81", + "name": "VLLNT UI — 09 Legacy catalog · 01", + "revision": 1, + "modifiedAt": "2026-10-02T14:14:36.410871Z", + "sharedLibrary": true, + "pages": 1, + "shapes": 3, + "components": 1, + "filePayloadSha256": "f03d3e19652051cd2efe7a4091e49ac63fdc7c98727e5aafdc8a5c076f8edd61" + }, + { + "id": "503b8235-8be1-80bf-8008-ba6ae7797c82", + "name": "VLLNT UI — 02 Atoms · 03", + "revision": 1, + "modifiedAt": "2026-10-02T14:14:39.302351Z", + "sharedLibrary": true, + "pages": 1, + "shapes": 3378, + "components": 67, + "filePayloadSha256": "b9707b84daf60b91cfb70cf4e9066ed95ee533027f524a06f3213b1c1bc4f5dd" + }, + { + "id": "503b8235-8be1-80bf-8008-ba6ae7797c83", + "name": "VLLNT UI — 03 Molecules · 02", + "revision": 1, + "modifiedAt": "2026-10-02T14:14:42.256134Z", + "sharedLibrary": true, + "pages": 1, + "shapes": 1023, + "components": 67, + "filePayloadSha256": "940d4ca9cdf4ee5448c97aa777d6b72d89dcc68a8701a13ff29f1120e986e586" + }, + { + "id": "503b8235-8be1-80bf-8008-ba6ae7797c84", + "name": "VLLNT UI — 01 Foundations · 03", + "revision": 1, + "modifiedAt": "2026-10-02T12:46:36.427374Z", + "sharedLibrary": false, + "pages": 1, + "shapes": 232, + "components": 0, + "filePayloadSha256": "8d8024b22c495253b01289dfd739006a4386aaa8ed431fd6478ce3010dfbafca" + }, + { + "id": "503b8235-8be1-80bf-8008-ba6ae7797c85", + "name": "VLLNT UI — 02 Atoms · 04", + "revision": 1, + "modifiedAt": "2026-10-02T14:14:44.621056Z", + "sharedLibrary": true, + "pages": 1, + "shapes": 258, + "components": 1, + "filePayloadSha256": "1e8e3337e74459e86a2a9b0564f27557d3e59db7bb8653eb8317e00baed12af9" + }, + { + "id": "503b8235-8be1-80bf-8008-ba6ae7797c86", + "name": "VLLNT UI — 03 Molecules · 03", + "revision": 0, + "modifiedAt": "2026-10-02T14:14:47.933235Z", + "sharedLibrary": true, + "pages": 1, + "shapes": 10867, + "components": 34, + "filePayloadSha256": "63c2d70d64953918565adacf9fa674f0efbbaad798f058b0a121e3d70fc3b0aa" + }, + { + "id": "503b8235-8be1-80bf-8008-ba6ae7797c87", + "name": "VLLNT UI — 02 Atoms · 05", + "revision": 1, + "modifiedAt": "2026-10-02T14:15:05.780827Z", + "sharedLibrary": true, + "pages": 1, + "shapes": 2932, + "components": 50, + "filePayloadSha256": "bb519b9b06eb0e9a19347745eb6608dccbc45f55c343891a5e5465c7fdb971bd" + }, + { + "id": "503b8235-8be1-80bf-8008-ba6ae7797c88", + "name": "VLLNT UI — 03 Molecules · 04", + "revision": 1, + "modifiedAt": "2026-10-02T14:15:08.614454Z", + "sharedLibrary": true, + "pages": 1, + "shapes": 7897, + "components": 6, + "filePayloadSha256": "cb24ad85048727c7d223f8da1c9afa5d37a01dc1bc6f57a835b8ee64e7eea58d" + }, + { + "id": "503b8235-8be1-80bf-8008-ba6ae7797c89", + "name": "VLLNT UI — 03 Molecules · 05", + "revision": 1, + "modifiedAt": "2026-10-02T14:15:12.405152Z", + "sharedLibrary": true, + "pages": 1, + "shapes": 32931, + "components": 176, + "filePayloadSha256": "ad8249b87ea1d62867d59bf2329df5159dec8cea3d9c10c3bd3fe3c37080cd3d" + }, + { + "id": "503b8235-8be1-80bf-8008-ba6ae7797c8a", + "name": "VLLNT UI — 03 Molecules · 06", + "revision": 2, + "modifiedAt": "2026-10-02T14:15:15.055662Z", + "sharedLibrary": true, + "pages": 1, + "shapes": 16220, + "components": 120, + "filePayloadSha256": "7d208eebff450829af5201e0886eb73b7db830d958453296bd2dc4b315341c91" + }, + { + "id": "503b8235-8be1-80bf-8008-ba6ae7797c8b", + "name": "VLLNT UI — 04 Organisms · 02", + "revision": 1, + "modifiedAt": "2026-10-02T14:15:17.519766Z", + "sharedLibrary": true, + "pages": 1, + "shapes": 815, + "components": 19, + "filePayloadSha256": "234a4149e44c3e1dc2df1f2cef5d6dc11a76662485fceca9d11b8e95155bc5f0" + }, + { + "id": "503b8235-8be1-80bf-8008-ba6ae7797c8c", + "name": "VLLNT UI — 01 Foundations · 04", + "revision": 1, + "modifiedAt": "2026-10-02T14:15:19.982012Z", + "sharedLibrary": true, + "pages": 1, + "shapes": 273, + "components": 8, + "filePayloadSha256": "dd5636e92e0af24a55c1d82ca4d2a2adbf63289ca213e019bdc99a5dc2624ff1" + }, + { + "id": "503b8235-8be1-80bf-8008-ba6ae7797c8d", + "name": "VLLNT UI — 02 Atoms · 06", + "revision": 1, + "modifiedAt": "2026-10-02T14:15:22.419657Z", + "sharedLibrary": true, + "pages": 1, + "shapes": 563, + "components": 26, + "filePayloadSha256": "18a913cc9eda2eee0826c0396799d99837103ece8d46cd130c3668d261db15d0" + }, + { + "id": "503b8235-8be1-80bf-8008-ba6ae7797c8e", + "name": "VLLNT UI — 03 Molecules · 07", + "revision": 0, + "modifiedAt": "2026-10-02T14:15:24.941894Z", + "sharedLibrary": true, + "pages": 1, + "shapes": 14142, + "components": 98, + "filePayloadSha256": "c7ff6d412cb3de005b7bec86cef14baf3a1047edb829f4eb110b7d9c92e0355a" + }, + { + "id": "503b8235-8be1-80bf-8008-ba6ae7797c8f", + "name": "VLLNT UI — 04 Organisms · 03", + "revision": 1, + "modifiedAt": "2026-10-02T14:15:48.606408Z", + "sharedLibrary": true, + "pages": 1, + "shapes": 1650, + "components": 24, + "filePayloadSha256": "b8223e031794f7eccc654dd001d8538c35b4f6f85583189db8b7461cf876dd77" + }, + { + "id": "503b8235-8be1-80bf-8008-ba6ae7797c90", + "name": "VLLNT UI — 01 Foundations · 05", + "revision": 1, + "modifiedAt": "2026-10-02T14:15:51.910695Z", + "sharedLibrary": true, + "pages": 2, + "shapes": 3024, + "components": 13, + "filePayloadSha256": "0e7481d2b19a00dd65f06066fc92e0c4181c3d405ffb25b706e6c47c3e0d46ca" + }, + { + "id": "503b8235-8be1-80bf-8008-ba6ae7797c91", + "name": "VLLNT UI — 03 Molecules · 08", + "revision": 2, + "modifiedAt": "2026-10-02T14:15:54.389463Z", + "sharedLibrary": true, + "pages": 1, + "shapes": 25727, + "components": 87, + "filePayloadSha256": "c5027f4d06c75af957149a14a5ad2476da862921a6f213ccebd715c1784d4396" + }, + { + "id": "503b8235-8be1-80bf-8008-ba6ae7797c92", + "name": "VLLNT UI — 04 Organisms · 04", + "revision": 0, + "modifiedAt": "2026-10-02T14:15:57.360176Z", + "sharedLibrary": true, + "pages": 1, + "shapes": 8605, + "components": 71, + "filePayloadSha256": "0724a6455d3a80ff2651f9f2f28743e1313983edca96a38f4bb49783a4209be2" + }, + { + "id": "503b8235-8be1-80bf-8008-ba6ae7797c93", + "name": "VLLNT UI — 03 Molecules · 09", + "revision": 2, + "modifiedAt": "2026-10-02T14:16:00.062552Z", + "sharedLibrary": true, + "pages": 1, + "shapes": 22715, + "components": 141, + "filePayloadSha256": "71edb2f2c3daa5a79ade1d5232b72098b2a29f41fdc544f81a8b6448526271af" + }, + { + "id": "503b8235-8be1-80bf-8008-ba6ae7797c94", + "name": "VLLNT UI — 04 Organisms · 05", + "revision": 2, + "modifiedAt": "2026-10-02T14:16:04.097891Z", + "sharedLibrary": true, + "pages": 1, + "shapes": 9002, + "components": 94, + "filePayloadSha256": "9dd7c52cd0be033258abee08a7cb49770778e6cb1d745fadee37b9f84670391f" + }, + { + "id": "503b8235-8be1-80bf-8008-ba6ae7797c95", + "name": "VLLNT UI — 04 Organisms · 06", + "revision": 2, + "modifiedAt": "2026-10-02T14:16:08.711782Z", + "sharedLibrary": true, + "pages": 1, + "shapes": 27147, + "components": 187, + "filePayloadSha256": "d3f578eedac26f32f1655f55ba939a6ae3a8cadd91bd7d2fc21cdb7a33988b51" + }, + { + "id": "503b8235-8be1-80bf-8008-ba6ae7797c96", + "name": "VLLNT UI — 04 Organisms · 07", + "revision": 2, + "modifiedAt": "2026-10-02T14:16:11.866828Z", + "sharedLibrary": true, + "pages": 1, + "shapes": 17165, + "components": 9, + "filePayloadSha256": "a72f0ed254d0107a1293c0cba2ca69771c706e2f35b3b10ff351d545e137c158" + }, + { + "id": "503b8235-8be1-80bf-8008-ba6ae7797c97", + "name": "VLLNT UI — 05 Templates · 02", + "revision": 1, + "modifiedAt": "2026-10-02T14:16:44.396341Z", + "sharedLibrary": true, + "pages": 1, + "shapes": 2486, + "components": 17, + "filePayloadSha256": "6d292a5d6eb0afe9014e0d2fbaa40628cb2707be0439d7047933b998e9e9735d" + }, + { + "id": "503b8235-8be1-80bf-8008-ba6ae7797c98", + "name": "VLLNT UI — 04 Organisms · 08", + "revision": 1, + "modifiedAt": "2026-10-02T14:16:48.036346Z", + "sharedLibrary": true, + "pages": 1, + "shapes": 12949, + "components": 54, + "filePayloadSha256": "6c29835ce859d63ed3623d24200d227a3b957c13c085e0e4c71d32b95908bee6" + }, + { + "id": "503b8235-8be1-80bf-8008-ba6ae7797c99", + "name": "VLLNT UI — 05 Templates · 03", + "revision": 1, + "modifiedAt": "2026-10-02T14:16:50.621253Z", + "sharedLibrary": true, + "pages": 1, + "shapes": 263, + "components": 4, + "filePayloadSha256": "28a483a44a2615ae3279f588b1c14bf91ada6c4626d4c1b3171b33a55592c2a6" + }, + { + "id": "503b8235-8be1-80bf-8008-ba6ae7797c9a", + "name": "VLLNT UI — 06 Pages", + "revision": 1, + "modifiedAt": "2026-10-02T13:12:24.671045Z", + "sharedLibrary": false, + "pages": 1, + "shapes": 754, + "components": 0, + "filePayloadSha256": "a302fe3bf3d0c3cedb7b6ba9fb53f09606f8e3402c30591b0a35a31580328a05" + }, + { + "id": "503b8235-8be1-80bf-8008-ba6ae7797c9b", + "name": "VLLNT UI — 08 Review evidence · 02", + "revision": 1, + "modifiedAt": "2026-10-02T13:12:44.714463Z", + "sharedLibrary": false, + "pages": 1, + "shapes": 117, + "components": 0, + "filePayloadSha256": "afb387eed611129dc666eece1ca75e0c589fc6ee91b13850f64149c2252ffa10" + }, + { + "id": "503b8235-8be1-80bf-8008-ba6ae7797c9c", + "name": "VLLNT UI — 09 Legacy catalog · 02", + "revision": 1, + "modifiedAt": "2026-10-02T13:13:19.384089Z", + "sharedLibrary": false, + "pages": 1, + "shapes": 5543, + "components": 0, + "filePayloadSha256": "b5766897f6505a55c8d421111ad03fc955b3eaa7a76e54371d911ea01aa6f3ff" + }, + { + "id": "503b8235-8be1-80bf-8008-ba83182b5131", + "name": "VLLNT UI — Starter", + "revision": 4, + "modifiedAt": "2026-10-02T14:37:04.928042Z", + "sharedLibrary": false, + "pages": 1, + "shapes": 12, + "components": 0, + "filePayloadSha256": "cb7a3f797341b51a138f6b8502d6de677feec35ebb7697f5df0e3177d5fc86f8" + } + ], + "libraryRelations": [ + [ + "503b8235-8be1-80bf-8008-ba6ae7797c79", + "503b8235-8be1-80bf-8008-ba6ae7797c78" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c7a", + "503b8235-8be1-80bf-8008-ba6ae7797c78" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c7b", + "503b8235-8be1-80bf-8008-ba6ae7797c78" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c7c", + "503b8235-8be1-80bf-8008-ba6ae7797c78" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c7d", + "503b8235-8be1-80bf-8008-ba6ae7797c78" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c7f", + "503b8235-8be1-80bf-8008-ba6ae7797c7b" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c7f", + "503b8235-8be1-80bf-8008-ba6ae7797c7c" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c81", + "503b8235-8be1-80bf-8008-ba6ae7797c78" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c82", + "503b8235-8be1-80bf-8008-ba6ae7797c78" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c82", + "503b8235-8be1-80bf-8008-ba6ae7797c7b" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c82", + "503b8235-8be1-80bf-8008-ba6ae7797c81" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c83", + "503b8235-8be1-80bf-8008-ba6ae7797c78" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c83", + "503b8235-8be1-80bf-8008-ba6ae7797c81" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c84", + "503b8235-8be1-80bf-8008-ba6ae7797c78" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c84", + "503b8235-8be1-80bf-8008-ba6ae7797c83" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c85", + "503b8235-8be1-80bf-8008-ba6ae7797c78" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c85", + "503b8235-8be1-80bf-8008-ba6ae7797c7b" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c85", + "503b8235-8be1-80bf-8008-ba6ae7797c81" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c85", + "503b8235-8be1-80bf-8008-ba6ae7797c82" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c85", + "503b8235-8be1-80bf-8008-ba6ae7797c83" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c86", + "503b8235-8be1-80bf-8008-ba6ae7797c78" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c86", + "503b8235-8be1-80bf-8008-ba6ae7797c7b" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c86", + "503b8235-8be1-80bf-8008-ba6ae7797c7c" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c86", + "503b8235-8be1-80bf-8008-ba6ae7797c82" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c87", + "503b8235-8be1-80bf-8008-ba6ae7797c78" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c87", + "503b8235-8be1-80bf-8008-ba6ae7797c7b" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c87", + "503b8235-8be1-80bf-8008-ba6ae7797c86" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c88", + "503b8235-8be1-80bf-8008-ba6ae7797c78" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c88", + "503b8235-8be1-80bf-8008-ba6ae7797c7b" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c88", + "503b8235-8be1-80bf-8008-ba6ae7797c7c" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c88", + "503b8235-8be1-80bf-8008-ba6ae7797c82" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c88", + "503b8235-8be1-80bf-8008-ba6ae7797c86" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c89", + "503b8235-8be1-80bf-8008-ba6ae7797c78" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c89", + "503b8235-8be1-80bf-8008-ba6ae7797c7b" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c89", + "503b8235-8be1-80bf-8008-ba6ae7797c82" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c89", + "503b8235-8be1-80bf-8008-ba6ae7797c83" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c8a", + "503b8235-8be1-80bf-8008-ba6ae7797c78" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c8a", + "503b8235-8be1-80bf-8008-ba6ae7797c7b" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c8a", + "503b8235-8be1-80bf-8008-ba6ae7797c7c" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c8a", + "503b8235-8be1-80bf-8008-ba6ae7797c81" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c8a", + "503b8235-8be1-80bf-8008-ba6ae7797c82" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c8a", + "503b8235-8be1-80bf-8008-ba6ae7797c83" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c8a", + "503b8235-8be1-80bf-8008-ba6ae7797c89" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c8b", + "503b8235-8be1-80bf-8008-ba6ae7797c78" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c8b", + "503b8235-8be1-80bf-8008-ba6ae7797c83" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c8c", + "503b8235-8be1-80bf-8008-ba6ae7797c78" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c8c", + "503b8235-8be1-80bf-8008-ba6ae7797c83" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c8c", + "503b8235-8be1-80bf-8008-ba6ae7797c8b" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c8d", + "503b8235-8be1-80bf-8008-ba6ae7797c78" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c8d", + "503b8235-8be1-80bf-8008-ba6ae7797c8c" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c8e", + "503b8235-8be1-80bf-8008-ba6ae7797c78" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c8e", + "503b8235-8be1-80bf-8008-ba6ae7797c7b" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c8e", + "503b8235-8be1-80bf-8008-ba6ae7797c81" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c8e", + "503b8235-8be1-80bf-8008-ba6ae7797c82" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c8e", + "503b8235-8be1-80bf-8008-ba6ae7797c83" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c8e", + "503b8235-8be1-80bf-8008-ba6ae7797c85" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c8e", + "503b8235-8be1-80bf-8008-ba6ae7797c86" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c8e", + "503b8235-8be1-80bf-8008-ba6ae7797c8c" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c8f", + "503b8235-8be1-80bf-8008-ba6ae7797c78" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c8f", + "503b8235-8be1-80bf-8008-ba6ae7797c81" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c8f", + "503b8235-8be1-80bf-8008-ba6ae7797c83" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c8f", + "503b8235-8be1-80bf-8008-ba6ae7797c8c" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c90", + "503b8235-8be1-80bf-8008-ba6ae7797c78" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c90", + "503b8235-8be1-80bf-8008-ba6ae7797c81" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c90", + "503b8235-8be1-80bf-8008-ba6ae7797c83" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c90", + "503b8235-8be1-80bf-8008-ba6ae7797c8f" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c91", + "503b8235-8be1-80bf-8008-ba6ae7797c78" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c91", + "503b8235-8be1-80bf-8008-ba6ae7797c7c" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c91", + "503b8235-8be1-80bf-8008-ba6ae7797c81" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c91", + "503b8235-8be1-80bf-8008-ba6ae7797c82" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c91", + "503b8235-8be1-80bf-8008-ba6ae7797c83" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c91", + "503b8235-8be1-80bf-8008-ba6ae7797c8f" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c91", + "503b8235-8be1-80bf-8008-ba6ae7797c90" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c92", + "503b8235-8be1-80bf-8008-ba6ae7797c78" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c92", + "503b8235-8be1-80bf-8008-ba6ae7797c81" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c92", + "503b8235-8be1-80bf-8008-ba6ae7797c83" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c92", + "503b8235-8be1-80bf-8008-ba6ae7797c8f" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c93", + "503b8235-8be1-80bf-8008-ba6ae7797c78" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c93", + "503b8235-8be1-80bf-8008-ba6ae7797c7b" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c93", + "503b8235-8be1-80bf-8008-ba6ae7797c81" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c93", + "503b8235-8be1-80bf-8008-ba6ae7797c83" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c93", + "503b8235-8be1-80bf-8008-ba6ae7797c87" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c93", + "503b8235-8be1-80bf-8008-ba6ae7797c89" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c93", + "503b8235-8be1-80bf-8008-ba6ae7797c8c" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c93", + "503b8235-8be1-80bf-8008-ba6ae7797c8e" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c93", + "503b8235-8be1-80bf-8008-ba6ae7797c92" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c94", + "503b8235-8be1-80bf-8008-ba6ae7797c78" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c94", + "503b8235-8be1-80bf-8008-ba6ae7797c7b" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c94", + "503b8235-8be1-80bf-8008-ba6ae7797c7c" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c94", + "503b8235-8be1-80bf-8008-ba6ae7797c81" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c94", + "503b8235-8be1-80bf-8008-ba6ae7797c82" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c94", + "503b8235-8be1-80bf-8008-ba6ae7797c83" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c94", + "503b8235-8be1-80bf-8008-ba6ae7797c89" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c94", + "503b8235-8be1-80bf-8008-ba6ae7797c8e" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c94", + "503b8235-8be1-80bf-8008-ba6ae7797c91" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c94", + "503b8235-8be1-80bf-8008-ba6ae7797c92" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c95", + "503b8235-8be1-80bf-8008-ba6ae7797c78" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c95", + "503b8235-8be1-80bf-8008-ba6ae7797c7b" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c95", + "503b8235-8be1-80bf-8008-ba6ae7797c82" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c95", + "503b8235-8be1-80bf-8008-ba6ae7797c83" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c95", + "503b8235-8be1-80bf-8008-ba6ae7797c89" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c95", + "503b8235-8be1-80bf-8008-ba6ae7797c8b" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c95", + "503b8235-8be1-80bf-8008-ba6ae7797c8c" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c95", + "503b8235-8be1-80bf-8008-ba6ae7797c91" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c96", + "503b8235-8be1-80bf-8008-ba6ae7797c78" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c96", + "503b8235-8be1-80bf-8008-ba6ae7797c7b" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c96", + "503b8235-8be1-80bf-8008-ba6ae7797c7c" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c96", + "503b8235-8be1-80bf-8008-ba6ae7797c81" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c96", + "503b8235-8be1-80bf-8008-ba6ae7797c82" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c96", + "503b8235-8be1-80bf-8008-ba6ae7797c86" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c96", + "503b8235-8be1-80bf-8008-ba6ae7797c88" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c96", + "503b8235-8be1-80bf-8008-ba6ae7797c8a" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c96", + "503b8235-8be1-80bf-8008-ba6ae7797c8c" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c97", + "503b8235-8be1-80bf-8008-ba6ae7797c78" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c97", + "503b8235-8be1-80bf-8008-ba6ae7797c81" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c97", + "503b8235-8be1-80bf-8008-ba6ae7797c83" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c97", + "503b8235-8be1-80bf-8008-ba6ae7797c8b" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c97", + "503b8235-8be1-80bf-8008-ba6ae7797c8c" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c97", + "503b8235-8be1-80bf-8008-ba6ae7797c8f" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c97", + "503b8235-8be1-80bf-8008-ba6ae7797c92" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c98", + "503b8235-8be1-80bf-8008-ba6ae7797c78" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c98", + "503b8235-8be1-80bf-8008-ba6ae7797c7b" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c98", + "503b8235-8be1-80bf-8008-ba6ae7797c81" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c98", + "503b8235-8be1-80bf-8008-ba6ae7797c82" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c98", + "503b8235-8be1-80bf-8008-ba6ae7797c83" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c98", + "503b8235-8be1-80bf-8008-ba6ae7797c87" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c98", + "503b8235-8be1-80bf-8008-ba6ae7797c89" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c98", + "503b8235-8be1-80bf-8008-ba6ae7797c8c" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c98", + "503b8235-8be1-80bf-8008-ba6ae7797c8e" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c98", + "503b8235-8be1-80bf-8008-ba6ae7797c8f" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c98", + "503b8235-8be1-80bf-8008-ba6ae7797c90" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c98", + "503b8235-8be1-80bf-8008-ba6ae7797c91" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c98", + "503b8235-8be1-80bf-8008-ba6ae7797c92" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c98", + "503b8235-8be1-80bf-8008-ba6ae7797c97" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c99", + "503b8235-8be1-80bf-8008-ba6ae7797c78" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c99", + "503b8235-8be1-80bf-8008-ba6ae7797c7d" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c99", + "503b8235-8be1-80bf-8008-ba6ae7797c81" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c99", + "503b8235-8be1-80bf-8008-ba6ae7797c83" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c99", + "503b8235-8be1-80bf-8008-ba6ae7797c8f" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c99", + "503b8235-8be1-80bf-8008-ba6ae7797c92" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c9a", + "503b8235-8be1-80bf-8008-ba6ae7797c78" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c9a", + "503b8235-8be1-80bf-8008-ba6ae7797c7d" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c9a", + "503b8235-8be1-80bf-8008-ba6ae7797c81" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c9a", + "503b8235-8be1-80bf-8008-ba6ae7797c83" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c9a", + "503b8235-8be1-80bf-8008-ba6ae7797c8b" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c9a", + "503b8235-8be1-80bf-8008-ba6ae7797c8f" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c9a", + "503b8235-8be1-80bf-8008-ba6ae7797c92" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c9a", + "503b8235-8be1-80bf-8008-ba6ae7797c97" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c9a", + "503b8235-8be1-80bf-8008-ba6ae7797c99" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c9b", + "503b8235-8be1-80bf-8008-ba6ae7797c78" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c9b", + "503b8235-8be1-80bf-8008-ba6ae7797c83" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c9c", + "503b8235-8be1-80bf-8008-ba6ae7797c78" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c9c", + "503b8235-8be1-80bf-8008-ba6ae7797c81" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c9c", + "503b8235-8be1-80bf-8008-ba6ae7797c83" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c9c", + "503b8235-8be1-80bf-8008-ba6ae7797c8c" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c9c", + "503b8235-8be1-80bf-8008-ba6ae7797c8f" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c9c", + "503b8235-8be1-80bf-8008-ba6ae7797c90" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c9c", + "503b8235-8be1-80bf-8008-ba6ae7797c97" + ], + [ + "503b8235-8be1-80bf-8008-ba83182b5131", + "503b8235-8be1-80bf-8008-ba6ae7797c78" + ] + ] + } +} diff --git a/design/penpot/snapshots/2026-10-03/partial.json b/design/penpot/snapshots/2026-10-03/partial.json new file mode 100644 index 00000000..42c30c3c --- /dev/null +++ b/design/penpot/snapshots/2026-10-03/partial.json @@ -0,0 +1,373 @@ +{ + "schemaVersion": 1, + "exportedOn": "2026-10-03", + "scope": "PARTIAL: 15 canonical modules listed in this receipt; excludes 24 modules and Starter", + "note": "Combined from native exports with 3037 identical overlaps; preserves 129 source boards, 873 component definitions and 54998 original shapes plus 3 Selection variant containers. Saved structure/CRC/SHA checked; combined archive native reimport/reopen and visual acceptance are not yet proven. Not an automatic overlay for the complete snapshot.", + "release": "https://github.com/vllnt/ui/releases/tag/penpot-snapshot-2026-10-03", + "asset": { + "name": "vllnt-ui-partial-native-refresh-2026-10-03.penpot", + "bytes": 68988603, + "sha256": "854731617ba8df4294d3374d6096548103bd98d0a0a99b48e4ca2c9282c764c1" + }, + "inventory": { + "generatedBy": "penpot/2.18.0", + "archiveMembers": 56617, + "totals": { + "files": 15, + "sharedLibraries": 15, + "pages": 15, + "shapes": 55001, + "components": 873, + "libraryRelations": 45 + }, + "files": [ + { + "id": "503b8235-8be1-80bf-8008-ba6ae7797c78", + "name": "VLLNT UI — 02 Atoms · 01", + "revision": 4, + "modifiedAt": "2026-10-02T14:33:26.165379Z", + "sharedLibrary": true, + "pages": 1, + "shapes": 434, + "components": 43, + "filePayloadSha256": "d051ad2380f2a029450b2075996913757333dbd0bf91015a4ba3eec028be9289" + }, + { + "id": "503b8235-8be1-80bf-8008-ba6ae7797c7b", + "name": "VLLNT UI — 02 Atoms · 02", + "revision": 7, + "modifiedAt": "2026-10-03T05:33:27.417967Z", + "sharedLibrary": true, + "pages": 1, + "shapes": 4685, + "components": 184, + "filePayloadSha256": "cbff5d7199f225c53298305d05e979d44f7ec4ea621473640c794c0ad79d9d44" + }, + { + "id": "503b8235-8be1-80bf-8008-ba6ae7797c7c", + "name": "VLLNT UI — 03 Molecules · 01", + "revision": 2, + "modifiedAt": "2026-10-03T06:37:04.208326Z", + "sharedLibrary": true, + "pages": 1, + "shapes": 2850, + "components": 140, + "filePayloadSha256": "08c04d33a79c89d07a652690a6ccdfd9d4f3ff902b77d6f9b9ef5e20c5ca115c" + }, + { + "id": "503b8235-8be1-80bf-8008-ba6ae7797c7d", + "name": "VLLNT UI — 04 Organisms · 01", + "revision": 3, + "modifiedAt": "2026-10-03T09:56:13.792891Z", + "sharedLibrary": true, + "pages": 1, + "shapes": 5755, + "components": 112, + "filePayloadSha256": "dfb2cdba112b45bec671b28718bd40a3248a7ce255d42327c398c0db5804822d" + }, + { + "id": "503b8235-8be1-80bf-8008-ba6ae7797c81", + "name": "VLLNT UI — 09 Legacy catalog · 01", + "revision": 1, + "modifiedAt": "2026-10-02T14:14:36.410871Z", + "sharedLibrary": true, + "pages": 1, + "shapes": 3, + "components": 1, + "filePayloadSha256": "f03d3e19652051cd2efe7a4091e49ac63fdc7c98727e5aafdc8a5c076f8edd61" + }, + { + "id": "503b8235-8be1-80bf-8008-ba6ae7797c82", + "name": "VLLNT UI — 02 Atoms · 03", + "revision": 1, + "modifiedAt": "2026-10-02T14:14:39.302351Z", + "sharedLibrary": true, + "pages": 1, + "shapes": 3378, + "components": 67, + "filePayloadSha256": "b9707b84daf60b91cfb70cf4e9066ed95ee533027f524a06f3213b1c1bc4f5dd" + }, + { + "id": "503b8235-8be1-80bf-8008-ba6ae7797c83", + "name": "VLLNT UI — 03 Molecules · 02", + "revision": 1, + "modifiedAt": "2026-10-02T14:14:42.256134Z", + "sharedLibrary": true, + "pages": 1, + "shapes": 1023, + "components": 67, + "filePayloadSha256": "940d4ca9cdf4ee5448c97aa777d6b72d89dcc68a8701a13ff29f1120e986e586" + }, + { + "id": "503b8235-8be1-80bf-8008-ba6ae7797c85", + "name": "VLLNT UI — 02 Atoms · 04", + "revision": 1, + "modifiedAt": "2026-10-02T14:14:44.621056Z", + "sharedLibrary": true, + "pages": 1, + "shapes": 258, + "components": 1, + "filePayloadSha256": "1e8e3337e74459e86a2a9b0564f27557d3e59db7bb8653eb8317e00baed12af9" + }, + { + "id": "503b8235-8be1-80bf-8008-ba6ae7797c86", + "name": "VLLNT UI — 03 Molecules · 03", + "revision": 1, + "modifiedAt": "2026-10-03T05:28:43.634437Z", + "sharedLibrary": true, + "pages": 1, + "shapes": 10867, + "components": 34, + "filePayloadSha256": "df28770dc65de8b60fc1e33667acf19cf3f1106f546ebe3de3bb4219282527a0" + }, + { + "id": "503b8235-8be1-80bf-8008-ba6ae7797c8b", + "name": "VLLNT UI — 04 Organisms · 02", + "revision": 1, + "modifiedAt": "2026-10-02T14:15:17.519766Z", + "sharedLibrary": true, + "pages": 1, + "shapes": 815, + "components": 19, + "filePayloadSha256": "234a4149e44c3e1dc2df1f2cef5d6dc11a76662485fceca9d11b8e95155bc5f0" + }, + { + "id": "503b8235-8be1-80bf-8008-ba6ae7797c8c", + "name": "VLLNT UI — 01 Foundations · 04", + "revision": 1, + "modifiedAt": "2026-10-02T14:15:19.982012Z", + "sharedLibrary": true, + "pages": 1, + "shapes": 273, + "components": 8, + "filePayloadSha256": "dd5636e92e0af24a55c1d82ca4d2a2adbf63289ca213e019bdc99a5dc2624ff1" + }, + { + "id": "503b8235-8be1-80bf-8008-ba6ae7797c8e", + "name": "VLLNT UI — 03 Molecules · 07", + "revision": 1, + "modifiedAt": "2026-10-02T20:26:42.613771Z", + "sharedLibrary": true, + "pages": 1, + "shapes": 14142, + "components": 98, + "filePayloadSha256": "b997e1458535b75c4b2fb6e119249989dacaafb9ba37a3282f93efe7fb552de3" + }, + { + "id": "503b8235-8be1-80bf-8008-ba6ae7797c8f", + "name": "VLLNT UI — 04 Organisms · 03", + "revision": 1, + "modifiedAt": "2026-10-02T14:15:48.606408Z", + "sharedLibrary": true, + "pages": 1, + "shapes": 1650, + "components": 24, + "filePayloadSha256": "b8223e031794f7eccc654dd001d8538c35b4f6f85583189db8b7461cf876dd77" + }, + { + "id": "503b8235-8be1-80bf-8008-ba6ae7797c92", + "name": "VLLNT UI — 04 Organisms · 04", + "revision": 3, + "modifiedAt": "2026-10-03T11:02:49.239173Z", + "sharedLibrary": true, + "pages": 1, + "shapes": 8605, + "components": 71, + "filePayloadSha256": "1d85986650452400f73739c226c107006448b9523e1394d218f83176b7830203" + }, + { + "id": "503b8235-8be1-80bf-8008-ba6ae7797c99", + "name": "VLLNT UI — 05 Templates · 03", + "revision": 1, + "modifiedAt": "2026-10-02T14:16:50.621253Z", + "sharedLibrary": true, + "pages": 1, + "shapes": 263, + "components": 4, + "filePayloadSha256": "28a483a44a2615ae3279f588b1c14bf91ada6c4626d4c1b3171b33a55592c2a6" + } + ], + "libraryRelations": [ + [ + "503b8235-8be1-80bf-8008-ba6ae7797c7b", + "503b8235-8be1-80bf-8008-ba6ae7797c78" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c7c", + "503b8235-8be1-80bf-8008-ba6ae7797c78" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c7d", + "503b8235-8be1-80bf-8008-ba6ae7797c78" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c81", + "503b8235-8be1-80bf-8008-ba6ae7797c78" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c82", + "503b8235-8be1-80bf-8008-ba6ae7797c78" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c82", + "503b8235-8be1-80bf-8008-ba6ae7797c7b" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c82", + "503b8235-8be1-80bf-8008-ba6ae7797c81" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c83", + "503b8235-8be1-80bf-8008-ba6ae7797c78" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c83", + "503b8235-8be1-80bf-8008-ba6ae7797c81" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c85", + "503b8235-8be1-80bf-8008-ba6ae7797c78" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c85", + "503b8235-8be1-80bf-8008-ba6ae7797c7b" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c85", + "503b8235-8be1-80bf-8008-ba6ae7797c81" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c85", + "503b8235-8be1-80bf-8008-ba6ae7797c82" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c85", + "503b8235-8be1-80bf-8008-ba6ae7797c83" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c86", + "503b8235-8be1-80bf-8008-ba6ae7797c78" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c86", + "503b8235-8be1-80bf-8008-ba6ae7797c7b" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c86", + "503b8235-8be1-80bf-8008-ba6ae7797c7c" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c86", + "503b8235-8be1-80bf-8008-ba6ae7797c82" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c8b", + "503b8235-8be1-80bf-8008-ba6ae7797c78" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c8b", + "503b8235-8be1-80bf-8008-ba6ae7797c83" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c8c", + "503b8235-8be1-80bf-8008-ba6ae7797c78" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c8c", + "503b8235-8be1-80bf-8008-ba6ae7797c83" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c8c", + "503b8235-8be1-80bf-8008-ba6ae7797c8b" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c8e", + "503b8235-8be1-80bf-8008-ba6ae7797c78" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c8e", + "503b8235-8be1-80bf-8008-ba6ae7797c7b" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c8e", + "503b8235-8be1-80bf-8008-ba6ae7797c81" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c8e", + "503b8235-8be1-80bf-8008-ba6ae7797c82" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c8e", + "503b8235-8be1-80bf-8008-ba6ae7797c83" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c8e", + "503b8235-8be1-80bf-8008-ba6ae7797c85" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c8e", + "503b8235-8be1-80bf-8008-ba6ae7797c86" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c8e", + "503b8235-8be1-80bf-8008-ba6ae7797c8c" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c8f", + "503b8235-8be1-80bf-8008-ba6ae7797c78" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c8f", + "503b8235-8be1-80bf-8008-ba6ae7797c81" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c8f", + "503b8235-8be1-80bf-8008-ba6ae7797c83" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c8f", + "503b8235-8be1-80bf-8008-ba6ae7797c8c" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c92", + "503b8235-8be1-80bf-8008-ba6ae7797c78" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c92", + "503b8235-8be1-80bf-8008-ba6ae7797c81" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c92", + "503b8235-8be1-80bf-8008-ba6ae7797c83" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c92", + "503b8235-8be1-80bf-8008-ba6ae7797c8f" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c99", + "503b8235-8be1-80bf-8008-ba6ae7797c78" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c99", + "503b8235-8be1-80bf-8008-ba6ae7797c7d" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c99", + "503b8235-8be1-80bf-8008-ba6ae7797c81" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c99", + "503b8235-8be1-80bf-8008-ba6ae7797c83" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c99", + "503b8235-8be1-80bf-8008-ba6ae7797c8f" + ], + [ + "503b8235-8be1-80bf-8008-ba6ae7797c99", + "503b8235-8be1-80bf-8008-ba6ae7797c92" + ] + ] + } +} diff --git a/design/penpot/snapshots/2026-10-03/verification.json b/design/penpot/snapshots/2026-10-03/verification.json new file mode 100644 index 00000000..1b3d195b --- /dev/null +++ b/design/penpot/snapshots/2026-10-03/verification.json @@ -0,0 +1,303 @@ +{ + "checkedOn": "2026-10-03", + "scope": "Saved archives and current library catalog; not full live visual/runtime acceptance", + "archives": { + "historical-full": { + "files": 40, + "sharedLibraries": 29, + "relations": 159, + "components": 1854, + "shapes": 245024, + "sourceBoardsExpected": 210, + "structureErrorCount": 1, + "structureErrors": [ + "canonical file names differ" + ], + "verdict": "HOLD_STRUCTURAL_FINDINGS", + "sha256MatchesReceipt": true, + "crcFirstBadMember": null, + "missingSourceShapes": 0, + "missingSourceComponents": 0, + "missingSourceBoards": 0, + "missingTokenBindings": 0, + "pendingFonts": 2166 + }, + "latest-partial": { + "files": 15, + "sharedLibraries": 15, + "relations": 45, + "components": 873, + "shapes": 55001, + "sourceBoardsExpected": 129, + "structureErrorCount": 0, + "structureErrors": [], + "verdict": "PASS_PARTIAL_STRUCTURAL_COVERAGE", + "sha256MatchesReceipt": true, + "crcFirstBadMember": null, + "missingSourceShapes": 0, + "missingSourceComponents": 0, + "missingSourceBoards": 0, + "missingTokenBindings": 0, + "pendingFonts": 1270 + } + }, + "historicalFullScopeQualification": { + "scope": "Saved historical archive: 39 canonical modules plus the explicitly identified Starter; no new native reopen or visual acceptance", + "checks": { + "exactKnownStarterOnly": true, + "onlyNameScopeFinding": true, + "noMissingSourceShapes": true, + "noMissingSourceComponents": true, + "noMissingSourceBoards": true, + "noMissingTokenBindings": true, + "shaMatches": true, + "crcPass": true, + "canonicalModules": true + }, + "verdict": "PASS_SAVED_39_MODULES_PLUS_STARTER", + "rawAuditorVerdictPreserved": "HOLD_STRUCTURAL_FINDINGS" + }, + "libraryCountReconciliation": { + "checkedAt": "2026-10-03T19:54:57.289496+00:00", + "liveLibraries": 29, + "liveVisibleEntries": 1844, + "historicalDefinitions": 1854, + "missingLibraries": [], + "extraLibraries": [], + "files": [ + { + "id": "503b8235-8be1-80bf-8008-ba6ae7797c78", + "name": "VLLNT UI — 02 Atoms · 01", + "liveVisibleEntries": 43, + "historicalDefinitions": 43, + "difference": 0, + "explanation": "same" + }, + { + "id": "503b8235-8be1-80bf-8008-ba6ae7797c7b", + "name": "VLLNT UI — 02 Atoms · 02", + "liveVisibleEntries": 174, + "historicalDefinitions": 184, + "difference": -10, + "explanation": "13 Selection states grouped into 3 families; 10 fewer visible entries" + }, + { + "id": "503b8235-8be1-80bf-8008-ba6ae7797c7c", + "name": "VLLNT UI — 03 Molecules · 01", + "liveVisibleEntries": 140, + "historicalDefinitions": 140, + "difference": 0, + "explanation": "same" + }, + { + "id": "503b8235-8be1-80bf-8008-ba6ae7797c7d", + "name": "VLLNT UI — 04 Organisms · 01", + "liveVisibleEntries": 112, + "historicalDefinitions": 112, + "difference": 0, + "explanation": "same" + }, + { + "id": "503b8235-8be1-80bf-8008-ba6ae7797c7e", + "name": "VLLNT UI — 05 Templates · 01", + "liveVisibleEntries": 1, + "historicalDefinitions": 1, + "difference": 0, + "explanation": "same" + }, + { + "id": "503b8235-8be1-80bf-8008-ba6ae7797c81", + "name": "VLLNT UI — 09 Legacy catalog · 01", + "liveVisibleEntries": 1, + "historicalDefinitions": 1, + "difference": 0, + "explanation": "same" + }, + { + "id": "503b8235-8be1-80bf-8008-ba6ae7797c82", + "name": "VLLNT UI — 02 Atoms · 03", + "liveVisibleEntries": 67, + "historicalDefinitions": 67, + "difference": 0, + "explanation": "same" + }, + { + "id": "503b8235-8be1-80bf-8008-ba6ae7797c83", + "name": "VLLNT UI — 03 Molecules · 02", + "liveVisibleEntries": 67, + "historicalDefinitions": 67, + "difference": 0, + "explanation": "same" + }, + { + "id": "503b8235-8be1-80bf-8008-ba6ae7797c85", + "name": "VLLNT UI — 02 Atoms · 04", + "liveVisibleEntries": 1, + "historicalDefinitions": 1, + "difference": 0, + "explanation": "same" + }, + { + "id": "503b8235-8be1-80bf-8008-ba6ae7797c86", + "name": "VLLNT UI — 03 Molecules · 03", + "liveVisibleEntries": 34, + "historicalDefinitions": 34, + "difference": 0, + "explanation": "same" + }, + { + "id": "503b8235-8be1-80bf-8008-ba6ae7797c87", + "name": "VLLNT UI — 02 Atoms · 05", + "liveVisibleEntries": 50, + "historicalDefinitions": 50, + "difference": 0, + "explanation": "same" + }, + { + "id": "503b8235-8be1-80bf-8008-ba6ae7797c88", + "name": "VLLNT UI — 03 Molecules · 04", + "liveVisibleEntries": 6, + "historicalDefinitions": 6, + "difference": 0, + "explanation": "same" + }, + { + "id": "503b8235-8be1-80bf-8008-ba6ae7797c89", + "name": "VLLNT UI — 03 Molecules · 05", + "liveVisibleEntries": 176, + "historicalDefinitions": 176, + "difference": 0, + "explanation": "same" + }, + { + "id": "503b8235-8be1-80bf-8008-ba6ae7797c8a", + "name": "VLLNT UI — 03 Molecules · 06", + "liveVisibleEntries": 120, + "historicalDefinitions": 120, + "difference": 0, + "explanation": "same" + }, + { + "id": "503b8235-8be1-80bf-8008-ba6ae7797c8b", + "name": "VLLNT UI — 04 Organisms · 02", + "liveVisibleEntries": 19, + "historicalDefinitions": 19, + "difference": 0, + "explanation": "same" + }, + { + "id": "503b8235-8be1-80bf-8008-ba6ae7797c8c", + "name": "VLLNT UI — 01 Foundations · 04", + "liveVisibleEntries": 8, + "historicalDefinitions": 8, + "difference": 0, + "explanation": "same" + }, + { + "id": "503b8235-8be1-80bf-8008-ba6ae7797c8d", + "name": "VLLNT UI — 02 Atoms · 06", + "liveVisibleEntries": 26, + "historicalDefinitions": 26, + "difference": 0, + "explanation": "same" + }, + { + "id": "503b8235-8be1-80bf-8008-ba6ae7797c8e", + "name": "VLLNT UI — 03 Molecules · 07", + "liveVisibleEntries": 98, + "historicalDefinitions": 98, + "difference": 0, + "explanation": "same" + }, + { + "id": "503b8235-8be1-80bf-8008-ba6ae7797c8f", + "name": "VLLNT UI — 04 Organisms · 03", + "liveVisibleEntries": 24, + "historicalDefinitions": 24, + "difference": 0, + "explanation": "same" + }, + { + "id": "503b8235-8be1-80bf-8008-ba6ae7797c90", + "name": "VLLNT UI — 01 Foundations · 05", + "liveVisibleEntries": 13, + "historicalDefinitions": 13, + "difference": 0, + "explanation": "same" + }, + { + "id": "503b8235-8be1-80bf-8008-ba6ae7797c91", + "name": "VLLNT UI — 03 Molecules · 08", + "liveVisibleEntries": 87, + "historicalDefinitions": 87, + "difference": 0, + "explanation": "same" + }, + { + "id": "503b8235-8be1-80bf-8008-ba6ae7797c92", + "name": "VLLNT UI — 04 Organisms · 04", + "liveVisibleEntries": 71, + "historicalDefinitions": 71, + "difference": 0, + "explanation": "same" + }, + { + "id": "503b8235-8be1-80bf-8008-ba6ae7797c93", + "name": "VLLNT UI — 03 Molecules · 09", + "liveVisibleEntries": 141, + "historicalDefinitions": 141, + "difference": 0, + "explanation": "same" + }, + { + "id": "503b8235-8be1-80bf-8008-ba6ae7797c94", + "name": "VLLNT UI — 04 Organisms · 05", + "liveVisibleEntries": 94, + "historicalDefinitions": 94, + "difference": 0, + "explanation": "same" + }, + { + "id": "503b8235-8be1-80bf-8008-ba6ae7797c95", + "name": "VLLNT UI — 04 Organisms · 06", + "liveVisibleEntries": 187, + "historicalDefinitions": 187, + "difference": 0, + "explanation": "same" + }, + { + "id": "503b8235-8be1-80bf-8008-ba6ae7797c96", + "name": "VLLNT UI — 04 Organisms · 07", + "liveVisibleEntries": 9, + "historicalDefinitions": 9, + "difference": 0, + "explanation": "same" + }, + { + "id": "503b8235-8be1-80bf-8008-ba6ae7797c97", + "name": "VLLNT UI — 05 Templates · 02", + "liveVisibleEntries": 17, + "historicalDefinitions": 17, + "difference": 0, + "explanation": "same" + }, + { + "id": "503b8235-8be1-80bf-8008-ba6ae7797c98", + "name": "VLLNT UI — 04 Organisms · 08", + "liveVisibleEntries": 54, + "historicalDefinitions": 54, + "difference": 0, + "explanation": "same" + }, + { + "id": "503b8235-8be1-80bf-8008-ba6ae7797c99", + "name": "VLLNT UI — 05 Templates · 03", + "liveVisibleEntries": 4, + "historicalDefinitions": 4, + "difference": 0, + "explanation": "same" + } + ] + }, + "caution": "Recorded font counts are archive-specific; later fixes and private trials must not be silently deducted from them." +} diff --git a/scripts/penpot_snapshot.py b/scripts/penpot_snapshot.py new file mode 100644 index 00000000..bd11b70c --- /dev/null +++ b/scripts/penpot_snapshot.py @@ -0,0 +1,157 @@ +#!/usr/bin/env python3 +"""Record or verify native Penpot exports without editing or extracting them. + +Uses only the Python 3 standard library. Scope and export date are declarations; +checksums and inventories are computed from the supplied saved archive. +""" + +import argparse +import hashlib +import json +from pathlib import Path +import sys +import zipfile + + +ROOT_SHAPE = "00000000-0000-0000-0000-000000000000.json" + + +def sha256_file(path): + digest = hashlib.sha256() + with path.open("rb") as stream: + for block in iter(lambda: stream.read(1024 * 1024), b""): + digest.update(block) + return digest.hexdigest() + + +def inventory(path): + """Read every member (including CRC), then summarize each exported file.""" + with zipfile.ZipFile(path) as archive: + names = archive.namelist() + if len(names) != len(set(names)): + raise ValueError("duplicate ZIP member names") + manifest = json.loads(archive.read("manifest.json")) + if manifest.get("type") != "penpot/export-files" or manifest.get("version") != 1: + raise ValueError("unsupported native Penpot export manifest") + file_ids = [item["id"] for item in manifest["files"]] + if len(file_ids) != len(set(file_ids)) or not file_ids: + raise ValueError("empty or duplicate file IDs") + members = {fid: [] for fid in file_ids} + # Reading every member also validates its CRC. No extraction or writes. + for name in sorted(names): + payload = archive.read(name) + parts = name.split("/") + if parts[0] != "files" or len(parts) < 2 or name.endswith("/"): + continue + fid = parts[1].removesuffix(".json") + if fid not in members: + raise ValueError("file payload absent from export manifest: " + fid) + members[fid].append((name, hashlib.sha256(payload).hexdigest())) + rows = [] + for item in sorted(manifest["files"], key=lambda item: item["id"]): + fid = item["id"] + data = json.loads(archive.read("files/" + fid + ".json")) + if data["id"] != fid or data["name"] != item["name"]: + raise ValueError("file metadata disagrees with export manifest: " + fid) + owned = [name.split("/") for name, _ in members[fid]] + fingerprint = hashlib.sha256(json.dumps( + members[fid], separators=(",", ":"), ensure_ascii=False + ).encode()).hexdigest() + rows.append({ + "id": fid, + "name": data["name"], + "revision": data.get("revn"), + "modifiedAt": data.get("modifiedAt"), + "sharedLibrary": data.get("isShared", False), + "pages": sum(len(s) == 4 and s[2] == "pages" and s[-1].endswith(".json") for s in owned), + "shapes": sum(len(s) == 5 and s[2] == "pages" and s[-1].endswith(".json") and s[-1] != ROOT_SHAPE for s in owned), + "components": sum(len(s) == 4 and s[2] == "components" and s[-1].endswith(".json") for s in owned), + "filePayloadSha256": fingerprint, + }) + relations = sorted(manifest.get("relations", [])) + for relation in relations: + if len(relation) != 2 or any(fid not in members for fid in relation): + raise ValueError("library relation points outside this export") + return { + "generatedBy": manifest.get("generatedBy"), + "archiveMembers": len(names), + "totals": { + "files": len(rows), + "sharedLibraries": sum(row["sharedLibrary"] for row in rows), + "pages": sum(row["pages"] for row in rows), + "shapes": sum(row["shapes"] for row in rows), + "components": sum(row["components"] for row in rows), + "libraryRelations": len(relations), + }, + "files": rows, + "libraryRelations": relations, + } + + +def record(archive, exported_on, scope, release_tag, note): + return { + "schemaVersion": 1, + "exportedOn": exported_on, + "scope": scope, + "note": note, + "release": "https://github.com/vllnt/ui/releases/tag/" + release_tag, + "asset": { + "name": archive.name, + "bytes": archive.stat().st_size, + "sha256": sha256_file(archive), + }, + "inventory": inventory(archive), + } + + +def verify(receipt, asset_dir): + if receipt.get("schemaVersion") != 1: + raise ValueError("unsupported snapshot receipt schema") + asset = receipt["asset"] + name = asset["name"] + if not name or name in (".", "..") or "/" in name or "\\" in name: + raise ValueError("asset name must be a basename") + archive = asset_dir / name + if archive.stat().st_size != asset["bytes"]: + raise ValueError("archive size mismatch: " + name) + if sha256_file(archive) != asset["sha256"]: + raise ValueError("archive SHA-256 mismatch: " + name) + if inventory(archive) != receipt["inventory"]: + raise ValueError("saved inventory mismatch: " + name) + return archive + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + commands = parser.add_subparsers(dest="command", required=True) + create = commands.add_parser("record", help="write a new receipt; never overwrite") + create.add_argument("archive", type=Path) + create.add_argument("--output", type=Path, required=True) + create.add_argument("--exported-on", required=True, help="actual export date, not receipt date") + create.add_argument("--scope", required=True, help="explicit full/partial scope and exclusions") + create.add_argument("--release-tag", required=True) + create.add_argument("--note", required=True, help="qualification and restore-test limits") + check = commands.add_parser("verify", help="check downloaded native archives against receipts") + check.add_argument("receipts", type=Path, nargs="+") + check.add_argument("--asset-dir", type=Path, required=True) + args = parser.parse_args() + try: + if args.command == "record": + receipt = record(args.archive, args.exported_on, args.scope, args.release_tag, args.note) + with args.output.open("x") as stream: + json.dump(receipt, stream, ensure_ascii=False, indent=2) + stream.write("\n") + print("RECORDED", args.output, json.dumps(receipt["inventory"]["totals"])) + else: + for path in args.receipts: + receipt = json.loads(path.read_text()) + verified = verify(receipt, args.asset_dir) + print("VERIFIED", verified.name, json.dumps(receipt["inventory"]["totals"])) + except (OSError, ValueError, KeyError, TypeError, zipfile.BadZipFile) as error: + print("FAILED:", error, file=sys.stderr) + return 1 + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/scripts/test_penpot_snapshot.py b/scripts/test_penpot_snapshot.py new file mode 100644 index 00000000..26b6157e --- /dev/null +++ b/scripts/test_penpot_snapshot.py @@ -0,0 +1,124 @@ +"""Recovery checks: reject damaged/missing assets and misleading receipts.""" + +import copy +import json +from pathlib import Path +import struct +import subprocess +import sys +import tempfile +import unittest +import zipfile + +import penpot_snapshot as snapshot + + +class SnapshotTests(unittest.TestCase): + def setUp(self): + self.temp = tempfile.TemporaryDirectory() + self.addCleanup(self.temp.cleanup) + self.root = Path(self.temp.name) + self.archive = self.root / "test.penpot" + self.entries = { + "manifest.json": {"type": "penpot/export-files", "version": 1, "generatedBy": "penpot/test", "files": [{"id": "f1", "name": "Kit"}], "relations": []}, + "files/f1.json": {"id": "f1", "name": "Kit", "revn": 1, "isShared": True}, + "files/f1/pages/p1.json": {"id": "p1"}, + "files/f1/pages/p1/" + snapshot.ROOT_SHAPE: {"id": "root"}, + "files/f1/pages/p1/s1.json": {"id": "s1", "type": "rect", "width": 10}, + "files/f1/components/c1.json": {"id": "c1"}, + } + self.write_archive(self.archive) + self.receipt = snapshot.record(self.archive, "2026-10-03", "partial test", "test", "fixture") + + def write_archive(self, path, reverse=False, compression=zipfile.ZIP_STORED): + with zipfile.ZipFile(path, "w", compression=compression) as archive: + for name, value in sorted(self.entries.items(), reverse=reverse): + archive.writestr(name, json.dumps(value)) + + def test_valid_archive_and_counts(self): + self.assertEqual(snapshot.verify(self.receipt, self.root), self.archive) + self.assertEqual(self.receipt["inventory"]["totals"], { + "files": 1, "sharedLibraries": 1, "pages": 1, "shapes": 1, + "components": 1, "libraryRelations": 0, + }) + + def test_missing_asset_is_rejected(self): + self.archive.unlink() + with self.assertRaises(FileNotFoundError): + snapshot.verify(self.receipt, self.root) + + def test_same_size_changed_bytes_are_rejected(self): + data = bytearray(self.archive.read_bytes()) + data[40] ^= 1 + self.archive.write_bytes(data) + with self.assertRaisesRegex(ValueError, "SHA-256 mismatch"): + snapshot.verify(self.receipt, self.root) + + def test_truncated_archive_is_rejected(self): + self.archive.write_bytes(self.archive.read_bytes()[:-10]) + with self.assertRaisesRegex(ValueError, "size mismatch"): + snapshot.verify(self.receipt, self.root) + + def test_inventory_tampering_is_rejected(self): + self.receipt["inventory"]["totals"]["components"] = 2 + with self.assertRaisesRegex(ValueError, "inventory mismatch"): + snapshot.verify(self.receipt, self.root) + + def test_corrupt_member_is_rejected_even_with_updated_archive_hash(self): + with zipfile.ZipFile(self.archive) as archive: + offset = archive.getinfo("files/f1/pages/p1/s1.json").header_offset + data = bytearray(self.archive.read_bytes()) + name_size, extra_size = struct.unpack_from(" Date: Sat, 3 Oct 2026 23:25:06 +0200 Subject: [PATCH 2/2] docs(design): record native snapshot upload approval boundary --- design/penpot/README.md | 16 ++++++++++------ design/penpot/STATUS.md | 6 ++++-- .../penpot/snapshots/2026-10-03/publication.json | 12 ++++++++++++ 3 files changed, 26 insertions(+), 8 deletions(-) create mode 100644 design/penpot/snapshots/2026-10-03/publication.json diff --git a/design/penpot/README.md b/design/penpot/README.md index b8c4730d..c8c176ac 100644 --- a/design/penpot/README.md +++ b/design/penpot/README.md @@ -1,13 +1,17 @@ # Penpot design snapshots -Native, editable Penpot exports are stored as GitHub release assets. Git tracks -their exact SHA-256 checksums, file inventories, revisions, library links and -qualification notes. This saves the design outside the Penpot server without -putting hundreds of megabytes into every clone. No Git LFS or Python packages +Git tracks the exact SHA-256 checksums, file inventories, revisions, library +links and qualification notes of native, editable Penpot exports. Versioned +GitHub release assets are the proposed off-server storage, keeping hundreds of +megabytes out of every clone. No Git LFS or Python packages are required. The checker requires Python 3.9 or newer. -[Initial recovery release](https://github.com/vllnt/ui/releases/tag/penpot-snapshot-2026-10-03) -— [migration status and remaining work](STATUS.md). +**Publication pending:** the two native archives remain local; no archive has +been uploaded to GitHub. Explicit approval to upload their editable contents +is pending. The release URL in the receipts is a reserved destination, and the +download commands below become usable only after publication. See the +[publication record](snapshots/2026-10-03/publication.json) and +[migration status and remaining work](STATUS.md). ## Current recovery points diff --git a/design/penpot/STATUS.md b/design/penpot/STATUS.md index 14d9161e..46fd5890 100644 --- a/design/penpot/STATUS.md +++ b/design/penpot/STATUS.md @@ -87,6 +87,8 @@ implementation evidence; a Penpot canvas does not prove them. Use [the recovery workflow](README.md) after each accepted design batch. Keep native named versions for quick rollback and native exports outside the server -for disaster recovery. The initial release preserves the historical full and -newer partial archives without claiming an automatic merge or continuous sync. +for disaster recovery. The prepared snapshot set preserves the historical full and +newer partial archives locally, without claiming an automatic merge or +continuous sync. Native archive upload to GitHub awaits explicit approval; +only the tracking records and recovery tooling are being committed. No scheduled automation has been restarted. diff --git a/design/penpot/snapshots/2026-10-03/publication.json b/design/penpot/snapshots/2026-10-03/publication.json new file mode 100644 index 00000000..b030af96 --- /dev/null +++ b/design/penpot/snapshots/2026-10-03/publication.json @@ -0,0 +1,12 @@ +{ + "status": "pending-native-archive-upload-approval", + "intendedRelease": "https://github.com/vllnt/ui/releases/tag/penpot-snapshot-2026-10-03", + "nativeAssetsUploaded": false, + "downloadedCopyVerified": false, + "localArchiveVerification": "Both archives passed SHA-256, CRC and committed inventory checks on 2026-10-03.", + "reason": "The repository is public. Explicit approval for uploading the two native design payloads is pending.", + "assets": [ + "vllnt-ui-native-complete-with-starter-2026-10-02.penpot", + "vllnt-ui-partial-native-refresh-2026-10-03.penpot" + ] +}