ansible-automation-eng…
Ansible automation: playbooks, roles, collections, Molecule testing, Vault security.
| Data Category | Storage | Reason | |---------------|---------|--------| | API tokens, OAuth tokens | **Keychain** | Encrypted at rest; protected by device passcode / Secure Enclave | | Passwords, private keys | **Keychain** | Never stored in plaintext | | User preferences
$ npx -y skills add notque/vexjoy-agent --agent claude-codeHow it fires
How this agent gets triggered: by you, by Claude, or both.
Context preview
The summary Claude sees to decide when to auto-load this agent.
| Data Category | Storage | Reason | |---------------|---------|--------| | API tokens, OAuth tokens | **Keychain** | Encrypted at rest; protected by device passcode / Secure Enclave | | Passwords, private keys | **Keychain** | Never stored in plaintext | | User preferences
| Data Category | Storage | Reason | |---------------|---------|--------| | API tokens, OAuth tokens | **Keychain** | Encrypted at rest; protected by device passcode / Secure Enclave | | Passwords, private keys | **Keychain** | Never stored in plaintext | | User preferences (theme, language) | UserDefaults | Non-sensitive; loss is acceptable | | Feature flags | UserDefaults | Non-sensitive | | JWT refresh tokens | **Keychain** | Credential — same as token | | Device-specific identifiers | UserDefaults or Keychain depending on sensitivity | Evaluate case by case |
**Detection trigger**: Any `UserDefaults` call with a key string containing `token`, `password`, `key`, `secret`, `credential`, or `auth` is a security violation requiring Keychain migration.
// Wrong
UserDefaults.standard.set(apiToken, forKey: "auth_token")
// Correct — Keychain wrapper
struct KeychainStore {
static func save(token: String, service: String, account: String) throws {
let data = Data(token.utf8)
let query: [CFString: Any] = [
kSecClass: kSecClassGenericPassword,
kSecAttrService: service,
kSecAttrAccount: account,
kSecValueData: data,
kSecAttrAccessible: kSecAttrAccessibleWhenUnlockedThisDeviceOnly
]
SecItemDelete(query as CFDictionary) // Remove existing item
let status = SecItemAdd(query as CFDictionary, nil)
guard status == errSecSuccess else {
throw KeychainError.saveFailed(status)
}
}
}For endpoints handling financial, healthcare, or authentication data, implement certificate or public key pinning via `URLSessionDelegate`.
final class PinningDelegate: NSObject, URLSessionDelegate, @unchecked Sendable {
private let pinnedHashes: Set<String>
init(pinnedHashes: Set<String>) {
self.pinnedHashes = pinnedHashes
}
func urlSession(
_ session: URLSession,
didReceive challenge: URLAuthenticationChallenge,
completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void
) {
guard challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust,
let serverTrust = challenge.protectionSpace.serverTrust,
let certificate = SecTrustGetCertificateAtIndex(serverTrust, 0) else {
completionHandler(.cancelAuthenticationChallenge, nil)
return
}
let serverCertData = SecCertificateCopyData(certificate) as Data
let hash = serverCertData.sha256HexString // implement SHA-256 helper
if pinnedHashes.contains(hash) {
completionHandler(.useCredential, URLCredential(trust: serverTrust))
} else {
completionHandler(.cancelAuthenticationChallenge, nil)
}
}
}| Source | Rule | |--------|------| | API keys in source files | **Hard boundary** — decompilation extracts them trivially | | API keys in Info.plist | **Hard boundary** — same decompilation risk | | Build-time secrets | Use `.xcconfig` files excluded from version control; read via `Bundle.main.infoDictionary` | | CI/CD secrets | Environment variables injected at build time; keep out of version control | | Runtime secrets | Fetched from server after authentication; stored in Keychain |
Validate all data from external sources before use:
// URL from deep link or pasteboard — never force-unwrap
guard let url = URL(string: rawString), url.scheme == "https" else {
logger.warning("Rejected invalid URL: \(rawString, privacy: .private)")
return
}
// API response data — always decode into typed models, never assume structure
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
let response = try decoder.decode(APIResponse.self, from: data)---
Use `import Testing` for all new test files. Migrate XCTest suites to Swift Testing only when explicitly requested.
| Feature | Swift Testing | XCTest | |---------|--------------|--------| | Test declaration | `@Test func name()` | `func testName()` | | Assertion | `#expect(condition)` | `XCTAssertTrue(condition)` | | Parameterized tests | `@Test(arguments: [...])` | Manual loop or subclassing | | Expected failure | `@Test(.disabled("reason"))` | `XCTSkip` | | Test tags | `@Test(.tags(.performance))` | None built-in |
import Testing
@testable import MyApp
@Suite("UserRepository")
struct UserRepositoryTests {
let sut: UserRepository
let mockClient: MockHTTPClient
init() {
mockClient = MockHTTPClient()
sut = UserRepository(client: mockClient)
}
@Test("fetch returns decoded user on success")
func fetchSuccess() async throws {
mockClient.stubbedData = try JSONEncoder().encode(User.fixture)
let user = try await sut.fetchUser(id: User.fixture.id)
#expect(user.id == User.fixture.id)
#expect(user.displayName == User.fixture.displayName)
}
@Test("fetch throws on network failure", arguments: [
URLError(.notConnectedToInternet),
URLError(.timedOut)
])
func fetchNetworkFailure(error: URLError) async {
mockClient.errorToThrow = error
await #expect(throws: FetchError.self) {
try await sut.fetchUser(id: UUID())
}
}
}Essays and writing behind this toolkit live at vexjoy.com. VexJoy Agent connects plain-English requests to specialist agents, skills, and workflows. /do selects the knowledge and tools needed for your task.
Repo: notque/vexjoy-agent
Ansible automation: playbooks, roles, collections, Molecule testing, Vault security.
**Scope**: Module selection patterns, builtin vs command/shell decisions, collection modules, and version-specific module changes **Version range**:…
**Scope**: Molecule test scenarios, ansible-lint rules, idempotency validation, and check-mode patterns **Version range**: Molecule 6.0+ / ansible-lint 6.0+ /…
Universal rules injected by /do at dispatch. Each agent's .md file supplies domain rules.
**Scope**: Failure modes in agent output style — over-reporting, self-congratulation, verbose narration, and hedging. Covers what to detect and how to fix…
Zero-dependency combat visual upgrades: CSS particle replacement, Framer Motion combat juice, CSS 3D card transforms.