tractatus/public/media-inquiry.html
TheFlow 682bfa2f5c feat: implement AI-powered features (Phase 1 Core)
**Three Public Features:**
- Media Inquiry System: Press/media can submit inquiries with AI triage (Phase 2)
- Case Study Submissions: Community can submit real-world AI safety failures
- Blog Curation: Admin-only topic suggestions with AI assistance (Phase 2)

**Backend Implementation:**
- Media routes/controller: /api/media/inquiries endpoints
- Cases routes/controller: /api/cases/submit endpoints
- Blog routes/controller: Already existed, documented
- Human oversight: All submissions go to moderation queue
- Tractatus boundaries: BoundaryEnforcer integration in blog controller

**Frontend Forms:**
- /media-inquiry.html: Public submission form for press/media
- /case-submission.html: Public submission form for case studies
- Full validation, error handling, success messages

**Validation Middleware Updates:**
- Support nested field validation (contact.email, submitter.name)
- validateEmail(fieldPath) now parameterized
- validateRequired() supports dot-notation paths

**Phase 1 Status:**
- AI triage: Manual (Phase 2 will add Claude API integration)
- All submissions require human review and approval
- Moderation queue operational
- Admin dashboard endpoints ready

**Files Added:**
- public/media-inquiry.html
- public/case-submission.html
- src/controllers/media.controller.js
- src/controllers/cases.controller.js
- src/routes/media.routes.js
- src/routes/cases.routes.js

**Files Modified:**
- src/routes/index.js (registered new routes)
- src/routes/auth.routes.js (updated validateEmail call)
- src/middleware/validation.middleware.js (nested field support)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-08 00:14:00 +13:00

273 lines
9.8 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Media Inquiry | Tractatus AI Safety</title>
<link rel="stylesheet" href="/css/tailwind.css?v=1759835330">
<style>
.form-group { margin-bottom: 1.5rem; }
.form-label {
display: block;
font-weight: 600;
color: #374151;
margin-bottom: 0.5rem;
}
.form-input, .form-textarea {
width: 100%;
padding: 0.75rem;
border: 1px solid #d1d5db;
border-radius: 0.375rem;
font-size: 1rem;
transition: border-color 0.15s;
}
.form-input:focus, .form-textarea:focus {
outline: none;
border-color: #3b82f6;
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
}
.form-textarea { min-height: 150px; resize: vertical; }
.form-help { font-size: 0.875rem; color: #6b7280; margin-top: 0.25rem; }
.required { color: #dc2626; }
#success-message, #error-message {
display: none;
padding: 1rem;
border-radius: 0.5rem;
margin-bottom: 1.5rem;
}
#success-message {
background-color: #d1fae5;
border: 1px solid #10b981;
color: #065f46;
}
#error-message {
background-color: #fee2e2;
border: 1px solid #ef4444;
color: #991b1b;
}
</style>
</head>
<body class="bg-gray-50">
<!-- Navigation -->
<nav class="bg-white border-b border-gray-200">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="flex justify-between h-16">
<div class="flex items-center">
<a href="/" class="text-xl font-bold text-gray-900">Tractatus Framework</a>
</div>
<div class="flex items-center space-x-6">
<a href="/researcher.html" class="text-gray-600 hover:text-gray-900">Researcher</a>
<a href="/implementer.html" class="text-gray-600 hover:text-gray-900">Implementer</a>
<a href="/advocate.html" class="text-gray-600 hover:text-gray-900">Advocate</a>
<a href="/docs.html" class="text-gray-600 hover:text-gray-900">Documentation</a>
<a href="/about.html" class="text-gray-600 hover:text-gray-900">About</a>
</div>
</div>
</div>
</nav>
<!-- Main Content -->
<div class="max-w-3xl mx-auto px-4 sm:px-6 lg:px-8 py-12">
<!-- Header -->
<div class="mb-8">
<h1 class="text-3xl font-bold text-gray-900 mb-3">Media Inquiry</h1>
<p class="text-lg text-gray-600">
Press and media inquiries about the Tractatus Framework. We review all inquiries and respond promptly.
</p>
</div>
<!-- Messages -->
<div id="success-message"></div>
<div id="error-message"></div>
<!-- Form -->
<div class="bg-white rounded-lg shadow-sm border border-gray-200 p-8">
<form id="media-inquiry-form">
<!-- Contact Information -->
<h2 class="text-xl font-semibold text-gray-900 mb-6">Contact Information</h2>
<div class="form-group">
<label for="contact-name" class="form-label">
Your Name <span class="required">*</span>
</label>
<input type="text" id="contact-name" name="contact.name" class="form-input" required>
</div>
<div class="form-group">
<label for="contact-email" class="form-label">
Email Address <span class="required">*</span>
</label>
<input type="email" id="contact-email" name="contact.email" class="form-input" required>
</div>
<div class="form-group">
<label for="contact-outlet" class="form-label">
Media Outlet/Organization <span class="required">*</span>
</label>
<input type="text" id="contact-outlet" name="contact.outlet" class="form-input" required>
<p class="form-help">Publication, website, podcast, or organization you represent</p>
</div>
<div class="form-group">
<label for="contact-phone" class="form-label">
Phone Number (optional)
</label>
<input type="tel" id="contact-phone" name="contact.phone" class="form-input">
</div>
<!-- Inquiry Details -->
<h2 class="text-xl font-semibold text-gray-900 mb-6 mt-8">Inquiry Details</h2>
<div class="form-group">
<label for="inquiry-subject" class="form-label">
Subject <span class="required">*</span>
</label>
<input type="text" id="inquiry-subject" name="inquiry.subject" class="form-input" required>
</div>
<div class="form-group">
<label for="inquiry-message" class="form-label">
Message <span class="required">*</span>
</label>
<textarea id="inquiry-message" name="inquiry.message" class="form-textarea" required></textarea>
</div>
<div class="form-group">
<label for="inquiry-deadline" class="form-label">
Deadline (if applicable)
</label>
<input type="datetime-local" id="inquiry-deadline" name="inquiry.deadline" class="form-input">
<p class="form-help">When do you need a response by?</p>
</div>
<!-- Submit Button -->
<div class="mt-8">
<button type="submit" id="submit-button" class="w-full bg-blue-600 text-white px-6 py-3 rounded-lg font-semibold hover:bg-blue-700 transition">
Submit Inquiry
</button>
<p class="form-help mt-3 text-center">
We review all media inquiries and typically respond within 24-48 hours.
</p>
</div>
</form>
</div>
<!-- Privacy Note -->
<div class="mt-6 text-sm text-gray-600 text-center">
<p>
Your contact information is handled according to our
<a href="/about/values.html" class="text-blue-600 hover:text-blue-700">privacy principles</a>.
We never share media inquiries with third parties.
</p>
</div>
</div>
<!-- Footer -->
<footer class="bg-gray-900 text-gray-300 mt-16 py-12">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="grid grid-cols-1 md:grid-cols-3 gap-8">
<div>
<h3 class="text-white font-semibold mb-4">Tractatus Framework</h3>
<p class="text-sm">
AI safety through architectural constraints and human agency preservation.
</p>
</div>
<div>
<h3 class="text-white font-semibold mb-4">Quick Links</h3>
<ul class="space-y-2 text-sm">
<li><a href="/docs.html" class="hover:text-white transition">Documentation</a></li>
<li><a href="/about.html" class="hover:text-white transition">About</a></li>
<li><a href="/about/values.html" class="hover:text-white transition">Values</a></li>
</ul>
</div>
<div>
<h3 class="text-white font-semibold mb-4">Contact</h3>
<ul class="space-y-2 text-sm">
<li><a href="/media-inquiry.html" class="hover:text-white transition">Media Inquiries</a></li>
<li><a href="/case-submission.html" class="hover:text-white transition">Submit Case Study</a></li>
</ul>
</div>
</div>
<div class="mt-8 pt-8 border-t border-gray-800 text-center text-sm">
<p>© 2025 Tractatus Framework. Licensed under <a href="/LICENSE" class="text-blue-400 hover:text-blue-300 transition">Apache License 2.0</a>.</p>
</div>
</div>
</footer>
<script>
const form = document.getElementById('media-inquiry-form');
const submitButton = document.getElementById('submit-button');
const successMessage = document.getElementById('success-message');
const errorMessage = document.getElementById('error-message');
form.addEventListener('submit', async (e) => {
e.preventDefault();
// Hide previous messages
successMessage.style.display = 'none';
errorMessage.style.display = 'none';
// Disable submit button
submitButton.disabled = true;
submitButton.textContent = 'Submitting...';
// Collect form data
const formData = {
contact: {
name: document.getElementById('contact-name').value,
email: document.getElementById('contact-email').value,
outlet: document.getElementById('contact-outlet').value,
phone: document.getElementById('contact-phone').value || null
},
inquiry: {
subject: document.getElementById('inquiry-subject').value,
message: document.getElementById('inquiry-message').value,
deadline: document.getElementById('inquiry-deadline').value || null,
topic_areas: []
}
};
try {
const response = await fetch('/api/media/inquiries', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(formData)
});
const data = await response.json();
if (response.ok) {
// Success
successMessage.textContent = data.message || 'Thank you for your inquiry. We will review and respond shortly.';
successMessage.style.display = 'block';
form.reset();
window.scrollTo({ top: 0, behavior: 'smooth' });
} else {
// Error
errorMessage.textContent = data.message || 'An error occurred. Please try again.';
errorMessage.style.display = 'block';
window.scrollTo({ top: 0, behavior: 'smooth' });
}
} catch (error) {
console.error('Submit error:', error);
errorMessage.textContent = 'Network error. Please check your connection and try again.';
errorMessage.style.display = 'block';
window.scrollTo({ top: 0, behavior: 'smooth' });
} finally {
// Re-enable submit button
submitButton.disabled = false;
submitButton.textContent = 'Submit Inquiry';
}
});
</script>
</body>
</html>