polizy-patterns

Implementation patterns for polizy authorization. Use when implementing team access, folder inheritance, field-level permissions, temporary access, revocation, or any specific authorization scenario.

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-patterns" with this command: npx skills add bratsos/polizy/bratsos-polizy-polizy-patterns

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

ScenarioPatternReference
Specific user → specific resourceDirect PermissionsDIRECT-PERMISSIONS.md
Team/group accessGroup AccessGROUP-ACCESS.md
Folder/file inheritanceHierarchyHIERARCHY.md
Sensitive fields (salary, PII)Field-LevelFIELD-LEVEL.md
Contractor/expiring accessTime-LimitedTIME-LIMITED.md
Removing accessRevocationREVOCATION.md
Tenant isolationMulti-TenantMULTI-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

MistakeSymptomFix
Missing member: { type: "group" }addMember() throwsAdd group relation to schema
Missing parent: { type: "hierarchy" }setParent() throwsAdd hierarchy relation to schema
Missing hierarchyPropagationParent permissions don't flowAdd propagation config
Relation not in actionToRelationscheck() returns falseAdd relation to action's array
Checking wrong actioncheck() returns falseVerify action name matches schema

References

Each pattern has detailed documentation:

Related Skills

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-storage

No summary provided by upstream source.

Repository SourceNeeds Review
General

polizy-schema

No summary provided by upstream source.

Repository SourceNeeds Review
General

polizy

No summary provided by upstream source.

Repository SourceNeeds Review
General

polizy-setup

No summary provided by upstream source.

Repository SourceNeeds Review