mirror of
https://github.com/abue-ammar/tinycast.git
synced 2026-10-02 00:04:44 +08:00
* Turn on the hardened runtime, and teach the updater the identity it will switch to Notarization needs two things Tinycast doesn't have: the hardened runtime, and an Apple Developer ID signature. This does the first and prepares for the second. The updater compares signatures before it installs, byte-for-byte against the leaf the running app carries. A Developer ID leaf is a different certificate, so switching identities outright would make every installed copy reject every future update. `BundleSignature` therefore learns the Developer ID requirement now, while releases are still signed with `Tinycast Self-Signed` — the code that trusts the new identity has to reach people before the first build carrying it does. The requirement pins the team, not the certificate, so a renewal strands nobody. It omits the `notarized` keyword on purpose: that resolves a ticket through syspolicyd or the network, and the updater verifies inside a cache directory Gatekeeper has never assessed, so an offline Mac would refuse a bundle the chain already proves is ours. Hardened runtime needs two entitlements. JavaScriptCore compiles every extension command, and without `allow-jit` it falls back to the interpreter. Without `automation.apple-events` every Apple event is refused with -1743 and no prompt, which silently kills Get Info, the Finder selection extensions read, and the System Events-driven system actions. Nothing else is required: the only dlopen is Apple's own IOBluetooth, so library validation stays on. The flag is not part of the designated requirement, so no Accessibility grant is lost here. `project.yml` keeps signing with `Tinycast Self-Signed`, so nothing changes for a contributor building locally. `Scripts/verify-signature.sh` asserts what notarization will check — the runtime flag on the app and on the embedded helper, an intact nested seal, and no get-task-allow. Both release jobs run it before packaging, because a nested binary missing the runtime flag is the most common notarization rejection there is. * Keep the hardened runtime out of Debug, where library validation refuses the debug dylib Hardened runtime turns on library validation, and a Debug build links `Tinycast Dev.debug.dylib`. The self-signed identity carries no Team ID, so the loader sees a team mismatch and aborts at launch — every local Debug build died with a DYLD "Library missing" termination. Notarization only ever sees Release, so the flag belongs in that config alone.
84 lines
3.0 KiB
YAML
84 lines
3.0 KiB
YAML
name: Tinycast
|
|
options:
|
|
bundleIdPrefix: com.tinycast
|
|
deploymentTarget:
|
|
macOS: "26.0"
|
|
createIntermediateGroups: true
|
|
groupSortPosition: top
|
|
|
|
settings:
|
|
base:
|
|
MARKETING_VERSION: "0.1.0"
|
|
CURRENT_PROJECT_VERSION: "1"
|
|
SWIFT_VERSION: "6.0"
|
|
DEVELOPMENT_TEAM: ""
|
|
CODE_SIGN_STYLE: Manual
|
|
# Stable self-signed identity so macOS keeps the Accessibility grant across rebuilds.
|
|
# Create it once — see docs/signing.md.
|
|
CODE_SIGN_IDENTITY: "Tinycast Self-Signed"
|
|
SWIFT_STRICT_CONCURRENCY: complete
|
|
configs:
|
|
Release:
|
|
# Release-only: library validation refuses Debug's `.debug.dylib`, whose team never matches.
|
|
ENABLE_HARDENED_RUNTIME: YES
|
|
# Strip the shipped binary (dSYM is still generated first) and drop unused code.
|
|
DEPLOYMENT_POSTPROCESSING: YES
|
|
STRIP_INSTALLED_PRODUCT: YES
|
|
STRIP_SWIFT_SYMBOLS: YES
|
|
DEAD_CODE_STRIPPING: YES
|
|
|
|
targets:
|
|
Tinycast:
|
|
type: application
|
|
platform: macOS
|
|
sources:
|
|
- path: Tinycast
|
|
# The helper's own sources: compiling them in would link Vision and PDFKit into the app,
|
|
# which is the whole thing running recognition out of process avoids.
|
|
excludes:
|
|
- Features/Clipboard/Service/ClipboardTextExtractor.swift
|
|
- Features/Clipboard/Service/ClipboardTextHelper.swift
|
|
# The MIT mark's licence asks the notice to travel with the binary, not just the repo.
|
|
- path: NOTICE.md
|
|
buildPhase: resources
|
|
dependencies:
|
|
- target: ClipboardTextHelper
|
|
link: false
|
|
embed: true
|
|
codeSign: true
|
|
copy:
|
|
destination: wrapper
|
|
subpath: Contents/Helpers
|
|
settings:
|
|
base:
|
|
PRODUCT_BUNDLE_IDENTIFIER: com.tinycast.app
|
|
INFOPLIST_FILE: Tinycast/Info.plist
|
|
CODE_SIGN_ENTITLEMENTS: Tinycast/Tinycast.entitlements
|
|
ASSETCATALOG_COMPILER_APPICON_NAME: tinycast
|
|
COMBINE_HIDPI_IMAGES: YES
|
|
LD_RUNPATH_SEARCH_PATHS:
|
|
- "$(inherited)"
|
|
- "@executable_path/../Frameworks"
|
|
configs:
|
|
# Debug is its own channel, like beta/stable in release.yml: a distinct bundle id means a
|
|
# locally-run build gets its own prefs, caches, TCC grants and login item instead of
|
|
# inheriting — and corrupting — the installed app's state.
|
|
Debug:
|
|
PRODUCT_NAME: Tinycast Dev
|
|
PRODUCT_BUNDLE_IDENTIFIER: com.tinycast.app.dev
|
|
|
|
ClipboardTextHelper:
|
|
type: tool
|
|
platform: macOS
|
|
sources:
|
|
- Tinycast/Features/Clipboard/Service/ClipboardTextExtractor.swift
|
|
- Tinycast/Features/Clipboard/Service/ClipboardTextHelper.swift
|
|
settings:
|
|
base:
|
|
# release.yml passes PRODUCT_NAME on the xcodebuild line, which hits every target: without
|
|
# these two pinned, a channel build renames the executable `ClipboardTextWorker` looks for
|
|
# and gives the module a name with a space in it.
|
|
EXECUTABLE_NAME: ClipboardTextHelper
|
|
PRODUCT_MODULE_NAME: ClipboardTextHelper
|
|
SKIP_INSTALL: YES
|