SPB Git

spb/ultra-sharp-agent-skills Public

Ultra-Sharp Agent Skills — a research-first skill-authoring system + 72 production-ready skills for AI agents.

Python 100%

# name: implementing-authorization description: Implements permission decisions in backend services — RBAC/ABAC models, resource-ownership checks, IDOR prevention, multi-tenant isolation, and centralized policy enforcement. Use when the user asks to add roles, permissions, access control, admin-only routes, ownership checks, tenant isolation, or asks why a user can see another user's data. Do not use for identity verification and login flows (implementing-authentication) or OS and file-system permissions.

# Implementing Authorization

# When to use / when NOT to use

  • Use for: deciding what an authenticated caller may do — roles, permissions, ownership checks, tenant isolation, policy middleware, privileged-action auditing.
  • Do NOT use for: logging users in (implementing-authentication), database GRANTs (db-skills/securing-databases), or OS/file permissions.

# Core rules

  1. Authorize on every request, server-side. Client-side hiding of buttons is UX, not security.
  2. Deny by default. Routes without an explicit policy are rejected, not allowed.
    • @require(perm="reports:read") on each route; unannotated routes 403 in middleware
    • ❌ "Only add checks to the sensitive endpoints"
  3. RBAC is the default model (user → roles → permissions). Reach for ABAC (attribute rules) only when decisions depend on resource attributes (owner, status, amount thresholds).
  4. Authentication is not authorization — check ownership. Fetching by ID must scope to the caller.
    • SELECT ... WHERE id = :id AND owner_id = :caller
    • SELECT ... WHERE id = :id after login — classic IDOR
  5. Multi-tenant: scope every query by tenant_id, derived from the session/token — never from the request body or URL. Use Postgres row-level security as a backstop where available.
  6. Centralize policy in one module/middleware. Scattered if user.role == "admin" checks drift and rot; route handlers call authorize(caller, action, resource) and nothing else.
  7. Audit privileged actions (role grants, data exports, deletions): who, what, when, from where — to an append-only log.

# Workflow

  1. Enumerate actions and resources; write the permission matrix (roles × actions) before code.
  2. Implement the central authorize() + deny-by-default middleware (rule 2, 6).
  3. Add ownership/tenant scoping at the data layer (rules 4–5) so a missed route check cannot leak cross-tenant data.
  4. Wire the audit log for privileged actions (rule 7).
  5. Validate: as user A, request user B's resource by ID (expect 403/404); as a role without the permission, call each privileged route (expect 403); confirm an unannotated test route is rejected by default. All three must pass before shipping.

# Edge cases & failure modes

  • 403 vs 404: return 404 for resources the caller must not know exist (cross-tenant); 403 within a tenant where existence is not secret. Pick per resource and stay consistent.
  • Role changes mid-session → re-read roles per request (or short cache ≤60 s); revoke sessions on demotion.
  • Background jobs and internal services → they get their own scoped identities, never a shared "system = superuser" that skips authorize().
  • Batch endpoints → authorize each item, not just the endpoint; report per-item denials.

# References

Copy-paste patterns and gotchas: see references/patterns.md.