Back to skills
extension
Category: Development & EngineeringNo API key required

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.

personAuthor: jakexiaohubgithub

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