# Permissions Guide

Mosis apps run in a secure sandbox with limited access to device features. To access sensitive capabilities, apps must declare permissions in their manifest.

## Why Permissions?

Permissions protect user privacy and security by:

1. **Informing users** what an app can access before installation
2. **Limiting damage** if an app misbehaves
3. **Maintaining trust** in the Mosis ecosystem

## Declaring Permissions

Add permissions to your `manifest.json`:

```json
{
  "id": "com.example.myapp",
  "name": "My App",
  "permissions": [
    "storage",
    "network"
  ]
}
```

Only request permissions your app actually needs. Users are more likely to trust apps with fewer permissions.

## Available Permissions

### storage

**Description:** Persist data locally between app sessions.

**Use cases:**
- Save user preferences
- Cache data for offline use
- Store app state

**API access:**
```lua
storage.set("key", value)
storage.get("key")
storage.remove("key")
storage.clear()
```

**Note:** All apps have access to in-memory storage during a session. The `storage` permission enables persistence across sessions.

---

### network

**Description:** Make HTTP/HTTPS requests to external servers.

**Use cases:**
- Fetch data from APIs
- Submit form data
- Load remote content

**API access:**
```lua
http.get(url, callback)
http.post(url, options, callback)
http.request(options, callback)
```

**Restrictions:**
- HTTPS only (HTTP blocked for security)
- Cannot access localhost or internal IPs
- Subject to CORS policies

---

### clipboard

**Description:** Read from and write to the system clipboard.

**Use cases:**
- Copy text or data
- Paste user content
- Share functionality

**API access:**
```lua
clipboard.write(text)
clipboard.read(callback)
```

---

### notifications

**Description:** Display system notifications to the user.

**Use cases:**
- Reminders
- Alerts
- Background updates

**API access:**
```lua
notifications.show({
    title = "Reminder",
    body = "Your timer is done!",
    icon = "icons/alarm.png"
})
```

**Restrictions:**
- Notifications may be rate-limited
- Users can disable notifications per-app

---

### camera

**Description:** Capture photos using the device camera.

**Use cases:**
- Photo capture
- QR code scanning
- Augmented reality

**API access:**
```lua
camera.capture({
    quality = "high",
    facing = "back"
}, function(result)
    if result.success then
        local imageData = result.data
    end
end)
```

**Restrictions:**
- User prompt before first access
- Cannot record video (photo only)

---

### microphone

**Description:** Record audio from the device microphone.

**Use cases:**
- Voice notes
- Audio messages
- Voice commands

**API access:**
```lua
microphone.start()
microphone.stop(function(result)
    local audioData = result.data
end)
```

**Restrictions:**
- User prompt before first access
- Maximum recording duration enforced

---

### location

**Description:** Access device location information.

**Use cases:**
- Weather apps
- Maps
- Location-based features

**API access:**
```lua
location.get(function(result)
    if result.success then
        print(result.latitude, result.longitude)
    end
end)

location.watch(function(result)
    -- Called on location changes
end)
```

**Restrictions:**
- User prompt before first access
- Approximate location only (no precise GPS)
- Battery impact warning

---

### contacts

**Description:** Read device contacts.

**Use cases:**
- Contact picker
- Address book integration
- Sharing with friends

**API access:**
```lua
contacts.pick(function(result)
    if result.success then
        print(result.name, result.phone)
    end
end)

contacts.getAll(function(result)
    for i, contact in ipairs(result.contacts) do
        print(contact.name)
    end
end)
```

**Restrictions:**
- Read-only access
- User prompt before first access

## Permission Levels

| Level | Description | Example |
|-------|-------------|---------|
| **Normal** | Low risk, minimal review | storage |
| **Sensitive** | Requires user prompt | camera, microphone, location |
| **Dangerous** | Extensive review required | contacts |

## Runtime Behavior

### First-Time Prompts

Some permissions trigger a user prompt on first use:

```lua
-- First call triggers prompt
camera.capture(options, function(result)
    if result.denied then
        -- User denied permission
        showPermissionExplanation()
    elseif result.success then
        -- Permission granted
        handlePhoto(result.data)
    end
end)
```

### Checking Permission Status

```lua
-- Check if permission is granted
if permissions.check("camera") then
    -- Already have permission
    showCameraButton()
else
    -- Need to request
    showRequestButton()
end
```

### Requesting at Runtime

```lua
permissions.request("camera", function(granted)
    if granted then
        startCamera()
    else
        showAlternative()
    end
end)
```

## Best Practices

### 1. Minimize Permissions

Only request what you need. An app with fewer permissions:
- Builds more user trust
- Passes review faster
- Has smaller attack surface

### 2. Request at the Right Time

Don't request all permissions at startup. Request when the user takes an action that needs it:

```lua
-- Bad: Request on app start
function onAppStart()
    permissions.request("camera")  -- Why?
end

-- Good: Request when needed
function onTakePhotoClicked()
    permissions.request("camera", function(granted)
        if granted then
            camera.capture(options, handlePhoto)
        end
    end)
end
```

### 3. Explain Why

Tell users why you need a permission before requesting:

```xml
<div id="permission-explanation" style="display: none;">
    <p>This app needs camera access to scan QR codes.</p>
    <button onclick="requestCamera()">Enable Camera</button>
</div>
```

### 4. Handle Denial Gracefully

Apps should work (with reduced functionality) even if permissions are denied:

```lua
function capturePhoto()
    if not permissions.check("camera") then
        -- Offer alternative
        showManualEntryOption()
        return
    end
    -- Proceed with camera
end
```

### 5. Don't Ask Again Immediately

If a user denies a permission, don't immediately ask again:

```lua
local lastDenied = storage.get("camera_denied_time")
if lastDenied and os.time() - lastDenied < 86400 then
    -- Wait at least 24 hours before asking again
    return
end
```

## Review Impact

Permission requests affect app review:

| Permission | Review Impact |
|------------|---------------|
| storage, network | Automatic approval |
| clipboard | Quick review |
| notifications | Standard review |
| camera, microphone | Extended review |
| location | Extended review |
| contacts | Manual review required |

Apps requesting sensitive permissions must:
1. Justify the need in submission notes
2. Use the permission appropriately
3. Respect user privacy

## Troubleshooting

### "Permission not declared"

```
Error: Cannot use camera without 'camera' permission
```

Add the permission to your manifest:
```json
"permissions": ["camera"]
```

### "Permission denied by user"

Handle this gracefully in your code:
```lua
if result.denied then
    showAlternativeUI()
end
```

### "Permission blocked"

The user permanently blocked the permission. Direct them to settings:
```lua
if result.blocked then
    showMessage("Please enable camera in system settings")
end
```

## See Also

- [Manifest Reference](../api/manifest.md) - Full manifest documentation
- [Security Guide](security.md) - App security best practices
- [Publishing Guide](publishing.md) - App review process
