diff --git a/Cargo.toml b/Cargo.toml
index 3a08b07..04ee03a 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "tauri-plugin-vnidrop-fs"
-version = "1.0.0-rc.1"
+version = "1.0.0-rc"
authors = [ "AbassHammed" ]
description = "Cross-platform filesystem manager for Tauri with Android SAF and iOS document picker support."
edition = "2021"
diff --git a/README.md b/README.md
index 24207f3..d00c637 100644
--- a/README.md
+++ b/README.md
@@ -75,12 +75,15 @@ configuration is:
}
```
-For production, prefer a tighter scope:
+The plugin default is intentionally read-only. It enables metadata, read,
+picker, and non-mutating helper commands, but not create, write, rename,
+delete, or persisted permission lifecycle commands. For production, prefer a
+tighter scope and opt into only the command profile your app needs:
```json
{
"permissions": [
- "vnidrop-fs:all-without-delete",
+ "vnidrop-fs:read-only",
{
"identifier": "vnidrop-fs:scope",
"allow": ["$APPDATA/files/**/*"],
@@ -102,8 +105,9 @@ Treat filesystem access as an explicit capability:
- Prefer picker-returned mobile URI objects over raw paths.
- Keep production capability files narrow. Do not ship `vnidrop-fs:all`,
- `fs:read-all`, `fs:write-all`, or `"allow": ["**"]` unless the whole app is
- intended to manage every reachable file.
+ `vnidrop-fs:all-without-delete`, `fs:read-all`, `fs:write-all`, or
+ `"allow": ["**"]` unless the whole app is intended to manage every reachable
+ file.
- Android `content://` operations are authorized by Android URI permissions and
document providers. Destructive operations such as rename and delete should
only be exposed in your UI for URIs the user selected or the app created.
diff --git a/package-lock.json b/package-lock.json
index 6d4aa89..8253f98 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "@vnidrop/tauri-plugin-fs",
- "version": "1.0.0-rc.1",
+ "version": "1.0.0-rc",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@vnidrop/tauri-plugin-fs",
- "version": "1.0.0-rc.1",
+ "version": "1.0.0-rc",
"license": "MIT OR Apache-2.0",
"dependencies": {
"@tauri-apps/api": "^2.11.0",
diff --git a/package.json b/package.json
index 897ef65..7ae4462 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@vnidrop/tauri-plugin-fs",
- "version": "1.0.0-rc.1",
+ "version": "1.0.0-rc",
"author": "AbassHammed",
"description": "Cross-platform filesystem manager for Tauri with Android SAF and iOS document picker support.",
"keywords": [
diff --git a/permissions/autogenerated/reference.md b/permissions/autogenerated/reference.md
index c5cc99b..c774dff 100644
--- a/permissions/autogenerated/reference.md
+++ b/permissions/autogenerated/reference.md
@@ -4,7 +4,7 @@ Default permissions for the plugin
#### This default permission set includes the following:
-- `all-without-delete`
+- `read-only`
## Permission Table
@@ -1422,6 +1422,19 @@ Denies the write_text_file command without any pre-configured scope.
|
+`vnidrop-fs:read-only`
+
+ |
+
+
+This enables read-only commands and non-mutating picker/metadata helpers.
+
+ |
+
+
+
+|
+
`vnidrop-fs:scope`
|
diff --git a/permissions/default.toml b/permissions/default.toml
index 3595734..1622d8f 100644
--- a/permissions/default.toml
+++ b/permissions/default.toml
@@ -1,5 +1,5 @@
[default]
description = "Default permissions for the plugin"
permissions = [
- "all-without-delete"
+ "read-only"
]
diff --git a/permissions/read-only.toml b/permissions/read-only.toml
new file mode 100644
index 0000000..5be489e
--- /dev/null
+++ b/permissions/read-only.toml
@@ -0,0 +1,44 @@
+"$schema" = "schemas/schema.json"
+
+[[permission]]
+identifier = "read-only"
+description = "This enables read-only commands and non-mutating picker/metadata helpers."
+commands.allow = [
+ "get_android_api_level",
+ "get_name",
+ "get_byte_length",
+ "get_type",
+ "get_mime_type",
+ "get_metadata",
+ "get_thumbnail",
+ "get_thumbnail_as_bytes",
+ "get_thumbnail_as_base64",
+ "get_thumbnail_as_data_url",
+ "get_fs_path",
+ "list_volumes",
+ "check_public_files_permission",
+ "count_all_file_streams",
+ "close_all_file_streams",
+ "open_read_file_stream",
+ "open_read_text_file_lines_stream",
+ "read_file",
+ "read_file_as_base64",
+ "read_file_as_data_url",
+ "read_text_file",
+ "read_dir",
+ "check_picker_uri_permission",
+ "check_persisted_picker_uri_permission",
+ "show_open_file_picker",
+ "show_open_dir_picker",
+ "show_view_file_dialog",
+ "show_view_dir_dialog",
+ "listSecurityScopedBookmarks",
+ "resolveSecurityScopedBookmark",
+ "readFile",
+ "readTextFile",
+ "readDir",
+ "exists",
+ "getMetadata",
+ "showOpenFilePicker",
+ "showOpenDirPicker"
+]
diff --git a/permissions/schemas/schema.json b/permissions/schemas/schema.json
index cb08b0e..79a8891 100644
--- a/permissions/schemas/schema.json
+++ b/permissions/schemas/schema.json
@@ -943,10 +943,16 @@
"markdownDescription": "Denies the write_text_file command without any pre-configured scope."
},
{
- "description": "Default permissions for the plugin\n#### This default permission set includes:\n\n- `all-without-delete`",
+ "description": "Default permissions for the plugin\n#### This default permission set includes:\n\n- `read-only`",
"type": "string",
"const": "default",
- "markdownDescription": "Default permissions for the plugin\n#### This default permission set includes:\n\n- `all-without-delete`"
+ "markdownDescription": "Default permissions for the plugin\n#### This default permission set includes:\n\n- `read-only`"
+ },
+ {
+ "description": "This enables read-only commands and non-mutating picker/metadata helpers.",
+ "type": "string",
+ "const": "read-only",
+ "markdownDescription": "This enables read-only commands and non-mutating picker/metadata helpers."
},
{
"description": "An empty permission you can use to modify the global scope.\n\n## Example\n\n```json\n{\n \"permissions\": [\n \"vnidrop-fs:all-without-delete\",\n {\n \"identifier\": \"vnidrop-fs:scope\",\n \"allow\": [\n \"$APPDATA/documents/**/*\"\n ],\n \"deny\": [\n \"$APPDATA/documents/secret.txt\"\n ]\n }\n ]\n}\n```\n",
diff --git a/tests/permissions.rs b/tests/permissions.rs
index 7c5cf0f..a011e9d 100644
--- a/tests/permissions.rs
+++ b/tests/permissions.rs
@@ -24,10 +24,39 @@ fn all_permission_contains_mutating_and_picker_commands() {
}
#[test]
-fn default_permission_uses_non_delete_profile() {
+fn default_permission_uses_read_only_profile() {
let contents = fs::read_to_string("permissions/default.toml").expect("default permission file should exist");
- assert!(contents.contains(r#""all-without-delete""#));
+ assert!(contents.contains(r#""read-only""#));
+}
+
+#[test]
+fn read_only_excludes_mutating_commands() {
+ let contents = fs::read_to_string("permissions/read-only.toml").expect("read-only permission file should exist");
+
+ for command in [
+ "create_new_file",
+ "create_new_dir",
+ "create_new_public_file",
+ "write_file",
+ "copy_file",
+ "rename_file",
+ "remove_file",
+ "remove_dir_all",
+ "persist_picker_uri_permission",
+ "release_persisted_picker_uri_permission",
+ "persistSecurityScopedBookmark",
+ "releaseSecurityScopedBookmark",
+ "createNewFile",
+ "writeFile",
+ "renameFile",
+ "removeFile",
+ ] {
+ assert!(
+ !contents.contains(&format!(r#""{command}""#)),
+ "read-only should not include {command}"
+ );
+ }
}
#[test]