Skip to content

Implement Fabric Permission API#5226

Open
Patbox wants to merge 4 commits intoFabricMC:26.1from
Patbox:permission-api
Open

Implement Fabric Permission API#5226
Patbox wants to merge 4 commits intoFabricMC:26.1from
Patbox:permission-api

Conversation

@Patbox
Copy link
Member

@Patbox Patbox commented Feb 22, 2026

Provides relatively simple, but way more flexible permission api for mods to use.

Using it is as simple as calling #checkPermission method on entity / CommandSourceStack, or any other PermissionContextOwner implementation. Proper contexts are implemented as a separate classes implementing PermissionContext, which allow to always receive uuid, type (player, entity, etc) and vanilla permission level, as well as optionally additional contexts provided via PermissionContext#get method (similar to PacketContext in that regard).

This api was designed to allow checks for players (online and offline), entities and other objects.

The checks themselves default to using vanilla TriState, but api allows providing any codec for it to read from (which automatically handles support for ints, strings and any other complex data). That is also one of main things that differentiate it from vanilla permission checks, which only allow checking for bools without externally defined defaults.

The implementer (think LuckPerms, PlayerRoles or some protection mod) only need to handle a single PermissionCheckCallback event.

@sylv256 sylv256 added enhancement New feature or request new module Pull requests that introduce new modules labels Feb 22, 2026
Copy link
Member

@Juuxel Juuxel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there should be a code example in the API docs showing how to use this API, especially from the POV of mods defining and checking permissions. It's currently a bit unclear to me. Some of the PR desc and test mod could probably be repurposed for a smaller example.

Comment on lines 40 to 48
this.type = switch (source.getEntity()) {
case Player player -> Type.PLAYER;
case Entity entity -> Type.ENTITY;
case null -> Type.SYSTEM;
};
this.uuid = switch (source.getEntity()) {
case Entity entity -> entity.getUUID();
case null -> Util.NIL_UUID;
};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think the entity should necessarily be used for determining the type, because it can be changed through commands like /execute as @a run .... See luckperms, which used to do the same thing Luckperms#3673!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh that is fair hmm. Through guess just looking at the command output might not be idea either. Will check if maybe patching it directly first before actually doing the check is better option

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed it to only determine the type / uuid on initial CommandSourceStack creation, so any later modification of it (calling with* methods) will inherit initial type and uuid

@lucko
Copy link

lucko commented Feb 27, 2026

Some feedback (in no particular order) as requested:

Mojang have recently added some permissions-y APIs to Player and ServerPlayer which permission manager mods can mixin to (LuckPerms does, unsure about others). This went under the radar a bit I think, so maybe you aren't aware. For example:

private static final Permission PERM = new Permission.Atom(
    Identifier.fromNamespaceAndPath("example_mod", "command.test")
);

ServerPlayer player;
if (!player.permissions().hasPermission(PERM)) {
  // deny
}

In my view this now captures ~90% of what mods will need. Before it was added, fabric-permissions-api was quite key as an interface between mods and permissions providers, I am not sure it necessarily is anymore. At the very least, given what I understand the philosophy of Fabric API to be, it seems sensible for any new APIs added on top to look and feel similar to the Permission APIs the game now has.

Some other comments - some of these are suggestions, others I think would be blockers for LP implementing this API fully:

  • Option/meta-like values, not sure it makes sense to call them "Permissions". I think I see why you did it this way but IMO it is confusing.
  • Offline player checks - these should return a CompletableFuture in my opinion. Often (in LP anyway), these result in some sort of database lookup or file I/O. I would prefer to see this reflected in the API to prevent authors from accidentally doing it on the game thread.
  • Context - pleased to see it as a feature, but I am not sure in it's current state how a permission mod would take what is there in PermissionContext and turn it into something queryable/comparable against a serialised data set. I am also unclear on the difference between the built-in contexts and extra/custom ones. Sponge (and LP) use simple String->String pairs for this, Forge has a higher level API but ultimately you can get down to String->String using built-in serialisation methods. Caching is another important thing, I have worries about Position being included by default for example as that feels far too granular. Maybe I have just misunderstood?

possibly others, but those are the key ones I can see so far :)

@Patbox
Copy link
Member Author

Patbox commented Feb 27, 2026

Yeah I am aware of vanilla's permission checks, which is why I delayed working on this api originally. It kinda felt bit too unfinished and doesn't handle default values as nicely (which my mods depending on defaults being dynamic for example). In future if Mojang implements more of it, it might make sense to get it connected closer with vanilla permission sets.

Main reason why it's all under permission is since everything is checked the same way (as within concept of this api there is no real distinction between boolean/TriState permissions and string/number ones). Boolean/TriState just got few extra utility methods due to it being commonly checked one.

That one is slightly tricky. Let's say you have a mod that adds machines that modify world or do something that needs to check for permission. It's likely they will want to check with their owner being their context, which will happen whatever the player is online or not. So the checks being straightforward is kinda important here.
Either way having "async" check methods for context does make sense. Will need to think if there is nicer way to solve it through.

With context values being serializable, I can look into that as I do see the usecase. For simpler ones I can look into implementing it, but I feel not everything will make sense to support that (for example the CommandSourceStack or Entity don't really make sense to be represented as a string). Generally my idea of context was to pretty much work similarly to how loot tables can include optional data that then might be used for more precise logic. Think about area protection mod wanting to change player permissions locally. In that case it needs the position to determine where thing happens. Similarly to loot tables custom ones would require direct compat. Technically speaking PermissionContext isn't static in itself, as for default entity one it dynamically queries then from said entity.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request new module Pull requests that introduce new modules

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants