Keys in One Object Must be the Same as Keys in Another Object
<h1>Initial Setting</h1>

<p>You have a JavaScript object for keeping configs, it may be extended by plugins, each plugin has a version and one property on the configs object.</p>

<pre class="lang-js prettyprint-override"><code>const CONFIGS = {
  plugins: {
    plugins: { version: '0.15' }, // Plugins is a plugin itself.
    proxies: { version: '0.15' }  // Used to configure proxies.
  },
  proxies: {
    HTTPS: ['satan.hell:666']
  }
}
</code></pre>

<h1>Question</h1>

<p>How to express in JSON schema, that each key of <code>CONFIGS.plugins</code> MUST have corresponding property on root of <code>CONFIGS</code> object and vice versa.</p>

<h1>My Failed Attempt</h1>

<p>ajv is 4.8.2, prints <em>"Valid!"</em> but must be <em>"Invalid"</em></p>

<pre class="lang-js prettyprint-override"><code>'use strict';

var Ajv = require('ajv');
var ajv = Ajv({allErrors: true, v5: true});

var schema = {

  definitions: {
    pluginDescription: {
      type: "object",
      properties: {
        version: { type: "string" }
      },
      required: ["version"],
      additionalProperties: false
    }
  },

  type: "object",
  properties: {

    plugins: {
      type: "object",
      properties: {

        plugins: {
          $ref: "#/definitions/pluginDescription"
        }

      },
      required: ["plugins"],
      additionalProperties: {
        $ref: "#/definitions/pluginDescription"
      }
    }

  },
  required: { $data: "0/plugins/#" }, // current obj &gt; plugins &gt; all props?
  additionalProperties: false
};

var validate = ajv.compile(schema);

test({
  plugins: {
    plugins: { version: 'def' },
    proxies: { version: 'abc' }
  }
  // Sic! No `proxies` prop, but must be.
});

function test(data) {
  var valid = validate(data);
  if (valid) console.log('Valid!');
  else console.log('Invalid: ' + ajv.errorsText(validate.errors));
}
</code></pre>