docs: establish project documentation and licensing

This commit is contained in:
2026-07-15 22:35:42 +02:00
parent b22536eaf4
commit fbabb213f1
7 changed files with 767 additions and 26 deletions

161
CODE_OF_CONDUCT.md Normal file
View File

@@ -0,0 +1,161 @@
# VniDrop Code of Conduct
## Our Pledge
We pledge to make our community welcoming, safe, and equitable for all.
We are committed to fostering an environment that respects and promotes the
dignity, rights, and contributions of all individuals, regardless of
characteristics including race, ethnicity, caste, color, age, physical
characteristics, neurodiversity, disability, sex or gender, gender identity or
expression, sexual orientation, language, philosophy or religion, national or
social origin, socio-economic position, level of education, or other status.
The same privileges of participation are extended to everyone who participates
in good faith and in accordance with this Code of Conduct.
## Encouraged Behaviors
While acknowledging differences in social norms, we all strive to meet our
community's expectations for positive behavior. We also understand that our
words and actions may be interpreted differently than we intend based on
culture, background, or native language.
With these considerations in mind, we agree to behave mindfully toward each
other and act in ways that center our shared values, including:
1. Respecting the purpose of our community, our activities, and our ways of
gathering.
2. Engaging kindly and honestly with others.
3. Respecting different viewpoints and experiences.
4. Taking responsibility for our actions and contributions.
5. Gracefully giving and accepting constructive feedback.
6. Committing to repairing harm when it occurs.
7. Behaving in other ways that promote and sustain the well-being of our
community.
## Restricted Behaviors
We agree to restrict the following behaviors in our community. Instances,
threats, and promotion of these behaviors are violations of this Code of
Conduct.
1. **Harassment.** Violating explicitly expressed boundaries or engaging in
unnecessary personal attention after any clear request to stop.
2. **Character attacks.** Making insulting, demeaning, or pejorative comments
directed at a community member or group of people.
3. **Stereotyping or discrimination.** Characterizing anyone's personality or
behavior on the basis of immutable identities or traits.
4. **Sexualization.** Behaving in a way that would generally be considered
inappropriately intimate in the context or purpose of the community.
5. **Violating confidentiality.** Sharing or acting on someone's personal or
private information without their permission.
6. **Endangerment.** Causing, encouraging, or threatening violence or other
harm toward any person or group.
7. **Behaving in other ways that threaten the well-being of our community.**
### Other Restrictions
1. **Misleading identity.** Impersonating someone else for any reason, or
pretending to be someone else to evade enforcement actions.
2. **Failing to credit sources.** Not properly crediting the sources of content
you contribute.
3. **Promotional materials.** Sharing marketing or other commercial content in
a way that is outside the norms of the community.
4. **Irresponsible communication.** Failing to responsibly present content
which includes, links, or describes any other restricted behaviors.
## Reporting an Issue
Tensions can occur between community members even when they are trying their
best to collaborate. Not every conflict represents a Code of Conduct violation,
and this Code of Conduct reinforces encouraged behaviors and norms that can help
avoid conflicts and minimize harm.
To report a possible violation, contact a VniDrop maintainer privately using the
contact information on their GitHub profile. Do not disclose sensitive details
in a public issue. If a report concerns a maintainer, contact a different
maintainer who is not involved in the incident.
Include the relevant links, dates, context, and any supporting material you are
comfortable sharing. Community Moderators will take reports seriously and make
every effort to respond promptly. They will investigate reports by reviewing
available messages, logs, and other evidence, or by interviewing witnesses and
participants. They will keep investigation and enforcement actions as
transparent as possible while prioritizing safety and confidentiality.
Enforcement actions are carried out privately with the involved parties, but
communicating to the whole community may be part of a mutually agreed-upon
resolution.
## Addressing and Repairing Harm
If an investigation finds that this Code of Conduct has been violated, the
following enforcement ladder may be used to determine how best to repair harm,
based on the incident's impact on the individuals involved and the community as
a whole. Depending on the severity of a violation, lower rungs on the ladder may
be skipped.
### 1. Warning
- **Event:** A violation involving a single incident or series of incidents.
- **Consequence:** A private, written warning from the Community Moderators.
- **Repair:** Examples include a private written apology, acknowledgement of
responsibility, and seeking clarification on expectations.
### 2. Temporarily Limited Activities
- **Event:** A repeated incidence of a violation that previously resulted in a
warning, or the first incidence of a more serious violation.
- **Consequence:** A private, written warning with a time-limited cooldown
period designed to underscore the seriousness of the situation and give the
community members involved time to process the incident. The cooldown period
may be limited to particular communication channels or interactions with
particular community members.
- **Repair:** Examples include making an apology, using the cooldown period to
reflect on actions and impact, and being thoughtful about re-entering
community spaces after the period is over.
### 3. Temporary Suspension
- **Event:** A pattern of repeated violations which the Community Moderators
have tried to address with warnings, or a single serious violation.
- **Consequence:** A private written warning with conditions for return from
suspension. In general, temporary suspensions give the person being suspended
time to reflect upon their behavior and possible corrective actions.
- **Repair:** Examples include respecting the spirit of the suspension, meeting
the specified conditions for return, and being thoughtful about how to
reintegrate with the community when the suspension is lifted.
### 4. Permanent Ban
- **Event:** A pattern of repeated Code of Conduct violations that other steps
on the ladder have failed to resolve, or a violation so serious that the
Community Moderators determine there is no way to keep the community safe
with this person as a member.
- **Consequence:** Access to all community spaces, tools, and communication
channels is removed. Permanent bans should be rarely used, have strong
reasoning behind them, and only be used if other remedies have failed to
change the behavior.
- **Repair:** There is no possible repair in cases of this severity.
This enforcement ladder is a guideline. It does not limit the ability of
Community Moderators to use their discretion and judgment in the best interests
of the VniDrop community.
## Scope
This Code of Conduct applies within all VniDrop community spaces and also when
an individual is officially representing VniDrop in public or other spaces.
Examples of representation include using an official email address, posting via
an official social media account, or acting as an appointed representative at
an online or offline event.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant, version
3.0](https://www.contributor-covenant.org/version/3/0/).
Contributor Covenant is stewarded by the Organization for Ethical Source. This
adapted Code of Conduct is licensed under [CC BY-SA
4.0](https://creativecommons.org/licenses/by-sa/4.0/). The enforcement ladder
was inspired by the work of Mozilla's code of conduct team.

167
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,167 @@
# Contributing to VniDrop
Thank you for helping improve VniDrop. Contributions may include bug reports,
feature proposals, documentation, tests, design feedback, and code.
By participating, you agree to follow the project
[Code of Conduct](CODE_OF_CONDUCT.md).
## Before You Start
- Search existing issues and pull requests before opening a duplicate.
- For a substantial feature or architecture change, open an issue first so the
approach and platform impact can be discussed.
- Keep each change focused. Avoid unrelated refactors, dependency upgrades, or
repository-wide formatting.
- Report suspected vulnerabilities through the private process in
[`SECURITY.md`](SECURITY.md), never in a public issue with technical details.
- Never include secrets, private tickets, file contents, key material, or
passphrases in an issue, log, test fixture, commit, or pull request.
## Development Setup
Clone the repository and create a branch from an up-to-date `master`:
```bash
git clone https://github.com/vnidrop/vnidrop.git
cd vnidrop
git switch master
git pull --ff-only
git switch -c feat/short-description
```
Use a branch name that describes the outcome, such as
`feat/folder-share`, `fix/cancel-export-hang`, or `docs/contributing`.
Install the tools needed for the area you plan to change:
- JDK 17 or newer for Gradle and application builds
- Rust stable with `rustfmt` and Clippy for the transfer core
- Android SDK and NDK for Android builds
- Xcode on macOS for iOS builds and simulator tests
- Node.js 22.12 or newer for the optional diagnostics service
The first Rust and Gradle builds may take several minutes while dependencies are
downloaded and native components are compiled.
## Repository Structure
| Path | Purpose |
|------|---------|
| `crates/vnidrop/` | Rust transfer core, persistence, approval, and streaming |
| `shared/` | Shared Kotlin Multiplatform UI and platform bridges |
| `androidApp/` | Android application shell |
| `iosApp/` | iOS application shell |
| `desktopApp/` | Desktop JVM application shell |
| `services/diagnostics-api/` | Optional Cloudflare diagnostics service |
Read the nearest contributor guidance before editing:
- [`AGENTS.md`](AGENTS.md) contains repository-wide engineering rules.
- [`crates/vnidrop/AGENTS.md`](crates/vnidrop/AGENTS.md) covers the Rust core.
- [`shared/AGENTS.md`](shared/AGENTS.md) covers Compose and Kotlin
Multiplatform work.
## Engineering Expectations
VniDrop follows a few important design constraints:
- File transfer payloads are streamed by Rust and should not be routed through
the Kotlin heap as the primary design.
- Android directory sharing expands SAF trees into individual file descriptors;
directory file descriptors are not passed to Rust.
- Approval and access checks must not be weakened for convenience.
- Receive publishing must preserve the existing no-overwrite behavior.
- Locks and synchronous guards must not be held across Rust `.await` points.
- Bug fixes require a regression test at the lowest layer that demonstrates the
failure.
Match the style of nearby code. Comments should explain non-obvious invariants,
platform constraints, concurrency behavior, or design decisions instead of
restating the code.
## Testing
Run checks from the repository root. Choose the suite for the files you changed.
### Rust Core
```bash
cargo fmt --all
cargo clippy --workspace --all-targets -- -D warnings
cargo test -p vnidrop
```
For cancel, export, or output-sink changes, also run:
```bash
cargo test -p vnidrop --test output_sink
```
For broader core changes, run the complete workspace suite:
```bash
cargo test --workspace --all-targets
```
### Shared Kotlin and Compose
```bash
./gradlew :shared:jvmTest
```
Platform-specific checks may also be appropriate:
```bash
./gradlew :shared:testAndroidHostTest
./gradlew :shared:iosSimulatorArm64Test
./gradlew :androidApp:assembleDebug
```
### Diagnostics Service
```bash
cd services/diagnostics-api
npm ci
npm run check
```
If a required check cannot run on your machine, explain why in the pull request
and list the checks you did run.
## Commits
Use concise commit messages that describe the outcome. The repository commonly
uses Conventional Commit-style subjects:
```text
feat(core): add folder transfer metadata
fix(ui): preserve receive progress after rotation
docs: clarify desktop setup
```
Create signed commits when your repository configuration requires signing. Do
not bypass a signing requirement with an unsigned commit.
## Pull Requests
Open pull requests against `master`. A good pull request should:
1. Explain what changed and why.
2. Stay limited to one coherent outcome.
3. Link the relevant issue, when one exists.
4. Describe platform or compatibility implications.
5. Include regression coverage for bug fixes and behavior changes.
6. Provide an executable test plan with the exact commands or concrete manual
scenarios used for verification.
7. Avoid generated files, unrelated formatting, and dependency changes unless
they are required by the contribution.
Review feedback is part of the collaboration process. Keep follow-up commits
focused, and resolve review threads only after the concern has been addressed.
## Licensing
VniDrop is distributed under the [Apache License 2.0](LICENSE). Unless explicitly
stated otherwise, contributions accepted into this repository are distributed
under the same license.

202
LICENSE Normal file
View File

@@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

159
README.md
View File

@@ -1,36 +1,143 @@
This is a Kotlin Multiplatform project targeting Android, iOS, Desktop (JVM). <p align="center">
<img src="assets/1024x1024.png" alt="VniDrop app icon" width="128" />
</p>
* [/iosApp](./iosApp/iosApp) contains an iOS application. Even if youre sharing your UI with Compose Multiplatform, <h1 align="center">VniDrop</h1>
you need this entry point for your iOS app. This is also where you should add SwiftUI code for your project.
* [/shared](./shared/src) is for code that will be shared across your Compose Multiplatform applications. <p align="center">
It contains several subfolders: <strong>Send files directly. Stay in control of who receives them.</strong>
- [commonMain](./shared/src/commonMain/kotlin) is for code thats common for all targets. </p>
- Other folders are for Kotlin code that will be compiled for only the platform indicated in the folder name.
For example, if you want to use Apples CoreCrypto for the iOS part of your Kotlin app,
the [iosMain](./shared/src/iosMain/kotlin) folder would be the right place for such calls.
Similarly, if you want to edit the Desktop (JVM) specific part, the [jvmMain](./shared/src/jvmMain/kotlin)
folder is the appropriate location.
### Running the apps <p align="center">
Cross-platform file transfer for Android, iOS, macOS, Windows, and Linux.
</p>
Use the run configurations provided by the run widget in your IDE's toolbar. You can also use these commands and <p align="center">
options: <a href="https://github.com/vnidrop/vnidrop/actions/workflows/rust-core.yml"><img src="https://github.com/vnidrop/vnidrop/actions/workflows/rust-core.yml/badge.svg" alt="Rust core status" /></a>
<a href="https://github.com/vnidrop/vnidrop/actions/workflows/shared-kmp.yml"><img src="https://github.com/vnidrop/vnidrop/actions/workflows/shared-kmp.yml/badge.svg" alt="Shared KMP status" /></a>
<img src="https://img.shields.io/badge/status-early%20development-F59E0B" alt="Early development" />
<a href="LICENSE"><img src="https://img.shields.io/badge/license-Apache%202.0-6D28D9" alt="Apache 2.0 license" /></a>
</p>
- Android app: `./gradlew :androidApp:assembleDebug` VniDrop moves files and folders from one device to another without first
- Desktop app: uploading them to a file-hosting service. Choose what to send, decide who may
- Hot reload: `./gradlew :desktopApp:hotRun --auto` receive it, and share a small invitation. The receiving device uses that
- Standard run: `./gradlew :desktopApp:run` invitation to find the sender and request the files.
- iOS app: open the [/iosApp](./iosApp) directory in Xcode and run it from there.
### Running tests There is no account to create and no cloud copy of the transfer waiting after
you are done. The sender remains in control and can stop sharing at any time.
Use the run button in your IDE's editor gutter, or run tests using Gradle tasks: ## How a transfer works
- Android tests: `./gradlew :shared:testAndroidHostTest` 1. **Choose files or a folder.** VniDrop prepares the selection on the sender's
- Desktop tests: `./gradlew :shared:jvmTest` device and keeps the original folder structure.
- iOS tests: `./gradlew :shared:iosSimulatorArm64Test` 2. **Create an invitation.** The app produces a small VniDrop invitation that
describes the transfer and how to reach the sender. Share it as a QR code, an
NFC tag, or a `.vnd` file.
3. **Connect to the sender.** The receiver opens the invitation. Iroh helps the
devices find each other and establishes an authenticated, end-to-end
encrypted connection.
4. **Request access.** By default, the sender sees who wants the transfer and
chooses whether to approve or refuse the request.
5. **Stream and verify.** After access is granted, `iroh-blobs` streams the files
and verifies their content while it arrives. VniDrop saves each file directly
to the chosen destination without replacing an existing file.
6. **Stay in control.** The sender can follow each receiver's progress, cancel a
transfer, or stop sharing so the invitation can no longer be used.
--- Iroh tries to connect the devices directly, including across home routers and
mobile networks. If a direct path cannot be established, it can forward the
same end-to-end encrypted connection through a relay. The relay forwards
encrypted packets; it is not a VniDrop file store.
Learn more about [Kotlin Multiplatform](https://www.jetbrains.com/help/kotlin-multiplatform-dev/get-started.html)… ## Why Iroh and `iroh-blobs`?
VniDrop combines a networking layer with its own sharing rules:
| Layer | What it does |
|-------|--------------|
| [Iroh](https://docs.iroh.computer/) | Gives each device a secure identity, helps devices find one another, creates encrypted connections, and falls back to relays when a direct path is unavailable. |
| [`iroh-blobs`](https://docs.rs/iroh-blobs/0.103.0/iroh_blobs/) | Turns files into content-addressed, verified streams, so corrupted or unexpected data is detected while receiving. Multiple files are grouped into one collection. |
| **VniDrop** | Adds human-friendly invitations, receiver approval, per-transfer access rules, progress, history, cancellation, and safe saving on each operating system. |
Content addressing is useful here because the invitation identifies exactly
what was shared. The receiver does not simply trust a filename or claimed size:
the incoming content must match its expected hash.
## Approval is part of the transfer
A VniDrop invitation helps two devices meet, but the default invitation is not
automatic permission to download.
| Access mode | Behavior |
|-------------|----------|
| **Ask before each download** | The default. Every new receiver asks first, and the sender can approve or refuse the request. Approval gives that device temporary access to this transfer. |
| **Anyone with this transfer** | No interactive approval is required. Anyone holding the invitation may receive the files until the sender stops sharing. This mode is intended only for non-sensitive items. |
VniDrop starts from a deny-by-default position: it serves only the content in an
active share, and only when that receiver's access mode allows it. Unknown
content requests are rejected.
Treat an invitation like a private access link. Share it only with the intended
people, especially when using **Anyone with this transfer**.
## What VniDrop supports
- Individual files, multiple files, and complete folders
- QR codes, NFC tags, and portable `.vnd` invitation files
- Per-receiver requests, approvals, progress, and delivery status
- Cancel, stop sharing, and local transfer history
- Safe receive destinations that do not silently overwrite existing files
- Android, iOS, and desktop apps built from a shared Compose Multiplatform UI
- Opt-in diagnostics with transfer contents, invitations, and file paths
excluded
## Privacy by design
- **No hosted transfer copy.** VniDrop does not upload file contents to its
diagnostics service or a VniDrop storage bucket.
- **Encrypted in transit.** Iroh connections are authenticated and encrypted
end to end, including when a relay is needed.
- **Local control.** Transfer history and sharing state stay on the device.
- **Sensitive invitations.** An invitation can grant access, so it is
deliberately excluded from product logs and diagnostics.
- **Explicit access.** Approval is required by default, and stopping a share
removes access immediately.
Please report suspected vulnerabilities through the private process in
[`SECURITY.md`](SECURITY.md), not through a public issue.
## Project status
VniDrop is in early development. The transfer engine, application experience,
and stored history format may change before a stable release. Build from source
if you want to try the current version.
```bash
git clone https://github.com/vnidrop/vnidrop.git
cd vnidrop
# Desktop
./gradlew :desktopApp:run
# Android debug build
./gradlew :androidApp:assembleDebug
# iOS
open iosApp/iosApp.xcodeproj
```
See [`CONTRIBUTING.md`](CONTRIBUTING.md) for prerequisites, development setup,
testing, and pull request guidance.
## Learn more
- [`crates/vnidrop/CORE_FLOW.md`](crates/vnidrop/CORE_FLOW.md) — protocol,
approval, durability, and file-handling details
- [`CONTRIBUTING.md`](CONTRIBUTING.md) — development and contribution guide
- [`SECURITY.md`](SECURITY.md) — security policy and private reporting
- [`CODE_OF_CONDUCT.md`](CODE_OF_CONDUCT.md) — community standards
## License
VniDrop is available under the [Apache License 2.0](LICENSE).

102
SECURITY.md Normal file
View File

@@ -0,0 +1,102 @@
# VniDrop Security Policy
VniDrop transfers files directly between devices and treats invitations as
capabilities. Security reports are taken seriously, especially when they affect
transfer authorization, file integrity, peer privacy, or the handling of local
files.
## Supported Versions
VniDrop is currently pre-release software and does not yet have tagged stable
releases. Security fixes are developed for the latest commit on `master`.
| Version | Supported |
|---------|-----------|
| Latest `master` | Yes |
| Older commits and unofficial builds | No |
Before reporting an issue, check whether it is reproducible on the latest
`master` when it is safe to do so. This table will be updated when versioned
releases are published.
## Reporting a Vulnerability
Do not disclose a suspected vulnerability, proof of concept, invitation ticket,
private file, or sensitive log in a public issue or discussion.
To make a private report:
1. Contact a VniDrop maintainer privately using the contact information on their
GitHub profile.
2. If no private contact method is available, open a public issue titled
**Security contact request**. Include no vulnerability details. A maintainer
will arrange a private channel for the report.
Code of Conduct incidents should instead follow the private reporting process in
[`CODE_OF_CONDUCT.md`](CODE_OF_CONDUCT.md).
### What to Include
Provide as much of the following information as you safely can:
- A concise description of the vulnerability and its potential impact
- The affected commit, platform, and application version
- Reproduction steps or a minimal proof of concept using test data
- Required access, permissions, or user interaction
- Relevant logs or screenshots with tickets, paths, endpoint identifiers,
credentials, and personal data redacted
- Any suggested mitigation or fix
- Whether the issue has been disclosed to anyone else
Do not attach real user files or reusable invitation tickets. Generate isolated
test fixtures where possible.
## Security-Sensitive Areas
Reports are especially useful when they involve:
- Bypassing transfer approval, access policy, or provider authorization
- Forging, leaking, replaying, or incorrectly accepting invitation tickets
- Serving blobs that are not registered for an active share
- Path traversal, symlink attacks, file overwrite, or unsafe temporary-file
publication
- Unsafe handling of Android file descriptors, SAF permissions, or iOS
security-scoped resources
- Remote code execution, memory-safety failures, or denial of service caused by
untrusted peer input
- Exposure of file contents, local paths, tickets, endpoint identifiers,
credentials, or other sensitive values through diagnostics or logs
- Authentication, authorization, or data-isolation failures in the diagnostics
service
The transfer protocol and file-publication invariants are documented in
[`crates/vnidrop/CORE_FLOW.md`](crates/vnidrop/CORE_FLOW.md).
## Coordinated Disclosure
After receiving a report, maintainers will aim to:
1. Confirm receipt and establish a private communication channel.
2. Reproduce and assess the issue, including affected platforms and versions.
3. Develop and verify a fix without weakening existing security boundaries.
4. Coordinate the release and public disclosure with the reporter.
5. Credit the reporter if they want public acknowledgement.
Response and remediation times depend on severity and complexity. Please allow
maintainers a reasonable opportunity to investigate and release a fix before
publishing technical details.
## Research Guidelines
When investigating VniDrop:
- Use devices, accounts, files, and peers that you own or have permission to
test.
- Minimize access to personal data and stop testing if you encounter data that
does not belong to you.
- Avoid privacy violations, service disruption, data destruction, and testing
that affects other users.
- Keep vulnerability details confidential until disclosure is coordinated.
- Follow applicable laws and the project [Code of Conduct](CODE_OF_CONDUCT.md).
Thank you for helping keep VniDrop and its users safe.

View File

@@ -2,6 +2,7 @@
name = "vnidrop" name = "vnidrop"
version = "0.1.0" version = "0.1.0"
edition = "2021" edition = "2021"
license = "Apache-2.0"
[lib] [lib]
name = "vnidrop" name = "vnidrop"

View File

@@ -2,6 +2,7 @@
"name": "vnidrop-diagnostics-api", "name": "vnidrop-diagnostics-api",
"private": true, "private": true,
"version": "0.1.0", "version": "0.1.0",
"license": "Apache-2.0",
"type": "module", "type": "module",
"engines": { "engines": {
"node": ">=22.12" "node": ">=22.12"