class_name KeetIdentity
extends Node
## Identity management for keet-daemon via UDS.
## Full lifecycle: setup, recovery, username, display name, lookups.
signal identity_loaded(identity: Dictionary)
signal name_changed(name: String)
signal member_found(member: Dictionary)
signal recovery_phrase_received(phrase: String)
signal setup_step_completed(step: String)
signal username_registered(username: String)
signal error_occurred(message: String)
var client: KeetUdsClient
# --- Identity info ---
func get_identity(callback: Callable = Callable()) -> void:
_require_client()
client.call_rpc("identity", {}, func(result, err):
if err != null:
error_occurred.emit("get_identity: %s" % str(err))
# Still call back with empty dict so vault check can proceed
if callback.is_valid():
callback.call({})
return
var ident: Dictionary = result if result is Dictionary else {}
identity_loaded.emit(ident)
if callback.is_valid():
callback.call(ident)
)
func get_status(callback: Callable = Callable()) -> void:
_require_client()
client.call_rpc("status", {}, func(result, err):
if err != null:
error_occurred.emit("get_status: %s" % str(err))
return
if callback.is_valid():
callback.call(result)
)
# --- Identity setup (first-run flow) ---
# Order: confirm → get recovery phrase → store phrase → set name → register username
func confirm_identity(callback: Callable = Callable()) -> void:
_require_client()
client.call_rpc("identity.confirm", {}, func(result, err):
if err != null:
error_occurred.emit("confirm: %s" % str(err))
return
setup_step_completed.emit("confirm")
if callback.is_valid():
callback.call(result)
)
func get_recovery_phrase(callback: Callable = Callable()) -> void:
_require_client()
client.call_rpc("identity.recovery", {}, func(result, err):
if err != null:
error_occurred.emit("recovery: %s" % str(err))
return
var phrase: String = ""
if result is Dictionary:
phrase = result.get("phrase", "")
recovery_phrase_received.emit(phrase)
if callback.is_valid():
callback.call(phrase)
)
func store_recovery_phrase(phrase: String, callback: Callable = Callable()) -> void:
_require_client()
client.call_rpc("identity.store", {"phrase": phrase}, func(result, err):
if err != null:
error_occurred.emit("store: %s" % str(err))
return
setup_step_completed.emit("store")
if callback.is_valid():
callback.call(result)
)
func restore_identity(phrase: String, callback: Callable = Callable()) -> void:
_require_client()
client.call_rpc("identity.restore", {"phrase": phrase}, func(result, err):
if err != null:
error_occurred.emit("restore: %s" % str(err))
return
setup_step_completed.emit("restore")
if callback.is_valid():
callback.call(result)
)
# --- Username & display name ---
func set_display_name(display_name: String, callback: Callable = Callable()) -> void:
_require_client()
client.call_rpc("identity.setName", {"name": display_name}, func(result, err):
if err != null:
error_occurred.emit("set_name: %s" % str(err))
return
name_changed.emit(display_name)
if callback.is_valid():
callback.call(result)
)
func register_username(username: String, callback: Callable = Callable()) -> void:
_require_client()
client.call_rpc("identity.register", {"username": username}, func(result, err):
if err != null:
error_occurred.emit("register: %s" % str(err))
return
username_registered.emit(username)
setup_step_completed.emit("register")
if callback.is_valid():
callback.call(result)
)
func check_username(username: String, callback: Callable = Callable()) -> void:
_require_client()
client.call_rpc("identity.checkName", {"username": username}, func(result, err):
if err != null:
error_occurred.emit("check_username: %s" % str(err))
return
if callback.is_valid():
callback.call(result)
)
# --- Vault (encrypted mnemonic) ---
func vault_status(callback: Callable = Callable()) -> void:
_require_client()
client.call_rpc("vault.status", {}, func(result, err):
if err != null:
error_occurred.emit("vault_status: %s" % str(err))
if callback.is_valid():
callback.call({})
return
if callback.is_valid():
callback.call(result if result is Dictionary else {})
)
func vault_setup(password: String, callback: Callable = Callable()) -> void:
_require_client()
client.call_rpc("vault.setup", {"password": password}, func(result, err):
if err != null:
error_occurred.emit("vault_setup: %s" % str(err))
if callback.is_valid():
callback.call({"ok": false, "error": str(err)})
return
setup_step_completed.emit("vault_setup")
if callback.is_valid():
callback.call(result if result is Dictionary else {"ok": true})
)
func vault_unlock(password: String, callback: Callable = Callable()) -> void:
_require_client()
client.call_rpc("vault.unlock", {"password": password}, func(result, err):
if err != null:
error_occurred.emit("vault_unlock: %s" % str(err))
if callback.is_valid():
callback.call({"ok": false, "error": str(err)})
return
setup_step_completed.emit("vault_unlock")
if callback.is_valid():
callback.call(result if result is Dictionary else {"ok": true})
)
func vault_import(phrase: String, password: String, callback: Callable = Callable()) -> void:
_require_client()
client.call_rpc("vault.import", {"phrase": phrase, "password": password}, func(result, err):
if err != null:
error_occurred.emit("vault_import: %s" % str(err))
if callback.is_valid():
callback.call({"ok": false, "error": str(err)})
return
setup_step_completed.emit("vault_import")
if callback.is_valid():
callback.call(result if result is Dictionary else {"ok": true})
)
func vault_export(password: String, callback: Callable = Callable()) -> void:
_require_client()
client.call_rpc("vault.export", {"password": password}, func(result, err):
if err != null:
error_occurred.emit("vault_export: %s" % str(err))
if callback.is_valid():
callback.call({"ok": false, "error": str(err)})
return
if callback.is_valid():
callback.call(result if result is Dictionary else {})
)
# --- Lookups ---
func lookup_user(username: String, callback: Callable = Callable()) -> void:
_require_client()
client.call_rpc("identity.lookup", {"username": username}, func(result, err):
if err != null:
error_occurred.emit("lookup_user: %s" % str(err))
return
var member: Dictionary = result if result is Dictionary else {}
member_found.emit(member)
if callback.is_valid():
callback.call(member)
)
func lookup_member(room_id: String, member_id: String, callback: Callable = Callable()) -> void:
_require_client()
client.call_rpc("identity.lookupMember", {"roomId": room_id, "memberId": member_id}, func(result, err):
if err != null:
error_occurred.emit("lookup_member: %s" % str(err))
return
var member: Dictionary = result if result is Dictionary else {}
member_found.emit(member)
if callback.is_valid():
callback.call(member)
)
func _require_client() -> void:
if client == null:
push_error("KeetIdentity: client not set")