loadHubIdentity function
Loads the hub identity persisted at path, creating it (mode 0600,
atomic temp+rename) on first use. File format — the SAME lines the
CLI's fa_hub_client key files use — so a host may share one identity
across surfaces when it wants to:
ed25519:<seed b64>, x25519:<priv b64>, x25519pub:<pub b64>.
The pub line is informational; keys are always re-derived from the
private scalars, so a torn legacy write can never pair a mismatched pub.
Implementation
Future<HubIdentity> loadHubIdentity(String path) async {
final file = File(path);
if (await file.exists()) {
try {
return await hubIdentityFromKeyFile(await file.readAsString());
} on Object {
// A torn or corrupt file falls through to regeneration: a fresh
// address beats an unusable fabric; save overwrites the file.
}
}
final identity = await HubIdentity.fromSeeds(
ed25519Seed: _randomBytes(32),
x25519Private: _randomBytes(32),
);
await File(path).parent.create(recursive: true);
// Atomic create via temp + rename: a crashed direct write could tear the
// file mid-line and break every later load.
final tmp = File('$path.tmp');
await tmp.writeAsString(await hubIdentityToKeyFile(identity), flush: true);
await tmp.rename(path);
if (!await _chmod600(path)) {
stderr.writeln(
'[hub] warning: identity file $path was NOT locked to mode 0600 — '
'the private keys may be readable by other local users',
);
}
return identity;
}