| Commit message (Collapse) | Author | Age | Files | Lines |
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Reported on device: the Domain section header's Note button rendered
vertically — "N o t e", one character per line in a screen-tall capsule —
at a larger (not even accessibility-tier) text size. Same pathology the
row badges had: text inside a squeezed HStack compresses to a
one-character column instead of the layout adapting.
Three-part fix, mirroring the proven row treatment:
- CollapsibleSectionView's header is now a ViewThatFits: title, trailing
controls, and chevron on one line while they genuinely fit; otherwise
the trailing controls drop below the title row. Applies to every
section header, not just Domain.
- The Note and Track bordered buttons get .fixedSize() so their text can
never letter-wrap — their natural width is what pushes the header onto
its stacked layout.
- The "Tracked" pill becomes an icon-only indicator (eye in a tinted
circle) — with Pin and Note beside it the full pill was the first thing
to compress, and the word survives for VoiceOver via its label.
Enforced audit suite stays green (7 tests, 0 failures, floor runtime).
The post-lookup header state itself is not reachable by the harness — it
requires a live lookup — so on-device confirmation closes this out.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Audit unchanged at 11 dark / 14 light — expected, as none of these
settings are exercised by performAccessibilityAudit, and simctl can
toggle only Increase Contrast, not Differentiate Without Color, Reduce
Motion, or Reduce Transparency. Correct by construction and build-clean;
runtime behaviour is verified in the Phase 6 manual pass.
Color independence:
- Widget status is now an SF Symbol (checkmark.circle.fill /
exclamationmark.triangle.fill / exclamationmark.octagon.fill), the same
vocabulary as the in-app badges, replacing a silent colour-only dot on
both the domain rows and the small-view count pills. Status now survives
greyscale and reads consistently across surfaces.
- Under accessibilityDifferentiateWithoutColor: the Dashboard
summary-card dot becomes a per-filter symbol, the selected quick-filter
chip gains a checkmark and a border (selection was fill-colour only, and
also gains the .isSelected trait), and LabeledValueRow prefixes a
warning/failure symbol. All gated on the setting so the default UI stays
uncluttered.
Reduce motion: all five withAnimation/.animation sites now pass nil under
accessibilityReduceMotion — AppCopyButton's check cross-fade,
CollapsibleSectionView's expand/collapse, TimelineDiffView's scroll, and
WatchlistView's list reorder.
Reduce transparency: the single .thinMaterial capsule falls back to an
opaque AppSurfaceElevated fill under accessibilityReduceTransparency.
The SweepActivityController item from the plan is dropped: it is pure
ActivityKit lifecycle with no animation, confirmed back in the issue
triage.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
phase 4)
The audit count is unchanged at 11 dark, and that is the expected
result: performAccessibilityAudit validates descriptions, traits,
contrast, hit regions, and clipping, but exercises none of VoiceOver's
speech, the More Content rotor, custom-content ordering, or
announcements — which is the entire substance of this phase. It is
verified by construction and stays green with no regressions; the
manual VoiceOver pass is Phase 6.
Icon-only controls (~14) get accessibilityLabel, obeying label-in-name:
where a control has visible text the label keeps it, so Voice Control
still works. The pin and bookmark toggles gain accessibilityValue and
.isSelected; the audit and workflow checkboxes gain .isSelected and a
hint. Decorative icons split out of Labels are hidden.
AppStatusBadgeView now reads as one word ("Critical"), not "icon,
Critical", via children: .ignore + label. SectionTitleView and
CollapsibleSectionView headers get the .isHeader trait for rotor
navigation; the collapsible header also exposes expanded/collapsed as a
value with a hint. The header deliberately does NOT use children:
.combine — its trailing() closure can hold Track/Pin controls, and
combining would swallow them.
Dense rows use combine-for-summary, custom-content-for-detail.
BatchResultRowView (8 elements) and WatchlistRowView (up to 9) become a
single element — domain as label, status as value — with risk, IP,
timestamp, source, certificate, and monitoring on the More Content
rotor, risk and certificate at .high importance. Reading all of it
inline would make a long sweep unnavigable. The custom-content chains
live in ViewModifiers because inlining six of them plus the layout broke
the type-checker. The shorter 3-4 element portfolio rows are left to
NavigationLink's automatic combine, per WWDC21-10121.
Technical strings get a speechStyle field on InfoRowViewData:
.technical applies speechAlwaysIncludesPunctuation and
accessibilityTextContentType(.sourceCode), set on DNS record values and
cipher suites so load-bearing punctuation is not swallowed.
Completion announcements: the sweep posts from the view model; the
single lookup posts from an onChange in the view, since resultsLoaded is
derived from many loading flags and has no single view-model moment.
Widget: each domain row was a silent 8pt status dot plus a bare "12d"
countdown. Rows now read as one phrase ("example.com, critical,
certificate expires in 12 days"); the count pills are labelled.
Not verifiable by the suite: the dense rows and the widget never render
in the audit (no tracked domains or batch results in the test
simulator), same limit as the deferred Phase 3 row reflow. Documented in
Docs/ACCESSIBILITY.md.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Takes the audit from 18 findings to 11 in dark mode. Everything that
remains is system-rendered or placeholder noise, characterised below.
The largest win was not where the plan expected. Every empty-state
heading reported as clipped text, and the cause was `Label`: it
constrains its own title, and `.fixedSize` applied to the Label does not
reach the `Text` inside. Splitting into `HStack { Image; Text }` and
putting the modifier on the Text cleared all four empty states at both
default and accessibility sizes.
That fix then caused a regression the audit caught immediately. `Label`
folds its image into the title's accessibility element; an HStack does
not, so the icon began announcing its raw SF Symbol name
("checklist.unchecked") to VoiceOver. Decorative icons split out of a
Label now carry .accessibilityHidden(true).
Tap targets:
- AppCopyButton was a literal 30x30 on nearly every data row. Now
@ScaledMetric from 44, floored at AppLayout.minimumTapTarget —
@ScaledMetric scales down below the default text size as well as up,
so the floor is load-bearing.
- controlMinHeight was 42 in compact density, putting every collapsible
section header and both Run buttons under the minimum.
Reflow:
- CardView's allowsHorizontalScroll defaulted to true, so nine call sites
hid content behind a horizontal gesture instead of wrapping — a WCAG
1.4.10 failure and the mechanism behind clipped rows at large text
sizes. The default is now false, and the remaining opt-in is suppressed
at accessibility sizes.
- Fixed .system(size:) point sizes replaced with text styles in the app
and the widget.
- The widget is clamped at accessibility1, the one place clamping is
correct: a widget canvas is a fixed size and WidgetKit truncates
overflow with no scroll affordance.
Two hypotheses were tested and discarded rather than left in. Monospaced
fonts looked like the clipping culprit — the app is 82% monospaced and
hyphenates mid-word at accessibility sizes — but switching the empty
state to proportional changed nothing, and prose typography is a design
decision rather than an accessibility fix. Shortening search prompts and
the domain placeholder also changed nothing: placeholder text is reported
clipped regardless of length, so "Search" is flagged exactly as "Search
portfolio" was.
Not done: ViewThatFits reflow for BatchResultRowView and
WatchlistRowView. Those rows never render in the audit because the test
simulator has no tracked domains or batch results, so any change there
would be unverifiable. Absence of findings is absence of data.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The selected Dashboard summary card rendered lavender, not blue. Its
background was a gradient of statusInfo at 28% and 12% opacity — a
dark-mode trick where a translucent accent over near-black reads as a
dim version of itself. Over a light background the same wash desaturates
toward violet.
Swapped for the authored StatusInfoSurface, which is a real colour with
a real contrast measurement rather than an emergent one. Same treatment
for the selected tag-filter chip (statusInfo at 30%) and an
intelligence-section badge (statusWarning at 14%).
The remaining opacity use, a 0.55 stroke in ContentView, is a border
rather than a text background and is left alone.
Verified across appearance and contrast settings on iOS 18.6: light 21
findings, light + Increase Contrast 18, dark 18, dark + Increase Contrast
18. Increase Contrast lowering the light count is the High Contrast
colorset variants working as intended on the system section headers.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Reported as "colors seem muted and hard to see on light mode", and
correct. The light palette optimised contrast and produced mud: #7A5600
reads olive rather than amber, #146C2E bottle-dark rather than green.
Contrast passed while the UI got harder to read, because hue identity is
what distinguishes warning from critical at a glance.
Two causes, both fixed.
Every foreground was required to clear 4.5:1 against its own 16% badge
tint — the harshest surface it ever sits on — which pushed each colour
about 20% darker than the common case needed. Most of what is actually on
screen is plain text on a card, with far more headroom. The fill is now
decoupled from the foreground: AppStatusTone carries a foreground and a
surface authored independently, with matching …Surface colorsets, so a
foreground no longer has to survive a wash of itself. Every status
foreground is now fully saturated.
And warning was yellow. Yellow cannot stay yellow at a lightness low
enough to pass 4.5:1 on white — it becomes olive. That is colorimetric,
not a tuning problem. Warning is now orange: #AD5100 light, #FF9F0A dark.
New light values: positive #008035, warning #AD5100, critical #CC0700.
Worst-case ratios 4.54–6.76 across page, card, and surface in both
schemes. Audit findings are unchanged — light 21, dark 18 — so the
vividness costs nothing.
Also picks up a literal .blue missed in phase 1: DomainDiffItem's
low-severity change colour, which the phase 1 sweep did not cover because
its pattern listed only cyan/yellow/green/red/orange/pink.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Removes the 16 scattered .preferredColorScheme(.dark) calls and the one
.toolbarColorScheme, and applies appearance in exactly one place — the
WindowGroup in DomainDigApp. Re-applying per view is what let the lock
spread across eight files unnoticed until light mode was unreachable.
Adds AppAppearance (System / Light / Dark) in @AppStorage, exposed under
Settings > Display next to Density. Honouring the system setting and
offering an override is one key, and it keeps the deliberate dark
aesthetic reachable for anyone who wants it.
Also replaces .secondary with AppTextSecondary across 191 sites. iOS's
own secondaryLabel is 3.29:1 on a light card — below AA — which never
showed while the app was locked to dark, where the same colour reads
6.32:1. Unlocking light mode is precisely what exposed it, so it belongs
here rather than in a later phase: without it, light mode would ship with
body text under 4.5:1 app-wide.
Dark mode reports 18 findings, unchanged from phase 1 — no regression
from unlocking. Light mode reports 21. The three extra are iOS-rendered
Section headers (TIER, PREFERENCES, SERVICES) using the system's grey;
overriding system header styling across every section to gain ~0.3:1 on
decorative labels is a poor trade and is left alone.
Two long-standing Settings contrast findings are now explained. They are
the last rows of a section sitting under the translucent tab bar, so the
audit measures text against a blended background — confirmed by
screenshot, present in dark mode since phase 0, and standard iOS
scroll-under behaviour rather than a defect.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Replaces every hard-coded colour with semantic asset colours that adapt to
light, dark, and Increase Contrast. Dark mode stays locked, so this is a
pure refactor: the audit reports the same findings before and after.
The accent is now blue rather than cyan, per the tech/DNS theme.
Why custom values rather than the system palette: every system colour
fails WCAG AA in light mode. Measured on white — systemYellow 1.51:1,
systemOrange 2.20:1, systemGreen 2.22:1, systemCyan 2.54:1, systemRed
3.55:1. All of them pass in dark mode, which is why the dark-locked app
looked fine, and why unlocking light mode was never a matter of deleting
.preferredColorScheme(.dark). Every new value clears 4.5:1 as text on its
page, its card, and its own 16% badge tint — the way AppStatusBadgeView
actually draws it.
The accent needed splitting in two. As text on a dark background it must
be light; as a fill behind a white label it must be dark. #4DA3FF reads
8.00:1 as text on black but 2.63:1 behind white text, so StatusInfo /
AccentColor cover the foreground role and AccentFill covers
.borderedProminent. AppOnAccent is the label colour for a solid fill and
flips by scheme.
Colours live in Shared/Colors.xcassets rather than the app catalog: the
Shared folder is already a synchronized group in all three targets, so
the widget and share extension pick the palette up with no project-file
surgery. AccentColor stays in the app catalog as the global tint — and is
now actually defined, having been an empty colorset that silently left
system controls rendering in stock blue while custom chrome used cyan.
Two deliberate visual changes: orange folds into StatusWarning and pink
into StatusCritical. They encoded the same severity as the colours they
now share, and both sites also carry a text label.
Audit findings drop 15 to 14, and one of the originals turned out to be
a phantom: the Inspect contrast failure was the Run button in its
disabled state, which WCAG 1.4.3 exempts. testInspectScreen now types a
domain first so the audit measures an enabled control. Findings also
carry the offending element now, so the remaining clipped-text items name
themselves ("No Portfolio Yet", "Search domains") instead of being
anonymous.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Fixes the 4 reported bugs and ~97 code smells flagged in the new-code
period. No behavior changes.
Bugs (swift:S3923) — DomainInspectionService's confidenceFor* helpers each
returned `error == nil ? .low : .low`, an inert conditional. Simplified to
`return .low` and dropped the now-unused `error` parameter.
Smells:
- Merged 14 identical `.empty`/`.error` switch branches in DomainViewModel
- Consolidated duplicate implementations (clearPresentedResults/reset,
String.nonEmpty/nilIfEmpty, ExportFormat.id/fileExtension)
- Extracted nested ternaries into TLSGrade.tone, EmailSecurityGrade.tone,
and ChangeImpactClassification.color; removed ContentView.impactColor
and the duplicate mapping in BatchResultsView
- Documented empty closures and singleton inits
- Marked unused protocol-conformance parameters `_`
- Renamed CloudSyncTrigger.`import` to `imported` (raw value preserved)
and SSLSessionDelegate's _serverTrust/_tlsMetadata
- Merged nested ifs in the DER parser; flattened closure nesting in
PortScanService and IntegrationService
- Replaced two-case switches with if/else
Left open: S107 (init parameter counts), S115 (constants mirroring DoH and
ipapi JSON keys), S1075 (false positives on https:// literals), and two
S117 hits on SwiftUI $binding shorthand. These want a Won't Fix resolution
in SonarCloud, not a code change.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Scheduled Reports: the entire Overview section was wrapped in a single
VStack inside one List row, so SwiftUI collapsed every control into one
tap target and the menu-style Cadence Picker captured taps intended for
the Generate Now button. Unwraps the VStack so each control is its own
row, matching the pattern used in IntegrationsView and elsewhere.
Also extends the .automatedMonitoring gate to the two Pickers and the
Generate Now button. Previously only the Toggle was disabled, leaving a
button that appeared active on Free but silently no-opped against the
guard in ScheduledReportService.
Inspect tab: removes the keyboard toolbar's Dismiss Keyboard button and
the onAppear that focused the single-domain field at launch.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
- ScheduledReportService (@MainActor, headless/storage-backed like
DomainMonitoringService): builds the latest report for every tracked domain
from persisted history, exports it via DomainReportExporter in the
configured format (markdown/PDF/JSON), writes it to a local Documents
subdirectory, logs the run, and fires a "Scheduled Report Ready" local
notification.
- ScheduledReportScheduler mirrors DomainMonitoringScheduler's BGTaskScheduler
approach with its own task identifier (net.cleberg.DomainDig.report.schedule,
added to Info.plist) and a daily/weekly cadence.
- ScheduledReportsView (Settings → Scheduled Reports): enable toggle, cadence
and format pickers, "Generate Now", and a log of past reports each shareable
via the existing ExportPresenter share sheet.
- Gated behind the existing .automatedMonitoring capability (Pro), consistent
with monitoring being the other background-automation feature.
- Settings/logs persist via UserDefaults (DomainExportFormat is now Codable),
not DomainDataPortabilityService backup/restore — this is local automation
configuration, not user-authored content, same reasoning as v4.7.0's
watchlist saved views.
|
| |
|
|
|
|
|
|
|
| |
Adds "Export Markdown"/"Export PDF" (and batch/workflow equivalents) to the
single-result, batch, watchlist, and workflow export menus, gated behind
.advancedExports like the existing CSV/JSON options. Matches the existing
menu structure and Pro-gate wording per file rather than introducing a new
shared component, consistent with how CSV/JSON were already duplicated across
these five menus before this change.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
- DomainExportFormat gains .markdown and .pdf (CaseIterable, Identifiable,
titled), alongside the existing text/csv/json.
- Markdown reuses the existing text-export content verbatim via a line-based
transform (section "Title\n----" underlines become "## Title", the leading
title becomes an H1, other lines become bullets), so the two formats can
never drift apart.
- PDF renders that Markdown as a simple monospaced multi-page document via
UIGraphicsPDFRenderer (mirrors AuditExporter's existing PDF approach;
degrades to raw Markdown bytes on non-UIKit platforms).
- Replaced the single/batch/tracked-domains/workflow share call sites' hand-
written per-format switches with format-agnostic functions
(exportSingleReportData, exportBatchReportData, exportTrackedDomainsData,
exportWorkflowData) that delegate straight to DomainReportExporter, removing
the now-orphaned per-format helper functions those switches used to call.
|
| |
|
|
|
|
|
|
|
|
|
| |
- Make DomainDig/DomainDig/Audit* the single active Audit Mode implementation
(models, views, exporter) with an Audit tab and session/export UI
- Include audit sessions in backup/restore lifecycle counts, summaries, and
merge behavior via DomainDataPortabilityService
- Remove the DomainDigCLI target, source file, scheme, and all project
references; keep the shared inspection/report pipeline for the app
- Align AppVersion.current to 4.4.1 and refresh README/architecture docs
- Add RELEASE_ROADMAP.md
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
historical context
and inferred enrichment.
- add derived intelligence fields for provider fingerprinting, classification,
ownership transitions, hosting transitions, subdomain history, risk signals,
and inferred timeline events
- expand DNS history beyond A/NS snapshots to retain A, AAAA, MX, NS, TXT, and
CNAME change state
- persist enriched intelligence in snapshots and history entries so analysis is
local-first and incremental
- add a dedicated Data+ Intelligence panel to current and historical domain
detail views
- surface intelligence events in timeline rows and include Data+ changes in diff
output
- preserve non-blocking inspection behavior by keeping enrichment additive to
the main lookup path
This makes Pro+ materially deeper for investigative workflows by improving
historical ownership visibility, infrastructure context, hosting change
detection, subdomain intelligence, and explainable risk signals.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Expose DomainDig as a programmable local domain intelligence engine over
localhost with explicit user opt-in and token-based authentication.
Highlights:
- add a localhost-only API server with safe start/stop lifecycle
- require a local token for every request and store it in Keychain
- add read endpoints for portfolio, domains, history, events, and monitoring
- add inspection endpoints that reuse the existing inspection engine
- add monitoring enable/disable control endpoints
- add structured JSON response envelopes with API versioning
- add lightweight capped request logging with clear/reset support
- add a Settings UI for Local API enablement, token management, status, and logs
- start the server on launch only when enabled
- include Local API secrets in local data reset cleanup
This is the first programmability release for DomainDig and establishes the
foundation for Shortcuts, scripts, and other local automation workflows.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
- add a destructive Delete All Data action with confirmation, progress, success,
and failure handling
- centralize wipe behavior in DataResetService instead of scattering delete
logic in views
- clear local persistence, temp/export files, integration secrets,
notifications, caches, and in-memory app state
- reset sync, purchase, and integration services after wipe so the app returns
to a clean first-launch state
Polish batch and empty-state UX
- present the batch sweep summary after manual bulk searches complete, not only
from Watchlist
- align the Workflows empty state styling with other empty states by removing
the extra background card treatment
Bump the project version from 4.0.0 to 4.1.0
|
| |
|
|
|
|
|
|
|
|
|
|
| |
* Outbound webhook delivery
* Native Slack webhook integration
* SMTP-based email alerts
* Per-integration event filtering
* Reliable local delivery queue
* Delivery logs and retry visibility
* Integration management UI
* Normalized event severity model
* Canonical structured event payloads
|
| |
|
|
|
|
|
|
|
|
|
| |
* Portfolio summary cards
* Recent activity feed across tracked domains
* Attention-required queue prioritized by severity
* Certificate expiry visibility and expiring-soon section
* Quick portfolio filters for triage
* Deterministic per-domain health scoring
* Local portfolio search
* Apex-domain grouping for tracked assets
|
| |
|
|
|
|
|
|
|
| |
* Stable domain intervals
* Frequent changes decrease intervals
* Duplicate states do not trigger alerts
* Quiet hours suppress alerts
* Quiet hours across midnight work correctly
* Sensitivity levels alter behavior as expected
|
| |
|
|
|
|
|
|
|
|
| |
- introduce TimelineView for historical snapshots
- allow comparison between any two snapshots
- implement DiffService for structured domain diffs
- improve diff visualization with clear change indicators
- add navigation across changes
- optimize history loading for performance
- extend CLI and export to support timeline data
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
- implement CloudKit sharing (CKShare) for TrackedDomain and DomainWorkflow
- support read-only and editable permissions
- add Share actions and shared state indicators in UI
- handle shared record ownership and participant roles
- implement deterministic conflict resolution to prevent duplication
- ensure compatibility with existing iCloud sync layer
- maintain local-first behavior with graceful offline handling
- remove debug logging for domain availability/rdap messages
notes:
- no custom backend or accounts introduced
- sharing is Apple ecosystem only (iCloud-based)
- large history data remains local-only
|
| |
|
|
|
|
|
|
|
|
|
| |
• introduce versioned DomainDig backup format
• add full backup export/import with merge and replace modes
• implement data validation and conflict handling
• add partial exports for tracked domains, workflows, and history
• add Data Portability settings section
• support Files/iCloud Drive import and export
• harden migrations for evolving local models
• extend CLI with backup export and validation
|
| |
|
|
|
|
|
|
|
|
| |
- introduce Data+ tier for advanced data features
- add ownership history and DNS history
- expand subdomain discovery with external sources
- add domain pricing insights
- implement local usage/credit system
- integrate external data service layer with rate limiting
- extend export and CLI for Data+ features
|
| |
|
|
|
|
|
|
|
| |
• implement PurchaseService using StoreKit 2
• activate feature tiers based on entitlement
• add minimal paywall and restore flow
• enforce free-tier limits with upgrade paths
• integrate Pro status into settings
• ensure clean and non-intrusive monetization flow
|
| |
|
|
|
|
|
|
|
|
|
| |
* consolidate DomainReport as canonical data model
* add feature tier system (free/pro/data+ scaffolding)
* apply clean feature gating across workflows and tracking
* refactor app structure for maintainability
* standardize navigation and settings
* add data lifecycle controls
* ensure consistency across UI, export, and CLI
* stabilize internal inspection API
|
| |
|
|
|
|
|
|
|
| |
* introduce domain risk assessment with transparent factors
* add insight engine for actionable observations
* implement cross-domain insights for workflows
* improve DNS, subdomain, email, and TLS interpretation
* classify change impact severity
* include insights and risk in export
|
| |
|
|
|
|
|
|
|
|
| |
* introduce DomainWorkflow model and persistence
* add WorkflowsView and execution flow
* support batch inspection via workflows
* add workflow-based export (TXT/CSV/JSON)
* enable bulk add from history/watchlist
* add quick actions for common operations
* integrate workflows with tracking and history
|
| |
|
|
|
|
|
|
|
|
| |
* add result provenance across major sections
* introduce confidence levels for ambiguous outputs
* distinguish observed facts from inferred summaries
* expand snapshot metadata for reproducibility
* improve error classification and partial snapshot handling
* include provenance and confidence in export
* add local notes for tracked domains and history
|
| |
|
|
|
|
|
|
|
| |
• add compact/comfortable density modes
• implement collapsible sections and sticky summary header
• improve visual status indicators and copy actions
• refine watchlist and history UX with swipe actions
• reorganize settings and improve empty states
• add subtle animations and accessibility improvements
|
| | |
|
| |
|
|
|
|
|
|
|
| |
* introduce DomainReport as canonical output model
* add JSON export for single and batch results
* create DomainReportBuilder for reusable report construction
* add CLI target using shared inspection pipeline
* refactor services for UI-independent usage
* ensure consistency across TXT, CSV, and JSON outputs
|
| |
|
|
|
|
|
|
|
| |
* implement RDAP-based ownership section
* add ownership diffing and change classification
* add passive subdomain discovery via certificate transparency
* highlight interesting subdomains
* introduce Data+ scaffolding for future features
* include ownership and subdomains in export and history
|
| |
|
|
|
|
|
|
|
|
|
| |
- implement “Check All” sweep for tracked domains
- add local notifications for changes and certificate expiration
- introduce change severity filtering (low/medium/high)
- enhance change summaries and diff readability
- add certificate expiration tracking and alerts
- improve watchlist indicators for changes
- add sweep summary screen
- optimize performance for larger watchlists
|
| | |
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
- replace basic watchlist with structured TrackedDomain model
- add manual refresh flow for tracked domains
- implement snapshot diffing (DNS, IP, TLS, HTTP, redirect, email, availability)
- add change summaries (changed/unchanged + affected sections)
- link tracked domains to history snapshots
- enhance HistoryEntry with normalized summary fields
- persist availability + suggestions in history and export
- add WatchlistView with pinning, notes, and status display
- introduce premium capability scaffolding (no StoreKit)
- enforce free-tier tracked domain limit (local only)
- refactor view model to support tracking, diffing, and refresh flows
notes:
- no background monitoring, notifications, or paid APIs yet
- all features remain local-first and manual
|
| |
|
|
|
|
|
|
|
| |
- implement availability detection (available/registered/unknown)
- integrate availability into domain results
- add lightweight domain suggestions
- introduce local watchlist with persistence
- add WatchlistView and toolbar access
- include availability in export
|
| |
|
|
|
|
|
|
| |
- normalize sections and add summary card
- fix resolver usage in reverse DNS
- include custom port scans in history/export
- standardize error handling
- decompose ContentView into smaller views
|
| | |
|
| | |
|
| | |
|
| |
|
|
|
|
|
| |
Add richer SSL/TLS inspection details including negotiated TLS version,
cipher suite, full certificate chain display, crt.sh lookup, and HSTS
preload status. Persist HSTS preload in history/export and run the
preload check in parallel with the SSL lookup.
|
| |
|
|
|
|
|
|
|
| |
- Add SOA, SRV, CAA, and DS DNS record lookups
- Add DNSSEC status detection via RRSIG queries
- Add configurable DNS-over-HTTPS resolver settings
- Support Cloudflare, Google, Quad9, and custom HTTPS resolvers
- Improve DoH compatibility with standards-based fallback handling
- Keep DNS results UI compact with a single DNSSEC indicator
|
| |
|
|
|
|
| |
- fix Email section to left align
- ensure container contents can overflow scroll but page cannot
- fix map width
|
| | |
|
| |
|