Phase 5 (0.6.4-beta) backend: multi-persona creation + post-as
Users can now hold multiple posting identities on one device and publish content under any of them. Each persona has its own ed25519 key; peers see them as distinct authors with no link back to the device's network identity. Node methods: - list_posting_identities() -> Vec<PostingIdentity> - create_posting_identity(display_name) — generates a fresh ed25519 key, persists, auto-follows self - delete_posting_identity(node_id) — refuses to delete the default - set_default_posting_identity(node_id) — validates identity exists; Node's cached default_posting_id/secret picks up on next restart - create_post_as(posting_id, content, intent, attachments) — routes through a shared create_post_inner that takes posting_id + posting_secret as parameters Post creation pipeline: - create_post_with_visibility now delegates to create_post_inner using default_posting_id/secret - create_post_inner threads posting_id / posting_secret through every content-signing, encryption, manifest, blob-header, and CDN-manifest step — the persona is fully honored end to end - update_neighbor_manifests now takes a posting_id param too, so posts from persona X only update neighbor manifests for X's own prior posts Tauri IPC: - list_posting_identities / create_posting_identity / delete_posting_identity / set_default_posting_identity - create_post_as with posting_id_hex + the same visibility params as create_post CLI: - personas / create-persona <name> / delete-persona <id> - post-as <posting_id> <text> Smoke-tested two-persona scenario: - A creates "Work" persona; posts from default and Work - B follows both; pulls from A; gets all three posts - Authors are AB84BA... (Work) and 7CD949... (default) — distinct on the wire Frontend UX (Settings > Personas, compose picker, filter pills, merged feed labels) is scoped as a separate commit. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
ce4b989b17
commit
7bdb2eb736
3 changed files with 296 additions and 15 deletions
|
|
@ -618,6 +618,73 @@ async fn main() -> anyhow::Result<()> {
|
|||
Err(e) => println!("Error: {}", e),
|
||||
},
|
||||
|
||||
"personas" => match node.list_posting_identities().await {
|
||||
Ok(identities) => {
|
||||
let default = {
|
||||
let s = node.storage.get().await;
|
||||
s.get_default_posting_id().ok().flatten()
|
||||
};
|
||||
if identities.is_empty() {
|
||||
println!("(no posting identities)");
|
||||
}
|
||||
for id in identities {
|
||||
let mark = if Some(id.node_id) == default { " *" } else { "" };
|
||||
let name = if id.display_name.is_empty() { "(unnamed)" } else { &id.display_name };
|
||||
println!(" {} {} {}{}", &hex::encode(id.node_id)[..12], name, id.created_at, mark);
|
||||
}
|
||||
}
|
||||
Err(e) => println!("Error: {}", e),
|
||||
},
|
||||
|
||||
"create-persona" => {
|
||||
let name = arg.unwrap_or("").to_string();
|
||||
match node.create_posting_identity(name).await {
|
||||
Ok(id) => {
|
||||
println!("Created posting identity: {}", hex::encode(id.node_id));
|
||||
}
|
||||
Err(e) => println!("Error: {}", e),
|
||||
}
|
||||
}
|
||||
|
||||
"delete-persona" => {
|
||||
if let Some(id_hex) = arg {
|
||||
match itsgoin_core::parse_node_id_hex(id_hex) {
|
||||
Ok(nid) => match node.delete_posting_identity(&nid).await {
|
||||
Ok(()) => println!("Deleted posting identity"),
|
||||
Err(e) => println!("Error: {}", e),
|
||||
},
|
||||
Err(e) => println!("Invalid node id: {}", e),
|
||||
}
|
||||
} else {
|
||||
println!("Usage: delete-persona <node_id>");
|
||||
}
|
||||
}
|
||||
|
||||
"post-as" => {
|
||||
if let Some(rest) = arg {
|
||||
let parts: Vec<&str> = rest.splitn(2, ' ').collect();
|
||||
if parts.len() < 2 {
|
||||
println!("Usage: post-as <posting_id_hex> <text>");
|
||||
} else {
|
||||
match itsgoin_core::parse_node_id_hex(parts[0]) {
|
||||
Ok(nid) => {
|
||||
match node
|
||||
.create_post_as(&nid, parts[1].to_string(),
|
||||
itsgoin_core::types::VisibilityIntent::Public, vec![])
|
||||
.await
|
||||
{
|
||||
Ok((id, _, _)) => println!("Posted as persona! ID: {}", hex::encode(id)),
|
||||
Err(e) => println!("Error: {}", e),
|
||||
}
|
||||
}
|
||||
Err(e) => println!("Invalid node id: {}", e),
|
||||
}
|
||||
}
|
||||
} else {
|
||||
println!("Usage: post-as <posting_id_hex> <text>");
|
||||
}
|
||||
}
|
||||
|
||||
"export-key" => {
|
||||
match node.export_identity_hex() {
|
||||
Ok(hex_key) => {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue