telemetry-facade-pattern — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited telemetry-facade-pattern (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Telemetry targetTelemetry target inside the SwiftPM Package.TelemetryEvent value type (enum / struct, Sendable)TelemetrySink protocol: public protocol TelemetrySink: Sendable {
func receive(_ event: TelemetryEvent) async
}| Facade type | Use when | Cost |
|---|---|---|
actor Telemetry (default) | any sink holds subscription identity (e.g. MXMetricManagerSubscriber) or does async I/O | observe is async |
struct Telemetry: Sendable | every sink is fully synchronous and stateless | no lifecycle owner for stateful sinks |
telemetry.observe(.sessionCompleted(id: sessionId, durationMs: 12_345))| Sink | Receives | Purpose |
|---|---|---|
OSLogSink | All events | Human-readable debug messages |
TrackingSink (default NoOpTrackingSink) | Business events | v1 has no third-party tracking but the protocol is reserved; future swaps require zero call-site changes |
MetricKitSink | OS 26 and earlier: MXMetricManagerSubscriber (≤26). OS 27+: hold a single MetricManager() instance (27+) | Performance / diagnostics persistence — base-class and actor-viability details: trap 6 in references/wiring-traps.md |
GameCenterSink (games) | Completion / achievement events | Submit score / unlock achievement |
public struct NoOpTrackingSink: TelemetrySink {
public init() {}
public func receive(_ event: TelemetryEvent) async { /* intentionally empty */ }
}For the six composition-root wiring traps (existing-but-unwired sinks, sink ordering, blocking I/O on the gameplay path, late-binding, sink-fired vs terminal-call-succeeded — GKLeaderboard.submitScore / GKAchievement.report never reached — and MetricKitSink's OS-version-dependent base class), read references/wiring-traps.md.
telemetry.observe(...) with no external tracking, and a future TelemetryDeck / in-house pipeline only swaps the sink.Telemetry target and use Logger directly. But if you anticipate adding tracking / metrics later, building the facade up front pays off.TrackingSink): handle routing inside the facade; call sites still unchanged.Telemetry target is standalone; UI / Engine don't directly depend on anything beyond OSLog.TelemetryEvent is a value type, Sendable.NoOpTrackingSink is provided and wired in the composition root.intend to fire** (not just that the sink type exists) — the "existing-but-unwired" failure mode.
pinning the order.
interactive path is never frozen by a sink's CloudKit/GameKit work.
not just the sink.
oslog-logger-defaults: the concrete OSLogSink implementation dependency.apple-three-piece-analytics: each piece corresponds to one sink.swiftpm-modularization: why Telemetry is its own target.references/official-docs.md.~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.