diff --git a/SPEC.md b/SPEC.md index 6c2cfdc..4878c51 100644 --- a/SPEC.md +++ b/SPEC.md @@ -204,7 +204,7 @@ Beside the Docker/Pi route, not replacing it: Huismus as an ordinary desktop app - **Updates.** The app checks GitHub Releases for a new version, downloads it in the background and installs it by itself the next time it opens, before the user can work (the owner's decision, 2026-11-04; `huismus-intern/besluiten.md`); a button in Settings → Updates updates right away, and "Nu zoeken" there looks for a new version right away instead of waiting for the daily look (on Docker too; the owner's request, 2026-11-05). A version that fails to install automatically is tried once; after that only the button tries it again. The check only fetches the public release list and can be turned off in Settings. Before an update is applied the app makes a backup (`manage.py backup`, M7); the migrations run after. If they fail, the app says so and offers to restore that backup. After a new version, in the app and on Docker alike, the overview shows a blue notice "Huismus is bijgewerkt naar ." with a link to Hulp → Wat is er nieuw and a close button, until it is closed or that page is opened; the last version seen is kept in the update status file next to the database, not in a backup. A new administration and the sample data get no notice; an administration from before the notice gets it once (issue #149; `huismus-intern/besluiten.md`, 2026-11-12). Built 2026-10-29 for macOS (choices: `huismus-intern/besluiten.md`; how it works: `docs/desktop.md`): a release offers `Huismus--macos.dmg`, which `release.yml` builds on a version tag on an Apple Silicon runner and checks with `--check` before it is published (the tag must equal the version in `pyproject.toml`; the app needs macOS 15 or later, the Homebrew Pango it carries is built for that); the download must match the SHA-256 GitHub lists for it; the app replaces itself through a small script after it has closed. Built 2026-10-29 for Windows (choices: `huismus-intern/besluiten.md`, "Windows-app: bouwkeuzes"): a release offers `Huismus--windows.exe` as well, an Inno Setup installer that installs per user in `%LOCALAPPDATA%\Programs\Huismus` without asking for administrator rights; on Windows the app looks only for that file, and updating runs it without any window from a small PowerShell script after the app has closed. `release.yml` publishes a release only once both apps are built and checked (on Windows the installed app) and the release test in the window passed on both; a trial build by hand (workflow_dispatch) builds and tests both apps with a version one patch above the latest release, and publishes nothing (2026-11-13; before, it built only Windows). Windows 10 or later, x64 only; WebView2 is not installed along: when it is missing, the app asks in a Windows message whether to download it from Microsoft, then closes. Opened a second time on Windows, the app brings the open window forward. The app carries its own root certificates (certifi) for HTTPS, so the update check and "Hoe gebruik je Huismus?" also work on a Mac without Homebrew; `--check` checks that (2026-11-02). - **Backups.** Once a day, the app writes a backup archive to a folder the user picks once (iCloud Drive, OneDrive, Dropbox, a USB drive). The live database never goes into a synced folder, only the archives. The dashboard shows when the last backup was, and warns after a failed backup (folder unreachable or full) and after 7 days without one. Restoring is a button in the app, on top of `manage.py restore`: it first backs up the current state, and the app serves no pages while it restores. Built 2026-10-29 (choices: `huismus-intern/besluiten.md`; how it works: `docs/desktop.md`): the folder and the status belong to the computer and are not in a backup; a backup from a newer version is refused. Since M15 step 2 a backup can also go, encrypted, straight to Dropbox or WebDAV. - **Release test in the window** (proposed 2026-11-07; the owner decided the same day to build it, and a failing test stops the release; issue #117). `--check` starts everything except the window, from the built app. A further job in `release.yml` tests what a user gets, on the same GitHub runners (a fresh virtual machine per run, nothing to rent). macOS: install from the `.dmg` as a user would. Windows: the app the installer put in place. Then open the app with its window on an empty administration, walk through the onboarding, make and issue one invoice, download its PDF, and keep a screenshot of each step with the release run. On Windows Playwright drives the app's own WebView2 window, with remote debugging switched on for the test only. On macOS Playwright cannot attach to a WKWebView, so it drives the same server while the test checks from a screenshot that the window opened. The test needs the window's token without that token reaching other programs outside the test. It also updates from the previous release's download and checks that the data stayed and a backup was made first. Together this replaces those steps of the check by hand in *Done when*. Built 2026-11-13 (choices: `huismus-intern/besluiten.md`; how it works: `docs/desktop.md`, "Een release maken"): jobs `macos-window-test` and `windows-window-test` run `scripts/window-test-mac.sh` and `scripts/window-test-windows.sh` with `scripts/window_test.py`, and `publish` needs both. The token: on macOS the test makes one and hands it to that one app process (`HUISMUS_RELEASE_TEST_TOKEN`, only one of 32 characters or more counts, taken out of the app's environment at once, masked in the run's log, never in a screenshot); on Windows the test needs none, and only its own environment switches remote debugging on, on 127.0.0.1 (`WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS`; the app never sets it). The update: the previous release, installed from its own download, gets records from its own `demo_data` (its source at that tag), and the new build is put in place as a version it downloaded and checked; it then installs it at its next start through its own path. Afterwards each kind and status of document, and the expenses, have the same count and total to the cent as before, so does the backup from before the update, and the overview says "Huismus is bijgewerkt naar .". Not tested there: looking the release up at GitHub and downloading it (the release is not online yet); that, on one platform, stays a check by hand at each release. The warnings for an unsigned app (Gatekeeper, SmartScreen) only appear for a real download and stay a check by hand. No paid service: browser-testing services hardly test native desktop apps, and desktop test suites (Ranorex, TestComplete, Squish) are too heavy for a hobby project. -- **What it gives up.** The app can only be reached while the laptop is open: no access from a phone, so no PWA (M9). One installation per administration (invariant 2): moving between laptop and Pi goes through backup and restore, never two running copies of the same data. +- **What it gives up.** The app can only be reached while the laptop is open: no access from a phone, so no PWA (M9). Decided by the owner on 2026-11-13 (`huismus-intern/besluiten.md`, issue #143): a later step links a phone over the user's own Wi-Fi with a QR code, never from the internet, and only after `review-veiligheid` has judged it. One installation per administration (invariant 2): moving between laptop and Pi goes through backup and restore, never two running copies of the same data. - **Order**: zero configuration first (it helps Docker too), then an unsigned macOS prototype for the owner on a real administration, then updates and backups, then Windows, then the public release (section 11). *Done when:* in CI, both apps build on a tag, and tests cover the generated `SECRET_KEY` (and that an environment key wins), the window token, that Docker still requires a login, and the backup warning. In CI before every release, the release test in the window: both apps install, open with their window on an empty administration, walk the onboarding, issue an invoice and download its PDF, and updating from the previous release keeps the data and makes a backup first. By hand, on a fresh macOS and Windows machine (a VM will do): it installs from the release download without a terminal (Gatekeeper, SmartScreen) and lands in the onboarding; a daily backup appears in the chosen folder and restores; at each release, on one platform, a real update is looked up at GitHub and downloaded. Strings exist in Dutch and English, and the README and `docs/` explain downloading and the first opening. Before the repository goes public, its git history has been checked for real data, and the CLAUDE.md Deploy section no longer calls it private. @@ -406,7 +406,7 @@ Collect **anonymised sample exports** (contacts, invoices per invoice/per line, ## 12. Later / out of scope for v1 -UBL/Peppol export, multi-currency. Decided by the owner on 2026-11-07 and now in scope, each with its own issue: recurring invoices (#82), time tracking (#80, #81), bank statement import as a file (CAMT.053 or MT940, #77), payment reminders (#114), a profit and loss statement per year (#109), and importing from other packages (#108). +Peppol, multi-currency. Decided by the owner on 2026-11-07 and now in scope, each with its own issue: recurring invoices (#82), time tracking (#80, #81), bank statement import as a file (CAMT.053 or MT940, #77), payment reminders (#114), a profit and loss statement per year (#109), and importing from other packages (#108). Decided by the owner on 2026-11-13 (`huismus-intern/besluiten.md`, "Sprintplanning") and in scope, after the ones above: a UBL e-invoice attached to an invoice, made locally (#169; sending through Peppol stays with the central server, #64), simple mileage records without a computed allowance (#125), investments and depreciation after the profit and loss statement (#124), a summary for the ICP return with its source first (#168), and saved articles to pick as invoice lines (#167). ## 13. Open questions