skills/bratsos/polizy/polizy-patterns

polizy-patterns

SKILL.md

Polizy Implementation Patterns

Copy-paste patterns for common authorization scenarios.

When to Apply

  • User says "how do I implement X"
  • User says "give team access to project"
  • User says "make files inherit folder permissions"
  • User says "grant temporary access"
  • User says "revoke all permissions"
  • User wants to implement a specific authorization scenario

Pattern Selection Guide

Scenario Pattern Reference
Specific user → specific resource Direct Permissions DIRECT-PERMISSIONS.md
Team/group access Group Access GROUP-ACCESS.md
Folder/file inheritance Hierarchy HIERARCHY.md
Sensitive fields (salary, PII) Field-Level FIELD-LEVEL.md
Contractor/expiring access Time-Limited TIME-LIMITED.md
Removing access Revocation REVOCATION.md
Tenant isolation Multi-Tenant MULTI-TENANT.md

Pattern 1: Direct Permissions

Grant specific user access to specific resource.

// Grant permission
await authz.allow({
  who: { type: "user", id: "alice" },
  toBe: "owner",
  onWhat: { type: "document", id: "doc1" }
});

// Check permission
const canEdit = await authz.check({
  who: { type: "user", id: "alice" },
  canThey: "edit",
  onWhat: { type: "document", id: "doc1" }
});

Pattern 2: Team-Based Access

Grant access through group membership.

// 1. Add users to team
await authz.addMember({
  member: { type: "user", id: "alice" },
  group: { type: "team", id: "engineering" }
});

await authz.addMember({
  member: { type: "user", id: "bob" },
  group: { type: "team", id: "engineering" }
});

// 2. Grant team access to resource
await authz.allow({
  who: { type: "team", id: "engineering" },
  toBe: "editor",
  onWhat: { type: "project", id: "project1" }
});

// 3. Team members can now access
const canAliceEdit = await authz.check({
  who: { type: "user", id: "alice" },
  canThey: "edit",
  onWhat: { type: "project", id: "project1" }
}); // true

Schema requirement:

relations: {
  member: { type: "group" },  // Required!
  editor: { type: "direct" },
}

Pattern 3: Folder/File Hierarchy

Inherit permissions from parent resources.

// 1. Set up hierarchy
await authz.setParent({
  child: { type: "document", id: "doc1" },
  parent: { type: "folder", id: "folder1" }
});

// 2. Grant access at folder level
await authz.allow({
  who: { type: "user", id: "alice" },
  toBe: "viewer",
  onWhat: { type: "folder", id: "folder1" }
});

// 3. Document inherits folder permission
const canView = await authz.check({
  who: { type: "user", id: "alice" },
  canThey: "view",
  onWhat: { type: "document", id: "doc1" }
}); // true

Schema requirement:

relations: {
  parent: { type: "hierarchy" },  // Required!
  viewer: { type: "direct" },
},
hierarchyPropagation: {
  view: ["view"],  // CRITICAL: Without this, no inheritance!
}

Pattern 4: Field-Level Permissions

Protect sensitive fields within records.

// Grant general record access
await authz.allow({
  who: { type: "user", id: "employee" },
  toBe: "viewer",
  onWhat: { type: "profile", id: "emp123" }
});

// Grant specific field access
await authz.allow({
  who: { type: "user", id: "hr_manager" },
  toBe: "viewer",
  onWhat: { type: "profile", id: "emp123#salary" }
});

// Employee can view profile, but not salary
await authz.check({
  who: { type: "user", id: "employee" },
  canThey: "view",
  onWhat: { type: "profile", id: "emp123" }
}); // true

await authz.check({
  who: { type: "user", id: "employee" },
  canThey: "view",
  onWhat: { type: "profile", id: "emp123#salary" }
}); // false

// HR can view salary
await authz.check({
  who: { type: "user", id: "hr_manager" },
  canThey: "view",
  onWhat: { type: "profile", id: "emp123#salary" }
}); // true

Pattern 5: Temporary Access

Grant time-limited permissions.

// Access valid for 30 days
await authz.allow({
  who: { type: "user", id: "contractor" },
  toBe: "editor",
  onWhat: { type: "project", id: "project1" },
  when: {
    validSince: new Date(),
    validUntil: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000)
  }
});

// Scheduled future access
await authz.allow({
  who: { type: "user", id: "new_hire" },
  toBe: "viewer",
  onWhat: { type: "onboarding", id: "docs" },
  when: {
    validSince: new Date("2024-02-01")  // Starts Feb 1
  }
});

Pattern 6: Revocation

Remove permissions.

// Remove specific permission
await authz.disallowAllMatching({
  who: { type: "user", id: "bob" },
  was: "editor",
  onWhat: { type: "document", id: "doc1" }
});

// Remove all user permissions on a resource
await authz.disallowAllMatching({
  who: { type: "user", id: "bob" },
  onWhat: { type: "document", id: "doc1" }
});

// Remove all permissions on a resource (when deleting it)
await authz.disallowAllMatching({
  onWhat: { type: "document", id: "doc1" }
});

// Remove user from group
await authz.removeMember({
  member: { type: "user", id: "alice" },
  group: { type: "team", id: "engineering" }
});

Pattern 7: Listing Accessible Objects

Find what a user can access.

// List all documents alice can access
const result = await authz.listAccessibleObjects({
  who: { type: "user", id: "alice" },
  ofType: "document"
});

// Result:
// {
//   accessible: [
//     { object: { type: "document", id: "doc1" }, actions: ["edit", "view", "delete"] },
//     { object: { type: "document", id: "doc2" }, actions: ["view"] },
//   ]
// }

// Filter by action
const editableOnly = await authz.listAccessibleObjects({
  who: { type: "user", id: "alice" },
  ofType: "document",
  canThey: "edit"  // Only return editable documents
});

Pattern 8: Combining Patterns

Real apps often combine multiple patterns:

// Organizational structure (groups)
await authz.addMember({ member: alice, group: frontend });
await authz.addMember({ member: frontend, group: engineering });

// Resource hierarchy
await authz.setParent({ child: codeFile, parent: srcFolder });
await authz.setParent({ child: srcFolder, parent: projectRoot });

// Team access at project level
await authz.allow({ who: engineering, toBe: "editor", onWhat: projectRoot });

// Alice can now edit codeFile through:
// alice → member → frontend → member → engineering → editor → projectRoot ← parent ← srcFolder ← parent ← codeFile

await authz.check({ who: alice, canThey: "edit", onWhat: codeFile }); // true

Common Mistakes

Mistake Symptom Fix
Missing member: { type: "group" } addMember() throws Add group relation to schema
Missing parent: { type: "hierarchy" } setParent() throws Add hierarchy relation to schema
Missing hierarchyPropagation Parent permissions don't flow Add propagation config
Relation not in actionToRelations check() returns false Add relation to action's array
Checking wrong action check() returns false Verify action name matches schema

References

Each pattern has detailed documentation:

Related Skills

Weekly Installs
3
Repository
bratsos/polizy
GitHub Stars
6
First Seen
Feb 3, 2026
Installed on
opencode3
gemini-cli3
antigravity3
claude-code3
github-copilot3
cursor3