swift — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited swift (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.
Use this skill for Swift code that needs strong API boundaries, predictable threading, and idiomatic Apple-platform integration. When the code is part of a Nitro Module, pair this with build-nitro-modules for generated specs, Promise mapping, and HybridObject constraints.
enum with associated values when the set is closed and value-like.barcode and barcodeType are meaningful only together, put both on ScannedBarcode; do not make both optional on a generic scanned-data struct.if let chains to discover valid field combinations, the API shape is probably wrong.// Avoid: the valid combinations are implicit and easy to misuse.
struct ScannedData {
let position: Point
let text: String?
let barcode: String?
let barcodeType: BarcodeType?
let face: Rect?
}
// Prefer: each state exposes the fields that are valid for that state.
protocol ScannedData {
var position: Point { get }
}
struct ScannedText: ScannedData {
let position: Point
let text: String
}
struct ScannedBarcode: ScannedData {
let position: Point
let barcode: String
let barcodeType: BarcodeType
}
struct ScannedFace: ScannedData {
let position: Point
let face: Rect
}Task, DispatchQueue, or Promise plumbing for simple value construction, cached metadata, or pure transforms.async/await, Task, and actors only when the full operation can be represented cleanly in Swift concurrency without queue escape hatches.DispatchQueue when Apple APIs, delegates, callbacks, C++ bridges, JS runtimes, or Nitro thread boundaries already revolve around queues, or when heavier native work must not block the caller.DispatchQueue.main unless the platform API requires the main thread, such as UIKit/AppKit/VisionKit presentation or view mutation. Keep main-thread blocks small and move parsing, conversion, I/O, session negotiation, and CPU work to an owned queue or async API.Task, DispatchQueue, actor, or thread hops as an architecture smell. A component should either own the queue/actor it works on, or cross into that owner once at the public async boundary or native callback boundary.DispatchQueue.asyncAfter, Task.sleep, Thread.sleep, timers, extra queue hops, or calling the same method twice. Fix the owner queue, lifecycle state, completion callback, delegate event, or async API boundary instead. Retry only for external nondeterminism such as hardware, OS services, remote services, or network, and keep retries bounded, cancellable, and idempotent.Task { @MainActor in ... } as a generic main-thread hop from a nonisolated or Nitro-generated entry point. It creates unstructured Swift concurrency. Use it only when the operation is otherwise Swift-concurrency based and benefits from async/await, task cancellation, or actor isolation end to end.DispatchQueue.main.async boundary or an async public method that owns the hop. Direct DispatchQueue.main.async is understood by Swift's actor checker for @MainActor calls; generic queue wrappers such as Promise.parallel(.main) usually are not.Task { @MainActor } or DispatchQueue.main.async hops through the workflow.MainActor.assumeIsolated, Thread.isMainThread branches, or queue .sync calls to make a Swift-concurrency design compile. That is a signal to choose a queue-based design or change the API boundary.DispatchQueue.sync, DispatchQueue.main.sync, or equivalent synchronous queue hops. Treat them as bugs, especially in property getters and setters.DispatchQueue.async or a Nitro Promise method for queue-bound work that callers must wait for.NSLock, identify the concrete shared mutable values, the threads/queues that can access them concurrently, and why ownership by MainActor, a serial queue, a Nitro runtime/thread, or immutable snapshots is not enough.Array and Dictionary mutations are not thread-safe. If listener add/remove can race with native delegate emission, either serialize every access on one owner queue/thread, or use a tiny lock only to mutate and snapshot the listener registry.Promise<T> methods, usually with Promise.parallel(queue).// Avoid: synchronous queue hop hidden in a getter.
var status: SessionStatus {
queue.sync { session.status }
}
// Prefer: make the async boundary explicit.
func getStatus() throws -> Promise<SessionStatus> {
return Promise.parallel(queue) {
return self.session.status
}
}final by default unless subclassing is part of the design.String, Array, Dictionary, structs, protocols, and Foundation value types. Avoid Objective-C bridge types unless an Apple API requires them.guard to validate input and state early. Throw specific errors for user-reachable failures.HybridDataScanner.swift should implement HybridDataScanner; it should not also contain extensions, conversions, UIViewController helpers, delegates, or framework adapters.Extensions/UIViewController+topPresentedViewController.swift, Extensions/CGPoint+Point.swift, or Extensions/Barcode+toScannedCode.swift with internal or package visibility where appropriate.Hybrid* implementation files or other primary implementation files, even when the extension is private, tiny, or only used by that file. Put every extension in a separate named Type+operation.swift extension/converter file so code splitting, maintainability, and future diffs stay clean.Hybrid* factories and implementation methods. Permission/status switches, Bundle.main.object(forInfoDictionaryKey:) checks, hardware capability checks, Info.plist validation, and similar setup guards belong in focused helper/extension files such as AVCaptureDevice+CameraAuthorization.swift or Bundle+CameraUsageDescription.swift; the factory call site should stay one or two lines.Hybrid*Factory.swift as orchestration only: resolve generated options, call preflight helpers, create/start the native session, and return/reject the Promise. Do not define session/coordinator/delegate classes, Native*Options adapters, presenter traversal helpers, scanner configuration builders, barcode mappings, permission switches, or Info.plist checks in the factory file.Hybrid* method grows a switch over Apple authorization/status, a multi-line guard for platform setup, view-controller lookup logic, DataScannerViewController configuration, or conversion loops, extract it before continuing. The caller should read as a short sequence of named operations, not as the implementation of each operation.Utils.swift files for these helpers. Name the file after the platform type or domain check and keep each helper focused on one check or conversion.targetFormats.flatMap { $0.toVNBarcodeFormat() }, not a multi-line flatMap { format in format.toVNBarcodeFormat() }. Do not use $0 when a surrounding or nested closure already uses shorthand arguments; name parameters in nested closures or when clarity needs it.map, flatMap, reduce, or Set(...).Int, String, Double, Any, CGPoint, or CGRect unless the conversion is genuinely about that type. Prefer the domain type direction, such as BarcodeFormat.from(format:) or BarcodeFormat(nativeFormat:), over Int.toBarcodeFormat().Array or Collection extensions only when the collection has real domain behavior, such as validation across elements, deduplication, ordering, batching, caching, nonempty checks, or error aggregation. If the receiver is a concrete [SomeDomainType] and the body mostly saves one map, keep that map in caller code.Promise.parallel(queue) for DispatchQueue-based work such as AVFoundation session operations.Promise.async only when wrapping Swift async/await or Task-native APIs end to end.Promise<T> instances. Prefer Promise.parallel, Promise.async, Promise.resolved, and Promise.rejected; use a manual Promise only for real native completion/delegate/callback bridges and keep it in the smallest scope with exactly-once completion.Promise.async with queue .sync calls or actor escape hatches.~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.