From d6f12a07bc632fe0227c2a735475afdd45c1455c Mon Sep 17 00:00:00 2001 From: "Jonathan D.A. Jewell" <6759885+hyperpolymath@users.noreply.github.com> Date: Fri, 13 Mar 2026 20:33:19 +0000 Subject: [PATCH] fix: security hardening, RSR structure alignment, README restoration - SHA-pin mlugg/setup-zig@v2 in zig-test.yml (was unpinned tag ref) - Add input validation to MCP bridge: cartridge name regex + encodeURIComponent to prevent path traversal via boj_cartridge_info/boj_cartridge_invoke - Move docs to docs/: ABI-FFI-README, READINESS, RSR_OUTLINE, TOPOLOGY - Remove root duplicates already in .github/: CODEOWNERS - Delete redundant AI tool configs: .clinerules, .cursorrules, .windsurfrules - Delete unused: .maintenance-perms-ignore, .nojekyll - Fix README.md: restore full original content, clean Glama badge placement, add MCP installation section, update doc paths to docs/ Co-Authored-By: Claude Opus 4.6 (1M context) --- .clinerules | 43 ------------------- .cursorrules | 47 --------------------- .github/workflows/zig-test.yml | 2 +- .maintenance-perms-ignore | 5 --- .nojekyll | 0 .windsurfrules | 43 ------------------- CODEOWNERS | 14 ------ README.md | 10 +++-- ABI-FFI-README.md => docs/ABI-FFI-README.md | 0 READINESS.md => docs/READINESS.md | 0 RSR_OUTLINE.adoc => docs/RSR_OUTLINE.adoc | 0 TOPOLOGY.md => docs/TOPOLOGY.md | 0 mcp-bridge/main.js | 14 +++++- 13 files changed, 19 insertions(+), 159 deletions(-) delete mode 100644 .clinerules delete mode 100644 .cursorrules delete mode 100644 .maintenance-perms-ignore delete mode 100644 .nojekyll delete mode 100644 .windsurfrules delete mode 100644 CODEOWNERS rename ABI-FFI-README.md => docs/ABI-FFI-README.md (100%) rename READINESS.md => docs/READINESS.md (100%) rename RSR_OUTLINE.adoc => docs/RSR_OUTLINE.adoc (100%) rename TOPOLOGY.md => docs/TOPOLOGY.md (100%) diff --git a/.clinerules b/.clinerules deleted file mode 100644 index bdabd95b..00000000 --- a/.clinerules +++ /dev/null @@ -1,43 +0,0 @@ -# SPDX-License-Identifier: PMPL-1.0-or-later -# Copyright (c) 2026 Jonathan D.A. Jewell (hyperpolymath) -# Authoritative source: docs/AI-CONVENTIONS.md - -# STARTUP: Read 0-AI-MANIFEST.a2ml first, then .machine_readable/STATE.a2ml. - -# LICENSE -# All original code: PMPL-1.0-or-later. -# Never AGPL-3.0. MPL-2.0 only as platform-required fallback. -# SPDX header required on every source file. -# Copyright: Jonathan D.A. Jewell (hyperpolymath) - -# STATE FILES (.machine_readable/ ONLY) -# Never create in repo root: STATE.a2ml, META.a2ml, ECOSYSTEM.a2ml, -# AGENTIC.a2ml, NEUROSYM.a2ml, PLAYBOOK.a2ml. -# The .machine_readable/ directory is the single source of truth. - -# BANNED PATTERNS -# Idris2: believe_me, assert_total, assert_smaller, unsafePerformIO -# Haskell: unsafeCoerce, unsafePerformIO, undefined, error -# OCaml: Obj.magic, Obj.repr, Obj.obj -# Coq: Admitted -# Lean: sorry -# Rust: transmute (unless FFI with // SAFETY: comment) - -# BANNED LANGUAGES -# TypeScript -> ReScript -# Node.js / npm / bun -> Deno -# Go -> Rust -# Python -> Julia or Rust - -# CONTAINERS -# Runtime: Podman (never Docker). -# File: Containerfile (never Dockerfile). -# Base: cgr.dev/chainguard/wolfi-base:latest or cgr.dev/chainguard/static:latest. - -# ABI/FFI -# ABI: Idris2 with dependent types (src/abi/). -# FFI: Zig with C ABI (ffi/zig/). -# Headers: generated/abi/. - -# BUILD: Use just (justfile) for all tasks. -# STYLE: Descriptive names. Document all files. SPDX headers everywhere. diff --git a/.cursorrules b/.cursorrules deleted file mode 100644 index 9e4535c0..00000000 --- a/.cursorrules +++ /dev/null @@ -1,47 +0,0 @@ -# SPDX-License-Identifier: PMPL-1.0-or-later -# Copyright (c) 2026 Jonathan D.A. Jewell (hyperpolymath) -# Authoritative source: docs/AI-CONVENTIONS.md - -# Read 0-AI-MANIFEST.a2ml in the repo root FIRST for canonical file locations. - -# LICENSE -# All original code: PMPL-1.0-or-later (SPDX header required on every file). -# Never use AGPL-3.0. Fallback to MPL-2.0 only when platform requires it. -# Copyright: Jonathan D.A. Jewell (hyperpolymath) - -# STATE FILES -# .a2ml metadata files go in .machine_readable/ ONLY. -# Never create STATE.a2ml, META.a2ml, ECOSYSTEM.a2ml, AGENTIC.a2ml, -# NEUROSYM.a2ml, or PLAYBOOK.a2ml in the repository root. - -# BANNED PATTERNS -# Idris2: believe_me, assert_total, assert_smaller, unsafePerformIO -# Haskell: unsafeCoerce, unsafePerformIO, undefined, error -# OCaml: Obj.magic, Obj.repr, Obj.obj -# Coq: Admitted -# Lean: sorry -# Rust: transmute (unless FFI with // SAFETY: comment) - -# BANNED LANGUAGES -# TypeScript -> use ReScript -# Node.js / npm / bun -> use Deno -# Go -> use Rust -# Python -> use Julia or Rust - -# CONTAINERS -# Runtime: Podman (never Docker) -# File: Containerfile (never Dockerfile) -# Base: cgr.dev/chainguard/wolfi-base:latest - -# ABI/FFI STANDARD -# ABI definitions: Idris2 with dependent types (src/abi/) -# FFI implementation: Zig with C ABI (ffi/zig/) -# Generated C headers: generated/abi/ - -# BUILD SYSTEM -# Use just (justfile) for all build, test, lint, and format tasks. - -# CODE STYLE -# Use descriptive variable names. -# Annotate and document all files. -# Add SPDX-License-Identifier header to every source file. diff --git a/.github/workflows/zig-test.yml b/.github/workflows/zig-test.yml index e66446af..384d2404 100644 --- a/.github/workflows/zig-test.yml +++ b/.github/workflows/zig-test.yml @@ -27,7 +27,7 @@ jobs: - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 - name: Install Zig - uses: mlugg/setup-zig@v2 + uses: mlugg/setup-zig@d1434d08867e3ee9daa34448df10607b98908d29 # v2 with: version: 0.15.2 diff --git a/.maintenance-perms-ignore b/.maintenance-perms-ignore deleted file mode 100644 index 2c8c4096..00000000 --- a/.maintenance-perms-ignore +++ /dev/null @@ -1,5 +0,0 @@ -# Regex patterns for justified permission-policy exceptions. -# One pattern per line. -# Example: -# ^vendor/ -# ^third_party/ diff --git a/.nojekyll b/.nojekyll deleted file mode 100644 index e69de29b..00000000 diff --git a/.windsurfrules b/.windsurfrules deleted file mode 100644 index bdabd95b..00000000 --- a/.windsurfrules +++ /dev/null @@ -1,43 +0,0 @@ -# SPDX-License-Identifier: PMPL-1.0-or-later -# Copyright (c) 2026 Jonathan D.A. Jewell (hyperpolymath) -# Authoritative source: docs/AI-CONVENTIONS.md - -# STARTUP: Read 0-AI-MANIFEST.a2ml first, then .machine_readable/STATE.a2ml. - -# LICENSE -# All original code: PMPL-1.0-or-later. -# Never AGPL-3.0. MPL-2.0 only as platform-required fallback. -# SPDX header required on every source file. -# Copyright: Jonathan D.A. Jewell (hyperpolymath) - -# STATE FILES (.machine_readable/ ONLY) -# Never create in repo root: STATE.a2ml, META.a2ml, ECOSYSTEM.a2ml, -# AGENTIC.a2ml, NEUROSYM.a2ml, PLAYBOOK.a2ml. -# The .machine_readable/ directory is the single source of truth. - -# BANNED PATTERNS -# Idris2: believe_me, assert_total, assert_smaller, unsafePerformIO -# Haskell: unsafeCoerce, unsafePerformIO, undefined, error -# OCaml: Obj.magic, Obj.repr, Obj.obj -# Coq: Admitted -# Lean: sorry -# Rust: transmute (unless FFI with // SAFETY: comment) - -# BANNED LANGUAGES -# TypeScript -> ReScript -# Node.js / npm / bun -> Deno -# Go -> Rust -# Python -> Julia or Rust - -# CONTAINERS -# Runtime: Podman (never Docker). -# File: Containerfile (never Dockerfile). -# Base: cgr.dev/chainguard/wolfi-base:latest or cgr.dev/chainguard/static:latest. - -# ABI/FFI -# ABI: Idris2 with dependent types (src/abi/). -# FFI: Zig with C ABI (ffi/zig/). -# Headers: generated/abi/. - -# BUILD: Use just (justfile) for all tasks. -# STYLE: Descriptive names. Document all files. SPDX headers everywhere. diff --git a/CODEOWNERS b/CODEOWNERS deleted file mode 100644 index c0c02712..00000000 --- a/CODEOWNERS +++ /dev/null @@ -1,14 +0,0 @@ -# SPDX-License-Identifier: PMPL-1.0-or-later -# CODEOWNERS - Define code review assignments -# See: https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners -# -# Replace hyperpolymath with your GitHub username or team - -# Default owners for everything -* @hyperpolymath - -# Security-sensitive files require explicit review -SECURITY.md @hyperpolymath -.github/workflows/ @hyperpolymath -Trustfile.a2ml @hyperpolymath -.machine_readable/ @hyperpolymath diff --git a/README.md b/README.md index 55ee937a..31bd662b 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,10 @@ Unified server capability catalogue with formally verified cartridges, distribut > `Set up Bundle of Joy Server from https://github.com/hyperpolymath/boj-server` > The AI reads this repo, asks you a few questions, and handles everything. + + BoJ MCP Server on Glama + + ## What is this? BoJ solves the **combinatoric explosion of developer server protocols**. Instead of hunting across dozens of MCP, LSP, DAP, and other servers, AI goes to ONE place — the Teranga menu — and orders what it needs. @@ -93,9 +97,7 @@ cd ../../ffi/zig && zig build # Run tests cd ffi/zig && zig build test -``` - - +``` ## Distributed Hosting (Umoja Network) @@ -126,7 +128,7 @@ PMPL-1.0-or-later (Palimpsest License). The license's provenance requirements (c ## Project Status -**Grade A (Production)** — 18 cartridges, 307 tests passing, thread-safe FFI (mutex-hardened), panic-attack validated. See `READINESS.md` for the full CRG assessment and `.machine_readable/STATE.a2ml` for milestone progress. +**Grade A (Production)** — 18 cartridges, 307 tests passing, thread-safe FFI (mutex-hardened), panic-attack validated. See `docs/READINESS.md` for the full CRG assessment and `.machine_readable/STATE.a2ml` for milestone progress. ## A Community Project diff --git a/ABI-FFI-README.md b/docs/ABI-FFI-README.md similarity index 100% rename from ABI-FFI-README.md rename to docs/ABI-FFI-README.md diff --git a/READINESS.md b/docs/READINESS.md similarity index 100% rename from READINESS.md rename to docs/READINESS.md diff --git a/RSR_OUTLINE.adoc b/docs/RSR_OUTLINE.adoc similarity index 100% rename from RSR_OUTLINE.adoc rename to docs/RSR_OUTLINE.adoc diff --git a/TOPOLOGY.md b/docs/TOPOLOGY.md similarity index 100% rename from TOPOLOGY.md rename to docs/TOPOLOGY.md diff --git a/mcp-bridge/main.js b/mcp-bridge/main.js index f37eced8..7f3ff660 100755 --- a/mcp-bridge/main.js +++ b/mcp-bridge/main.js @@ -106,9 +106,16 @@ async function fetchCartridges() { } } +function isValidCartridgeName(name) { + return typeof name === "string" && /^[a-z0-9][a-z0-9-]*$/.test(name) && name.length <= 64; +} + async function invokeCartridge(name, params) { + if (!isValidCartridgeName(name)) { + return { error: `Invalid cartridge name: ${name}` }; + } try { - const res = await fetch(`${BOJ_BASE}/cartridge/${name}/invoke`, { + const res = await fetch(`${BOJ_BASE}/cartridge/${encodeURIComponent(name)}/invoke`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(params || {}), @@ -120,8 +127,11 @@ async function invokeCartridge(name, params) { } async function fetchCartridgeInfo(name) { + if (!isValidCartridgeName(name)) { + return { error: `Invalid cartridge name: ${name}` }; + } try { - const res = await fetch(`${BOJ_BASE}/cartridge/${name}`); + const res = await fetch(`${BOJ_BASE}/cartridge/${encodeURIComponent(name)}`); return await res.json(); } catch { const all = OFFLINE_MENU.tier_teranga.concat(OFFLINE_MENU.tier_shield);