Protect and erase PII
Use a personal value for one operation without keeping it in the message history.
This example checks whether an email address belongs to a particular domain. The caller receives a boolean; the address is not copied into a result or Model.
Protect the input and mark its final use
Section titled “Protect the input and mark its final use”public record CheckEmailDomain(@ProtectData String email) {}
public class EmailCheck { @HandleCommand(onMissingProtectedData = MissingProtectedDataPolicy.FAIL) @DropProtectedData boolean handle(CheckEmailDomain command) { return command.email().endsWith("@example.com"); }}data class CheckEmailDomain(@field:ProtectData val email: String?)
class EmailCheck { @HandleCommand(onMissingProtectedData = MissingProtectedDataPolicy.FAIL) @DropProtectedData fun handle(command: CheckEmailDomain): Boolean = command.email?.endsWith("@example.com") == true}For a tracked command, @ProtectData stores the value separately and leaves a reference in the stored message.
Fluxzero restores it for the handler. @DropProtectedData makes this invocation its final use and removes the
retained value. Later processing of that stored message cannot retrieve the address; this handler explicitly
fails if it is missing.
Use the drop annotation only when no other handler or retry still needs that value. It is not a transaction that keeps PII available until every downstream action succeeds.
Try it
Section titled “Try it”TestFixture.createAsync(new EmailCheck()) .whenCommand(new CheckEmailDomain("alice@example.com")) .expectResult(true);TestFixture.createAsync(EmailCheck()) .whenCommand(CheckEmailDomain("alice@example.com")) .expectResult(true)Keep the address out of your own logs and any unprotected copies. Erasing the protected value does not erase copies your code has already made.
See ProtectData and DropProtectedData for the annotations. The data protection reference explains missing-value policies and Model boundaries.
© 2026 Fluxzero