-
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy patharcvix-formally-verified-reversible-shell.tex
More file actions
1673 lines (1398 loc) · 65.9 KB
/
Copy patharcvix-formally-verified-reversible-shell.tex
File metadata and controls
1673 lines (1398 loc) · 65.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
% SPDX-License-Identifier: MPL-2.0
% arXiv-style academic paper on Valence Shell
% Author: Jonathan D.A. Jewell
\documentclass[11pt,a4paper]{article}
% --- Packages ---
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{lmodern}
\usepackage{amsmath,amssymb,amsthm}
\usepackage{mathtools}
\usepackage{stmaryrd}
\usepackage{listings}
\usepackage{xcolor}
\usepackage{hyperref}
\usepackage{cleveref}
\usepackage{booktabs}
\usepackage{multirow}
\usepackage{graphicx}
\usepackage{enumitem}
\usepackage[margin=1in]{geometry}
\usepackage{fancyhdr}
\usepackage{natbib}
\usepackage{microtype}
\usepackage{tikz}
\usetikzlibrary{arrows.meta,positioning,shapes.geometric,fit}
% --- Theorem environments ---
\newtheorem{theorem}{Theorem}[section]
\newtheorem{lemma}[theorem]{Lemma}
\newtheorem{corollary}[theorem]{Corollary}
\newtheorem{proposition}[theorem]{Proposition}
\newtheorem{definition}[theorem]{Definition}
\newtheorem{remark}[theorem]{Remark}
\newtheorem{example}[theorem]{Example}
% --- Listings ---
\definecolor{codegreen}{rgb}{0,0.5,0}
\definecolor{codegray}{rgb}{0.5,0.5,0.5}
\definecolor{codepurple}{rgb}{0.58,0,0.82}
\definecolor{backcolour}{rgb}{0.97,0.97,0.97}
\definecolor{leanblue}{rgb}{0.0,0.2,0.6}
\lstdefinestyle{leanstyle}{
backgroundcolor=\color{backcolour},
commentstyle=\color{codegreen}\itshape,
keywordstyle=\color{leanblue}\bfseries,
numberstyle=\tiny\color{codegray},
stringstyle=\color{codepurple},
basicstyle=\ttfamily\small,
breaklines=true,
captionpos=b,
keepspaces=true,
numbers=left,
numbersep=5pt,
showstringspaces=false,
frame=single,
xleftmargin=2em,
framexleftmargin=1.5em,
morekeywords={theorem,def,structure,inductive,where,deriving,match,with,
fun,by,exact,intro,apply,simp,rfl,unfold,funext,rw,cases,have,let,
forall,exists,Prop,Type,abbrev,namespace,open,import,some,none,
if,then,else,infix},
}
\lstdefinestyle{ruststyle}{
backgroundcolor=\color{backcolour},
commentstyle=\color{codegreen}\itshape,
keywordstyle=\color{blue}\bfseries,
numberstyle=\tiny\color{codegray},
stringstyle=\color{codepurple},
basicstyle=\ttfamily\small,
breaklines=true,
captionpos=b,
keepspaces=true,
numbers=left,
numbersep=5pt,
showstringspaces=false,
frame=single,
xleftmargin=2em,
framexleftmargin=1.5em,
morekeywords={fn,pub,let,mut,match,struct,enum,impl,self,use,mod,
if,else,return,Some,None,Result,Ok,Err,true,false,where,trait,
for,in,while,loop,break,continue,type,const,static,async,await},
}
\lstdefinestyle{coqstyle}{
backgroundcolor=\color{backcolour},
commentstyle=\color{codegreen}\itshape,
keywordstyle=\color{codepurple}\bfseries,
basicstyle=\ttfamily\small,
breaklines=true,
captionpos=b,
keepspaces=true,
numbers=left,
numbersep=5pt,
showstringspaces=false,
frame=single,
xleftmargin=2em,
framexleftmargin=1.5em,
morekeywords={Theorem,Lemma,Proof,Qed,Definition,Inductive,Record,
forall,exists,match,with,end,let,in,if,then,else,Prop,Set,Type,
fun,fix,struct,Section,Variable,Hypothesis},
}
% --- Macros ---
\newcommand{\FS}{\mathcal{F}}
\newcommand{\Op}{\mathsf{Op}}
\newcommand{\inv}[1]{#1^{-1}}
\newcommand{\pre}[1]{\mathsf{pre}(#1)}
\newcommand{\valence}{\textsc{Valence}}
\newcommand{\rmr}{\textsc{rmr}}
\newcommand{\rmo}{\textsc{rmo}}
\newcommand{\maa}{\textsc{maa}}
\newcommand{\cno}{\textsc{cno}}
\newcommand{\lean}{Lean~4}
\newcommand{\coq}{Coq}
% --- Title ---
\title{%
\textbf{Valence: A Shell with Formally Verified Reversibility\\
and Mutually Assured Accountability}
}
\author{%
Jonathan D.A.\ Jewell\\
\texttt{j.d.a.jewell@open.ac.uk}\\
\textit{Independent Researcher}
}
\date{March 2026}
\begin{document}
\maketitle
% =============================================================================
% ABSTRACT
% =============================================================================
\begin{abstract}
Unix shells provide no formal guarantees about the reversibility of operations.
A mistyped \texttt{rm -rf} can destroy months of work in milliseconds, and the
traditional response---backups, snapshots, ``be careful''---shifts the burden of
correctness entirely onto the human operator. We present \valence{}, an
interactive shell in which every built-in filesystem operation has a
machine-checkable mathematical proof of reversibility \emph{in a formal
abstract model}. The core contribution is a \emph{reversible operation algebra}
formalised in six independent proof assistants (\lean{}, Coq, Agda,
Isabelle/HOL, Mizar, and F*), yielding over 200 verified theorems; the same
theorems are independently cross-validated across all six systems, providing
confidence through prover diversity (the Rust implementation is validated by
property-based testing, not mechanically verified against the model). We
introduce the \emph{Mutually Assured Accountability} (\maa{}) framework, which
decomposes shell operations into two formally distinct modes:
\emph{Remove-Match-Reverse} (\rmr{}), providing proven undo/redo with
transaction grouping, and \emph{Remove-Match-Obliterate} (\rmo{}), a
formally-specified irreversible deletion mode designed for GDPR compliance
(currently a stub; full proof of non-recoverability is future work).
We describe the Rust implementation (15,720 lines, 602 passing tests), the
multi-prover verification strategy, and the algebraic structure---including
Certified Null Operations (\cno{}), operation commutativity, and sequence
composition---that makes reversibility a first-class mathematical property of
the shell rather than an ad-hoc afterthought.
\end{abstract}
\noindent\textbf{Keywords:} formal verification, reversible computing, shell
design, interactive systems, proof assistants, undo mechanisms, GDPR (planned)
% =============================================================================
% 1. INTRODUCTION
% =============================================================================
\section{Introduction}
\label{sec:introduction}
The Unix shell is one of the most consequential interfaces in computing. System
administrators, developers, and researchers compose sequences of shell commands
to manage filesystems, configure services, and orchestrate infrastructure. Yet
the shell offers \emph{zero formal guarantees} about what happens when things
go wrong. There is no undo. There is no rollback. There is no proof that an
operation can be reversed.
The consequences are severe and well-documented. Accidental deletion of
production databases, recursive removal of critical directories, and
misconfigured permission changes have caused outages costing millions of
dollars~\citep{gitlab-incident,aws-outage}. The standard mitigations---backups,
snapshots, confirmation prompts, and the venerable ``alias rm='rm -i'\,''---are
all \emph{best-effort} measures. None provides a mathematical guarantee that
the system can be restored to its prior state.
This paper addresses what we term the \emph{trust gap}: the chasm between what
shell users \emph{hope} will happen when they attempt to undo an operation and
what can be \emph{proven} to happen. We present \valence{}, a shell in which
reversibility is not a feature bolted on after the fact, but a foundational
algebraic property of the system, verified by six independent theorem provers.
\subsection{Contributions}
\begin{enumerate}[label=(\arabic*)]
\item A \textbf{formal model of filesystem reversibility} as a function-space
algebra, with precondition structures, inverse operations, and
composition theorems (\cref{sec:algebra}).
\item The \textbf{Mutually Assured Accountability} (\maa{}) framework,
decomposing shell operations into proven-reversible (\rmr{}) and
proven-irreversible (\rmo{}) modes (\cref{sec:maa}).
\item A \textbf{multi-prover cross-validation} strategy in which identical
theorems are proved independently in six proof systems (\lean{}, Coq,
Agda, Isabelle/HOL, Mizar, F*), providing extraordinary confidence
through prover diversity (\cref{sec:verification}).
\item A \textbf{working Rust implementation} of 16+ reversible operations
with undo/redo stacks, transaction grouping, proof-annotated output,
and 602 passing tests (\cref{sec:implementation}).
\item \textbf{Formal proofs of non-recoverability} for secure deletion
(\rmo{}), showing that obliteration is provably non-injective and
therefore no uniform recovery function exists (\cref{sec:rmo}).
\end{enumerate}
\subsection{Paper Organisation}
\Cref{sec:background} surveys related work in reversible computing, shell
design, and formal verification. \Cref{sec:maa} introduces the \maa{}
framework. \Cref{sec:algebra} develops the reversible operation algebra.
\Cref{sec:verification} describes the multi-prover strategy and presents
selected theorems. \Cref{sec:theorems} gives detailed proofs for core
operations. \Cref{sec:implementation} describes the Rust shell.
\Cref{sec:rmo} formalises irreversible deletion. \Cref{sec:evaluation}
evaluates proof coverage and performance. \Cref{sec:related} discusses related
work, and \Cref{sec:conclusion} concludes.
% =============================================================================
% 2. BACKGROUND
% =============================================================================
\section{Background}
\label{sec:background}
\subsection{Reversible Computing}
Reversible computing has a rich history rooted in thermodynamics.
Landauer~\citep{landauer1961} demonstrated that logically irreversible
computation necessarily dissipates energy, and Bennett~\citep{bennett1973}
showed that any computation can be made logically reversible. These results
concern \emph{physical} reversibility---whether a computation can be run
backward without energy loss.
\valence{} addresses a different but related notion: \emph{algorithmic
reversibility}. We do not claim that our operations satisfy Landauer's
principle or that they can be executed in reverse on a physically reversible
processor. Rather, we prove that for each operation $f$, there exists an
inverse $\inv{f}$ such that $\inv{f}(f(s)) = s$ for all states $s$ satisfying
the appropriate preconditions. This is an \emph{information-theoretic}
property: the operation preserves enough information to reconstruct the prior
state.
\subsection{Shell Design and Undo Mechanisms}
Traditional Unix shells (Bash, Zsh, Fish) provide no built-in undo mechanism
for filesystem operations. The closest analogues are:
\begin{itemize}
\item \textbf{Trash utilities} (e.g., \texttt{trash-cli}): Move files to a
trash directory instead of deleting them. No formal guarantees; does
not handle \texttt{mkdir}, \texttt{chmod}, or other operations.
\item \textbf{PowerShell transactions}: Windows PowerShell offered
transacted filesystem operations via the Kernel Transaction Manager
(KTM)~\citep{powershell-transactions}. These were deprecated and never
provided formal proofs of reversibility.
\item \textbf{Filesystem snapshots}: ZFS~\citep{zfs}, Btrfs~\citep{btrfs},
and Plan~9's fossil/venti~\citep{plan9fossil} provide point-in-time
snapshots. These operate at the block level, not the operation level,
and cannot selectively undo individual commands.
\item \textbf{libvirt snapshots}: Virtual machine snapshots capture entire
disk states but are coarse-grained and expensive.
\end{itemize}
None of these approaches provides \emph{operation-level} reversibility with
mathematical proofs. \valence{} fills this gap.
\subsection{Formal Verification of Systems Software}
Formal verification has been applied to operating systems
(seL4~\citep{klein2009}), compilers (CompCert~\citep{leroy2009}), file systems
(FSCQ~\citep{chen2015}), and distributed systems
(IronFleet~\citep{hawblitzel2015}). The verified file system FSCQ is
particularly relevant: it provides crash-safety guarantees for a POSIX-like
file system using the Coq proof assistant. \valence{} differs in scope (we
verify \emph{reversibility} of shell operations, not crash safety of a
filesystem implementation) and in strategy (we use six provers rather than
one).
The multi-prover approach is, to our knowledge, novel in systems verification.
While N-version programming~\citep{avizienis1985} uses multiple independent
implementations for fault tolerance at runtime, we use multiple independent
\emph{proofs} for confidence at verification time.
% =============================================================================
% 3. THE MAA FRAMEWORK
% =============================================================================
\section{The MAA Framework: Mutually Assured Accountability}
\label{sec:maa}
The Mutually Assured Accountability framework is the organising principle of
\valence{}. It decomposes all shell operations into two formally distinct
categories based on their information-theoretic properties.
\subsection{RMR: Remove-Match-Reverse}
\rmr{} governs operations that are \emph{proven reversible}. Every \rmr{}
operation satisfies the following contract:
\begin{definition}[\rmr{} Operation]
\label{def:rmr}
An operation $f : \FS \to \FS$ is an \rmr{} operation if there exists an
inverse $\inv{f} : \FS \to \FS$ and a precondition predicate
$\pre{f} : \FS \to \mathsf{Prop}$ such that:
\[
\forall\, s : \FS.\;\; \pre{f}(s) \implies \inv{f}(f(s)) = s
\]
and this implication is proven in at least one (and ideally multiple)
mechanised proof assistants.
\end{definition}
The three components of \rmr{} are:
\begin{itemize}
\item \textbf{Remove}: The forward operation modifies the filesystem state
(e.g., creating a directory, writing a file).
\item \textbf{Match}: The inverse operation is computed from the forward
operation and any stored undo data (e.g., original file contents).
\item \textbf{Reverse}: Applying the inverse restores the original state,
with a machine-checkable proof that restoration is exact.
\end{itemize}
At runtime, every \rmr{} operation is recorded on an undo stack with its
inverse and any necessary undo data. Transaction grouping allows multiple
operations to be treated as a single atomic unit for undo purposes.
\subsection{RMO: Remove-Match-Obliterate}
\rmo{} governs operations that are \emph{proven irreversible}. This is the
dual of \rmr{}: where \rmr{} guarantees that data \emph{can} be recovered,
\rmo{} guarantees that data \emph{cannot} be recovered.
\begin{definition}[\rmo{} Operation]
\label{def:rmo}
An operation $g : \FS_{\text{ext}} \to \FS_{\text{ext}}$ is an \rmo{}
operation if $g$ is provably \emph{not injective}: there exist distinct states
$s_1 \neq s_2$ such that $g(s_1) = g(s_2)$, and therefore no uniform left
inverse exists.
\end{definition}
\rmo{} is essential for regulatory compliance. The European Union's General
Data Protection Regulation (GDPR) Article~17 establishes a ``right to
erasure''---data subjects can demand that their personal data be permanently
deleted. A system that merely marks data as deleted (while retaining the
underlying bytes) does not satisfy this requirement. \rmo{} provides a
mathematical guarantee that after obliteration, no recovery function can
reconstruct the original data.
\subsection{The Accountability Duality}
The \maa{} framework treats reversibility and irreversibility as dual
properties that together provide complete accountability:
\begin{center}
\begin{tikzpicture}[
box/.style={draw, rounded corners, minimum width=3.5cm, minimum height=1.5cm,
align=center, font=\small},
arr/.style={-{Stealth[length=3mm]}, thick}
]
\node[box, fill=green!10] (rmr) {\textbf{RMR}\\Proven Reversible\\``Can always undo''};
\node[box, fill=red!10, right=3cm of rmr] (rmo) {\textbf{RMO}\\Proven Irreversible\\``Cannot recover''};
\node[box, fill=blue!10, below=2cm of $(rmr)!0.5!(rmo)$] (maa) {\textbf{MAA}\\Complete Accountability\\Every operation classified};
\draw[arr] (rmr) -- (maa);
\draw[arr] (rmo) -- (maa);
\draw[arr, dashed, <->] (rmr) -- node[above, font=\footnotesize\itshape] {duality} (rmo);
\end{tikzpicture}
\end{center}
Every operation in \valence{} must be classified as either \rmr{} or \rmo{}.
There is no ``unclassified'' category. This ensures that the user always knows
whether an operation can be undone, and the system can enforce the appropriate
guarantees.
% =============================================================================
% 4. REVERSIBLE OPERATION ALGEBRA
% =============================================================================
\section{Reversible Operation Algebra}
\label{sec:algebra}
\subsection{The Filesystem Model}
We model the filesystem as a total function from paths to optional nodes:
\begin{definition}[Filesystem]
\label{def:fs}
A \emph{filesystem} is a function $\FS : \mathsf{Path} \to
\mathsf{Option}(\mathsf{FSNode})$, where:
\begin{align*}
\mathsf{Path} &\triangleq \mathsf{List}(\mathsf{String}) \\
\mathsf{FSNode} &\triangleq \mathsf{FSNodeType} \times \mathsf{Permissions} \\
\mathsf{FSNodeType} &\triangleq \mathsf{file} \mid \mathsf{directory}
\end{align*}
The empty filesystem $\FS_\emptyset$ maps the root path $[]$ to a directory
node and all other paths to $\mathsf{None}$.
\end{definition}
This function-space model, implemented in \lean{} as \lstinline[style=leanstyle]{abbrev Filesystem := Path -> Option FSNode}, is deliberately abstract. We do not model block allocation, inode tables, or physical storage layout (except in the \rmo{} extension, which adds a storage layer). This abstraction allows clean proofs while remaining faithful to the observable behaviour of POSIX filesystem operations.
\subsection{The Update Primitive}
All filesystem mutations are expressed through a single primitive:
\begin{definition}[Filesystem Update]
\label{def:fsupdate}
\[
\mathsf{fsUpdate}(p, n, \FS) \triangleq
\lambda\, p'.\; \begin{cases}
n & \text{if } p = p' \\
\FS(p') & \text{otherwise}
\end{cases}
\]
\end{definition}
This point-update function is the foundation of all operations. Its simplicity
is key to tractable proofs: every operation reduces to one or two applications
of $\mathsf{fsUpdate}$, and the case analysis on path equality yields clean
proof obligations.
\subsection{Operations and Their Inverses}
Each filesystem operation is defined as a pair: the forward operation and its
precondition structure. The inverse is derived from the algebraic structure.
\begin{definition}[Reversible Operation Pair]
\label{def:oppair}
A \emph{reversible operation pair} is a tuple
$(f, \inv{f}, \pre{f}, \pre{\inv{f}})$ where:
\begin{enumerate}[label=(\roman*)]
\item $f : \FS \to \FS$ is the forward operation,
\item $\inv{f} : \FS \to \FS$ is the inverse operation,
\item $\pre{f} : \FS \to \mathsf{Prop}$ is the forward precondition,
\item $\pre{\inv{f}} : \FS \to \mathsf{Prop}$ is the inverse precondition,
\item $\forall\, s.\; \pre{f}(s) \implies \inv{f}(f(s)) = s$
\hfill (forward--inverse)
\item $\forall\, s.\; \pre{\inv{f}}(s) \implies f(\inv{f}(s)) = s$
\hfill (inverse--forward)
\end{enumerate}
\end{definition}
\Cref{tab:operations} lists the 16+ operations implemented in \valence{} with
their inverses and the proof systems in which reversibility has been verified.
\begin{table}[t]
\centering
\caption{Reversible operation pairs in \valence{}.}
\label{tab:operations}
\small
\begin{tabular}{@{}llll@{}}
\toprule
\textbf{Forward ($f$)} & \textbf{Inverse ($\inv{f}$)} &
\textbf{Theorem Name} & \textbf{Provers} \\
\midrule
\texttt{mkdir} & \texttt{rmdir} & \texttt{mkdir\_rmdir\_reversible} & L4, Coq, Ag, Is, Mi \\
\texttt{rmdir} & \texttt{mkdir} & \texttt{rmdir\_mkdir\_reversible} & L4, Coq, Ag, Is, Mi \\
\texttt{touch} & \texttt{rm} & \texttt{createFile\_deleteFile\_reversible} & L4, Coq, Ag, Is \\
\texttt{rm} & \texttt{touch} & \texttt{deleteFile\_createFile\_reversible} & L4, Coq, Ag, Is \\
\texttt{cp} & \texttt{rm} (dst) & \texttt{copyFile\_rm\_reversible} & L4, Coq \\
\texttt{mv} & \texttt{mv} (swap) & \texttt{move\_reverse\_reversible} & L4, Coq \\
\texttt{ln -s} & \texttt{unlink} & \texttt{symlink\_unlink\_reversible} & L4 \\
\texttt{chmod} & \texttt{chmod} (old) & \texttt{chmod\_reversible} & L4 \\
\texttt{chown} & \texttt{chown} (old) & \texttt{chown\_reversible} & L4 \\
\texttt{write} & \texttt{write} (old) & \texttt{write\_restore\_reversible} & L4, Coq, Ag \\
\texttt{truncate} & \texttt{write} (old) & \texttt{truncate\_restore\_reversible} & L4 (pending) \\
\texttt{append} & \texttt{truncate} & \texttt{append\_truncate\_reversible} & L4 (pending) \\
\texttt{export} & \texttt{unset} & \texttt{variable\_assignment\_reversible} & L4 \\
\texttt{unset} & \texttt{export} & \texttt{variable\_unset\_reversible} & L4 \\
\bottomrule
\end{tabular}
\\[0.5em]
\footnotesize L4 = Lean~4, Ag = Agda, Is = Isabelle/HOL, Mi = Mizar.
\end{table}
\subsection{Operation Composition}
Individual reversibility is necessary but not sufficient. Shell sessions involve
\emph{sequences} of operations, and we must prove that sequences are also
reversible.
\begin{definition}[Operation Sequence]
\label{def:sequence}
An \emph{operation sequence} is a list of operations. Application is by
left fold:
\[
\mathsf{applySequence}([\,], s) = s \qquad
\mathsf{applySequence}(f :: \mathit{rest}, s) =
\mathsf{applySequence}(\mathit{rest}, f(s))
\]
The \emph{reverse sequence} reverses the list and replaces each operation with
its inverse:
\[
\mathsf{reverseSequence}(\mathit{ops}) =
\mathsf{map}\;\inv{(\cdot)}\;(\mathsf{reverse}\;\mathit{ops})
\]
\end{definition}
\begin{theorem}[Sequence Reversibility]
\label{thm:sequence}
If every operation in a sequence is individually reversible (with its
preconditions holding at each intermediate state), then the reverse sequence
restores the original state:
\[
\forall\, \mathit{ops}, s.\;\;
\mathsf{allReversible}(\mathit{ops}, s) \implies
\mathsf{applySequence}(\mathsf{reverseSequence}(\mathit{ops}),
\mathsf{applySequence}(\mathit{ops}, s)) = s
\]
\end{theorem}
The proof proceeds by structural induction on the operation list, using the
append lemma for sequence application and the single-operation reversibility
theorem at each step. The full mechanised proof is in
\texttt{proofs/lean4/FilesystemComposition.lean}.
\subsection{Certified Null Operations}
A key algebraic property is that an operation followed by its inverse is
equivalent to the identity:
\begin{definition}[Certified Null Operation (\cno{})]
\label{def:cno}
An operation $f$ followed by its inverse $\inv{f}$ is a \emph{Certified Null
Operation} if:
\[
\pre{f}(s) \implies f(s) \approx s \text{ after } \inv{f}
\]
where $\approx$ denotes filesystem equivalence (pointwise equality on all
paths).
\end{definition}
\begin{theorem}[\cno{} Identity]
\label{thm:cno}
For any reversible operation $f$ with precondition $\pre{f}$:
\[
\pre{f}(s) \implies \inv{f}(f(s)) \approx s
\]
where $\approx$ is a proven equivalence relation (reflexive, symmetric,
transitive).
\end{theorem}
The equivalence relation $\approx$ is defined as pointwise equality:
$\FS_1 \approx \FS_2 \iff \forall\, p.\; \FS_1(p) = \FS_2(p)$. We prove that
this is an equivalence relation and that all operations preserve it.
\subsection{Operation Independence and Commutativity}
Operations on disjoint paths commute:
\begin{theorem}[Path Independence]
\label{thm:independence}
For operations $f_1$ on path $p_1$ and $f_2$ on path $p_2$ with
$p_1 \neq p_2$:
\[
f_1(f_2(s)) = f_2(f_1(s))
\]
\end{theorem}
This follows directly from the definition of $\mathsf{fsUpdate}$: updates at
different paths do not interfere. This property is critical for the
implementation, as it allows the shell to reorder undo operations when paths
are independent.
\subsection{Transaction Grouping}
\valence{} supports grouping multiple operations into a single transaction:
\begin{definition}[Transaction]
\label{def:transaction}
A \emph{transaction} is a named sequence of operations that is undone or
redone as a unit. The \texttt{begin}/\texttt{commit}/\texttt{rollback}
commands delimit transactions.
\end{definition}
Transaction reversibility follows directly from \cref{thm:sequence}: if every
operation in the transaction is individually reversible, the entire transaction
is reversible.
% =============================================================================
% 5. FORMAL VERIFICATION APPROACH
% =============================================================================
\section{Formal Verification: The Multi-Prover Strategy}
\label{sec:verification}
\subsection{Rationale for Multiple Provers}
A formal proof is only as trustworthy as the proof assistant that checks it.
Every proof assistant has a trusted computing base (TCB): the kernel, the type
checker, and in some cases the elaboration engine. Bugs in the TCB can cause
false theorems to be accepted~\citep{pollack1998}.
Our mitigation is \emph{prover diversity}. We prove the same theorems
independently in six proof systems built on different logical foundations:
\begin{table}[t]
\centering
\caption{Proof systems used in \valence{}, with their logical foundations.}
\label{tab:provers}
\begin{tabular}{@{}lll@{}}
\toprule
\textbf{Prover} & \textbf{Foundation} & \textbf{Role} \\
\midrule
Lean~4 & Dependent type theory (CIC variant) & Primary source of truth \\
Coq & Calculus of Inductive Constructions & CIC cross-validation \\
Agda & Intensional type theory (Martin-L\"of) & MLTT cross-validation \\
Isabelle/HOL & Higher-order logic & Classical logic validation \\
Mizar & Tarski--Grothendieck set theory & Set-theoretic validation \\
F* & Dependent + refinement types & SMT-backed validation \\
\bottomrule
\end{tabular}
\end{table}
A bug in any single prover would need to be replicated across \emph{all six}
systems---systems built by different teams, in different languages, using
different algorithms---to produce a false theorem. This is analogous to
N-version programming~\citep{avizienis1985} applied to verification rather
than execution.
\subsection{Proof Architecture}
Each prover formalises the same abstract filesystem model, differing only in
the idioms required by each system. The proof structure follows a layered
architecture:
\begin{enumerate}[label=\textbf{Layer \arabic*:}]
\item \textbf{Filesystem Model.} Paths, nodes, permissions, the empty
filesystem, and the update primitive.
\item \textbf{Individual Operations.} Preconditions, forward operations,
postcondition lemmas, and reversibility theorems for each operation.
\item \textbf{Composition.} The operation abstraction, sequence application,
reverse sequences, and the main composition theorem.
\item \textbf{Equivalence.} The filesystem equivalence relation,
equivalence-preservation lemmas, and \cno{} identity.
\item \textbf{Extensions.} Content operations, permission operations,
symbolic links, copy/move, and \rmo{}.
\end{enumerate}
In \lean{}, the primary source of truth, these correspond to:
\begin{itemize}
\item \texttt{FilesystemModel.lean} --- 199 lines, core model
\item \texttt{FileOperations.lean} --- file create/delete
\item \texttt{FilesystemComposition.lean} --- sequence composition
\item \texttt{FilesystemEquivalence.lean} --- equivalence relation
\item \texttt{CopyMoveOperations.lean} --- copy and move
\item \texttt{PermissionOperations.lean} --- chmod and chown
\item \texttt{SymlinkOperations.lean} --- symbolic links
\item \texttt{FileContentOperations.lean} --- read/write
\item \texttt{RMOOperations.lean} --- secure deletion
\end{itemize}
\subsection{Cross-Validation Protocol}
Not all theorems are proved in all six systems. We follow a tiered strategy:
\begin{enumerate}
\item \textbf{Core reversibility theorems} (e.g.,
\texttt{mkdir\_rmdir\_reversible}): proved in 5--6 systems.
\item \textbf{Composition theorems}: proved in 4--5 systems.
\item \textbf{Extension theorems} (permissions, symlinks, \rmo{}): proved
in 1--3 systems, with additional systems planned.
\end{enumerate}
The core insight is that the \emph{most critical} theorems receive the most
redundant verification, while less critical theorems are verified in fewer
systems. This allocates verification effort proportionally to risk.
% =============================================================================
% 6. KEY THEOREMS AND PROOFS
% =============================================================================
\section{Key Theorems and Proofs}
\label{sec:theorems}
We now present the central theorems with their mechanised proofs in \lean{}.
All proofs compile and type-check without axioms (beyond the standard library).
\subsection{mkdir/rmdir Reversibility}
The foundational theorem of \valence{}: creating and then removing a directory
restores the original filesystem.
\begin{theorem}[\texttt{mkdir\_rmdir\_reversible}]
\label{thm:mkdir-rmdir}
\[
\forall\, p, \FS.\;\;
\mathsf{MkdirPrecondition}(p, \FS) \implies
\mathsf{rmdir}(p, \mathsf{mkdir}(p, \FS)) = \FS
\]
where $\mathsf{MkdirPrecondition}$ requires:
\begin{enumerate}[label=(\alph*)]
\item Path $p$ does not exist in $\FS$,
\item Parent of $p$ exists and is a directory,
\item Parent of $p$ has write permission.
\end{enumerate}
\end{theorem}
\begin{proof}[Proof (Lean~4)]
We reproduce the mechanised proof from
\texttt{proofs/lean4/FilesystemModel.lean}:
\begin{lstlisting}[style=leanstyle,caption={The mkdir/rmdir reversibility proof in Lean 4.}]
theorem mkdir_rmdir_reversible (p : Path) (fs : Filesystem)
(hpre : MkdirPrecondition p fs) :
rmdir p (mkdir p fs) = fs := by
unfold rmdir mkdir fsUpdate
funext p'
by_cases h : p = p'
. -- Case p = p': show none = fs p
subst h
simp
cases hfs : fs p with
| none => rfl
| some node =>
exfalso
apply hpre.notExists
unfold pathExists
exact <node, hfs>
. -- Case p != p': trivial, update at p doesn't affect p'
simp [h]
\end{lstlisting}
The proof proceeds by functional extensionality: we must show the two
filesystems agree on every path $p'$. When $p' = p$, the mkdir creates a node
and rmdir removes it, yielding $\mathsf{None}$---which equals $\FS(p)$ because
the precondition guarantees $p$ does not exist. When $p' \neq p$, neither
operation touches $p'$.
\end{proof}
The reverse direction (rmdir then mkdir) also holds under an additional
condition:
\begin{theorem}[\texttt{rmdir\_mkdir\_reversible}]
\label{thm:rmdir-mkdir}
\[
\forall\, p, \FS.\;\;
\mathsf{RmdirPrecondition}(p, \FS) \land
\FS(p) = \mathsf{Some}(\mathsf{directory}, \mathsf{defaultPerms})
\implies
\mathsf{mkdir}(p, \mathsf{rmdir}(p, \FS)) = \FS
\]
\end{theorem}
The additional condition---that the directory was created with default
permissions---is necessary because \texttt{mkdir} always creates directories
with default permissions. If the original directory had non-default
permissions, exact restoration requires the \texttt{chmod} operation as well.
This is an instance of the general principle that reversibility requires
sufficient undo data.
\subsection{File Create/Delete Reversibility}
\begin{theorem}[\texttt{createFile\_deleteFile\_reversible}]
\label{thm:create-delete}
\[
\forall\, p, \FS.\;\;
\mathsf{CreateFilePrecondition}(p, \FS) \implies
\mathsf{deleteFile}(p, \mathsf{createFile}(p, \FS)) = \FS
\]
\end{theorem}
The proof is structurally identical to \cref{thm:mkdir-rmdir}. Both operations
reduce to $\mathsf{fsUpdate}$, and the argument is by functional extensionality
with a case split on path equality. The precondition that $p$ does not exist
is critical: it ensures that $\mathsf{fsUpdate}(p, \mathsf{None}, \FS) = \FS$
at path $p$.
\subsection{Copy/Move Reversibility}
Copy and move operations are more complex because they involve two paths.
\begin{theorem}[\texttt{copyFile} reversibility]
\label{thm:copy}
\[
\forall\, \mathit{src}, \mathit{dst}, \FS.\;\;
\mathsf{copyFilePrecondition}(\mathit{src}, \mathit{dst}, \FS) \implies
\mathsf{deleteFile}(\mathit{dst},
\mathsf{copyFile}(\mathit{src}, \mathit{dst}, \FS)) = \FS
\]
provided $\mathit{src} \neq \mathit{dst}$.
\end{theorem}
The copy operation adds a node at $\mathit{dst}$; deleting that node restores
$\FS$. The condition $\mathit{src} \neq \mathit{dst}$ ensures that deleting
the destination does not affect the source.
\begin{theorem}[\texttt{move} reversibility]
\label{thm:move}
\[
\forall\, \mathit{src}, \mathit{dst}, \FS.\;\;
\mathsf{movePrecondition}(\mathit{src}, \mathit{dst}, \FS) \implies
\mathsf{move}(\mathit{dst}, \mathit{src},
\mathsf{move}(\mathit{src}, \mathit{dst}, \FS)) = \FS
\]
\end{theorem}
Move is its own inverse (with swapped arguments). The precondition includes a
non-circularity check: for directory moves, the source must not be a prefix of
the destination.
\subsection{Permission Reversibility}
\begin{theorem}[\texttt{chmod\_reversible}]
\label{thm:chmod}
\[
\forall\, p, \FS, m_{\text{old}}, m_{\text{new}}.\;\;
\FS(p) = \mathsf{Some}(\mathit{node}) \land
\mathit{node}.\mathsf{mode} = m_{\text{old}}
\implies
\mathsf{chmod}(p, m_{\text{old}},
\mathsf{chmod}(p, m_{\text{new}}, \FS)) = \FS
\]
\end{theorem}
Permission changes are self-inverse: applying the old permissions after the
new permissions restores the original state. The same pattern holds for
\texttt{chown}.
\subsection{Content Write Reversibility}
\begin{theorem}[\texttt{write\_restore\_reversible}]
\label{thm:write}
\[
\forall\, p, \FS, c_{\text{old}}, c_{\text{new}}.\;\;
\mathsf{readFile}(p, \FS) = \mathsf{Some}(c_{\text{old}})
\implies
\mathsf{writeFile}(p, c_{\text{old}},
\mathsf{writeFile}(p, c_{\text{new}}, \FS)) = \FS
\]
\end{theorem}
Write operations are also self-inverse: writing the old content after the new
content restores the original state. This requires storing the old content as
undo data, which the \valence{} runtime handles automatically.
\subsection{Sequence Composition (Full Proof)}
The composition theorem (\cref{thm:sequence}) is the most important structural
result. We reproduce its key inductive step:
\begin{lstlisting}[style=leanstyle,caption={The sequence composition proof (inductive step).}]
theorem operationSequenceReversible
(ops : List Operation) (fs : Filesystem)
(hrev : allReversible ops fs) :
applySequence (reverseSequence ops)
(applySequence ops fs) = fs := by
induction ops generalizing fs with
| nil => simp [applySequence, reverseSequence]
| cons op rest ih =>
simp only [reverseSequence, applySequence,
List.reverse_cons, List.map_append]
have <hrev_op, hrev_rest> := hrev
have ih_result := ih (applyOp op fs) hrev_rest
have single := singleOpReversible op fs hrev_op
rw [applySequence_append]
simp only [applySequence]
rw [ih_result]
exact single
\end{lstlisting}
The proof unfolds as follows: for the empty list, both the forward and reverse
sequences are identity. For a cons cell $f :: \mathit{rest}$, the reverse
sequence is $\mathsf{reverseSequence}(\mathit{rest}) \mathbin{+\!\!+}
[\inv{f}]$. By the append lemma, applying this sequence is equivalent to first
applying $\mathsf{reverseSequence}(\mathit{rest})$ (which by the inductive
hypothesis restores $f(s)$) and then applying $\inv{f}$ (which by single
operation reversibility restores $s$).
% =============================================================================
% 7. IMPLEMENTATION
% =============================================================================
\section{Implementation}
\label{sec:implementation}
\subsection{Architecture}
\valence{} is implemented as an interactive shell in Rust, chosen for its
memory safety guarantees without garbage collection and its strong type system.
The implementation comprises 15,720 lines of Rust across 30 source files.
The architecture separates concerns into layers:
\begin{enumerate}
\item \textbf{Parser}: Tokenisation, quote processing, glob expansion,
variable expansion, arithmetic expansion, here documents.
\item \textbf{Operations}: Built-in filesystem commands with precondition
checking and proof-reference annotations.
\item \textbf{State Manager}: Undo/redo stacks, transaction groups,
operation history, and checkpoint/restore.
\item \textbf{REPL}: Interactive line editor with syntax highlighting,
command correction, and multi-line input for control structures.
\item \textbf{External Execution}: PATH lookup, pipeline construction,
I/O redirection, job control.
\end{enumerate}
\subsection{Operation Recording}
Every operation is recorded as an \texttt{Operation} struct containing:
\begin{lstlisting}[style=ruststyle,caption={The Operation type in Rust.}]
pub struct Operation {
pub id: Uuid,
pub op_type: OperationType,
pub path: String,
pub undo_data: Option<Vec<u8>>,
pub timestamp: DateTime<Utc>,
pub transaction_id: Option<Uuid>,
}
\end{lstlisting}
The \texttt{undo\_data} field stores whatever information is needed to reverse
the operation: original file contents for writes, original permissions for
chmod, the source path for moves, etc. The \texttt{transaction\_id} groups
operations for atomic undo.
\subsection{Undo/Redo Implementation}
The undo and redo stacks are maintained in the \texttt{ShellState} struct. Each
undo pops the most recent operation, applies its inverse, and pushes the
inverse onto the redo stack. Redo is symmetric.
A critical implementation detail, discovered during a 2026-02-12 audit: the
\texttt{record\_operation} function must \emph{clear the redo stack} (since
new operations invalidate the redo history), but a separate
\texttt{record\_redo\_operation} function must \emph{not} clear it (since redo
operations should not invalidate subsequent redos). This distinction is
essential for multi-step redo correctness.
\subsection{Proof Integration}
Each operation type maps to its corresponding formal proof references:
\begin{lstlisting}[style=ruststyle,caption={Proof reference mapping.}]
pub fn for_operation(op: OperationType) -> ProofReference {
match op {
Mkdir | Rmdir => MKDIR_RMDIR_REVERSIBLE,
CreateFile | DeleteFile => CREATE_DELETE_REVERSIBLE,
WriteFile => WRITE_FILE_REVERSIBLE,
CopyFile => COPY_FILE_REVERSIBLE,
Move => MOVE_REVERSIBLE,
Symlink | Unlink => SYMLINK_UNLINK_REVERSIBLE,
Chmod => CHMOD_REVERSIBLE,
Chown => CHOWN_REVERSIBLE,
// ...
}
}
\end{lstlisting}
When verbose mode is enabled, each operation prints its proof reference:
the theorem name, the file locations in each prover, and a human-readable
description. The \texttt{explain} command provides proof-annotated dry runs
without executing operations.
\subsection{Verification at the Implementation Level}
The \lean{} proofs operate on an abstract model. The Rust implementation
operates on the real filesystem. Bridging this gap is the
\emph{correspondence problem}, which we address through three mechanisms:
\begin{enumerate}
\item \textbf{Property-based testing}: Using the Rust \texttt{proptest}
framework, we generate random filesystem states and operation sequences,
execute them on real filesystems, and check that the reversibility
invariant holds. Over 1,000 iterations per property test, across 30+
property tests.
\item \textbf{Correspondence tests}: Dedicated test suites that mirror the
exact theorem statements from \lean{} (e.g.,
\texttt{prop\_mkdir\_rmdir\_reversible} corresponds to
\texttt{mkdir\_rmdir\_reversible}).
\item \textbf{Compile-time feature flags}: An optional \texttt{lean-verify}
feature that invokes the \lean{} type checker at build time to verify
that preconditions are satisfiable.
\end{enumerate}
We estimate the overall correspondence confidence at 85--95\%, with the core
operations (mkdir, rmdir, touch, rm) at 95\% and newer operations (glob,
conditionals) at 65--70\%. Full mechanised correspondence proofs (e.g., via
code extraction from Coq to OCaml, or via Rust verification tools like
Creusot~\citep{denis2022}) are planned future work.
% =============================================================================
% 8. RMO: VERIFIED IRREVERSIBLE DELETION
% =============================================================================
\section{RMO: Verified Irreversible Deletion}
\label{sec:rmo}
\subsection{The Storage Layer}