square-napkin-92357
06/27/2025, 9:16 AMclass User implements Namespace {
related: {
editors: User[]
viewers: User[]
owners: User[]
}
}
class Dashboard implements Namespace {
related: {
members: (User | Dashboard)[]
}
}
class DashboardInstance implements Namespace {
related: {
parents: Dashboard[]
viewers: (User | SubjectSet<Dashboard, "members">)[]
owners: (User | SubjectSet<Dashboard, "members">)[]
editors: (User | SubjectSet<Dashboard, "members">)[]
}
permits = {
view: (ctx: Context): boolean =>
this.related.parents.traverse((p) =>
p.related.viewers.includes(ctx.subject),
) ||
this.related.viewers.includes(ctx.subject) ||
this.related.owners.includes(ctx.subject),
edit: (ctx: Context): boolean => this.related.editors.includes(ctx.subject),
}
}
brief-egg-61061
06/27/2025, 9:16 AMbrief-egg-61061
06/27/2025, 9:16 AMdashboard
table with many records (dashboard_id1, dashboard_id2, ...). - Users can be owners, editors, or viewers of a dashboard. - Owners are also editors. - Editors are also viewers. - If a user can view a dashboard, they can view all dashboard instances under it (hierarchical permission). ### Recommended OPL Model You should model the relationships and permissions to reflect the hierarchy and inheritance of roles. The OPL should use plural relationship names and express the permission inheritance (owner → editor → viewer) and the transitive view permission through parent dashboards. Here’s an updated version of your code, following Ory Keto conventions and your requirements: typescript import { Namespace, Context, SubjectSet } from "@ory/keto-namespace-types" class User implements Namespace {} class Dashboard implements Namespace { related: { owners: User[] editors: User[] viewers: User[] parents: Dashboard[] } permits = { // Owners are also editors, editors are also viewers view: (ctx: Context): boolean => this.related.viewers.includes(ctx.subject) || this.permits.edit(ctx) || this.related.parents.traverse((parent) => parent.permits.view(ctx)), edit: (ctx: Context): boolean => this.related.editors.includes(ctx.subject) || this.permits.own(ctx), own: (ctx: Context): boolean => this.related.owners.includes(ctx.subject), } } class DashboardInstance implements Namespace { related: { parents: Dashboard[] viewers: (User | SubjectSet<Dashboard, "viewers">)[] editors: (User | SubjectSet<Dashboard, "editors">)[] owners: (User | SubjectSet<Dashboard, "owners">)[] } permits = { // Inherit view permission from parent dashboard view: (ctx: Context): boolean => this.related.viewers.includes(ctx.subject) || this.permits.edit(ctx) || this.related.parents.traverse((parent) => parent.permits.view(ctx)), edit: (ctx: Context): boolean => this.related.editors.includes(ctx.subject) || this.permits.own(ctx), own: (ctx: Context): boolean => this.related.owners.includes(ctx.subject), } }
Key points: - Use plural relationship names (owners
, editors
, viewers
) as per Ory Keto conventions. - Express permission inheritance using this.permits.edit(ctx)
and this.permits.own(ctx)
to avoid code duplication and ensure correct role escalation. - Use .traverse
to allow transitive permissions from parent dashboards, so if a user can view a parent, they can view all children. - Use SubjectSet<Dashboard, "viewers">
etc., to allow group-based permissions if needed. This model is directly aligned with the Ory Keto documentation and best practices for hierarchical and inherited permissions [Create a permission model](https://www.ory.sh/docs/keto/modeling/create-permission-model#define-permissions-in-the-opl), [OPL examples](https://www.ory.sh/docs/keto/reference/ory-permission-language#examples). If you need to support group membership or more complex subject sets, you can further extend the relationships as shown in the OPL examples. Let me know if you need help with the relationship tuples or API usage!square-napkin-92357
06/27/2025, 9:22 AMbrief-egg-61061
06/27/2025, 9:22 AMbrief-egg-61061
06/27/2025, 9:22 AMpermission.ts
(the Ory Permission Language file) with a self-hosted Ory Keto instance running via Docker Compose, you need to convert your OPL file into a configuration format that Keto understands and then mount it into the container. However, the knowledge sources do not provide a direct, step-by-step guide for mounting a .ts
OPL file into a Docker Compose setup for Ory Keto. Here’s what is clear from the documentation: - Ory Keto uses a configuration file (typically YAML) for namespaces and permission rules. - The Ory Permission Language (OPL) is used in Ory Network and can be managed via the Ory Console or CLI. - For self-hosted Keto, you can export/import the permission configuration using the Ory CLI, and the configuration is typically in YAML, JSON, or JSON-pretty format, not TypeScript directly. Recommended approach based on the docs: 1. Write your permission model in OPL (permission.ts
). 2. Use the Ory CLI to import the configuration into Ory Network, or export from Ory Network to YAML for self-hosted Keto. - Example to export from Ory Network: sh ory get permission-config --project <project-id> --workspace <workspace-id> --format yaml > permission-config.yaml
- You can then mount permission-config.yaml
into your Keto Docker container. 3. Mount the configuration file in Docker Compose: - In your docker-compose.yml
, add a volume to mount the config file: yaml services: keto: image: oryd/keto:<version> volumes: - ./permission-config.yaml:/etc/config/permission-config.yaml command: - serve - --config - /etc/config/permission-config.yaml
Summary: You cannot directly mount a .ts
OPL file into Ory Keto. You must convert it to a supported configuration format (YAML/JSON) and mount that file. The OPL is mainly used in Ory Network and via the Ory Console or CLI, not directly in self-hosted Keto containers. For more details, see the [Ory CLI configuration guide](https://www.ory.sh/docs/guides/cli/configure-permission-service) and [Ory Permission Language reference](https://www.ory.sh/docs/keto/reference/ory-permission-language). If you need to work locally, consider using the Ory CLI to test and convert your OPL file, then mount the resulting config into your Docker container as described above.square-napkin-92357
06/27/2025, 10:07 AMbrief-egg-61061
06/27/2025, 10:07 AMbrief-egg-61061
06/27/2025, 10:07 AMGET /admin/identities
This endpoint lists all identities in the system. You can use various query parameters for pagination, filtering, and consistency. For example: - `page_size`: Number of items per page (default: 250, max: 500) - `page_token`: Token for the next page - `consistency`: Read consistency level (strong
or eventual
) - `include_credential`: Include credentials such as password
or oidc
in the response - `organization_id`: Filter identities by organization - `ids`: Retrieve multiple identities by their IDs - `credentials_identifier`: Look up by credential identifier (username, email) Example request: GET /admin/identities?page_size=100&consistency=eventual
Authentication: You must authenticate using an Ory access token to perform this operation. For more details, see the [Ory API Reference for listIdentities](https://www.ory.sh/docs/kratos/concepts/identity-user-model) and the [API documentation](https://raw.githubusercontent.com/ory/docs/master/docs/reference/api.json) (see the "listIdentities" method) and [Kratos API Reference](https://raw.githubusercontent.com/ory/kratos/master/spec/api.json).