befundschani 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. befundschani-0.1.0/.env.example +18 -0
  2. befundschani-0.1.0/.gitignore +19 -0
  3. befundschani-0.1.0/.gitlab-ci.yml +91 -0
  4. befundschani-0.1.0/CHANGELOG.md +63 -0
  5. befundschani-0.1.0/LICENSE.md +650 -0
  6. befundschani-0.1.0/Makefile +33 -0
  7. befundschani-0.1.0/PKG-INFO +16 -0
  8. befundschani-0.1.0/README.md +45 -0
  9. befundschani-0.1.0/befundschani.spec +100 -0
  10. befundschani-0.1.0/docs/architecture/autostart-service.md +36 -0
  11. befundschani-0.1.0/docs/architecture/pipelines.md +44 -0
  12. befundschani-0.1.0/docs/configuration/files.md +25 -0
  13. befundschani-0.1.0/docs/history.md +29 -0
  14. befundschani-0.1.0/docs/index.md +55 -0
  15. befundschani-0.1.0/docs/releasing.md +77 -0
  16. befundschani-0.1.0/docs/security/cross-signing.md +193 -0
  17. befundschani-0.1.0/docs/security/encryption.md +283 -0
  18. befundschani-0.1.0/docs/security/overview.md +112 -0
  19. befundschani-0.1.0/docs/setup/first-time-setup.md +105 -0
  20. befundschani-0.1.0/install_befundschani_service.py +12 -0
  21. befundschani-0.1.0/mkdocs.yml +1 -0
  22. befundschani-0.1.0/packaging/windows/befundschani.wxs +64 -0
  23. befundschani-0.1.0/packaging/windows/harvest.py +85 -0
  24. befundschani-0.1.0/pyinstaller/entry_daemon.py +6 -0
  25. befundschani-0.1.0/pyinstaller/entry_setup.py +6 -0
  26. befundschani-0.1.0/pyproject.toml +49 -0
  27. befundschani-0.1.0/scripts/build_macos_dmg.sh +39 -0
  28. befundschani-0.1.0/scripts/build_olm_windows_wheel.sh +115 -0
  29. befundschani-0.1.0/scripts/build_windows_dist.sh +21 -0
  30. befundschani-0.1.0/scripts/build_windows_msi.sh +34 -0
  31. befundschani-0.1.0/scripts/make_demo_befunde.py +47 -0
  32. befundschani-0.1.0/scripts/update_translations.sh +10 -0
  33. befundschani-0.1.0/src/befundschani/__init__.py +5 -0
  34. befundschani-0.1.0/src/befundschani/assets/logo.svg +572 -0
  35. befundschani-0.1.0/src/befundschani/assets/medspeak_logo.png +0 -0
  36. befundschani-0.1.0/src/befundschani/assets/medspeak_logo64.png +0 -0
  37. befundschani-0.1.0/src/befundschani/config.py +117 -0
  38. befundschani-0.1.0/src/befundschani/daemon.py +530 -0
  39. befundschani-0.1.0/src/befundschani/edifact.py +51 -0
  40. befundschani-0.1.0/src/befundschani/i18n.py +43 -0
  41. befundschani-0.1.0/src/befundschani/inbox.py +136 -0
  42. befundschani-0.1.0/src/befundschani/ipc.py +37 -0
  43. befundschani-0.1.0/src/befundschani/main_app.py +855 -0
  44. befundschani-0.1.0/src/befundschani/matrix_config_ui.py +1380 -0
  45. befundschani-0.1.0/src/befundschani/matrix_transport.py +287 -0
  46. befundschani-0.1.0/src/befundschani/medspeak_api.py +197 -0
  47. befundschani-0.1.0/src/befundschani/outbox.py +192 -0
  48. befundschani-0.1.0/src/befundschani/service_installer.py +359 -0
  49. befundschani-0.1.0/src/befundschani/setup_wizard.py +69 -0
  50. befundschani-0.1.0/src/befundschani/templates/befundschani.service +15 -0
  51. befundschani-0.1.0/src/befundschani/templates/com.befundschani.daemon.plist +28 -0
  52. befundschani-0.1.0/src/befundschani/templates/windows_service.py +128 -0
  53. befundschani-0.1.0/src/befundschani/templates/windows_service_install.bat +50 -0
  54. befundschani-0.1.0/src/befundschani/templates/windows_task_scheduler.xml +51 -0
  55. befundschani-0.1.0/src/befundschani/translations/befundschani_de.qm +0 -0
  56. befundschani-0.1.0/src/befundschani/translations/befundschani_de.ts +815 -0
  57. befundschani-0.1.0/src/befundschani/verification.py +392 -0
  58. befundschani-0.1.0/tests/conftest.py +27 -0
  59. befundschani-0.1.0/tests/data/demo2.bef +30 -0
  60. befundschani-0.1.0/tests/data/demo2pat.lab +59 -0
  61. befundschani-0.1.0/tests/data/demo_vanilla.pdf +0 -0
  62. befundschani-0.1.0/tests/edifact_helpers.py +50 -0
  63. befundschani-0.1.0/tests/test_config_seed.py +87 -0
  64. befundschani-0.1.0/tests/test_edifact.py +48 -0
  65. befundschani-0.1.0/tests/test_gui.py +744 -0
  66. befundschani-0.1.0/tests/test_inbox.py +186 -0
  67. befundschani-0.1.0/tests/test_medspeak_api.py +169 -0
  68. befundschani-0.1.0/tests/test_normalize.py +52 -0
  69. befundschani-0.1.0/tests/test_outbox.py +237 -0
  70. befundschani-0.1.0/tests/test_service_installer.py +191 -0
  71. befundschani-0.1.0/tests/test_transport_filter.py +61 -0
  72. befundschani-0.1.0/tests/test_verification.py +106 -0
  73. befundschani-0.1.0/uv.lock +1462 -0
@@ -0,0 +1,18 @@
1
+ # Befund-Schani credential seed.
2
+ # Copy to `.env` (in the working directory or ~/.config/befundschani/.env,
3
+ # or point BEFUNDSCHANI_ENV at it) to pre-fill the setup dialog so you don't
4
+ # have to type credentials every time. All keys are optional.
5
+
6
+ HOMESERVER=
7
+ MATRIX_USERNAME=
8
+ MATRIX_PASSWORD=
9
+ MATRIX_RECOVERY_KEY=
10
+
11
+ # Optional — also seedable:
12
+ # DAME_INBOX=
13
+ # DAME_OUTBOX=
14
+ # DAME_ARCHIVE=
15
+ # ME_NUMBER=
16
+ # medspeak API for ME/MXID lookups — defaults to the HOMESERVER itself;
17
+ # set only if the API runs on a different host:
18
+ # API_BASE_URL=
@@ -0,0 +1,19 @@
1
+ dame/*
2
+ build/
3
+ dist/
4
+ *.spec
5
+ __pycache__/
6
+ *.pycsite/
7
+
8
+ # Keep the hand-written PyInstaller spec (generated ones stay ignored)
9
+ !befundschani.spec
10
+
11
+ # Local credential seed — never commit
12
+ .env
13
+
14
+ # Demo befunde carry real ME numbers (PII) — never commit
15
+ /tests/data/demo_befund_*.bef
16
+ dist-windows/
17
+ dist-wheels/
18
+ packaging/windows/harvested.wxs
19
+ dist-macos/
@@ -0,0 +1,91 @@
1
+ stages:
2
+ - build
3
+ - package
4
+ - publish
5
+
6
+ # Windows MSI pipeline (three stages, no Windows runner needed):
7
+ # 1. build-olm-windows-wheel cross-compiles python-olm with mingw-w64
8
+ # (no Windows wheels exist upstream; libolm is linked statically).
9
+ # 2. build-windows-bundle runs PyInstaller inside Wine (Windows Python).
10
+ # 3. build-windows-msi compiles the WiX sources natively with wixl.
11
+ # Runs automatically on tags and on pipelines started from the web UI
12
+ # ("Run pipeline"). Individual `when: manual` jobs would not work here:
13
+ # GitLab skips jobs whose `needs` point at an optional manual job that
14
+ # was never started, so the three-job chain could never complete.
15
+ .windows-rules: &windows-rules
16
+ rules:
17
+ - if: $CI_COMMIT_TAG
18
+ - if: $CI_PIPELINE_SOURCE == "web"
19
+
20
+ build-olm-windows-wheel:
21
+ stage: build
22
+ image: debian:bookworm
23
+ <<: *windows-rules
24
+ before_script:
25
+ - apt-get update -qq
26
+ # gcc: olm's python/Makefile preprocesses headers with the HOST cc.
27
+ - apt-get install -yqq --no-install-recommends
28
+ gcc mingw-w64 cmake make curl ca-certificates unzip
29
+ python3 python3-cffi python3-setuptools
30
+ script:
31
+ - bash scripts/build_olm_windows_wheel.sh
32
+ artifacts:
33
+ paths:
34
+ - dist-wheels/
35
+
36
+ build-windows-bundle:
37
+ stage: package
38
+ image: tobix/pywine:3.13
39
+ <<: *windows-rules
40
+ needs: [build-olm-windows-wheel]
41
+ script:
42
+ - bash scripts/build_windows_dist.sh
43
+ artifacts:
44
+ paths:
45
+ - dist-windows/befundschani/
46
+
47
+ build-windows-msi:
48
+ stage: package
49
+ image: debian:bookworm
50
+ <<: *windows-rules
51
+ needs: [build-windows-bundle]
52
+ before_script:
53
+ - apt-get update -qq
54
+ - apt-get install -yqq --no-install-recommends msitools wixl python3
55
+ script:
56
+ - bash scripts/build_windows_msi.sh
57
+ artifacts:
58
+ paths:
59
+ - dist-windows/*.msi
60
+
61
+ # macOS: no CI job — there is no macOS runner available (GitLab SaaS macOS
62
+ # runners need Premium). Build locally on a Mac: `make dmg`
63
+ # (scripts/build_macos_dmg.sh). Re-add a job with a runner tag if a Mac
64
+ # runner is ever registered.
65
+
66
+ build:
67
+ stage: build
68
+ image: python:3.13-slim
69
+ rules:
70
+ - if: $CI_COMMIT_TAG
71
+ script:
72
+ - pip install build
73
+ - python -m build
74
+ artifacts:
75
+ paths:
76
+ - dist/
77
+
78
+ publish-pypi:
79
+ stage: publish
80
+ image: python:3.13-slim
81
+ rules:
82
+ - if: $CI_COMMIT_TAG
83
+ environment: pypi
84
+ # OIDC token for PyPI Trusted Publishing (no API key stored in CI).
85
+ # twine >= 6.1 detects PYPI_ID_TOKEN and exchanges it against PyPI itself.
86
+ id_tokens:
87
+ PYPI_ID_TOKEN:
88
+ aud: pypi
89
+ script:
90
+ - pip install -U "twine>=6.1"
91
+ - twine upload dist/*
@@ -0,0 +1,63 @@
1
+ # Changelog
2
+
3
+ ## Unreleased
4
+
5
+ - CI: PyPI release pipeline on git tags via Trusted Publishing (OIDC, GitLab environment "pypi"), no stored token
6
+ - Outbox pipeline: DaMe outbox → EDIFACT parse → ME→MXID lookup (medspeak API) → encrypted Matrix send → archive
7
+ - Inbox pipeline: Matrix documents (.pdf/.lab/.bef/.req/.edf) → DaMe inbox + read receipt; auto-join invites
8
+ - medspeak API client with Matrix-OpenID token lifecycle (request/cache/refresh, no API key)
9
+ - Device verification: recovery-key (SSSS) self-signing and emoji/SAS verification in the settings dialog
10
+ - Matrix layer migrated from mautrix to matrix-nio[e2e] with a real persistent crypto store (nio_store/)
11
+ - Daemon rewritten as asyncio application; IPC wire protocol unchanged; setup-required gate + unverified warning
12
+ - Settings dialog: archive folder picker; daemon is paused during Matrix setup (single-process store)
13
+ - Packaging: hatchling build backend so console scripts and tests work from an installed package
14
+ - Tray app: first-run auto-launches setup; Settings/Show-Hide/Quit context menu; open DaMe inbox
15
+ - Own ME number: fetched from the medspeak API (GET /api/v1/me) at setup, manual fallback field
16
+ - Outbox sender-check + inbox recipient-check against the own ME number (both off when unset)
17
+ - PyInstaller bundle (befundschani.spec): setup wizard + daemon; setup installs the service then runs setup
18
+ - Cross-platform service installer (systemd/launchd/Windows) with frozen-exe paths; daemon pause/resume via IPC
19
+ - Setup: expired saved token no longer dead-ends — falls back to password entry instead of a hard error
20
+ - .env credential seeding (HOMESERVER/MATRIX_USERNAME/MATRIX_PASSWORD/MATRIX_RECOVERY_KEY, folders, ME) to skip re-typing
21
+ - Setup verification no longer hangs: SAS sync drops full_state, waits a bounded 3 min, then lets setup finish unverified
22
+ - Request timeouts (20 s) on all setup HTTP calls (verification + medspeak API) so a slow homeserver can't stall setup
23
+ - Quit now works even with the Settings dialog open: its background worker is stopped and process exit is guaranteed
24
+ - Settings OK button enabled only after a fresh successful Test Connection; any credential/security-key change disables it
25
+ - .env credentials override a saved config (fixes seeded HOMESERVER not showing); a seeded password logs in fresh instead of reusing a stale token
26
+ - Username normalization: accepts @user, user, @user:domain or user:domain — logged in as a full MXID (missing domain from homeserver)
27
+ - Default homeserver is https://medspeak.io (unless a saved config or .env overrides); homeserver input normalized to https://
28
+ - Settings: Connection and Folder groups now use a form layout (aligned labels) instead of ad-hoc rows
29
+ - Live per-keystroke field validation (Qt6 validators): homeserver/username/recovery-key turn red while invalid
30
+ - ME/mailbox number is free text (any practice identifier; no ME-prefix required) — also in the EDIFACT parser
31
+ - Main window redesigned for medical staff (German): connection status, medspeak-ID, ME number, and a colour-coded list of sent/received/failed documents
32
+ - About dialog explains the app, credits the medspeak association, links to medspeak.io; shows the Befund-Schani + medspeak logos
33
+ - Befund-Schani mascot (assets/logo.svg) is the app/window/taskbar/tray icon and the main-window header
34
+ - Test Connection reuses a valid saved session (same device, no re-verification); a fresh device is created only on a real password login
35
+ - Test helper to wrap a plain PDF into a sendable DaMe befund (tests/edifact_helpers.py: make_befund + random_me_number); scripts/make_demo_befunde.py generates demo befunde outside the repo
36
+ - Dialogs say "DaMe/GNV/medicalNet" and note that Befund-Schani does not affect their normal operation
37
+ - Recovery key field is masked (like the password) and validated live against its real format (base58 SSSS key)
38
+ - Full Qt6 i18n: all UI strings via tr() (English source), German translation bundled (befundschani_de.qm); locale-aware loader also localizes Qt's standard buttons
39
+ - Settings: "Automatic Start" group with "Set up as a service" button; OS-specifics encapsulated in ServiceManager classes
40
+ - Fix: self-sent documents addressed to the own ME number now land in the DaMe inbox (sync echo was dropped before)
41
+ - Fix: source-mode service unit starts the daemon as a module (relative imports broke every systemd/launchd start)
42
+ - Settings: folder/ME-only changes save via OK without a new connection test; credential edits still require one
43
+ - Settings: window is resizable now; the autostart button is only shown while the service is not installed yet
44
+ - Main window lists skipped documents (wrong recipient) instead of dropping them silently
45
+ - medspeak API base URL now follows the homeserver (test server talks to test API); .env API_BASE_URL overrides
46
+ - Main window shows "Connected to <server>" with the real homeserver domain instead of a hardcoded "medspeak"
47
+ - Settings: ME number is optional — own block with checkbox below the connection test; auto-fetched when enabled
48
+ - Connection test checks the medspeak account: missing account/ME shows a danger notice + one-time browser login link
49
+ - Settings: ME number entry is locked until a connection test has succeeded (or an untouched tested session exists)
50
+ - ME number: info note on the checkbox; sending is only active with an ME number (daemon skips the outbox without one)
51
+ - An API-verified ME number becomes read-only (own_me_verified persisted) — removable only by unchecking the box
52
+ - Fix: a removed ME number (saved as null) is no longer re-enabled by the ME_NUMBER seed from .env
53
+ - Split ME identity from function toggles: "send via medspeak" and "deliver to DaMe inbox" — daemon honors both
54
+ - ME number is now fully API-driven: read-only field filled by the connection test; no checkbox/manual entry
55
+ - Settings: ME auto-refresh on open, hint label, profile-link button beside the field; both toggles need an ME
56
+ - Settings: start/stop buttons for the background service (state-aware, OS-independent via ServiceManager)
57
+ - Spelling "medSpeak" in all user-visible texts; About: version, AGPL-3.0 license link, GitLab source link
58
+ - Main window: 50% larger logo, version + medSpeak association under the title; Help menu opens GitLab issues
59
+ - Main window: "medSpeak ID" label without "Your" (consistent with "ME number")
60
+ - Wrong-recipient reports are delivered to the DaMe inbox anyway, with a clear "Recipient mismatch" log warning
61
+ - Main window 50% wider; message list gets a context menu with "Copy message" (clipboard)
62
+ - Windows MSI pipeline: mingw cross-built python-olm wheel, PyInstaller under Wine, WiX/wixl MSI packaging
63
+ - macOS target: build script + `make dmg` (native .app/DMG on a Mac; manual CI job for macOS runners)