Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,18 @@ Format basiert auf [Keep a Changelog](https://keepachangelog.com/de/1.1.0/).

## [Unreleased]

## [1.2.1] - 2026-10-03

> This cumulative source release gathers changes since the published `v1.2.0` (2026-05-02). The duplicate September `[1.2.0]` heading below was a historical changelog label, not a separate published release.

### Fixed
- **RFC 3501 IMAP Date Format Locale Isolation (IMAP-003):**
- Resolved query syntax errors (`BAD Invalid date in SEARCH command`) during `older_than_days` IMAP rule searches on non-English (e.g. German `de_DE`) host locales.
- Implemented `format_imap_date` in `imap_client.py` using fixed RFC 3501 English month tokens (`Jan`..`Dec`) rather than runtime-locale-dependent `strftime("%d-%b-%Y")` (which produced localized abbreviations like `Mrz`, `Mai`, `Okt`, `Dez`).
- Added test coverage in `tests/test_imap_service.py` verifying RFC 3501 date-text formatting across all 12 calendar months and explicitly under active German locale.
- **IMAP filter control-character rejection (2026-10-03):**
- Rejects CR, LF, and NUL in sender and subject inputs before trimming, so malformed rules do not reach IMAP `SEARCH` or deletion.
- Skips the entire invalid rule while continuing other safe rules; quoted-string backslash and quote escaping remains intact.

### Added
- **Pfad B Discoverability, Visual 4-View Architecture, Level 1 SBOM Stand 2026-10-03 & Contract Test Expansion (2026-10-03):**
Expand Down Expand Up @@ -69,7 +76,9 @@ Format basiert auf [Keep a Changelog](https://keepachangelog.com/de/1.1.0/).
- Authored comprehensive bilingual Security Policy (`SECURITY.md`) establishing 48-hour response SLA and 5-day triage (`INV-SLA-10`), supported versions lifecycle (1.2.x), direct security coordinator contacts, private vulnerability advisory paths, and architectural local-first / zero-egress / non-elevated user-mode guarantees.
- Added 6 automated metadata contract tests in `tests/test_metadata.py` validating CI timeouts and concurrency, stale lifecycle automation, gitignore multi-host and lock defense, PEP 621 URL definitions and pytest options, bilingual security policy invariants, and changelog/marketing log recency.

## [1.2.0] - 2026-09-12
### Historical September work (originally labelled `[1.2.0]` on 2026-09-12)

> Correction: this is a historical work entry, not a published `1.2.0` release. The published `v1.2.0` is dated 2026-05-02; this September work is included cumulatively in `1.2.1`.

### Added
- **Pfad B Discoverability, Visual Architecture & Governance Parity (2026-09-12):**
Expand Down
4 changes: 2 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ UniversalMailCleaner operates entirely in standard user mode (`RunAsInvoker`). C

### Strict Version Freeze Discipline

Under policy `T-20260920-167562623`, the current version `1.2.0` is strictly frozen. Routine hygiene, CI matrix, and documentation changes must not bump version numbers; all updates are recorded under `## [Unreleased]` in `CHANGELOG.md`.
Policy `T-20260920-167562623` keeps versions frozen by default. The user-authorized versioned source release recorded in master ticket `T-20261003-933110552` sets the current source-release version to `1.2.1`. Routine hygiene, CI matrix, and documentation changes must not bump it; interim changes are recorded under `## [Unreleased]` in `CHANGELOG.md`. Further version bumps require another explicitly authorized versioned release.

### Plan D Local Development Workflow

Expand Down Expand Up @@ -89,4 +89,4 @@ Die Anwendung läuft vollständig im unprivilegierten Standard-Benutzermodus ohn

### Version-Freeze-Disziplin (T-20260920-167562623)

Die Version `1.2.0` bleibt eingefroren. Alle Änderungen werden unter `## [Unreleased]` im `CHANGELOG.md` erfasst.
Die Freeze-Richtlinie `T-20260920-167562623` hält Versionen standardmäßig eingefroren. Die im Masterticket `T-20261003-933110552` dokumentierte Nutzerautorisierung setzt `1.2.1` als aktuelle Quellrelease-Version. Alltägliche Hygiene-, CI- und Dokumentationsänderungen erhöhen sie nicht; Zwischenänderungen stehen unter `## [Unreleased]` im `CHANGELOG.md`. Weitere Versionssprünge benötigen eine ausdrücklich autorisierte Versionsveröffentlichung.
21 changes: 21 additions & 0 deletions MARKETING-LOG.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,27 @@
# MARKETING-LOG — doc-bricks/UniversalMailCleaner
# Tracked Pfad B Discoverability, Visual Architecture, Governance & Verification Milestones

================================================================================
[2026-10-03 21:38 CEST] [VERSIONED_SOURCE_RELEASE_1_2_1_PREPARATION]
Repository: doc-bricks/UniversalMailCleaner
Branch: release/universalmailcleaner-1.2.1-20261003
Version: 1.2.1 (user-authorized source-release candidate; master ticket T-20261003-933110552)
License: MIT (SPDX-License-Identifier: MIT)
Maintainer: Lukas Geiger ([email protected])
Security Contact: [email protected], [email protected]

- Prepared the 1.2.1 version surfaces and cumulative changelog from the actual
published v1.2.0 release dated 2026-05-02; retained the September work entry
while correcting its duplicate historical 1.2.0 label.
- Recorded IMAP sender/subject control-character rejection (CR, LF, NUL) and
per-rule fail-closed behavior while preserving safe rules and quoted-string
escaping.
- Source release packaging will use the exact reviewed release commit with
`git archive --format=zip`; the archive will contain tracked repository files
only, excluding `.git` and untracked user profiles, with a SHA256SUMS.txt sidecar.
- This entry records release preparation; it does not claim a tag, published
GitHub asset, Store package, or installed application.

================================================================================
[2026-09-12 16:00 CEST] [PFAD_B_DISCOVERABILITY_AND_DESIGN]
Repository: doc-bricks/UniversalMailCleaner
Expand Down
2 changes: 1 addition & 1 deletion README-DE.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

[![Lizenz: MIT](https://img.shields.io/badge/Lizenz-MIT-green)](LICENSE)
[![Hinweis: Urheberrecht](https://img.shields.io/badge/Hinweis-Urheberrecht-blue)](NOTICE)
[![Version](https://img.shields.io/badge/Version-v1.2.0-blue)](CHANGELOG.md)
[![Version](https://img.shields.io/badge/Version-v1.2.1-blue)](CHANGELOG.md)
[![Plattform: Windows](https://img.shields.io/badge/Plattform-Windows-blue?logo=windows)](#sec-10)
[![PySide6](https://img.shields.io/badge/UI-PySide6-41cd52)](https://pypi.org/project/PySide6/)
[![Python 3.10+](https://img.shields.io/badge/Python-3.10%2B-blue?logo=python)](pyproject.toml)
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

[![License: MIT](https://img.shields.io/badge/License-MIT-green)](LICENSE)
[![Notice: Attribution](https://img.shields.io/badge/Notice-Attribution-blue)](NOTICE)
[![Version](https://img.shields.io/badge/Version-v1.2.0-blue)](CHANGELOG.md)
[![Version](https://img.shields.io/badge/Version-v1.2.1-blue)](CHANGELOG.md)
[![Platform: Windows](https://img.shields.io/badge/Platform-Windows-blue?logo=windows)](#quick-start--setup)
[![PySide6](https://img.shields.io/badge/UI-PySide6-41cd52)](https://pypi.org/project/PySide6/)
[![Python 3.10+](https://img.shields.io/badge/Python-3.10%2B-blue?logo=python)](pyproject.toml)
Expand Down
2 changes: 1 addition & 1 deletion README_de.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

[![Lizenz: MIT](https://img.shields.io/badge/Lizenz-MIT-green)](LICENSE)
[![Hinweis: Urheberrecht](https://img.shields.io/badge/Hinweis-Urheberrecht-blue)](NOTICE)
[![Version](https://img.shields.io/badge/Version-v1.2.0-blue)](CHANGELOG.md)
[![Version](https://img.shields.io/badge/Version-v1.2.1-blue)](CHANGELOG.md)
[![Plattform: Windows](https://img.shields.io/badge/Plattform-Windows-blue?logo=windows)](#sec-10)
[![PySide6](https://img.shields.io/badge/UI-PySide6-41cd52)](https://pypi.org/project/PySide6/)
[![Python 3.10+](https://img.shields.io/badge/Python-3.10%2B-blue?logo=python)](pyproject.toml)
Expand Down
2 changes: 1 addition & 1 deletion THIRD_PARTY_LICENSES.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
**Canonical Project License:** MIT License (`MIT`)<br>
**Audit Date:** 2026-10-03 (Pfad B Discoverability & Architecture; Previous: 2026-10-01, 2026-09-26, 2026-09-22)<br>
**Auditor:** Antigravity / Gemini (via GithubBot Pfad B)<br>
**Version:** `1.2.0`<br>
**Version:** `1.2.1`<br>
**Umbrella Ecosystem:** `open-bricks` / `doc-bricks`<br>
**Notice Attribution:** See canonical root [`NOTICE`](NOTICE) file.

Expand Down
2 changes: 1 addition & 1 deletion THIRD_PARTY_LICENSES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Project: UniversalMailCleaner (doc-bricks/UniversalMailCleaner)
Canonical License: MIT License (SPDX: MIT)
Audit Date: 2026-10-03 (Pfad B Discoverability & Architecture; Previous: 2026-10-01, 2026-09-26)
Auditor: Antigravity / Gemini (via GithubBot Pfad B)
Version: 1.2.0 (Strictly frozen per T-20260920-167562623)
Version: 1.2.1 (Strictly frozen per T-20260920-167562623)
Umbrella Ecosystem: open-bricks / doc-bricks
Attribution: See canonical root NOTICE file.

Expand Down
2 changes: 1 addition & 1 deletion llms.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ UniversalMailCleaner is a local-first Windows desktop app for cleaning IMAP and
- Ecosystem Umbrella: open-bricks (https://github.com/open-bricks)
- License: MIT License (SPDX: `MIT`)
- Canonical Attribution: `NOTICE`
- Version: 1.2.0
- Version: 1.2.1
- Main app entry point: `mail_imap_cleaner_v1.py`
- Core modules: `imap_client.py`, `gmail_service.py`, `workers.py`, `models.py`, `scheduler_widget.py`, `profile_exchange.py`
- Third-Party License Inventory & Level 1 SBOM: `THIRD_PARTY_LICENSES.md` & `THIRD_PARTY_LICENSES.txt`
Expand Down
2 changes: 1 addition & 1 deletion mail_imap_cleaner_v1.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@

# ==================== CONFIGURATION ====================

__version__ = "1.2.0"
__version__ = "1.2.1"
APP_NAME = "UniversalMailCleaner"
APP_VERSION = __version__
BASE_DIR = Path.home() / ".mail_cleaner"
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"

[project]
name = "universalmailcleaner"
version = "1.2.0"
version = "1.2.1"
description = "Local-first Windows desktop app for cleaning IMAP and Gmail mailboxes."
readme = "README.md"
requires-python = ">=3.9"
Expand Down
19 changes: 15 additions & 4 deletions tests/test_metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ def test_version_parity():
with open(pyproject_path, "rb") as f:
pyproject_data = tomllib.load(f)
version = pyproject_data["project"]["version"]
assert version == "1.2.0", f"Unexpected version in pyproject.toml: {version}"
assert version == "1.2.1", f"Unexpected version in pyproject.toml: {version}"

# 2. mail_imap_cleaner_v1.py
main_py = ROOT / "mail_imap_cleaner_v1.py"
Expand All @@ -114,6 +114,16 @@ def test_version_parity():
content = readme_path.read_text(encoding="utf-8")
assert f"Version-v{version}-blue" in content or f"v{version}" in content

# 5. Machine-readable and third-party license version surfaces
version_markers = {
"llms.txt": f"- Version: {version}",
"THIRD_PARTY_LICENSES.md": f"**Version:** `{version}`<br>",
"THIRD_PARTY_LICENSES.txt": f"Version: {version}",
}
for filename, marker in version_markers.items():
content = (ROOT / filename).read_text(encoding="utf-8")
assert marker in content, f"Current version missing from {filename}"


def test_manifest_files_exist():
"""Verify all critical repo files exist and are non-empty."""
Expand Down Expand Up @@ -338,11 +348,11 @@ def test_statutory_notice_and_version_freeze():
assert "§ 521 BGB" in de_content
assert "Gefälligkeitsrecht" in de_content

# Strict version freeze: version must be 1.2.0 across pyproject and main
# Strict version freeze after authorized versioned source release: 1.2.1
pyproject_path = ROOT / "pyproject.toml"
with open(pyproject_path, "rb") as f:
data = tomllib.load(f)
assert data["project"]["version"] == "1.2.0"
assert data["project"]["version"] == "1.2.1"


def test_utf8_hygiene():
Expand Down Expand Up @@ -542,7 +552,8 @@ def test_contributing_guide_present_and_invariants():
assert "RunAsInvoker" in content
assert "INV-USER-02" in content
assert "T-20260920-167562623" in content
assert "1.2.0" in content
assert "T-20261003-933110552" in content
assert "1.2.1" in content
assert "Plan D" in content
for inv in INVARIANTS:
assert inv in content, f"Invariant {inv} missing in CONTRIBUTING.md"
Expand Down
Loading