<!-- SOLIDABILITY-WORLD · part 52 -->
ly
  let authorizedEditor = null; // userId of authorized operator, if any

  // Audit log (client-side mirror; server is source of truth)
  let auditLog = [];

  function setRole(role, editorId) {
    if (!['diagnostic', 'operator', 'admin'].includes(role)) return false;
    currentRole = role;
    authorizedEditor = editorId || null;
    logAudit('role-set', `Role set to ${role}`, null);
    return true;
  }

  function getRole() { return currentRole; }
  function canModify() { return currentRole === 'operator' || currentRole === 'admin'; }
  function isReadOnly() { return !canModify(); }

  // Every fix suggestion gets an audit entry
  function suggestFix(roomKey, fixType, description, preview) {
    const entry = {
      id: 'fix_' + Date.now(),
      timestamp: new Date().toISOString(),
      type: 'suggestion',
      actor: 'diagnostic-ai',
      actorRole: 'diagnostic',
      roomKey,
      fixType,
      description,
      preview: (preview || '').slice(0, 2000),
      status: 'proposed',
    };
    auditLog.push(entry);
    if (auditLog.length > 200) auditLog.shift();
    return entry;
  }

  // Operator approves and applies
  function approveFix(fixId, operatorId) {
    if (!canModify()) {
      return { ok: false, error: 'Read-only role cannot approve fixes' };
    }
    const entry = auditLog.find(e => e.id === fixId);
    if (!entry) return { ok: false, error: 'Fix not found' };
    entry.status = 'approved';
    entry.approvedBy = operatorId;
    entry.approvedAt = new Date().toISOString();
    return { ok: true, entry };
  }

  function logAudit(type, summary, data) {
    auditLog.push({
      id: 'audit_' + Date.now(),
      timestamp: new Date().toISOString(),
      type,
      actor: currentRole === 'diagnostic' ? 'diagnostic-ai' : 'operator',
      actorRole: currentRole,
      summary,
      data: data ? JSON.stringify(data).slice(0, 500) : null,
    });
    if (auditLog.length > 200) auditLog.shift();
  }

  function getAuditLog() { return [...auditLog]; }

  // Parse @solidability annotations from source
  // Format: // @solidability:ignore <reason>
  //         // @solidability:intent <description>
  //         // @solidability:risk <level> <reason>
  function parseAnnotations(source) {
    const annotations = [];
    const lines = source.split('\n');
    lines.forEach((line, idx) => {
      const match = line.match(/@solidability:(\w+)\s*(.*)/);
      if (match) {
        annotations.push({
          line: idx + 1,
          directive: match[1],
          value: match[2].trim(),
        });
      }
    });
    return annotations;
  }

  // Show role badge in UI
  function renderRoleBadge() {
    const badge = document.getElementById('trust-badge');
    if (!badge) return;
    const isRO = isReadOnly();
    badge.innerHTML = isRO
      ? `<span class="role-badge readonly">🔒 READ-ONLY</span>`
      : `<span class="role-badge operator">✏️ OPERATOR</span>`;
    badge.title = isRO
      ? 'Diagnostic AI: can inspect and suggest, cannot modify'
      : 'Authorized: can preview and apply fixes with approval';
  }

  // Server-side audit: append-only, hash-chained, tamper-evident
  async function serverAudit(action, target, detail, patchHash, baseRevision) {
    try {
      const resp = await fetch('/api/solidability-world/audit', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        credentials: 'same-origin',
        body: JSON.stringify({ action, target, detail, patchHash, baseRevision }),
      });
      const data = await resp.json();
      if (data.ok) {
        logAudit('server-audit', `${action}: ${target || ''}`, { hash: data.hash });
      }
      return data;
    } catch (e) {
      console.error('[SWTrust] Audit write failed:', e.message);
      return { ok: false, error: e.message };
    }
  }

  async function verifyAuditChain() {
    try {
      const resp = await fetch('/api/solidability-world/audit/verify', { credentials: 'same-origin' });
      return await resp.json();
    } catch (e) {
      return { ok: false, error: e.message };
    }
  }

  // Approval integrity: request, validate, consume
  async function requestApproval(patch, files, scope, description) {
    try {
      const resp = await fetch('/api/solidability-world/approval/request', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        credentials: 'same-origin',
        body: JSON.stringify({ patch, files, scope, description }),
      });
      return await resp.json();
    } catch (e) {
      return { ok: false, error: e.message };
    }
  }

  async function validateApproval(approvalId, patch) {
    try {
      const resp = await fetch('/api/solidability-world/approval/validate', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        credentials: 'same-origin',
        body: JSON.stringify({ approvalId, patch }),
      });
      return await resp.json();
    