name: revyl-cli-auth-bypass-ios description: Native iOS leaf recipe for test-only auth bypass deep links using Revyl launch arguments.
Revyl iOS Auth Bypass Skill
Use this leaf skill when revyl-cli-auth-bypass has selected a native iOS app. This is app code guidance, not a Revyl authentication shortcut.
For the first-pass setup, start from revyl-cli-auth-bypass; it detects the stack, applies the shared safety contract, and delegates here for Swift/iOS implementation details.
Native Agent Behavior
- Ask at most 1-3 concise clarification questions only when the target app, platform, session, URL scheme, token source, or sensitive action cannot be inferred from the repo or Revyl CLI.
- Prefer safe defaults and keep moving when app source,
revyl dev list, screenshots, or reports can answer the question. - When Revyl prints a viewer or local app URL, open it in the native browser/tool surface when available: Codex Browser/in-app browser for local URLs, Revyl viewer URLs, screenshots, and page checks; Claude Code
.claude/skillsslash-command discovery plus WebFetch/WebSearch or configured MCP/browser tools; Cursor.cursor/skillsplus.cursor/rules/revyl-skills.mdcand available MCP/browser tools. - If no browser tool is exposed, report the URL and verify through
revyl device screenshotorrevyl device reportinstead of claiming browser access. - Confirm before entering sensitive data, submitting forms, uploading files, accepting browser permissions, changing sharing/access, or deleting data.
Contract
Use one app-specific deep link shape:
myapp://revyl-auth?token=<token>&role=<role>&redirect=<allowlisted-route>
Revyl launch variables arrive in iOS simulator apps as launch arguments, for example:
-REVYL_AUTH_BYPASS_ENABLED true -REVYL_AUTH_BYPASS_TOKEN <token>
Files To Add Or Update
Info.plist: register the app URL scheme.- SwiftUI app root or app/scene delegate: handle
myapp://revyl-auth. - Auth/session module: create the normal app session for an allowlisted role.
- Router/coordinator: route only to allowlisted destinations.
- Account, debug, or settings screen: show accepted/rejected auth-bypass state in test builds.
URL Scheme
Register an app-specific scheme such as myapp in Info.plist:
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLSchemes</key>
<array>
<string>myapp</string>
</array>
</dict>
</array>
Swift Handler
Keep session creation app-specific and explicit:
import Foundation
private let allowedRedirects: [String: AppRoute] = [
"/account": .account,
"/checkout": .checkout,
"/cart": .cart
]
private let allowedRoles: Set<String> = ["buyer", "support"]
func launchValue(_ key: String) -> String? {
let args = ProcessInfo.processInfo.arguments
guard let index = args.firstIndex(of: "-\(key)") else { return nil }
let valueIndex = args.index(after: index)
return args.indices.contains(valueIndex) ? args[valueIndex] : nil
}
func queryValue(_ name: String, in url: URL) -> String? {
let items = URLComponents(url: url, resolvingAgainstBaseURL: false)?.queryItems ?? []
return items.first(where: { $0.name == name })?.value
}
func handleRevylAuthBypass(_ url: URL) throws -> Bool {
guard url.scheme == "myapp", url.host == "revyl-auth" else { return false }
guard launchValue("REVYL_AUTH_BYPASS_ENABLED") == "true" else {
throw AuthBypassError.disabled
}
guard queryValue("token", in: url) == launchValue("REVYL_AUTH_BYPASS_TOKEN") else {
throw AuthBypassError.badToken
}
let role = queryValue("role", in: url) ?? "buyer"
let redirect = queryValue("redirect", in: url) ?? "/account"
guard allowedRoles.contains(role) else { throw AuthBypassError.badRole }
guard let route = allowedRedirects[redirect] else { throw AuthBypassError.badRedirect }
TestSession.signIn(role: role)
AppRouter.shared.navigate(to: route)
return true
}
Call the handler from SwiftUI or app delegate URL handling:
.onOpenURL { url in
do {
if try handleRevylAuthBypass(url) {
AuthBypassStatus.shared.accepted()
}
} catch {
AuthBypassStatus.shared.rejected(String(describing: error))
}
}
Replace TestSession, AppRouter, AppRoute, and AuthBypassStatus with the app's real session and UI surfaces.
Verification
Start a fresh Revyl session with launch vars attached:
export REVYL_AUTH_BYPASS_TOKEN="<test-only-token>"
revyl global launch-var update REVYL_AUTH_BYPASS_TOKEN --value "$REVYL_AUTH_BYPASS_TOKEN"
revyl dev --platform ios --no-build \
--launch-var REVYL_AUTH_BYPASS_ENABLED \
--launch-var REVYL_AUTH_BYPASS_TOKEN
Then verify valid and rejected links:
revyl device navigate --url "myapp://revyl-auth?token=$REVYL_AUTH_BYPASS_TOKEN&role=buyer&redirect=%2Fcheckout"
revyl device screenshot --out /tmp/revyl-auth-bypass-ios-valid.png
revyl device navigate --url "myapp://revyl-auth?token=wrong-token&role=buyer&redirect=%2Fcheckout"
revyl device navigate --url "myapp://revyl-auth?token=$REVYL_AUTH_BYPASS_TOKEN&role=admin&redirect=%2Fcheckout"
revyl device navigate --url "myapp://revyl-auth?token=$REVYL_AUTH_BYPASS_TOKEN&role=buyer&redirect=%2Fadmin"
revyl device screenshot --out /tmp/revyl-auth-bypass-ios-rejected.png
Guardrails
- Never ship an unconditional production bypass.
- Gate by simulator/debug/staging/test build plus
REVYL_AUTH_BYPASS_ENABLED=true. - Never put raw tokens in source, YAML, screenshots, or PR copy.
- Keep role and redirect allowlists small and app-specific.
- Show rejected state visibly in the app so the agent can diagnose failures.