TurtleGit for Mac

View Markdown source ↗

Signed Finder development

Finder badges and menus require the app, extension and cache service to share an authorized App Group. An unsigned build cannot prove this integration. TurtleGit uses the macOS group name $(TeamIdentifierPrefix)org.turtlegit.macos, expanded with the selected Apple developer team. The three peers receive the same group; the cache Mach service appends .cache to that name.

Apple permits this macOS team-qualified namespace without listing the group in a provisioning profile. Its registered group. namespace follows different profile rules. See Apple's App Group container guidance. Runtime lookup derives the team from the actual code signature and verifies the task's group entitlement before requesting a container. Unsigned/ad-hoc processes refuse access. The authenticated XPC requirement still pins Apple's signature anchor, the same team and the exact app/helper identifiers.

Build a development candidate

Select your real Apple developer team in Xcode. For a universal development candidate using an already installed Apple Development identity and existing profiles, use the shared App Store scheme. Prepare the current pinned runtimes in this checkout first using the runtime build instructions in scripts/build-git-runtime.py, scripts/build-libgit2-runtime.py and scripts/build-metafile-runtime.py. In particular, after changing the Metafile pin or renderer patch, refresh it with python3 scripts/build-metafile-runtime.py before the app build. Runtime caches belong to the checkout; a cache in another worktree does not refresh this one. The embedding phase deliberately refuses a staged manifest that disagrees with the current pin. Refreshing that payload lets Xcode reuse already compiled app objects rather than cleaning and rebuilding them.

xcodebuild -project TurtleGitMac.xcodeproj -scheme TurtleGitAppStore \
  -configuration AppStore -destination 'generic/platform=macOS' \
  -derivedDataPath build/signed-development \
  ARCHS='arm64 x86_64' ONLY_ACTIVE_ARCH=NO \
  DEVELOPMENT_TEAM=YOUR_TEAM_ID CODE_SIGN_IDENTITY='Apple Development' build

Replace YOUR_TEAM_ID with your team's identifier. This command does not request provisioning updates. If your team needs new or renewed managed development profiles for the app, Finder extension or cache service, configure them in Xcode; adding -allowProvisioningUpdates is a separate provisioning-enabled build choice. Development profiles can expire. This candidate is not an App Store export or a notarized Developer ID release. Distribution signing, licensing clearance and submission remain separate release requirements. A successful build also needs its own measured-input, signature and runtime evidence before acceptance claims.

The launch-agent embedding phase expands the service name using the same build team without changing the already signed helper. Do not hand-edit only one peer's entitlement or leave the literal build-variable text in the packaged agent plist. A build with no team gets an unqualified diagnostic service name; it does not acquire App Group access.

Check actual sandbox execution

After building, run the signed-runtime check with the explicit SHA-1 of your installed development identity, as listed by security find-identity -v -p codesigning:

python3 scripts/test-signed-finder-runtime.py \
  build/signed-development/Build/Products/AppStore/TurtleGitMac.app \
  --team YOUR_TEAM_ID --identity YOUR_IDENTITY_SHA1 \
  --report build/qa/signed-finder-runtime.json

The check first verifies actual Apple signatures, peer teams, sandbox/group entitlements, the generated service name and inherited sandbox signing on the packaged Git and Metafile executables. It then creates disposable copies with unique QA bundle identifiers. These run directly as sandboxed processes, without registering a Finder extension or background job. A writer runs the packaged inherited-sandbox Lexilla helper and Git and publishes a private fixture snapshot. A separate reader verifies its content. A negative process without the group entitlement must fail to read that snapshot.

A separate mode receives captured metafile bytes through bounded arguments, with no external repository file grants. It runs the packaged inherited-sandbox Metafile helper and native comparison image loader for WMF, EMF and EMF+ vector, text, bitmap, gradient, region and hatch cases, including selected indexed and RGB565 texture images. It checks actual dimensions and sampled colors, malformed input refusal, a deadline after helper launch, private-directory removal and owned helper process/group drainage. This selected corpus does not certify all metafile record types or Windows pixel equivalence.

The check removes only its UUID-named fixture directory through an entitled process and reaps its processes. The shipping candidate stays unchanged. It does not certify installed Finder activation, live overlays, multi-selection menus, background-service registration, external repository bookmarks, Keychain/SSH or network transport. Those require the corresponding signed installed workflows.

Switching developer teams changes the App Group namespace. Shared cache and menu presentation files are regenerated by the app; do not move permission bookmarks or credentials into the group to work around a missing entitlement. Private grant stores remain separate from Finder's status data.

Inherited-sandbox helpers cannot be launched by an ordinary unsandboxed build script. Embedding runs functional checks on the verified source payload before signing, then audits the signed copy's bytes, architecture, linkage and exact inheritance entitlements. The signed sandbox probe supplies the real parent for Lexilla's version check, Git's repository operations and Metafile conversion.

Installed development checkpoint

The October 17 installed check additionally verified user activation, live badges, native agent registration, authenticated permission transfer and background refresh after the app quit on macOS 27.0.1. It found and repaired Finder's dropped menu representedObject; an actual file-context Show Log then opened the containing signed app. The disposable watch/recent/helper grants were removed, the agent unregistered and owned app/ extension processes closed. This is development acceptance, not App Store export, minimum-version acceptance or certification of every Finder command.

October 18 signed runtime checkpoint

The October 18 checkpoint at 16380893 refreshes the universal Apple Development candidate at build/signed-development/Build/Products/AppStore/TurtleGitMac.app. It reuses existing profiles with DEVELOPMENT_TEAM=A49SCA5S8K and CODE_SIGN_IDENTITY='Apple Development'; no provisioning update was requested. An initial exact-certificate override failed because the targets use automatic signing. Actual signatures establish team A49SCA5S8K for all three peers.

That bundle passed deep/strict code verification, universal app component checks, the 204-item runtime code/data audit and cache-service packaging. Four owned sandbox probe processes pass writer, independent reader, denied nonmember and cleanup. The writer runs the actual packaged inherited-sandbox Git and Lexilla. The OS resolves the authorized group container; only a private UUID fixture is created/removed. All four probe processes exit and are independently absent afterward. The shipping candidate remains unchanged.

The unsigned validate-app-bundle.py --require-git command was mistakenly run after the signed build and failed at direct Git startup with SIGTRAP. Such a helper requires its sandboxed parent, as described above. The separate static signed audit and runtime probe passed; this is not a complete unsigned-validator pass on signed code. It does not renew the older installed checkpoint, launch the shipping main GUI, register a service/extension, export or submit an archive, or certify external folder grants and every signed workflow.

October 19 signed runtime checkpoint (historical)

The October 19 checkpoint replaces the local development-signed candidate at the same path with measured inputs based on bfa1fafe, including the current metafile renderer and custom TurtleGit artwork. The record retains the dirty script inputs and their complete input digest. Existing Apple Development profiles establish team A49SCA5S8K; no provisioning update, export or submission was requested.

Deep/strict seals, all eight universal app components, the 205-item runtime layout, branding, cache packaging and exact metafile source reconstruction pass. The 6,302-member candidate inventory is identical before and after the probes. Five owned signed processes pass writer, reader, denied nonmember, metafile and cleanup modes. Eight images render with expected dimensions/colors, text/bitmap content, gradient, region, hatch and selected indexed4/RGB565 texture behavior. A malformed palette index is refused; a positive deadline expires after actual helper launch. Captured bytes remain unchanged and request directories are removed. The observer captured one actual helper PID/group; it and all five receiver PIDs/groups are independently absent afterward. The private group fixture and disposable clones are removed.

This is actual selected sandbox execution on Apple Silicon. It does not renew the older installed Finder checkpoint, launch the shipping GUI, certify physical Intel/minimum macOS or every graphics format, or establish distribution signing, licensing clearance and App Store acceptance. The older Release preview and unsigned archive are unchanged.

October 24 history and Notes signed checkpoint

The October 24 receipt records a new universal AppStore Apple Development candidate based on 9a8e37ce, using team A49SCA5S8K, the installed identity and existing profiles. No provisioning update, archive export or submission was requested. The build exited successfully; its five contradictory “failed with exit code 0” diagnostics remain recorded.

Static checks passed deep/strict seals, identity/branding, cache packaging, all eight universal owned app components and 206 runtime code items. App, Finder and cache peers retain version 0.1.0/build 2 and the same team-qualified App Group. Packaged LibGit2 and Metafile helpers passed their actual same-team, inherited-sandbox and resolved-layout checks. The original measured build-input signature remains intact. A pre-execution correction changed only the external runner: a legitimate Git maintenance child can share the request's process group, so group-leader requirements apply to direct LibGit2/Metafile helpers rather than every Git descendant. All other measured inputs and the Swift probe were explicitly unchanged; the app was not rebuilt from that revised test harness.

All six signed modes passed on their first execution: writer, independent reader, denied nonmember, history, metafile and cleanup. They used disposable same-team signed clones and one private UUID directory in the authorized App Group, with no external file grants, injected executors, user preferences or windows. The shipping GUI was not launched and no Finder/service job was registered.

The new history UUID TEAM mode used the actual packaged Git and default LibGit2 runtime through public Core APIs. It verified typed commit/tree/raw annotated-tag identities, distinct packed NFC/NFD reference spellings, pinned Browser listing and file bytes, and historical gitlink metadata. Unconditional SHA-1 Notes ran with the master preference disabled, used the configured notes ref and signature despite environment overrides, round-tripped 1,416,000 exact Unicode/LF UTF-8 bytes, and then retained an empty note association. HEAD, index, configuration and working bytes remained unchanged. The retained metafile mode rendered eight selected images, refused one malformed image and exercised a deadline after actual helper spawn; original corpus bytes were unchanged.

Six probe receivers and three observed helper PIDs were reaped and independently absent. The observer captured one LibGit2 process and two Metafile processes, including their PPID/PGID/role receipts; their owned groups drained without forced cleanup. Actual Git commands completed, although the history observer sampled no Git PID. The private group fixture and exact disposable clone directory were removed. An initial postcheck used an overbroad signed-finder-* glob that also matched two historical report files; checking this run's exact clone folder passed. No runtime case failed or reran, and no app rebuild was needed.

The final checkpoint confirmed all 6,356 shipping-bundle inventory members were unchanged, along with the measured validation-input signature and documented external-runner-only delta. The existing /Applications app was untouched and user-installed Finder PID 57078 was preserved. The October 19 receipt above remains historical evidence for its own source revision.

This establishes selected actual sandbox execution on Apple Silicon and static universal packaging. It does not renew installed Finder/XPC delivery, prove the native Notes editor/Settings workflow under external bookmark grants, or certify live badges, context-menu delivery, background registration, Keychain/SSH/network transport, physical Intel/minimum macOS behavior or every current metafile case. The private App Group repository does not establish permission for arbitrary user repositories. Distribution export and submission remain separate from this Apple Development build and scoped probe.

October 25 installed consolidation

The 5b315808 consolidation receipt adds actual installed-app folder grants, native Commit/Settings/Remote checks, Finder file-menu Log/Notes delivery and helper-only Normal → Modified → Normal badge refresh after normal application Quit. It retains the measured signed source and bundle inventory separately from later development. The original watched/recent repositories were retained, and temporary background registration was disabled after removing only the test fixture. This is bounded installed acceptance, not an App Store distribution export or complete Finder/dialog certification.

October 25 build 7 consolidation

The build 7 receipt records the recoverably installed universal Apple Development candidate at clean d89ad1f6 inputs. Its strict signatures, peer identities, inherited helper layout and 6,362-member source/staged/installed inventory agree. The first build refused an old staged Metafile manifest; refreshing the current pinned runtime allowed a packaging-only repair without repeated Swift compilation. No provisioning update, App Store export or submission was performed.

Actual private three-way Merge grants and the separate read-only source comparison passed their bounded flow. Physical title, selector and accessibility findings are recorded separately from later source corrections. An image launch failed before rendering, and the mail flow was deferred; neither gains a new physical pass. Test-owned windows/processes were closed and affected private test state was restored. The earlier sandbox helper probes and Finder acceptance retain their own source revisions and scope.