Skip to content
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
35 changes: 34 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,38 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [0.0.16] - 2026-07-26

### Added

- Native iPhone notification registration now belongs to the signed-in 1Helm
profile. Background channel and resident-agent updates use a
durable, retryable, idempotent delivery queue, honor global sound and
per-channel mute choices, skip the author, encrypt device tokens in the push
relay, and open the relevant channel or thread when tapped.
- Settings → Notifications now lets a phone owner explicitly request system
notification permission, see whether the current phone is registered, and
turn registration off without changing another device.

### Changed

- Phone channel chrome now uses two calm rows: hamburger and channel name on
top, then a right-aligned row for Favorite, Router, resident status,
Terminal, Notes, and Skipper. Desktop remains one compact row, and every
phone action retains a 44-point target without horizontal overflow.
- The native iOS status surface matches the current light or dark page header
behind the Dynamic Island while WebView controls remain physically below the
system indicators.

### Fixed

- Choosing **Take Photo or Video** from a message attachment no longer causes
iOS to terminate 1Helm. Camera, photo-library, and video-microphone access now
have narrow user-facing privacy declarations tied to explicit attachment
actions.
- The Notes top bar shares the mobile surface treatment and keeps **New note**
and **Close** visible on a 390-point phone viewport.

## [0.0.15] - 2026-07-26

### Fixed
Expand Down Expand Up @@ -406,7 +438,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
notarization, stapled tickets, Gatekeeper verification, persistent
Application Support, and isolated Apple container machines.

[Unreleased]: https://github.com/gitcommit90/1Helm/compare/v0.0.15...HEAD
[Unreleased]: https://github.com/gitcommit90/1Helm/compare/v0.0.16...HEAD
[0.0.16]: https://github.com/gitcommit90/1Helm/releases/tag/v0.0.16
[0.0.15]: https://github.com/gitcommit90/1Helm/releases/tag/v0.0.15
[0.0.14]: https://github.com/gitcommit90/1Helm/releases/tag/v0.0.14
[0.0.13]: https://github.com/gitcommit90/1Helm/releases/tag/v0.0.13
Expand Down
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,10 @@ Android Keystore.
server, and do not retain host data or provider credentials beyond the
selected server address and secure session token. Use **Disconnect** in the
profile menu to erase both from the device.
- iPhone notifications are opt-in under **Settings → Notifications**. Device
registration belongs to the signed-in account, per-channel mute still wins,
and tapping an update opens its channel or thread. iOS camera and photo
access is requested only after an explicit attachment action.

## Ready on day one. Specialized by day one hundred.

Expand Down Expand Up @@ -282,7 +286,7 @@ A fresh data directory opens first-run setup. The source runtime defaults to
| `PORT` | `8123` | HTTP/WebSocket control-plane port. |
| `CTRL_DATA_DIR` | `./data` | Databases, routing state, uploads, and narrow workspace mirrors. |
| `HELM_CHANNEL_COMPUTER_BACKEND` | `apple` on macOS, `lxc` on Linux, `wsl` on Windows | Host isolation backend; `native` and `mock` are explicit development/test overrides. |
| `HELM_CHANNEL_MACHINE_IMAGE` | `local/1helm-channel-machine:0.0.15` | Versioned channel-machine image contract. |
| `HELM_CHANNEL_MACHINE_IMAGE` | `local/1helm-channel-machine:0.0.16` | Versioned channel-machine image contract. |

### Agent-first JSON CLI

Expand Down
1 change: 1 addition & 0 deletions android/app/capacitor.build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ dependencies {
implementation project(':capacitor-app')
implementation project(':capacitor-browser')
implementation project(':capacitor-keyboard')
implementation project(':capacitor-push-notifications')
implementation project(':capacitor-splash-screen')
implementation project(':capacitor-status-bar')

Expand Down
2 changes: 2 additions & 0 deletions android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,6 @@

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
</manifest>
3 changes: 3 additions & 0 deletions android/capacitor.settings.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ project(':capacitor-browser').projectDir = new File('../node_modules/@capacitor/
include ':capacitor-keyboard'
project(':capacitor-keyboard').projectDir = new File('../node_modules/@capacitor/keyboard/android')

include ':capacitor-push-notifications'
project(':capacitor-push-notifications').projectDir = new File('../node_modules/@capacitor/push-notifications/android')

include ':capacitor-splash-screen'
project(':capacitor-splash-screen').projectDir = new File('../node_modules/@capacitor/splash-screen/android')

Expand Down
7 changes: 5 additions & 2 deletions capacitor.config.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"appName": "1Helm",
"webDir": "public",
"loggingBehavior": "none",
"backgroundColor": "#08090c",
"backgroundColor": "#111318",
"zoomEnabled": false,
"appendUserAgent": " 1HelmMobile",
"server": {
Expand Down Expand Up @@ -48,7 +48,10 @@
"StatusBar": {
"overlaysWebView": false,
"style": "DEFAULT",
"backgroundColor": "#08090c"
"backgroundColor": "#111318"
},
"PushNotifications": {
"presentationOptions": []
}
}
}
26 changes: 26 additions & 0 deletions cloudflare/migrations/0002_mobile_push.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
CREATE TABLE IF NOT EXISTS push_installations (
installation_id TEXT PRIMARY KEY,
management_secret_hash TEXT NOT NULL,
created_at INTEGER NOT NULL,
updated_at INTEGER NOT NULL
);
CREATE TABLE IF NOT EXISTS push_devices (
id INTEGER PRIMARY KEY AUTOINCREMENT,
installation_id TEXT NOT NULL REFERENCES push_installations(installation_id) ON DELETE CASCADE,
recipient_id TEXT NOT NULL,
platform TEXT NOT NULL,
token_hash TEXT NOT NULL,
token_cipher TEXT NOT NULL,
created_at INTEGER NOT NULL,
updated_at INTEGER NOT NULL,
UNIQUE(installation_id,platform,token_hash)
);
CREATE INDEX IF NOT EXISTS idx_push_devices_recipient ON push_devices(installation_id,recipient_id);
CREATE TABLE IF NOT EXISTS push_deliveries (
installation_id TEXT NOT NULL REFERENCES push_installations(installation_id) ON DELETE CASCADE,
idempotency_key TEXT NOT NULL,
recipient_id TEXT NOT NULL,
delivered_count INTEGER NOT NULL DEFAULT 0,
created_at INTEGER NOT NULL,
PRIMARY KEY (installation_id,idempotency_key)
);
27 changes: 27 additions & 0 deletions cloudflare/schema.sql
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,30 @@ CREATE TABLE IF NOT EXISTS feedback_attachments (
data TEXT NOT NULL,
created_at INTEGER NOT NULL
);

CREATE TABLE IF NOT EXISTS push_installations (
installation_id TEXT PRIMARY KEY,
management_secret_hash TEXT NOT NULL,
created_at INTEGER NOT NULL,
updated_at INTEGER NOT NULL
);
CREATE TABLE IF NOT EXISTS push_devices (
id INTEGER PRIMARY KEY AUTOINCREMENT,
installation_id TEXT NOT NULL REFERENCES push_installations(installation_id) ON DELETE CASCADE,
recipient_id TEXT NOT NULL,
platform TEXT NOT NULL,
token_hash TEXT NOT NULL,
token_cipher TEXT NOT NULL,
created_at INTEGER NOT NULL,
updated_at INTEGER NOT NULL,
UNIQUE(installation_id,platform,token_hash)
);
CREATE INDEX IF NOT EXISTS idx_push_devices_recipient ON push_devices(installation_id,recipient_id);
CREATE TABLE IF NOT EXISTS push_deliveries (
installation_id TEXT NOT NULL REFERENCES push_installations(installation_id) ON DELETE CASCADE,
idempotency_key TEXT NOT NULL,
recipient_id TEXT NOT NULL,
delivered_count INTEGER NOT NULL DEFAULT 0,
created_at INTEGER NOT NULL,
PRIMARY KEY (installation_id,idempotency_key)
);
Loading
Loading