Skip to content

Security and recovery model

BloqueApp separates service identity, approver identity, signed policy, signed allowances, and local Android enforcement. These controls reduce accidental or unauthorized access; they do not make a consumer phone tamper-proof. The architecture page describes the authority split; the shared concepts cover partner allowances, requests, and offline behavior. See also the glossary and limitations.

Device Owner setup overview

Device Owner is Android's device-management role that enables BloqueApp's package-level enforcement. Setting it up is a separate, on-device enrollment process; pairing with an approver does not grant this role. The flow below is an overview, not an install-ready procedure. The current project proof covers QR enrollment on a spare Galaxy A32. A Galaxy A36 handover has not been verified.

flowchart TD
    A[Owner agrees to setup] --> B[Back up wanted data and confirm account recovery]
    B --> C{Device is eligible for enrollment?}
    C -->|No| X[Stop and resolve eligibility]
    C -->|Yes| D[Owner performs an authorized reset]
    D --> E[At the eligible setup screen, scan QR]
    E --> F[QR points to an APK on HTTPS and includes its checksum]
    F --> G[Android Setup Wizard downloads and provisions the DPC]
    G --> H[Verify BloqueApp is actually Device Owner]
    H --> I[Pair, sync signed policy, review permissions]
    I --> J[Check a harmless test target]

The owner must be able to unlock the device and recover any account that Android may request after a reset. Resetting erases device data. QR enrollment is completed in Android Setup Wizard with the owner's consent; seeing BloqueApp installed is not proof that Device Owner enrollment succeeded. Continue only after ownership is verified, then pair and check a harmless target before relying on enforcement. See the architecture page for the role's limits.

Pairing with an approver

Pairing links one Android device identity with one authenticated approver identity. It is separate from Device Owner enrollment: pairing alone does not enable Android enforcement. A short-lived one-use code starts the exchange; the six-digit number is a comparison step, and the phone must confirm the match.

flowchart TD
    A[Phone displays a short-lived pairing code] --> B[Approver signs in to the browser and submits that code]
    B --> C[Server creates a pending pairing and shows a six-digit number]
    C --> D[Compare the number on the browser and phone]
    D --> E{Do the numbers match?}
    E -->|No| F[Do not confirm; restart pairing when needed]
    E -->|Yes| G[Confirm on the phone]
    G --> H[Server records the pairing]
    H --> I[Phone can sync and verify signed policy]
    H --> J[Approver may separately enable browser push]

The number comparison helps catch a code entered for the wrong device; it does not authorize pairing by itself. Only the authenticated phone can confirm the pending exchange. Policy sync is a separate authenticated step, and browser push is optional. See authority boundaries for how the service, browser, and phone divide responsibility.

Separate identities

The restricted phone authenticates to the service with a device bearer token. The browser uses a separate random approver session token in a Secure, HttpOnly, SameSite=Strict cookie. SQLite stores hashes of these bearer and session tokens, not their returned values. Pairing joins one device to one approver; device-supplied IDs are not treated as authorization.

The device and browser use different authenticated routes. Browser mutations require JSON and reject cross-origin browser signals when those signals are present; the web page receives no device credential. The phone does not receive approver credentials. Policy publication comes from the operator-owned source, not from either client.

Durable decisions and idempotency

An approval decision is checked against the authenticated approver, paired device, pending request, expiry, current policy, requested package, and duration. The service writes the decision and any resulting grant in a SQLite transaction. Concurrent decisions serialize so one can win for a request. A retry with the same idempotency key and identical request body returns the saved result; reusing that key for a different body is a conflict.

After commit, the service attempts a best-effort SignalR hint. Failure to send the hint does not undo the decision. The phone retrieves the persisted receipt over authenticated HTTPS, and a request notification is only a route to that receipt. The PWA reports success only after the decision endpoint acknowledges it.

Signed policy and grants

The service signs policy snapshots and scoped grants with its configured RSA key. The Android build supplies a pinned public key, issuer, and key identifier. The client verifies the signature before exposing claims, then checks the expected endpoint and context, including audience/device, pairing, request, package, policy ID and revision, scope, issuance time, and expiry. It rejects malformed or overlong envelopes, mismatched context, and grants outside the allowed time window.

The phone persists a consumed grant marker before scheduling or applying access. Expiry, revocation, and reboot recovery retain replay history; a historical receipt cannot be used to reapply an old grant. The current signed effective policy still decides whether the package is selected, whether sleep applies, and whether a scope is enabled. An existing accepted lease keeps its original deadline across policy updates, but the newer restrictions still apply. A sleep override is explicit signed scope and is honored only when current policy enables it.

The policy cache rejects rollback to an older revision and conflicting documents with the same revision. A corrupt or missing snapshot cannot convert a previously managed package into unrestricted access. Device-protected enforcement state is kept separate from credential-protected pairing secrets. Storage protection and OS controls do not protect against a person who controls or resets the phone.

Notifications and realtime messages

Web Push wakes the browser service worker and can display request status even when the approver page is closed. The durable outbox retries delivery within bounded limits, but browser push providers and connectivity can delay or lose delivery. A push payload is not an approval decision. Notification actions still use the authenticated same-origin endpoint, and the server’s saved response is authoritative.

The Android SignalR hub accepts a paired device bearer in the Authorization header and refuses query-string tokens and approver cookies. It scopes the connection to the authenticated device and offers no client group-subscription method. A RequestChanged message contains a request identifier and version for refresh; it does not carry authorization. The foreground client fetches a durable receipt. Resume and bounded transient retry provide separate recovery paths.

Privacy and recovery

Usage event processing stays on the phone. The app does not upload screenshots, accessibility text, messages, full browser URLs, or precise location as part of this flow. The server retains request and decision state needed for receipts and pairing, plus push subscription data when the approver opts in. The Web Push delivery feature is configuration-gated.

When access is denied, a signature or policy cannot be verified, Usage Access is unavailable, or accounting becomes ambiguous, the local path fails closed for the affected selected package or bank session. Essential apps and explicit recovery routes remain available. Legacy Device Admin activation does not grant Device Owner authority; package suspension requires the app to be actually provisioned as Device Owner. A reset can remove that provisioning, so reset-proof enforcement is not promised. For choices and practical recovery steps, see the user guide and limitations.