Never trust a mastermind You probably know the game mastermind:
The player tries to guess a code of 4 slots, with 8 possible colors - no duplicates this time.
Let's call those colors A through H, so possible solutions could be ABCD or BCHD.
Each time you place a guess, the game master will respond with two information: how many slots you got right, and how many colors you got right but in the wrong place.
Some examples:
If the code is ABCD
and your guess is ACHB
the response 12: the color A is correctly placed, the two colors B&amp;C are in the wrong place.

Code is ABCD
you guess EFGH
response is 00

Code is ABCD
you guess ABCD
response is 40

A full representation would be:
ABCD04,DCBA40
or
ABCD00,EFGH22,EFHG13,HFGE40

A partial game does not contain the final solution, 
nor necessarily enough data to define a unique solution.
ABCD00,EFGH22,EFHG13

An example for an invalid partial game would be:
ABCD03,EFGH02: This would require that 5 colors are present

In essence, all games that cannot have a solution are invalid. The gamemaster made a mistake.
Your task
Never trust a game master. Your task is to write a program that takes a partial or full game description and validates whether such a game state is possible.

Expect that no game description is longer than 8 attempts.
Expect that the gamemaster can make a mistake on the very first turn, e.g. ABCD41
The player can make an &quot;invalid&quot; guess to gain further information, e.g. AAAA to check if there is an A at all. Such a game is still valid, you only evaluate the gamemaster's responses. In such a case, exact hit takes precedence over near-misses, for code ABCD it's AAAA10, not AAAA14.
You can format the input and output in whatever way you see fit, including replacing the colors by digits etc.
Any pre-generated hashtable counts towards the total number of bytes.
You know the loophole thing.

The shortest code wins.
Additional test cases:
 - ABCD11,ACEG02,HGFE11,CCCC10,CDGH01 =&gt; valid
 - ABCD01,EFGH03,CGGH11,HGFE21 =&gt; valid
 - ABCD22,EFGH01,ACDE11 =&gt; invalid
 - ABCD02,EFGH01,AABB21,AEDH30 =&gt; invalid
 - ABCD03,DCBA02 =&gt; invalid 
 - ABCD32 =&gt; invalid

You can generate any number of valid cases by playing the game.
Invalid solutions are hard to come up with. If you find invalid combinations that first slipped through your code, please comment it below for your fellow golfers.
Bonus:
Bonus points if you come up with a solution that uses a significantly different approach than generating and traversing all possible permutations.
JavaScript (ES6),  116 112  107 bytes
Expects an array of entries in the following format: [[a,b,c,d], &quot;XY&quot;], where a to d are integers in [0..7], X is the number of correct digits and Y is the number of near-misses.
Returns 0 or 1.

f=(a,n)=&gt;n&gt;&gt;12?0:!a.some(([a,x])=&gt;!a.every(o=(d,i)=&gt;o[x-=d^(v=n&gt;&gt;i*3&amp;7)?a.includes(v):10,v]^=1)|x)|f(a,-~n)

Try it online!
Commented
f = (                     // f is a recursive function taking:
  a,                      //   a[] = input
  n                       //   n = 12-bit counter, initially undefined, to
) =&gt;                      //       describe all possible codes
n &gt;&gt; 12 ?                 // if n = 4096:
  0                       //   stop the recursion
:                         // else:
  !a.some(([a, x]) =&gt;     //   for each entry [a, x, y] in a[], with a[] =
                          //   guess, x = correct digits and near-misses:
    !a.every(o =          //     we use the object o to keep track of the
                          //     digits that were already extracted from n,
                          //     in order to discard invalid codes
      (d, i) =&gt;           //     for each value d at position i in a[]:
      o[                  //
        x -=              //       update x:
          d ^ (           //         compare d with ...
            v =           //         ... v which is defined as ...
              n &gt;&gt; i * 3  //         ... the next 3-bit digit extracted from n
              &amp; 7         //
          ) ?             //         if d is not equal to v, decrement x if ...
            a.includes(v) //           ... v appears elsewhere in a[]
          :               //         else:
            10,           //           subtract 10 from x
        v                 //       actual index in o to ...
      ] ^= 1              //       ... mark this digit as used; or yield 0
                          //       and exit every() if it was already used
    )                     //     end of every(); the iteration fails if it's
    | x                   //     falsy or x is not equal to 0
  )                       //   end of some()
  | f(a, -~n)             //   do a recursive call with n + 1