Skip to content

Changelog

Changelog

1.3.3 (2026-11-07)

Bug Fixes

  • bump dnspython >=2.9.0 to resolve CVE-2026-114605 (#419) (#420) (b9d5ee9)

1.3.2 (2026-11-07)

Documentation

  • AGENTS.md canonical, CLAUDE.md symlink (#421) (82e74d7)

1.3.1 (2026-11-02)

Bug Fixes

  • bump certifi >=2026.10.19 to remove compromised eMudhra CA certs (#409) (#413) (37e17a1)
  • bump filelock >=4.2.1 to resolve 3 CVEs (#411) (#412) (4eaa49e)
  • bump pillow >=13.0.0 and fastembed >=0.9 to resolve 35+ CVEs (#410) (#414) (b40fd68)
  • bump urllib3 >=2.8.0 to resolve 3 CVEs (#397) (#400) (e38b741)
  • get CI green and fold in the open bot PRs (#405, #406) (#408) (4a6b354)
  • make the name-key delta migration one-time (#394) (3b1bae9)
  • quiet clipboard fallback when pbcopy has no pasteboard (#407) (8fb4be8)

1.3.0 (2026-10-04)

Features

Bug Fixes

  • bump anyio>=4.14.2 to resolve CVE-2026-63374 and CVE-2026-64847 (#375) (#376) (4a92718)
  • request immutable ids for outbox drafts (#378) (bde2bb2)
  • scope outbox receipts, save the token cache atomically (cece5ad)
  • skip German system folders in mail auto-discovery (#391) (4a8c454)

1.2.5 (2026-09-21)

Bug Fixes

  • replace N+1 DB query patterns in worker and admin state (#361) (#368) (2ee15d3)

1.2.4 (2026-09-09)

Bug Fixes

  • bump mkdocs-material to >=9.7.7 for CVE-2026-73295 (#349) (#352) (2f95ccd)
  • use is_relative_to instead of startswith for path-traversal guard (#341) (#343) (8c35fbf)

1.2.3 (2026-08-27)

Bug Fixes

  • close four recurring sync failures and an unretryable-draft path (#311) (b85200f)
  • retry token-transport faults and bound MSAL calls with a timeout (#309) (fd95a72)
  • token acquisition never prompts (#312) (d3cdb2c)

1.2.2 (2026-08-21)

Bug Fixes

  • add missing return type annotations in commands and config_loader (#303) (#306) (a4733bf)

1.2.1 (2026-08-19)

Bug Fixes

  • enforce attachment_root boundary in resolve_attachment (#299) (#300) (4b8d8b6)

1.2.0 (2026-08-10)

Features

  • consolidate five units into m365-brain (4d7eb21)
  • file catalogue, three silent-config fixes, and publication readiness (b349830)
  • knowledge layer, Graph transport, and the vault path contract (2f587f6)
  • make the file catalogue real, close three silent-config defects, and scrub for publication (1968fbd)
  • one config root covering every knob the port needs (83c0a68)
  • runtime, CLI, and the three bundled skills (bf1401a)
  • the typed outbox, Graph file writes, and auth profiles (dcaa3a1)

Bug Fixes

  • $top on a delta query is the item budget, not a page size (#264) (81912ca)
  • bump pypdf lower bound to 6.15.0 for CVE-2026-71852 and CVE-2026-71870 (#277) (#281) (3cbe17d)
  • drop email lookback_days, a window Graph never applied (#266) (df0a98f)
  • keep logs off stdout in every verb, not just two (cf242d9)
  • make a capped answer say it was capped (a319694)
  • make a contact's address resolvable by ops links (ce90a00)
  • make a contact's address resolvable by ops links (70e92e7)
  • make a Teams chat's participants countable by ops tiers (a94be26)
  • make a Teams chat's participants countable by ops tiers (b64ebd7)
  • make every config knob bind, or take it out (e7ea191)
  • resolve every printed path, and accept one back (36cdb69)
  • scope the prune to the roots a run actually walked (26b8294)
  • separate two status vocabularies, give relations spellable types (#265) (83081a4)
  • stop answering three different questions with exit 3 (d13236b)
  • stop four words from carrying two vocabularies each (a076ba6)

Documentation

  • add INTENT.md, CONTRACTS.md, and ADRs 0001-0012 (b335ef0)
  • author the deferred backlog (51d05fd)
  • bring in the knowledge-layer design docs and split the test tree (215fd50)
  • stop the shipped documents describing a CLI that is not there (347f01f)
  • task for an application-permission auth profile (4d59fe2)

1.1.1 (2026-08-04)

Bug Fixes

  • add leading dot to svc.ms in SSRF domain allowlist (#182) (d0c5cb7)
  • catch GraphApiError instead of dead httpx.HTTPStatusError in _file_helpers.py (#184) (a65f640)
  • consume OAuth CSRF state token after verification to prevent replay (#245) (219b89d)
  • eliminate TOCTOU race in token cache file permissions (#239) (d10aa75)
  • remove type: ignore suppressions in _teams_ingest.py with assert narrowing (#256) (897d39c)
  • replace type: ignore with sqlalchemy.desc() in admin_state.py (#189) (05ca1b4)
  • store OAuth CSRF state as per-token files (#244) (951bfea)
  • update stale test call sites for consolidated refactors (a75a0e5)

1.1.0 (2026-06-16)

Features

  • adopt obsidian-import 1.2.0 public API and extraction isolation (8773a1d)
  • merge-based incremental Teams sync with whole-history retention (e0d9378)
  • skip non-file Teams attachment types and stop retrying permanent download failures (912396a)
  • teams_chats: download file attachments and inline images (6eae19c)

Bug Fixes

  • add missing teams_chats attachment fields to admin config test fixtures (fcd8bb0)
  • add missing teams_chats attachment fields to test config fixtures (8638edf)
  • escape single quotes in OData folder filter to prevent injection (#214) (a967321)
  • re-raise unexpected exceptions in worker instead of swallowing (#207) (d22f9cc)
  • remove unused _access_token state var storing raw bearer token (#215) (48ab25f)
  • validate user_id as UUID before filesystem path construction (#216) (26ecb6f)

1.0.0 (2026-05-14)

⚠ BREAKING CHANGES

  • EmailExtractorConfig.folders is replaced by a mailboxes list. Each entry has address (use "me" for /me/ endpoints, or a UPN for /users/{address}/ endpoints), folders (list or null for auto-discovery), and output_subdir (storage namespace under emails/).

Features

  • support multiple mailboxes in email extractor (d65700f)

Bug Fixes

  • add server-side admin authorization to AdminState handlers (#169) (4064034)
  • align tests with module split and apply ruff format/imports (16f95c4)
  • email: drop wellKnownName from auto-discover (v1.0 incompatible) (953b6c8)
  • email: drop wellKnownName from auto-discover select (v1.0) (ccea9fc)
  • narrow SSRF allowlist by replacing .windows.net with specific CDN domains (#171) (e4bd3d9)
  • pin pillow >=12.2.0 to remediate CVE-2026-40192 (#127) (509ab6d)
  • sanitize attachment filename to basename to prevent path traversal (#170) (f8ad054)

0.3.0 (2026-04-13)

Features

  • add Alembic DB migrations - WP4 (cb7793e)
  • add config.deploy.yaml for Azure Blob storage in production (74a7ea5)
  • add email attachment download + dedup to m365-extract (620b587)
  • add observability (WP3) + type converters config (WP2e) (5e01da6)
  • add sync type and pagination transparency logging for email (a09cda0)
  • add truncation indicator to teams chat frontmatter (4460228)
  • enable onedrive, sharepoint, contacts extractors (55bf9c6)
  • harden continuous mode with auth failure recovery and heartbeat logging (f5d8ea6)
  • implement contacts and directory extractors (79c9149)
  • implement contacts and directory extractors (4666ef0), closes #16
  • include attendee email and status in calendar events (0c35526)
  • merge daemon into web app (WP8) + constitution fixes (b06f67c)
  • per-user storage isolation in daemon (8a16324)
  • Sub-phase 4A — TokenStore, UserManager, WebConfig (9bf5c3c)
  • Sub-phase 4B — auth code flow + web token provider (c649172)
  • Sub-phase 4C — FastAPI app shell with auth, sync, health endpoints (da325e8)
  • Sub-phase 4D — scheduler + admin routes (758bec4)
  • unify deployment config — single config.deploy.yaml for both services (d7b848d)

Bug Fixes

  • add missing email config fields and fix token expiry buffer in tests (5874b96)
  • add missing email config fields to test fixtures and fix token expiry buffer (1588b7f)
  • add missing graph config fields to admin config loader test fixtures (e02a30a)
  • add missing graph config fields to admin config loader test fixtures (5d515d7)
  • add missing graph config fields to admin config loader tests (e525471)
  • add missing graph config fields to admin test fixtures (903b35b)
  • add missing graph config fields to admin test fixtures (b283168)
  • add missing graph config fields to admin test fixtures (6b3478f)
  • add missing graph config fields to admin test fixtures (832b5c5)
  • align test_returns_cached_token_when_valid expires_at with token buffer (#98) (63a887b)
  • auto-fix CI failures (attempt 1) (3771c6d)
  • auto-fix CI failures (attempt 1) (fd878e5)
  • auto-fix CI failures (attempt 1) (ea1ae0b)
  • auto-fix CI failures (attempt 1) (9a049d4)
  • auto-fix CI failures (attempt 1) (7c6d081)
  • auto-fix CI failures (attempt 1) (bd4ef3a)
  • auto-fix CI failures (attempt 1) (08726ff)
  • auto-fix CI failures (attempt 1) (18a492c)
  • auto-fix CI failures (attempt 1) (72c16bd)
  • create writable state dir for daemon in Docker (043270a)
  • enable WebSockets + upgrade Actions to Node.js 24 (773374f)
  • Graph API compatibility for teams_channels, contacts, and null sender (e6d4b21)
  • narrow broad except Exception to specific types in email extractor (#94) (9156710)
  • pin pypdf >=6.9.2 to mitigate CVE-2026-33699 infinite loop DoS (#91) (5cc359d)
  • populate items_synced in SyncRecord from extractor counts (181e813)
  • remove magic number and duplicated config fallback in worker.py (#95) (cfd4896)
  • serialize ConvertersConfig to dict before passing to extractors (#44) (5b9c1e0)
  • use JSON params files instead of .bicepparam for Bicep deploy (9c7c567)
  • validate and cap Retry-After header in graph client (#70) (81311e6)
  • validate download URL domains and sanitize SAS tokens from logs (#41) (c5cb8b5)
  • web app must use config.web.yaml (no blob storage env vars) (264358c)

Documentation

  • update MATURITY.md and roadmap.md to reflect dark factory progress (5bd1bab)

[Unreleased]

Breaking Changes

  • m365_extract.frontmatter builders now take a single dataclass argument instead of keyword arguments. Replace build_email_frontmatter(subject=..., message_id=..., ...) with build_email_frontmatter(EmailData(subject=..., message_id=..., ...)). Same shape for build_calendar_frontmatter / CalendarEventData, build_contact_frontmatter / ContactData, build_directory_user_frontmatter / DirectoryUserData, build_onedrive_frontmatter / OneDriveFileData, build_sharepoint_frontmatter / SharePointFileData, build_teams_chat_frontmatter / TeamsChatData, and build_teams_channel_frontmatter / TeamsChannelData. All dataclass fields are required — callers must pass every field explicitly.

Security

  • Pin pyopenssl>=26.0,<27 to fix CVE-2026-27448 (TLS callback bypass) and CVE-2026-27459 (buffer overflow)
  • Upgrade pypdf from 6.9.2 to 6.10.0 to fix CVE-2026-40260 (memory DoS via crafted PDF XMP metadata, GHSA-3crg-w4f6-42mx)
  • Track CVE-2026-3219 (pip ZIP/tar archive confusion, GHSA-58qw-9mgm-455v, MODERATE) — no fix released yet; pin will be narrowed when a patched pip version is available

Features

  • worker refactor: replaced monolithic daemon thread with independent sync worker (m365_extract/worker.py)
  • Per-(user, extractor) jobs via ThreadPoolExecutor with configurable concurrency
  • PostgreSQL advisory locks prevent duplicate job runs
  • ExtractorStatus model replaces SyncRecord (single row per user+extractor pair)
  • New CLI command m365-extract worker for standalone multi-user sync
  • start_worker_thread() bridge for single-container deployment
  • Per-extractor state files eliminate concurrent write races
  • Dashboard shows per-extractor status grid
  • WorkerConfig section added to config schema
  • docker-compose updated with separate worker service
  • Alembic migration: syncrecord → extractorstatus

Breaking Changes

  • CLI sync --continuous removed (replaced by worker command)
  • SyncRecord model replaced by ExtractorStatus
  • daemon.py, daemon_runner.py, continuous.py deleted

0.2.2 (2026-03-20)

Bug Fixes

  • log warning instead of silently swallowing exceptions in teams_chats.py (#15) (2792534)
  • replace bare RuntimeError with GraphApiError in graph_client.py (#17) (f64cb90)
  • resolve merge conflicts with main (deb79e8)

0.2.1 (2026-03-18)

Bug Fixes

  • add path traversal protection to LocalBackend (3e8a1f3)
  • add path traversal protection to LocalBackend (d670501), closes #3
  • auto-fix CI failures (attempt 1) (eae79af)
  • format local.py to pass ruff format check (68102b5)
  • set restrictive permissions (0600) on MSAL token cache file (ae73ff0)
  • set restrictive permissions (0600) on MSAL token cache file (a41314a), closes #4

0.2.0 (2026-03-17)

Features

  • initial release with full packaging infrastructure (7ab5361)

Bug Fixes

  • disable --locked for setup-pixi in release lockfile update job (4b8a5cc)
  • use docker run with --skipApiVersionCheck for Azurite in CI (470b82a)

[0.1.0] - 2026-03-17

Added

  • Core Graph API client with delta sync, pagination, retry, rate limiting
  • MSAL device code authentication with token caching
  • 6 extractors: email, calendar, teams_chats, teams_channels, onedrive, sharepoint
  • Local filesystem storage backend
  • Azure Blob Storage backend with Azurite dev workflow
  • Document conversion via obsidian-import integration
  • CLI: m365-extract auth login, sync --once, sync --continuous
  • Frozen dataclass config with strict validation and env var expansion
  • Bicep IaC templates for Azure Storage (dev/prod)
  • Docker images (Dockerfile.web, Dockerfile.daemon — multi-stage, non-root)
  • Docker Compose with Azurite emulator (profile)
  • 158 unit tests + 9 Azurite integration tests