{
  "slug": "code/authz-spicedb",
  "title": "Authorization with SpiceDB",
  "description": "Relationship-based authorization for Cuitty Code repositories, apps, and Registry integration.",
  "url": "https://cuitty.com/docs/code/authz-spicedb",
  "markdown_url": "https://cuitty.com/docs/code/authz-spicedb.md",
  "json_url": "https://cuitty.com/docs/code/authz-spicedb.json",
  "frontmatter": {
    "title": "Authorization with SpiceDB",
    "description": "Relationship-based authorization for Cuitty Code repositories, apps, and Registry integration.",
    "order": 15,
    "section": "Code",
    "updatedAt": "2026-06-09"
  },
  "headings": [
    {
      "depth": 2,
      "slug": "required-services",
      "text": "Required services"
    },
    {
      "depth": 2,
      "slug": "environment-variables",
      "text": "Environment variables"
    },
    {
      "depth": 2,
      "slug": "schema-and-object-types",
      "text": "Schema and object types"
    },
    {
      "depth": 2,
      "slug": "permissions-model",
      "text": "Permissions model"
    },
    {
      "depth": 2,
      "slug": "outbox-statuses",
      "text": "Outbox statuses"
    },
    {
      "depth": 2,
      "slug": "replay-and-reconciliation",
      "text": "Replay and reconciliation"
    },
    {
      "depth": 2,
      "slug": "failure-modes-and-recovery",
      "text": "Failure modes and recovery"
    },
    {
      "depth": 2,
      "slug": "related-pages",
      "text": "Related pages"
    }
  ],
  "body_markdown": "Cuitty Code uses SpiceDB for relationship-based authorization across repositories, organizations, apps, installs, and package integration points. The database remains the source of metadata, while SpiceDB answers permission checks. Standalone Cuitty Registry authorization is documented separately in [Registry authorization](/docs/registry/authz).\n\n## Required services\n\n- Cuitty Code API.\n- SpiceDB reachable from the API.\n- Database with the `authz_outbox` migration applied.\n- A worker path that drains relationship writes from the outbox.\n\n## Environment variables\n\nProduction deployments should resolve the preshared key through Cuitty Safe:\n\n```dotenv\nSPICEDB_ENDPOINT=https://spicedb.example.com:50051\nSPICEDB_PRESHARED_KEY=cuitty-safe:acme/prod/spicedb-preshared-key\nAUTH_ISSUER=https://auth.example.com\nAUTH_CLIENT_ID=cuitty-git\n```\n\nFor an isolated local development SpiceDB only, use a disposable placeholder value:\n\n```dotenv\nSPICEDB_ENDPOINT=http://localhost:50051\nSPICEDB_PRESHARED_KEY=<local-dev-only-spicedb-key>\nAUTH_ISSUER=http://localhost:7705\nAUTH_CLIENT_ID=cuitty-code\n```\n\nUse TLS and Safe-managed secret references for production SpiceDB deployments. Do not promote the local placeholder into shared env files, CI, or self-hosted production configuration.\n\n## Schema and object types\n\nLoad the schema before API writes:\n\n```bash\nzed schema write spicedb/schema.zed\n```\n\nRepresentative object types include:\n\n- `user`\n- `organization`\n- `org_invite`\n- `account_slug`\n- `repository`\n- `app_listing`\n- `app_installation`\n- `code_app`\n- `code_app_installation`\n- `code_app_grant`\n- `package`\n- `code_package`\n- `registry_namespace` when Registry integration is enabled\n- `registry_package` when Registry integration is enabled\n\nVerify representative permissions with known local data:\n\n```bash\nzed permission check user:alice read repository:acme/demo\nzed permission check user:alice view package:acme/npm/acme-widget\nzed permission check user:alice install app_listing:acme/review-bot\n```\n\n## Permissions model\n\nSecurity-expanding writes, such as creating public visibility, granting install permission, or publishing package access, should fail closed if SpiceDB writes cannot be committed. Security-reducing writes, such as revoking access or making a package private, should continue to be retried until the graph reflects the database state.\n\nPrivate apps and packages may return `404` to callers without view permission. Authenticated callers with partial permission may receive `403` for actions such as publish, install, or settings updates.\n\n## Outbox statuses\n\nAuthorization relationship writes are recorded in `authz_outbox` with these statuses:\n\n- `pending`: queued for dispatch.\n- `processing`: claimed by a dispatcher.\n- `succeeded`: written to SpiceDB.\n- `failed_retryable`: failed but should be retried.\n- `failed_terminal`: failed in a way that needs operator inspection.\n\nInspect stuck rows directly when operational tooling is not available:\n\n```sql\nSELECT id, operation_kind, resource_kind, resource_id, status, attempts, last_error\nFROM authz_outbox\nWHERE status IN ('pending', 'processing', 'failed_retryable', 'failed_terminal')\nORDER BY created_at ASC\nLIMIT 50;\n```\n\n## Replay and reconciliation\n\nReplay retryable relationship writes with the deployment's authz dispatcher or maintenance command. If the deployment exposes only SQL access, mark stale `processing` rows back to `pending` after confirming no dispatcher is running, then restart the API or worker that drains the outbox.\n\n```sql\nUPDATE authz_outbox\nSET status = 'pending'\nWHERE status = 'processing'\n  AND updated_at < datetime('now', '-15 minutes');\n```\n\nAfter replay, spot-check resource permissions with `zed permission check` and compare database visibility against SpiceDB relationships.\n\n## Failure modes and recovery\n\n- SpiceDB unavailable: pause security-expanding app, package-target, and transfer writes; restore SpiceDB; drain the outbox.\n- Schema not loaded: re-run `zed schema write spicedb/schema.zed` and retry failed rows.\n- Retryable backlog: inspect `last_error`, fix connectivity or schema drift, and replay.\n- Terminal failures: compare `payload_json` with the current schema and repair the row or resource manually.\n\n## Related pages\n\n- [Cuitty Code Apps](/docs/code/apps)\n- [Registry authorization](/docs/registry/authz)\n- [App execution with Airflow](/docs/code/app-execution-airflow)\n- [Operator runbook](/docs/code/operator-runbook)",
  "links_out": [
    "/docs/registry/authz",
    "/docs/code/apps",
    "/docs/code/app-execution-airflow",
    "/docs/code/operator-runbook"
  ]
}