Skip to content

Version 2.1.0; macOS package runs on every Apple Silicon chip (M1 to M5 and later) - #23

Merged
AmrasElessar merged 28 commits into
mainfrom
claude/peaceful-galileo-lj97u7
Oct 26, 2026
Merged

AmrasElessar merged 28 commits into
mainfrom
claude/peaceful-galileo-lj97u7

Conversation

@AmrasElessar

@AmrasElessar AmrasElessar commented Oct 26, 2026 •

Copy link
Copy Markdown
Owner

Summary / Özet

  • Sürüm 2.1.0 / Version 2.1.0 — v2.0.0 zaten yayımlı; o zamandan beri gelenler (HTTPS ve yalnızca yerel ağ, Windows / macOS / Linux paketleri ve başlatıcılar, imzalı güncellemeler, VirusTotal, Hakkında ve Lisanslar) 2.1.0 olur. config.py, pyproject.toml, web/package.json (+ lock, npm version), README rozeti; CHANGELOG [Unreleased] → [2.1.0].
    v2.0.0 is already published; everything since becomes 2.1.0, so the release workflow can publish a new tag.
  • Apple Silicon — macOS paketi (arm64) tüm Apple Silicon çiplerinde aynıdır; "M1–M4" yerine "M1 ve sonrası (M5 dahil)": README, sürüm notları, OKUBENI, Hakkında sayfası, THIRD_PARTY_LICENSES.md.
    The arm64 package is the same for every Apple Silicon Mac; the docs now say M1 and later.

After merging: Actions ▸ Release ▸ Run workflow on main with publish ticked creates v2.1.0.

Type of change / Değişiklik tipi

  • 🐛 Bug fix (non-breaking change which fixes an issue)
  • ✨ New feature (non-breaking change which adds functionality)
  • 💥 Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • 📝 Documentation update
  • 🔧 Refactor / chore
  • 🔒 Security fix

Checklist

  • I have read CONTRIBUTING.md
  • Server checks pass (cd server && ruff check . && ruff format --check . && mypy adminpdf && pytest) — 348 passed / 11 skipped locally
  • Web checks pass (cd web && npm run check && npm run build) — only the version field changed
  • I have added tests that prove my fix is effective or that my feature works
  • I have updated CHANGELOG.md under [Unreleased]
  • User-facing strings are in both Turkish and English (Field(tr=, en=) / t("tr", "en"))
  • The UI stays keyboard-accessible (WCAG 2.1 AA)
  • Documentation is updated (both Turkish and English sections of README.md if applicable)

Linked issues / Bağlı issue'lar

—

Screenshots (UI changes only)

—

Test plan / Test planı

  • Full server test suite passes with VERSION 2.1.0; scripts/release_notes.py 2.1.0 prints the 2.1.0 CHANGELOG section; THIRD_PARTY_LICENSES.md up to date (--check).
  • The branch also carries a content-free merge of its earlier, already squash-merged history (no file changes).

🤖 Generated with Claude Code

https://claude.ai/code/session_01SgNH4tzUdde2tgUEgsfWxD

claude added 24 commits October 26, 2026 07:04
- images_to_pdf: compute the image rect ourselves (PyMuPDF's keep_proportion
  stretched square images over the A4 box) and add a placement option:
  fit / fill (crop) / stretch / original size.
- Tool grid: tint tools usable on the selection pastel green, move them and
  their groups to the front, row-major layout; user-pinned favourites row.
- Shortcuts dialog: up to four columns so it fits on screen.
- SchemaForm: show_if accepts a list of values.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SgNH4tzUdde2tgUEgsfWxD
- Files and jobs belong to an owner (this machine, or one paired device);
  other devices get 404. Owner ids are hashes, never the session cookie.
- A loopback request carrying proxy forwarding headers is treated as
  remote, so a local reverse proxy cannot make the LAN 'local'.
- Pairing: keys under 12 characters refused at start-up, a global attempt
  limit on top of the per-client one, bounded limiter memory, sessions
  expire after 30 days and are capped.
- LibreOffice runs with a throwaway hardened profile: no macros or active
  content, links never updated, no recalculation on load, all network
  traffic sent to a dead proxy (tests cover SSRF and local file includes).
- API responses are no-store; extra security headers; uvicorn Server
  header off; /api/docs off unless APT_API_DOCS=true.
- Storage cap (APT_MAX_STORAGE_MB, 507) and per-owner pending job cap (429);
  the sweeper no longer expires inputs of running jobs.
- Docker trusts only the bridge gateway (APT_TRUSTED_NETWORKS=gateway),
  never in LAN mode; CI token is read-only.
- pdfjs-dist 6.4.299 (GHSA-hq66-cqwq-w95j).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SgNH4tzUdde2tgUEgsfWxD
Optionally rebuild the redacted document from page images only (no text,
fonts, objects, annotations, attachments or metadata survive), so nothing
under a treatment can be recovered by any tool.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SgNH4tzUdde2tgUEgsfWxD
- HTTPS on by default with the server's own name-constrained local CA
  (private addresses and local names only, so a leaked key cannot vouch for
  real websites); the server certificate follows LAN address changes.
  TLS 1.2+, ECDHE + AEAD ciphers; HSTS only for DNS names.
- Clients outside the local network (public addresses) are always refused;
  APT_TRUSTED_NETWORKS may only list local ranges.
- --trust-ca and a one-time OS trust prompt on desktop start; public
  /api/session/ca.crt for devices; 'Connect device' dialog on the server PC
  with a pairing QR code (segno) and the CA fingerprint.
- Mobile: compact header, scrollable viewer modes, KVKK findings usable on
  phones, no keyboard hints on touch, 40 px touch targets, no iOS zoom on
  input focus; opaque KVKK preview boxes.
- Docker health check, CI and release smoke tests over verified HTTPS.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SgNH4tzUdde2tgUEgsfWxD
The Windows package now ships Tesseract with tur/eng/osd data in ocr/, so
OCR works on PCs whose network blocks downloads. Sources are pinned in
scripts/ocr/sources.json (SHA-256 enforced when set) and the installer's
signature is reported at build time; ocr/manifest.json records the SHA-256
of every bundled file, the app re-checks it before use and refuses a
damaged or altered bundle. 'OCR Onar (Windows).bat' repairs language data
only with files matching those hashes; install-ocr-windows.ps1 verifies
pinned hashes too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SgNH4tzUdde2tgUEgsfWxD
- AdminPDFToolkit.exe (C# 5 WinForms, built with the Windows csc): ticks
  off every component via python -m adminpdf.selfcheck, starts the server
  with no console window, shows addresses and the certificate
  fingerprint, network-sharing switch, notification-area icon. Version
  info and asInvoker manifest; Authenticode signing when the
  WINDOWS_SIGN_PFX secret is set. .bat files move to scripts\.
- python -m adminpdf.updater: optional update check; installs only
  releases whose Ed25519-signed SHA256SUMS verifies, matching hash, never
  a downgrade, zip-slip safe; data\ is kept. Release workflow writes
  SHA256SUMS(.sig) and release-manifest.json (scripts/release_signing.py).
- Ghostscript bundled in gs\; Tesseract and Ghostscript resolved to their
  newest release at build time and verified against GitHub's published
  SHA-256; Ghostscript's source tarball is published with the release.
- CI compiles the launcher on Windows with /warnaserror.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SgNH4tzUdde2tgUEgsfWxD
- Certificates: cap the common name at 64 characters (long computer
  names broke certificate creation, seen on macOS runners).
- Tests: no POSIX mode check on Windows; a LibreOffice that refuses the
  crafted documents outright also passes (nothing leaks).
- Windows package: unpack the Tesseract / Ghostscript NSIS installers
  with 7-Zip instead of a silent install (which re-launched elevated and
  returned before any file existed); pin Tesseract to its newest release
  v5.4.0.20240606 by SHA-256.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SgNH4tzUdde2tgUEgsfWxD
The start-up banner contains Turkish letters that cp1252 cannot encode;
the server died before listening when started from a .bat on such a PC.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SgNH4tzUdde2tgUEgsfWxD
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SgNH4tzUdde2tgUEgsfWxD
- python -m adminpdf.launcher: the Windows launcher's window in Tk —
  component checklist, server without a terminal (own process group),
  network sharing, update notice, data in the user's folder (macOS may
  run downloaded apps from a read-only location).
- scripts/build_unix_portable.py: python-build-standalone (SHA-256
  checked) + the app; Linux x86_64 tar.gz with a menu-entry script,
  macOS arm64 AdminPDFToolkit.app, ad-hoc signed (no paid Apple account;
  'Open Anyway' once). Release CI builds and smoke-tests both.
- Updater looks for the package of the running system; in-place install
  stays Windows-only. Self-check shows brew / apt / dnf commands for a
  missing Tesseract or Ghostscript.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SgNH4tzUdde2tgUEgsfWxD
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SgNH4tzUdde2tgUEgsfWxD
- In-app "Hakkında ve Lisanslar / About & Licences" dialog with separate
  Turkish and English tabs: supported systems, first-start warnings,
  every installed Python package (direct and transitive, from metadata),
  web bundle npm packages, bundled tool files with SHA-256 sources,
  programs, runtimes, fonts, data, build tools and methods (/api/about).
- scripts/third_party.py replaces python_licenses.py and writes
  THIRD_PARTY_LICENSES.md as a full Turkish part then a full English part.
- Windows SmartScreen, certificate prompt, firewall, macOS Gatekeeper,
  keychain and browser/phone certificate warnings documented on the
  README main page, release notes, OKUBENI files and in the app.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SgNH4tzUdde2tgUEgsfWxD
- scripts/virustotal.py (standard library): uploads the packages and the
  launcher exe to VirusTotal with a free API key (secret
  VIRUSTOTAL_API_KEY), or looks them up by SHA-256; paces itself to the
  free 4-per-minute limit; writes a TR/EN Markdown table and
  virustotal.json. Skips without a key and never fails the release.
- release.yml: virustotal job between the builds and publish; its table
  goes into the release notes and the step summary, virustotal.json is
  published with the release.
- README: "Güvenlik / Security" badge row (VirusTotal results of the
  latest release via shields.io, HTTPS, LAN only, signed updates,
  verified bundles, CSP, code signing). SECURITY.md and CHANGELOG.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SgNH4tzUdde2tgUEgsfWxD
…ut a web build

- mypy: named function instead of a lambda returning CompletedProcess;
  the os.startfile ignore is no longer unused on Windows.
- test_stream_json_runs_the_selfcheck: CI has no web build, so the
  self-check is not "ready" there; assert the exit code matches the
  streamed result instead of requiring 0.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SgNH4tzUdde2tgUEgsfWxD
…Brand links

- Highlights (TR/EN): extra-secure KVKK PDF, image-to-PDF page size and
  placement, HTTPS + LAN-only + per-device isolation, green/first tools
  and favourites, phone/tablet QR, in-app About & Licences.
- Phones/tablets: the launcher's Network sharing switch (the old
  'Baslat - Ag Paylasimi (Windows).bat' no longer exists).
- English install: macOS / Linux packages; launcher row in the stack;
  350+ tests, VirusTotal and signed SHA256SUMS; APT_OCR_DIR/APT_GS_DIR.
- Roadmap: portable packages, HTTPS/LAN pairing, signed updates and
  VirusTotal done; MSI installer left open. D Brand: public sibling repos.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SgNH4tzUdde2tgUEgsfWxD
…arning

- README Installation: numbered macOS steps with the exact Gatekeeper
  message (incl. macOS 15 wording), Done (not Move to Trash) > Privacy &
  Security > Open Anyway, xattr alternative, keychain password, brew;
  numbered Linux steps with the browser certificate import and apt/dnf.
  Same in the English part.
- Launcher menu names as they are in the app.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SgNH4tzUdde2tgUEgsfWxD
- security.default_gateway reads /proc/net/route with Path.read_text
  (file always closed).
- launcher: say why each ignored OSError is safe to ignore.
- selfcheck: one import style for importlib.
- third_party / virustotal: explicit parentheses around intentionally
  joined strings in lists.
- test_security: requests made before the assert, not inside it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SgNH4tzUdde2tgUEgsfWxD
On a slow macOS runner the server had not printed its banner after 6 s.
Read stdout line by line in a thread and wait up to 90 s for the banner
(or the process ending); stderr goes to a file so the pipe cannot fill.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SgNH4tzUdde2tgUEgsfWxD
…ter)

The arm64 package is the same for all Apple Silicon Macs; "M1–M4" read
as if M5 were unsupported. README, release notes, OKUBENI, About page
and THIRD_PARTY_LICENSES.md now say M1 and later.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SgNH4tzUdde2tgUEgsfWxD
v2.0.0 is already published; everything since (HTTPS and local-network
only, self-contained Windows / macOS / Linux packages with launchers,
signed updates, VirusTotal, About & Licences) becomes 2.1.0. Version in
config.py, pyproject.toml, web/package.json (npm version), README badge;
CHANGELOG [Unreleased] -> [2.1.0] with compare links.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SgNH4tzUdde2tgUEgsfWxD
@AmrasElessar AmrasElessar changed the title docs: macOS package runs on every Apple Silicon chip (M1 to M5 and later) Version 2.1.0; macOS package runs on every Apple Silicon chip (M1 to M5 and later) Oct 26, 2026
@AmrasElessar
AmrasElessar enabled auto-merge (squash) October 26, 2026 11:47
Twice today a Linux server job sat for 20+ minutes in 'System tools
(Linux)' while the same step took 20 s on its siblings. Each apt call now
has a timeout and network timeouts, up to three attempts (dpkg repaired
between them), the man-db rebuild is skipped, the step is capped at 20
minutes, and it ends by checking that every tool is installed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SgNH4tzUdde2tgUEgsfWxD
The release workflow signs SHA256SUMS with RELEASE_SIGNING_KEY; the app
now carries the matching Ed25519 public key, so a verified update can be
installed in place instead of only being announced. Checked with a
throwaway SHA256SUMS signed by the new private key. Tests: the
"no key configured" case clears the key explicitly; new test that the
built-in key is a valid Ed25519 public key.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SgNH4tzUdde2tgUEgsfWxD
- The Ubuntu mirror served LibreOffice at a few tens of KB/s and three
  6-minute attempts were not enough. Downloaded .deb files now go into
  the Actions cache (one key per runner image), downloads are kept
  between attempts, and each attempt may take up to 15 minutes.
- pytest-xdist: one test worker per CPU (pytest -n auto). Locally the
  suite drops from 3 min 21 s to about 1 min, all 349 tests passing in
  three runs; the macOS job took 19 minutes serially.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SgNH4tzUdde2tgUEgsfWxD
The runners' azure mirror served packages at ~100 KB/s and a 43 MB
LibreOffice part did not finish in 6 minutes. LibreOffice is now
installed only in the Python 3.13 Linux job (its tests skip elsewhere,
as on Windows and macOS), the apt sources point at archive.ubuntu.com,
and the package cache key includes the Python version so each job keeps
its own package set.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SgNH4tzUdde2tgUEgsfWxD
@AmrasElessar
AmrasElessar merged commit 7ae6b18 into main Oct 26, 2026
27 of 36 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants