I think you should define a localstorage for your products and use the foreign key to select the right products when loading. I think the reason for you problem is found in the documentation, since localstorage says:

You might also have luck in configuring the store and/or writer, but I think having them in separate stores will be better. I've been programming with nested stores since yesterday (due to nested data in my JSON service) and I have to say I don't think it's pretty compared to normal store setup.

Make two separate stores for a cart and products - it's a good idea.
But I do not see any barriers for the storage of models with hasMany association because data is stored as single JSON-string.
Most likely this is error in localstorage proxy... or this proxy simply not support hasMany associations.
If so - then let the developers will confirm this.

I took kostysh's ideas and made it almost work. The problem is that the products store is acting global, so anytime you add a new cart, all products previously saved are now associated with the NEW cart, not the old ones that they were added to. I need multiple carts and each cart to have its own separate list of products. Is that even possible?

For an app that ONLY needs one cart, this would work, but I am just using this as a proof of concept before I apply my more complex data - where I need a main list of items, each with its own list of associated items.

When creating a new item (cart), internally it is calling load, and then read (when newCart.products() is first called). The read function is sent a filter with the new items uuid, but that filter is not applied, and instead all records are UPDATED to use the new uuid, instead of filtered to match the new uuid.

I changed my Ext.data.proxy.WebStorage.read() in the sencha 2 library to be: