Skip to content
This repository was archived by the owner on Nov 12, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions .github/workflows/verification-codes.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
name: Native verification code offers
on:
workflow_dispatch:
pull_request:
paths:
- mseries/phone-setup/*code*.py
- mseries/install-verification-codes.sh
- .github/workflows/verification-codes.yml
jobs:
codes:
name: Private native field insertion and shortcut preservation (arm64)
runs-on: ubuntu-26.04-arm
timeout-minutes: 10
steps:
- uses: actions/checkout@v7
- uses: actions/checkout@v7
with:
repository: erikwb/blueferry
ref: 60fd7ef1abbd25947981f0cf27a521d82784a75f
path: .code-test-blueferry
- name: Install native fixture dependencies
run: sudo apt-get update && sudo apt-get install -y python3-gi python3-dbus python3-pil gir1.2-gtk-4.0 gir1.2-atspi-2.0 libgranite-7-dev at-spi2-core dbus-x11 xvfb xauth xdotool gsettings-desktop-schemas gnome-settings-daemon-common shellcheck
- name: Check models, actual field editing and settings in isolation
env:
PYTHONPATH: ${{ github.workspace }}/.code-test-blueferry/src
run: |
bash -n mseries/install-verification-codes.sh
shellcheck mseries/install-verification-codes.sh
python3 mseries/phone-setup/check_verification_codes.py
2 changes: 1 addition & 1 deletion docs/features.html
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ <h2>Omarchy M-series enhancements</h2>
<tr><td>Function-key mode</td><td class="part">Differs</td><td>Running with media keys first (fnmode=1); upstream uses the kernel default (auto). Awaiting a deliberate choice.</td></tr>
<tr><td>Microphone mapping</td><td class="no">Not ported</td><td>Needs re-homing to elementary's audio session.</td></tr>
<tr><td>iCloud password sync</td><td class="part">Options documented</td><td>No official Linux client. Unofficial read-only tools exist but sign in with your Apple ID and are new; a one-way export into a cross-platform password manager is the safest path. The owner leans to a Brave extension (icp supports Brave) or Brave Sync.</td></tr>
<tr><td>iMessage / SMS</td><td class="part">Working on this desktop</td><td>BlueFerry with a nearby iPhone: actual outgoing and incoming texts verified on J314S, iPhone 14 Pro / iOS 27.0.1, scoped BlueZ 5.87. Native GTK/Granite Messages adds conversations, contacts/photos, a composer and bounded recent-inbox refresh. Ordered Apple-pin snapshot import is implemented; actual owner Mac export and automatic pin sync remain unqualified. Full iCloud history, reboot/suspend recovery and factory-image installation are not qualified. No Mac relay is required for texting. Local Codex MCP cache reads and a phone mark-unread patch are also verified; full unread parity and automatic iMessage pin matching remain incomplete.</td></tr>
<tr><td>iMessage / SMS</td><td class="part">Working on this desktop</td><td>BlueFerry with a nearby iPhone: actual outgoing and incoming texts verified on J314S, iPhone 14 Pro / iOS 27.0.1, scoped BlueZ 5.87. Native GTK/Granite Messages adds conversations, contacts/photos, a composer and bounded recent-inbox refresh. Near-pointer verification-code helper supports native field insertion and explicit browser copy in isolated fixtures; live sign-in qualification remains open. Four-across contact favorites and a separator accompany ordered Apple-pin snapshot import; actual owner Mac export and automatic pin sync remain unqualified. Full iCloud history, reboot/suspend recovery and factory-image installation are not qualified. No Mac relay is required for texting. Local Codex MCP cache reads and a phone mark-unread patch are also verified; full unread parity and automatic iMessage pin matching remain incomplete.</td></tr>
<tr><td>Hardware video decode</td><td class="no">Missing</td><td>Needs AVD kernel support, firmware and a VA-API bridge.</td></tr>
<tr><td>Touch ID</td><td class="no">Blocked upstream</td><td>No public Linux code exists. Omarchy lists it as not in its first release and Asahi lists it as to be announced. A watcher reports when that changes.</td></tr>
<tr><td>Windows taskbar CodexBar</td><td>Native quota popup beside Wi-Fi with separate grouping, 56% larger text, and bundled Windows Start menu. Canonical build checks preserve the complete taskbar, hover popup and Teams/Outlook running markers.</td><td>Local integration loaded; persistence CI</td></tr>
Expand Down
39 changes: 39 additions & 0 deletions mseries/OS9-HANDOFF.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,44 @@
# OS 9 implementation / Claude Code handoff

## Native favorites and visible Messages launcher — 2026-10-20

Owner requests: four favorite contact icons per row in the contacts sidebar,
with a horizontal divider before ordinary conversations. Implemented ordered
GTK grid with photos/initials, names/tooltips, selected state and search reflow;
thread switching keeps drafts. 15 private Messages GUI tests pass, including
four-column wrapping, divider visibility, favorite routing and draft retention.
Light/dark/narrow fixtures reviewed. Native installer passed and staged sources;
Messages PID 263569 remained running, so grid loads at next launch.

Fixed missing launcher icon: user hicolor theme lacked index.theme/cache.
Installer preserves an existing index or installs the standard hicolor index,
updates the scoped cache, and adds TryExec. GIO reports Messages visible;
GTK resolves our SVG, and launching the desktop entry brings up the existing
window. No panel/dock restart. Verification Codes is installed/enabled/active;
shortcut Shift+Super+V. 17 isolated code checks pass including real Return-to-field
and Brave explicit clipboard copy/no DOM change/no form submit. Live code
insertion/pointer placement remains unqualified. No real texts sent.

## Apple pins merged; verification-code helper qualification — 2026-10-20

PR #349 merged as `6b1d520c675a227394b5a5a88298083f71e81657`; final head
`2621ffe` passed every applicable check. Last macOS ARM runner initially failed
allocation (capacity annotations, no code run), then passed on retry. ARM macOS
15/26 and Intel 26 fixtures all pass. SIP-enabled owner export/import is still
open; use the small kit in `phone-setup/macos-visit/README.md`. Installed importer
loads next Messages launch; the owner's current window/drafts remain protected.

Verification-code helper candidate uses GTK/Granite near-pointer cards, parsed
shortcut collision checks and AT-SPI field editing. Fixed GTK rejecting
Component.GrabFocus despite accepting EditableText.SetTextContents. Private
Brave testing exposed the absent EditableText bridge; browser mode explicitly
copies/closes instead of promising insertion. Chromium source confirms that
interface gap. No global runtime key injection, automatic clipboard copy or form
submission. Optional browser tests use their own profile/debug endpoint and
synthetic contents only, never the owner's browser. Source/limits and exact
checks: `phone-setup/VERIFICATION-CODES.md`. Owner-field/pointer/compositor and
session restart qualification remains open. No real text sent for these tests.

## Apple pin cache read/export passes on ARM and Intel macOS — 2026-10-20

PR #349 now reads IMCore's local getter and falls back to Apple's canonical
Expand Down
28 changes: 22 additions & 6 deletions mseries/ROADMAP.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,23 @@
# Roadmap, features and follow-ups (MacBook Pro 14" M1 Pro, elementary OS 9 on Asahi)

## Four-across contact favorites and Applications launcher — 2026-10-20

Favorites now use a four-column photo/initials grid above ordinary conversations,
with a themed horizontal separator. Search reflows tiles; selection preserves
drafts. 15 private GTK tests pass; light/dark/narrow fixtures reviewed. Installed
for next Messages launch. Applications entry is visible and missing icon fixed
by the scoped hicolor index/cache. No panel/dock restart.

## Verification-code offers — 2026-10-20

Installed/enabled helper adds near-pointer code cards, an available shortcut and explicit
AT-SPI field insertion. Native keyboard-to-field and private Brave copy-only
paths are covered by synthetic fixtures; direct Chromium fill needs an extension.
Offers are memory-only, expire in five minutes and respect SMS domain binding.
Installer/uninstaller preserves unrelated shortcuts and existing Messages/phone
services. Owner-field/compositor placement/focus qualification remains open.
See [implementation and limits](phone-setup/VERIFICATION-CODES.md).

## PR #343 source-merge qualification passed — 2026-10-20

Production GTK launcher controls pass light/dark visual inspection and real
Expand Down Expand Up @@ -61,12 +79,10 @@ account/FDA/SIP-enabled access and NAS transfer remain unverified. Updated small
kit performs no security changes and retains source modification time. The
earlier process-gate interpretation below is superseded by this result.

Candidate PR #349 adds the ordered native import/review and encrypted mapping
store, staged for next Messages launch. The original IMCore reader passes macOS
runtime fixtures; its real runner probe reports the standalone process unsupported
and no initialized pin configuration. Resolve that access gate before promising
an owner export or another successful macOS trip. The source and validation record
below now distinguishes implemented importer mechanics from unqualified pin access.
PR #349 merged as `6b1d520c675a227394b5a5a88298083f71e81657` after all checks
passed. Ordered native import/review and encrypted mapping storage are staged
for next Messages launch. Owner account export, SIP-enabled access and actual
transfer/import remain unqualified; no successful owner macOS trip is promised.

Open feature: native Pin/Unpin, a qualified ordered Mac snapshot import, then
direct Linux synchronization of Apple's pin-settings store. Research found
Expand Down
12 changes: 11 additions & 1 deletion mseries/install-phone-setup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,20 @@ install -m644 "$here/phone-setup/message_pins.py" "$root/message_pins.py"
icons=${XDG_DATA_HOME:-$HOME/.local/share}/icons/hicolor/scalable/apps
install -d "$icons"
install -m644 "$here/phone-setup/io.elementary.mseries.Messages.svg" "$icons/io.elementary.mseries.Messages.svg"
icon_theme=${XDG_DATA_HOME:-$HOME/.local/share}/icons/hicolor
if [[ ! -f "$icon_theme/index.theme" ]]; then
install -m644 /usr/share/icons/hicolor/index.theme "$icon_theme/index.theme"
fi
gtk4-update-icon-cache -f "$icon_theme" >/dev/null 2>&1 || true
# Pairing capability checks must use the client matching our scoped BlueZ service.
for pair in 'mseries-phone-setup:phone-setup.py' 'mseries-messages:messages.py'; do
launcher=${pair%%:*}
entry=${pair#*:}
rm -f "$HOME/.local/bin/$launcher"
python3 - "$HOME/.local/bin/$launcher" <<'PY'
from pathlib import Path
import sys
Path(sys.argv[1]).unlink(missing_ok=True)
PY
cat > "$HOME/.local/bin/$launcher" <<LAUNCHER
#!/bin/sh
if [ -f /etc/systemd/system/bluetooth.service.d/91-mseries-bluez-587.conf ]; then
Expand Down Expand Up @@ -55,6 +64,7 @@ Exec="$HOME/.local/bin/mseries-messages"
Icon=io.elementary.mseries.Messages
Categories=Network;Chat;
Keywords=iPhone;iMessage;SMS;BlueFerry;
TryExec=$HOME/.local/bin/mseries-messages
StartupNotify=true
Terminal=false
DESKTOP
Expand Down
64 changes: 64 additions & 0 deletions mseries/install-verification-codes.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#!/usr/bin/env bash
set -euo pipefail
here=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)
root=${XDG_DATA_HOME:-$HOME/.local/share}/mseries/phone-setup
units=${XDG_CONFIG_HOME:-$HOME/.config}/systemd/user
apps=${XDG_DATA_HOME:-$HOME/.local/share}/applications
if [[ ${1:-} == --uninstall ]]; then
systemctl --user disable --now mseries-verification-codes.service 2>/dev/null || true
python3 "$here/phone-setup/code_shortcut.py" uninstall "$HOME/.local/bin/mseries-verification-codes" "$root"
python3 - "$root" "$units" "$apps" "$HOME/.local/bin" <<'PYTHON'
from pathlib import Path
import sys
root,units,apps,bins=map(Path,sys.argv[1:])
files=[root/name for name in ('verification_codes.py','code_offers.py','code_fields.py','code_shortcut.py')]
files += [units/'mseries-verification-codes.service', apps/'io.elementary.mseries.VerificationCodes.desktop', bins/'mseries-verification-codes']
for path in files: path.unlink(missing_ok=True)
PYTHON
systemctl --user daemon-reload
update-desktop-database "$apps" 2>/dev/null || true
echo 'Verification Codes removed; Messages and Bluetooth remain running.'
exit 0
fi
[[ $# == 0 ]] || { echo 'Usage: install-verification-codes.sh [--uninstall]' >&2; exit 2; }
python3 -c 'import gi, blueferry; gi.require_version("Gtk", "4.0"); gi.require_version("Granite", "7.0"); gi.require_version("Atspi", "2.0"); gi.require_version("GdkX11", "4.0")'
command -v xdotool >/dev/null
python3 "$here/phone-setup/test_codes.py"
install -d "$root" "$HOME/.local/bin" "$units" "$apps"
install -m644 "$here/phone-setup/code_offers.py" "$here/phone-setup/code_fields.py" "$here/phone-setup/code_shortcut.py" "$root/"
install -m755 "$here/phone-setup/verification_codes.py" "$root/verification_codes.py"
cat > "$HOME/.local/bin/mseries-verification-codes" <<LAUNCHER
#!/bin/sh
export GDK_BACKEND=x11
export GSK_RENDERER=cairo
exec /usr/bin/python3 "$root/verification_codes.py" "\$@"
LAUNCHER
chmod 755 "$HOME/.local/bin/mseries-verification-codes"
cat > "$units/mseries-verification-codes.service" <<UNIT
[Unit]
Description=Verification code suggestions from iPhone messages
After=graphical-session.target blueferry.service
PartOf=graphical-session.target
[Service]
ExecStart="$HOME/.local/bin/mseries-verification-codes" --background
Restart=on-failure
RestartSec=3
UMask=0077
[Install]
WantedBy=graphical-session.target
UNIT
cat > "$apps/io.elementary.mseries.VerificationCodes.desktop" <<DESKTOP
[Desktop Entry]
Type=Application
Name=Verification Codes
Comment=Use a recent iPhone code in the focused verification field
Exec="$HOME/.local/bin/mseries-verification-codes" --show
Icon=dialog-password
Categories=Utility;
Terminal=false
DESKTOP
python3 "$root/code_shortcut.py" install "$HOME/.local/bin/mseries-verification-codes" "$root"
systemctl --user daemon-reload
systemctl --user enable --now mseries-verification-codes.service
update-desktop-database "$apps" 2>/dev/null || true
echo 'Verification Codes installed. Bluetooth and Messages were not restarted.'
12 changes: 10 additions & 2 deletions mseries/phone-setup/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,15 +79,23 @@ window's last snapshot. The app does not download the full iCloud archive or
recover a complete sent history. A real inbox read returned 11 entries on this
phone; a controlled suspend/missed-message/reopen scenario remains unverified.

### Apple Messages pins (candidate)
### Verification-code offers

A separate native helper detects recent SMS verification codes and offers them
near the pointer. Its shortcut activates the card; Enter inserts into a supported
native field, or explicitly copies for Brave. Browser direct fill remains open.
Install/undo, qualification and privacy details: [Verification Codes](VERIFICATION-CODES.md).

### Apple Messages pins

Messages → menu → **Import iPhone Pins…** accepts the private JSON generated by
our macOS Apple pin-store helper. The preview preserves Apple's order and suggests only
unique exact individual-address matches. Choose the current conversation for
ambiguous people or groups; the recipients appear below each choice. Unmatched
pins remain available through **Review Imported Pins…**. Re-importing the same
Apple identifiers retains prior explicit matches even if Apple reorders them.
Pins appear above ordinary conversations with the export time visible. This is
Pins appear as four contact tiles per row above ordinary conversations, with a
horizontal separator, photos/initials and the export time visible. This is
a snapshot, not live phone synchronization, and importing does not send texts
or mark conversations read.

Expand Down
61 changes: 61 additions & 0 deletions mseries/phone-setup/VERIFICATION-CODES.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# Verification codes from iPhone texts

Install `bash mseries/install-verification-codes.sh` after BlueFerry is working.
This adds **Verification Codes** to Applications and a separate user service.
It preserves the running Messages window and Bluetooth services.

Focus a verification-code field. A recent matching code can appear near the
pointer. Press the shortcut printed by the installer (normally **Shift+Super+V**)
to activate the offer, then **Enter** to use it. **Esc** dismisses. The popup shows
the selected field and app. Existing shortcuts are compared as parsed accelerators;
aliases and modifier order count as the same binding. If occupied, the installer
tries Shift+Super+O, then Ctrl+Alt+O; Applications remains available if all are busy.

Native apps that expose AT-SPI EditableText support **Use Code**. Insertion replaces
that exact, revalidated code field and does not press Enter or submit the form.
Passive offers leave partially entered fields alone; the explicit shortcut can
replace a value in a clearly labelled code field. Generic password and message
fields are rejected. Split one-character fields require manual paste.

**Brave currently supports offers and Copy Code, not direct insertion.** Its
Linux accessibility bridge exposes field metadata and Text but not EditableText.
The popup therefore offers **Copy Code** with Enter as its action, closes, and
lets the owner paste. No global typing or automatic clipboard change is used.
Direct browser filling needs a companion extension and is still open work.
This limitation was reproduced with Brave 155.1.97.59 in a private profile;
[Chromium's interface registration](https://chromium.googlesource.com/chromium/src/+/c213438d949dc89f3d8d5df3dec27dcc01d7d027/ui/accessibility/platform/ax_platform_node_auralinux.cc)
also omits EditableText. No Chromium implementation is copied here.

The helper uses upstream BlueFerry's deterministic OTP extraction and its
existing backend, not a second phone connection. It requests at most 20 recent
inbox messages at startup or when the backend event count changes. Offers expire
after five minutes and live only in RAM. This helper writes no message bodies,
codes or recipient metadata to disk/logs; upstream history retains its existing
policy. Only an explicit **Copy Code** action writes the clipboard. Consumed
offers are suppressed for the remaining lifetime of the process. Domain-bound
SMS codes require the exact HTTPS host; embedded-frame bindings are withheld.
Unbound SMS codes have no domain assertion and the destination remains visible.

The popup uses GTK 4/Granite 7 and follows the desktop's light/dark preference.
It runs under XWayland to position near the pointer; Messages remains native
Wayland. `xdotool` reads pointer/display geometry and moves/activates only the
helper's own window. Runtime code insertion uses the field's accessibility API.
No desktop compositor, panel, keyboard driver or browser debug interface is modified.

## Checks and remaining qualification

Run `python3 mseries/phone-setup/check_verification_codes.py` for synthetic-only
model, keyboard-to-native-field, expiry, password rejection and shortcut
preservation checks. `--browser` additionally launches an isolated browser and
checks actual clipboard copy with unchanged DOM input/submit counters. It needs
Brave/Chromium and Python `websockets`. `--screenshots DIR` renders light/dark
and copy-only cards. Tests create a private home, settings backend, D-Bus and
display; they never query the owner's phone or browser profile.

Live owner sign-in insertion, pointer placement/focus on the running compositor,
session restart and all other apps/sites remain qualification work. Synthetic
field and private-browser passes do not establish universal autofill support.

Undo with `bash mseries/install-verification-codes.sh --uninstall`. It removes
only this helper's files/service and its still-owned shortcut, retaining unrelated
bindings, phone pairing, history and the Messages window.
Loading
Loading