Introduction
Derafu Identity Bundle is a Symfony bundle for authentication, authorization, and organizational multi-tenancy. It provides the plumbing every SaaS needs — users, roles, permissions, organizations, memberships, invitations, email verification, password reset — as reusable infrastructure that the consuming app extends.
What it is
- A MappedSuperclass + ResolveTargetEntityListener bundle: the bundle owns the ORM schema (columns, relations, constraints); the app owns the concrete entities (class names, table names, extra fields).
- A cascading RBAC engine: permissions are checked at three levels — global → organization → resource — with automatic fallback. A global super-admin passes every check without explicit membership.
- A user lifecycle toolkit: registration, email verification, password reset, and email change — all headless (services + events, no controllers or templates).
- A multi-tenant membership system: GitHub-style organizations with roles, invitations by email, and an accept flow.
What it is not
- Not a replacement for Symfony Security (it builds on top of it).
- Not a JWT library (it wraps Lexik JWT for convenience).
- Not a 2FA, OAuth, or social-login solution (use dedicated bundles).
- Not a UI — no controllers, no templates, no forms. The app owns UX.
Mental model
User estebandelaf
├── personal resources (UserOwnedInterface)
└── member of Organization "derafu"
├── OrganizationMembership (role = org.owner)
├── shared resources (OrganizationOwnedInterface)
└── other invited members
Resources in the app (Contribuyente, Repo, Project, …) integrate with the bundle by implementing one or more interfaces — the bundle provides traits with ready-made Doctrine mapping.
Architecture pattern
Every ORM relation in the bundle targets an interface, not a
concrete class. Doctrine resolves interfaces to the app’s classes at
runtime via resolve_target_entities, configured automatically by the
bundle’s DI extension. The app never appears in the bundle’s code.
Bundle App
────── ───
BaseUser (MappedSuperclass) ◄── User (#[ORM\Entity])
UserInterface ──────────────► resolved to User at runtime