Skip to content

feat(mac-release): Developer ID signing + Owletto rebrand + submodule bump#894

Merged
buremba merged 4 commits into
mainfrom
feat/mac-release-signed
May 18, 2026
Merged

feat(mac-release): Developer ID signing + Owletto rebrand + submodule bump#894
buremba merged 4 commits into
mainfrom
feat/mac-release-signed

Conversation

@buremba
Copy link
Copy Markdown
Member

@buremba buremba commented May 18, 2026

Summary

Companion to lobu-ai/owletto#187. After both merge, dispatching mac-release produces a Developer ID signed + notarized Owletto.dmg.

  • mac-release.yml: paths updated for the Lobu.xcodeproj → Owletto.xcodeproj rename in the submodule, scheme assertion + xcodebuild invocation switch to -scheme Owletto, archive path to Owletto.xcarchive, and EXPECTED_BUNDLE_ID to com.owletto.mac.
  • Provisioning profile handling becomes optional (gated on `env.PROFILE_BASE64 != ''`). With no restricted entitlements shipping today, signed builds work without a profile; the step lights up automatically once `APPLE_PROVISION_PROFILE_BASE64`/`_NAME` are set (e.g. after Apple approves the pending HealthKit Capability Request).
  • Header docs rewritten to list the 5 required secrets and 2 optional ones, plus the Apple flow for re-adding HealthKit later.
  • Submodule pointer `packages/owletto` 970eb500 → 2a513a20 to pick up the Owletto rename in the submodule.

GH secrets already set on this repo

`APPLE_CERT_P12_BASE64`, `APPLE_CERT_PASSWORD`, `APPLE_TEAM_ID=CCV9Q352W3`, `APPLE_ID=emre@lobu.ai`, `APPLE_APP_PASSWORD`. `SPARKLE_ED_PRIVATE_KEY` already in place. `APPLE_PROVISION_PROFILE_*` intentionally not set — added later when HealthKit ships.

Test plan

  • Merge owletto#187 first (or trust the submodule pointer is reachable on its branch).
  • After both PRs land, run `gh workflow run mac-release.yml -f version=<X.Y.Z>` on lobu-ai/lobu and inspect:
    • Verify release contract (path + scheme + bundle-id + Sparkle key checks)
    • Detect signing mode → SIGNED
    • Import signing certificate
    • Archive (signed) — manual Developer ID, hardened runtime
    • Build DMG → Notarize and staple → Attach to release → Sparkle appcast
  • Download the DMG; `spctl -a -vv Owletto.app` should report "accepted" with team CCV9Q352W3.
  • First launch on a fresh-ish Mac: no Gatekeeper warning, no right-click → Open dance.

Summary by CodeRabbit

  • Chores
    • macOS release pipeline updated to target the Owletto app with stricter build and signing validations.
    • Added optional restricted‑entitlement support and conditional provisioning profile installation for signed builds.
    • DMG and archive steps adjusted to consume Owletto build outputs.
    • Embedded Owletto project reference updated to a newer commit.
    • Context configuration extended to include a URL and public key.

Review Change Stack

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 18, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The macOS release workflow was refactored from Lobu to Owletto: release contract checks now target Owletto/com.owletto.mac, an optional provisioning-profile install was added for SIGNED builds, archive/sign/DMG steps were updated to use Owletto paths, the owletto submodule was bumped, and context7.json was populated.

Changes

Owletto Release Workflow Migration

Layer / File(s) Summary
Documentation and contract setup
.github/workflows/mac-release.yml
Workflow documentation expanded for Apple signing secrets and optional APPLE_PROVISION_PROFILE_BASE64/APPLE_PROVISION_PROFILE_NAME; inline release comment and required-path checks changed from Lobu to Owletto.
Release contract verification
.github/workflows/mac-release.yml
Scheme and plist validation now read packages/owletto/apps/mac/Owletto.xcodeproj and packages/owletto/apps/mac/Owletto/Info.plist; expect Owletto scheme, CFBundleName/CFBundleDisplayName = Owletto, PRODUCT_BUNDLE_IDENTIFIER = com.owletto.mac, and SUPublicEDKey present.
Provisioning profile installation
.github/workflows/mac-release.yml
New signed-only step decodes APPLE_PROVISION_PROFILE_BASE64, extracts provisioning profile UUID from the decoded plist, installs <UUID>.provisionprofile into ~/Library/MobileDevice/Provisioning Profiles, and sets installed=true for downstream gating.
Archive, signing, and packaging
.github/workflows/mac-release.yml
Archive uses Owletto.xcodeproj -scheme Owletto; signed path conditionally passes PROVISIONING_PROFILE_SPECIFIER, re-signs Sparkle nested helpers and Owletto.app (leaf-first) with Developer ID + hardened runtime + timestamp, and strictly verifies codesign. Unsigned/ad-hoc flow archives Owletto and ad-hoc codesigns Owletto.app; DMG step sources Owletto.app from the archive.
Submodule update
packages/owletto
Git submodule pointer updated to a new commit hash.
Context JSON update
context7.json
context7.json populated with url and public_key string fields.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • lobu-ai/lobu#838: Related submodule update that modifies/rotates Sparkle SUPublicEDKey, which this workflow now validates.
  • lobu-ai/lobu#857: Also updates the packages/owletto git submodule pointer; changes overlap at the submodule level.
  • lobu-ai/lobu#807: Modifies macOS workflow release-contract validations and Xcode scheme expectations, similar to this PR's workflow edits.

Poem

🐰 I hopped through CI with a tiny cheer,
Decoded profiles and signed with care,
Owletto’s scheme now shines so clear,
Bundles bundled, DMG near—
Release bells ring, I twitch my ear.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately captures the three main changes: Developer ID signing setup, Owletto rebrand, and submodule bump.
Description check ✅ Passed The description covers summary, test plan with checkboxes, and additional notes about secrets and breaking changes.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/mac-release-signed

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/mac-release.yml:
- Around line 271-281: The PP_ARG expansion is unquoted when passed to
xcodebuild which will split profiles with spaces; set PP_ARG as a single quoted
string containing the PROVISIONING_PROFILE_SPECIFIER value (using the secret
APPLE_PROVISION_PROFILE_NAME) and expand it quoted in the xcodebuild invocation
(i.e., make PP_ARG a single token and use a quoted "$PP_ARG" when calling
xcodebuild) so the profile name with spaces is preserved; update the code around
the PP_ARG assignment and the xcodebuild line accordingly (references: PP_ARG,
APPLE_PROVISION_PROFILE_NAME, steps.profile.outputs.installed, xcodebuild).

In `@packages/owletto`:
- Line 1: The packages/owletto submodule is pointing to a non-existent commit
(2a513a20f55e5660452dd8416324ea0157028eae) in the lobu-ai/owletto repo; verify
the intended commit hash exists in lobu-ai/owletto (and that the Owletto rename
and merge from lobu-ai/owletto#187 are pushed), then update the submodule
pointer to a valid commit: open the packages/owletto submodule entry (the
submodule ref in .gitmodules/.git/config or the gitlink in the superproject),
replace the bad SHA with the correct pushed commit, commit that change in the
superproject, and run git submodule sync && git submodule update --init to
confirm the submodule now checks out successfully.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 016f1c35-5436-4c26-8e6e-d0975d51ed9e

📥 Commits

Reviewing files that changed from the base of the PR and between a8e4a35 and eba1b30.

📒 Files selected for processing (2)
  • .github/workflows/mac-release.yml
  • packages/owletto

Comment thread .github/workflows/mac-release.yml Outdated
Comment thread packages/owletto Outdated
buremba added a commit that referenced this pull request May 18, 2026
…d-split

pi review of #894 flagged that PROVISIONING_PROFILE_SPECIFIER built into a
scalar and expanded unquoted as `$PP_ARG` would split a profile name
containing spaces (e.g. "Owletto Developer ID") into three xcodebuild
arguments. Switch to a bash array so each element survives word-splitting,
and only append the specifier when the profile-install step actually ran.
@buremba
Copy link
Copy Markdown
Member Author

buremba commented May 18, 2026

pi review applied

Fixed: mac-release.yml Archive (signed) step now uses a bash array for xcodebuild args, so a PROVISIONING_PROFILE_SPECIFIER containing spaces ("Owletto Developer ID") no longer word-splits. Pushed in 4995076.

Acknowledged, not fixed (intentional scope): pi also flagged that the bundle-id change ai.lobu.mac → com.owletto.mac breaks Sparkle in-place updates for existing installs (Sparkle 2.x refuses an update with a mismatched bundle id). This is forced — Apple won't release ai.lobu.mac from the expired Burak Kabakcı team without both teams active, and the new team CCV9Q352W3 can't claim a globally-taken identifier. Installed users (very small, app is pre-1.0) will need to download the fresh DMG. UserDefaults / security-scoped bookmarks / Keychain entries also reset because they're bundle-id-keyed; the ad-hoc → Developer ID signature transition already resets TCC grants regardless. Migration code is a follow-up if the install base grows.

buremba added 4 commits May 18, 2026 23:52
…tto submodule

Pair PR for lobu-ai/owletto#187 (rebrand Lobu.xcodeproj → Owletto.xcodeproj
and switch to the new Apple Developer team CCV9Q352W3 under emre@lobu.ai).

mac-release.yml updates:
- All paths follow the rename: packages/owletto/apps/mac/Lobu.xcodeproj
  → Owletto.xcodeproj, Lobu/Info.plist → Owletto/Info.plist,
  Lobu.entitlements → Owletto.entitlements.
- Scheme assertion: 'Lobu' → 'Owletto'; -scheme Owletto passed to
  xcodebuild; archive path Lobu.xcarchive → Owletto.xcarchive.
- Bundle id assertion EXPECTED_BUNDLE_ID: ai.lobu.mac → com.owletto.mac.
- Provisioning-profile handling becomes optional. The "Install
  provisioning profile" step is gated on env.PROFILE_BASE64 != '' and
  PROVISIONING_PROFILE_SPECIFIER is only passed to xcodebuild when a
  profile was actually installed. Without restricted entitlements (no
  HealthKit yet, pending Apple's Capability Request approval), signed +
  notarized builds run without a profile.
- Header docs rewritten: list the 5 required secrets
  (APPLE_CERT_P12_BASE64, APPLE_CERT_PASSWORD, APPLE_TEAM_ID, APPLE_ID,
  APPLE_APP_PASSWORD) and the 2 optional ones, documenting the Apple
  Capability Request flow for adding HealthKit later.

Submodule bump:
- packages/owletto 970eb500 → 2a513a20 to pick up the Owletto.xcodeproj
  layout from lobu-ai/owletto#187. Without this bump the release
  contract step would fail (Lobu.xcodeproj no longer exists in the
  submodule).
…d-split

pi review of #894 flagged that PROVISIONING_PROFILE_SPECIFIER built into a
scalar and expanded unquoted as `$PP_ARG` would split a profile name
containing spaces (e.g. "Owletto Developer ID") into three xcodebuild
arguments. Switch to a bash array so each element survives word-splitting,
and only append the specifier when the profile-install step actually ran.
Notarization rejected the first signed run with 'binary not signed with
valid Developer ID' / 'signature does not include a secure timestamp'
errors on Sparkle.framework's nested helpers (Updater.app, Autoupdate,
Downloader.xpc, Installer.xpc). Xcode's archive doesn't apply Developer
ID + secure timestamp to these when Sparkle is integrated via SPM.

Add a post-archive step that re-signs each helper leaf-first with
--options runtime --timestamp, then re-signs the framework and umbrella
app so the new helper signatures get sealed into the parent.
Final codesign --verify --deep --strict before the bundle is handed
to Build DMG / notarytool.
@buremba buremba force-pushed the feat/mac-release-signed branch from 77feff7 to 3c2d07f Compare May 18, 2026 22:52
@buremba buremba merged commit d3591b1 into main May 18, 2026
18 of 19 checks passed
@buremba buremba deleted the feat/mac-release-signed branch May 18, 2026 22:53
@codecov-commenter
Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

buremba added a commit that referenced this pull request May 18, 2026
Two fixes wrapped together because both are needed to land this PR.

1. owletto submodule now points at 0275737 (the squash-merge of
   lobu-ai/owletto#188 into main), so it's reachable from owletto/main
   and check-drift stops failing.

2. .github/workflows/ci.yml's mac-build-smoke job still references
   Lobu.xcodeproj + scheme Lobu, but the rebrand in #894 renamed both
   to Owletto. Update the paths so the job builds again. This was
   pre-existing breakage on main, not introduced by this branch.
buremba added a commit that referenced this pull request May 18, 2026
…ative auto-pair (#896)

* feat(server,chrome-ext): mint session_token alongside child PAT for native auto-pair

POST /api/me/devices/mint-child-token now returns a Better Auth session_token
alongside the worker PAT. The Owletto Chrome extension's native auto-pair
needs this so the embedded iframe (which runs on the gateway origin with its
own session) lands signed-in instead of bouncing the user to a second
password prompt.

The session is minted via internalAdapter.createSession() for the same user
the bridge bearer authenticates, mirroring how /api/local-init mints
bootstrap sessions. Mint failures are logged + ignored — the child PAT is
still returned so the worker can poll; the iframe just falls back to the
sign-in screen (matching pre-handoff behavior).

Pairs with owletto#188, which:
- Forwards session_token through ChromeBridgeHost.swift.
- Adds installGatewaySessionCookie helper in sidepanel.js that hits
  /api/exchange-token in a top-level tab before storage.set so the cookie is
  in the jar by the time the iframe mounts.
- Fixes a latent path bug: tryLocalInit was calling /api/auth/exchange-token,
  which the Better Auth /api/auth/* catch-all 404s. Real route is
  /api/exchange-token.

Bumps owletto submodule to the matching SHA.

* chore(submodule): bump owletto to d4a2616 (silent session-cookie refresh)

Picks up the second commit on owletto#188: renderInitialView now does a
native-bridge handshake on every paired boot so the iframe gets a fresh
session cookie before mounting. Closes the already-paired gap that
the first commit didn't cover (storage.accessToken existing meant
mountEmbeddedApp was called directly, skipping the cookie install).

* chore(submodule): bump owletto to 14b641c (silent refresh no longer leaks workers)

Codex review caught it: the silent refresh in renderInitialView was calling
mint-child-token just to extract session_token, but that endpoint also
creates worker_id + PAT + device_workers row server-side — all discarded.
Every side-panel open leaked one row.

Fixed in owletto by handing the stored access_token to /api/exchange-token
directly (resolveDeepLinkToken accepts PATs). No new minting, no leak.

* chore: bump owletto to merged main + fix mac-build-smoke after rebrand

Two fixes wrapped together because both are needed to land this PR.

1. owletto submodule now points at 0275737 (the squash-merge of
   lobu-ai/owletto#188 into main), so it's reachable from owletto/main
   and check-drift stops failing.

2. .github/workflows/ci.yml's mac-build-smoke job still references
   Lobu.xcodeproj + scheme Lobu, but the rebrand in #894 renamed both
   to Owletto. Update the paths so the job builds again. This was
   pre-existing breakage on main, not introduced by this branch.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants