AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
SKILL verified MIT Self-run

Descope Fga Schema

skill-descope-skills-descope-fga-schema · by descope

Author, edit, or apply a Descope FGA schema using the ReBAC/ABAC DSL. Use this skill whenever the user asks to create a new FGA schema, modify an existing one, add types/relations/permissions/conditions, review an authorization model, or apply schema changes to a Descope project. Trigger even if the user says things like "set up authorization", "define roles and permissions", "add team-based acce…

No reviews yet
0 installs
25 views
0.0% view→install

Install

$ agentstack add skill-descope-skills-descope-fga-schema

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/skill-descope-skills-descope-fga-schema)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
3mo ago

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Descope Fga Schema? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

FGA DSL Authoring

Help the user design and apply Descope FGA schemas. The workflow is: understand the requirement → draft the DSL → validate via dry run → show the user + any data loss warnings → get confirmation → apply.

MCP Setup — check first, stop if missing

Before doing anything else, check whether the Descope Management MCP is connected by looking for tools whose names contain FGASchema or DryRunSchema (e.g. mcp__descope__DryRunSchema). The exact prefix depends on how the user installed the MCP, but the operation IDs are DryRunSchema, CreateFGASchema, and GetFGASchema.

If the tools are not found: output only the message below, then end your turn. Do not generate a schema, do not say "here's what I'll apply once connected", do not do any design work, do not continue:

> The Descope Management MCP is required. If not yet installed, install and authorize it, then restart Claude Code and re-run /descope-fga-schema. > If already installed, it may need authorization. Authorize the Descope MCP, then restart Claude Code and re-run /descope-fga-schema.

If the tools are found: call GetFGASchema immediately as a connectivity probe before doing any other work. If this call returns an authorization error, output only the message below and end your turn:

> The Descope MCP is installed but not authorized. Authorize it, restart Claude Code, and re-run /descope-fga-schema.

All FGA operations go through MCP tool calls — never make raw HTTP requests yourself.

Once connected, use the GetFGASchema tool to read the current schema before editing — always do this when the user asks to modify an existing schema.

Grammar

Every schema begins with exactly:

model AuthZ 1.0

No other name or version is accepted by the API.

Full structure:

model AuthZ 1.0

[constraint [:][(args...)]]*
[condition () {  }]*

type 
  [relation :  [| ]* [with ]]*
  [permission :  [with ]]*

Keywords: model type relation permission condition constraint with

Operators:

  • Permission expr: | union, & intersect, - subtract. Mix operators with parens: a | (b - c)
  • Set arrow: relation.permission — walks a stored relation to reach the subject's own permissions (e.g. parent.can_view)
  • Target set: Type#relation — see dedicated section below
  • with clause (relations and permissions): & AND, | OR, ! NOT, parens: with A & (B | !C). Conditions are evaluated at check timewith gates whether the relation or permission counts during evaluation. Only one with clause is allowed per relation or permission definition — combine multiple conditions inside it with &/|/!.

No comments — the DSL parser has no comment token.

Naming: PascalCase for Types, Conditions, Constraints. snake_case for relations and permissions.

Target Set Pattern (Type#relation)

When a relation should be held by members of a group (e.g. "any member of this Team"), put Type#relation directly in the relation definition. This stores individual member subjects — the right granularity for permission checks.

The indirect way — storing the group itself and deriving membership via a permission — produces correct relation expansion, but it introduces a contributor_team relation with no semantic meaning of its own. The only meaningful entity is the individual member. The target set syntax is more concise and directly expresses the intent.

Avoid (extra relation with no semantic value):

type Repository
  relation contributor_team: Team
  permission contributor: contributor_team.member

Prefer (concise, direct):

type Repository
  relation contributor: Team#member

You can mix direct subjects with target set subjects: relation editor: User | Team#member

ABAC Anti-Patterns to Avoid

Never use a "blocked" relation + subtraction to express a condition

with conditions are evaluated at check time — when a permission check is made against the context passed in the request. Relations are always stored unconditionally; the condition only affects whether the relation counts during permission evaluation.

The blocked relation + subtraction pattern is wrong because it requires manually maintaining a separate set of blocked edges in the DB for every excluded user. It's the wrong tool: use with !Condition on the relation that grants access instead — it is evaluated automatically at check time with no extra stored relations.

// NEVER do this — requires maintaining a separate "blocked" edge per user in the DB
relation creator: User
relation blocked: User with NorthKorea
permission can_delete: creator - blocked

// Right — condition evaluated automatically at check time; no extra edges
relation creator: User with !NorthKorea
permission can_delete: creator

Don't write custom CEL when a built-in constraint covers it

A custom condition that checks a numeric range is just reinventing NumRange (or NumAtLeast/NumAtMost). Built-in constraints are more concise, less error-prone, and form a common vocabulary that makes schemas easier for both humans and agents to read and reason about. Use them.

Wrong:

condition DuringBusinessHours(seconds_since_midnight int) { seconds_since_midnight >= 32400 && seconds_since_midnight  **Warning: applying this schema will permanently delete all stored relations of these types:**
> - `folder#viewer`
> - `doc#editor`
>
> This cannot be undone. Confirm to proceed.

If `hasDeletes` is false, just show the schema and ask for confirmation.

### Step 3 — Get confirmation

End your turn after Step 2. Do not call `CreateFGASchema` in the same turn as `DryRunSchema` — the user must see the schema and any deletion warnings before you proceed. Wait for the user to reply with explicit approval ("yes", "apply", "go ahead", etc.).

### Step 4 — Apply

Before calling `CreateFGASchema`, verify all three of the following are true:
- You showed the full DSL in a code block in a prior turn (not in this turn)
- You surfaced all deletion warnings from the dry-run response (or confirmed `hasDeletes` was false)
- The user's most recent message is an explicit approval in response to your confirmation prompt

If any of these are not true, do not call `CreateFGASchema`. Go back to Step 2 instead.

When all three are confirmed, call `CreateFGASchema` with the same DSL from the dry run. Confirm success to the user.

The reason this gate matters: `CreateFGASchema` is irreversible. Relation tuples deleted by a schema change cannot be recovered. Skipping confirmation is never safe, even when the change looks minor.

## Examples

### Basic ReBAC with hierarchy

model AuthZ 1.0

type User

type Folder

type Doc relation owner: User relation parent: Folder permission canview: owner | parent.owner permission canedit: owner


### Group membership via target set

model AuthZ 1.0

type User

type Team relation member: User

type Repository relation owner: User relation contributor: User | Team#member permission canpush: owner | contributor permission canread: can_push


### ABAC: time-gated access

model AuthZ 1.0

constraint ShiftHours:NumRange

type User

type PatientRecord relation viewer: User with ShiftHours relation owner: User permission can_view: viewer | owner


### Reused constraint kind with aliases — and `with` on a permission

model AuthZ 1.0

constraint FiveEyes:GeoCountry("US","GB","CA","AU","NZ") constraint Sanction:GeoCountry("KP","IR","SY","RU") constraint OfficeOnly:IpRange("10.0.0.0/8")

type User

type Resource relation allowed: User with FiveEyes & !Sanction relation owner: User permission canaccess: allowed permission candelete: owner with OfficeOnly


`allowed` carries geo-gating on the relation — it applies to every permission that uses `allowed`. `can_delete` uses `with` on the permission itself so the IP restriction scopes only deletion, not access.

### Nested permissions with `with` — conditions stack

model AuthZ 1.0

constraint BusinessHours:NumRange(32400, 61200) constraint OfficeNetwork:IpRange("10.0.0.0/8")

type User

type Document relation reader: User permission canread: reader with BusinessHours permission canedit: can_read with OfficeNetwork


`can_edit` requires both `BusinessHours` (from `can_read`) **and** `OfficeNetwork` (from `can_edit`'s own `with`). Both conditions must be true at check time — `with` clauses on nested permissions accumulate.

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [descope](https://github.com/descope)
- **Source:** [descope/skills](https://github.com/descope/skills)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.