You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: CHANGELOG.md
+6-3Lines changed: 6 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -6,6 +6,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
6
6
7
7
## [Unreleased]
8
8
9
+
## [0.3.0] - 2026-08-27
10
+
9
11
### Added
10
12
11
13
- Android-first manual rebuild with shared Compose Multiplatform Send and Receive UI.
@@ -14,7 +16,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
14
16
- Current macOS/Linux DNS-SD/mDNS discovery and registration through JmDNS on eligible IPv4 and IPv6 LAN addresses.
15
17
- Separate discovery and registration lifecycle states shared by Android, Desktop, the controller, and UI.
16
18
- Stable per-install device identity and advertised dynamic HTTP/file-transfer ports.
17
-
-Text offers, receiver Accept/Decline, text transfer, Copy, and Clear.
19
+
-One-request direct text delivery with sender name, a 100,000-character limit, Copy, and Clear.
18
20
- Android and Desktop multiple-file selection and metadata offers.
19
21
- Raw TCP file transfer using one persistent connection per accepted batch.
20
22
- Operation-bound file framing with operation ID, index, and size validation plus one final batch result containing receiver success and the completed-file count.
@@ -27,12 +29,13 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
27
29
- Application-lifetime network startup and state-driven connection repair.
28
30
- Enabled iOS device and Apple-silicon Simulator targets with native Bonjour discovery, document selection, clipboard, Files-visible storage, and streamed TCP transfer implementations.
29
31
- Added an iOS-only GitHub Actions workflow for an unsigned Simulator app and optional development-signed iPhone IPA.
30
-
- Prepared version `0.2.0` across Android, Desktop, and iOS; retained private Android release signing configuration and the permanent Windows MSI upgrade identity.
32
+
- Prepared version `0.3.0` across Android, Desktop, and iOS; retained private Android release signing configuration and the permanent Windows MSI upgrade identity.
31
33
- Public architecture, development, roadmap, security, privacy, and contribution documentation.
32
34
33
35
### Changed
34
36
35
-
- Made incoming transfer state the source of truth for offer type, operation identity, and acceptance phase; accepted text now shows a waiting state until its matching payload arrives.
37
+
- Separated text from file operations: text now delivers directly while idle without an offer, decision, operation ID, waiting state, remote cancellation, or Cancel action.
38
+
- Kept file offers, receiver decisions, operation IDs, cancellation, timeouts, progress, and raw TCP streaming unchanged in purpose.
36
39
- Replaced the old generated sync implementation with a smaller, manually understood flow.
37
40
- Separated Ktor HTTP offer/control messages from raw TCP file bytes.
38
41
- Reused one TCP connection for the complete accepted multi-file batch instead of opening one connection per file.
Copy file name to clipboardExpand all lines: README.md
+16-17Lines changed: 16 additions & 17 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -16,7 +16,7 @@
16
16
### Android → Android
17
17
18
18
<imgsrc="screenshots/hero-demo.gif"alt="Sync360 Android-to-Android text and file transfer demo"width="1080" />
19
-
<sub>Nearby discovery, receiver approval, and direct Android-to-Android text/file transfer.</sub>
19
+
<sub>Nearby discovery and direct Android-to-Android text/file transfer.</sub>
20
20
21
21
### Desktop → Android
22
22
@@ -33,7 +33,7 @@ We have all done it: send a file to ourselves, wait for it to upload, open anoth
33
33
Sync360 is for that nearby moment.
34
34
35
35
```text
36
-
open app -> find nearby device -> choose what to send -> receiver approves -> send directly
36
+
open app -> find nearby device -> choose text or files -> send directly
37
37
```
38
38
39
39
The current app discovers other Sync360 devices on the same local network and transfers content directly between them. The transfer path does not use an account, cloud storage, or a Sync360 backend. It depends on the local network and the two devices involved.
@@ -50,8 +50,8 @@ In an initial Windows 11 Ethernet test, the native Windows DNS-SD backend discov
50
50
51
51
- Discover nearby Android devices with Android NSD/mDNS.
52
52
- Advertise dynamic HTTP and file-transfer ports on the local network.
53
-
-Send a text offer and let the receiver accept or decline it.
54
-
-Transfer accepted text and copy it from the Receive screen.
53
+
-Deliver text directly with one HTTP request when the receiver is idle.
54
+
-Enforce a 100,000-character text limit and show the sender name with Copy and Clear actions.
55
55
- Select images, videos, documents, and multiple files.
56
56
- Show file metadata to the receiver before any file bytes are sent.
57
57
- Stream file bytes directly over raw TCP without loading an entire file into memory.
@@ -92,13 +92,14 @@ The current progress UI tracks the exact bytes transferred across the accepted b
92
92
93
93
Sync360 uses two small networking paths with different jobs:
94
94
95
-
-**Ktor HTTP is the control plane.** It carries text/file offers, receiver decisions, file metadata, and text payloads.
95
+
-**Ktor HTTP handles direct text delivery and the file control plane.** It carries text payloads, file offers, receiver decisions, and file metadata.
96
96
-**Raw TCP is the file data plane.** It streams the actual file bytes directly between devices.
97
97
98
98
```mermaid
99
99
flowchart LR
100
100
A["Sender device"] -->|"Android NSD or platform Desktop DNS-SD"| B["Receiver device"]
101
-
A -->|"Ktor: offer + decision + metadata"| B
101
+
A -->|"Ktor: direct text delivery"| B
102
+
A -->|"Ktor: file offer + decision"| B
102
103
A -->|"Raw TCP: streamed file bytes"| B
103
104
B -->|"Platform Downloads writer"| D["Downloads"]
104
105
```
@@ -113,14 +114,12 @@ Android and Desktop start the shared network controller from their application e
113
114
SendScreen
114
115
-> SendScreenViewModel
115
116
-> OutgoingRequestsController
116
-
-> POST /sync360/text/offer
117
-
-> receiver Accept/Decline
118
-
-> accepted receiver waits for the matching text payload
119
-
-> POST /sync360/text/transfer
120
-
-> ReceiveScreen shows the text
117
+
-> POST /sync360/text/deliver with sender name and text
118
+
-> receiver atomically accepts only while idle
119
+
-> ReceiveScreen shows the sender name and text
121
120
```
122
121
123
-
The sender shares a preview and character count first. After acceptance, the receiver remains in a waiting-for-text state until the matching full text arrives. One operation ID ties the offer, accepted payload, and any explicit cancellation to the same sender operation.
122
+
Text uses one request and has no offer, receiver decision, operation ID, waiting state, remote cancellation, or Cancel action. The UI, outgoing controller, and receiver reject text above 100,000 Kotlin `String.length` units. The receiver checks `Idle` and publishes the complete received text atomically under the incoming-operation mutex; otherwise it reports that it is busy.
124
123
125
124
### File path
126
125
@@ -237,9 +236,9 @@ macOS/Linux:
237
236
2. Connect both devices to the same Wi-Fi network or hotspot.
238
237
3. Keep Sync360 open on both devices during the current foreground-only test flow.
239
238
4. On the Send screen, wait for the other device to appear.
240
-
5.Choose Text or Files, select the nearby device, and send an offer.
241
-
6.Accept the offer on the receiving device.
242
-
7.Received files will be written to the platform's Downloads folder.
239
+
5.For text, enter the content and select the nearby device; idle receivers show it immediately.
240
+
6.For files, select the files and nearby device, then accept the offer on the receiver.
241
+
7.Accepted files will be written to the platform's Downloads folder.
243
242
244
243
Some routers enable client isolation and block local device-to-device traffic. If discovery or transfer does not work, try another trusted Wi-Fi network or a phone hotspot.
245
244
@@ -251,7 +250,7 @@ Reload is available only after the current discovery window has stopped while se
251
250
252
251
Sync360 is **not secure for untrusted networks yet**.
253
252
254
-
The current implementation uses cleartext local HTTP and raw TCP. Operation IDs correlate offers, cancellation, accepted text, and file sockets for correctness, but they are not secret or authenticated. Sync360 does not yet authenticate the sender, encrypt content, or verify file integrity with a cryptographic hash. Receiver approval exists in the UI, but it is not a complete security boundary.
253
+
The current implementation uses cleartext local HTTP and raw TCP. File operation IDs correlate offers, cancellation, and file sockets for correctness, but they are not secret or authenticated. Direct text delivery has no receiver approval. Sync360 does not yet authenticate the sender, encrypt content, or verify file integrity with a cryptographic hash. File receiver approval exists in the UI, but it is not a complete security boundary.
255
254
256
255
Use the current app only for development and testing on private networks you control. Please report security-sensitive findings according to [SECURITY.md](SECURITY.md), not in a public issue.
257
256
@@ -278,7 +277,7 @@ Use the current app only for development and testing on private networks you con
278
277
Sync360 is not trying to become a chat app, cloud-sync product, or permanent device manager. The product direction stays focused:
279
278
280
279
```text
281
-
find nearby -> approve -> send directly
280
+
find nearby -> send text or approve files -> transfer directly
open app -> discover nearby device -> choose text or files -> send directly
7
7
```
8
8
9
9
The old AI-generated sync implementation was removed. The current app is being rebuilt manually so its maintainer can understand and own the complete discovery, request, transfer, and storage path.
@@ -16,7 +16,7 @@ The old AI-generated sync implementation was removed. The current app is being r
16
16
- Windows discovery/registration through the operating system `dnsapi.dll` DNS-SD API on all interfaces.
17
17
- Current macOS/Linux discovery/registration through JmDNS on eligible IPv4 and IPv6 LAN addresses.
18
18
- Application-lifetime network startup with separate discovery and registration lifecycle states.
19
-
- Ktor HTTP offers, receiver decisions, metadata, and text payloads.
19
+
- Ktor HTTP direct text delivery plus file offers, receiver decisions, and metadata.
20
20
- Raw TCP streaming for file bytes.
21
21
- Multiple files sent sequentially over one accepted-batch connection.
22
22
- Android file access through `ContentResolver` and Downloads writing through `MediaStore`.
@@ -78,7 +77,7 @@ Current shared transfer constants use a 512 KiB payload buffer, 5-second connect
78
77
79
78
## Important limitations
80
79
81
-
Sync360 currently uses cleartext local HTTP and raw TCP. Operation IDs correlate protocol messages and file sockets but do not authenticate a peer. The app has receiver approval but no authentication, encryption, or checksum. The current target-SDK-37 Android build also lacks Android 17's required local-network runtime-permission flow. Windows receiving depends on Windows Firewall allowing the application. Use development builds only on private networks you control.
80
+
Sync360 currently uses cleartext local HTTP and raw TCP. Direct text has no receiver approval or operation ID. File operation IDs correlate protocol messages and sockets but do not authenticate a peer. File offers require receiver approval, but the app has no authentication, encryption, or checksum. The current target-SDK-37 Android build also lacks Android 17's required local-network runtime-permission flow. Windows receiving depends on Windows Firewall allowing the application. Use development builds only on private networks you control.
Copy file name to clipboardExpand all lines: docs/ARCHITECTURE.md
+9-9Lines changed: 9 additions & 9 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -18,9 +18,8 @@ app starts
18
18
-> FileTransferReceiver opens an OS-assigned TCP port
19
19
-> NetworkServices advertises both ports through DNS-SD/mDNS
20
20
-> nearby Sync360 devices are resolved into NearbyDevice
21
-
-> sender posts a text or file offer through Ktor HTTP
22
-
-> receiver accepts or declines
23
-
-> accepted text continues through HTTP
21
+
-> sender delivers text directly or posts a file offer through Ktor HTTP
22
+
-> idle receiver publishes the text, or the receiver accepts/declines the file offer
24
23
-> accepted file bytes stream through one raw TCP connection
25
24
-> platform DownloadsWriter saves the files
26
25
```
@@ -74,8 +73,8 @@ ViewModels launch UI-facing work. They do not implement platform APIs or socket
74
73
### Controllers
75
74
76
75
-`NetworkServicesController` starts the HTTP server, file receiver, and discovery/registration once for the application lifetime. It also coordinates timed discovery stop, discovery restart, and full connection repair.
77
-
-`OutgoingRequestsController`creates offers, calls the Ktor client, and starts accepted file transfers.
78
-
-`IncomingServerRequestsController`serializes Accept/Decline/Cancel races and uses `ClientServerState` as the source of truth for the active incoming operation. Text follows `TextOffer -> WaitingForText -> TextReceived`; files follow `FileOffer -> WaitingForFiles -> ReceivingFiles -> FilesReceived`. Active states retain their accepted request, so operation type, sender identity, operation ID, and acceptance phase are derived from state instead of duplicated in a second operation model.
76
+
-`OutgoingRequestsController`validates and delivers text, creates file offers, and starts accepted file transfers.
77
+
-`IncomingServerRequestsController`uses one operation mutex to atomically admit direct text only while idle and to serialize file Accept/Decline/Cancel races. Text follows `Idle -> TextReceived -> Idle`; files follow `Idle -> IncomingFileOffer -> WaitingForFiles -> ReceivingFiles -> FilesReceived`. File states retain their request, so sender identity, operation ID, and acceptance phase remain derived from state.
79
78
80
79
### Discovery
81
80
@@ -99,16 +98,17 @@ The macOS/Linux JmDNS fallback starts on eligible IPv4 and IPv6 addresses from e
99
98
100
99
## Control plane: Ktor HTTP
101
100
102
-
Ktor carries offers, decisions, metadata, and text:
101
+
Ktor carries direct text plus file offers, decisions, and metadata:
103
102
104
103
```text
105
-
POST /sync360/text/offer
106
-
POST /sync360/text/transfer
104
+
POST /sync360/text/deliver
107
105
POST /sync360/file/offer
108
106
POST /sync360/operation/cancel
109
107
```
110
108
111
-
An offer waits up to 50 seconds for the receiver's decision. After acceptance, the controller derives a 30-second payload-preparation timeout from `WaitingForText` or `WaitingForFiles`; leaving either state automatically cancels that timer. A random operation ID correlates the offer, accepted payload, explicit cancellation, and file connection. Cancellation succeeds only when both the operation ID and sender device ID match the active state. The timeouts remain fallbacks for crashes and lost network communication. The shared flow uses `FileOfferRequest` directly for the accepted metadata; file contents still remain in platform file readers and are not placed in the HTTP request.
109
+
Text is delivered in one request containing the sender device name and text. It has no offer, decision, operation ID, waiting state, or cancellation route. Text above 100,000 Kotlin `String.length` units is rejected, and the receiver atomically checks `Idle` and publishes `TextReceived` under the operation mutex.
110
+
111
+
A file offer waits up to 50 seconds for the receiver's decision. After acceptance, the controller derives a 30-second payload-preparation timeout from `WaitingForFiles`. A random operation ID correlates the file offer, explicit cancellation, and file connection. Cancellation succeeds only when both the operation ID and sender device ID match the active file state. The timeouts remain fallbacks for crashes and lost network communication. The shared flow uses `FileOfferRequest` directly for the accepted metadata; file contents remain in platform file readers and are not placed in the HTTP request.
Copy file name to clipboardExpand all lines: docs/DEVELOPMENT.md
+4-4Lines changed: 4 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -56,7 +56,7 @@ Windows:
56
56
57
57
## Preparing public packages
58
58
59
-
The current package version is `0.2.0`.
59
+
The current package version is `0.3.0`.
60
60
61
61
Android release APKs must use the maintainer's permanent private signing key. Copy `keystore.properties.example` to the ignored `keystore.properties` file and set:
62
62
@@ -88,8 +88,8 @@ The Windows `upgradeUuid` must remain unchanged for the lifetime of Sync360, and
88
88
1. Connect both devices to the same trusted Wi-Fi network or hotspot.
89
89
2. Open Sync360 on both devices and keep it in the foreground during current testing.
90
90
3. Wait for the other device to appear on the Send screen.
91
-
4. Test a text offer: Accept, Decline, transfer, Copy, and Clear.
92
-
5. Test one file, multiple files, and cancellation.
91
+
4. Test direct text delivery while idle and busy, the 100,000/100,001 boundaries, sender name, Copy, and Clear.
92
+
5. Test file Accept/Decline, one file, multiple files, and cancellation.
93
93
6. Confirm completed files appear in Downloads.
94
94
7. Resize the Desktop window and verify compact single-pane navigation and the wider 50/50 Send/Receive layout.
95
95
@@ -121,7 +121,7 @@ Useful source locations:
121
121
-`WindowsNetworkServices` — Windows DNS-SD registration, discovery, resolution, cancellation, and shared-state mapping.
122
122
-`WindowsDnsSdApi` — focused JDK Foreign Function and Memory bindings for `dnsapi.dll`.
123
123
-`JvmNetworkServices` — current macOS/Linux JmDNS registration, discovery, repair cleanup, and IPv4/IPv6 LAN-interface selection.
124
-
-`Sync360HttpServer` / `Sync360HttpClient` — offer and text routes.
124
+
-`Sync360HttpServer` / `Sync360HttpClient` — direct text delivery and file control routes.
0 commit comments