Skip to content

Conversation

@duncan-daydream
Copy link
Collaborator

  • Introduces ConfigVariable, a type-safe wrapper for configuration variables that encapsulates key, fallback value, and VariablePrivacy to determine when values should be marked as secret based on type-specific rules.
  • Introduces StructuredConfigReader, wrapping swift-configuration's ConfigReader with type-safe access, privacy-aware queries, and always-return semantics that return fallback values on error.
  • Introduces TelemetryAccessReporter, a standard access reporter that posts configuration access events to EventBus:
    • DidAccessVariableBusEvent: Posted on successful access with key, value, source, and fallback usage
    • DidFailToAccessVariableBusEvent: Posted on resolution failure with key and error

Dfowj and others added 28 commits January 6, 2026 10:31
- DidAccessVariableBusEvent: posted when a variable is successfully accessed
- DidFailToAccessVariableBusEvent: posted when a variable can't be found (.success(nil)) or if an error is raised when querying providers (.failure(error))
- Use the convenience initializer w/ EventBus parameter to get the standard TelemetryAccessReporter
- Use the primary initializer to pass an access reporter type directly.
@duncan-daydream duncan-daydream marked this pull request as draft January 8, 2026 17:18
@github-actions
Copy link

github-actions bot commented Jan 8, 2026

Code Coverage Report

Overall Coverage: 1.95% (3 of 154)

DevConfiguration: 1.95% (3 of 154)
File Coverage Covered Lines Executable Lines
ConfigVariable.swift 0.00% 0 8
DevConfiguration.swift 100.00% 3 3
DidAccessVariableBusEvent.swift 0.00% 0 5
DidFailToAccessVariableBusEvent.swift 0.00% 0 4
StructuredConfigReader.swift 0.00% 0 90
TelemetryAccessReporter.swift 0.00% 0 33
VariablePrivacy.swift 0.00% 0 11

public let accessReporter: any AccessReporter

/// The internal configuration reader that is used to resolve configuration values.
let reader: ConfigReader

Choose a reason for hiding this comment

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

I think this can be public.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Whats your though here? If they don't want to use our interface all the time, or our interface isn't up to parity with the internal reader, they should be able to get direct access?

I wanted it private to prevent confusion between the reader's interface and ours, but 🤷‍♂️

public let value: ConfigContent

/// The name of the provider that supplied the value.
public let source: String

Choose a reason for hiding this comment

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

Could probably just call this providerName to match Swift Configuration.

/// Returns `true` if sensitive types (like String) should be treated as private.
///
/// This is equivalent to `.auto || .private`.
var isPrivateForSensitiveTypes: Bool {
Copy link

@prachigauriar prachigauriar Jan 10, 2026

Choose a reason for hiding this comment

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

Looking at how you use this, I think I’d rather have some extensions on ConfigVariable. Something like:

extension ConfigVariable {
    var isSecret: Bool {
        return secrecy == .secret
    }
}


extension ConfigVariable<String> {
    var isSecret: Bool {
        return secrecy != .public
    }
}


extension ConfigVariable<[String]> {
    var isSecret: Bool {
        return secrecy != .public
    }
}

This works correctly in a playground. It would transform your access functions in StructuredConfigReader into:

return try reader.requiredIntArray(
    forKey: variable.key,
    isSecret: variable.isSecret
)

/// Variable privacy determines how values are handled in telemetry, logging,
/// and other observability systems. Secret values are redacted or obfuscated
/// to prevent sensitive information from being exposed.
public enum VariablePrivacy {

Choose a reason for hiding this comment

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

Should we change this to VariableSecrecy to match Swift Configuration naming?

///
/// The reader never throws. If resolution fails, it returns the variable's fallback value and posts a
/// `DidFailToAccessVariableBusEvent` to the event bus.
public final class StructuredConfigReader {

Choose a reason for hiding this comment

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

Perhaps we should rename this ConfigVariableReader, since that’s really what it is.

Also, does it need to be a class vs. a struct? ConfigReader is a struct.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants