mirror of
https://github.com/MeshCore-Beacon/beacon-server.git
synced 2026-10-17 22:20:12 +00:00
fix: address maintainer review for #176
This commit is contained in:
@@ -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.
|
||||
@@ -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++
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user