The server module named github.com/hanzoai/team/server/v8 — a path that
resolves to the retired workspace's repository, not this one — while
server/public still published github.com/mattermost/mattermost/server/public.
Both are github.com/hanzoteam/server/... now, which is where this code
actually lives.
That second half is what made the binary unbootable. Upstream's public path
stayed claimed by upstream, mattermost-plugin-ai imported it, and the build
linked public/model twice; public/plugin's gob.Register then ran twice under
one name and panicked at init, before main. Reverting the rename traded the
brand for a working binary. Rebranding the plugin alongside it needs no such
trade: the agents fork is github.com/hanzoteam/agents/v2 against our public
module, so no module named mattermost/mattermost is in the graph at all.
Measured: `go list -deps ./cmd/mattermost` names exactly one public/model, and
it is ours.
Renaming server/public to github.com/hanzoai/team/server/public left the old
path unclaimed, and mattermost-plugin-ai still imports it — so the binary
linked public/model TWICE, ours and upstream's, and public/plugin's
gob.Register calls ran twice under one name:
panic: gob: registering duplicate types for "[]*model.SlackAttachment":
[]*model.MessageAttachment != []*model.SlackAttachment
at init, before main. The server has not been able to start since that rename
landed, which is why the deployment is still answering from an older build.
server/v8 keeps its new name; nothing outside this repo imports it. public
does not, because its path is not a brand — it is the plugin API, and every
plugin written against Mattermost imports it by that name. Our own agents
fork is proof: it carries a replace pointing that exact path back here.
Reverting the public half is what makes the two copies one again. Measured
after: `go list -deps ./cmd/mattermost` names exactly one public/model, the
binary starts, and it serves.
Every package in this fork announced itself as github.com/mattermost/mattermost —
in 4,553 import lines, in both go.mod module declarations, and in the workspace.
A fork whose own import path names another company is one nobody can read as
theirs, and it is the first thing anyone sees at the top of every file.
server/v8 and server/public are now github.com/hanzoai/team/server/…, rewritten
mechanically and verified: `go build ./...` is clean for both modules and `go vet`
passes.
Three things are deliberately UNTOUCHED, because they are other people's names
rather than our branding: mattermost-plugin-ai and mattermost-plugin-mscalendar
are real dependencies we consume, github.com/mattermost/msgpack is a real
dependency, and the github.com/mattermost/mattermost/pull/… links in comments
point at real upstream discussions that renaming would turn into dead links.
server/public needs a `replace` to resolve locally now: the require still names a
version, and no proxy serves our path. The workspace alone does not satisfy a
require, which is exactly how this failed the first time.
Co-authored-by: Hanzo Dev <[email protected]>
* allow workflow_dispatch trigger for Server CI (for plugins CI)
* [MM-68402] MBE Phase 2: declare four generic plugin hooks (#36291)
* new hooks-only phase 2
* remove ChannelWillBeMoved
* remove RecapWillBeProcessed and MessageWillBeRewrittenByAI
Drop the AI/recap hooks from the new-hook surface; AI-LLM paths
remain uncovered in tech preview and are documented as residuals.
* [MM-68403] MBE Phase 3: ChannelGuards primitive (storage + cache + plugin API) (#36365)
* phase 3
* phase 3: register ChannelGuard mock in test setup helper
NewChannels' startup-time call to reloadGuardCache invokes
s.ChannelGuard().GetAll(); without an expectation on the mock store,
every test that sets up the server with GetMockStoreForSetupFunctions
panics during init.
* phase 3: register ChannelGuard mock in retrylayer test
retrylayer.New walks every store getter to wrap it; without the mock
expectation on ChannelGuard, TestRetry panics during layer construction.
* use rctx properly in the store methods
* phase 3: match rctx arg in testlib ChannelGuard mock
GetAll now takes request.CTX, so the testify expectation must include
mock.Anything; otherwise the call panics under the mocked store.
* phase 3: set api.ctx in TestChannelGuardLowercaseNormalization
The test constructs PluginAPI directly without a ctx, which used to
work when App.RegisterChannelGuard built its own EmptyContext. Now
that the App methods take rctx from the caller, the nil ctx panics
inside RequestContextWithMaster.
* [MM-68404] MBE Phase 4: App-layer plugin hook wiring (#36407)
* phase 4
* Fix nil rctx in TestChannelGuardLowercaseNormalization
The PluginAPI struct literal was missing ctx: rctx after a refactor
moved the rctx declaration below the struct construction, leaving
api.ctx as nil. This caused a nil pointer dereference in reloadGuardCache
when RegisterChannelGuard called store.RequestContextWithMaster(nil).
* Remove ChannelWillBeMoved hook call from MoveChannel (phase 4)
The hook and its ID were removed from mbe-phase-2 but the call site in
MoveChannel and its i18n string were not cleaned up during the rebase.
* remove channel will be moved test
* Remove RecapWillBeProcessed and MessageWillBeRewrittenByAI hook calls (phase 4)
The hooks and their IDs were removed from mbe-phase-2 but the call sites
in ProcessRecapChannel and RewriteMessage, their i18n strings, and their
tests were not cleaned up during the rebase.
* Revert channel_id plumbing on rewrite endpoint (phase 4)
The channel_id field on RewriteRequest was added in phase 4 to feed the
synthetic post passed to MessageWillBeRewrittenByAI. With that hook
removed from mbe-phase-2, channel_id has no consumer; revert the field,
the api4 validation, the app.RewriteMessage parameter, and the
corresponding webapp client + hook plumbing.
* [MM-68555] MBE Phase 5: Channel-guard enforcement + two-phase dispatch (#36473)
* phase 5
* Bake plugin counter-file paths into source instead of env vars
t.Setenv panics when an ancestor test calls t.Parallel, so the two
channel-guard tests broke under ENABLE_FULLY_PARALLEL_TESTS in CI.
Build each plugin source per-subtest with its temp file path embedded
as a Go literal — same pattern as TestPluginUploadsAPI.
* Remove guarded helpers and tests for dropped hooks (phase 5)
The runGuardedRecapWillBeProcessed and runGuardedMessageWillBeRewrittenByAI
helpers were never wired (their app-layer call sites were already removed
in the phase-4 cleanup), and the corresponding sub-tests across panic /
allow / reject / partial plugins reference hooks that no longer exist.
* [MM-68405] MBE Phase 6: fire MessagesWillBeConsumed on the edit path (#36475)
---------
---------
---------
---------
* rebase onto master
---------
Co-authored-by: Hanzo Dev <[email protected]>
* add WithRPCErr hooks (server-facing/internal only)
* zero _returns on RPC failure in WithRPCErr companions
Aligns the WithRPCErr template with the HooksRPCErr godoc contract: when
g.client.Call returns a transport error, gob may have partially decoded the
reply. Reassign _returns to a zero value before destructuring so callers always
receive zeroed outputs alongside a non-nil transport error.
* rename HooksRPCErr to HooksWithRPCErr for naming consistency
Every related symbol uses the WithRPCErr suffix (MessageHasBeenPostedWithRPCErr,
RunMultiPluginHookWithRPCErr, RunMultiHookWithRPCErr, etc.). Aligning the
interface name removes the only outlier and makes the convention uniform.
* rename rpcErrImpl to hooksWithRPCErrImpl
Mirrors the existing hooksImpl/Hooks naming pattern on hooksTimerLayer.
* add supervisor.HooksWithRPCErr() and drop runtime type assertion
The old path did rp.supervisor.Hooks().(HooksWithRPCErr) and handled the
"doesn't implement" branch — but that branch was structurally unreachable
(the compile-time `_ HooksWithRPCErr = (*hooksTimerLayer)(nil)` assertion
guards it).
Change supervisor.hooks from `Hooks` to the concrete `*hooksTimerLayer`
(which implements both interfaces, enforced at field assignment), add a
parallel HooksWithRPCErr() accessor, and call it directly. Hooks() keeps
its public Hooks-interface signature via implicit conversion at return.
* drop "implemented by" clause from HooksWithRPCErr godoc
Both hooksRPCClient and hooksTimerLayer satisfy the interface, and naming
implementations in interface godocs adds rot — the contract is what readers
need, not the list of wrappers.
---------
Co-authored-by: Hanzo Dev <[email protected]>
* MM-68016, MM-68017, MM-68018 Add plugin pre-hooks for channel member add, team member add, and channel archive
Enable plugins to intercept and reject (or modify) three operations before
they are persisted: adding a channel member, adding a team member, and
archiving a channel. These are the three high-priority hooks from epic
MM-68003.
* feat: filewillbedonwloaded hook
* feat: error popup
* chore: make generated pluginapi
* tests
* feat: different errors for different download types
* feat: allow toast positions
* fix: avoid using deprecated i18n function
* feat: add plugin API to show toasts
* feat: downloadType parameter
* tests: updated tests
* chore: make check-style
* chore: i18n
* chore: missing fields in tests
* chore: sorted i18n for webapp
* chore: run mmjstool
* test: fixed webapp tests with new changes
* test: missing mocks
* fix: ensure one-file attachments (previews) are handler properly as thumbnails
* chore: lint
* test: added new logic to tests
* chore: lint
* Add SendToastMessage API and FileWillBeDownloaded hook
- Introduced SendToastMessage method for sending toast notifications to users with customizable options.
- Added FileWillBeDownloaded hook to handle file download requests, allowing plugins to control access to files.
- Updated related types and constants for file download handling.
- Enhanced PluginSettings to include HookTimeoutSeconds for better timeout management.
* Update webapp/channels/src/components/single_image_view/single_image_view.tsx
* chore: copilot reviews
* test: head requests
* chore: linted the webapp
* tests: fixed path
* test: fixed mocked args
* allow sending message to a connection directly
* fix: hook thread safety
* chore: formatting
* chore: remove configuration from system console
* chore: release version
* chore: update signature
* chore: update release version
* chore: addressed comments
* fix: update file rejection handling to use 403 Forbidden status and include rejection reason header
* Fix nil pointer panic in runFileWillBeDownloadedHook
The atomic.Value in runFileWillBeDownloadedHook can be nil if no
plugins implement the FileWillBeDownloaded hook. This causes a panic
when trying to assert the nil interface to string.
This fix adds a nil check before the type assertion, defaulting to
an empty string (which allows the download) when no hooks have run.
Fixes:
- TestUploadDataMultipart/success panic
- TestUploadDataMultipart/resume_success panic
* test: move the logout test last
* chore: restored accidential deletion
* chore: lint
* chore: make generated
* refactor: move websocket events to new package
* chore: go vet
* chore: missing mock
* chore: revert incorrect fmt
* chore: import ordering
* chore: npm i18n-extract
* chore: update constants.tsx from master
* chore: make i18n-extract
* revert: conflict merge
* fix: add missing isFileRejected prop to SingleImageView tests
* fix: mock fetch in SingleImageView tests for async thumbnail check
The component now performs an async fetch to check thumbnail availability
before rendering. Tests need to mock fetch and use waitFor to handle
the async state updates.
* refactor: move hook logic to app layer
* chore: update version to 11.5
* Scope file download rejection toast to the requesting connection
Thread the Connection-Id header through RunFileWillBeDownloadedHook and
sendFileDownloadRejectedEvent so the WebSocket event is sent only to the
connection that initiated the download, instead of all connections for
the user.
---------
Co-authored-by: Hanzo Dev <[email protected]>
* option for auto inviting plugin to all shared channels.
* auto-invite remotes to shared channels when flag set
* fix unit test
* immediately ping new remotes; fix unique siteurl bug
* make i18n-extract
* fix translations
* plugin hooks for file attachments
* hook for profile image sync
* fix profile image sync
* fix unit test
---------
Co-authored-by: Mattermost Build <[email protected]>
* Add interface for PreferencesHaveChanged hook
* Add context to preference-related methods of App
* Implement PreferencesHaveChanged
* Re-add missing "fmt" import
* Update minimum server version for the new hook
* Remove pointers to be consistent with other preference APIs
* feature: implemented basic MessageWillBeConsumed hook and applied on GetSinglePost method.
* use hook in get methods
* chore: refactored hook usage and created utils functions to apply hook
* bugfix: single post not updating
* chore: adjusted hook to return post
* chore: reverted some uneeded changes
* chore: updated hook to accept slice of posts
* bugfix: slice filled with niil values
* chore: MessageWillBeConsumed ranamed to MessagesWillBeConsumed
* Update plugin/hooks.go
Co-authored-by: Jesse Hallam <[email protected]>
* Add feature flag
* Update min version
* update tests to account for feature flag
* fix linting issues
---------
Co-authored-by: Matej Topolovac <>
Co-authored-by: mtopolovac <[email protected]>
Co-authored-by: Jesse Hallam <[email protected]>
Co-authored-by: Kevin Hsieh <[email protected]>
Co-authored-by: Jesse Hallam <[email protected]>
* Adding 'MessageHasBeenDeleted' hook to plugins
* Remove debug logs
* Add unit test
* Bumping the required version
* Fix CI problems
* Increasing the minimum version
* go fmt
---------
Co-authored-by: Ben Schumacher <[email protected]>
Co-authored-by: Mattermost Build <[email protected]>
* add NotificationWillBePushed hook
* mocks
* use a struct for hook parameters; simplify number of parameters sent across RPC
* missing wg.Wait
* change to a bool return value
Remove changes related to the unshipped threads everywhere feature, including commits c8bd2a6af6 and 372e34132c.
Since a version of Playbooks shipped calling this experimental API, keep a `nil` implementation to avoid breaking compatibility. We remove the hooks altogether, but keep the numbering again to avoid breaking compatbility.
Fixes: https://mattermost.atlassian.net/browse/MM-53358
It was a good decision in hindsight to keep the public module as 0.x
because this would have been a breaking change again.
https://mattermost.atlassian.net/browse/MM-53032
```release-note
Changed the Go module path from github.com/mattermost/mattermost-server/server/v8 to github.com/mattermost/mattermost/server/v8.
For the public facing module, it's path is also changed from github.com/mattermost/mattermost-server/server/public to github.com/mattermost/mattermost/server/public
```