{"id":31852179,"url":"https://github.com/yahiaosama/authz-schema-sync-check","last_synced_at":"2026-01-26T12:16:33.398Z","repository":{"id":289872552,"uuid":"971274299","full_name":"yahiaosama/authz-schema-sync-check","owner":"yahiaosama","description":"Authz Schema Sync Checker","archived":false,"fork":false,"pushed_at":"2025-09-17T15:23:31.000Z","size":157,"stargazers_count":2,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-09-17T17:52:04.017Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/yahiaosama.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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":"2025-04-23T09:18:17.000Z","updated_at":"2025-09-17T15:22:38.000Z","dependencies_parsed_at":"2025-04-25T14:38:25.425Z","dependency_job_id":"cbdc06d8-3d9c-422a-ba1d-37e2947cc7e6","html_url":"https://github.com/yahiaosama/authz-schema-sync-check","commit_stats":null,"previous_names":["yahiaosama/authz-schema-sync-check"],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/yahiaosama/authz-schema-sync-check","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yahiaosama%2Fauthz-schema-sync-check","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yahiaosama%2Fauthz-schema-sync-check/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yahiaosama%2Fauthz-schema-sync-check/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yahiaosama%2Fauthz-schema-sync-check/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/yahiaosama","download_url":"https://codeload.github.com/yahiaosama/authz-schema-sync-check/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yahiaosama%2Fauthz-schema-sync-check/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279011361,"owners_count":26084937,"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","status":"online","status_checked_at":"2025-10-12T02:00:06.719Z","response_time":53,"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":"2025-10-12T13:01:13.974Z","updated_at":"2025-10-12T13:02:05.820Z","avatar_url":"https://github.com/yahiaosama.png","language":"Python","funding_links":[],"categories":["Clients"],"sub_categories":["Third-party Libraries"],"readme":"# authz-schema-sync-check\n\nA pre-commit hook for generating and syncing type definitions from SpiceDB schema.\n\n## Overview\n\nThis package provides a pre-commit hook that generates type definitions from a SpiceDB schema file (`schema.zed`) and ensures they are in sync with output files. It supports generating both Python and TypeScript type definitions, and can be extended to support other languages through custom templates. It uses Git to compare the generated code with the existing code and can automatically apply changes.\n\n## Installation\n\nThis package is built with Poetry and should be used with Poetry:\n\n```bash\n# For development\ngit clone https://github.com/yahiaosama/authz-schema-sync-check.git\ncd authz-schema-sync-check\npoetry install\n```\n\n## Usage\n\n### As a Pre-commit Hook\n\nAdd the following to your `.pre-commit-config.yaml` file to use it exactly as in the backend repository:\n\n```yaml\nrepos:\n  - repo: https://github.com/yahiaosama/authz-schema-sync-check\n    rev: v0.2.0\n    hooks:\n      - id: authz-schema-sync-check\n        args: [\n          \"--schema\", \"backend/app/infra/authz/schema.zed\",\n          \"--outputs\", \n            \"backend/app/infra/authz/resources.py\", \n            \"frontend-apps/packages/shared/src/authz/resources.ts\",\n          \"--verbose\",\n          \"--colorized-diff=true\",\n          \"--auto-fix\"\n        ]\n        files: 'backend/app/infra/authz/schema\\.zed$|backend/app/infra/authz/resources\\.py$|frontend-apps/packages/shared/src/authz/resources\\.ts$'\n        pass_filenames: false\n```\n\nAvailable options:\n- `--schema`: Path to the schema.zed file (default: `schema.zed`)\n- `--outputs`: Output paths, optionally with template names in format 'output_path[:template_name]' (required)\n  - For `.py` files, the default template is `default_types.py.jinja`\n  - For `.ts` files, the default template is `default_types.ts.jinja`\n  - For other file types, you must specify the template explicitly\n- `--auto-fix`: Automatically apply changes if out of sync\n- `--verbose`: Enable verbose output\n- `--colorized-diff`: Enable or disable colorized diff output (true/false, default: true)\n\nThe `files` pattern determines when the hook runs. In the example above, it will run whenever:\n- The `schema.zed` file is modified\n- The `resources.py` file is modified\n- The `resources.ts` file is modified\n\n**Important Note**: The hook will fail if any output file doesn't exist, even with `--auto-fix` enabled. With `--auto-fix`, it will create the file but still fail, requiring you to review and commit the newly created file in a separate step. This is an intentional security feature to ensure that generated files are always explicitly committed by the user, preventing accidental inclusion of unreviewed generated code.\n\n### As a Command-line Tool\n\nYou can also use the package as a command-line tool:\n\n```bash\n# Generate a single output with default template (inferred from file extension)\npoetry run authz-schema-sync-check --schema path/to/schema.zed --outputs \"path/to/resources.py\"\n\n# Generate multiple outputs with default templates\npoetry run authz-schema-sync-check --schema path/to/schema.zed --outputs \\\n  \"path/to/resources.py\" \\\n  \"path/to/resources.ts\"\n\n# Generate outputs with explicit templates\npoetry run authz-schema-sync-check --schema path/to/schema.zed --outputs \\\n  \"path/to/resources.py:default_types.py.jinja\" \\\n  \"path/to/resources.ts:default_types.ts.jinja\"\n\n# Automatically apply changes\npoetry run authz-schema-sync-check --schema path/to/schema.zed --outputs \\\n  \"path/to/resources.py\" \\\n  --auto-fix\n\n# Check with colorized diff disabled\npoetry run authz-schema-sync-check --schema path/to/schema.zed --outputs \\\n  \"path/to/resources.py\" \\\n  --colorized-diff=false\n```\n\nOptions:\n- `--schema`: Path to the schema.zed file (default: `schema.zed`)\n- `--outputs`: Output paths, optionally with template names in format 'output_path[:template_name]' (required)\n  - For `.py` files, the default template is `default_types.py.jinja`\n  - For `.ts` files, the default template is `default_types.ts.jinja`\n  - For other file types, you must specify the template explicitly\n- `--auto-fix`: Automatically apply changes if out of sync\n- `--verbose`: Enable verbose output\n- `--colorized-diff`: Enable or disable colorized diff output (true/false, default: true)\n\n## Generated Type Definitions\n\nThe package can generate type definitions in multiple languages based on the schema. The available templates are:\n\n- `default_types.py.jinja`: Generates Python type definitions\n- `default_types.ts.jinja`: Generates TypeScript type definitions\n\nYou can also create your own templates in the `templates` directory.\n\n### Python Type Definitions\n\nThe Python template generates the following:\n\n1. **Permission Type Aliases**: Type literals for permissions specific to each resource type.\n2. **Resource Base Class**: A generic base class for all resources.\n3. **Resource Classes**: Classes for each object type defined in the schema, with a `permission_type` class variable.\n\n### Example\n\n#### schema.zed\n\n```\ndefinition user {\n    relation organization: organization\n    relation self: user\n\n    permission read = self\n    permission update = self\n    permission make_admin = organization-\u003eadministrate\n    permission revoke_admin = organization-\u003eadministrate\n}\n\ndefinition group {\n    relation organization: organization\n    relation member: user | group#member\n\n    permission edit_members = organization-\u003eadministrate\n}\n\ndefinition organization {\n    relation admin: user\n    relation member: user | group#member\n\n    permission administrate = admin\n    permission read = member\n}\n```\n\n#### Generated Python Output (resources.py)\n\n```python\n\"\"\"\nGENERATED CODE - DO NOT EDIT MANUALLY\nThis file is generated from schema.zed and should not be modified directly.\n\"\"\"\n\nfrom typing import Generic, Literal, TypeVar\n\n# Permission type aliases for each resource type\nUserPermission = Literal[\"read\", \"update\", \"make_admin\", \"revoke_admin\"]\nGroupPermission = Literal[\"edit_members\"]\nOrganizationPermission = Literal[\"administrate\", \"read\"]\n\n# Type variable for permission literals\nP = TypeVar(\"P\", bound=str)\n\n# Base resource class\nclass Resource(Generic[P]):\n    \"\"\"Base class for all resources with typed permissions.\"\"\"\n\n    def __init__(self, id: str, resource_type: str):\n        self.id = id\n        self.type = resource_type\n\n# Resource classes with their specific permission types\nclass User(Resource[UserPermission]):\n    \"\"\"User resource from schema.zed\"\"\"\n\n    # Set the permission type for this resource\n    permission_type = UserPermission\n\n    def __init__(self, id: str):\n        super().__init__(id, \"user\")\n\nclass Group(Resource[GroupPermission]):\n    \"\"\"Group resource from schema.zed\"\"\"\n\n    # Set the permission type for this resource\n    permission_type = GroupPermission\n\n    def __init__(self, id: str):\n        super().__init__(id, \"group\")\n\nclass Organization(Resource[OrganizationPermission]):\n    \"\"\"Organization resource from schema.zed\"\"\"\n\n    # Set the permission type for this resource\n    permission_type = OrganizationPermission\n\n    def __init__(self, id: str):\n        super().__init__(id, \"organization\")\n\n# Note: snake_case resource names are converted to CamelCase\n# For example, table_view would become TableView\n```\n\n## Development\n\n### Setup\n\n1. Clone the repository:\n   ```bash\n   git clone https://github.com/yahiaosama/authz-schema-sync-check.git\n   cd authz-schema-sync-check\n   ```\n\n2. Install dependencies with Poetry:\n   ```bash\n   poetry install\n   ```\n\n### Running Tests\n\n```bash\npoetry run pytest\n```\n\n### TypeScript Type Definitions\n\nThe TypeScript template generates a discriminated union type that represents all valid resource-permission combinations from the schema.\n\n#### Generated TypeScript Output (resources.ts)\n\n```typescript\n/**\n * GENERATED CODE - DO NOT EDIT MANUALLY\n * This file is generated from schema.zed and should not be modified directly.\n */\n\n/**\n * Type representing all valid resource-permission combinations\n * from the SpiceDB schema.\n */\nexport type ResourcePermission = \n  | { resource: \"user\"; permission: \"read\" | \"update\" | \"make_admin\" | \"revoke_admin\"; resourceId: string | number }\n  | { resource: \"group\"; permission: \"edit_members\"; resourceId: string | number }\n  | { resource: \"organization\"; permission: \"administrate\" | \"read\"; resourceId: string | number };\n```\n\nThis TypeScript type ensures that only valid resource-permission combinations can be used at compile time. For example:\n\n```typescript\n// Valid combinations\nconst valid1: ResourcePermission = { resource: \"user\", permission: \"read\", resourceId: \"user-123\" };\nconst valid2: ResourcePermission = { resource: \"organization\", permission: \"administrate\", resourceId: 456 };\n\n// Invalid combinations - TypeScript error\nconst invalid1: ResourcePermission = { resource: \"user\", permission: \"administrate\", resourceId: \"user-123\" }; // Error\nconst invalid2: ResourcePermission = { resource: \"invalid\", permission: \"read\", resourceId: 789 }; // Error\n```\n\n## Troubleshooting\n\n### Missing Output File\n\nIf you see an error like:\n\n```\nError processing path/to/resources.py: Output file does not exist\n```\n\nThis means the output file doesn't exist yet. Run the hook with `--auto-fix` to create it:\n\n```bash\npoetry run authz-schema-sync-check --schema path/to/schema.zed --outputs \"path/to/resources.py\" --auto-fix\n```\n\nThe hook will create the file but still fail with an error like:\n\n```\nError processing path/to/resources.py: Output file did not exist but has been created\nPlease review and commit the newly created file: path/to/resources.py\n```\n\nThis is intentional - you need to review the generated file and commit it manually. This ensures that generated files are always explicitly reviewed before being committed.\n\n### Files Out of Sync\n\nIf you see an error like:\n\n```\nError processing path/to/resources.py: File is out of sync with schema\n```\n\nThis means you've modified the schema.zed file but haven't updated the output file. Run the hook with `--auto-fix` to update it:\n\n```bash\npoetry run authz-schema-sync-check --schema path/to/schema.zed --outputs \"path/to/resources.py\" --auto-fix\n```\n\nThen review the changes and commit them.\n\n### Template Not Found\n\nIf you see an error like:\n\n```\nError processing path/to/resources.py: Template 'nonexistent.jinja' not found\n```\n\nThis means the specified template doesn't exist. Make sure the template exists in the `templates` directory.\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyahiaosama%2Fauthz-schema-sync-check","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fyahiaosama%2Fauthz-schema-sync-check","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyahiaosama%2Fauthz-schema-sync-check/lists"}