Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proof of concept for Plugin system (fixes #3562) #4695

Draft
wants to merge 16 commits into
base: main
Choose a base branch
from
Draft

Conversation

Nutomic
Copy link
Member

@Nutomic Nutomic commented May 3, 2024

This PR adds a basic plugin hook using Extism (webassembly), including a simple example plugin written in Go. Plugins can also be written in many other languages like JS, Rust, .NET or C.

For now there are only two plugin hooks available, before and after a new post is created through the local api. However we can add all sorts of plugin hooks, eg for different api actions or incoming federated actions. The question is which plugin hooks are actually needed. So if you are interested in writing Lemmy plugins, please comment below with the hooks that you need.

I dont intend to merge this PR until there is at least a single real-world plugin in development.

Todo:

  • Add before hook for all api endpoints
  • Add after hook for all api endpoints
  • Add hooks for federation actions
  • Write documentation
  • Wait for feedback from plugin authors
  • Include list of loaded plugins in /api/v3/site for transparency
  • Persistent data storage
  • Address various todo notes in code
  • Check how it affects performance
  • Check how it affects compile time (with this PR number of dependencies goes from 587 to 765)
  • How to handle security? Plugins can eg log plaintext passwords during login, arbitrarily rewrite new posts or even change the target of mod actions. Probably not much we can do without severely limiting the functionality, so we need to tell admins to be careful. Edit: Maybe can make Sensitive type unavailable to wasm.

@Nutomic Nutomic mentioned this pull request May 3, 2024
4 tasks
@db0
Copy link
Contributor

db0 commented May 3, 2024

Oh shit that's awesome! I'll look into creating a plugin use-case ASAP using python. I have some ideas

@Die4Ever
Copy link

Die4Ever commented May 3, 2024

would it be possible to automatically wrap every api route in plugin calls? just a global generic handler, idk if the router you're using allows this

@Die4Ever
Copy link

Die4Ever commented May 3, 2024

also I think we should organize behind a single GitHub tag, like

https://github.com/topics/lemmy-plugin

@Die4Ever
Copy link

Die4Ever commented May 3, 2024

as for ideas about which hooks to add, probably the hooks that would be needed to do some of the top issues (sorted by thumbs up reactions)

https://github.com/LemmyNet/lemmy/issues?q=is%3Aissue+is%3Aopen+sort%3Areactions-%2B1-desc

grouping communities, post tags, instance agnostic links, user flair, moderation tools... these aren't easy but they're probably good examples, and I would also like a plugin for an invite system

@Die4Ever
Copy link

Die4Ever commented May 3, 2024

also maybe there should be some standard for plugins creating their own tables/dbs in the shared postgres instance?

@RikudouSage
Copy link

Basically everything my LemmyWebhook package does would be nice.

@bkil
Copy link

bkil commented May 3, 2024

Do you plan to make it compatible with https://webxdc.org/ or the plugin/script/addon/extension architecture of dozens of extant IRC & instant messaging clients & bot frameworks?

@SleeplessOne1917
Copy link
Member

This is a significant feature that will need to have a lot of feedback from users, frontend developers, and potential plugin developers. I think further discussion of this should be handled in an RFC.

@Nutomic
Copy link
Member Author

Nutomic commented May 6, 2024

would it be possible to automatically wrap every api route in plugin calls? just a global generic handler, idk if the router you're using allows this

Good thinking. Ive now added a middleware which adds plugin hooks automatically for every single api route.

also maybe there should be some standard for plugins creating their own tables/dbs in the shared postgres instance?

It looks like Extism allows providing an api for persistent data storage.

Do you plan to make it compatible with https://webxdc.org/ or the plugin/script/addon/extension architecture of dozens of extant IRC & instant messaging clients & bot frameworks?

That looks like Javascript, not wasm so it wont be compatible. But it would be possible to write a Lemmy plugin which pulls in these existing plugins.

This is a significant feature that will need to have a lot of feedback from users, frontend developers, and potential plugin developers. I think further discussion of this should be handled in an RFC.

An RFC makes sense to discuss how something should be implemented, but in this case its pretty straightforward. I will rather write a documentation page to explain how to develop a plugin.

@Die4Ever
Copy link

Die4Ever commented May 6, 2024

Basically everything my LemmyWebhook package does would be nice.

from the discussion we had on Mastodon, it sounds like plugins would need the ability to create triggers/listeners/notifiers in postgres

https://phpc.social/@chrastecky/112395784140811086

but maybe that's a roundabout way to get those features

@dullbananas
Copy link
Collaborator

Will people be able to install plugins for their own communities, or will plugins only be for the entire instance?

@Nutomic
Copy link
Member Author

Nutomic commented May 7, 2024

Will people be able to install plugins for their own communities, or will plugins only be for the entire instance?

Plugins have access to all the data that is passed to the api (or returned from the api). So its possible to write plugins which only become active in certain communities. Community mods can write such a plugin and ask the instance admin to install it. However mods shouldnt be able to upload plugins directly, as those could use too many server resources and slow down the server which would be hard to debug.

@Nutomic
Copy link
Member Author

Nutomic commented May 7, 2024

I wrote documentation on how to create plugins. If you write a plugin let me know how it goes!

@Fmstrat
Copy link

Fmstrat commented May 11, 2024

Basically everything my LemmyWebhook package does would be nice.

from the discussion we had on Mastodon, it sounds like plugins would need the ability to create triggers/listeners/notifiers in postgres

https://phpc.social/@chrastecky/112395784140811086

but maybe that's a roundabout way to get those features

Allowing plugin developers to use PG listeners could be a nightmare for diagnosing performance issues.

Also, don't allow plugins to directly access the DB if possible. 90% of Devs will be lazy and use something like prisma, locking tables that don't need to be locked.

@neuronicnobody
Copy link

neuronicnobody commented May 14, 2024

I wrote a plugin here to get a feel for the development experience and it was more or less smooth sailing. Great docs! Exciting to see the possibility for more extensible software in the Fediverse.

In the case of my plugin above, which downcases excessive caps locks in community posts, would be cool to have Extism Host Functions so that the plugin could take additional action (e.g. send a message to the poster, update a karma system, etc.)

I also noticed that if I put multiple wasm files in the plugins directory I was getting some errors. Does the POC support this now?

Full disclosure, I'm part of the team that maintains Extism.

@Fmstrat
Copy link

Fmstrat commented May 14, 2024

Another question from a requirements perspective: Should plugins allow authentication? For instance, I could see a use-case of creating/associating instance accounts via LDAP or some other such authentication schene to align to a pre-existing system of users.

@Nutomic
Copy link
Member Author

Nutomic commented May 15, 2024

@neuronicnobody Thanks for testing! I didnt test loading multiple plugins before so that was broken, but now its working in my testing. However your plugin (downloaded wasm from git repo) throws called Result::unwrap() on an Err value: unknown import: xtp:test/harness::call has not been defined. Adding host functions would definitely be useful, but maybe that can be done later to keep things simple for now. As you are an Extism maintainer it would be good if you could review my code here.

@Fmstrat Authentication should be done directly in Lemmy as its more secure. The only reason we dont have LDAP etc yet is that no one implemented it yet, so its unlikely that someone would suddenly implement it if only it was possible as plugin.

@Fmstrat
Copy link

Fmstrat commented May 15, 2024

@Nutomic Good to know, thank you. Would the Dev team be open to a draft PR for external authentication systems in the future? This would be adventagous for privacy oriented orgs and government run entities to adopt.

@dessalines
Copy link
Member

There are several authentication related issues: https://github.com/LemmyNet/lemmy/issues?q=is%3Aissue+is%3Aopen+authentication

@neuronicnobody
Copy link

neuronicnobody commented May 15, 2024

@Nutomic

Are you sure you didn't try to load the test-deloudify.wasm file instead of the deloudify.wasm? I created the test wasm to run tests against the lemmy plugin using this test runner we have here. It brings in some imports in the xtp:test/harness namespace that are supplied by the XTP CLI. From those links you can check out the exports and imports each module defines and you can download the raw bytes as well if you want to try and test again.

Absolutely agree with you on the phasing of Host Functions, just wanted to point them out as an option for later!

And yeah will definitely take a look at the code.

@Nutomic
Copy link
Member Author

Nutomic commented May 21, 2024

@neuronicnobody Youre right, with the other file it works as expected.

@neuronicnobody
Copy link

@neuronicnobody Youre right, with the other file it works as expected.

Awesome!

Also, I perused the PR and nothing stuck out to me as a problem or obvious area to improve, but I'll also circulate this with some of the others on the team in case they have any thoughts. You can always find us in Discord as well if you're not already there.

@dullbananas
Copy link
Collaborator

You can always find us in Discord as well if you're not already there.

https://stallman.org/discord.html

@Die4Ever
Copy link

someone had the idea that plugins should be able to host their own separate UI, which could help a lot with moderation plugins https://lemmy.ml/comment/11743890

I also think at some point Lemmy may want to have a default set of plugins that are automatically installed

@lullis
Copy link
Contributor

lullis commented Sep 2, 2024

Can this plugin system provide a mechanism to initiate actions on behalf of the community actor?

I am thinking of a system where a community can follow different actors and that announces activities that have a certain keyword. IIUIC, this would allow, e.g, for someone to take posts shared on flipboard and broadcast them to a group discussion, and have the flipboard actor as the "creator" of the post on Lemmy, right?

@Nutomic
Copy link
Member Author

Nutomic commented Sep 9, 2024

@Die4Ever WIth the current implementation in this PR, plugins can add extra data to existing API responses which can be used by alternative frontends. We could also allow plugins to add new API endpoints, but thats not implemented yet.

@lullis Im not sure how that would work. My idea for the plugin system is that it can mainly allow to observe and/or modify API requests and responses. If you want to trigger federation actions, you should rather do that by sending your own API requests (eg with a bot account). But maybe I misunderstand what you want to do, you can write a longer explanation in a new issue.

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.