From af5315313d8300f9801912047c0e07ceb2fffa46 Mon Sep 17 00:00:00 2001 From: George Brancovici Date: Thu, 9 Jul 2026 14:15:36 -0400 Subject: [PATCH] Add migration docs and fix notarization scripts to use inline credentials Keychain profile approach doesn't work from Galaxy terminal (no interactive auth entitlement). Switched to inline Apple ID/team/password in notarize.sh and package.sh. Added migration-docs/ for session continuity on new machines. Co-Authored-By: Claude Opus 4.6 (1M context) --- migration-docs/README.md | 21 +++++ migration-docs/conversation-transcript.md | 91 ++++++++++++++++++++++ migration-docs/credentials-and-signing.md | 69 +++++++++++++++++ migration-docs/current-state.md | 63 +++++++++++++++ migration-docs/project-architecture.md | 94 +++++++++++++++++++++++ migration-docs/session-history-may.md | 48 ++++++++++++ migration-docs/user-preferences.md | 32 ++++++++ notarize.sh | 4 +- package.sh | 4 +- 9 files changed, 424 insertions(+), 2 deletions(-) create mode 100644 migration-docs/README.md create mode 100644 migration-docs/conversation-transcript.md create mode 100644 migration-docs/credentials-and-signing.md create mode 100644 migration-docs/current-state.md create mode 100644 migration-docs/project-architecture.md create mode 100644 migration-docs/session-history-may.md create mode 100644 migration-docs/user-preferences.md diff --git a/migration-docs/README.md b/migration-docs/README.md new file mode 100644 index 00000000..fd9e145b --- /dev/null +++ b/migration-docs/README.md @@ -0,0 +1,21 @@ +# Migration Docs — Galaxy Project + +This folder contains everything needed for a new Claude instance to pick up exactly where the previous session left off. + +## How to Use + +Give all files in this folder to the new Claude instance at the start of conversation. Say something like: + +> "Read all files in `migration-docs/` — this is a handoff from a previous Claude session. Pick up where it left off." + +## Contents + +| File | Purpose | +|------|---------| +| `README.md` | This file — instructions for handoff | +| `conversation-transcript.md` | Full transcript of the 2026-07-08/09 session | +| `session-history-may.md` | Prior session log (May 13-14, 2026) — signing pipeline creation | +| `project-architecture.md` | Codebase architecture reference (56-crate Rust workspace) | +| `current-state.md` | Exact state of repo, uncommitted changes, pending work | +| `credentials-and-signing.md` | Apple signing credentials, certificate info, how the build pipeline works | +| `user-preferences.md` | How George works, what he expects, communication style | diff --git a/migration-docs/conversation-transcript.md b/migration-docs/conversation-transcript.md new file mode 100644 index 00000000..b7a37a89 --- /dev/null +++ b/migration-docs/conversation-transcript.md @@ -0,0 +1,91 @@ +# Conversation Transcript — 2026-07-08 / 2026-07-09 + +## Session Start + +George activated minion mode. Session startup: +- Checked conversation logs, memory systems, tasks — no active tasks +- Last session was May 13-14 (2 month gap) +- Set up hourly doc-sync cron (job `b3d95f3a`, fires at :17) + +## Task 1: Pull Latest Code + +**George:** "pull the latest code" + +- Ran `git stash -u -- Cargo.lock` (modified Cargo.lock in working tree) +- `git pull --ff-only` — fast-forwarded from `840bc4d` to `40bd86f6` (3,893 files updated) +- Major changes: rebase-with-warp merge, OpenAI/LiteLLM support, Bedrock crash logging +- Cargo.lock stash had conflict with upstream — resolved by taking upstream version (`git checkout -- Cargo.lock`) +- New remote branch: `feat/warp-parity`, new tags: `v1.6.2`, `v1.6.3` + +## Task 2: Build Release + +**George:** "how to build" + +Provided build commands: +```bash +cargo run # Dev run +cargo bundle --bin galaxy-oss --package galaxy # Bundle .app +./build-debug.sh # Full debug DMG +./build-release.sh # Full release DMG +./script/presubmit # fmt + clippy + tests +``` + +**George:** "build release failed" + +Ran `./build-release.sh` — compiled and signed successfully but hung at notarization. + +**Root cause:** Keychain profile `notarytool-profile` was gone (keychain reset since May session). + +Attempted to store credentials: +```bash +xcrun notarytool store-credentials notarytool-profile \ + --apple-id g.brancovici@samsung.com \ + --team-id 3JU72Z7Y3J \ + --password cowi-fved-uajk-arsk +``` + +Failed with "HTTP 401 Invalid credentials" when using Samsung password directly. Needed app-specific password. + +**George provided app-specific password:** `cowi-fved-uajk-arsk` + +Credentials validated but `store-credentials` failed with "User interaction is not allowed" — Galaxy terminal can't write to keychain (no interactive auth entitlement). + +Tried `security unlock-keychain` — still failed. The issue is `notarytool` needs a macOS security dialog that non-standard terminals can't show. + +**Solution:** Modified scripts to use inline credentials instead of keychain profile: +- `notarize.sh` — replaced `--keychain-profile notarytool-profile` with `--apple-id`/`--team-id`/`--password` +- `package.sh` — same change + +**Result:** Full `./build-release.sh` completed successfully: +- Compile: OK (release profile, 1.89s — was cached) +- Bundle: Galaxy.app created +- Sign: Developer ID Application: SAMSUNG ELECTRONICS AMERICA, INC. (3JU72Z7Y3J) +- Notarize app: Accepted (submission `04c80ce4-b4de-4ffa-81f7-63e4b80299ee`) +- Create DMG: OK (hdiutil, one retry needed for "Resource busy") +- Sign DMG: OK +- Notarize DMG: Accepted (submission `ce8e821f-3898-488f-9370-f5d67e617ec5`) +- Staple: OK +- Output: `target/release/bundle/osx/Galaxy.dmg` + +## Task 3: Clean Build Instructions + +**George:** "I need to run the build script myself fresh. how do I clean up everything before that?" + +Provided: +```bash +# Just remove bundle output (quick): +rm -rf target/release/bundle/osx/Galaxy.app target/release/bundle/osx/Galaxy.dmg + +# Full recompile (slower, ~2 min): +cargo clean --release +``` + +## Task 4: Migration Docs (current) + +**George:** "create a folder migration-docs..." + +Creating this migration package. + +## Hourly Doc Syncs + +Multiple hourly cron fires occurred throughout the session. All reported "no updates needed" after the initial sync that created the conversation log and active-work.md. diff --git a/migration-docs/credentials-and-signing.md b/migration-docs/credentials-and-signing.md new file mode 100644 index 00000000..4b20e207 --- /dev/null +++ b/migration-docs/credentials-and-signing.md @@ -0,0 +1,69 @@ +# Credentials & Signing Pipeline + +## Apple Developer Credentials + +| Field | Value | +|-------|-------| +| Apple ID | g.brancovici@samsung.com | +| Team ID | 3JU72Z7Y3J | +| Team Name | SAMSUNG ELECTRONICS AMERICA, INC. | +| Certificate | Developer ID Application: SAMSUNG ELECTRONICS AMERICA, INC. (3JU72Z7Y3J) | +| App-Specific Password | cowi-fved-uajk-arsk | +| Bundle ID | com.samsung.Galaxy | + +## Signing Pipeline + +The build pipeline is a sequence of standalone scripts: + +``` +build-release.sh + ├── cargo bundle --release --bin galaxy-oss --package galaxy + ├── sign.sh --release + ├── notarize.sh --release + └── package.sh --release +``` + +### sign.sh +- Signs `Galaxy.app` with Samsung Developer ID cert +- Uses hardened runtime (`--options runtime`) +- Signs inside-out (binary first, then bundle) +- Uses `--timestamp` on all codesign calls +- Entitlements from `BuildSupport/Galaxy.entitlements` + +### notarize.sh +- Creates zip of Galaxy.app +- Submits to Apple notary service via `xcrun notarytool submit` +- Uses inline credentials (NOT keychain profile — doesn't work from Galaxy terminal) +- Waits for acceptance, then staples ticket + +### package.sh +- Creates DMG with app + /Applications symlink via `hdiutil` +- Signs the DMG +- Notarizes the DMG (same inline credentials) +- Staples ticket to DMG + +### Entitlements (BuildSupport/Galaxy.entitlements) +- `com.apple.security.network.client` — outbound network +- `com.apple.security.automation.apple-events` — AppleScript +- `com.apple.security.cs.allow-unsigned-executable-memory` — Metal/wgpu shader compilation + +## Known Issues + +1. **Keychain profile doesn't work from Galaxy terminal** — `xcrun notarytool store-credentials` requires interactive macOS keychain authorization dialog. Galaxy (as a non-standard terminal) can't show it. Workaround: inline credentials in scripts. + +2. **hdiutil "Resource busy"** — Sometimes the first `hdiutil create` attempt fails. Scripts retry up to 3 times with 3s delay. + +3. **App-specific password expiration** — Apple app-specific passwords can be revoked from appleid.apple.com. If notarization fails with 401, generate a new one at Sign-In & Security → App-Specific Passwords. + +## macOS Keychain Notes + +If you ever need to use keychain profile approach (e.g., from Terminal.app): +```bash +security unlock-keychain -p 'MACOS_PASSWORD' ~/Library/Keychains/login.keychain-db +xcrun notarytool store-credentials notarytool-profile \ + --apple-id g.brancovici@samsung.com \ + --team-id 3JU72Z7Y3J \ + --password cowi-fved-uajk-arsk +``` + +George's macOS password uses `!` prefix — must be single-quoted in shell to avoid zsh history expansion. diff --git a/migration-docs/current-state.md b/migration-docs/current-state.md new file mode 100644 index 00000000..b35913f4 --- /dev/null +++ b/migration-docs/current-state.md @@ -0,0 +1,63 @@ +# Current State — as of 2026-07-09 + +## Git State + +- **Branch:** `master` +- **HEAD:** `40bd86f6` — "Adding logging when we crash in bedrock, adding open AI request translator changes and AI page settings cleanup" +- **Remote:** Up to date with `origin/master` +- **Other branches:** `feat/warp-parity` (remote only) +- **Tags:** `v1.6.3` (latest) + +## Uncommitted Changes + +Two modified files (NOT yet committed): + +### `notarize.sh` (diff) +```diff +- --keychain-profile notarytool-profile \ ++ --apple-id "g.brancovici@samsung.com" \ ++ --team-id "3JU72Z7Y3J" \ ++ --password "cowi-fved-uajk-arsk" \ +``` + +### `package.sh` (diff) +```diff +- --keychain-profile notarytool-profile \ ++ --apple-id "g.brancovici@samsung.com" \ ++ --team-id "3JU72Z7Y3J" \ ++ --password "cowi-fved-uajk-arsk" \ +``` + +**Why:** The keychain profile `notarytool-profile` was lost (keychain reset). Replaced with inline credentials because Galaxy terminal can't write to keychain (no interactive auth entitlement). These changes have been tested — full build-release.sh completed successfully with them. + +## What Was Just Completed + +- Pulled latest code (840bc4d → 40bd86f6, massive update with Warp rebase) +- Fixed notarization scripts to use inline credentials +- Successfully built a signed+notarized release DMG (`target/release/bundle/osx/Galaxy.dmg`) + +## What's Next (Pending Work) + +### Immediate +- **Commit the script changes** — `notarize.sh` and `package.sh` credential fix (George hasn't asked for commit yet) +- **George may re-run build-release.sh** — he asked for clean build instructions + +### Backlog (from May code review — still open) +1. **[HIGH]** Gate `dump_error_snapshot` behind `GALAXY_BEDROCK_DIAGNOSTICS=1` env var +2. **[HIGH]** Fix `error_dump_directory` using compile-time `CARGO_MANIFEST_DIR` in release builds +3. **[HIGH]** Install script fetches Homebrew/rustup from HEAD without pinning +4. **[MED]** Silent mutex poisoning in `dump_error_snapshot` +5. **[MED]** Captured lines buffer unbounded by bytes +6. **[MED]** `is_retryable` uses fragile string matching +7. **[MED]** `rotate_if_needed` double-renames +8. **[MED]** `read_file_tail` blocks async runtime +9. **[LOW]** Integer overflow in token sum cast to u32 +10. **[LOW]** Race condition in install script's pkill → rm -rf +11. **[LOW]** `git pull --ff-only` fails silently on diverged branches + +## Build Output Location + +``` +target/release/bundle/osx/Galaxy.app # Signed app bundle +target/release/bundle/osx/Galaxy.dmg # Signed + notarized DMG (distributable) +``` diff --git a/migration-docs/project-architecture.md b/migration-docs/project-architecture.md new file mode 100644 index 00000000..0237d54d --- /dev/null +++ b/migration-docs/project-architecture.md @@ -0,0 +1,94 @@ +# Galaxy Project Architecture + +Galaxy is a fork of Warp (the terminal emulator) rebranded under Samsung/Ryan Ward, using **Amazon Bedrock** as sole AI provider instead of Warp's server-side AI. + +**Purpose:** Experiment to run a fully client-side AI terminal where the client calls Bedrock directly without going through the Warp server for AI. Rebranded from "Warp" to "Galaxy" at the crate/binary/config level. + +## Key Facts + +- **Language:** Rust (toolchain 1.92.0, edition 2021) +- **Workspace:** 56 member crates under `crates/` + main `app/` +- **Default binary:** `galaxy-oss` (OSS channel) +- **Channel binaries:** galaxy-oss, galaxy-local, galaxy-stable, galaxy-dev, galaxy-preview +- **Config dir:** `~/.galaxy-ai/` (channel-suffixed: `-dev`, `-oss`) +- **UI Framework:** GalaxyUI (custom, Entity-Component-Handle pattern, Flutter-inspired elements) +- **Database:** SQLite via Diesel ORM +- **Author:** Ryan Ward +- **GitLab:** gitlab.com:samnasbo/shared/galaxy + +## Critical Architecture Decisions + +1. **AI flows through Bedrock exclusively** — `app/src/ai/bedrock/client.rs` (`BedrockClient::converse_stream`) +2. **Models:** Default = Claude Opus 4.6 on Bedrock; also supports Claude Sonnet, Haiku, Nova Pro/Lite/Micro, DeepSeek R1 +3. **Bedrock auth methods:** AWS Profile (default), Static Keys, SSO +4. **Cross-region inference:** Auto-prefixes model IDs (us., eu., jp., apac., au.) based on configured region +5. **Prompt caching:** CachePoints placed on system prompt and second-to-last message + tool config +6. **Tool set:** run_shell_command, read_files, apply_file_diffs, grep, file_glob, suggest_next_prompt +7. **Stream format:** Bedrock ConverseStream events → converted to `warp_multi_agent_api::ResponseEvent` (protobuf-based) +8. **OpenAI/LiteLLM support added** (as of v1.6.3) — new provider alongside Bedrock + +## Directory Layout + +- `app/` — Main binary and application logic + - `app/src/ai/` — AI module (agent, bedrock, mcp, skills, ambient agents, etc.) + - `app/src/ai/bedrock/` — Direct Bedrock client (client.rs, convert.rs, stream.rs, models.rs, convert_request.rs) + - `app/src/settings/ai.rs` — AI settings (Bedrock config, permissions, autoexecution rules) + - `app/src/terminal/` — Terminal emulation + - `app/src/code/` — Code editor mode + - `app/src/workspace/` — Workspace management +- `crates/galaxyui_core/` — Core UI framework (scene, elements, events, fonts, layout) +- `crates/galaxyui/` — Extended UI framework +- `crates/galaxyui_extras/` — UI extras (theming, preferences) +- `crates/galaxy_features/` — Feature flag system (`FeatureFlag` enum, DOGFOOD/PREVIEW/RELEASE tiers) +- `crates/galaxy_terminal/` — Terminal emulation core +- `crates/editor/` — Text editor +- `crates/ai/` — AI library (indexing, project context, codebase embedding) +- `crates/persistence/` — SQLite/Diesel persistence +- `crates/integration/` — Integration test framework + +## Build & Test + +```bash +# Dev run: +cargo run + +# Bundle into .app: +cargo bundle --bin galaxy-oss --package galaxy + +# Full distributable release DMG (compile + sign + notarize + package): +./build-release.sh + +# Full distributable debug DMG: +./build-debug.sh + +# Copy DMGs to ~/Downloads: +./copy-dmgs.sh + +# Presubmit (fmt + clippy + nextest + doc tests): +./script/presubmit + +# Tests only: +cargo nextest run --no-fail-fast --workspace --exclude command-signatures-v2 + +# Clean release build artifacts: +cargo clean --release + +# Clean just bundle output: +rm -rf target/release/bundle/osx/Galaxy.app target/release/bundle/osx/Galaxy.dmg +``` + +## Settings Architecture + +Settings defined via `define_settings_group!` macro. Bedrock settings in TOML at `~/.galaxy-ai/settings.toml`: +- `ai.bedrock.enabled` (default: true) +- `ai.bedrock.auth_method` (profile/static_keys/sso) +- `ai.bedrock.profile` (default: "default") +- `ai.bedrock.region` (auto-detect if empty) +- `ai.bedrock.cross_region_inference` (default: true) +- `ai.bedrock.models` (custom model list, overrides defaults) + +## Feature Flags + +Three-tier rollout: DOGFOOD_FLAGS → PREVIEW_FLAGS → RELEASE_FLAGS (or default in Cargo.toml features). +Runtime check: `FeatureFlag::YourFlag.is_enabled()`. +Defined in `crates/galaxy_features/src/lib.rs`. diff --git a/migration-docs/session-history-may.md b/migration-docs/session-history-may.md new file mode 100644 index 00000000..ac3b477e --- /dev/null +++ b/migration-docs/session-history-may.md @@ -0,0 +1,48 @@ +# Prior Session — 2026-05-13 / 2026-05-14 + +## Tasks Completed + +1. **Codebase learn** — Full read of the Galaxy codebase (56-crate Rust workspace, fork of Warp with Bedrock AI) +2. **Code signing pipeline** — Created complete macOS signing, notarization, and DMG packaging workflow +3. **Review & hardening** — Two rounds of adversarial review + fixes applied +4. **Documentation** — Updated GALAXY.md with signing/diagnostics docs +5. **Code review** — Started adversarial review of last day's committed changes + +## Key Decisions + +- **Entitlements:** `network.client` + `automation.apple-events` + `cs.allow-unsigned-executable-memory` (for Metal/wgpu shader compilation under hardened runtime) +- **Signing approach:** Simple standalone scripts (sign.sh, notarize.sh, package.sh) rather than adapting Warp's 800-line CI bundle script +- **Signing method:** Inside-out (binary first, then bundle) with `--timestamp` on all codesign calls +- **Architecture:** arm64 only (no universal binary needed) +- **Bundle ID:** `com.samsung.Galaxy` +- **Certificate:** `Developer ID Application: SAMSUNG ELECTRONICS AMERICA, INC. (3JU72Z7Y3J)` + +## Files Created + +- `BuildSupport/Galaxy.entitlements` — macOS entitlements for code signing +- `sign.sh` — Code signs Galaxy.app with Samsung Developer ID cert + hardened runtime +- `notarize.sh` — Submits to Apple notary service + staples ticket +- `package.sh` — Creates DMG + signs + notarizes + staples +- `build-debug.sh` — Full pipeline orchestration (debug) +- `build-release.sh` — Full pipeline orchestration (release) +- `copy-dmgs.sh` — Copies DMGs to ~/Downloads with date+letter suffix +- `GALAXY.md` — Updated with signing pipeline + diagnostics documentation + +## Code Review Findings (STILL OPEN) + +### High Severity +1. **[Security] `dump_error_snapshot` writes full conversation context to world-readable files** — Error dumps include user's shell command outputs, secrets potentially in conversation. Recommendation: gate behind `GALAXY_BEDROCK_DIAGNOSTICS=1` or set 0600 permissions. +2. **[Security] `error_dump_directory` uses compile-time `CARGO_MANIFEST_DIR`** — Points to build machine path in release builds. Should be gated behind `cfg!(debug_assertions)`. +3. **[Security] Install script fetches Homebrew/rustup from HEAD without pinning** — Supply chain risk in curl-pipe-bash context. + +### Medium Severity +4. **[Robustness] Silent mutex poisoning in `dump_error_snapshot`** — Partial data written without indication. +5. **[Performance] Captured lines buffer unbounded by bytes** — Single "line" can be several MB for large contexts. +6. **[Correctness] `is_retryable` uses fragile string matching** — `"Validation error"` may not appear in stream errors. +7. **[Correctness] `rotate_if_needed` double-renames** — Off-by-one: current file renamed twice (harmless but confused logic). +8. **[Robustness] `read_file_tail` blocks async runtime** — 200KB sync I/O per file on potentially slow filesystem. + +### Low Severity +9. Integer overflow in token sum cast to u32 +10. Race condition in install script's pkill → rm -rf sequence +11. `git pull --ff-only` fails silently on diverged branches diff --git a/migration-docs/user-preferences.md b/migration-docs/user-preferences.md new file mode 100644 index 00000000..45bc8d09 --- /dev/null +++ b/migration-docs/user-preferences.md @@ -0,0 +1,32 @@ +# User Preferences — George Brancovici + +## Communication Style + +- **Direct and terse.** Don't over-explain. Don't apologize. Don't ask unnecessary questions. +- **Just do it.** When he says "run this shit yourself" — run it. Don't suggest he do it. +- **Don't be precious.** He'll curse, be blunt, call you out. Roll with it and deliver. +- **No hand-holding.** He's a senior engineer. Don't explain basic concepts. +- **Action over discussion.** When something needs doing, do it. Don't present 3 options and ask which one. + +## Work Patterns + +- Works in Galaxy terminal (the app he's building) — this means some macOS interactive features (keychain dialogs, etc.) won't work from within it +- Uses zsh +- Samsung employee (g.brancovici@samsung.com) +- Works on macOS (arm64/Apple Silicon) +- Python env: py312 + +## Technical Preferences + +- Prefers simple standalone scripts over complex CI pipelines +- arm64 only — no universal binary +- Inline credentials over keychain profiles (pragmatic, gets the job done) +- Release builds matter — he distributes the DMG + +## What NOT to Do + +- Don't ask "want me to X?" when the answer is obvious from context +- Don't explain what went wrong in 3 paragraphs — say it in 1 sentence +- Don't suggest he do things himself unless there's a genuine technical blocker (interactive auth, etc.) +- Don't add caveats and disclaimers to every suggestion +- Don't say "I apologize" — just fix it diff --git a/notarize.sh b/notarize.sh index cf748387..9a8846f9 100755 --- a/notarize.sh +++ b/notarize.sh @@ -29,7 +29,9 @@ ditto -c -k --keepParent "$APP_PATH" "$ZIP_PATH" echo "Submitting to Apple notary service (this may take a few minutes)..." RESULT=$(xcrun notarytool submit "$ZIP_PATH" \ - --keychain-profile notarytool-profile \ + --apple-id "g.brancovici@samsung.com" \ + --team-id "3JU72Z7Y3J" \ + --password "cowi-fved-uajk-arsk" \ --wait 2>&1) echo "$RESULT" diff --git a/package.sh b/package.sh index f0583931..07c56fe2 100755 --- a/package.sh +++ b/package.sh @@ -57,7 +57,9 @@ codesign --force --sign "$SIGNING_IDENTITY" --timestamp "$DMG_PATH" echo "Submitting DMG to Apple notary service..." RESULT=$(xcrun notarytool submit "$DMG_PATH" \ - --keychain-profile notarytool-profile \ + --apple-id "g.brancovici@samsung.com" \ + --team-id "3JU72Z7Y3J" \ + --password "cowi-fved-uajk-arsk" \ --wait 2>&1) echo "$RESULT"