{"id":51549482,"url":"https://github.com/ory/keto-playground","last_synced_at":"2026-07-09T22:30:34.129Z","repository":{"id":346843104,"uuid":"1191686509","full_name":"ory/keto-playground","owner":"ory","description":null,"archived":false,"fork":false,"pushed_at":"2026-05-15T20:33:10.000Z","size":122,"stargazers_count":3,"open_issues_count":0,"forks_count":1,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-15T23:32:43.728Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ory.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-25T13:43:16.000Z","updated_at":"2026-04-22T05:56:41.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/ory/keto-playground","commit_stats":null,"previous_names":["ory/keto-playground"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/ory/keto-playground","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ory%2Fketo-playground","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ory%2Fketo-playground/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ory%2Fketo-playground/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ory%2Fketo-playground/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ory","download_url":"https://codeload.github.com/ory/keto-playground/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ory%2Fketo-playground/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35314872,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-09T02:00:07.329Z","response_time":57,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-07-09T22:30:33.161Z","updated_at":"2026-07-09T22:30:34.119Z","avatar_url":"https://github.com/ory.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Keto Playground\n\nInteractive React app for exploring and editing Ory Keto permission graphs. Works in two modes:\n\n- **Offline** — loads bundled example data, fully editable, no Keto instance needed\n- **Live** — connects to your Ory Network project, fetches real tuples and runs live permission checks\n\nSelect a use case and a user to see their permission graph: which entities they're connected to, through what relations, and what permissions they have on each resource.\n\n- Nodes are color-coded by namespace (User, Role, Customer, etc.)\n- Edges show relation names (members, parent_lob, allowed_roles, etc.)\n- The sidebar shows direct relations and permission results (ALLOWED/DENIED)\n\n## Schema Editor\n\nIn **offline mode**, a **Schema** panel at the bottom of the graph shows the OPL (Ory Permission Language) TypeScript source for the selected example:\n\n- **Expand** the panel to read the full namespace definitions (`related` blocks and `permits` logic)\n- **Edit** the schema directly in the textarea — useful for exploring what-if changes locally\n- An **\"edited\"** badge marks when the local copy differs from the original\n- **Reset to original** restores the bundled schema\n- Switching examples automatically loads the new schema and discards local edits\n- **Local only** — to push changes to a live Ory instance, run `ory update opl --file namespace.ts`\n\n\u003e The Keto API does not expose OPL at runtime, so the Schema Editor is unavailable in Live mode.\n\n## Relationship Editor\n\nIn **offline mode**, a **Relationships** panel at the bottom of the graph lets you edit the tuple data live:\n\n- **Expand** the panel to see all relation tuples in a scrollable table\n- **Delete** any tuple — the graph updates immediately\n- **Edit** any tuple inline: hover a row to reveal the ✏ button, which turns the row into editable inputs; press Enter to save or Escape to cancel. Editing a base tuple saves it as a custom row (marked with a blue border)\n- **Subject format** in the edit field: plain `alice` for a direct subject ID, or `Namespace:object` / `Namespace:object#relation` for a subject set\n- **Add new tuples** via a form: pick namespace, object, relation, and a subject (User ID or Subject Set)\n- Newly added `subject_id` values appear in the user dropdown straight away\n- An **\"edited\"** badge marks when changes are active\n- **Reset to default** restores the original example data\n\n## Prerequisites\n\n- Node.js 20+\n- An Ory Network project with OPL and tuples loaded (optional — the app works offline with bundled examples)\n\n## Quick Start\n\n### Offline (no Ory project needed)\n\n```bash\ncd permission-visualizer\nmake dev\n```\n\nOpen **http://localhost:5173** — the app detects that no API is configured and uses bundled offline data.\n\n### With a live Ory project\n\n1. Copy the env file and fill in your credentials:\n\n```bash\ncd permission-visualizer\ncp .env.example .env\n# Edit .env with your ORY_SDK_URL and ORY_ACCESS_TOKEN\n```\n\n2. Seed an example into Keto:\n\n```bash\nmake seed EXAMPLE=b2b-hierarchy   # or any example from examples/\n```\n\n3. Start the dev server:\n\n```bash\nmake dev\n```\n\nOpen **http://localhost:5173**. The Vite dev server proxies `/api/*` requests to your Ory project, injecting the access token so the browser never sees the PAT.\n\n### Docker\n\n```bash\nmake docker-build\nmake docker-run   # reads .env for ORY_SDK_URL and ORY_ACCESS_TOKEN\n```\n\nThe production container uses a zero-dependency Node.js server (`server.js`) that serves the built SPA and proxies `/api/*` to Ory. Runs on port 3000 by default.\n\n## How It Works\n\n```\nBrowser (React + Cytoscape.js)\n    |\n    |  /api/relation-tuples\n    |  /api/relation-tuples/check\n    |  /api/namespaces\n    ▼\nVite Dev Proxy (:5173/api/*) — or — server.js (:3000/api/*)\n    |\n    |  + Authorization: Bearer \u003cPAT\u003e\n    ▼\nOry Network API (ORY_SDK_URL)\n```\n\n1. **Fetch namespaces** — gets the list of entity types from the current OPL\n2. **Fetch all tuples** — paginated fetch across all namespaces\n3. **Derive users** — extracts all `subject_id` values from tuples\n4. **Build graph** — when a user is selected, traces their connections through the tuple graph\n5. **Check permissions** — runs permission checks for all relevant resources and displays ALLOWED/DENIED badges\n\nIf no API is reachable, the app falls back to bundled offline data generated from `examples/`.\n\n## Configuration\n\nEnvironment variables are read from `permission-visualizer/.env`:\n\n| Variable           | Default                 | Description                      |\n| ------------------ | ----------------------- | -------------------------------- |\n| `ORY_ACCESS_TOKEN` | (required)              | PAT injected into proxy requests |\n| `ORY_TUNNEL_URL`   | `http://localhost:4000` | Where the ory tunnel is running  |\n| `ORY_SDK_URL`      | —                       | Your Ory project URL (e.g. `https://your-project.projects.oryapis.com`) |\n| `ORY_ACCESS_TOKEN` | —                       | Ory PAT, injected into proxy requests |\n\n## Available Use Cases\n\nAll 7 examples live in `permission-visualizer/examples/` and are available in the app dropdown:\n\n| Use Case            | Interesting Users to Try                                                                    |\n| ------------------- | ------------------------------------------------------------------------------------------- |\n| RBAC App Access     | `alice` (admin — all access), `eve` (viewer — limited)                                      |\n| RBAC Bank Accounts  | `john-smith` (owner), `james` (teller), `kevin` (branch_admin)                              |\n| RAG Document Access | `alice` (owner + team), `oscar` (no access)                                                 |\n| B2B Hierarchy       | `ceo-pat` (sees everything), `mgr-retail-lisa` (one LOB), `rep-saas-yara` (one customer)    |\n| SaaS Feature Gating | `alice` (enterprise), `eve` (free tier)                                                     |\n| Healthcare Records  | `dr-jones` (multi-patient), `dr-garcia` (emergency access), `dr-specialist-lee` (consented) |\n| Content Publishing  | `writer-alice` (drafts), `editor-diana` (review), `publisher-frank` (publish)               |\n\n## Makefile Targets\n\nRun all targets from `permission-visualizer/`:\n\n| Target | Description |\n|--------|-------------|\n| `make dev` | Start the Vite dev server |\n| `make build` | Install deps and create the production bundle |\n| `make seed EXAMPLE=\u003cname\u003e` | Seed a use case into Ory Keto |\n| `make generate-offline` | Regenerate offline data from `examples/` |\n| `make docker-build` | Build the Docker image |\n| `make docker-run` | Run the container (reads `.env`) |\n| `make clean` | Remove `dist/` and `node_modules/` |\n\n## Tech Stack\n\n- [React](https://react.dev/) + [Vite](https://vite.dev/)\n- [Cytoscape.js](https://js.cytoscape.org/) with [dagre layout](https://github.com/cytoscape/cytoscape.js-dagre) for directed graph rendering\n- Ory Keto REST API (via dev proxy or production server)\n\n## Tests\n\n```bash\ncd permission-visualizer/app\nnpx playwright install chromium\nnpx playwright test\n```\n\n| Test file                           | Requires                                        |\n| ----------------------------------- | ----------------------------------------------- |\n| `tests/relationship-editor.spec.js` | Nothing — uses offline bundled data (18 tests)  |\n| `tests/schema-editor.spec.js`       | Nothing — uses offline bundled data (10 tests)  |\n| `tests/visualizer.spec.js`          | Live Ory tunnel on port 4000 (11 tests)         |\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fory%2Fketo-playground","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fory%2Fketo-playground","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fory%2Fketo-playground/lists"}