<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: 이대겸</title>
    <description>The latest articles on DEV Community by 이대겸 (@_9bf2089fc277e31aa5979).</description>
    <link>https://dev.to/_9bf2089fc277e31aa5979</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4224586%2F6fda6363-7d80-4f92-97a7-83f16ff9f7b3.png</url>
      <title>DEV Community: 이대겸</title>
      <link>https://dev.to/_9bf2089fc277e31aa5979</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/_9bf2089fc277e31aa5979"/>
    <language>en</language>
    <item>
      <title>How to Catch PrivacyInfo.xcprivacy and Required-Reason API Gaps Before App Store Submission</title>
      <dc:creator>이대겸</dc:creator>
      <pubDate>Tue, 03 Nov 2026 15:42:57 +0000</pubDate>
      <link>https://dev.to/_9bf2089fc277e31aa5979/how-to-catch-privacyinfoxcprivacy-and-required-reason-api-gaps-before-app-store-submission-1opc</link>
      <guid>https://dev.to/_9bf2089fc277e31aa5979/how-to-catch-privacyinfoxcprivacy-and-required-reason-api-gaps-before-app-store-submission-1opc</guid>
      <description>&lt;p&gt;Apple's privacy-manifest requirements have added a new release checklist for iOS teams. A repository can contain app-owned code that uses a Required-Reason API, one or more &lt;code&gt;PrivacyInfo.xcprivacy&lt;/code&gt; files, and third-party SDKs that have their own privacy-manifest or signature requirements.&lt;/p&gt;

&lt;p&gt;The painful time to discover an obvious gap is after preparing a release.&lt;/p&gt;

&lt;p&gt;This guide shows a bounded, repeatable way to check repository evidence before App Store Connect upload. It does not replace Apple's final build validation or App Review.&lt;/p&gt;

&lt;h2&gt;
  
  
  What should you check before upload?
&lt;/h2&gt;

&lt;p&gt;For a privacy-manifest preflight, three questions are especially useful:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Does app-owned native source contain signals for Apple's Required-Reason API categories?&lt;/li&gt;
&lt;li&gt;Do the scanned &lt;code&gt;PrivacyInfo.xcprivacy&lt;/code&gt; files appear to cover those categories without obvious structure gaps?&lt;/li&gt;
&lt;li&gt;Do dependency files contain SDKs on Apple's commonly used SDK list that deserve version-specific privacy-manifest/signature review?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Common App Store Connect messages developers search for include &lt;code&gt;ITMS-91053&lt;/code&gt; and &lt;code&gt;ITMS-91056&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Find app-owned Required-Reason API signals
&lt;/h2&gt;

&lt;p&gt;A simple example is app-owned use of &lt;code&gt;UserDefaults&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;defaults&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;UserDefaults&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;standard&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;isFirstLaunch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;defaults&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;forKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"hasLaunchedBefore"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A static preflight can recognize that source signal as the category:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;NSPrivacyAccessedAPICategoryUserDefaults&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;If the bounded repository scan finds that signal but does not find a relevant category declaration in the scanned privacy manifests, it can flag the file and line for review.&lt;/p&gt;

&lt;p&gt;That is more useful than a generic warning because the developer gets repository evidence to inspect.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Review PrivacyInfo.xcprivacy structure
&lt;/h2&gt;

&lt;p&gt;A privacy manifest can exist while still containing an obvious declaration gap.&lt;/p&gt;

&lt;p&gt;A typical accessed-API entry has both the API category and a reasons array:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;NSPrivacyAccessedAPITypes&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;array&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;dict&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;NSPrivacyAccessedAPIType&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;NSPrivacyAccessedAPICategoryUserDefaults&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;NSPrivacyAccessedAPITypeReasons&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;array&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;CA92.1&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/array&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/dict&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/array&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The reason code above is only an example for a specific Apple-defined UserDefaults use case. Do not copy a reason code merely because it makes a warning disappear. Confirm that the selected Apple-approved reason matches the app's actual behavior.&lt;/p&gt;

&lt;p&gt;A repository preflight can flag obvious structure gaps, such as an accessed API type that appears to be missing a corresponding reasons declaration. The final built product remains authoritative.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Inventory Apple-listed SDK dependencies
&lt;/h2&gt;

&lt;p&gt;Privacy-manifest work is not limited to app-owned Swift or Objective-C.&lt;/p&gt;

&lt;p&gt;Useful dependency evidence can appear in files such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Podfile&lt;/code&gt; and &lt;code&gt;Podfile.lock&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Package.swift&lt;/code&gt; and &lt;code&gt;Package.resolved&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;pubspec.yaml&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;package.json&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A preflight can inventory names that appear on Apple's commonly used SDK list, such as Firebase modules, Flutter, hermes, Alamofire, Kingfisher, Lottie, RealmSwift, and others.&lt;/p&gt;

&lt;p&gt;This should be treated as a review signal, not proof that a submission is broken. The exact dependency version packaged into the final app determines whether the expected privacy manifest and, when applicable, SDK signature are present.&lt;/p&gt;

&lt;h2&gt;
  
  
  Run the same preflight locally
&lt;/h2&gt;

&lt;p&gt;If you want to check a repository without connecting it to a web service, run the AccessVerdict CLI locally:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx @accessverdict/cli scan &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For machine-readable output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx @accessverdict/cli scan &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nt"&gt;--json&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For CI, &lt;code&gt;--strict&lt;/code&gt; makes review-only findings return a non-zero exit code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx @accessverdict/cli scan &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nt"&gt;--strict&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The CLI scans repository text files on your machine and does not upload repository source code to AccessVerdict. Its optional anonymous usage telemetry contains only a random installation id, CLI version, outcome class, and whether &lt;code&gt;--json&lt;/code&gt; or &lt;code&gt;--strict&lt;/code&gt; was used. It does not send repository names, paths, filenames, source code, or finding text. Set &lt;code&gt;DO_NOT_TRACK=1&lt;/code&gt; or &lt;code&gt;ACCESSVERDICT_TELEMETRY=0&lt;/code&gt; to disable it.&lt;/p&gt;

&lt;p&gt;You can also try the CLI against the five synthetic cases in the companion GitHub repository.&lt;/p&gt;

&lt;h2&gt;
  
  
  Put the preflight in GitHub Actions
&lt;/h2&gt;

&lt;p&gt;A minimal CI check can run the same public CLI on pull requests:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;App Store privacy preflight&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;pull_request&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;privacy-preflight&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;DO_NOT_TRACK&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;1"&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v4&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-node@v4&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;node-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;24&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npx --yes @accessverdict/cli scan . --strict&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The companion repository runs a live version of this workflow and verifies both a clean fixture and an expected blocker fixture:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/tzlee123/ios-privacy-manifest-preflight-cases/actions/workflows/accessverdict-cli-demo.yml" rel="noopener noreferrer"&gt;https://github.com/tzlee123/ios-privacy-manifest-preflight-cases/actions/workflows/accessverdict-cli-demo.yml&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The demo disables telemetry so automated example runs do not get counted as real CLI usage.&lt;/p&gt;

&lt;h2&gt;
  
  
  A deterministic repository preflight
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://accessverdict.dev/app-store-preflight?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=privacy_preflight" rel="noopener noreferrer"&gt;AccessVerdict&lt;/a&gt; runs bounded, read-only repository checks and reports file-level evidence.&lt;/p&gt;

&lt;p&gt;Its current preflight focuses on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;PrivacyInfo.xcprivacy&lt;/code&gt; presence and obvious structure gaps;&lt;/li&gt;
&lt;li&gt;app-owned Required-Reason API source signals;&lt;/li&gt;
&lt;li&gt;category coverage in scanned privacy manifests;&lt;/li&gt;
&lt;li&gt;common Apple-listed SDK dependency inventory;&lt;/li&gt;
&lt;li&gt;repository-scope uncertainty.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The scanner does not execute customer code and does not claim to reproduce App Review.&lt;/p&gt;

&lt;p&gt;The useful workflow is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Scan the repository.&lt;/li&gt;
&lt;li&gt;Review the file-level finding.&lt;/li&gt;
&lt;li&gt;Confirm the requirement in Apple's documentation.&lt;/li&gt;
&lt;li&gt;Fix the project locally.&lt;/li&gt;
&lt;li&gt;Run the same preflight again.&lt;/li&gt;
&lt;li&gt;Confirm the final Xcode privacy report and built product before submission.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Five small cases you can inspect
&lt;/h2&gt;

&lt;p&gt;A companion public repository contains five minimal synthetic cases:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;missing privacy manifest;&lt;/li&gt;
&lt;li&gt;required-reason API category missing from an existing manifest;&lt;/li&gt;
&lt;li&gt;obvious manifest reasons-structure gap;&lt;/li&gt;
&lt;li&gt;Apple-listed SDK dependency review;&lt;/li&gt;
&lt;li&gt;clean preflight case.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Browse the cases on GitHub: &lt;a href="https://github.com/tzlee123/ios-privacy-manifest-preflight-cases" rel="noopener noreferrer"&gt;ios-privacy-manifest-preflight-cases&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why not just ask an AI assistant?
&lt;/h2&gt;

&lt;p&gt;AI is useful for explaining Apple documentation and helping write a fix.&lt;/p&gt;

&lt;p&gt;A release gate has a different job: run the same bounded checks every time and return repeatable evidence. The two workflows complement each other.&lt;/p&gt;

&lt;p&gt;Use an assistant to understand or edit. Use a deterministic preflight to rerun the release check.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final checklist
&lt;/h2&gt;

&lt;p&gt;Before an App Store upload:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;inspect app-owned Required-Reason API usage;&lt;/li&gt;
&lt;li&gt;review the privacy-manifest evidence in the repository;&lt;/li&gt;
&lt;li&gt;inspect the exact third-party SDK versions used by the build;&lt;/li&gt;
&lt;li&gt;rerun the same preflight after changes;&lt;/li&gt;
&lt;li&gt;confirm the final Xcode-generated privacy report and submitted build.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can run the repository preflight at &lt;a href="https://accessverdict.dev/app-store-preflight?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=privacy_preflight" rel="noopener noreferrer"&gt;accessverdict.dev&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;AccessVerdict is an advisory static-analysis tool and is not affiliated with Apple. A clean repository scan is not a guarantee of App Store approval.&lt;/p&gt;

</description>
      <category>ios</category>
      <category>swift</category>
      <category>privacy</category>
      <category>appstore</category>
    </item>
  </channel>
</rss>
