Roadmap

What is built, what is coming, and roughly when. Generated from ROADMAP.md.

The same information as ROADMAP.md, which is where it is written and where the reasoning behind each one lives.

154 items 144 done, 10 planned Shipped DSP engine: phase discard, many-to-one normalisation, CSPRNG modulation (done) Accent neutralisation, on by default (done) Cryptography: Argon2id, X25519+ML-KEM-768, XChaCha20-Poly1305 (done) Encryption at rest, by default, plaintext never touching disk (done) App lock: Argon2id verifier, persisted rate limit (done) Audio: device enumeration, live path, decode, WAV write (done) Metadata stripping: tags, EXIF/GPS, chunk-level RIFF cleaner (done) Microphone and camera monitor (Windows, Linux) (done) Tamper detection, unprivileged half (veilvoice-guard) (done) Secure erase, with an honest account of flash storage (done) CLI and desktop app (done) Website, wiki, no-JavaScript edition, legal gate (done) Search over the whole repository and website, with a static fallback (done) Portable release verifier needing no GnuPG (veilvoice-verify) (done) Install scripts for Windows, Linux and macOS (done) Reproducible signed releases on ten platforms (done) Four audit rounds: 47 defects found and fixed (done) In progress Documentation generator: a page, flowchart and banner for every crate and every .rs file, (done) Repository panel no longer shows a README's own markup as text (done) Write the missing module documentation for the 14 files that had almost none (done) Website split into a page per section, every published link still working (done) Motion and polish: smooth loading and scrolling, hover, CSS-first tooltips (done) Demonstration animation: a voice going in, the mark lighting up, an unidentifiable wave co (done) Cycling line of project facts, slow enough to read: CSS rather than an image, so it follow (done) Every website theme in the app, plus user-defined palettes with contrast computed rather t (done) Interactive workflow diagrams that open the relevant source, highlighted, in the site's pa (done) Randomised, user-configurable ratchet interval, with invalid input refused rather than cla (done) Installer with a window: Tokyo Night, animated, and portable described as the normal case (done) Optional companion setup: VB-CABLE on Windows, PipeWire on Linux, BlackHole on macOS, and (done) The site's search presented as an index, and animated (done) Security and monitoring features Screen-capture detection: which recorders are running, muted per program by an allowlist (done) Keyboard and mouse activity monitoring, reported as the heuristic it is (done) Ransomware canaries and mass-change rate detection, now veilvoice_guard::sentry (done) Learn what runs, then allowlist it, with time-limited grants and a log, now veilvoice_watc (done) veilvoice-policy: settings sealed with the existing post-quantum cryptography, and shaped (done) Privileged mode: an opt-in service, and an elevated no-service mode, with the difference v (done) Alert on driver and kernel-module installation; cross-view checks (done) Failsafe: on by default: notice the moment another program picks up a *real* microphone wh (done) Notification overlay: rounded, translucent, contrast computed, or an alert, or off (done) Duress and decoy passwords (done) Conversations, subtitles and video Conversation mode: tell the engine a recording holds more than one speaker, and give each (done) Up to ten speakers, each with a name, carried into the audio and into subtitles (done) A rolling seed per speaker, at a randomised interval inside a range the user sets, with no (done) Video output: the waveform, a circle per speaker in their palette colour or their own pict (done) A preview of the video and of the voices before anything is generated (done) An asynchronous pipeline, every speaker rendering at once rather than in sequence (done) Every crate and every .rs file explained: the technical workflow in a paragraph, then the (done) The website on mobile, and on every engine: not only the one it was written in (done) Seventh audit round across the whole tree, then the production deploy (done) Building it yourself, and proving the download matches Build the whole repository from source, from the tool itself: find or install a toolchain, (done) Reproducibility check: build here, hash what came out, and compare it against the publishe (done) The hashes are trusted only after the signature is: verify the detached signature over SHA (done) Set the machine up per platform: the build dependencies each operating system actually nee (done) Custom install: CLI, desktop app, or both, from a build you just made or from a download y (done) Four verbosity levels: nothing, minimal, normal (the default) and everything, applied to e (done) Group mode, where you can see it Group mode in the desktop app, shown as a mode rather than hidden in a flag: off by defaul (done) A name and a colour per speaker in the app: the colour chosen automatically to be as disti (done) Live levels while a recording is running, in the app and in the terminal (done) Seeing it before you install it The live monitor: what is going in and what is coming out, on every tab, on by default, an (done) An interactive demonstration on the website: the inside of the application and of the comm (done) A frequently asked questions page, answering what gets asked rather than what is convenien (done) A drawn graphic for every workflow chart: coloured arrows, an explanation inside the pictu (done) This roadmap, published as a page, with a picture of what is done and what is not, generat (done) A video of the roadmap, scrolling what is finished, with a short pause and a countdown bef (done) The front page animation, in more depth: the same picture, saying what the engine actually (done) A full security and functionality audit, and an optimisation pass, before the next deploy: (done) The lock, the guard, and a window that does not stutter The lock screen tells an attacker nothing: no explanation of what the lock is or is not wo (done) veilvoice-guard inside the desktop application: the integrity record taken at the first la (done) The app lock, hardened as far as it honestly goes: an authentication tag under the passphr (done) What the lock is worth, written down properly: one account, in the documentation, separati (done) Every website palette in the application, chosen from the interface (done) A window that does not stutter: the interface measured rather than described, every task o (done) Finally Fifth audit round: every vulnerability class across the tree, twelve findings written up i (done) v0.1.10 released: ten platforms, signed, and verified by hand after publication (done) Ready for the release audit: the RPM built, lintian run and its findings fixed, manual pag (done) Encrypted volumes: Cryptomator, VeraCrypt, and the disk underneath Find the encrypted volumes this machine already has: detect an installed Cryptomator or Ve (done) Write veiled output into a chosen volume: a destination that is a Cryptomator vault or a m (done) The hidden-volume question, asked properly: asked before the first write, three answers, a (done) The guided path, for when detection fails: plain instructions, a folder chosen by hand, an (done) What full-disk encryption is for, said once and said properly: BitLocker, FileVault, LUKS (done) The app lock as a key, not only a verifier: the app-lock passphrase seals everything VeilV (done) Asked for after the encrypted volumes A video of a veiled recording: a black frame and the audio, so a recording can be posted w (done) Import from every format OBS writes: bring in a recording made elsewhere, video or audio, (done) Veil the other person afterwards: the interviewee given their own voice in post, through t (done) GnuPG verification inside the window: in the verify tab, beside the hash check, using the (done) veilvoice-verify finds the release itself: GnuPG arguments where wanted, and an auto that (done) An autolock timeout: on at half an hour, from five minutes to forty eight hours, chosen fr (done) Group mode explained where it is used: how to build a plan, what each field does, and what (done) Release notes people can actually read: every release listed newest first, its notes openi (done) One version per release, in order, enforced: the tag, the workspace and every package defi (done) v0.1.15 released: the audit run over everything since v0.1.14, CI green, and the release p (done) A verifier anybody can use, checking everything: one press or one command checks the signa (done) The window, and the things that were marked done and were not A window that is genuinely idle: the cause of the frames found by asking the toolkit rathe (done) The window toolkit brought forward: eframe and egui from 0.29 to 0.32, which is what made (done) What drew the window, reported: the graphics choices named in the source with their reason (done) Crash reports about the failure they are about: the closing note chosen from the panic rat (done) One version, in one file: every other copy derived from Cargo.toml or checked against it, (done) v0.1.17 released: the idle window fixed at the cause, the toolkit upgraded, and the releas (done) Asked for while v0.1.17 was being built A demonstration that is the program: five recorded sessions of the real binaries replayed (done) A crash report offered rather than buried: the report already written to disk surfaced abo (done) A first run that explains itself: one card per tab saying what it is for, skippable, and a (done) An obfuscated program folder: VeilVoice's own files encrypted under names derived from the (done) A first-run setup and tour: the app lock, the recording passphrase and the autolock explai (done) Host the website locally: a script and an nginx config that serve website/ exactly as GitH (done) A self-signed code certificate beside the OpenPGP key: a detached, signed APPMANIFEST.json (done) Asked for after v0.1.18 Memory that reads as ciphertext from outside the process: the app-lock key holds the secre (planned) A layout no two copies share: the in-memory shape of that protected state varied per build (planned) Tamper noticed, and the source named: an attempt to read or write VeilVoice's memory from (planned) One author in the history, and every commit verified: the commit history rewritten so the (done) A demonstration you navigate rather than watch: the website's demo driven by the reader, a (done) Told when anything touches VeilVoice at all: every attempt to open, read, write or attach (planned) A verdict, and then a choice: something reaching into VeilVoice is reported with what it d (planned) The allowlist that cannot be worn as a disguise: a signed antivirus reading VeilVoice's me (planned) A studio vault that needs both keys: every recording the studio makes, and every preview i (done) Recording Studio: the place recording happens, with the vault already open because both lo (done) Recording Browser: everything in the vault, listed with what it is and when it was made, p (done) Neither lock alone, proven rather than asserted: tests that open the vault with each secre (done) A pass for size and speed, changing no behaviour: the tree read for the things that accumu (done) Written so the next pass finds nothing: the practices that pass established are now the st (done) The BSDs built twice, like everywhere else: FreeBSD, OpenBSD and NetBSD were the three pla (done) A BSD reader can check their own copy either way: all three routes written up per system r (done) The live scramble moved into the Studio: veiling as it runs has stopped being a separate t (done) Both sides of the glass, kept or discarded: the Studio asks which of the two to keep befor (done) Audio that says when it was interfered with: a device swapped or unplugged mid-session, an (done) Every guest, veiled and plain, side by side: two bars per speaker in group mode, what went (done) Decoy vaults, as many as you choose: the Browser asks whether to make dummy vaults and how (done) Setup inside the app, with defaults it worked out: first run ends on a card that reads thi (done) Portable first, and it tells you where it is: a folder called veilvoice-data beside the pr (done) Acceleration on unless you turned it off: the window asks the platform for a hardware cont (done) A video of who said what, from the Studio: done. The preview page and the video file are n (done) Resolutions somebody would actually pick: 1080p as the default, with 1440p, 2160p and a cu (done) How much code this actually is, counted one way and said once: a functional line count in (done) v0.1.19, the audited release: the full audit of roadmap item 127 run over the whole reposi (done) The full final audit, and what counts as complete: no part of this repository is signed of (done) The demonstration on the page, and the drawing of it gone: the recorded terminal sessions (done) veilvoice verify, said that way everywhere: nine places still described a veilvoice-verify (done) Staleness as an invariant rather than a habit: CLAUDE.md now states that a change is not f (done) The Recording Studio, in full: everything roadmap items 121 to 137 specify, built and work (done) The Studio release: 145 with the Browser, the decoys, the setup and the BSD reproducibilit (planned) Several microphones at once, veiled and metered each: one input per guest, each veiled by (done) The window draws at the display's rate, and says so: the animations ran at twenty frames a (done) A signature check that needs only a signature check: veilvoice verify and the Verify tab c (planned) The meters above a call: the live monitor had two places to sit and both were inside the V (done) Mutation testing, as a check rather than as an afternoon: changing the code a line at a ti (done) The numbers the README states, written by the tool that measures them: the functional line (done) A link into a page lands on what it names: the site's header is sticky, so a fragment jump (done) What this project says it is made of, checked against what it is: the front page renders t (done) Companion software installed for you, wherever that can honestly be done: today VeilVoice (planned) Every page says where it lives, and a crawler is told it may read the site: og:image was a (done) The banner moves on the no-JavaScript page too: that edition showed the still while the ma (done) Fewer crates, chosen by what somebody would actually take: twenty-seven crates for one app (done) The wiki becomes the documentation, and publishes itself: the wiki held the reference, a p (done) The lock and the unlock are one control: the button that locks the window and the button t (done) VeilVoice on a phone: an Android package a person installs without developer tools, signed (planned) done: 144 next: 0 planned: 10 blocked: 0

144 of 154 are built, tested, documented and in main. Area is not progress. Every square is the same size and one item is not one day: the first is the whole signal engine, and another is a page of questions. The estimates below are the closest thing to an answer, and they are estimates.

Everything that is finished, in one go

A little under half a minute. It scrolls what is done, waits four seconds with a countdown in the corner, and starts again.

144 items finished 1 DSP engine: phase discard, many-to-one normalisation, CSPRNG modulation 2 Accent neutralisation, on by default 3 Cryptography: Argon2id, X25519+ML-KEM-768, XChaCha20-Poly1305 4 Encryption at rest, by default, plaintext never touching disk 5 App lock: Argon2id verifier, persisted rate limit 6 Audio: device enumeration, live path, decode, WAV write 7 Metadata stripping: tags, EXIF/GPS, chunk-level RIFF cleaner 8 Microphone and camera monitor (Windows, Linux) 9 Tamper detection, unprivileged half (veilvoice-guard) 10 Secure erase, with an honest account of flash storage 11 CLI and desktop app 12 Website, wiki, no-JavaScript edition, legal gate 13 Search over the whole repository and website, with a static fallback 14 Portable release verifier needing no GnuPG (veilvoice-verify) 15 Install scripts for Windows, Linux and macOS 16 Reproducible signed releases on ten platforms 17 Four audit rounds: 47 defects found and fixed 18 Documentation generator: a page, flowchart and banner for every crate and every .rs file, mirrored to the website and the GitHub wiki 20 Repository panel no longer shows a README's own markup as text 21 Write the missing module documentation for the 14 files that had almost none 22 Website split into a page per section, every published link still working 23 Motion and polish: smooth loading and scrolling, hover, CSS-first tooltips 24 Demonstration animation: a voice going in, the mark lighting up, an unidentifiable wave coming out 25 Cycling line of project facts, slow enough to read: CSS rather than an image, so it follows the reader's theme and needs no script 26 Every website theme in the app, plus user-defined palettes with contrast computed rather than assumed 27 Interactive workflow diagrams that open the relevant source, highlighted, in the site's palette 28 Randomised, user-configurable ratchet interval, with invalid input refused rather than clamped 30 Installer with a window: Tokyo Night, animated, and portable described as the normal case rather than as something missing 31 Optional companion setup: VB-CABLE on Windows, PipeWire on Linux, BlackHole on macOS, and Audacity everywhere, detected if present and installed only if confirmed 32 The site's search presented as an index, and animated 33 Screen-capture detection: which recorders are running, muted per program by an allowlist 35 Keyboard and mouse activity monitoring, reported as the heuristic it is 36 Ransomware canaries and mass-change rate detection, now veilvoice_guard::sentry 37 Learn what runs, then allowlist it, with time-limited grants and a log, now veilvoice_watch::appctl 38 veilvoice-policy: settings sealed with the existing post-quantum cryptography, and shaped so they can only be tightened 39 Privileged mode: an opt-in service, and an elevated no-service mode, with the difference visible to the user 40 Alert on driver and kernel-module installation; cross-view checks 65 Failsafe: on by default: notice the moment another program picks up a *real* microphone while you are being veiled, warn, and close it 41 Notification overlay: rounded, translucent, contrast computed, or an alert, or off 42 Duress and decoy passwords 46 Conversation mode: tell the engine a recording holds more than one speaker, and give each a distinct voice while destroying every voiceprint 47 Up to ten speakers, each with a name, carried into the audio and into subtitles 48 A rolling seed per speaker, at a randomised interval inside a range the user sets, with no interval hardcoded and a fresh one at every launch 49 Video output: the waveform, a circle per speaker in their palette colour or their own picture inside a coloured ring, a title, and a black or image background with padding 50 A preview of the video and of the voices before anything is generated 51 An asynchronous pipeline, every speaker rendering at once rather than in sequence 52 Every crate and every .rs file explained: the technical workflow in a paragraph, then the same thing in plain words 53 The website on mobile, and on every engine: not only the one it was written in 54 Seventh audit round across the whole tree, then the production deploy 55 Build the whole repository from source, from the tool itself: find or install a toolchain, pin it to rust-toolchain.toml, and run the same build the release does 56 Reproducibility check: build here, hash what came out, and compare it against the published SHA256SUMS entry for this platform, saying which files matched and which did not 57 The hashes are trusted only after the signature is: verify the detached signature over SHA256SUMS against the project key *before* any hash from it is compared, and refuse rather than warn if it does not verify 58 Set the machine up per platform: the build dependencies each operating system actually needs, detected, named with who ships them, and installed only on an explicit yes 59 Custom install: CLI, desktop app, or both, from a build you just made or from a download you just verified 60 Four verbosity levels: nothing, minimal, normal (the default) and everything, applied to every one of the above, with the exit status carrying the answer when the output carries nothing 61 Group mode in the desktop app, shown as a mode rather than hidden in a flag: off by default, a toggle that does not persist, and a separate tick for "always start in group mode" 62 A name and a colour per speaker in the app: the colour chosen automatically to be as distinct as the number of speakers allows, overridable per speaker, and drawn from every palette the website offers 63 Live levels while a recording is running, in the app and in the terminal 66 The live monitor: what is going in and what is coming out, on every tab, on by default, and a preview that lets you hear yourself veiled before anybody else does 67 An interactive demonstration on the website: the inside of the application and of the command line, laid out in the site's own colours, that a reader can click through before downloading anything 68 A frequently asked questions page, answering what gets asked rather than what is convenient to answer 69 A drawn graphic for every workflow chart: coloured arrows, an explanation inside the picture, and every word wrapped rather than running off the edge 70 This roadmap, published as a page, with a picture of what is done and what is not, generated from this file so the two cannot disagree 71 A video of the roadmap, scrolling what is finished, with a short pause and a countdown before it repeats 72 The front page animation, in more depth: the same picture, saying what the engine actually does to the signal rather than one word 73 A full security and functionality audit, and an optimisation pass, before the next deploy: the whole tree, both halves, and the last thing that happens 74 The lock screen tells an attacker nothing: no explanation of what the lock is or is not worth while it is locked, the account of that moved to the documentation and to the unlocked application, and a small animation in its place 75 veilvoice-guard inside the desktop application: the integrity record taken at the first launch and checked at every one after, sealed under the app-lock passphrase where there is one 76 The app lock, hardened as far as it honestly goes: an authentication tag under the passphrase, two copies with the spare administrator-owned where the platform allows it, restoration when one goes, randomised names and masked contents, and a report that only the passphrase can clear 77 What the lock is worth, written down properly: one account, in the documentation, separating the parts that are real from the parts that are only obscurity 78 Every website palette in the application, chosen from the interface 79 A window that does not stutter: the interface measured rather than described, every task off the drawing thread, and the smallest amount of code that does it 44 Fifth audit round: every vulnerability class across the tree, twelve findings written up individually (F-48 to F-59) 45 v0.1.10 released: ten platforms, signed, and verified by hand after publication 80 Ready for the release audit: the RPM built, lintian run and its findings fixed, manual pages generated from the binaries, 32-bit re-run over the new code, and the parser campaign run over all six targets with a seed corpus kept 81 Find the encrypted volumes this machine already has: detect an installed Cryptomator or VeraCrypt, and the vaults and mounted volumes each is offering, without asking either to do anything 82 Write veiled output into a chosen volume: a destination that is a Cryptomator vault or a mounted VeraCrypt volume, remembered, and used for every export 83 The hidden-volume question, asked properly: asked before the first write, three answers, and a job that will not start until one is given 84 The guided path, for when detection fails: plain instructions, a folder chosen by hand, and the same confirmation a detected one gets 85 What full-disk encryption is for, said once and said properly: BitLocker, FileVault, LUKS and LUKS2, and the OpenBSD and FreeBSD equivalents, single-sourced and shown in both 86 The app lock as a key, not only a verifier: the app-lock passphrase seals everything VeilVoice veils, automatically, as an option that says what it costs 87 A video of a veiled recording: a black frame and the audio, so a recording can be posted where only video is accepted 88 Import from every format OBS writes: bring in a recording made elsewhere, video or audio, and take the sound out of it 89 Veil the other person afterwards: the interviewee given their own voice in post, through the group plan that already exists 90 GnuPG verification inside the window: in the verify tab, beside the hash check, using the GnuPG somebody already has 91 veilvoice-verify finds the release itself: GnuPG arguments where wanted, and an auto that looks in Downloads, checks the archive, and checks what came out of it 92 An autolock timeout: on at half an hour, from five minutes to forty eight hours, chosen from a list or typed, with the range itself adjustable, and offered during first-run setup 93 Group mode explained where it is used: how to build a plan, what each field does, and what happens without one 94 Release notes people can actually read: every release listed newest first, its notes opening in place, and every file one click away 95 One version per release, in order, enforced: the tag, the workspace and every package definition checked against each other before a release can go out 96 v0.1.15 released: the audit run over everything since v0.1.14, CI green, and the release published 97 A verifier anybody can use, checking everything: one press or one command checks the signature, the archive, every file you extracted, and then asks your own GnuPG the same question 98 A window that is genuinely idle: the cause of the frames found by asking the toolkit rather than by reasoning, the animation stopped when the window is unfocused or being dragged, and the result measured to nothing 99 The window toolkit brought forward: eframe and egui from 0.29 to 0.32, which is what made the frames answerable, and the runtime dependency it added declared everywhere a package can declare it. Brought forward again to 0.36 with roadmap item 148, which took ttf-parser out of the dependency graph and one advisory out of the exception list with it 100 What drew the window, reported: the graphics choices named in the source with their reasoning, and the driver actually obtained shown on the About tab, read from the driver 101 Crash reports about the failure they are about: the closing note chosen from the panic rather than the same guess every time, and a missing system library named along with the package that carries it 102 One version, in one file: every other copy derived from Cargo.toml or checked against it, with the files that keep a history added to rather than rewritten 103 v0.1.17 released: the idle window fixed at the cause, the toolkit upgraded, and the release published 104 A demonstration that is the program: five recorded sessions of the real binaries replayed on the website, re-run and compared on every build, sitting with the screenshots 105 A crash report offered rather than buried: the report already written to disk surfaced above whatever tab you land on, with what it contains listed and readable in full before anything leaves your machine, and the filing left to the person 106 A first run that explains itself: one card per tab saying what it is for, skippable, and after an upgrade only the tabs that are new, with portable and installed said plainly on the last card 109 An obfuscated program folder: VeilVoice's own files encrypted under names derived from the app-lock passphrase, with decoys among them, so the lock protects data rather than only a window 110 A first-run setup and tour: the app lock, the recording passphrase and the autolock explained and offered once, skipping whichever is already set 111 Host the website locally: a script and an nginx config that serve website/ exactly as GitHub Pages does, so the site survives the repo or Pages going down, and is the audit surface during development 112 A self-signed code certificate beside the OpenPGP key: a detached, signed APPMANIFEST.json describing each binary, verify scripts for Unix and Windows, and an import tutorial, for organisations that want a known publisher without breaking reproducible builds 116 One author in the history, and every commit verified: the commit history rewritten so the whole of it matches the attribution rule this project already states, with the assistance credit staying exactly where a reader looks for it (the README, and the footer of every page) rather than in a trailer that makes a second contributor of it, and every commit in the history signed rather than only the recent ones. Trees are unchanged by this, so reproducible builds still verify 117 A demonstration you navigate rather than watch: the website's demo driven by the reader, a header per part of the program, and the screenshots for whichever they pick shown under it. Not an imitation of the interface: the real captures, the ones the build already regenerates and compares, so the demo cannot drift from the program. The command line gets the same treatment, a worked case per thing somebody actually wants to do, explained rather than listed, and the site's own Demo link lands on the section and opens it 121 A studio vault that needs both keys: every recording the studio makes, and every preview it holds, sealed into one vault whose key exists only when the app lock *and* the at-rest passphrase have both been given. Neither alone derives it, so a stolen laptop with the app unlocked opens nothing and a known recording passphrase without the app opens nothing. The same post-quantum sealing used everywhere else, held in the same page-locked, zeroizing memory, with the same honest report of how much the operating system actually agreed to lock 122 Recording Studio: the place recording happens, with the vault already open because both locks were answered on the way in. Capture, monitor, preview and re-take without a plaintext file existing at any point, and a session that locks itself back up when the app does rather than staying open behind a screensaver 123 Recording Browser: everything in the vault, listed with what it is and when it was made, played back by decrypting into page-locked memory rather than writing a temporary file somebody would have to remember to shred, whole rather than in blocks because the container is sealed and authenticated as one piece. Export is a deliberate act with its own warning, because leaving the vault is the moment the protection ends 124 Neither lock alone, proven rather than asserted: tests that open the vault with each secret in turn and get nothing, and a stated account of what the pair does and does not buy. It raises the cost of a stolen machine and of a guessed passphrase; it does not defeat somebody watching the process while both are entered, and that is written beside the feature rather than left implied 125 A pass for size and speed, changing no behaviour: the tree read for the things that accumulate rather than the things that break. Work repeated that could be done once, allocations in paths that run per frame or per sample, generic code instantiated more times than it needs to be, dependencies pulled in for one function, and anything the compiler is doing twice. Measured before and after, with the binary size and the timings recorded, and not one behavioural change: every test that passed before passes after, or the change is reverted rather than argued for 126 Written so the next pass finds nothing: the practices that pass established are now the standing way this project is written, in CLAUDE.md, and three of the four are enforced by a build rather than by somebody remembering. No audio callback may allocate, block or print, checked by a test that reads the callbacks themselves rather than by the comments that said so. Every dependency says what it is for on the line that declares it, checked in CI, which found three on its first run that no line of code referred to. Work that can be done once is done once, and the comment says what made it constant. The fourth is a habit and is written as one: the reading happens before the push rather than to the tree once a year 128 The BSDs built twice, like everywhere else: FreeBSD, OpenBSD and NetBSD were the three platforms whose archives said not-verified (built once, in a VM), which was honest and was the only gap in the reproducibility claim. The second build now happens in the same VM, with the same path remapping and the same SOURCE_DATE_EPOCH the other ten platforms use, and the verdict is published in the release notes beside theirs. At v0.1.19 all three reported reproducible, so every one of the eleven targets is now verified rather than eight of them. A BSD that stops reproducing says so in those words rather than quietly dropping the line 129 A BSD reader can check their own copy either way: all three routes written up per system rather than left as a Linux instruction somebody has to translate. veilvoice verify on its own is the same command everywhere and needs no GnuPG, no network and none of the system's own tools, which is why it is offered first and why a BSD reader has nothing to translate. The second opinion is where systems differ, and the script now has a spelling for the BSDs: it had two, Linux and macOS, and a BSD reader fell through to the Linux one and was told to run a command this project's *other* script says they do not have. That is F-167. The guide's table of which system runs what is checked against the program rather than typed beside it, and the one command this project has not run on a BSD, installing GnuPG on OpenBSD and NetBSD, is left unsaid rather than guessed 130 The live scramble moved into the Studio: veiling as it runs has stopped being a separate tab and is what the Studio does. It was already the same engine, the same ratchet and the same virtual-cable routing on both screens, which is what made two of them wrong rather than merely redundant: the Studio recorded with whichever devices the other tab happened to be set to, and each tab started a session of its own, so veiling on one and recording on the other opened the same microphone twice. There is one starter now. The tab is the voice above and the take below, the voice half works with the vault shut because veiling a call has never needed a vault, and ending a take leaves the veiling running 131 Both sides of the glass, kept or discarded: the Studio asks which of the two to keep before the button rather than after it, because a recording of somebody's real voice is not a thing to discover having made. The veiled voice is selected, both is offered, and the microphone on its own is offered last. Anything that keeps the microphone says so in the same words the plaintext path uses: it is sealed in the vault as strongly as anything else, and it is still a recording anybody who opens the vault can hear who was speaking in. Never remembered between runs and reset when the window locks, for the reason group mode is not remembered. Both kept means two takes, the unveiled one named for it. The command line's record keeps the veiled voice only and is unchanged: this is a Studio decision, made where the vault that receives it is 132 Audio that says when it was interfered with: a device swapped or unplugged mid-session, and another program taking the microphone while a take is running, are noticed and shown rather than recorded silently. This row used to open by asking for the samples reaching the recorder to be *checked* against what the engine produced. They cannot differ: the recorder is fed from inside the output callback, from the same slice the engine has just written into, so that check is a buffer compared with itself. It is a property to keep rather than one to measure, and a test reads the source for it. What was actually missing was the report: the platform announces a stream error on a callback of its own, and both of them were eprintln! and nothing else, so on Windows, where the window has no console, a microphone unplugged mid-call was silent. Stated limit up front, beside the report rather than after it: this notices interference with VeilVoice's own path and cannot vouch for a microphone that was already lying 133 Every guest, veiled and plain, side by side: two bars per speaker in group mode, what went into each of their turns and what the engine produced from it, drawn as the render walks the file. One bar answers "is something being written" and not "is this person being veiled", which is the question somebody rendering an interview is asking; two that move differently are the only thing on screen showing the engine is between them. Under them, in the same words the live meters use, what they cannot show. The row asked for this live, and that half is roadmap item 147: group mode works on a recording that already exists and never opens a device, the live path opens one input, and there is no per-guest live signal in this tree to draw. The one-microphone live case already has its two bars, in the Studio 134 Decoy vaults, as many as you choose: the Browser asks whether to make dummy vaults and how many, sizes them from the real one so they are indistinguishable by size, and fills them with encrypted nonsense under keys that are thrown away. Cracked, one yields bytes that will not parse as anything: a decoy is not a vault with weak contents, it is a vault whose contents never existed. Asked there rather than at first run, because a decoy is sized from the real vault and at first run there is not one yet. The real vault is found by trying each directory rather than by name, so a decoy is not told apart by reading the folder either. The count defaults from the free space actually detected rather than from a number picked here, and the honest limit is stated: this raises the cost of a search, it does not make the real vault unfindable to somebody who watches you open it 135 Setup inside the app, with defaults it worked out: first run ends on a card that reads this machine rather than asserting anything about it. Where recordings will go and how much room is free there, read from the operating system and said as an hour of veiled audio rather than as a number of bytes. How many devices there are to record from and play to. What the window will ask the graphics driver for, with the tick that turns it off. Every one says what it costs, and where the machine will not answer the card says that instead of printing a figure nobody measured. Nothing on it has to be answered and nothing is a gate 136 Portable first, and it tells you where it is: a folder called veilvoice-data beside the program makes the settings, the vaults and the lock live in it, so a copy on a stick stays a copy on a stick. Opted into rather than detected, because "beside the program if that is writable" would move an ordinary installation's state the day somebody unpacked it somewhere writable, and the symptom would be an empty vault. The About tab prints the exact paths it is using and says which of the two arrangements is in force, rather than leaving somebody to guess. Installing later can carry those settings over or leave them, and that is a question the install button waits for rather than a default, because the answer differs for a shared machine and a private one. Carried means copied, never moved, and nothing already at the destination is replaced 137 Acceleration on unless you turned it off: the window asks the platform for a hardware context and accepts a software one, so a virtual machine, a remote desktop or a server with no card still opens. One tick in Settings turns the asking off, for the machines where a driver accepts and then draws badly: a hybrid-graphics laptop handing over the wrong adapter, or a black window on a broken OpenGL path. That case cannot be detected, because from inside the process it looks like success, so it is a switch rather than a measurement and the honest limit is said where the tick is. The About tab shows what was asked for beside what the driver actually gave, which is the pair that answers "why is this slow" 139 A video of who said what, from the Studio: done. The preview page and the video file are now two drawings of one recording rather than a picture and a black rectangle. A circle per speaker in their own colour, whoever is talking lit, a level under each name that moves with the sound, the waveform and a playhead. The frames are drawn here, as pixels: raster is a canvas with rectangles, antialiased circles and a PNG writer, and font is a five-by-seven monospace face of ninety-five glyphs written out in the file. Neither borrows anything, because the drawing is SVG and no ffmpeg can be assumed to read SVG, and pulling in a rasteriser to convert it would have undone the argument the ffmpeg module already makes about large C libraries. The one dependency is miniz_oxide for the deflate PNG needs, which was already in this tree under flate2. A picture is written when the picture changes, not thirty times a second: the playhead moves a pixel at a time rather than a frame at a time, so ten minutes at thirty writes hundreds of files rather than eighteen thousand, and the saving is reported rather than claimed. A short recording holds nothing and should not, because the playhead crosses the whole waveform however long the recording is. That is why the ffmpeg command is a concat list with a duration per picture rather than a numbered sequence, which would have played an hour of conversation in a few seconds. Names outside printable ASCII cannot be drawn by a face this size and come out as boxes; the render names them rather than letting somebody find out by watching. Single-person recordings take the same path as a group of eight 140 Resolutions somebody would actually pick: 1080p as the default, with 1440p, 2160p and a custom size offered, rather than the 1280x720 the renderer starts at today. The size the display is actually running at is offered as a preset where the platform will say, and where it will not the list is simply the fixed ones: a guess about somebody's monitor is worse than a menu 141 How much code this actually is, counted one way and said once: a functional line count in the README, and the same count per crate in each crate's own documentation, with the definition stated where it is used: a line holding code, not a blank line and not a comment. Deliberately a new number rather than a redefinition of an existing one. The per-file line counts already printed on the generated pages, in the artwork and in the reference links are a different measure, counted differently, and are left exactly as they are: changing what an existing number means, everywhere it appears, to match a new definition would silently alter every page and link that carries one 138 v0.1.19, the audited release: the full audit of roadmap item 127 run over the whole repository, everything it finds fixed, and the tag cut on what came out. Not the code alone: the documentation, the website, the packaging, the scripts and the reproducibility, and the optimisation pass, because a release audited in part is a release described inaccurately. The Studio is deliberately not in it. A release named after a feature that is still being written is the thing this roadmap exists to prevent, so 0.1.19 is the release that says the tree is sound and 0.1.20 is the one that says what was built on it 127 The full final audit, and what counts as complete: no part of this repository is signed off until every part of it has been. Security, memory safety and the post-quantum surface; correctness and QA over every crate; reproducibility of the build and of every generated artefact; the documentation, the website, the packaging and the scripts; and the optimisation pass above, because bloat that nobody measured is a claim nobody checked. A round that covers the code and skips the documentation, or covers both and skips whether the thing still builds byte for byte, is not a final audit and is not to be described as one 142 The demonstration on the page, and the drawing of it gone: the recorded terminal sessions and the photographs of the window both on the front page in the order somebody meets them, neither behind a button. The hand-drawn CSS model of the application is removed rather than relabelled: it sat beside photographs of the same interface and asked a reader to work out which to believe, on a site whose argument is that they should not have to take anybody's word for anything 143 veilvoice verify, said that way everywhere: nine places still described a veilvoice-verify executable that stopped being published at 0.1.18, three of them lists the program itself reads. The lists are now taken from the job that publishes the binaries, and a test reads the repository the way a reader does and fails on anything telling somebody to run a program that is not there 144 Staleness as an invariant rather than a habit: CLAUDE.md now states that a change is not finished until everything describing it has changed with it, that a fact appearing twice is derived or checked rather than repeated, and that the only exception is a record of the past. Written down because the two roadmap items above were the same failure found twice, in different files, months apart 145 The Recording Studio, in full: everything roadmap items 121 to 137 specify, built and working together rather than as parts. Recording in an environment that never lets a plaintext sample reach the disk, sealed post-quantum into a vault that needs both the app lock and the at-rest passphrase, held in page-locked zeroizing memory. It shows, at all times and both live and on replay, whether the voice being recorded is veiled or not: done, and the part that was missing was the running take, which said the clock and not which voice it was keeping, so a take of somebody's real voice looked exactly like one that was not for the whole of the recording. It has its own failsafe, separate from the application's, so a fault in the Studio stops the Studio rather than the recording: done. The device a take is being recorded from going away is the fault it catches, and it stores what was captured and stops, rather than discarding it, retrying, or moving the recording onto a microphone the person did not choose. Group mode records every guest with the same guarantees: done, and it is roadmap item 147, because group mode never opens a device and the live path opened one input. A room in the Studio opens one per guest, veils each into a voice of their own, and stores a take per guest beside the mix, in the same vault, under the same lock and with the same choice of which side to keep. The output is rendered inside the vault, viewed and listened to inside the vault, and leaving it is an export: a deliberate act, warned about, because that is the moment the protection ends. Something like a recording studio somebody already knows how to use, that happens to be secure, rather than a security tool somebody has to learn to record with. No longer carries a version number: it was aimed at v0.1.20, that release shipped with the parts named in their own entries, and a target date a release has already passed is worse than none 147 Several microphones at once, veiled and metered each: one input per guest, each veiled by its own engine with its own seed and destination voice, mixed into the one output a call or a recorder hears. The capture path is veilvoice_audio::room: a recorder per guest and one for the mix, one sample rate agreed across every device before anything opens, a ring per guest so one microphone's clock drifting is that guest's dropped samples rather than everybody's, and the honest account the row asked for as a number rather than a promise, since the output callback runs every engine before it returns and the load is the sum of their realtime factors against the deadline they share. The mix is summed and clipped and never limited, because a limiter is a dynamics processor and this program's whole claim is about what changes a voice. The Studio drives it: a guest list with a name and a microphone each, two bars per guest with the load and the clipping count beside them, and a take that stores the mix and every guest separately, veiled or unveiled on the same choice the single microphone has. The Studio holds one session or the other and never both, which is one field rather than two so it cannot be got wrong. Two guests on one microphone is refused by name before anything opens, the default device included, because one microphone carrying two people is one signal and veiling it gives both of them the same voice 148 The window draws at the display's rate, and says so: the animations ran at twenty frames a second by design, from a constant in the mark and a fifty-millisecond cadence in the busy path, and a reader with a 144 Hz display saw that as judder. The sixteen-millisecond veiling path was worse than it looks: a display at sixty shows a frame every 16.67 ms, so asking for one "within sixteen" misses the frame it wanted and lands on the next, which is thirty asked for as sixty. Done, and not by choosing a bigger number: while anything is moving the window asks for the next frame now and vsync spaces it, so it draws once per refresh at whatever the display runs at. That is also what makes the display measurable, since neither egui nor eframe exposes a refresh rate: frames paced that way are the display's own, and the median of the last thirty-two is a figure one slow frame cannot move, clamped between 30 and 240. Settings offers 30, 60, 90, 120, 144, 165 and 240 for somebody who wants fewer frames on a battery, and a live readout in the header. The About tab carries what it is aiming at, what the display measured, the rate as drawn and how many frames arrived late; a frame more than half again late is late, and two seconds of that says so once, naming what the window is drawing with. Idle still draws nothing. Nothing in the measurement allocates, locks or prints per frame 150 The meters above a call: the live monitor had two places to sit and both were inside the VeilVoice window, which on a call or while streaming is behind the thing being talked into, so the one picture of what a microphone is doing was covered exactly when it mattered. A third choice now: a small window of its own, kept above other windows, off the task bar, draggable and resizable, drawing the same two levels and the same sentence about what a level cannot tell you. Not the default, because a window that puts itself above everything is a thing to ask for. Closing it brings the strip back rather than turning the meters off, since the close button belongs to the window manager and pressing it means "not in my way". Where a platform will not give a second window it falls back to the floating card, which is the same thing inside the window 151 Mutation testing, as a check rather than as an afternoon: changing the code a line at a time and asking whether any test objects is the only thing this project runs that asks whether an assertion exists for what came back, as opposed to whether an input was explored. Its first run over four cryptographic files found fifteen changes the whole suite accepted, including one that replaced the randomness adapter with a constant. All three parts are in. mutants.yml runs the campaign weekly over the eight cryptography files and dispatches before a release, and its verdict is not a number: tools/mutants/check.py compares the run against tools/mutants/survivors.txt, a committed list where every entry carries the argument for why that mutant cannot be killed, so a new survivor is a diff somebody reads and a survivor that has been killed fails too, because the list would then claim something untrue. The campaign was extended to the app lock, the studio vault, the obfuscated store and the reversible encodings: 674 mutants, 81 survivors, and four rounds of writing tests and re-measuring brought that to fifteen, every one of them argued. And tools/audit/build_output.py fails the build on any build output outside the root target/, which is F-185, because the fifteen gigabytes the first attempt died on turned out to be written by this project's own tooling on every machine that is not Windows 152 The numbers the README states, written by the tool that measures them: the functional line count and the test count appear in README.md, on the front page and in one row of docs/AUDIT.md, and all four are typed by hand and compared against the tree by the website suite. The comparison is right and the typing is the problem: every change to any Rust file moves the line count, so a commit that touches code and does not touch those four places fails a check that has nothing to do with what the commit was for. Four times in one round was the measurement. tools/measured/generate.py now writes all ten of them from the numbers it already takes, using the same anchors the suite checks, so the tool that writes a claim and the suite that checks it cannot disagree about where the claim is. The comparison stays exactly as it was: it is the guard, and it no longer doubles as the thing that catches a person on every push 153 A link into a page lands on what it names: the site's header is sticky, so a fragment jump puts the heading underneath it unless the target is pushed down clear of the bar. The amount it was pushed by was one number, 90px, and the header is 133px at desktop widths, 171px where the navigation wraps to three rows, 115px on a phone, 143px at 320px and 81px on the reference pages. The rule also covered sections and the two larger headings only, so every entry on the releases page and every roadmap entry got nothing at all. Driven in a browser, 425 of 430 fragment links on this site landed wrong. The offset is measured from the header now and re-measured when the window changes shape or a font arrives late, the landing is held for a second afterwards because pictures below the fold can still move the page and it lets go the moment the reader scrolls, and where somebody landed is outlined briefly, which under reduced motion is an outline that sits there rather than fading. Navigation itself is untouched: no click is prevented and no history entry written, because the full-size screenshot viewers open through :target. F-191 154 What this project says it is made of, checked against what it is: the front page renders the README, the README lists the crates twice and the library guide lists them a third time, and the three had drifted to thirteen, twelve and thirteen rows against a workspace of twenty-seven. The missing fifteen included both halves of the download verifier, the failsafe, the video renderer and the workspace store. tools/audit/crate_tables.py reads the workspace and all three tables on every build and fails naming each crate a table has missed, so the next crate cannot be added without them. The sentences stay hand-written, because one assembled from a crate name is padding. F-192 156 Every page says where it lives, and a crawler is told it may read the site: og:image was assets/banner.png on every page, a relative address, and the crawlers that read that tag do not resolve one. Every link to this site posted anywhere had always shown no picture, and nothing about the page looked wrong. There was no canonical address either, so one page reachable two ways was two pages to an index, and two pages carried no preview tags at all. tools/site/seo.py builds all of it from what each page already says, every generator that writes a page calls it, and robots.txt and a sitemap covering all 398 pages exist where there were none. Checked twice on purpose: once that each page is what the generator would write, once that what the generator writes is correct. F-194 157 The banner moves on the no-JavaScript page too: that edition showed the still while the main site animated the same artwork, both drawn by assets/generate.py from the same source. It shows the animation now, with the still still served to anybody who has asked their system for less movement, chosen by markup rather than by a script because that page runs none 158 Fewer crates, chosen by what somebody would actually take: twenty-seven crates for one application, seven of them under seven hundred lines and four used by exactly one caller. Full modularity is not free: every split is a published surface, a Cargo.toml, a README, a banner, a page of the reference and a row in every table that lists them, and a reader deciding what to depend on had to read twenty-seven descriptions to find the two they wanted. Thirteen now, drawn at what somebody would realistically take on its own. The six observers became veilvoice-watch, the two alarms and the safety catch became veilvoice-guard, the verifier absorbed both of its backends, the renderer absorbed the graphics probe that answers one question for it, the decoy passphrase joined the cryptography it is part of, the update check joined the installer, and the saved profiles joined the settings. Nothing was deleted and no behaviour changed: every module kept its name, its tests and its page, and the whole suite passed before and after 159 The wiki becomes the documentation, and publishes itself: the wiki held the reference, a page for each of the thirteen crates and each source file in them, and three guides, and nothing else. No Home, so a reader arrived at whichever page GitHub picked; no _Sidebar, so there was no list of the rest; and none of the prose that answers what somebody actually arrives asking, how to build it, how to check a download reproduces, how to contribute, what the website is made of. Those are pages now, converted from the documents rather than written again, so --check fails on a difference and there is no second copy to go stale. Two documents that did not exist were written to be converted: docs/CONTRIBUTING.md and docs/WEBSITE.md, the second covering both editions of the site and all twelve scripts. A guard walks every [[link]] in all 202 pages, because a wiki link to a missing page renders as an invitation to create it rather than as an error, so nothing else would ever notice. And a workflow pushes the lot to the wiki repository, which is where a reader looks and where none of it was 160 The lock and the unlock are one control: the button that locks the window and the button that unlocks it were written where each was needed and sized by whatever its own text happened to measure, so one was 46 points wide beside a 132-point dropdown and the other was the word unlock padded with literal spaces, eight points taller than the password field beside it and four points off its middle. Roadmap item 123 fixed the height of the first and said the width was a different complaint; it was the same complaint. One width for the picker and both buttons, each button's height taken from whatever it stands beside, and the field grown to the button rather than the button squashed to the field. Measured in a headless frame rather than read off a photograph, on the rows that ship rather than on replicas of them, with a test that fails if controls left to themselves happen to agree anyway. F-196

An animation rather than a video file, and that is a decision rather than a shortcut. This project ships no codec and does not bundle ffmpeg, and the rule it already follows for video is to render here and always produce something that needs nothing else installed. An encoded file would also be a committed binary whose bytes depend on which build of which encoder made it, so it could not be regenerated and compared the way every other picture here is. If you want a file, ffmpeg -i roadmap-film.svg roadmap.mp4 will make you one from this.

What is left, and roughly what it takes

Working days, one person, no interruptions, so the calendar will be longer than the sum. In the order it is expected to be done.

#MarkerStateEstimate
113Memory that reads as ciphertext from outside the process the app-lock key holds the secrets and the veiling state encrypted in RAM with the same post-quantum sealing used at rest, each value decrypted only for the moment it is used and re-sealed straight after, so a scan of the process's memory finds no passphrase and no voiceprintplanned20
114A layout no two copies share the in-memory shape of that protected state varied per build and per run, so a scanner tuned to one copy of VeilVoice does not recognise the next, and no fixed offset survives from one binary to another. No junk and no decoy RAM: the footprint is unchanged, the protection is in the arrangement rather than in bulkplanned10
115Tamper noticed, and the source named an attempt to read or write VeilVoice's memory from another process detected where each operating system allows it, the app locked and the person told, and the reaching process identified as far as the platform permits, on Windows, macOS, Linux and the BSDs. Where a platform cannot say, it says that rather than guessingplanned20
118Told when anything touches VeilVoice at all every attempt to open, read, write or attach to one of VeilVoice's processes surfaced to the person, not only the ones that succeed, with what reached in named as far as the platform will say. Built on roadmap items 113 to 115 rather than beside them: the memory is already sealed, this is the part that says somebody triedplanned15
119A verdict, and then a choice something reaching into VeilVoice is reported with what it did and what VeilVoice can prove about it, and the person decides: remove it, quarantine it, or mark it a false positive that is remembered. The decision is the person's, always, because a program that silently uninstalls another program on a heuristic is a worse problem than the one it set out to solveplanned12
120The allowlist that cannot be worn as a disguise a signed antivirus reading VeilVoice's memory is what antivirus does, and flagging Defender as a rootkit would train somebody to ignore the warnings. So known-good is recognised by a verified code signature checked at the moment of the access, never by a process name, a path or a hash somebody can copy. An allowlist entry permits the read and still records it, still shows it in the log, and never widens to the file storage or the app lock: nothing on it can turn into a way through the protection roadmap items 113 to 115 provide. Stated limit, as everywhere: an attacker who already holds the kernel can forge what the kernel is asked, and this says so rather than promising otherwiseplanned18
146The Studio release 145 with the Browser, the decoys, the setup and the BSD reproducibility, tagged after its own audit round rather than on the strength of an earlier one. An audit covers the tree it was run on and no other. v0.1.20 carried the vault, both tabs, the render settings, the corrections, the player and the BSD double build, and was audited in its own round; the decoys, the machine card, the portable arrangement, the acceleration switch and the choice of which side to keep landed after it. So this describes the release after 0.1.20, and says so rather than keeping a number that has goneplanned8
149A signature check that needs only a signature check veilvoice verify and the Verify tab check an RSA-4096 OpenPGP signature over SHA256SUMS, and do it through pgp, which brings an entire OpenPGP implementation, rsa, aes, aes-gcm, aes-kw and the whole RustCrypto generation it was written against. That last part is why every cryptographic crate in this tree is held a generation back: moving them while pgp stays would compile two copies of each primitive into both binaries. The job is a reader for exactly what a detached signature over a text file is, the packet framing, the hashed subpackets, the RSA-PKCS1-v1.5 verify over SHA-256 and SHA-512, with nothing else in it, tested against the published signatures of every release and against the fixtures the fuzz targets already hold. When it lands, pgp and rsa leave the graph, RUSTSEC-2023-0071 leaves the exceptions with them, and the ten held majors move in one commitplanned20
155Companion software installed for you, wherever that can honestly be done today VeilVoice detects ffmpeg, Audacity, GnuPG and the audio routing drivers, and offers a package-manager line where the platform has one and its own page where it does not. That leaves the Windows reader, who has no package manager by default, doing the most work on the platform where the routing driver matters most. This finishes the job per operating system and per architecture: the release that matches the machine, fetched and checked against its published hash before anything is run, then installed. Where the software has an installer of its own, that installer is run and the install path is its question to ask, because a program that answers it on the installer's behalf is a program guessing at somebody else's layout. Where there is no installer, the default location for the platform is used unless the person names another, and where a package manager already governs the machine it stays in charge rather than being worked around. Nothing proprietary is ever installed silently: its licence is still accepted by the person it binds. The same routes from veilvoice companions and from the About tab, one list, one implementation, with progress, cancel and resume as the existing installs already haveplanned25
107VeilVoice on a phone an Android package a person installs without developer tools, signed, published beside the desktop archives and verifiable the same way. Roadmap item 52 established that the code compiles for Android; what is missing is the NDK in the release build, a capture path that uses the platform's own audio rather than ALSA, a window that works at a phone's size, and a signing key that does not require a legal identity, all four set out in VeilVoice on a phone above along with why iOS is a separate question. It sits last because it is worth more once there is a Studio to put on the phone, and because none of the desktop work is waiting on itplanned10

Blocked, and why that is not the same as late

Nothing is blocked. Five items were, some of them for months, each waiting on a decision rather than on effort, and they have been taken off rather than left to make the list look busy. The roadmap says what each one was, what it was waiting for, and why the reasoning is kept even though the item is gone.

Everything that is finished

In the order the roadmap lists it, under the heading it was asked for. Every item links to itself, so one can be sent to somebody on its own.

Shipped #

In progress #

Security and monitoring features #

Each of these is a crate of its own, so that another project can depend on one without taking all of them. Every one is opt-in, and every one states what it cannot do as plainly as what it can.

Conversations, subtitles and video #

Asked for after v0.1.12. One recording, several speakers, each given a different voice and each voiceprint destroyed just as thoroughly; names and subtitles; and an optional video of the result.

Building it yourself, and proving the download matches #

Asked for after the conversation work. Today veilvoice-verify answers one question, is this download the one that was published, and answers it without GnuPG, without a network client of its own, and without ever holding a private key. The request is to make the same program answer the harder question: is the published build the one this source produces, and to have it set your machine up so you can find out.

The program is renamed veilvoice-setup-tools, because checking a signature is then the smallest thing it does.

Group mode, where you can see it #

The engine has handled several speakers since roadmap item 46. The desktop app has never shown it. These are about making the thing visible and usable rather than about the signal, which is already done.

Seeing it before you install it #

Asked for after v0.1.14. Everything here is about the same problem from two sides: somebody deciding whether to trust this, and somebody using it and not being sure it is working. Neither is answered by more features.

The lock, the guard, and a window that does not stutter #

Asked for after the tenth audit round. Four of these are one subject seen from different sides: the app lock is the weakest control this project ships, it is described as such in several places, and the request is to make it as strong as it can honestly be made rather than to keep apologising for it.

Finally #

Encrypted volumes: Cryptomator, VeraCrypt, and the disk underneath #

Asked for after the encrypted volumes #

The window, and the things that were marked done and were not #

Two rows above were marked done before they were, and this section exists partly to say so. Roadmap item 79 declared a window that does not stutter, twice: once when the drawing thread was cleared, and again when a repaint timer was removed and the improvement measured. Both changes were real and neither reached the cause, which was the animated logo asking for another frame thirty times a second whether or not anybody could see it. Roadmap item 95 declared one version per release enforced, and the enforcement covered the package definitions and not the twelve other places, the README's install block among them, that repeat the version by hand.

Neither is being un-marked. What was done was done. The correction is that a roadmap item means the work described happened, not that the symptom is gone, and this list is more useful if the difference is visible.

Asked for while v0.1.17 was being built #

Everything here came from one message and they belong together: somebody arriving at this project for the first time, deciding whether to trust it, installing it, and finding their way around it without reading a manual.

Asked for after v0.1.18 #

The app lock already turns the app-lock passphrase into a key that seals everything VeilVoice writes (roadmap item 86). This asks for the same protection one layer in: the secrets and the veiling state while they are in memory, so that a program which can read another process's RAM, a rootkit or a debugger, reads ciphertext rather than a passphrase or a voiceprint.

The honest limit is stated with the feature rather than after it. Data the CPU is actively working on has to be plaintext for the instant it is used, and an attacker already running as the kernel can wait for that instant. This raises the cost of an external read and narrows the window to nearly nothing; it does not claim to beat an adversary who already owns the machine.

Generated from ROADMAP.md at commit time by tools/site/roadmap.py. 154 items across 14 sections.