diff --git a/crates/arti/src/logging.rs b/crates/arti/src/logging.rs
index 7e5a53325d0391925ec218746a7114f14f42f6a0..cd26d3f58ce1db41be666f6165de62cab49c4d3a 100644
--- a/crates/arti/src/logging.rs
+++ b/crates/arti/src/logging.rs
@@ -39,14 +39,8 @@ pub struct LoggingConfig {
     /// Configuration for one or more logfiles.
     #[serde(default)]
     #[builder_field_attr(serde(default))]
-    #[builder(
-        setter(custom),
-        field(
-            type = "Option<Vec<LogfileConfigBuilder>>",
-            build = "self.build_files()?"
-        )
-    )]
-    files: Vec<LogfileConfig>,
+    #[builder(sub_builder)]
+    files: LogfileListConfig,
 }
 
 /// Return a default tracing filter value for `logging.console`.
@@ -68,20 +62,28 @@ impl LoggingConfig {
     }
 }
 
-impl LoggingConfigBuilder {
+/// Local type alias, mostly helpful for derive_builder to DTRT
+type LogfileListConfig = Vec<LogfileConfig>;
+
+#[derive(Default, Clone, Deserialize)]
+#[serde(transparent)]
+/// List of logfiles to use, being built as part of the configuration
+pub struct LogfileListConfigBuilder {
+    /// The logfiles, as overridden
+    files: Option<Vec<LogfileConfigBuilder>>,
+}
+
+impl LogfileListConfigBuilder {
     /// Add a file logger
-    pub fn append_file(&mut self, file: LogfileConfigBuilder) -> &mut Self {
+    pub fn append(&mut self, file: LogfileConfigBuilder) -> &mut Self {
         self.files
-            .get_or_insert_with(LoggingConfigBuilder::default_files)
+            .get_or_insert_with(Self::default_files)
             .push(file);
         self
     }
 
     /// Set the list of file loggers to the supplied `files`
-    pub fn set_files(
-        &mut self,
-        files: impl IntoIterator<Item = LogfileConfigBuilder>,
-    ) -> &mut Self {
+    pub fn set(&mut self, files: impl IntoIterator<Item = LogfileConfigBuilder>) -> &mut Self {
         self.files = Some(files.into_iter().collect());
         self
     }
@@ -94,7 +96,7 @@ impl LoggingConfigBuilder {
     }
 
     /// Resolve `LoggingConfigBuilder.files` to a value for `LoggingConfig.files`
-    pub(crate) fn build_files(&self) -> Result<Vec<LogfileConfig>, ConfigBuildError> {
+    pub(crate) fn build(&self) -> Result<Vec<LogfileConfig>, ConfigBuildError> {
         let default_buffer;
         let files = match &self.files {
             Some(files) => files,
diff --git a/doc/semver_status.md b/doc/semver_status.md
index bc8f951325360d054223aeb08eb3bfc8cd31e0ab..10e395668a9486d304c414ca7a039723ce152301 100644
--- a/doc/semver_status.md
+++ b/doc/semver_status.md
@@ -22,6 +22,12 @@ We can delete older sections here after we bump the releases.
 
 BREAKING: Configuration of fallback directories overhauled; now uses FalllbadkDirBuilder more.
 
+### arti
+
+BREAKING: Replaced LoggingConfigBuilder::file (taking Vec) with LoggingConfigBuilder::files
+BREAKING: LoggingConfigBuilder::build() throws ConfigBuildError, not a bespoke error
+MODIFIED: LoggingConfigBuilder is now Deserialize
+
 ### tor-basic-util
 
 MODIFIED: Added `reset()` method to RetrySchedule.