Skip to content

Compute and store message sha256 on send#18

Open
markmnl wants to merge 3 commits into
mainfrom
calchash
Open

Compute and store message sha256 on send#18
markmnl wants to merge 3 commits into
mainfrom
calchash

Conversation

@markmnl
Copy link
Copy Markdown
Owner

@markmnl markmnl commented May 16, 2026

Import github.com/markmnl/fmsgd/pkg/fmsg and use it in the Send handler to build the wire-format fmsg.Header from in-memory fields, then call GetMessageHash() to obtain the SHA-256 over the encoded header + decompressed body + attachment data. The hash is written to msg.sha256 in the same UPDATE that sets time_sent.

Also update fetchMessage to SELECT add_to_from so the Send handler has the correct AddToFrom value when building the header for add-to messages.

This fixes the production error where POST /fmsg with a pid failed because the parent message had sha256 = NULL and the DB trigger populate_msg_psha256_from_pid requires a non-null sha256 on any sent parent message.

Import github.com/markmnl/fmsgd/pkg/fmsg and use it in the Send
handler to build the wire-format fmsg.Header from in-memory fields,
then call GetMessageHash() to obtain the SHA-256 over the encoded
header + decompressed body + attachment data.  The hash is written to
msg.sha256 in the same UPDATE that sets time_sent.

Also update fetchMessage to SELECT add_to_from so the Send handler
has the correct AddToFrom value when building the header for add-to
messages.

This fixes the production error where POST /fmsg with a pid failed
because the parent message had sha256 = NULL and the DB trigger
populate_msg_psha256_from_pid requires a non-null sha256 on any sent
parent message.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the message send flow to compute and persist a deterministic SHA-256 hash for a message at send-time, using the canonical fmsg wire-format header/body/attachments encoding, and ensures add_to_from is available when constructing the header.

Changes:

  • Import github.com/markmnl/fmsgd/pkg/fmsg and compute msg.sha256 during POST /fmsg/:id/send in the same DB update that sets time_sent.
  • Load additional DB fields needed for hash computation (add_to_from, psha256, and attachment header metadata).
  • Add the github.com/markmnl/fmsgd module dependency.

Reviewed changes

Copilot reviewed 2 out of 3 changed files in this pull request and generated 2 comments.

File Description
src/handlers/messages.go Compute and store message sha256 on send; extend fetchMessage to select add_to_from.
src/go.mod Adds the github.com/markmnl/fmsgd module requirement.
src/go.sum Adds checksums for the newly required github.com/markmnl/fmsgd module.
Comments suppressed due to low confidence (2)

src/handlers/messages.go:857

  • Attachment metadata is loaded with errors silently ignored (attErr ignored, per-row Scan errors ignored, and attRows.Err() is never checked). If any scan/query issue occurs, the hash may be computed without some attachments and then written to msg.sha256, permanently diverging from the real wire-format hash. Please fail the request if attachment metadata cannot be read completely/correctly.
	attRows, attErr := h.DB.Pool.Query(ctx,
		"SELECT flags, type, filename, filesize, filepath FROM msg_attachment WHERE msg_id = $1 ORDER BY position",
		msgID,
	)
	if attErr == nil {
		for attRows.Next() {
			var a attachMeta
			if scanErr := attRows.Scan(&a.flags, &a.typ, &a.filename, &a.filesize, &a.path); scanErr == nil {
				attachments = append(attachments, a)
			}
		}
		attRows.Close()
	}

src/handlers/messages.go:843

  • attachMeta.filesize is declared as int32, but attachments are written with an int64 byte count (io.Copy result) and DB filesize is likely a 64-bit integer. If a value is out of int32 range, pgx will return a scan error (currently ignored) and the attachment will be omitted from the hash. Use int64 for scanning and validate it fits into the wire/header size type before casting.
	type attachMeta struct {
		flags    int16
		typ      string
		filename string
		filesize int32
		path     string
	}

Comment thread src/handlers/messages.go
Comment on lines +830 to +834
// Fetch psha256 (the parent message's sha256 hash used as the pid wire field).
var psha256 []byte
if existing.HasPid {
_ = h.DB.Pool.QueryRow(ctx, "SELECT psha256 FROM msg WHERE id = $1", msgID).Scan(&psha256)
}
Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot apply changes based on this feedback

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in commit 18ccd92:

  • psha256 lookup now uses err = instead of _ =, returning 5xx on any DB error
  • Added a length check: if psha256 is not exactly 32 bytes, the handler returns 5xx with a clear error message
  • Attachment query errors now return 5xx instead of silently treating it as "no attachments"
  • Per-row scan errors during attachment iteration now close the rows and return 5xx
  • Added attRows.Err() check after the iteration loop

Comment thread src/go.mod
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants