Skip to content
polizy-troubleshooting logo

Polizy Troubleshooting

polizy-troubleshooting

Debug and fix polizy authorization issues. Use when permission checks fail unexpectedly, errors occur, or authorization behavior is confusing. Covers check algorithm, common issues, and anti-patterns.

NeverSight/skills_feed0installs215starsOther

SKILL.md

Full skill instructions

Polizy Troubleshooting

Debug authorization issues when things don't work as expected.

When to Apply

  • User says "permission check not working"
  • User says "user can't access X but should"
  • Error messages from polizy
  • User confused about why authorization behaves a certain way
  • check() returns false unexpectedly

Quick Diagnosis Flowchart

check() returns false unexpectedly
         │
         ▼
Is the relation in actionToRelations?
    │           │
   NO           YES
    │            │
    ▼            ▼
ADD IT      Is there a group relation?
             │           │
            NO           YES
             │            │
             ▼            ▼
    (Direct check)    Is user in group?
             │            │
             ▼           NO → Check addMember()
    Is tuple           YES
    present?            │
       │                ▼
      NO              Does group have permission?
       │                │
       ▼               NO → Check group's allow()
    Add with          YES
    allow()            │
                       ▼
                  Check depth limit

Common Issues

1. Relation Not Mapped to Action

Symptom: check() returns false even with permission granted.

// Schema
actionToRelations: {
  view: ["viewer"],  // "editor" missing!
  edit: ["editor"],
}

// Grant
await authz.allow({ who: alice, toBe: "editor", onWhat: doc });

// Check
await authz.check({ who: alice, canThey: "view", onWhat: doc }); // false!

Fix: Add relation to action's array:

actionToRelations: {
  view: ["viewer", "editor"],  // Now editors can view
  edit: ["editor"],
}

2. Missing Group Relation

Symptom: addMember() throws error.

// Schema missing group type
relations: {
  viewer: { type: "direct" },
}

await authz.addMember({ member: alice, group: team });
// Error: No group relation defined in schema

Fix: Add group relation:

relations: {
  viewer: { type: "direct" },
  member: { type: "group" },  // Add this
}

3. Missing Hierarchy Propagation

Symptom: Parent permission doesn't flow to children.

// Schema
relations: {
  parent: { type: "hierarchy" },
  viewer: { type: "direct" },
},
// Missing hierarchyPropagation!

await authz.setParent({ child: doc, parent: folder });
await authz.allow({ who: alice, toBe: "viewer", onWhat: folder });
await authz.check({ who: alice, canThey: "view", onWhat: doc }); // false!

Fix: Add hierarchyPropagation:

hierarchyPropagation: {
  view: ["view"],  // Now view propagates
}

4. User Not in Group

Symptom: Group has permission but user can't access.

Debug:

// Check group membership
const memberships = await authz.listTuples({
  subject: { type: "user", id: "alice" },
  relation: "member",
});
console.log("Alice's groups:", memberships);

Fix: Add user to group:

await authz.addMember({ member: alice, group: team });

5. Max Depth Exceeded

Symptom: Deep group chain returns false silently.

Detect:

const authz = new AuthSystem({
  storage,
  schema,
  throwOnMaxDepth: true,  // Throws instead of silent false
});

try {
  await authz.check({ who: alice, canThey: "view", onWhat: doc });
} catch (error) {
  if (error instanceof MaxDepthExceededError) {
    console.log("Depth exceeded at:", error.depth);
  }
}

Fix: Increase depth or reduce nesting:

const authz = new AuthSystem({
  storage,
  schema,
  defaultCheckDepth: 20,  // Increase from default 10
});

6. Time-Based Condition Not Valid

Symptom: Permission granted with when but check fails.

Debug:

const tuples = await authz.listTuples({
  subject: alice,
  object: doc,
});

for (const tuple of tuples) {
  console.log("Condition:", tuple.condition);
  if (tuple.condition?.validSince) {
    console.log("Starts:", tuple.condition.validSince);
  }
  if (tuple.condition?.validUntil) {
    console.log("Expires:", tuple.condition.validUntil);
  }
}

Common causes:

  • validSince is in the future
  • validUntil is in the past

Debugging Techniques

1. List All Tuples for Subject

const tuples = await authz.listTuples({
  subject: { type: "user", id: "alice" },
});

console.log("Alice's permissions:");
for (const tuple of tuples) {
  console.log(`  ${tuple.relation} on ${tuple.object.type}:${tuple.object.id}`);
}

2. List All Tuples for Object

const tuples = await authz.listTuples({
  object: { type: "document", id: "doc1" },
});

console.log("Permissions on doc1:");
for (const tuple of tuples) {
  console.log(`  ${tuple.subject.type}:${tuple.subject.id} is ${tuple.relation}`);
}

3. Trace Group Membership

async function traceGroupPath(userId: string) {
  const user = { type: "user", id: userId };
  const groups: string[] = [];

  const directMemberships = await authz.listTuples({
    subject: user,
    relation: "member",
  });

  for (const tuple of directMemberships) {
    groups.push(`${tuple.object.type}:${tuple.object.id}`);

    // Check nested groups
    const nestedMemberships = await authz.listTuples({
      subject: tuple.object,
      relation: "member",
    });

    for (const nested of nestedMemberships) {
      groups.push(`  → ${nested.object.type}:${nested.object.id}`);
    }
  }

  return groups;
}

console.log("Group path:", await traceGroupPath("alice"));

4. Trace Hierarchy Path

async function traceHierarchyPath(objectType: string, objectId: string) {
  const path: string[] = [`${objectType}:${objectId}`];
  let current = { type: objectType, id: objectId };

  while (true) {
    const parentTuples = await authz.listTuples({
      subject: current,
      relation: "parent",
    });

    if (parentTuples.length === 0) break;

    const parent = parentTuples[0].object;
    path.push(`${parent.type}:${parent.id}`);
    current = parent;
  }

  return path;
}

console.log("Hierarchy:", await traceHierarchyPath("document", "doc1"));
// ["document:doc1", "folder:subfolder", "folder:root"]

5. Enable Logging

const debugLog: string[] = [];

const authz = new AuthSystem({
  storage,
  schema,
  logger: {
    warn: (msg) => {
      debugLog.push(msg);
      console.warn("[Polizy]", msg);
    },
  },
});

// After operations, check debugLog for warnings

Error Reference

ErrorCauseFix
SchemaError: Relation "X" is not definedUsing undefined relationAdd relation to schema
SchemaError: No group relation definedMissing group typeAdd member: { type: "group" }
SchemaError: No hierarchy relation definedMissing hierarchy typeAdd parent: { type: "hierarchy" }
MaxDepthExceededErrorGroup/​hierarchy too deepIncrease depth or flatten
ConfigurationError: storage is requiredMissing storage adapterProvide storage in constructor
ConfigurationError: schema is requiredMissing schemaProvide schema in constructor

Anti-Patterns to Avoid

See ANTI-PATTERNS.md for detailed explanations:

  1. Duplicating permissions across users - Use groups
  2. Deep group nesting - Keep 2-3 levels
  3. Generic relation names - Use semantic names
  4. Checking after action - Check before
  5. Not handling authorization errors - Show feedback

References

Related Skills

More Other skills

Delegate independent tasks to specialized agents working concurrently with isolated context.

295.4K 206.3K
View

Applies Anthropic's official brand colors and typography to any sort of artifact that may benefit from having Anthropic's look-and-feel. Use it when brand colors or style guidelines, visual formatting, or company design standards apply.

179.7K 100.1K
View

Toolkit for styling artifacts with a theme. These artifacts can be slides, docs, reportings, HTML landing pages, etc. There are 10 pre-set themes with colors/fonts that you can apply to any artifact that has been creating, or can generate a new theme on-the-fly.

179.7K 89.5K
View

A set of resources to help me write all kinds of internal communications, using the formats that my company likes to use. Claude should use this skill whenever asked to write some sort of internal communications (status reports, leadership updates, 3P updates, company newsletters, FAQs, incident reports, project updates, etc.).

179.7K 76.1K
View

Fundamental design principles for writing maintainable, testable Python code.

40.2K 21.9K
View

Modern responsive layouts using container queries, fluid typography, CSS Grid, and mobile-first strategies.

40.2K 20K
View

Generate Playwright tests from scenarios using interactive browser exploration and validation.

39.7K 18.2K
View

Modern React state management with Redux Toolkit, Zustand, Jotai, and React Query for every state category.

40.2K 14.7K
View

GDPR-compliant data handling with consent management, data subject rights, and privacy controls.

40.2K 14.3K
View

Python error handling patterns including input validation, exception hierarchies, and partial failure handling. Use when implementing validation logic, designing exception strategies, handling batch processing failures, or building robust APIs.

40.2K 13.5K
View

Detailed multi-file refactor planning with safety checks and rollback guidance.

39.7K 13K
View