Change log#

0.1.2 (unreleased)#

New features#

  • Added configurable per-field anonymization modes with four options: keep (preserve original), remove (strip property), randomize (hash - default), and replace (fixed placeholder). Supports 10 configurable fields: SUMMARY, DESCRIPTION, LOCATION, COMMENT, CONTACT, RESOURCES, CATEGORIES, ATTENDEE, ORGANIZER, and UID. New field_modes parameter in anonymize() function. CLI flags: --summary, --description, --location, etc. Web API: config field in request bodies and query parameters. Frontend: collapsible “Advanced Options” section in all three tabs. Backward compatible with existing preserve parameter. Constraint: UID cannot use remove mode (would break recurring events). See Issue 92.

  • Added Fernet-based encrypted links for live calendar proxying. Endpoints: POST /fernet-generate (creates token) and GET /fernet/{token} (fetches and anonymizes on-the-fly). Token encrypts source URL and salt via FERNET_KEY environment variable. Frontend radio buttons toggle between Fernet (live) and R2 (snapshot) modes. Added cryptography>=46.0.0 to [web] dependencies. See Issue 95.

  • Added /anonymized endpoint for curl-friendly anonymization. Supports GET with ics query parameter and POST with raw ICS body. Returns text/calendar without Content-Disposition header for easy piping. See Issue 25.

  • Added shareable links with Cloudflare R2 storage. Users can generate time-limited public URLs for anonymized calendars with 30-day auto-expiry. New endpoints: POST /share (generate link) and GET /s/{id} (retrieve file). Frontend checkboxes in all three tabs (upload, paste, fetch URL). R2 client wrapper with MockR2Client for local dev and WorkersR2Client for production. Health endpoint reports R2 availability. R2 bucket binding configured in wrangler.jsonc. See Issue 7.

  • Added Cloudflare Workers deployment support with Python FastAPI via Pyodide. Configured wrangler.jsonc for Workers Assets serving static files. Created worker.py entry point using asgi.fetch() integration. Added build.sh to bundle local package into python_modules/. GitHub Actions workflow deploys on main branch. Custom domain configured at https://icalendar-anonymizer.com. See Issue 19 and PR 83.

  • Added Docker setup for self-hosting. Multi-stage Dockerfile with Python 3.13-slim, non-root user (UID 1000), and gunicorn with uvicorn workers. Health check endpoint GET /health returns service status, version, and feature flags. docker-compose.yml with environment variables for host, port, workers, and file size limit. Documentation at docs/usage/self-hosting.rst. See Issue 8.

  • Added frontend interface with file upload, paste, and URL fetch capabilities. Implemented drag and drop file upload with visual feedback. Added progressive enhancement for no-JavaScript environments. Provided WCAG AA compliant accessibility features (keyboard navigation, screen readers). Included mobile-responsive design for all device sizes. Zero external dependencies (vanilla HTML/CSS/JS). See Issue 5.

  • Added FastAPI web service with three endpoints: POST /anonymize (JSON), POST /upload (file), GET /fetch (URL). SSRF protection blocks private IPs, localhost, and invalid schemes. 10s timeout, 10MB limit. Install: pip install icalendar-anonymizer[web]. See Issue 4.

Minor changes#

  • Added REUSE.toml for fallback licensing of files without SPDX headers (auto-generated _version.py). In-file headers remain preferred. See Issue 58.

  • Improved test coverage for Cloudflare Workers integration. See PR 90.

  • Moved fastapi, httpx, and python-multipart from core dependencies to [web] extras. Base installation now only requires icalendar. See Issue 23.

  • Updated documentation to use python -m pip per best practices.

Bug fixes#

  • Fixed property iteration causing subcomponent corruption. Changed calendar property iteration from property_items() to items() to avoid copying subcomponent properties to calendar level, and added filtering of BEGIN/END structural markers in component property processing. This resolves malformed ICS output where event properties appeared at calendar level and were wrapped in spurious subcomponents during serialization/deserialization. See Issue 92.

  • Fixed Cloudflare Workers deployment issues including module bundling, build order, static asset serving, and wrangler configuration. See PR 84, PR 85, PR 86, PR 87, PR 88.

0.1.1 (2025-12-25)#

New features#

  • Added Sphinx documentation with PyData theme on Read the Docs. Includes installation guide, Python API reference with property table and autodoc, CLI usage guide, web service API documentation, and contributing guide with commit format reference. Changed bash to shell code-block lexer, converted lists to definition lists, added documentation standards section. Configured docs/conf.py with sphinx_design, sphinx_copybutton, sphinx.ext.intersphinx. Updated pyproject.toml with doc dependencies. Added badge to README.md. Documentation at https://icalendar-anonymizer.readthedocs.io/stable/. See Issue 9 and PR 60.

  • Added .readthedocs.yaml configuration file with Ubuntu 24.04 build environment and Python 3.13 to enable automatic documentation builds on Read the Docs. See PR 56.

  • Added command-line interface with icalendar-anonymize and ican commands. Supports stdin/stdout piping, file I/O, and verbose mode. Uses Click for argument parsing with built-in - convention for Unix-style streams. Binary mode handling for ICS files. Comprehensive error handling with clear messages. Install with pip install icalendar-anonymizer[cli]. See Issue 3.

Minor changes#

  • Commented out CHANGES.rst formatting guidelines to hide from rendered documentation. Added note in CONTRIBUTING.md directing contributors to read the source file for formatting guidelines. Guidelines remain visible in source. See Issue 61.

Bug fixes#

  • Fixed GitHub release notes to strip “v” prefix from PyPI version in install command. Added version extraction step in .github/workflows/release.yml to convert tag v0.1.0 to 0.1.0 for pip install command, ensuring correct PyPI package installation.

0.1.0 (2025-12-05)#

New features#

  • Added preserve parameter to anonymize() function. Accepts optional set of property names to preserve beyond defaults. Case-insensitive. Allows preserving properties like CATEGORIES or COMMENT for bug reproduction when user confirms no sensitive data. Added 7 tests for preserve functionality. See Issue 53.

  • Added core anonymization engine with anonymize() function using SHA-256 deterministic hashing. Removes personal data (names, emails, locations, descriptions) while preserving technical properties (dates, recurrence, timezones). Configurable salt parameter enables reproducible output. Property classification system with default-deny for unknown properties. Structure-preserving hash functions maintain word count and email format. UID uniqueness preserved across calendar. Special handling for ATTENDEE/ORGANIZER with CN parameter anonymization. Test suite with 35 tests achieves 95% coverage. See Issue 1 and Issue 2.

  • Added comprehensive CI/CD workflows with GitHub Actions: test matrix across Ubuntu/Windows/macOS with Python 3.11-3.13, Ruff to lint and check the format of code, Codecov integration with multi-platform coverage tracking, PyPI trusted publishing (OIDC, no tokens required), Docker multi-arch builds (AMD64/ARM64), and automatic GitHub releases with generated notes. Added .github/workflows/tests.yml, .github/workflows/publish.yml, .github/workflows/docker.yml, and .github/workflows/release.yml. Configured hatch test matrix for local multi-version testing and coverage exclusions in pyproject.toml. Added CI/CD badges to README.md (tests, coverage, PyPI version, Python versions, Docker pulls). Added test structure with placeholder files referencing related issues. Docker images published to Docker Hub at sashankbhamidi/icalendar-anonymizer. See Issue 10.

  • Added .gitattributes to normalize line endings across platforms (LF in repository, native line endings on checkout).

  • Added comprehensive pre-commit hooks configuration with Ruff linting/formatting, file integrity checks, and commit message validation. Updated CONTRIBUTING.md with setup instructions and usage documentation. Added Ruff badge to README.md. See Issue 20.

  • Added conventional commits configuration (.cz.toml), pre-commit hooks, CI workflows, and documentation. See Issue 27.

  • Applied Sphinx best practices to CHANGES.rst including proper RST roles, subheadings, and past tense verbs. See Issue 31.

  • Added project configuration files (.gitignore, .editorconfig, .python-version, requirements-dev.txt). See Issue 16.

  • Added LICENSE with AGPL-3.0-or-later license. See Issue 14.

  • Added CONTRIBUTING.md with development workflow, commit message format, testing requirements, and project structure. See Issue 15.

  • Added README.md with installation instructions and usage examples for Python API, CLI, and web service. See Issue 13.

  • Added pyproject.toml with hatchling build system, hatch-vcs version management, package structure, and dependencies. Tests included in package at src/icalendar_anonymizer/tests/. See Issue 12.

  • Added REUSE specification compliance with SPDX headers to all source files, configuration files, documentation, and workflows. Added .github/workflows/reuse.yml for automated CI compliance checking and reuse hook to .pre-commit-config.yaml for local validation. Downloaded LICENSES/AGPL-3.0-or-later.txt. Project is fully compliant with REUSE 3.3 specification for clear licensing. See Issue 22.

Minor changes#

  • Standardized docstring format to multi-line Google-style across all modules. Removed placeholder Examples sections. See Issue 52.

  • Parametrized duplicate test patterns using pytest.mark.parametrize() for datetime, recurrence, metadata, text anonymization, and word count tests. Reduced test duplication while maintaining coverage. See Issue 52.

  • Added doctest validation for core modules with test_with_doctest.py. See Issue 52.

  • Updated CONTRIBUTING.md with code style guidelines including docstring format, test organization patterns, and import conventions. See Issue 52.