feat(framework): P1+P2 — public sanitization + blocking CI gate
Adds tools/quality/scripts/verify-sanitized.sh (two-class, self-tested) wired
blocking in .woodpecker/ci.yml; sanitizes operator identity from the public
framework package so the gate is green.
- purge jarvis/jason/woltje/PDA across 26 files -> generic
- delete jarvis-loop.json overlay; add neutral examples/{personas,overlays}
- relocate maintainer AUDIT to docs/audits/; delete 2 jarvis-brain rule blocks
- neutralize SOUL persona; strip "(Policy: Jason ...)" keeping universal rule
- test fixtures jason.woltje -> ci-bot (both git tests pass)
Deferred (tracked): private third-party host (uscllc) genericization.
Refs #542, closes #571
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -309,7 +309,7 @@ if [[ -f "$pi_settings" ]]; then
|
||||
fi
|
||||
|
||||
# Mosaic-specific skills presence check.
|
||||
mosaic_skills=(mosaic-board mosaic-forge mosaic-prdy mosaic-macp mosaic-standards mosaic-prd mosaic-jarvis mosaic-setup-cicd)
|
||||
mosaic_skills=(mosaic-board mosaic-forge mosaic-prdy mosaic-macp mosaic-standards mosaic-prd mosaic-setup-cicd)
|
||||
for skill_name in "${mosaic_skills[@]}"; do
|
||||
if [[ -d "$MOSAIC_HOME/skills/$skill_name" ]] || [[ -L "$MOSAIC_HOME/skills/$skill_name" ]]; then
|
||||
pass "Mosaic skill present: $skill_name"
|
||||
|
||||
@@ -5,8 +5,8 @@ set -euo pipefail
|
||||
#
|
||||
# Usage:
|
||||
# mosaic-init # Interactive mode
|
||||
# mosaic-init --name "Jarvis" --style direct # Flag overrides
|
||||
# mosaic-init --name "Jarvis" --role "memory steward" --style direct \
|
||||
# mosaic-init --name "Mosaic Agent" --style direct # Flag overrides
|
||||
# mosaic-init --name "Mosaic Agent" --role "memory steward" --style direct \
|
||||
# --accessibility "ADHD-friendly chunking" --guardrails "Never auto-commit"
|
||||
|
||||
MOSAIC_HOME="${MOSAIC_HOME:-$HOME/.config/mosaic}"
|
||||
@@ -50,7 +50,7 @@ Generate Mosaic identity and configuration files:
|
||||
Interactive by default. Use flags to skip prompts.
|
||||
|
||||
Options:
|
||||
--name <name> Agent name (e.g., "Jarvis", "Assistant")
|
||||
--name <name> Agent name (e.g., "Mosaic Agent", "Assistant")
|
||||
--role <description> Role description (e.g., "memory steward, execution partner")
|
||||
--style <style> Communication style: direct, friendly, or formal
|
||||
--accessibility <prefs> Accessibility preferences (e.g., "ADHD-friendly chunking")
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#
|
||||
# Usage:
|
||||
# mosaic-init.ps1 # Interactive mode
|
||||
# mosaic-init.ps1 -Name "Jarvis" -Style direct # Flag overrides
|
||||
# mosaic-init.ps1 -Name "Mosaic Agent" -Style direct # Flag overrides
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
param(
|
||||
|
||||
@@ -62,7 +62,6 @@ legacy_paths=(
|
||||
"$HOME/.claude/presets/domains"
|
||||
"$HOME/.claude/presets/tech-stacks"
|
||||
"$HOME/.claude/presets/workflows"
|
||||
"$HOME/.claude/presets/jarvis-loop.json"
|
||||
)
|
||||
|
||||
for p in "${legacy_paths[@]}"; do
|
||||
|
||||
@@ -70,7 +70,6 @@ $legacyPaths = @(
|
||||
(Join-Path $env:USERPROFILE ".claude\presets\domains"),
|
||||
(Join-Path $env:USERPROFILE ".claude\presets\tech-stacks"),
|
||||
(Join-Path $env:USERPROFILE ".claude\presets\workflows"),
|
||||
(Join-Path $env:USERPROFILE ".claude\presets\jarvis-loop.json")
|
||||
)
|
||||
|
||||
foreach ($p in $legacyPaths) {
|
||||
|
||||
@@ -8,7 +8,7 @@ usage() {
|
||||
cat <<USAGE
|
||||
Usage: $(basename "$0") [--apply]
|
||||
|
||||
Migrate runtime-local skill directories (e.g. ~/.claude/skills/jarvis) to Mosaic-managed
|
||||
Migrate runtime-local skill directories (e.g. ~/.claude/skills/<name>) to Mosaic-managed
|
||||
skills by replacing local directories with symlinks to ~/.config/mosaic/skills-local.
|
||||
|
||||
Default mode is dry-run.
|
||||
|
||||
@@ -16,7 +16,7 @@ if ($Help) {
|
||||
Write-Host @"
|
||||
Usage: mosaic-migrate-local-skills.ps1 [-Apply] [-Help]
|
||||
|
||||
Migrate runtime-local skill directories (e.g. ~/.claude/skills/jarvis) to
|
||||
Migrate runtime-local skill directories (e.g. ~/.claude/skills/<name>) to
|
||||
Mosaic-managed skills by replacing local directories with junctions to
|
||||
~/.config/mosaic/skills-local.
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ Manage Authentik identity provider (SSO, users, groups, applications, flows) via
|
||||
## Prerequisites
|
||||
|
||||
- `jq` installed
|
||||
- Authentik credentials in `~/src/jarvis-brain/credentials.json` (or `$MOSAIC_CREDENTIALS_FILE`)
|
||||
- Authentik credentials in `~/.config/mosaic/credentials.json` (or `$MOSAIC_CREDENTIALS_FILE`)
|
||||
- Required fields: `authentik.url`, `authentik.username`, `authentik.password`
|
||||
|
||||
## Authentication
|
||||
@@ -47,7 +47,7 @@ All scripts support:
|
||||
~/.config/mosaic/tools/authentik/user-list.sh
|
||||
|
||||
# Search for a user
|
||||
~/.config/mosaic/tools/authentik/user-list.sh -s "jason"
|
||||
~/.config/mosaic/tools/authentik/user-list.sh -s "alice"
|
||||
|
||||
# Create a user in the admins group
|
||||
~/.config/mosaic/tools/authentik/user-create.sh -u newuser -n "New User" -e new@example.com -g admins
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
# Usage:
|
||||
# agent-lint.sh # Scan all projects in ~/src/
|
||||
# agent-lint.sh --project <path> # Scan single project
|
||||
# agent-lint.sh --json # Output JSON for jarvis-brain
|
||||
# agent-lint.sh --json # Output JSON for machine consumption
|
||||
# agent-lint.sh --verbose # Show per-check details
|
||||
# agent-lint.sh --fix-hint # Show fix commands for failures
|
||||
#
|
||||
|
||||
@@ -5,7 +5,7 @@ Manage Coolify container deployment platform (projects, services, deployments, e
|
||||
## Prerequisites
|
||||
|
||||
- `jq` and `curl` installed
|
||||
- Coolify credentials in `~/src/jarvis-brain/credentials.json` (or `$MOSAIC_CREDENTIALS_FILE`)
|
||||
- Coolify credentials in `~/.config/mosaic/credentials.json` (or `$MOSAIC_CREDENTIALS_FILE`)
|
||||
- Required fields: `coolify.url`, `coolify.app_token`
|
||||
|
||||
## Scripts
|
||||
|
||||
@@ -39,7 +39,7 @@ if [[ "$*" == "login list --output json" ]]; then
|
||||
cat <<'JSON'
|
||||
[
|
||||
{"name":"evil-usc","url":"https://evilgit.uscllc.com","user":"bad.actor"},
|
||||
{"name":"usc","url":"https://git.uscllc.com","user":"jason.woltje"}
|
||||
{"name":"usc","url":"https://git.uscllc.com","user":"ci-bot"}
|
||||
]
|
||||
JSON
|
||||
exit 0
|
||||
@@ -263,8 +263,8 @@ set -euo pipefail
|
||||
if [[ "$*" == "login list --output json" ]]; then
|
||||
cat <<'JSON'
|
||||
[
|
||||
{"name":"mosaicstack","url":"https://git.mosaicstack.dev","user":"jason.woltje"},
|
||||
{"name":"usc","url":"https://git.uscllc.com","user":"jason.woltje"}
|
||||
{"name":"mosaicstack","url":"https://git.mosaicstack.dev","user":"ci-bot"},
|
||||
{"name":"usc","url":"https://git.uscllc.com","user":"ci-bot"}
|
||||
]
|
||||
JSON
|
||||
exit 0
|
||||
|
||||
@@ -49,7 +49,7 @@ set -euo pipefail
|
||||
if [[ "$*" == "login list --output json" ]]; then
|
||||
cat <<'JSON'
|
||||
[
|
||||
{"name":"mosaicstack","url":"https://git.mosaicstack.dev","user":"jason.woltje"}
|
||||
{"name":"mosaicstack","url":"https://git.mosaicstack.dev","user":"ci-bot"}
|
||||
]
|
||||
JSON
|
||||
exit 0
|
||||
|
||||
@@ -5,7 +5,7 @@ Manage GLPI IT service management (tickets, computers/assets, users).
|
||||
## Prerequisites
|
||||
|
||||
- `jq` and `curl` installed
|
||||
- GLPI credentials in `~/src/jarvis-brain/credentials.json` (or `$MOSAIC_CREDENTIALS_FILE`)
|
||||
- GLPI credentials in `~/.config/mosaic/credentials.json` (or `$MOSAIC_CREDENTIALS_FILE`)
|
||||
- Required fields: `glpi.url`, `glpi.app_token`, `glpi.user_token`
|
||||
|
||||
## Authentication
|
||||
|
||||
86
packages/mosaic/framework/tools/quality/scripts/verify-sanitized.sh
Executable file
86
packages/mosaic/framework/tools/quality/scripts/verify-sanitized.sh
Executable file
@@ -0,0 +1,86 @@
|
||||
#!/usr/bin/env bash
|
||||
# verify-sanitized.sh — blocking CI gate: the public framework package must
|
||||
# contain no operator-specific personal data or private executable defaults.
|
||||
#
|
||||
# Two rule classes:
|
||||
# 1. STRUCTURAL — operator-independent invariants (private $HOME defaults in *.sh).
|
||||
# 2. DENYLIST — a LABELED, one-time regression guard for the CURRENT operator's
|
||||
# identity tokens. This is NOT a general PII detector (a future
|
||||
# operator's name can't be enumerated); the durable control is the
|
||||
# L0 prose firewall + human review. This gate just stops *this*
|
||||
# contamination from coming back.
|
||||
#
|
||||
# Scope: all of the framework package — *.md, *.sh, *.ps1, and the CLI scripts under
|
||||
# tools/_scripts/ (which are extensionless). Excluded: examples/ (holds
|
||||
# sanitized, placeholdered worked examples), node_modules/, and this gate file.
|
||||
#
|
||||
# NOTE on scope: private THIRD-PARTY host references (e.g. a maintainer's employer
|
||||
# Gitea) are intentionally NOT in this denylist — they are functionally entangled in
|
||||
# host-routing + test fixtures and are tracked as a separate follow-up.
|
||||
#
|
||||
# Self-tests run first: plant known tokens and assert the scan catches them, so a
|
||||
# broken regex cannot silently no-op the gate.
|
||||
#
|
||||
# Usage: verify-sanitized.sh [FRAMEWORK_ROOT]
|
||||
set -uo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
FRAMEWORK_ROOT="${1:-$(cd "$SCRIPT_DIR/../../.." && pwd)}"
|
||||
SELF_REL="tools/quality/scripts/verify-sanitized.sh"
|
||||
|
||||
# Labeled current-contaminant denylist. Anchored so substrings like "comparison" or
|
||||
# "jsonwebtoken" do not match. (jarvis-brain is caught by 'jarvis'.)
|
||||
DENYLIST='jarvis|jason|woltje|brain\.woltje\.com|/home/jwoltje|\bPDA\b'
|
||||
|
||||
# Structural: a private $HOME path used as a shell default (e.g. ${VAR:-$HOME/src/...}).
|
||||
STRUCTURAL_SH=':[-=]\$\{?HOME\}?/src/'
|
||||
|
||||
# Build the in-scope file list once (NUL-delimited).
|
||||
_scope_files() {
|
||||
find "$FRAMEWORK_ROOT" -type f \
|
||||
\( -name '*.md' -o -name '*.sh' -o -name '*.ps1' -o -path '*/tools/_scripts/*' \) \
|
||||
-not -path '*/examples/*' \
|
||||
-not -path '*/node_modules/*' \
|
||||
-not -path "*/$SELF_REL" \
|
||||
-print0
|
||||
}
|
||||
|
||||
fail=0
|
||||
cd "$FRAMEWORK_ROOT" || { echo "FRAMEWORK_ROOT not found: $FRAMEWORK_ROOT" >&2; exit 3; }
|
||||
|
||||
deny_hits="$(_scope_files | xargs -0 -r grep -nIEi "$DENYLIST" 2>/dev/null || true)"
|
||||
if [[ -n "$deny_hits" ]]; then
|
||||
echo "✗ [denylist] operator-identity tokens in shipped files:"
|
||||
echo "$deny_hits" | sed "s#$FRAMEWORK_ROOT/##; s/^/ /"
|
||||
fail=1
|
||||
fi
|
||||
|
||||
struct_hits="$(_scope_files | xargs -0 -r grep -nIE "$STRUCTURAL_SH" 2>/dev/null \
|
||||
| grep -E '\.sh:|/tools/_scripts/' || true)"
|
||||
if [[ -n "$struct_hits" ]]; then
|
||||
echo "✗ [structural] private \$HOME/src default in a shipped script:"
|
||||
echo "$struct_hits" | sed "s#$FRAMEWORK_ROOT/##; s/^/ /"
|
||||
fail=1
|
||||
fi
|
||||
|
||||
# ---- self-test: the gate must catch planted tokens ----
|
||||
_selftest() {
|
||||
local tmp; tmp="$(mktemp -d)" || return 1
|
||||
printf 'contact jason.woltje at jarvis-brain (PDA note)\n' > "$tmp/planted.md"
|
||||
printf 'X="${VAR:-$HOME/src/whatever/x.json}"\n' > "$tmp/planted.sh"
|
||||
local ok=0
|
||||
grep -qIEi "$DENYLIST" "$tmp/planted.md" || { echo "✗ SELF-TEST: denylist regex broken" >&2; ok=1; }
|
||||
grep -qIE "$STRUCTURAL_SH" "$tmp/planted.sh" || { echo "✗ SELF-TEST: structural regex broken" >&2; ok=1; }
|
||||
rm -rf "$tmp"
|
||||
return $ok
|
||||
}
|
||||
_selftest || exit 2
|
||||
|
||||
if [[ "$fail" -ne 0 ]]; then
|
||||
echo
|
||||
echo "Sanitization gate FAILED. Public framework files must not contain operator identity" >&2
|
||||
echo "or private \$HOME defaults. Move personal content to init-generated files or examples/." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "✓ sanitization gate passed (framework *.md/*.sh/*.ps1/_scripts; examples/ excluded)"
|
||||
@@ -5,7 +5,7 @@ Interact with Woodpecker CI pipelines (list builds, check status, trigger builds
|
||||
## Prerequisites
|
||||
|
||||
- `jq` and `curl` installed
|
||||
- Woodpecker credentials in `~/src/jarvis-brain/credentials.json`
|
||||
- Woodpecker credentials in `~/.config/mosaic/credentials.json`
|
||||
|
||||
## Setup
|
||||
|
||||
|
||||
Reference in New Issue
Block a user