fix: address maintainer review for #176

This commit is contained in:
n30nex
2026-09-30 07:19:03 -04:00
committed by MrAlders0n
parent 8f6032877b
commit 6bf58acb80
5 changed files with 8 additions and 27 deletions
-16
View File
@@ -1,16 +0,0 @@
# Channel-message transport scope
Channel history, the global/hash message APIs, reconnect backfill and `channelMessage` events now include `scope` and `scopeStatus`. Live events also include their stored message `id`; existing fields, endpoints and cursors are unchanged.
| Status | Meaning |
|---|---|
| `matched` | `scope` names the scope recorded on the first stored packet. |
| `unscoped` | The first stored packet has no transport codes; `scope` is null. |
| `unknown` | Transport codes were recorded but no scope name was resolved, including ambiguous matches. |
| `unavailable` | Scope/capture metadata is missing. |
These labels belong to the first stored packet, not every later reception of the same payload. Later paths may differ. Live delivery reads that same evidence while inserting the channel message, so a later reception cannot relabel it differently from history. Existing scope query filters retain their meaning. Imported catalogue membership and channel names are never used as message evidence.
The insertion query returns metadata only for a new message. Duplicate deliveries still produce no extra live message. Adding a decryption key later uses the existing backfill path, retains the stored packet evidence and does not broadcast old messages as new traffic. This change adds no keys, migration or historical scan. Expired packet/message detail remains unavailable.
Deploy this API before its web consumer. Older clients may ignore the added fields; clients reading older servers must treat absent metadata as unavailable, not assume a message is unscoped. Scope filtering of live events requires the new fields. The channel encryption key and the packet transport scope are separate concepts.
+3 -6
View File
@@ -29,10 +29,8 @@ type DecryptGroupTextResult struct {
ChannelID int
ChannelHash []byte
Entry keystore.Entry
// NewMessage is false if InsertChannelMessage found the message already existed
// (packet_hash is unique per message) -- e.g. re-running the backfill twice.
NewMessage bool
Message *InsertedChannelMessage
// Message is nil when the packet already has a stored channel message.
Message *InsertedChannelMessage
}
// DecryptGroupText attempts to decrypt a GRP_TXT payload against keys and, on success,
@@ -90,7 +88,6 @@ func DecryptGroupText(ctx context.Context, db DB, keys ChannelKeyStore, packetHa
ChannelID: channelID,
ChannelHash: channelHashBytes,
Entry: usedEntry,
NewMessage: newMsg != nil,
Message: newMsg,
}, nil
}
@@ -117,7 +114,7 @@ func BackfillChannelMessages(ctx context.Context, db DB, keys ChannelKeyStore) (
slog.Error(fmt.Sprintf("ingest: backfill: decrypt failed for packet %s", hex.EncodeToString(p.PacketHash)), "component", "ingest", "error", err)
continue
}
if result != nil && result.NewMessage {
if result != nil && result.Message != nil {
decrypted++
}
}
+2 -2
View File
@@ -49,8 +49,8 @@ func TestDecryptGroupText_Success(t *testing.T) {
if result.Payload.Sender != "ded" || result.Payload.Text != "hello" {
t.Errorf("expected decrypted sender=ded text=hello, got sender=%s text=%s", result.Payload.Sender, result.Payload.Text)
}
if !result.NewMessage {
t.Error("expected NewMessage true when InsertChannelMessage reports a new insert")
if result.Message == nil {
t.Error("expected a message when InsertChannelMessage reports a new insert")
}
if db.upsertChannelCalls != 1 {
t.Errorf("expected UpsertChannel to be called once, got %d", db.upsertChannelCalls)
+1 -1
View File
@@ -131,7 +131,7 @@ type DB interface {
// UpsertNodeShortID upserts a node_short_ids row for path resolution.
UpsertNodeShortID(ctx context.Context, nodeID uuid.UUID, iata string, prefix4 []byte) error
// InsertChannelMessage stores a decrypted group text message. Returns insert success and an error.
// InsertChannelMessage stores a decrypted group text message. Returns the inserted message, nil for a duplicate, and an error.
InsertChannelMessage(ctx context.Context, m InsertChannelMessageParams) (*InsertedChannelMessage, error)
// UpdateObserverStatus updates the observer row from a /status message. Returns the OberserID
+2 -2
View File
@@ -54,7 +54,7 @@ type channelMessageEvent struct {
Content string `json:"content"`
SentAt int64 `json:"sentAt"` // epoch ms
Scope *string `json:"scope"`
ScopeStatus api.ChannelScopeStatus `json:"scopeStatus"`
ScopeStatus api.ChannelScopeStatus `json:"scopeStatus" enums:"matched,unscoped,unknown,unavailable"`
}
// nodeUpdateEvent is the JSON payload for a nodeUpdate WS event.
@@ -215,7 +215,7 @@ func (w *Worker) handlePayloadTypeSideEffects(ctx context.Context, packet *meshc
return
}
if result.NewMessage {
if result.Message != nil {
evt := channelMessageEvent{
ID: result.Message.ID,
Scope: result.Message.Scope,