// Proof-of-enforcement for kb#147, run with: node src/trust-gate.test.mjs
//
// Deliberately does NOT touch the live agap-mcp container, LiteLLM, or
// Vaultwarden — it exercises the exact exported functions server.js calls
// (trustRankOf/vaultAllowed/resolveCallerAgent/isVaultTool) against a
// synthetic registry + token map, so this is a real test of the enforcement
// logic itself, not a mock of it.

import assert from 'node:assert/strict';
import {
  trustRankOf,
  vaultAllowed,
  resolveCallerAgent,
  isVaultTool,
  trustedRankThreshold,
  _resetRegistryCacheForTests,
} from './trust-gate.js';

const registry = {
  trust_classes: {
    human: { rank: 3 },
    trusted: { rank: 2 },
    sandboxed: { rank: 1 },
    untrusted: { rank: 0 },
  },
  agents: [
    { id: 'adolf', trust_class: 'trusted' },
    { id: 'claude-coder', trust_class: 'trusted' },
    { id: 'torgash', trust_class: 'sandboxed' },
    { id: 'researcher', trust_class: 'sandboxed' },
    { id: 'kimi-endpoint', trust_class: 'untrusted' },
  ],
};

const tokenMap = {
  'tok-adolf': 'adolf',
  'tok-claude-coder': 'claude-coder',
  'tok-torgash': 'torgash',
  'tok-researcher': 'researcher',
};

let passed = 0;
function check(label, fn) {
  fn();
  passed++;
  console.log(`ok - ${label}`);
}

check('trusted rank threshold resolves from registry', () => {
  assert.equal(trustedRankThreshold(registry), 2);
});

check('trusted agents (adolf, claude-coder) can reach vault', () => {
  assert.equal(vaultAllowed('adolf', registry), true);
  assert.equal(vaultAllowed('claude-coder', registry), true);
});

check('sandboxed agents (torgash, researcher) CANNOT reach vault', () => {
  assert.equal(vaultAllowed('torgash', registry), false);
  assert.equal(vaultAllowed('researcher', registry), false);
});

check('untrusted agent cannot reach vault', () => {
  assert.equal(vaultAllowed('kimi-endpoint', registry), false);
});

check('unauthenticated caller (no token resolved) cannot reach vault', () => {
  assert.equal(vaultAllowed(null, registry), false);
  assert.equal(trustRankOf(null, registry), -1);
});

check('unknown/unregistered agent id fails closed, not open', () => {
  assert.equal(vaultAllowed('some-new-agent-nobody-declared', registry), false);
});

check('resolveCallerAgent maps bearer token -> agent id, else null', () => {
  assert.equal(resolveCallerAgent('tok-torgash', tokenMap), 'torgash');
  assert.equal(resolveCallerAgent('tok-adolf', tokenMap), 'adolf');
  assert.equal(resolveCallerAgent('not-a-real-token', tokenMap), null);
  assert.equal(resolveCallerAgent(null, tokenMap), null);
});

check('end-to-end: a sandboxed agent\'s token provably cannot reach vw_* tools', () => {
  const callerAgentId = resolveCallerAgent('tok-torgash', tokenMap);
  assert.equal(callerAgentId, 'torgash');
  assert.equal(isVaultTool('vw_get_password'), true);
  assert.equal(vaultAllowed(callerAgentId, registry), false); // <- the acceptance bar
});

check('end-to-end: a trusted agent\'s token can reach vw_* tools', () => {
  const callerAgentId = resolveCallerAgent('tok-adolf', tokenMap);
  assert.equal(vaultAllowed(callerAgentId, registry), true);
});

check('non-vault tool name is unaffected by the gate', () => {
  assert.equal(isVaultTool('gitea_read_file'), false);
  assert.equal(isVaultTool('zabbix_get_problems'), false);
});

_resetRegistryCacheForTests(null);
console.log(`\n${passed} passed`);
