Commit 6e9dea95d0

6e9dea95d015c0f2d335d9b89b8ee843b4c2b05e

parent: fd8ca178a3

Unsigned

cmc <hello@cleberg.net> · 2026-07-17 16:20 UTC

v4.8.0: Bump version and mark shipped in roadmap

Bump AppVersion/marketing version to 4.8.0 and build number to 40 across the
app, widget, and share extension targets. Mark v4.8.0 (markdown/PDF export,
scheduled reports, stronger share affordances, verified local API consistency)
shipped in RELEASE_ROADMAP.md.

Layout: unified · split

DomainDig.xcodeproj/project.pbxproj +12 −12
@@ -495,7 +495,7 @@
495 ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 495 ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
496 CODE_SIGN_ENTITLEMENTS = DomainDig/DomainDig.entitlements; 496 CODE_SIGN_ENTITLEMENTS = DomainDig/DomainDig.entitlements;
497 CODE_SIGN_STYLE = Automatic; 497 CODE_SIGN_STYLE = Automatic;
498 CURRENT_PROJECT_VERSION = 39; 498 CURRENT_PROJECT_VERSION = 40;
499 DEVELOPMENT_TEAM = ZCNAX3VL9D; 499 DEVELOPMENT_TEAM = ZCNAX3VL9D;
500 ENABLE_PREVIEWS = YES; 500 ENABLE_PREVIEWS = YES;
501 GENERATE_INFOPLIST_FILE = YES; 501 GENERATE_INFOPLIST_FILE = YES;
@@ -512,7 +512,7 @@
512 "$(inherited)", 512 "$(inherited)",
513 "@executable_path/Frameworks", 513 "@executable_path/Frameworks",
514 ); 514 );
515 MARKETING_VERSION = 4.7.0; 515 MARKETING_VERSION = 4.8.0;
516 PRODUCT_BUNDLE_IDENTIFIER = net.cleberg.DomainDig; 516 PRODUCT_BUNDLE_IDENTIFIER = net.cleberg.DomainDig;
517 PRODUCT_NAME = "$(TARGET_NAME)"; 517 PRODUCT_NAME = "$(TARGET_NAME)";
518 STRING_CATALOG_GENERATE_SYMBOLS = YES; 518 STRING_CATALOG_GENERATE_SYMBOLS = YES;
@@ -532,7 +532,7 @@
532 ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 532 ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
533 CODE_SIGN_ENTITLEMENTS = DomainDig/DomainDig.entitlements; 533 CODE_SIGN_ENTITLEMENTS = DomainDig/DomainDig.entitlements;
534 CODE_SIGN_STYLE = Automatic; 534 CODE_SIGN_STYLE = Automatic;
535 CURRENT_PROJECT_VERSION = 39; 535 CURRENT_PROJECT_VERSION = 40;
536 DEVELOPMENT_TEAM = ZCNAX3VL9D; 536 DEVELOPMENT_TEAM = ZCNAX3VL9D;
537 ENABLE_PREVIEWS = YES; 537 ENABLE_PREVIEWS = YES;
538 GENERATE_INFOPLIST_FILE = YES; 538 GENERATE_INFOPLIST_FILE = YES;
@@ -549,7 +549,7 @@
549 "$(inherited)", 549 "$(inherited)",
550 "@executable_path/Frameworks", 550 "@executable_path/Frameworks",
551 ); 551 );
552 MARKETING_VERSION = 4.7.0; 552 MARKETING_VERSION = 4.8.0;
553 PRODUCT_BUNDLE_IDENTIFIER = net.cleberg.DomainDig; 553 PRODUCT_BUNDLE_IDENTIFIER = net.cleberg.DomainDig;
554 PRODUCT_NAME = "$(TARGET_NAME)"; 554 PRODUCT_NAME = "$(TARGET_NAME)";
555 STRING_CATALOG_GENERATE_SYMBOLS = YES; 555 STRING_CATALOG_GENERATE_SYMBOLS = YES;
@@ -568,7 +568,7 @@
568 APPLICATION_EXTENSION_API_ONLY = YES; 568 APPLICATION_EXTENSION_API_ONLY = YES;
569 CODE_SIGN_ENTITLEMENTS = DomainDigWidget/DomainDigWidget.entitlements; 569 CODE_SIGN_ENTITLEMENTS = DomainDigWidget/DomainDigWidget.entitlements;
570 CODE_SIGN_STYLE = Automatic; 570 CODE_SIGN_STYLE = Automatic;
571 CURRENT_PROJECT_VERSION = 39; 571 CURRENT_PROJECT_VERSION = 40;
572 DEVELOPMENT_TEAM = ZCNAX3VL9D; 572 DEVELOPMENT_TEAM = ZCNAX3VL9D;
573 GENERATE_INFOPLIST_FILE = NO; 573 GENERATE_INFOPLIST_FILE = NO;
574 INFOPLIST_FILE = DomainDigWidget/Info.plist; 574 INFOPLIST_FILE = DomainDigWidget/Info.plist;
@@ -579,7 +579,7 @@
579 "@executable_path/Frameworks", 579 "@executable_path/Frameworks",
580 "@executable_path/../../Frameworks", 580 "@executable_path/../../Frameworks",
581 ); 581 );
582 MARKETING_VERSION = 4.7.0; 582 MARKETING_VERSION = 4.8.0;
583 PRODUCT_BUNDLE_IDENTIFIER = net.cleberg.DomainDig.DomainDigWidget; 583 PRODUCT_BUNDLE_IDENTIFIER = net.cleberg.DomainDig.DomainDigWidget;
584 PRODUCT_NAME = "$(TARGET_NAME)"; 584 PRODUCT_NAME = "$(TARGET_NAME)";
585 SKIP_INSTALL = YES; 585 SKIP_INSTALL = YES;
@@ -597,7 +597,7 @@
597 APPLICATION_EXTENSION_API_ONLY = YES; 597 APPLICATION_EXTENSION_API_ONLY = YES;
598 CODE_SIGN_ENTITLEMENTS = DomainDigWidget/DomainDigWidget.entitlements; 598 CODE_SIGN_ENTITLEMENTS = DomainDigWidget/DomainDigWidget.entitlements;
599 CODE_SIGN_STYLE = Automatic; 599 CODE_SIGN_STYLE = Automatic;
600 CURRENT_PROJECT_VERSION = 39; 600 CURRENT_PROJECT_VERSION = 40;
601 DEVELOPMENT_TEAM = ZCNAX3VL9D; 601 DEVELOPMENT_TEAM = ZCNAX3VL9D;
602 GENERATE_INFOPLIST_FILE = NO; 602 GENERATE_INFOPLIST_FILE = NO;
603 INFOPLIST_FILE = DomainDigWidget/Info.plist; 603 INFOPLIST_FILE = DomainDigWidget/Info.plist;
@@ -608,7 +608,7 @@
608 "@executable_path/Frameworks", 608 "@executable_path/Frameworks",
609 "@executable_path/../../Frameworks", 609 "@executable_path/../../Frameworks",
610 ); 610 );
611 MARKETING_VERSION = 4.7.0; 611 MARKETING_VERSION = 4.8.0;
612 PRODUCT_BUNDLE_IDENTIFIER = net.cleberg.DomainDig.DomainDigWidget; 612 PRODUCT_BUNDLE_IDENTIFIER = net.cleberg.DomainDig.DomainDigWidget;
613 PRODUCT_NAME = "$(TARGET_NAME)"; 613 PRODUCT_NAME = "$(TARGET_NAME)";
614 SKIP_INSTALL = YES; 614 SKIP_INSTALL = YES;
@@ -626,7 +626,7 @@
626 APPLICATION_EXTENSION_API_ONLY = YES; 626 APPLICATION_EXTENSION_API_ONLY = YES;
627 CODE_SIGN_ENTITLEMENTS = DomainDigShareExtension/DomainDigShareExtension.entitlements; 627 CODE_SIGN_ENTITLEMENTS = DomainDigShareExtension/DomainDigShareExtension.entitlements;
628 CODE_SIGN_STYLE = Automatic; 628 CODE_SIGN_STYLE = Automatic;
629 CURRENT_PROJECT_VERSION = 39; 629 CURRENT_PROJECT_VERSION = 40;
630 DEVELOPMENT_TEAM = ZCNAX3VL9D; 630 DEVELOPMENT_TEAM = ZCNAX3VL9D;
631 GENERATE_INFOPLIST_FILE = NO; 631 GENERATE_INFOPLIST_FILE = NO;
632 INFOPLIST_FILE = DomainDigShareExtension/Info.plist; 632 INFOPLIST_FILE = DomainDigShareExtension/Info.plist;
@@ -637,7 +637,7 @@
637 "@executable_path/Frameworks", 637 "@executable_path/Frameworks",
638 "@executable_path/../../Frameworks", 638 "@executable_path/../../Frameworks",
639 ); 639 );
640 MARKETING_VERSION = 4.7.0; 640 MARKETING_VERSION = 4.8.0;
641 PRODUCT_BUNDLE_IDENTIFIER = net.cleberg.DomainDig.DomainDigShareExtension; 641 PRODUCT_BUNDLE_IDENTIFIER = net.cleberg.DomainDig.DomainDigShareExtension;
642 PRODUCT_NAME = "$(TARGET_NAME)"; 642 PRODUCT_NAME = "$(TARGET_NAME)";
643 SKIP_INSTALL = YES; 643 SKIP_INSTALL = YES;
@@ -655,7 +655,7 @@
655 APPLICATION_EXTENSION_API_ONLY = YES; 655 APPLICATION_EXTENSION_API_ONLY = YES;
656 CODE_SIGN_ENTITLEMENTS = DomainDigShareExtension/DomainDigShareExtension.entitlements; 656 CODE_SIGN_ENTITLEMENTS = DomainDigShareExtension/DomainDigShareExtension.entitlements;
657 CODE_SIGN_STYLE = Automatic; 657 CODE_SIGN_STYLE = Automatic;
658 CURRENT_PROJECT_VERSION = 39; 658 CURRENT_PROJECT_VERSION = 40;
659 DEVELOPMENT_TEAM = ZCNAX3VL9D; 659 DEVELOPMENT_TEAM = ZCNAX3VL9D;
660 GENERATE_INFOPLIST_FILE = NO; 660 GENERATE_INFOPLIST_FILE = NO;
661 INFOPLIST_FILE = DomainDigShareExtension/Info.plist; 661 INFOPLIST_FILE = DomainDigShareExtension/Info.plist;
@@ -666,7 +666,7 @@
666 "@executable_path/Frameworks", 666 "@executable_path/Frameworks",
667 "@executable_path/../../Frameworks", 667 "@executable_path/../../Frameworks",
668 ); 668 );
669 MARKETING_VERSION = 4.7.0; 669 MARKETING_VERSION = 4.8.0;
670 PRODUCT_BUNDLE_IDENTIFIER = net.cleberg.DomainDig.DomainDigShareExtension; 670 PRODUCT_BUNDLE_IDENTIFIER = net.cleberg.DomainDig.DomainDigShareExtension;
671 PRODUCT_NAME = "$(TARGET_NAME)"; 671 PRODUCT_NAME = "$(TARGET_NAME)";
672 SKIP_INSTALL = YES; 672 SKIP_INSTALL = YES;
DomainDig/AppVersion.swift +1 −1
@@ -2,6 +2,6 @@ import Foundation
2 2
3enum AppVersion { 3enum AppVersion {
4 nonisolated static var current: String { 4 nonisolated static var current: String {
5 "4.7.0" 5 "4.8.0"
6 } 6 }
7} 7}
RELEASE_ROADMAP.md +25 −5
@@ -6,7 +6,7 @@ ports, geolocation, subdomains, availability). The next several releases invest
6in *reach and surfacing* — getting that data onto more iOS surfaces and into more 6in *reach and surfacing* — getting that data onto more iOS surfaces and into more
7workflows — rather than adding raw protocol checks. 7workflows — rather than adding raw protocol checks.
8 8
9Current version: `v4.7.0`. 9Current version: `v4.8.0`.
10 10
11## v4.4.1 Patch: Release Readiness — ✅ shipped 11## v4.4.1 Patch: Release Readiness — ✅ shipped
12 12
@@ -68,13 +68,33 @@ Goal: help users interpret and organize, not just collect.
68 domain, tag filter chips, and named saved filter/sort/tag presets 68 domain, tag filter chips, and named saved filter/sort/tag presets
69 (UserDefaults-backed; not yet part of backup/restore). 69 (UserDefaults-backed; not yet part of backup/restore).
70 70
71## v4.8.0 Minor: Reporting & Sharing 71## v4.8.0 Minor: Reporting & Sharing — ✅ shipped
72 72
73Goal: turn point-in-time snapshots into shareable, scheduled deliverables. 73Goal: turn point-in-time snapshots into shareable, scheduled deliverables.
74 74
75- Scheduled report generation (markdown/json/pdf) for tracked domains. 75- **Markdown and PDF export formats** — `DomainExportFormat` gains `.markdown`
76- Stronger share affordances for reports and audit evidence. 76 and `.pdf` alongside text/csv/json. Markdown reuses the existing text-export
77- Export polish and consistency across app and local API output. 77 content via a line-based transform (never drifts from the text export); PDF
78 renders that Markdown via `UIGraphicsPDFRenderer`, mirroring the approach
79 `AuditExporter` already used for audit sessions.
80- **Scheduled report generation** — `ScheduledReportService` /
81 `ScheduledReportScheduler` (Settings → Scheduled Reports): a BGTaskScheduler-
82 driven daily/weekly job that builds a markdown/PDF/JSON report bundle for all
83 tracked domains, writes it locally, logs the run, and notifies when ready.
84 Mirrors `DomainMonitoringService`'s headless, storage-backed design; gated
85 behind the same Pro `.automatedMonitoring` capability.
86- **Stronger share affordances** — "Export Markdown"/"Export PDF" added to the
87 single-result, batch, watchlist, and workflow export menus; generated
88 scheduled reports are individually shareable from their log.
89- **Export consistency verified** — the local API already serves the canonical
90 `DomainReport` directly (no field allowlist), so `reputation`, `domainPricing`,
91 and every other field added since v4.7.0 already flow through automatically.
92 No code change was needed there.
93
94Deferred/scoped out: scheduled-report settings and logs are UserDefaults-only
95(not part of `DomainDataPortabilityService` backup/restore), same reasoning as
96v4.7.0's watchlist saved views — this is local automation config, not
97user-authored content.
78 98
79## v5.0.0 Major: Contract Stabilization & Engineering Health 99## v5.0.0 Major: Contract Stabilization & Engineering Health
80 100