Added
- Centralized Configuration (
LBConfig): IntroducedLBConfigstruct (Hashable,Sendable) consolidatingmaxLogs,isEnabled,minLogLevel,redactSensitiveFields,sensitiveKeys, andidentifierinto a single value. The wholeLogBirdlogging entry (gate, redactor, identifier) is now derived from one config snapshot. Includes a new publicLogBird.configproperty (static and instance) to read/replace the configuration atomically. - Configurable Recording Gate (
isEnabled+minLogLevel): AddedisEnabled: Boolmaster switch (defaults totrueunderDEBUG,falseotherwise, resolved via#if DEBUGinsideLBConfig.init) andminLogLevel: LBLogLevelseverity floor. When recording is disabled or the entry is below the threshold,log(...)returns early after a single queue hop — no OSLog forwarding, storage, or publishing.clearLogs()andexport()remain ungated. Available on both static and instance facades. - Layered Sensitive Keys API (
LBSensitiveKeysAction): IntroducedLBSensitiveKeysActionenum with.add([String]),.set([String]),.reset, and.clearcases, exposed viaLogBird.sensitiveKeys(_:)(static and instance) andLBConfig.sensitiveKeys(_:). New keys are normalized at insertion time (lowercased, stripping-,_, and whitespace). - Global Default Sensitive Keys: Added thread-safe global application defaults through
LogBird.setDefaultSensitiveKeys(_:)and read-onlyLogBird.defaultSensitiveKeys(Set<String>). Per-instance configs either inherit these globals (with optional.addextensions) or define an explicit override set via.set. LBLogLevel: Comparable:LBLogLevelnow conforms toComparable, ordered by declaration severity (.debug < .info < .warning < .error < .critical) via an internalseverityRank, not the alphabetical raw value. Required by theminLogLevelfloor.- Expanded Default Sensitive Key Set: Extended the curated default needles from 6 to 10:
password,token,authorization,auth,secret,apikey,cookie,bearer,credentials,privatekey. Defaults are now pre-normalized at declaration time. - Convenience Initializer: Added
LogBird.init(subsystem:category:fileID:maxLogs:minLogLevel:)convenience initializer exposing the most common tuning knobs without requiring a fullLBConfig.
Modified
LogBird.initSignature: The designated initializer parametermaxLogs: Int = 1000was replaced byconfig: LBConfig = LBConfig(). [Breaking] Migrate withLogBird(config: LBConfig(maxLogs: ...))or the new convenience initializer.sensitiveKeysProperty: Changed from a read-write[String]property to a read-onlySet<String>view on both static and instance facades. [Breaking] Direct assignment (LogBird.sensitiveKeys = [...]) no longer compiles; reconfigure viaLogBird.sensitiveKeys(_:)with anLBSensitiveKeysAction(.add,.set,.reset,.clear).defaultSensitiveKeysSemantics: Changed from a per-instance[String]constant (static let) to the global application defaults accessor (static var,Set<String>, thread-safe). [Breaking] It now reflects/overrides app-wide defaults instead of the shared instance baseline.LBManagerState Consolidation: Replaced the scatteredstoredMaxLogs,storedRedactSensitiveFields,storedSensitiveKeys, andstoredIdentifierfields with a singlestoredConfig: LBConfigvalue. All configuration reads/writes now go through one atomicdispatchQueue.sync.- Atomic Per-Field Config Setters: Per-field setters (
maxLogs,identifier,redactSensitiveFields,isEnabled,minLogLevel) now mutatestoredConfiginside a singledispatchQueue.sync, eliminating the prior read-modify-write TOCTOU window across two queue hops.
Fixed
- Config TOCTOU Race: Resolved a time-of-check/time-of-use race where a concurrent change to a different config field could be clobbered by a read-modify-write spanning two queue hops. All field setters are now atomic.
- Snapshot Consistency: The OSLog identifier is now read from the same config snapshot used by the gate and redactor, so a single log entry can no longer be split across two configurations by a concurrent change.
- Dead State Removal: Removed the unused
storedIdentifierproperty andLogSnapshotstruct left over after theLBConfigconsolidation. - Dangling
defaultIsEnabledReference: Removed stale documentation/SwiftDoc references to aLogBird.defaultIsEnabledsymbol that was never defined; the#if DEBUGdefault now lives once insideLBConfig.init.
Removed
maxLogs:Parameter onLogBird.init: Replaced byconfig: LBConfig. [Breaking]LogBird.sensitiveKeysSetter: Direct assignment is no longer supported; use theLBSensitiveKeysActionAPI. [Breaking]LogBird.defaultSensitiveKeysas a[String]static let: Replaced by the globalSet<String>accessor. [Breaking]- Public
LBSensitiveKeysState: Scoped to internal (backs a private property ofLBConfigand was never part of the public surface).
Full migration guide: see .agents/skills/logbird-migration/SKILL.md for side-by-side refactoring recipes covering both v1.0.0 → v2.0.0 and v2.0.0 → v2.1.0.