feat(fof-layer2): wire FoF gating into post-create path
Threads optional fof_gating through create_post_inner so a published
post can carry the author-signed gating snapshot at publish time
(covered by PostId = BLAKE3(Post)).
New public entry point:
Node::create_post_with_fof_comments(content, attachments)
-> (PostId, Post, PostVisibility, cek: [u8; 32])
Builds the FoFCommentGating block via fof::build_fof_comment_gating
from the default persona's keyring (own V_me + every received V_x),
then calls create_post_inner with VisibilityIntent::Public (Mode 2
keeps body public). Returns the per-post CEK to the caller for local
caching (decrypting one's own comments later).
Existing create_post / create_post_as / create_post_with_visibility
threads `None` through the new arg — back-compat for non-FoF posts.
CommentPolicy::FriendsOfFriends is NOT published as a SetPolicy diff
in this commit; the post's `fof_gating` field is itself the signal
that the post supports FoF commenting. The four-check CDN verify gate
(next commit) reads fof_gating directly.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
bdcd2142cd
commit
673f9e2261
1 changed files with 37 additions and 1 deletions
|
|
@ -1014,6 +1014,7 @@ impl Node {
|
|||
content,
|
||||
intent,
|
||||
attachment_data,
|
||||
None,
|
||||
).await
|
||||
}
|
||||
|
||||
|
|
@ -1038,9 +1039,43 @@ impl Node {
|
|||
content,
|
||||
intent,
|
||||
attachment_data,
|
||||
None,
|
||||
).await
|
||||
}
|
||||
|
||||
/// FoF Layer 2: create a Mode 2 post (public body, FoF-gated
|
||||
/// comments). Intent is Public; the FoF gating block is built
|
||||
/// from the default persona's keyring and embedded in
|
||||
/// `Post.fof_gating`. The author retains the per-post CEK locally
|
||||
/// for decrypting their own comments later.
|
||||
///
|
||||
/// Returns `(post_id, post, visibility, cek)`. `visibility` is
|
||||
/// always Public for Mode 2.
|
||||
pub async fn create_post_with_fof_comments(
|
||||
&self,
|
||||
content: String,
|
||||
attachment_data: Vec<(Vec<u8>, String)>,
|
||||
) -> anyhow::Result<(PostId, Post, PostVisibility, [u8; 32])> {
|
||||
// Build the gating block from the default persona's keyring.
|
||||
let built = {
|
||||
let storage = self.storage.get().await;
|
||||
crate::fof::build_fof_comment_gating(&*storage, &self.default_posting_id)?
|
||||
.ok_or_else(|| anyhow::anyhow!(
|
||||
"default persona has no V_me; rotate or recreate before FoF posts"
|
||||
))?
|
||||
};
|
||||
let cek = built.cek;
|
||||
let (post_id, post, visibility) = self.create_post_inner(
|
||||
&self.default_posting_id,
|
||||
&self.default_posting_secret,
|
||||
content,
|
||||
VisibilityIntent::Public,
|
||||
attachment_data,
|
||||
Some(built.gating),
|
||||
).await?;
|
||||
Ok((post_id, post, visibility, cek))
|
||||
}
|
||||
|
||||
async fn create_post_inner(
|
||||
&self,
|
||||
posting_id: &NodeId,
|
||||
|
|
@ -1048,6 +1083,7 @@ impl Node {
|
|||
content: String,
|
||||
intent: VisibilityIntent,
|
||||
attachment_data: Vec<(Vec<u8>, String)>,
|
||||
fof_gating: Option<crate::types::FoFCommentGating>,
|
||||
) -> anyhow::Result<(PostId, Post, PostVisibility)> {
|
||||
// Validate attachments
|
||||
if attachment_data.len() > 4 {
|
||||
|
|
@ -1163,7 +1199,7 @@ impl Node {
|
|||
content: final_content,
|
||||
attachments,
|
||||
timestamp_ms: now,
|
||||
fof_gating: None,
|
||||
fof_gating,
|
||||
};
|
||||
|
||||
let post_id = compute_post_id(&post);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue