Maxime Leduc
10/02/2025, 11:06 PMAsk Inkeep
10/02/2025, 11:06 PMpermit support automation2
10/02/2025, 11:06 PMAsk Inkeep
10/02/2025, 11:06 PMawait permit.api.tenants.create({
key: "stripeinc",
name: "Stripe Inc",
attributes: {
allowed_locations: ["US", "CA"],
},
}) ;
2. Herds as Resource Instances
Model herds as resource instances that belong to specific farm tenants . Each herd can have attributes for subscription level and species type:
await permit.api.resource_instances.create({
key: "react",
resource: "repository",
tenant: "default",
attributes: {
private: "false",
owner: "Company C",
},
}) ;
3. User Role Assignments
Assign users to roles within specific tenants (farms) (1) . When checking permissions, include the tenant context:
const permitted = await permit.check(userKey, "create", {
type: "document", // The resource name
tenant: tenantKey, // The tenant key
}) ;
4. Hierarchical Permissions with ReBAC
Use relationship-based access control to model the farm-to-herd hierarchy (3) . Create parent relationships between farms and herds, then define role derivations:
await permit.api.relationshipTuples.create({
subject: "folder:finance",
relation: "parent",
object: "file:2023_report",
}) ;
Role derivations can propagate permissions from farm level to herd level :
await permit.api.resourceRoles.update("file", "editor", {
granted_to: {
users_with_role: [
{
linked_by_relation: "parent",
on_resource: "folder",
role: "editor",
},
],
},
}) ;
Dynamic Permission Evaluation
When evaluating permissions, pass the relevant attributes in your check calls. The PDP will evaluate policies based on:
• User's role in the farm (tenant) (1)
• Herd's attributes (subscription level, species type) (2)
• Farm's subscription level (tenant attributes)
• Relationships between farms and herds (3)
This approach allows you to create policies that dynamically evaluate access based on all four factors you mentioned, ensuring that features are properly gated based on the combination of user role, farm context, herd subscription, and species type.Ask Inkeep
10/02/2025, 11:07 PMThomas
10/02/2025, 11:31 PMAsk Inkeep
10/02/2025, 11:32 PMMaxime Leduc
10/02/2025, 11:32 PMThomas
10/02/2025, 11:32 PMThomas
10/02/2025, 11:34 PMMaxime Leduc
10/02/2025, 11:37 PMThomas
10/02/2025, 11:42 PMMaxime Leduc
10/02/2025, 11:42 PMMaxime Leduc
10/02/2025, 11:43 PMOr Weis
10/03/2025, 7:12 AMOr Weis
10/03/2025, 7:12 AMMaxime Leduc
10/03/2025, 9:00 AMJules Robichaud-Gagnon
10/03/2025, 12:22 PM<https://ghc.up.railway.app/> . but we cannot tweak the demo dashboard or login as one of the email without having the password.
I may have missed some important part.Or Weis
10/03/2025, 12:29 PMJules Robichaud-Gagnon
10/03/2025, 2:47 PMcheck function.
Ex:
await permit.check(user, "create", "animal", {
context: {
// additional data to be passed to the policy evaluation
herd_plan_features: herd.current_plan.features
},
});
Then use ABAC normally using herd_plan_features in our rules.
https://docs.permit.io/how-to/enforce-permissions/check/#using-the-context-objectJules Robichaud-Gagnon
10/03/2025, 2:58 PMawait permit.check(user, "create", "document", {
context: {
// additional data to be passed to the policy evaluation
totalDocuments: 100,
},
});
I believe it should be:
await permit.check(user, "create", "document", {
// additional data to be passed to the policy evaluation
totalDocuments: 100,
});
Unless is is intended there’s a "context" in a context
https://pdp-api.permit.io/redoc#tag/Authorization-API/operation/is_allowed_bulk_allowed_bulk_post
but it does not appear to require to have a context in context.Thomas
10/03/2025, 2:59 PMJules Robichaud-Gagnon
10/03/2025, 3:00 PMJules Robichaud-Gagnon
10/03/2025, 3:01 PMJules Robichaud-Gagnon
10/03/2025, 3:01 PMThomas
10/03/2025, 3:02 PMThomas
10/03/2025, 3:02 PMlist operators?Thomas
10/03/2025, 3:02 PMJules Robichaud-Gagnon
10/03/2025, 3:06 PMcontext the features of the current herd’s subscription level.
Is that right?Thomas
10/03/2025, 3:08 PMThomas
10/03/2025, 3:09 PMJules Robichaud-Gagnon
10/03/2025, 3:10 PMJules Robichaud-Gagnon
10/03/2025, 3:11 PMThomas
10/03/2025, 3:11 PMThomas
10/03/2025, 3:12 PMcontextJules Robichaud-Gagnon
10/03/2025, 3:13 PMThomas
10/03/2025, 3:13 PMJules Robichaud-Gagnon
10/03/2025, 3:14 PMThomas
10/03/2025, 3:14 PMThomas
10/03/2025, 3:14 PMThomas
10/03/2025, 3:15 PMThomas
10/03/2025, 3:15 PMJules Robichaud-Gagnon
10/03/2025, 3:17 PMconst permitted = await permit.check(
// the user object
{
// the user key
key: "<mailto:john@permit.io|john@permit.io>",
// just-in-time attributes on the user
attributes: {
location: "England",
department: "Engineering",
},
},
// the action the user is trying to do
"create",
// Resource
{
// the type of the resource (the resource key)
type: "document",
// just-in-time attributes on the resource
attributes: {
hasApproval: "true",
},
// the tenant the resource belong to
tenant: "companyB",
}
);
https://docs.permit.io/how-to/enforce-permissions/check#attributesThomas
10/03/2025, 3:18 PMThomas
10/03/2025, 3:18 PMJules Robichaud-Gagnon
10/03/2025, 3:19 PMJules Robichaud-Gagnon
10/06/2025, 2:13 PM{
"allOf": [
{
"allOf": [
{
"resource.herd_features": {
"array_subset": [
"feature_1"
]
}
}
]
}
]
}
"attributes": {
"herd_features": [
"feature_1"
]
}
equivalent python code
>>> {"feature_1"}.issubset({"feature_1"})
True
With more than 2 attributes it does not and two values in the subset it does not work:
ABAC rule:
{
"allOf": [
{
"allOf": [
{
"resource.herd_features": {
"array_subset": [
"feature_1",
"feature_2"
]
}
}
]
}
]
}
"attributes": {
"herd_features": [
"feature_1",
"feature_2"
]
}
equivalent python code:
>>> {"feature_1", "feature_2"}.issubset({"feature_1", "feature_2"})
True
It gets even weirder if I just pass 1 of the value as attributes (with the two values in the subset):
This returns `allow: true`:
"attributes": {
"herd_features": [
"feature_1"
]
}
This returns `allow: false`:
"attributes": {
"herd_features": [
"feature_2"
]
}
Which does not make any sense.Or Weis
10/06/2025, 2:24 PMAsk Inkeep
10/06/2025, 2:24 PMAsk Inkeep
10/06/2025, 2:24 PMarray_subset operator behavior you're describing, let me clarify how it works based on the documentation.
According to the operators documentation (1) , array_subset checks if an array has a subset of values. The operator validates: ["a", "b"] has ["a", "b", "c"] - meaning the attribute array should contain all the values specified in the condition.
The semantics appear to be inverted from what you might expect. When you define:
{
"resource.herd_features": {
"array_subset": [
"feature_1",
"feature_2"
]
}
}
This checks if ["feature_1", "feature_2"] is a subset of the herd_features attribute - meaning herd_features must contain at least those two features for the condition to pass.
For your use case with herd features, you might want to consider using array_contains instead , which checks if an array contains a specific value: ["a", "b", "c"] has "a" .
If you need to check that the herd has certain features available, you could structure your ABAC rule to check each required feature individually using array_contains, or ensure your herd_features attribute includes all features the herd subscription provides, then use array_subset appropriately.
The documentation shows that these operators are designed to work with the attribute types (Bool, Number, String, Array) , so make sure your attributes are properly typed when passing them in the check call.Ask Inkeep
10/06/2025, 2:24 PMAsk Inkeep
10/06/2025, 2:27 PMThomas
10/06/2025, 2:33 PMJules Robichaud-Gagnon
10/06/2025, 2:34 PMJules Robichaud-Gagnon
10/06/2025, 2:44 PMarray_contains is not what I need. I need to know if it has all the required features. This why the use of the set operations.
Note: I may have to use “superset” if the comparison is inverted but it is not what it is about.
I have unexpected results with basic set operations.Or Weis
10/06/2025, 2:55 PMJules Robichaud-Gagnon
10/06/2025, 2:57 PM{
"allOf": [
{
"allOf": [
{
"resource.herd_features": {
"array_subset": [
"feature_1",
"feature_2"
]
}
}
]
}
]
}
This returns `allow: true`:
"attributes": {
"herd_features": [
"feature_1"
]
}
This returns `allow: false`:
"attributes": {
"herd_features": [
"feature_2"
]
}
This is not normalOr Weis
10/06/2025, 3:00 PMJules Robichaud-Gagnon
10/06/2025, 5:20 PM/allowed though PDP? (that can be up to an hour or even more)Or Weis
10/06/2025, 5:22 PMJules Robichaud-Gagnon
10/06/2025, 5:23 PMJules Robichaud-Gagnon
10/06/2025, 5:26 PMOr Weis
10/06/2025, 5:28 PMJules Robichaud-Gagnon
10/06/2025, 5:45 PM"allow": true
With these attributes:
"attributes": {
"herd_features": [
"feature_1",
"feature_2",
"feature_3"
]
}
and this superset
{
"allOf": [
{
"allOf": [
{
"resource.herd_features": {
"array_superset": [
"feature_1",
"feature_2"
]
}
}
]
}
]
}
or this subset
{
"allOf": [
{
"allOf": [
{
"resource.herd_features": {
"array_subset": [
"feature_1",
"feature_2"
]
}
}
]
}
]
}
In both case, it returns "allow": false and its not supposed to.
I say “one of” because it is never clear to me which one in A or B for A ⊇ B (superset) or A ⊆ B (subset). Is A supposed to be the attributes or the values the policy?Or Weis
10/06/2025, 5:56 PMJules Robichaud-Gagnon
10/06/2025, 6:26 PM