Commit 54c151e22f

54c151e22f8a5d4d7a9c290e79fc7626415f7083

parent: fbf2d9bf2c

Unsigned

cmc <hello@cleberg.net> · 2026-07-17 15:47 UTC

v4.7.0: Bump version and mark shipped in roadmap

Bump AppVersion/marketing version to 4.7.0 and build number to 39 across the
app, widget, and share extension targets. Mark v4.7.0 (comparison, reputation,
tags/saved views) shipped in RELEASE_ROADMAP.md and escalate the overdue
XCTest-target gap ahead of v5.0.0.

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 = 38; 498 CURRENT_PROJECT_VERSION = 39;
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.6.0; 515 MARKETING_VERSION = 4.7.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 = 38; 535 CURRENT_PROJECT_VERSION = 39;
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.6.0; 552 MARKETING_VERSION = 4.7.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 = 38; 571 CURRENT_PROJECT_VERSION = 39;
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.6.0; 582 MARKETING_VERSION = 4.7.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 = 38; 600 CURRENT_PROJECT_VERSION = 39;
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.6.0; 611 MARKETING_VERSION = 4.7.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 = 38; 629 CURRENT_PROJECT_VERSION = 39;
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.6.0; 640 MARKETING_VERSION = 4.7.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 = 38; 658 CURRENT_PROJECT_VERSION = 39;
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.6.0; 669 MARKETING_VERSION = 4.7.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.6.0" 5 "4.7.0"
6 } 6 }
7} 7}
RELEASE_ROADMAP.md +21 −10
@@ -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.6.0`. 9Current version: `v4.7.0`.
10 10
11## v4.4.1 Patch: Release Readiness — ✅ shipped 11## v4.4.1 Patch: Release Readiness — ✅ shipped
12 12
@@ -50,15 +50,23 @@ Goal: make monitoring and results feel first-class across contexts.
50Deferred: monitoring-alert Live Activities (only the sweep activity shipped) and 50Deferred: monitoring-alert Live Activities (only the sweep activity shipped) and
51Lock Screen accessory widget families (carried over from v4.5.0). 51Lock Screen accessory widget families (carried over from v4.5.0).
52 52
53## v4.7.0 Minor: Intelligence & Comparison 53## v4.7.0 Minor: Intelligence & Comparison — ✅ shipped
54 54
55Goal: help users interpret and organize, not just collect. 55Goal: help users interpret and organize, not just collect.
56 56
57- **Domain-vs-domain comparison** (side-by-side), extending the existing 57- **Domain-vs-domain comparison** — `DiffService.compare(domainA:domainB:)`
58 time-based `DiffService` to compare two distinct domains. 58 reuses the existing section-diff builders; `DomainCompareView` (Watchlist
59- **Reputation / blocklist signals** as a new optional data source (currently 59 toolbar → "Compare Domains") picks two tracked domains and renders the result
60 absent); surfaced in the report and available to monitoring alerts. 60 with the existing diff section UI.
61- **Tags / folders and saved views** for the watchlist to organize large sets. 61- **Reputation / blocklist signals** — a new pluggable data source
62 (`ExternalDataService.reputation(domain:)`, Pro+) mirroring the existing
63 ownership/DNS-history/pricing enrichment pattern. Ships with no bundled
64 third-party endpoint; folds a listed status into risk score/factors and
65 insights, so it rides the existing report and monitoring change-severity
66 pipeline rather than needing bespoke monitoring wiring.
67- **Tags and saved views** for the watchlist — freeform tags per tracked
68 domain, tag filter chips, and named saved filter/sort/tag presets
69 (UserDefaults-backed; not yet part of backup/restore).
62 70
63## v4.8.0 Minor: Reporting & Sharing 71## v4.8.0 Minor: Reporting & Sharing
64 72
@@ -88,6 +96,9 @@ feature releases above will accumulate.
88## Cross-cutting note 96## Cross-cutting note
89 97
90New feature surfaces (widgets, intents, extensions) each add a target and a 98New feature surfaces (widgets, intents, extensions) each add a target and a
91persistence/entitlement seam. Add at least characterization tests for 99persistence/entitlement seam. This project still has **no XCTest target** —
92`DomainDataPortabilityService` and the report builders **before** v4.7.0, so the 100v4.5.0 through v4.7.0 all shipped without the characterization-test safety net
93v5.0.0 contract and refactor work has a safety net rather than starting from zero. 101originally recommended before v4.7.0. That gap is now larger (comparison,
102reputation, and tags/saved-views all touch persisted models with hand-written
103backward-compatible decoders) and should be the very first thing v5.0.0 does,
104not a later item within it.