Disallow bespoke abstractions and use the industry standard ones instead. People who make abstractions inflate how productive they’re making everyone else. Your user base is much smaller than popular libs, so your docs and abstractions are not as battle tested and easy to use as much as you think.

This is raw OpenFGA code:

    await client.Write(
        new ClientWriteRequest(
            [
                // Alice is an admin of form 123
                new()
                {
                    Object = "form:124",
                    Relation = "editor",
                    User = "user:avery",
                },
            ]
        )
    );

    var checkResponse = await client.Check(
        new ClientCheckRequest
        {
            Object = "form:124",
            Relation = "editor",
            User = "user:avery",
        }
    );

    var checkResponse2 = await client.Check(
        new ClientCheckRequest
        {
            Object = "form:125",
            Relation = "editor",
            User = "user:avery",
        }
    );
This is an abstraction we wrote on top of it:

    await Permissions
        .WithClient(client)
        .ToMutate()
        .Add<User, Form>("alice", "editor", "226")
        .Add<User, Team>("alice", "member", "motion")
        .SaveChangesAsync();

    var allAllowed = await Permissions
        .WithClient(client)
        .ToValidate()
        .Can<User, Form>("alice", "edit", "226")
        .Has<User, Team>("alice", "member", "motion")
        .ValidateAllAsync();
You would make the case that the former is better than the latter?

In the first example, I have to learn and understand OpenFGA, in the second example I have to learn and understand OpenFGA and your abstractions.

Well the point of using abstractions is that you don't need to know the things that it is abstracting. I think the abstraction here is self explaining what it does and you can certainly understand and use it without needing to understand all the specifics behind it.

More importantly: it prevents "usr:alice_123" instead of "user:alice_123" by using the type constraint to generate the prefix for the identifier.