acceptable-psychiatrist-42609
05/22/2025, 11:57 AMmysterious-mechanic-56172
07/30/2025, 1:22 PMadorable-dream-95774
07/31/2025, 11:49 PMadorable-dream-95774
08/01/2025, 2:12 AMketo.yml
you need to add:
namespaces:
location: file:///<path-to-your-file>
In my case, I mounted my file in my docker-compose for local development to /etc/config/keto/permissions.ts. So I have:
serve:
read:
host: 0.0.0.0
port: 4466
write:
host: 0.0.0.0
port: 4467
metrics:
host: 0.0.0.0
port: 4468
namespaces:
location: file:///etc/config/keto/permissions.ts
dsn: <postgres://keto:keto_secret@keto-db:5432/keto>
log:
level: trace
format: json
mysterious-mechanic-56172
08/01/2025, 7:00 AMmagnificent-energy-493
adorable-dream-95774
08/01/2025, 3:51 PMadorable-dream-95774
08/01/2025, 5:17 PMadorable-dream-95774
08/01/2025, 6:27 PMsubject_set
in the tuples themselves in addition to the traverse
definition in the OPL schema.
So, for example, I have:
import { Namespace, Context } from "@ory/permission-namespace-types"
class User implements Namespace {}
// FollowUpBoss CRM entities
class FollowUpBossPerson implements Namespace {
related: {
owners: User[]
editors: User[]
viewers: User[]
}
permits = {
view: (ctx: Context): boolean =>
this.related.viewers.includes(ctx.subject) ||
this.related.editors.includes(ctx.subject) ||
this.related.owners.includes(ctx.subject),
edit: (ctx: Context): boolean =>
this.related.editors.includes(ctx.subject) ||
this.related.owners.includes(ctx.subject)
}
}
class FollowUpBossDeal implements Namespace {
related: {
owners: User[]
editors: User[]
viewers: User[]
parents: FollowUpBossPerson[]
}
permits = {
view: (ctx: Context): boolean =>
this.related.viewers.includes(ctx.subject) ||
this.related.editors.includes(ctx.subject) ||
this.related.owners.includes(ctx.subject) ||
this.related.parents.traverse((parent) => parent.permits.view(ctx)),
edit: (ctx: Context): boolean =>
this.related.editors.includes(ctx.subject) ||
this.related.owners.includes(ctx.subject) ||
this.related.parents.traverse((parent) => parent.permits.edit(ctx))
}
}
Then as example tuples I have:
{
"relation_tuples": [
{
"namespace": "FollowUpBossPerson",
"object": "FollowUpBossPerson:636",
"relation": "editors",
"subject_id": "eefa251f-cff2-468f-9ffb-15ff9dc32b46"
},
{
"namespace": "FollowUpBossDeal",
"object": "FollowUpBossDeal:1793",
"relation": "editors",
"subject_id": "FollowUpBossPerson:636"
},
{
"namespace": "FollowUpBossDeal",
"object": "FollowUpBossDeal:1793",
"relation": "parents",
"subject_set": {
"namespace": "FollowUpBossPerson",
"object": "FollowUpBossPerson:636",
"relation": ""
}
},
...
]
}
Then I can perform checks:
❯ curl -X POST "<http://localhost:4466/relation-tuples/check>" \
-H "Content-Type: application/json" \
-d '{
"namespace": "FollowUpBossDeal",
"object": "FollowUpBossDeal:1793",
"relation": "view",
"subject_id": "FollowUpBossPerson:636"
}'
{"allowed":true}
❯ curl -X POST "<http://localhost:4466/relation-tuples/check>" \
-H "Content-Type: application/json" \
-d '{
"namespace": "FollowUpBossDeal",
"object": "FollowUpBossDeal:1793",
"relation": "view",
"subject_id": "eefa251f-cff2-468f-9ffb-15ff9dc32b46"
}'
{"allowed":true}
Hope this helps anyone else stuck on this!