Define two destinations
Create an explicit public-artifact destination and a separate private diagnostics destination. The public directory contains what customers download. The private destination holds dSYMs and the build metadata needed by maintainers or authorized crash-reporting services. Do not assume that a generic upload exclusion also preserves the files somewhere useful.
An Xcode archive is an internal release record and may intentionally include symbols. It is not equivalent to an exported customer package. Audit your download bucket, CI artifacts and support attachments separately: an otherwise correct app export can still be accompanied by a public archive containing internal diagnostics.
Pair symbols with the executable
Use the binary image UUID to establish which symbol resources belong to which build. A matching marketing version is insufficient when a release has been rebuilt or distributed in several architectures. Retain the build number, architecture and binary UUID with the private symbol index.
For an owned macOS fixture, the commands below expose the relevant identifiers. Use paths appropriate to the actual executable and dSYM. Compare matching architectures, and investigate mismatches before a release depends on the symbols for incident response.
dwarfdump --uuid Example.app/Contents/MacOS/Example
dwarfdump --uuid Example.app.dSYMProve the recovery path
Generate or retain an authorized diagnostic report for a known release fault and follow the same symbolication process your support team will use. Check that meaningful application frames appear. An upload success notification from a crash service does not prove that the correct UUID was indexed or that every embedded image has symbols.
Limit access to diagnostic resources because they can reveal names, file paths and implementation detail. Set retention from the support lifetime of the release rather than an arbitrary CI cleanup interval. Customers may remain on an older build long after the next version is published.
Use CloneGuard at the release boundary
Screen the customer-facing artifact tree for accidentally included debug companions. Keep the private symbol location outside the tree being manifested, and do not pass a signed native application through loose-web staging. CloneGuard deliberately refuses that staging use case.
Hash the final distributed package after normal native checks. A release receipt records exact bytes; it does not assert that the private dSYM is correct or that crash recovery was tested. Document those native diagnostic checks as separate evidence so a future maintainer can repeat the process.
Practical checklist
- Keep private symbols for every supported release.
- Compare executable and dSYM UUIDs.
- Test symbolication of an owned crash report.
- Check public storage permissions independently.
Sources and further reading
Primary references support the technical details. Procedures here are guidance; only explicitly recorded project results describe tests we ran.
Prepared with AI assistance. How this library is produced. Suggest a correction; keep private code and credentials out of public issues.