Skip to content

Add chat_join() and invites on chat_poll() - #8

Merged
TroyHernandez merged 1 commit into
mainfrom
feat/invites
Aug 7, 2026
Merged

TroyHernandez merged 1 commit into
mainfrom
feat/invites

Conversation

@TroyHernandez

Copy link
Copy Markdown
Contributor

Phase 1d — the change that lets corteza stop reading chat_poll()$raw.

The inviter is the point

chat_poll()$invites returns chat_invite() records carrying the channel and who issued the invitation.

That second field is why this PR needed cornball-ai/mx.client#21 first. corteza gates invites on an operator list and refuses everything else; a record with only a room id would have left it walking $raw to find the sender, and 1d would have achieved nothing.

inviter is NA when the transport does not say, never NULL. A consumer deciding whether to accept has to tell "someone I do not trust" from "I could not tell who" — both refuse, for different reasons, and only one is worth logging as a rejection. NULL would collapse the second into the absence of a field.

No timestamp

The one place this record differs from chat_message() and chat_reaction(). An invitation is a standing state rather than an event at a moment, and Matrix's stripped invite state carries no reliable origin_server_ts. A field that could only ever be NA is worse than no field, so there isn't one — asserted, so it does not quietly acquire one later.

chat_join()

Matrix goes through mx.api::mx_room_join(), Slack through conversations.join. Errors propagate, same reasoning as chat_react(): a join that silently did nothing leaves the caller believing it is in a room it will never hear a word from, which looks exactly like an idle room.

The capability split earns itself again

adapter invites join
Matrix tracks installed mx.client TRUE
Slack FALSE TRUE
IRC, loopback FALSE FALSE

Slack is FALSE/TRUE: a bot is added to a private channel by a member, which arrives as no event this adapter can see, but it can join an open channel itself. A single flag would have a consumer either wait for invitations that never arrive or refuse to join a channel it could.

Testing

660 assertions, 298 on a bare runner with no mx.* installed. Four mutations, all caught: dropping $invites entirely, dropping the inviter from the record, letting a NULL inviter through as NULL, and Slack claiming it receives invitations.

R CMD check --as-cran clean but for the expected new-submission NOTE. mx.client floor raised to 0.2.0.4.

Downstream

corteza drops matrix_invite_inviters() and its last $raw read, at which point grep -c 'res\$raw' R/matrix.R reaches zero — the migration plan's stated finish line for phase 2.

Phase 1d. This is the change that lets corteza stop reading
chat_poll()$raw.

chat_poll() gains $invites: chat_invite() records carrying the channel
and, critically, who issued the invitation. corteza gates invites on an
operator list and refuses anything else, so a record with only a room id
would have left it walking $raw for the sender -- and 1d would have
achieved nothing.

inviter is NA when the transport does not say, never NULL. A consumer
deciding whether to accept has to tell "someone I do not trust" from "I
could not tell who": both refuse, for different reasons, and only one is
worth logging as a rejection. NULL would collapse the second into the
absence of a field.

There is no ts, which is the one place this record differs from
chat_message() and chat_reaction(). An invitation is a standing state
rather than an event at a moment, and Matrix's stripped invite state
carries no reliable origin_server_ts. A field that could only ever be NA
is worse than no field.

chat_join() accepts one. Matrix goes through mx.api::mx_room_join();
Slack through conversations.join. Errors propagate, on the same
reasoning as chat_react(): a join that silently did nothing would leave
the caller believing it is in a room it will never hear a word from,
which is indistinguishable from an idle room.

Capabilities split into invites (they come out of chat_poll) and join
(chat_join works), and Slack is FALSE/TRUE -- a Slack bot is added to a
private channel by a member, which arrives as no event this adapter can
see, but it can join an open channel itself. A single flag would have a
consumer either wait for invitations that never arrive or refuse to join
a channel it could.

660 assertions, 298 on a bare runner. Four mutations, all caught:
dropping $invites, dropping the inviter from the record, letting a NULL
inviter through as NULL, and Slack claiming it receives invitations.
@TroyHernandez
TroyHernandez merged commit 9b42944 into main Aug 7, 2026
5 of 8 checks passed
@TroyHernandez
TroyHernandez deleted the feat/invites branch August 7, 2026 15:27
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.

1 participant