Draft 0.5: identity/registry spec; Phase A signed MA registry, mailbox challenge auth, key rotation, skew rejection

This commit is contained in:
George Coles
2026-09-15 05:45:02 -04:00
parent fb45cfa8cf
commit 559c260639
18 changed files with 1526 additions and 105 deletions
+105 -2
View File
@@ -33,6 +33,12 @@ enum Command {
data_dir: String,
#[arg(long)]
force: bool,
#[arg(long)]
id: Option<String>,
#[arg(long)]
registry: Option<String>,
#[arg(long)]
ma_key: Option<String>,
},
Add {
path: PathBuf,
@@ -70,6 +76,16 @@ enum Command {
#[command(subcommand)]
command: MemberCommand,
},
Key {
#[command(subcommand)]
command: KeyCommand,
},
Registry {
#[arg(long, default_value = "./frx-registry")]
dir: PathBuf,
#[command(subcommand)]
command: RegistryCommand,
},
Aggregates {
#[arg(long)]
from: Option<String>,
@@ -87,6 +103,8 @@ enum MemberCommand {
pubkey: String,
#[arg(long, default_value = "source")]
class: String,
#[arg(long = "previous")]
previous: Vec<String>,
},
Remove {
name: String,
@@ -94,6 +112,48 @@ enum MemberCommand {
List,
}
#[derive(Subcommand)]
enum KeyCommand {
Show,
Rotate,
}
#[derive(Subcommand)]
enum RegistryCommand {
Init,
Add {
id: String,
pubkey: String,
#[arg(long, default_value = "source")]
class: String,
#[arg(long)]
not_before: Option<u64>,
#[arg(long)]
not_after: Option<u64>,
},
AddKey {
id: String,
pubkey: String,
#[arg(long)]
not_before: Option<u64>,
#[arg(long)]
not_after: Option<u64>,
},
RevokeKey {
id: String,
pubkey: String,
},
Remove {
id: String,
},
List,
Show,
Serve {
#[arg(long, default_value = "127.0.0.1:7800")]
listen: String,
},
}
#[derive(Clone, Copy, ValueEnum)]
enum Exposure {
Metadata,
@@ -110,6 +170,9 @@ async fn main() -> Result<()> {
relay,
data_dir,
force,
id,
registry,
ma_key,
} => {
if cli.config.exists() && !force {
bail!(
@@ -117,7 +180,19 @@ async fn main() -> Result<()> {
cli.config.display()
);
}
let config = Config::new(&name, &listen, &relay, &data_dir);
if registry.is_some() && ma_key.is_none() {
bail!("--ma-key is required with --registry");
}
let mut config = Config::new(&name, &listen, &relay, &data_dir);
config.node.id = id;
config.node.registry = registry;
config.node.ma_key = ma_key;
if config.node.registry.is_none() {
config.node.dev_bootstrap = true;
println!(
"warning: no registry configured; development open bootstrap (any valid key is accepted; do not deploy)"
);
}
let key = Keypair::generate();
config.save_key(&key)?;
config.save(&cli.config)?;
@@ -167,10 +242,38 @@ async fn main() -> Result<()> {
name,
pubkey,
class,
} => commands::member_add(&cli.config, &name, &pubkey, &class)?,
previous,
} => commands::member_add(&cli.config, &name, &pubkey, &class, &previous)?,
MemberCommand::Remove { name } => commands::member_remove(&cli.config, &name)?,
MemberCommand::List => commands::member_list(&cli.config)?,
},
Command::Key { command } => match command {
KeyCommand::Show => commands::key_show(&cli.config)?,
KeyCommand::Rotate => commands::key_rotate(&cli.config)?,
},
Command::Registry { dir, command } => match command {
RegistryCommand::Init => commands::registry_init(&dir)?,
RegistryCommand::Add {
id,
pubkey,
class,
not_before,
not_after,
} => commands::registry_add(&dir, &id, &pubkey, &class, not_before, not_after)?,
RegistryCommand::AddKey {
id,
pubkey,
not_before,
not_after,
} => commands::registry_add_key(&dir, &id, &pubkey, not_before, not_after)?,
RegistryCommand::RevokeKey { id, pubkey } => {
commands::registry_revoke_key(&dir, &id, &pubkey)?
}
RegistryCommand::Remove { id } => commands::registry_remove(&dir, &id)?,
RegistryCommand::List => commands::registry_list(&dir)?,
RegistryCommand::Show => commands::registry_show(&dir)?,
RegistryCommand::Serve { listen } => commands::registry_serve(&dir, &listen).await?,
},
Command::Aggregates {
from,
period,