Repository navigation
Fix driver uuid broadcast channel; comment visibility and comment.created; chat participant roles and system message meta - #306
Merged
roncodes merged 3 commits intoOct 13, 2026
Conversation
…annels
addRelationshipSpecificChannels checked isset($model->driver_assigned_uuid) but then built the
channel from $model->driverAssigned_uuid, an attribute that never exists, so every order lifecycle
event broadcast on a dead 'driverAssigned.' channel instead of 'driverAssigned.{driver uuid}'.
Read the same snake case key it checks.
…st comment.created
Comments carry meta.visibility = internal | customer (a 'visibility' shorthand is accepted on
create). When none is given: replies follow their parent, comments on orders are internal when
written through an internal (console) route and customer from anywhere else, and comments on other
subjects keep no visibility, which stays visible, so existing data and callers are unaffected.
- Comment::scopeVisibleToCustomers() (everything but internal) and scopeInternal(),
getVisibility(), isInternal(), isVisibleToCustomers()
- the public v1 comments API excludes internal comments from the listing (CommentFilter
queryForPublic) and find, accepts an optional visibility on create, and the Comment resource
hides internal replies outside internal requests and exposes a top level 'visibility'
- new CommentCreated event broadcasts 'comment.created' with the comment resource on
company.{company_uuid} for every comment and, for customer visible comments only, on the
subject's channels ({subject type}.{public_id} and {subject type}.{uuid}, e.g. order.order_x);
a broadcast failure is logged and never fails the comment
Adds a nullable json meta column to chat_participants and chat_messages (guarded migration). - ChatParticipant: meta (fillable, json cast), ROLE_* constants (customer, driver, store, system) and getRole() reading meta.role; the resource adds 'role' and 'meta', so a message's sender.role reaches the apps over HTTP and the chat_message broadcasts - ChatMessage: meta (fillable, json cast), isSystem() (meta.system) and getSystemKind() (meta.kind); the resource adds 'system' and 'meta' and renders a missing sender as null instead of failing (the duplicate public 'sender' key it dropped was always overwritten by the participant resource) The public send-message endpoint still builds its own attributes, so customers cannot post system messages or set roles; existing chat behaviour is unchanged.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What and why
Core pieces for the order operations work (order notes visibility, order chat with the store), plus a broadcast channel bug fix.
1. Fix: relationship uuid channels (
ResourceLifecycleEvent)addRelationshipSpecificChannelscheckedisset($model->driver_assigned_uuid)but built the channel from$model->driverAssigned_uuid, which never exists, so order lifecycle events went out on a deaddriverAssigned.channel instead ofdriverAssigned.{driver uuid}. It now reads the same snake case key it checks. Channel prefixes are unchanged (driverAssigned.,customer.,facilitator.,vendor.). The existing test hid the bug by setting both attributes; it now sets only the real column, and a regression test covers the case where only foreign keys are set.2. Comment visibility (
meta.visibility=internal|customer)Comment::$visibilityAwareSubjectTypes = ['order']) isinternalwhen written through an internal route (int/...,storefront/int/...) andcustomerfrom anywhere else. Comments on any other subject keep no visibility, and no visibility counts as visible, so existing comments and callers behave as before. Unknown values are dropped and the default applies.visibilityis accepted on create as a shorthand formeta.visibility(inComment::publish, so it works for both the console and the public API).Comment: the scopesscopeVisibleToCustomers()(everything butinternal, including null meta and meta without a visibility) andscopeInternal(), plusgetVisibility(),isInternal()andisVisibleToCustomers().CommentFilter::queryForPublic) andGET v1/comments/{id}exclude internal comments; an internal comment'sfindreturns 404.POST v1/commentsaccepts an optionalvisibility(nullable|in:internal,customer).visibilityfield (internalorcustomer). Outside internal requests, internal replies are left out ofreplies.3. Chat participant roles and system messages
2026_10_13_000000_add_meta_to_chat_participants_and_chat_messages_tablesadds a nullable jsonmetacolumn tochat_participantsandchat_messages. Each step checks whether the column exists first, anddown()drops it.ChatParticipant:metais fillable with a json cast. Adds theROLE_CUSTOMER|ROLE_DRIVER|ROLE_STORE|ROLE_SYSTEMconstants,ROLES, andgetRole(), which readsmeta.roleand returns null for unknown values. The resource addsroleandmeta, sosender.rolereaches apps over HTTP and in thechat_message.*broadcasts.ChatMessage:metais fillable with a json cast. AddsisSystem()(meta.system) andgetSystemKind()(meta.kind, e.g.order_updated,address_change_requested). The resource addssystem(bool) andmeta. A missing sender now renders asnullinstead of throwing. The resource also had a duplicate publicsenderkey that the participant resource always overwrote; it is removed, so the output is unchanged.send-messageendpoint still builds its own attributes, so customers cannot post system messages. Existing chat behaviour is otherwise unchanged.4.
comment.createdbroadcastA new
Fleetbase\Events\CommentCreated(ShouldBroadcastNow) is dispatched fromComment::created. Its payload is{ id, event: "comment.created", created_at, subject_id, data: <Comment resource> }.company.{company_uuid}.internal) are also broadcast on the subject's channels,{subject type}.{subject public_id}and{subject type}.{subject uuid}(e.g.order.order_x). Internal notes never go to subject channels.Migrations
migrations/2026_10_13_000000_add_meta_to_chat_participants_and_chat_messages_tables.php(nullable jsonmetaonchat_participantsandchat_messages, guarded)Validation
vendor/bin/pest(full suite, PHP 8.4): 2113 passed, 1 failed. The same single failure happens on the base branch (UtilsTest > utils reads composer package keyword metadata from the lock file, because there is nocomposer.lockin a worktree). Base had 2104 passed, so there are no regressions, and the 9 new tests pass.EventsAndExceptionsTest > unauthorized request exception...test fails only whenCommentControllerTestruns before it in a partial run, because of agetControllermacro. This also happens on the base branch, and the test passes in the full suite.php-cs-fixer fix --dry-run: 0 files to fix.scripts/check-test-date-drift.php: passed.phpstanon the touched files: only the same categories the codebase already reports at level max (undefined Eloquent magic properties,mixedresource calls). There are no new kinds of error.New tests:
tests/Unit/EventsAndExceptionsTest.php: uuid channel regression, and chat resourcerole/meta/system/ senderless messagetests/Unit/Http/CommentControllerTest.php: visibility defaults (console, storefront int, public, explicit, meta, invalid), replies inheriting from their parent, scopes, public listing/find/replies hiding internal comments,visibilityon public create,comment.createdchannels and payload, dispatch, and broadcast failure tolerancetests/Unit/Models/ChatModelsTest.php: migration up/down/idempotent, role and system meta round tripDocs / API impact
GET v1/commentsandGET v1/comments/{id}no longer return comments withmeta.visibility = internal.POST v1/commentsacceptsvisibility(internal|customer). Comment responses gainvisibility. Chat participant responses gainroleandmeta, and chat message responses gainsystemandmeta. These need updating infleetbase/postman(Comments and Chat collections). (needs-api-spec)comment.createdevent and its channels, plus the fixeddriverAssigned.{uuid}channel, should be documented infleetbase/fleetbase.iounder the realtime/socket events docs. (needs-docs)Part of the order operations program (notes visibility, order chat with the store).