feat(fls): write the e-mail programs of a .fls, loaded by Java as the original

topologyWriter.ts writes the e-mail server's domain and bean accounts with
their mailboxes, and the e-mail client's three folders and address book.
The client's account is no bean (FILIUS 2.14 has no kontoListe property):
it lives in /konten.txt and is written with the files.

A Java error is not copied: older files keep recipients as strings, which
Java puts into its typed lists unchecked, and its e-mail window fails on
them. The writer writes the AddressEntry Java's own AddressEntry(String)
makes of each; a null recipient is left out. The Java oracle now reports
that reading next to each such string, and our addressEntry matches it on
all 9 in the corpus. The test names the departure (RECIPIENTS_AS_STRINGS)
and checks that it touches man-in-the-middle.fls alone.

Checked by Java against Java: every corpus file, read and written again,
loads with the same e-mail programs as the original, up to that departure.
The synthetic topology adds an e-mail server and client with an account, a
mailbox, three folders, an address book and recipients of every form. 15
mutation probes, each loaded by Java, were all caught. The writer now
writes everything the reader reads of Java's view.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-09-30 08:44:34 +00:00
co-authored by Claude Opus 5.5
parent ccec734143
commit 34d3788cd2
9 changed files with 1083 additions and 58 deletions
+4 -2
View File
@@ -440,13 +440,15 @@ public class FlsOracle {
/**
* Older files keep recipients as strings: the list is typed, but the
* decoder does not check, so an element may be a String.
* decoder does not check, so an element may be a String. With it, how
* Java's own AddressEntry(String) reads it.
*/
static List<Object> addresses(List<AddressEntry> entries) {
List<Object> result = new ArrayList<>();
for (Object entry : entries) {
if (entry == null) result.add(null);
else result.add(entry instanceof AddressEntry address ? address(address) : Arrays.asList("string", entry.toString()));
else result.add(entry instanceof AddressEntry address ? address(address)
: Arrays.asList("string", entry.toString(), address(new AddressEntry(entry.toString()))));
}
return result;
}