Custom Providers¶
Ghostvault supports any website — not just Google. Built-in providers (google, github, facebook) work out of the box. For any other site, create a custom provider recipe.
What is a provider?¶
A provider is a data-driven login recipe. It describes:
- Where to go (
login_url) - How to detect success (
auth_cookie_names+success_url_fragments) - How to check if session expired (
session_probe_url) - How to sign out (
logout_url)
Each profile (account) is a container — it holds sessions for every website equally. Google is just one provider; it's not a "parent" that others depend on.
Create a custom provider¶
await gv.create_provider(
name="my_bank",
login_url="https://mybank.com/login",
success_url_fragments=["mybank.com/dashboard"],
auth_cookie_names=["session_id"],
auth_cookie_domain="https://mybank.com",
session_probe_url="https://mybank.com/account",
login_url_fragments=["mybank.com/login"],
description="My bank login",
)
Then use it:
await gv.create_account(name="Banking", provider="my_bank")
await gv.sign_in("acc_xyz", provider="my_bank")
# → browser opens mybank.com/login → user logs in → session saved
Login levels¶
| Level | What it does | When |
|---|---|---|
| 1 (manual) | Open login_url, user does everything | Always available |
| 2 (auto-fill) | Execute login_steps (fill/click) |
Provider has login_steps + credentials stored |
| 3 (recording) | Replay recorded actions | Provider has recorded_steps |
Auto-selection: gv_sign_in picks the highest available level. If Level 2/3 fails → falls back to Level 1.
Detect login options on a page¶
Not sure what a page offers? Scan it:
await gv.detect_login_options(url="https://app.example.com/login")
# → {sso_providers: ["google", "github"], has_form: true,
# recommendation: "ask_user"}
The agent should ask the user which provider to use when multiple SSO options are detected.
Level 2: form auto-fill¶
Add login_steps to the provider:
await gv.update_provider("internal_app", login_steps=[
{"action": "fill", "target": "#username", "credential_key": "username"},
{"action": "fill", "target": "#password", "credential_key": "password"},
{"action": "click", "target": "button[type=submit]"},
])
Store credentials:
Then sign in — it auto-fills:
Level 3: record + replay¶
Record a login flow once, replay automatically next time:
# Record (user completes login manually in the browser):
await gv.record_login("acc_xyz", provider="my_bank")
# → browser opens → JS listener captures every click/fill
# → user logs in (including 2FA, captcha, whatever)
# → steps saved to provider config
# Replay (next time):
await gv.sign_in("acc_xyz")
# → replays recorded steps → pauses for credentials/captcha
Level 3 limitations
- Selectors may break if the site changes its UI (re-record needed)
- Captcha/2FA always require user interaction (replay pauses)
- Passwords are never recorded — store them via
gv_set_credentials
Provider management¶
await gv.list_providers() # all providers + capability flags
await gv.get_provider("github") # full config
await gv.update_provider("my_bank", login_url="https://new.mybank.com/login")
await gv.delete_provider("my_bank") # built-ins can't be deleted
Session health check¶
await gv.check_session("acc_xyz")
# → {health: "active", reason: "Session is active"}
# → {health: "expired", reason: "Redirected to login page"}
Storage¶
Provider recipes are stored in ~/.ghostvault/providers.json (shared across all accounts). Built-in providers (google, github, facebook, generic) are hardcoded and cannot be modified.
Credentials are stored per-account in the fingerprint bundle (encrypted when encryption-at-rest is enabled).