Keeping the ranked fields like total_score and average_score as DecimalFields while JSONB stays a storage/presentation layer is a clean split, and it makes the B-Tree indexes do real work. One small addition if you adopt the version stamp: a CHECK constraint or a validator that rejects payloads whose blueprint version doesn't match a known one would catch drift early, even without schema enforcement on the keys. Thanks for the detailed answer.
