Intelligence
Artifacts
Browse the repository, read documents, and manage the governance folders. Source, runtime, and infrastructure are read-only.
Repository
repositories/aaf-holdings/hq01/lib/uploads/config.ts
3.1 KB
import path from "node:path";
/**
* Configuration for the HQ01 Artifact Upload flow.
*
* The destination categories below are the *entire* security boundary for
* writes: the browser only ever sends a category **key**, never a path. The
* server maps that key to a fixed absolute directory. There is no way for a
* caller to write outside this allowlist, which is what keeps HQ01 from
* exposing arbitrary filesystem writes.
*/
/**
* Base of the upload tree. Defaults to the AAF workspace root (which is also the
* Artifacts explorer root, so uploaded files appear there immediately).
* Overridable for tests via HQ01_UPLOAD_ROOT.
*/
export const UPLOAD_ROOT =
process.env.HQ01_UPLOAD_ROOT?.trim() || "/srv/aaf";
/** Maximum accepted upload size: 25 MB. */
export const MAX_UPLOAD_BYTES = 25 * 1024 * 1024;
/** The only file extensions HQ01 will accept. */
export const ALLOWED_EXTENSIONS = new Set([
".pdf",
".md",
".txt",
".yaml",
".yml",
".json",
]);
export interface UploadCategory {
/** Stable key sent by the client. */
key: string;
/** Human label shown in the UI. */
label: string;
/** One-line description of what belongs here. */
blurb: string;
/** Absolute destination directory (created on demand). */
dir: string;
}
/**
* The fixed destination allowlist. `dir` is always derived from UPLOAD_ROOT, so
* every target is contained within the workspace and nothing else is writable.
*/
export const UPLOAD_CATEGORIES: UploadCategory[] = [
{
key: "pdf",
label: "PDF Artifact",
blurb: "Reference PDFs and scanned documents.",
dir: path.join(UPLOAD_ROOT, "artifacts", "pdf"),
},
{
key: "canonical",
label: "Canonical Document",
blurb: "Parent doctrine — the highest-level governing documents (CANONICAL_*).",
dir: path.join(UPLOAD_ROOT, "canonical"),
},
{
key: "exec-constitution",
label: "Executive Constitution",
blurb: "Standing authority and rules for an executive.",
dir: path.join(UPLOAD_ROOT, "constitutions", "executives"),
},
{
key: "dept-constitution",
label: "Department Constitution",
blurb: "Standing authority for a department.",
dir: path.join(UPLOAD_ROOT, "constitutions", "departments"),
},
{
key: "roadmap",
label: "Roadmap",
blurb: "Department and product roadmaps.",
dir: path.join(UPLOAD_ROOT, "roadmaps"),
},
{
key: "doctrine",
label: "Doctrine",
blurb: "Promoted, ratified doctrine and lessons.",
dir: path.join(UPLOAD_ROOT, "doctrine"),
},
{
key: "template",
label: "Template",
blurb: "Reusable work-order and document templates.",
dir: path.join(UPLOAD_ROOT, "templates"),
},
{
key: "inbox",
label: "Uploads Inbox",
blurb: "Default drop zone for unsorted uploads.",
dir: path.join(UPLOAD_ROOT, "uploads"),
},
];
export function getCategory(key: string): UploadCategory | undefined {
return UPLOAD_CATEGORIES.find((c) => c.key === key);
}
/** A presentable, comma-free list of accepted extensions for the UI. */
export const ALLOWED_EXTENSIONS_LABEL = [...ALLOWED_EXTENSIONS].join(" ");
root · /srv/aaf