mobile-appIn progress

CallVault

com.aoneahsan.callvault

CallVault is a personal, offline-first Android call-recording app โ€” Flutter UI over a Kotlin pluggable capture engine โ€” that keeps an on-device library (Drift/SQLite as source of truth), backs audio up to your own FilesHub/Laravel storage, and syncs only metadata to your own Supabase project, with a second admin dashboard built from the same codebase as a Flutter Web build.

2026-05 โ†’ PresentPersonal Project

At a glance

Category
mobile-app
Status
In progress
Started
May 2026
Last updated
2 months ago

Identifier

com.aoneahsan.callvault

Preview

Take a look before you go

The still below is painted first, then the running site loads behind it โ€” so the dialog is never an empty rectangle waiting on a network round trip. Where a site allows framing the live app takes over; where it refuses, the still stays and says so. Nothing is requested until you press.

CallVault, as its brand card renders

About

What this actually is

I did not build a way around Android's call-recording limits.

Android closed that door to ordinary applications after Android 10, and pretending otherwise produces software that records silence and a user who finds out afterwards. So CallVault treats capture as an abstraction with two honest strategies behind it instead.

A RecordingSource interface, two implementations.

One is a microphone foreground service that needs no root. The other is a folder watcher that ingests an external recorder's output on a rooted device. Which one you get depends on the phone in your hand rather than on a promise made on a page.

Neither of them is silent, and that is deliberate.

Recording runs behind a live banner and a persistent notification, so the person holding the phone can see it happening. An application that hides a recording is a different product with a different purpose, and this one is for recording your own calls.

The library is offline-first, and SQLite is the source of truth.

A Drift database on the device holds the record of what exists. Sync is a separate, idempotent, multi-stage state machine with retry and backoff, which means a failed upload is a state to resume from rather than a row that quietly vanishes.

That distinction is the whole reliability story.

A design where the server is the source of truth and the device holds a cache is a design where a bad afternoon on a train costs you a recording. Turning it round costs storage on the handset and buys a system that cannot lose something it already has.

Where the audio goes is worth reading twice.

Recordings upload to self-hosted FilesHub storage. Only metadata syncs to your own Supabase project, behind Postgres row-level security. There is no third-party analytics in the application at all.

The server is yours.

That is more setup than signing into somebody's account, and it is the only version of this that is defensible for a recording of a phone call, because the alternative is a private conversation sitting on infrastructure neither party to it has ever heard of.

Around that sit the ordinary things a library needs.

Playback with seek, skip and speed. Search across the number, the contact and your own notes, with a stats dashboard over the top. Notes are searchable because a call is usually easier to find by what was said in it than by the number that made it. An optional biometric lock on the application, and a Wi-Fi-only control for uploads.

The admin dashboard is the same codebase compiled for the web, which is the reason there is one at all.

The Flutter side is Riverpod and go_router with Material 3 on top, freezed for the models and just_audio for playback, with GitHub Actions doing the builds. One codebase, two outputs.

What it cost is distribution.

It is sideloaded by design, because the Play Store does not permit silent call recorders, so this is an application somebody installs deliberately rather than one they come across. It is Android-only. It is in development rather than finished, and saying so is cheaper than having it discovered.

That last sentence is on the page for the same reason the banner is on the screen.

It is at callvault.aoneahsan.com.

Whether recording a particular call is lawful where you are standing is a question about your jurisdiction and not about this software, and no application is able to answer it for you.

Worth knowing

  • Works *with* Android's recording lock, not around it โ€” instead of pretending to capture the remote party (impossible for a normal app since Android 10), CallVault abstracts capture behind a pluggable `RecordingSource` and ships two honest strategies (no-root mic vs. rooted folder-watcher). The constraint is documented, not hidden.
  • Sideloaded by design, not by accident โ€” Play Store bans silent call recorders, so distribution is intentionally an APK; the README and store-listing copy both state this plainly.
  • The device is the source of truth โ€” Drift/SQLite holds everything first; the iron rule is that nothing is pruned before `status = SYNCED`, so a failed upload never loses a recording.
  • One codebase, two binaries โ€” and a hard web constraint โ€” an "IRON RULE" keeps `dart:io` out of the web import closure so `flutter build web` (the admin dashboard) compiles; admin audio plays URL-only, never from a local `File`.
  • Your-server-only privacy posture โ€” no third-party analytics or telemetry anywhere; audio to your FilesHub, metadata to your Supabase, RLS owner-scoped.
  • Security gate is live, not JWT-cached โ€” admin access is decided by a live `is_admin()` / `currentProfileProvider`, never by trusting JWT `user_metadata`; clients stay on the anon key, `service_role` lives only in edge functions.
  • Free-tier kept warm โ€” a GitHub Actions `supabase-keepalive.yml` workflow pings the free Supabase project so it doesn't auto-pause.
  • Blueprint-first build โ€” an 18-doc devplan (`docs/devplan/00..17`) plus resumable JSON trackers drive the work, and store/publishing assets already exist under `app-publish-assets/` (SVG-first graphics + policy-safe Play copy).

Built with

  • Flutter
  • Dart
  • Riverpod v2
  • go_router
  • Drift (SQLite)
  • Kotlin
  • Supabase
  • FilesHub
  • Material 3
  • freezed
  • just_audio
  • GitHub Actions

Key features

What it does, and what that costs to build

Each of these is a capability the stack genuinely provides. None of them is an outcome nobody measured โ€” there is no "cut onboarding by 40%" on this page, because no one measured onboarding.

  • Transparent call recording with a live banner and persistent notification
  • Pluggable capture engine (no-root mic service or rooted folder watcher)
  • Offline-first library where SQLite is the source of truth
  • Idempotent multi-stage sync pipeline with retry and backoff
  • Your-server-only storage: audio to FilesHub, metadata to your Supabase
  • Audio playback with seek, skip, and speed controls
  • Search by number, contact, or notes plus a stats dashboard
  • Optional biometric app lock and Wi-Fi-only upload controls

Screenshots

5 slots, 2 of them filled in

These are designed frames, not pictures. Each one records what belongs in the slot and at what width; the capture itself is taken from the running app. Drawing a fake screenshot here would put an image on the site that no build has ever produced.

Timeline

Still being worked on

  1. May 2026

    Work started

    The earliest month on record for CallVault.

  2. Sep 2026

    Last change

    Status is in-progress โ€” 2 months ago. Ongoing, so this row moves whenever something lands.

Questions

Common questions

The questions that actually arrive, answered in the first sentence.

Who built CallVault?
Ahsan Mahmood built it, in Flutter and Dart with a Kotlin capture engine underneath, and it is at callvault.aoneahsan.com. Riverpod holds the state, go_router the navigation, Drift the on-device database, and the same codebase compiles to a Flutter Web admin dashboard so there is no second application to keep in step. It is in development rather than finished, and it is Android-only. The person who wrote the capture engine is the person who wrote the sync pipeline it feeds.
Does it record without the caller knowing?
It does not record without YOU knowing: a recording runs behind a live banner and a persistent notification, which is a deliberate design decision rather than a platform requirement somebody worked around. What the person on the other end of the call sees is not something the application controls, and nothing here claims to have told them. An application that hides a recording is a different product with a different purpose, and this one exists to record your own calls. Whether a given recording is lawful where you are is a question about your jurisdiction rather than about the software, and no application can answer it on your behalf.
Where do the recordings actually go?
To your own servers, and nowhere else. Audio uploads to self-hosted FilesHub storage, while only metadata syncs to your own Supabase project behind Postgres row-level security, so the recording and the record of it live in two places you control. There is no third-party analytics in the application at all. That arrangement costs more to set up than a vendor account would, and it is the only arrangement that is defensible for a recording of a phone call.
What happens when an upload fails?
Nothing is lost, because SQLite on the device is the source of truth rather than a cache of the server. Sync is a separate idempotent multi-stage state machine with retry and backoff, so a failed upload is a state to resume from rather than a row that quietly disappears. A Wi-Fi-only setting exists for anyone who would rather uploads waited for a network they are not paying for by the megabyte. Being offline-first here is a data-integrity decision more than a convenience.
Does CallVault work on iPhone?
No. It is Android-only, and the capture engine is Kotlin sitting on Android APIs, so there is nothing here that could be pointed at another platform without being rewritten. There is no iOS release behind any of my work in any case, because there is no Apple Developer account here and nothing I build has shipped to the App Store. It is also sideloaded by design rather than installed from a store, because the Play Store does not permit silent call recorders.

Keep looking

More mobile work

  • SM

    SMS Mobile App

    com.aoneahsan.smsapp

    Android-first SMS automation that dispatches campaigns through the phone itself.

    completedFeatured
  • PR

    PregnancyPal

    com.aoneahsan.pregnancypal

    Week-by-week maternal wellness, nutrition, vitals and prenatal exercise.

    completedFeatured
  • HA

    HabitForge

    com.aoneahsan.habitforge

    Habit tracking with visual strength scoring and offline-first sync.

    completedFeatured
All 23 projects