Repository navigation
fix(a11y): audit findings before 1.0, plus Xcode Cloud release plumbing - #46
Merged
Merged
Conversation
An accessibility audit (Apple's XCUIApplication.performAccessibilityAudit
over Home, Goals, a goal, Money, Me and Log expense) plus a Simulator pass
at AX5 turned up six real problems. Each one is a claim App Store Connect's
Accessibility Nutrition Label would otherwise make falsely.
- Hidden system tab bar exposed to VoiceOver: `.toolbar(.hidden, for:
.tabBar)` on the TabView hides the bar but leaves four unlabelled buttons
in the accessibility tree ("Element has no description" x4). Applied per
child instead, they are gone.
- Category chip labels under 4.5:1: `tileColor` is a glyph color (3:1 on
its tint). New `warmClayDeep` / `warmSkyDeep` / `warmLilacDeep` at 5:1
and `ExpenseCategory.tileTextColor` for text on the tint; both quick-add
and receipt-review chips use it. Amber already had `warmAmberDeep`.
- Goal detail stat pills at AX sizes: "$1,480" wrapped into "$1,48 / 0" in
a third of the width. VStack at accessibility sizes via AnyLayout.
- Goal card name at AX sizes: "Trip to Oaxaca" truncated to "Trip t...".
Two-line name and the percent/favorite row drops below the identity when
the type is an accessibility size.
- Me tab: hero card labels were white at 0.7/0.75 alpha (4.0:1 light,
3.4:1 dark); full white now. Stat strip stacks at AX sizes and labels
wrap instead of shrinking; "See all" hit areas were 41x16 and 50x16 pt.
- Home greeting read to VoiceOver as the bare "Afternoon."; it is now one
heading: "Good afternoon. Tuesday, August 18".
Also: the inline add fields on Money grow with Dynamic Type instead of a
fixed 40pt.
SavelyUITests/AccessibilityAuditUITests.swift runs the audit on demand and
documents the findings that were accepted and why, and what the audit
cannot prove (VoiceOver itself).
Verified: build, 102 unit tests, the audit, and the screenshot tour at
AX5 (goal detail, goals list, log expense) on iPhone 17 Pro Max.
App Store Connect refused build 1: this Mac only has Xcode-beta, and Apple does not accept archives from a beta Xcode. Xcode Cloud archives with a released Xcode, so, as Fave did, Savely ships from there. ci_scripts/ci_post_clone.sh materialises the gitignored Savely/Config.plist (a required Resources build input) from the OPENAI_API_KEY workflow secret when present, or a placeholder when not, with the same printenv discipline as Fave: the value never binds to a variable or reaches xtrace. Because FeatureFlags.tipsEnabled is false the placeholder is what 1.0 should ship; the only refusal is archive + flag on + no key. Dry-run against a scratch clone with a canary key containing "&<>" under bash -x: zero hits in the trace, one XML-escaped hit in the plist, plutil OK, and the gate exits 1. Info.plist gains ITSAppUsesNonExemptEncryption = false: the app has no cryptography of its own and its one network call is HTTPS via URLSession. docs/xcode-cloud.md carries only what differs from Fave and the workflow settings (released Xcode, Archive - iOS, manual start, ASC build counter set to 2 because build 1 is taken).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
XCUIApplication.performAccessibilityAuditand a Simulator pass at AX5, each one a claim the App Store accessibility label would otherwise make falsely: hidden system tab bar exposed as four unlabelled buttons, category chip text under 4.5:1 (clay 3.59, sky 3.61, amber 3.45), goal stat pills wrapping "$1,480" into "$1,48 / 0", goal card name truncating to "Trip t…", Me hero labels at 0.7 alpha (3.4:1 in dark), "See all" hit areas at 41x16 pt, and the Home greeting read as the bare "Afternoon."warmClayDeep/warmSkyDeep/warmLilacDeep(5:1 on their tints) andExpenseCategory.tileTextColor; AnyLayout stacks at accessibility sizes in the goal detail, goal card and Me stat strip.SavelyUITests/AccessibilityAuditUITests.swiftruns the audit on demand and documents which findings were accepted and why, and what it cannot prove.ci_scripts/ci_post_clone.sh+docs/xcode-cloud.md: Savely ships from Xcode Cloud (this Mac only has Xcode-beta and ASC rejected build 1). The script writes the gitignoredSavely/Config.plistwith the same printenv discipline as Fave and refuses only archive +tipsEnabled+ no key.Info.plist:ITSAppUsesNonExemptEncryption = false(HTTPS via URLSession only).Why
Build 1 was rejected for the beta Xcode, so a build 2 is needed anyway. Fixing these first means build 2 can carry VoiceOver, Larger Text and Sufficient Contrast in the accessibility label instead of the three that were safe to claim today (Dark Interface, Differentiate Without Color, Reduced Motion).
Test plan
xcodebuild build -scheme Savely -destination 'platform=iOS Simulator,name=iPhone 17 Pro Max'xcodebuild test -scheme Savely -skip-testing:SavelyUITests ...(102 tests, 0 failures)xcodebuild test -only-testing:SavelyUITests/AccessibilityAuditUITests— remaining findings are the four tab captions (tab bar exemption), rows scrolled under the tab bar, the disabled Save button, and one "Text clipped" on the Money text field that is not understood and not claimedcontent_size accessibility-extra-extra-extra-large: goal detail, goals list, log expense, privacy, month trendci_post_clone.shdry-run on a scratch clone: canary key with&<>underbash -x, zero hits in trace, escaped in plist,plutil -lintOK, gate exits 1Risks
WarmGoalCardheader is restructured intoidentity/percent/favoriteButton; visual parity at default sizes checked in the tour, worth one glance in Xcode previews.ci_scripts/runs on GitHub Actions; it only runs on Xcode Cloud.Checklist
docs/xcode-cloud.mdadded;CLAUDE.mdunchanged