Skip to content

Conversation

@bolinfest
Copy link
Collaborator

@bolinfest bolinfest commented Dec 10, 2025

This PR attempts to solve two problems by introducing a AbsolutePathBuf type with a special deserializer:

  • AbsolutePathBuf attempts to be a generally useful abstraction, as it ensures, by constructing, that it represents a value that is an absolute, normalized path, which is a stronger guarantee than an arbitrary PathBuf.
  • Values in config.toml that can be either an absolute or relative path should be resolved against the folder containing the config.toml in the relative path case. This PR makes this easy to support: the main cost is ensuring AbsolutePathBufGuard is used inside deserialize_config_toml_with_base().

While AbsolutePathBufGuard may seem slightly distasteful because it relies on thread-local storage, this seems much cleaner to me than using than my various experiments with https://docs.rs/serde/latest/serde/de/trait.DeserializeSeed.html. Further, since the deserialize() method from the Deserialize trait is not async, we do not really have to worry about the deserialization work being spread across multiple threads in a way that would interfere with AbsolutePathBufGuard.

To start, this PR introduces the use of AbsolutePathBuf in OtelTlsConfig. Note how this simplifies otel_provider.rs because it no longer requires settings.codex_home to be threaded through. Furthermore, this sets us up better for a world where multiple config.toml files from different folders could be loaded and then merged together, as the absolutifying of the paths must be done against the correct parent folder.

None if path.is_absolute() => {
Self::from_absolute_path(path).map_err(SerdeError::custom)
}
None => Err(SerdeError::custom(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this panic?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't have a strong opinion. I thought since None if path.is_absolute() didn't panic, then it would be "gentler" for this not to panic.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Come to think of it, it is likely important that None if path.is_absolute() does not panic, because if we want to use AbsolutePathBuf as an "input type" for app server (v2), we can have the requirement that callers pass in absolute paths.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What I'd like to catch is when deserialization runs without the guard.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But I don't think it's guaranteed to be a logic error. If V2 accepts AbsolutePathBuf over the wire and requires the client to specify an absolute path and the client sends a relative path, then app server should send back an error rather than crash, right?

#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
pub struct AbsolutePathBuf(PathBuf);

impl AbsolutePathBuf {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thoughts on keeping this close to config and naming with something that includes config? PathRelaveToConfig :D

Do we want this type to spread to other parts of codebase?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given that I made this small crate just for AbsolutePathBuf, I think it should live near the type rather than in core/config in case we have other objects from which we want to deserialize it.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, sorry, my above comment was with respect to the guard.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want this type to spread to other parts of codebase?

Yes, I think that we do. It is helpful to enforce path absoluteness at construction and not have to check it all over the place later (particularly when you likely no longer have the base path handy, as was the case in otel_provider.rs).

@bolinfest
Copy link
Collaborator Author

@dtolnay not sure if this would be of interest to you, but it feels like DeserializeSeed is designed for the "root" note of a tree of objects to deserialize [with context] whereas it would be nice to have a way to deserialize leaf nodes like in this case here.

@bolinfest bolinfest merged commit fa4cac1 into main Dec 10, 2025
69 of 73 checks passed
@bolinfest bolinfest deleted the pr7796 branch December 10, 2025 01:37
@github-actions github-actions bot locked and limited conversation to collaborators Dec 10, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants