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
23 changes: 23 additions & 0 deletions docs/ios-privacy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# OpenMausMobile privacy

OpenMausMobile is a companion for an OpenMausBot service chosen and operated by the user.

## Data handling

- The app stores the selected computer address in iOS preferences and its pairing token in the iOS Keychain.
- Messages, approvals, transcript searches, exports, and screen images travel directly between the phone and that computer.
- OpenMausBot stores transcripts on that computer. The app does not send the developer a cloud copy.
- The app contains no advertising, analytics, tracking, or third-party SDKs.
- The app does not sell personal information.

Local-network connections should only be used on a network the user trusts. For remote access, the project recommends Tailscale so traffic is protected by the user's tailnet. Tailscale is a separate service with its own privacy terms.

If optional hosted services are introduced later, this policy and the App Store privacy disclosure will be updated before those services ship.

## Control and deletion

Unpairing removes the connection and pairing token from the phone. Revoking the phone in OpenMausBot's Companion settings prevents that credential from reaching the computer. Transcript deletion is controlled by the OpenMausBot installation that stores it.

## Support

Questions or privacy requests can be opened at [OpenMausBot Support](https://github.com/milind-soni/OpenMausBot/issues).
23 changes: 23 additions & 0 deletions ios/App/PrivacyInfo.xcprivacy
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSPrivacyTracking</key>
<false/>
<key>NSPrivacyTrackingDomains</key>
<array/>
<key>NSPrivacyCollectedDataTypes</key>
<array/>
<key>NSPrivacyAccessedAPITypes</key>
<array>
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategoryUserDefaults</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>CA92.1</string>
</array>
</dict>
</array>
</dict>
</plist>
11 changes: 11 additions & 0 deletions ios/App/Session.swift
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,17 @@ final class Session: ObservableObject {

init() {
_ = NotificationCoordinator.shared
#if DEBUG
if ProcessInfo.processInfo.arguments.contains("-store-preview"),
let url = Bundle.main.url(forResource: "StorePreview", withExtension: "json"),
let data = try? Data(contentsOf: url),
let fleet = try? JSONDecoder().decode(Fleet.self, from: data) {
connection = Connection(name: "Preview Mac", host: "preview.tailnet.ts.net", port: 8810)
state.hydrate(fleet)
status = .live
return
}
#endif
restore()
Task { await refreshNotificationAuthorization() }
}
Expand Down
77 changes: 77 additions & 0 deletions ios/App/StorePreview.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
{
"bots": [
{
"id": "preview-scout",
"threadId": "preview-thread-scout",
"name": "Scout",
"title": "Researcher",
"description": "Finds the facts and brings back sources.",
"notifications": true,
"color": "cyan",
"unread": true,
"modelSelection": { "instanceId": "preview", "model": "preview" },
"createdAt": 1787000000000,
"activeLeafId": "scout-approval",
"tasks": [
{ "threadId": "preview-thread-scout", "title": "iOS launch research", "createdAt": 1787000000000 }
],
"messages": [
{ "id": "scout-user", "role": "user", "kind": "text", "at": 1787028500000, "text": "Compare the final TestFlight checklist with Apple’s requirements." },
{ "id": "scout-reply", "role": "bot", "kind": "text", "at": 1787028580000, "parentId": "scout-user", "text": "I checked signing, privacy declarations, review notes, and the real-device test pass. One action needs your approval before I continue." },
{
"id": "scout-approval",
"role": "bot",
"kind": "options",
"at": 1787028640000,
"parentId": "scout-reply",
"card": {
"title": "Approval needed",
"subtitle": "Upload build 1 to TestFlight for internal testing?",
"options": ["Allow", "Deny"],
"requestId": "preview-request",
"tool": "App Store Connect",
"allowKey": "testflight:upload"
}
}
]
},
{
"id": "preview-pixel",
"threadId": "preview-thread-pixel",
"name": "Pixel",
"title": "Designer",
"description": "Shapes polished product experiences.",
"notifications": true,
"color": "purple",
"unread": false,
"modelSelection": { "instanceId": "preview", "model": "preview" },
"createdAt": 1786900000000,
"activeLeafId": "pixel-reply",
"tasks": [{ "threadId": "preview-thread-pixel", "title": "App Store screenshots", "createdAt": 1786900000000 }],
"messages": [
{ "id": "pixel-user", "role": "user", "kind": "text", "at": 1787028100000, "text": "Prepare the App Store screenshots." },
{ "id": "pixel-reply", "role": "bot", "kind": "text", "at": 1787028200000, "parentId": "pixel-user", "text": "The iPhone roster and approval flow are ready for the product page." }
]
},
{
"id": "preview-forge",
"threadId": "preview-thread-forge",
"name": "Forge",
"title": "Engineer",
"description": "Builds and verifies releases.",
"notifications": true,
"color": "orange",
"unread": false,
"busy": true,
"modelSelection": { "instanceId": "preview", "model": "preview" },
"createdAt": 1786800000000,
"activeLeafId": "forge-reply",
"tasks": [{ "threadId": "preview-thread-forge", "title": "Release build", "createdAt": 1786800000000 }],
"messages": [
{ "id": "forge-user", "role": "user", "kind": "text", "at": 1787027800000, "text": "Run the complete release verification." },
{ "id": "forge-reply", "role": "bot", "kind": "text", "at": 1787027900000, "parentId": "forge-user", "text": "Building the signed archive and checking the privacy manifest…" }
]
}
],
"groups": []
}
33 changes: 33 additions & 0 deletions ios/AppStore/RELEASE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# TestFlight and App Store release

The app is native Swift and uses XcodeGen; EAS commands do not apply.

## One-time Apple setup

1. Enrol in the Apple Developer Program.
2. Register the bundle ID `com.openmausbot.companion` (or change it in `project.yml` before the first upload).
3. Create the matching app in App Store Connect with the name **OpenMaus Mobile**, primary category **Productivity**, and a unique SKU.
4. Create or select an Apple Distribution certificate and App Store provisioning profile.
5. Add the review contact details in App Store Connect; do not commit private contact data or App Store Connect keys.

## Before every upload

1. Run `swift test` from `ios/` and the repository test suite.
2. Generate the Xcode project with `xcodegen generate` from `ios/`.
3. Set `DEVELOPMENT_TEAM` for the Release configuration in Xcode or on the archive command line.
4. Increment `CURRENT_PROJECT_VERSION` for every upload. Update `MARKETING_VERSION` only for a new App Store version.
5. Archive a generic iOS device build and validate it in Xcode Organizer.
6. Upload to App Store Connect and distribute to internal TestFlight testers first.
7. Complete a real-iPhone pass for pairing, Bonjour permission, Keychain restore, Tailscale, approvals, background/foreground reconciliation, and transcript sharing.
8. After internal testing, submit to an external TestFlight group before App Review.

## App Store Connect

- Copy the localized text from `en-US/`.
- Use `privacy-answers.md` and verify it still matches the binary.
- Use `review-notes.md`, adding a real review contact in App Store Connect.
- Support URL: `https://github.com/milind-soni/OpenMausBot/issues`
- Privacy policy URL: `https://github.com/milind-soni/OpenMausBot/blob/main/docs/ios-privacy.md`
- Choose manual release for 1.0; enable a phased release after the first production build is stable.

The unsigned simulator CI proves compilation, not distribution signing. A TestFlight upload cannot be automated until the Apple team, App Store Connect record, and protected signing/API-key secrets exist.
26 changes: 26 additions & 0 deletions ios/AppStore/en-US/description.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
OpenMausMobile is the private iPhone companion for OpenMausBot on your computer.

Keep your AI team moving when you step away from your desk:

• Answer approvals and questions
• Follow replies as they stream
• Send messages to bots and rooms
• Switch and manage task contexts
• Search the complete local transcript history
• Edit messages and move between conversation versions
• Share transcripts as Markdown or JSON
• Watch a bot’s computer when you need context

YOUR COMPUTER STAYS IN CHARGE

OpenMausMobile connects directly to the companion service on your own computer. Your bot transcripts remain in OpenMausBot’s local storage; this app does not upload a cloud copy to the developer.

PAIR ONCE, REVOKE ANY TIME

Pair with a short-lived code from OpenMausBot’s Companion panel. The computer stores only a hash of the phone credential and lets you revoke the device at any time.

USE IT AT HOME OR AWAY

Bonjour finds your computer on a trusted local network. For private remote access, install Tailscale on both devices and connect with the computer’s MagicDNS name.

Requires OpenMausBot running on a Mac, Windows, or Linux computer. Tailscale is optional and is not affiliated with OpenMausBot.
1 change: 1 addition & 0 deletions ios/AppStore/en-US/keywords.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ai,agent,assistant,automation,developer,chat,workflow,approval,remote,productivity
1 change: 1 addition & 0 deletions ios/AppStore/en-US/promotional_text.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Stay close to your OpenMausBot team: answer approvals, follow work, search conversations, and keep tasks moving from your iPhone.
7 changes: 7 additions & 0 deletions ios/AppStore/en-US/release_notes.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Welcome to OpenMausMobile 1.0.

• Pair securely with your OpenMausBot computer
• Chat with bots and rooms
• Answer approvals and questions
• Search, manage tasks, edit versions, react, and share transcripts
• Follow live work and reconnect without losing events
1 change: 1 addition & 0 deletions ios/AppStore/en-US/subtitle.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Your AI team, in your pocket
11 changes: 11 additions & 0 deletions ios/AppStore/privacy-answers.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# App Privacy answers

Use these answers for version 1.0, provided the shipped binary still matches this repository.

- Tracking: **No**
- Data linked to the user: **None collected by the developer**
- Data not linked to the user: **None collected by the developer**
- Third-party advertising or analytics SDKs: **None**
- Privacy policy URL: `https://github.com/milind-soni/OpenMausBot/blob/main/docs/ios-privacy.md`

The app sends messages, pairing credentials, and transcript requests directly to the OpenMausBot companion service selected by the user. That computer is the user's endpoint; the project does not receive a cloud copy. If a hosted push relay or analytics is added, these answers and `PrivacyInfo.xcprivacy` must be revised before upload.
15 changes: 15 additions & 0 deletions ios/AppStore/review-notes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# App Review notes

OpenMausMobile is a companion for the OpenMausBot desktop application and does not use a developer-hosted login.

To review the app:

1. Install and start OpenMausBot on a Mac, Windows, or Linux computer.
2. Open **Settings → Companion**, enable the companion, and choose **Start pairing**.
3. On the iPhone, select the discovered computer or enter the address shown by the desktop panel.
4. Enter the six-digit pairing code.
5. Create a bot on the desktop or with the `+` button in the iPhone roster, then send a message.

The phone and computer must be on the same trusted network. Alternatively, both may be signed into the same Tailscale network and the reviewer may enter the computer's `.ts.net` MagicDNS name.

No purchase or subscription is required. The computer is the source of bot data and credentials; the developer cannot provide a universal demo account without routing reviewers into someone else's private computer.
3 changes: 3 additions & 0 deletions ios/AppStore/screenshots/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# App Store screenshots

`iPhone-6.9-roster.png` is captured from the Debug-only `-store-preview` fixture on an iPhone 17 Pro simulator. Re-capture it after any material roster or approval UI change, and capture the remaining product-page screens from a real paired device before submission.
Binary file added ios/AppStore/screenshots/iPhone-6.9-roster.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 5 additions & 1 deletion ios/project.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ targets:
settings:
base:
PRODUCT_BUNDLE_IDENTIFIER: com.openmausbot.companion
MARKETING_VERSION: "0.1.0"
MARKETING_VERSION: "1.0.0"
CURRENT_PROJECT_VERSION: "1"
SWIFT_VERSION: "5.9"
TARGETED_DEVICE_FAMILY: "1,2"
Expand All @@ -45,6 +45,10 @@ targets:
# purpose: someone may well have both, and two identical labels on
# one person's devices is a small cruelty.
CFBundleDisplayName: OpenMausMobile
CFBundleShortVersionString: $(MARKETING_VERSION)
CFBundleVersion: $(CURRENT_PROJECT_VERSION)
LSApplicationCategoryType: public.app-category.productivity
ITSAppUsesNonExemptEncryption: false
# REQUIRED, and easy to lose. Without a launch screen iOS runs the
# app in compatibility scaling: letterboxed inside black bars, with
# everything drawn oversized, on every modern iPhone. An empty
Expand Down
Loading