package rbac import ( "context" "code.nochebuena.dev/einherjar/contracts/security" ) var _ security.PermissionProvider = (*chainPermissionProvider)(nil) type chainPermissionProvider struct { providers []security.PermissionProvider } // NewChainPermissionProvider tries providers in order, returning the first non-zero mask. // Errors short-circuit the chain immediately. // // Typical pattern: JWT claims fast-path → cached DB fallback: // // rbac.NewChainPermissionProvider( // rbac.NewClaimsPermissionProvider("perms"), // rbac.NewCachedPermissionProvider(dbProvider, cache, 5*time.Minute), // ) func NewChainPermissionProvider(providers ...security.PermissionProvider) security.PermissionProvider { return &chainPermissionProvider{providers: providers} } func (c *chainPermissionProvider) ResolveMask(ctx context.Context, uid, resource string) (security.PermissionMask, error) { for _, p := range c.providers { mask, err := p.ResolveMask(ctx, uid, resource) if err != nil { return 0, err } if mask != 0 { return mask, nil } } return 0, nil }