fix(docs): require document_type and audience before publishing

Documents could be set to visibility: 'public' without document_type,
audience, or status fields — either via bulk migration scripts or the
upload-document.js script. This allowed internal session logs to appear
in the public docs UI.

Safeguards added:
- Document.publish() now rejects if document_type or audience is missing
- Document.publish() now sets status: 'current' automatically
- upload-document.js requires --type and --category flags (was optional)
- upload-document.js sets status: 'current' and document_type on insert

Also archived 2 internal Phase 5 PoC session documents that were
incorrectly public, and set status: 'current' on 4 legitimate public
documents that were missing it.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
TheFlow 2026-02-22 18:48:48 +13:00
parent ce9e150e37
commit b76889582c
2 changed files with 40 additions and 1 deletions

View file

@ -41,8 +41,10 @@ if (args.length === 0 || args[0] === '--help' || args[0] === '-h') {
Usage: node scripts/upload-document.js <markdown-file> [options]
Options:
--category <cat> Category: getting-started, technical-reference, research-theory,
--category <cat> REQUIRED. Category: getting-started, technical-reference, research-theory,
advanced-topics, case-studies, business-leadership
--type <type> REQUIRED. Document type: working-paper, case-study, technical-report,
guide, reference, brief
--audience <aud> Audience: general, researcher, implementer, leader, advocate, developer
--title <title> Override document title (extracted from H1 if not provided)
--author <author> Document author (default: Agentic Governance Research Team)
@ -67,12 +69,14 @@ Examples:
# Upload research paper
node scripts/upload-document.js docs/research/my-paper.md \\
--category research-theory \\
--type working-paper \\
--audience researcher \\
--tags "ai-safety,governance,research"
# Upload technical guide (no PDF)
node scripts/upload-document.js docs/guides/setup.md \\
--category getting-started \\
--type guide \\
--audience developer \\
--no-pdf
@ -96,6 +100,7 @@ if (!mdFilePath) {
const options = {
category: null,
audience: 'general',
document_type: null,
title: null,
author: 'Agentic Governance Research Team',
tags: [],
@ -115,6 +120,9 @@ for (let i = 1; i < args.length; i++) {
case '--audience':
options.audience = args[++i];
break;
case '--type':
options.document_type = args[++i];
break;
case '--title':
options.title = args[++i];
break;
@ -481,6 +489,17 @@ async function uploadDocument() {
try {
console.log('\n=== Tractatus Document Upload ===\n');
// SECURITY: Require --category and --type for public documents
const validTypes = ['working-paper', 'case-study', 'technical-report', 'guide', 'reference', 'brief'];
if (!options.category) {
console.error('❌ Error: --category is required. Available: getting-started, resources, research-theory, technical-reference, advanced-topics, business-leadership');
process.exit(1);
}
if (!options.document_type || !validTypes.includes(options.document_type)) {
console.error(`❌ Error: --type is required. Available: ${validTypes.join(', ')}`);
process.exit(1);
}
// Verify markdown file exists
const mdPath = path.resolve(mdFilePath);
try {
@ -559,7 +578,9 @@ async function uploadDocument() {
quadrant: null,
persistence: 'HIGH',
audience: options.audience,
document_type: options.document_type,
visibility: 'public',
status: 'current',
category: options.category,
licence: options.licence,
order: options.order,

View file

@ -214,6 +214,23 @@ class Document {
return { success: false, message: 'Document must have content before publishing' };
}
// SECURITY: Require document_type for public docs
const docType = doc.document_type;
if (!docType) {
return {
success: false,
message: 'Document must have a document_type before publishing. Set document_type to one of: working-paper, case-study, technical-report, guide, reference, brief'
};
}
// SECURITY: Require audience for public docs
if (!doc.audience) {
return {
success: false,
message: 'Document must have an audience before publishing. Set audience to one of: researcher, implementer, leader, general'
};
}
// SECURITY: Require valid category for public docs
const category = options.category || doc.category;
if (!category || category === 'none') {
@ -241,6 +258,7 @@ class Document {
{
$set: {
visibility: 'public',
status: 'current',
category,
order: options.order !== undefined ? options.order : doc.order,
workflow_status: 'published',