{"id":25990288,"url":"https://github.com/getlarge/purrfect-sitter","last_synced_at":"2025-10-08T22:58:31.170Z","repository":{"id":280185474,"uuid":"940233448","full_name":"getlarge/purrfect-sitter","owner":"getlarge","description":null,"archived":false,"fork":false,"pushed_at":"2025-03-01T19:59:01.000Z","size":92,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-01T20:42:58.849Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","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/getlarge.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}},"created_at":"2025-02-27T20:38:52.000Z","updated_at":"2025-03-01T19:59:05.000Z","dependencies_parsed_at":"2025-03-01T20:43:10.644Z","dependency_job_id":"b3b50974-44e6-49ef-9a75-a4fc20b47628","html_url":"https://github.com/getlarge/purrfect-sitter","commit_stats":null,"previous_names":["getlarge/purrfect-sitter"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/getlarge%2Fpurrfect-sitter","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/getlarge%2Fpurrfect-sitter/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/getlarge%2Fpurrfect-sitter/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/getlarge%2Fpurrfect-sitter/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/getlarge","download_url":"https://codeload.github.com/getlarge/purrfect-sitter/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":242039689,"owners_count":20061925,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":"2025-03-05T13:53:57.817Z","updated_at":"2025-10-08T22:58:31.165Z","avatar_url":"https://github.com/getlarge.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Purrfect Sitter\n\nA cat sitting application with dual authorization strategies.\nThis is the support project for the [How to Protect Your API with OpenFGA](https://dev.to/this-is-learning/how-to-protect-your-api-with-openfga-from-rebac-concepts-to-practical-usage-4n9j) article.\n\n\u003cfigure\u003e\n  \u003cimg src=\"https://dev-to-uploads.s3.amazonaws.com/uploads/articles/faoyboj4ihjrn3msync4.png\" alt=\"An anonymous developer surrounded by cats\"/\u003e\n  \u003cfigcaption\u003eAn anonymous developer surrounded by cats\u003c/figcaption\u003e\n\u003c/figure\u003e\n\n## Architecture\n\n### Core Application\n\n- Fastify-based API\n- User authentication with Ory Kratos\n- Core models: User, Cat, CatSitting, Review\n- TypeBox for JSON Schema validation\n- Drizzle ORM for database access\n- OpenFGA for fine-grained authorization\n\n### NX Workspace Structure\n\n```\napps/\n  purrfect-sitter/       # Main Fastify application\n  purrfect-sitter-e2e/   # End-to-end tests\n\nlibs/                    # Domain-specific libraries\n  database/              # Database schema and repositories\n  models/                # DTOs and validation schemas\n  auth/                  # Authentication and authorization\n  cats/                  # Cats domain business logic\n  cat-sittings/          # Cat sittings domain business logic\n  reviews/               # Reviews domain business logic\n```\n\n### Authorization Strategies\n\nThis application implements two authorization strategies that can be toggled via environment variables:\n\n1. **Database Lookups** (`AUTH_STRATEGY=db`)\n\n   - Traditional database queries to check permissions\n   - Uses JOINs and WHERE clauses for relationship checks\n   - Direct SQL conditions for time-based rules\n\n2. **OpenFGA** (`AUTH_STRATEGY=openfga`)\n   - Relationship-based authorization using OpenFGA\n   - Declarative authorization model (authorization-model.fga)\n   - Uses relationship tuples for permissions\n   - Supports complex relationship checks with contextual tuples\n\nBoth strategies implement the same authorization rules, allowing for performance comparisons.\n\n## Getting Started\n\n### Prerequisites\n\n- Node.js 18+\n- Docker and Docker Compose\n- Nx CLI (`npm install -g nx`)\n\n### Environment Setup\n\n1. Start the required services:\n\n```bash\ndocker compose --profile dev up -d\n```\n\nThis starts:\n\n- PostgreSQL database\n- OpenFGA authorization service\n- Ory Kratos identity server\n\n2. Set environment variables:\n\n```\nDATABASE_URL=postgres://postgres:postgres@localhost:5432/purrfect-sitter\nKRATOS_URL=http://localhost:4433\nOPENFGA_URL=http://localhost:8080\nOPENFGA_STORE_ID=\u003cstore_id\u003e\nAUTH_STRATEGY=db  # or 'openfga'\n```\n\n3. Run database migrations:\n\n```bash\nnpx nx run database:generate\nnpx nx run database:migrate\n```\n\n4. Start the development server:\n\n```bash\nnpx nx run purrfect-sitter:serve\n```\n\n## API Endpoints\n\nThe API follows RESTful principles and provides the following endpoints:\n\n### Cats\n\n- `GET /api/cats` - List all cats\n- `GET /api/cats/:id` - Get cat details\n- `POST /api/cats` - Create cat profile (authenticated)\n- `PUT /api/cats/:id` - Update cat profile (owner or admin)\n- `DELETE /api/cats/:id` - Delete cat profile (owner or admin)\n\n### Cat Sittings\n\n- `GET /api/cat-sittings` - List cat sittings (filtered by permissions)\n- `GET /api/cat-sittings/:id` - Get cat sitting details (owner, sitter, or admin)\n- `POST /api/cat-sittings` - Create cat sitting request (authenticated)\n- `PUT /api/cat-sittings/:id` - Update cat sitting (owner, sitter, or admin)\n- `PUT /api/cat-sittings/:id/status` - Update cat sitting status (owner or sitter)\n- `DELETE /api/cat-sittings/:id` - Delete cat sitting (owner or admin)\n\n### Reviews\n\n- `GET /api/reviews` - List reviews (public)\n- `GET /api/reviews/:id` - Get review details (author, subject, or admin)\n- `POST /api/reviews` - Create review (cat owner after completed sitting)\n- `PUT /api/reviews/:id` - Update review (author only)\n- `DELETE /api/reviews/:id` - Delete review (admin only)\n\n## Testing\n\n### Unit Testing\n\n- Run unit tests for a specific project:\n  ```bash\n  npx nx test \u003cproject-name\u003e\n  ```\n- Run tests with coverage:\n  ```bash\n  npx nx test \u003cproject-name\u003e --coverage\n  ```\n\n### E2E Testing\n\nThis project includes comprehensive end-to-end tests that validate both authorization strategies.\n\n#### Test Structure\n\nE2E tests are located in the `apps/purrfect-sitter-e2e/` directory:\n\n- `src/purrfect-sitter/` - Main test suites\n  - `cats/` - Tests for cat management APIs\n  - `cat-sittings/` - Tests for cat sitting APIs\n  - `reviews/` - Tests for review APIs\n- `src/support/` - Test utilities and setup\n\n#### Test Environment Setup\n\nE2E tests use a dedicated test environment with:\n\n- Test-specific Kratos configuration\n- Dedicated PostgreSQL database\n- Separate OpenFGA store\n\n#### Running E2E Tests\n\nRun E2E tests using the Makefile commands:\n\n```bash\n# Run with database strategy\nmake e2e-test-db\n\n# Run with OpenFGA strategy\nmake e2e-test-openfga\n\n# Run with both strategies sequentially\nmake e2e-test-all\n```\n\nOr directly with Nx:\n\n```bash\n# Set strategy via environment variable\nAUTH_STRATEGY=db npx nx e2e purrfect-sitter-e2e\n```\n\n## Performance Analysis\n\n### Authorization Benchmarking\n\nThis project includes tools for benchmarking and analyzing the performance differences between database query-based authorization and OpenFGA-based authorization.\n\n#### Benchmarking Scripts\n\nLocated in `tools/scripts/`:\n\n- `benchmark-auth-strategies.ts` - Runs identical scenarios against both authorization strategies and captures telemetry data.\n\n  - Creates users, cats, cat sittings, and reviews\n  - Executes three scenarios:\n    1. Simple case: View cat (public resource)\n    2. Medium case: Cat sitting management (create, update, status changes)\n    3. Complex case: Review management (nested authorization checks)\n  - Automatically cleans up all created resources\n\n- `trace-analyzer.ts` - Analyzes OpenTelemetry trace data from Zipkin:\n  - Fetches traces from Zipkin API\n  - Groups traces by scenario\n  - Calculates performance metrics for each scenario:\n    - Total execution time\n    - Total transaction time (end-to-end HTTP request duration)\n    - Operation count\n    - Time ratio between strategies\n    - Operation count ratio\n  - Aggregates metrics across iterations for better analysis\n  - Generates both detailed and aggregated CSV/JSON reports\n\n#### Running Benchmark Tests\n\n1. Ensure all services are running:\n\n   ```bash\n   make start-dev\n   ```\n\n2. Ensure the database is running and migrations are applied:\n\n   ```bash\n   npx nx run database:generate\n   DATABASE_URL=postgresql://dbuser:secret@localhost:5432/purrfect-sitter npx nx run database:migrate\n   ```\n\n3. Ensure the OpenFGA model is created:\n\n   ```bash\n   npx nx run purrfect-sitter:create-auth-model\n   ```\n\n4. Start the Purrfect Sitter application:\n\n   ```bash\n   AUTH_STRATEGY=openfga npx nx run purrfect-sitter:serve:local\n   ```\n\n5. Run the benchmark script:\n\n   ```bash\n   node --experimental-strip-types tools/scripts/benchmark-auth-strategies.ts\n   ```\n\n   This script:\n\n   - Creates test users (cat owner, cat sitter, admin)\n   - Sets up necessary data (cats, cat sittings)\n   - Executes multiple iterations of each scenario with headers for tracing\n   - Sends HTTP requests with `X-Benchmark-Scenario` headers to identify scenarios in traces\n\n6. Analyze the results:\n\n   ```bash\n   node --experimental-strip-types tools/scripts/trace-analyzer.ts\n   ```\n\n   This will:\n\n   - Fetch OpenFGA traces from Zipkin\n   - Calculate metrics for individual scenario iterations\n   - Aggregate metrics by scenario type across iterations\n   - Generate two report types:\n     - `auth-comparison-[timestamp].json/.csv` - Aggregated metrics with averages\n     - `auth-comparison-detailed-[timestamp].json/.csv` - Detailed per-iteration metrics\n\n#### Visualization\n\n- View traces in Zipkin UI (http://localhost:9411)\n- Examine generated CSV/JSON reports for quantitative comparison:\n  - Look at the `totalScenarioTime` field for end-to-end transaction times\n  - Compare metrics between different scenario types\n  - Analyze the aggregated reports for overall performance patterns\n- Use the data to create charts showing performance differences between strategies\n- Run benchmarks with both AUTH_STRATEGY=db and AUTH_STRATEGY=openfga to compare approaches\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgetlarge%2Fpurrfect-sitter","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgetlarge%2Fpurrfect-sitter","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgetlarge%2Fpurrfect-sitter/lists"}