Annotation Interface ProtectData
When a field is annotated with @ProtectData, Fluxzero does not always protect the entire
object graph rooted at that field. Instead, it applies the following rules:
1) The field value is protected as a whole if the value is a leaf value as determined by
ReflectionUtils.isLeafValue(Object), a
JsonNode, a Data, an Iterable, a
Map, or a type annotated with @ProtectData.
2) Otherwise, Fluxzero only traverses into nested properties that are themselves explicitly annotated with
@ProtectData.
3) For nested paths, every property in the path must therefore be explicitly annotated with @ProtectData.
If any intermediate property is not annotated, traversal stops at that point and nested values below it are not
protected.
This makes the behavior explicit and opt-in: sensitive nested values are only protected when each step in the path is marked for protection, while scalar or container-like values are offloaded as a single protected value.
When a message is later deserialized and passed to a handler, Fluxzero will automatically reinject the protected information into the payload prior to invoking the handler method.
To permanently remove protected data after it is no longer needed, consider using the DropProtectedData
annotation on a handler method.
Updates committed through Model also retain only redacted event payloads.
Reconstruction restores values that are still available; erased values remain absent and vault read failures
fail reconstruction. This does not redact values copied into Model state, documents or snapshots. Durable Model
updates require vault storage even when their commands are handled locally.
Safe record editing and Model-event redaction require a supported
serialized property
mapping. Custom wire shapes must supply this capability explicitly; unsupported mappings prevent publication.
Example
public record RegisterCitizen(
String name,
@ProtectData String socialSecurityNumber
) {
}
Nested Example
public record RegisterCitizen(
@ProtectData SensitiveDetails details
) {
}
public record SensitiveDetails(
@ProtectData String socialSecurityNumber,
String displayName
) {
}
In this example, details/socialSecurityNumber is protected, while details/displayName remains part
of the regular payload because it is not annotated.- See Also: