polizy-schema

Schema design guide for polizy authorization. Use when defining relations, actions, action mappings, hierarchy propagation, or modifying authorization models. Covers direct, group, and hierarchy relation types.

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "polizy-schema" with this command: npx skills add bratsos/polizy/bratsos-polizy-polizy-schema

Polizy Schema Design

The schema is the heart of polizy. It defines your authorization model: what relationships exist and what actions they enable.

When to Apply

  • User says "design permissions schema" or "define authorization model"
  • User asks "what relations do I need for X"
  • User says "add new relation" or "add new action"
  • User is confused about relation types (direct vs group vs hierarchy)
  • User wants to modify their existing schema
  • User asks about defineSchema or actionToRelations

Priority Table

PriorityDecisionImpact
CriticalChoose correct relation typesWrong type = broken inheritance
CriticalMap all actions to relationsUnmapped = always denied
ImportantConfigure hierarchyPropagationWithout it, no parent→child inheritance
ImportantUse semantic namesClarity for future maintainers
OptionalKeep schema minimalStart simple, expand as needed

Schema Structure

import { defineSchema } from "polizy";

const schema = defineSchema({
  // 1. Define relationship types
  relations: {
    owner: { type: "direct" },     // Direct permission
    editor: { type: "direct" },
    viewer: { type: "direct" },
    member: { type: "group" },     // Group membership
    parent: { type: "hierarchy" }  // Parent-child resources
  },

  // 2. Map actions to relations that grant them
  actionToRelations: {
    delete: ["owner"],
    edit: ["owner", "editor"],
    view: ["owner", "editor", "viewer"]
  },

  // 3. Optional: Define hierarchy propagation
  hierarchyPropagation: {
    view: ["view"],   // view on parent → view on child
    edit: ["edit"]    // edit on parent → edit on child
  }
});

Relation Types Quick Reference

TypePurposeExampleUse When
directUser → Resourcealice is owner of doc1Specific user needs specific resource access
groupUser → Group membershipalice is member of engineeringTeam-based access, organizational structure
hierarchyResource → Parent resourcedoc1's parent is folder1Folder/file, project/task, inherited permissions

See RELATION-TYPES.md for detailed explanations.

Common Schema Patterns

Basic Document Access

const schema = defineSchema({
  relations: {
    owner: { type: "direct" },
    editor: { type: "direct" },
    viewer: { type: "direct" },
  },
  actionToRelations: {
    delete: ["owner"],
    edit: ["owner", "editor"],
    view: ["owner", "editor", "viewer"],
  },
});

Team-Based Access

const schema = defineSchema({
  relations: {
    owner: { type: "direct" },
    editor: { type: "direct" },
    viewer: { type: "direct" },
    member: { type: "group" },  // Required for addMember()
  },
  actionToRelations: {
    manage: ["owner"],
    edit: ["owner", "editor"],
    view: ["owner", "editor", "viewer"],
  },
});

Hierarchical Resources (Folders/Files)

const schema = defineSchema({
  relations: {
    owner: { type: "direct" },
    editor: { type: "direct" },
    viewer: { type: "direct" },
    parent: { type: "hierarchy" },  // Required for setParent()
  },
  actionToRelations: {
    delete: ["owner"],
    edit: ["owner", "editor"],
    view: ["owner", "editor", "viewer"],
  },
  hierarchyPropagation: {
    view: ["view"],  // CRITICAL: Without this, no inheritance
    edit: ["edit"],
  },
});

Full-Featured Schema

const schema = defineSchema({
  relations: {
    // Direct permissions
    owner: { type: "direct" },
    editor: { type: "direct" },
    viewer: { type: "direct" },
    commenter: { type: "direct" },

    // Group membership
    member: { type: "group" },

    // Hierarchy
    parent: { type: "hierarchy" },
  },
  actionToRelations: {
    // Destructive
    delete: ["owner"],
    transfer: ["owner"],

    // Modification
    edit: ["owner", "editor"],
    comment: ["owner", "editor", "commenter"],

    // Read
    view: ["owner", "editor", "viewer", "commenter"],
  },
  hierarchyPropagation: {
    view: ["view"],
    edit: ["edit"],
    comment: ["comment"],
  },
});

Decision Guide: Which Relation Type?

Need to grant access to a specific user on a specific resource?
  → Use "direct" relation (owner, editor, viewer)

Need users to inherit access from a team/department?
  → Use "group" relation (member)
  → Add users to groups with addMember()
  → Grant group access with allow()

Need child resources to inherit parent permissions?
  → Use "hierarchy" relation (parent)
  → Set parent with setParent()
  → Configure hierarchyPropagation

Common Mistakes

MistakeSymptomFix
Missing relation in actionToRelationscheck() returns falseAdd relation to the action's array
No member: { type: "group" }addMember() throws errorAdd group relation to schema
No parent: { type: "hierarchy" }setParent() throws errorAdd hierarchy relation to schema
Missing hierarchyPropagationParent permissions don't flow to childrenAdd hierarchyPropagation config
Using generic names ("access")Can't distinguish read/writeUse semantic names (viewer, editor)

Schema Evolution

When adding to an existing schema:

// v1: Basic
const schemaV1 = defineSchema({
  relations: {
    owner: { type: "direct" },
    viewer: { type: "direct" },
  },
  actionToRelations: {
    edit: ["owner"],
    view: ["owner", "viewer"],
  },
});

// v2: Add editor role
const schemaV2 = defineSchema({
  relations: {
    owner: { type: "direct" },
    editor: { type: "direct" },  // NEW
    viewer: { type: "direct" },
  },
  actionToRelations: {
    edit: ["owner", "editor"],  // UPDATED
    view: ["owner", "editor", "viewer"],  // UPDATED
  },
});

// v3: Add groups
const schemaV3 = defineSchema({
  relations: {
    owner: { type: "direct" },
    editor: { type: "direct" },
    viewer: { type: "direct" },
    member: { type: "group" },  // NEW
  },
  actionToRelations: {
    edit: ["owner", "editor"],
    view: ["owner", "editor", "viewer"],
  },
});

Important: Existing tuples remain valid when you add new relations/actions. No migration needed.

Related Skills

References

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

polizy-patterns

No summary provided by upstream source.

Repository SourceNeeds Review
General

polizy

No summary provided by upstream source.

Repository SourceNeeds Review
General

polizy-troubleshooting

No summary provided by upstream source.

Repository SourceNeeds Review
General

polizy-storage

No summary provided by upstream source.

Repository SourceNeeds Review