gitfield-sync
1 #!/bin/bash 2 set -euo pipefail 3 IFS=$'\n\t' 4 5 # ╭─────────────────────────────────────╮ 6 # │ CONFIGURATION │ 7 # ╰─────────────────────────────────────╮ 8 REPO_PATH=$(git rev-parse --show-toplevel 2>/dev/null) || error "Not inside a Git repository" 9 REPO_NAME=$(basename "$REPO_PATH") 10 GITFIELD_DIR="$REPO_PATH/.gitfield" 11 WELL_KNOWN_DIR="$REPO_PATH/.well-known" 12 DOCS_DIR="$REPO_PATH/docs" 13 DOCS_WELL_KNOWN_DIR="$DOCS_DIR/.well-known" 14 LOG_FILE="$GITFIELD_DIR/pushed.log" 15 GITFIELD_MD="$REPO_PATH/GITFIELD.md" 16 DOCS_GITFIELD_MD="$DOCS_DIR/GITFIELD.md" 17 CANONICAL_META="$GITFIELD_DIR/canonical.meta" 18 CANONICAL_MD="$GITFIELD_DIR/canonical.md" 19 INDEX_JSON="$GITFIELD_DIR/index.json" 20 WELL_KNOWN_JSON="$WELL_KNOWN_DIR/gitfield.json" 21 GITFIELD_README="$GITFIELD_DIR/README.txt" 22 DOCS_CANONICAL_META="$DOCS_DIR/canonical.meta" 23 DOCS_CANONICAL_MD="$DOCS_DIR/canonical.md" 24 DOCS_INDEX_JSON="$DOCS_DIR/index.json" 25 DOCS_PUSHED_LOG="$DOCS_DIR/pushed.log" 26 DOCS_GITFIELD_README="$DOCS_DIR/gitfield.README.txt" 27 DOCS_GITFIELD_JSON="$DOCS_DIR/gitfield.json" 28 DOCS_WELL_KNOWN_JSON="$DOCS_WELL_KNOWN_DIR/gitfield.json" 29 DOCS_INDEX="$DOCS_DIR/index.html" 30 DOCS_CSS="$DOCS_DIR/style.css" 31 DOCS_REPOS_JSON="$DOCS_DIR/repos.json" 32 DOCS_README="$DOCS_DIR/README.md" 33 DOCS_NOJEKYLL="$DOCS_DIR/.nojekyll" 34 DOCS_ROBOTS="$DOCS_DIR/robots.txt" 35 DOCS_SITEMAP="$DOCS_DIR/sitemap.xml" 36 DOCS_INTEGRITY="$DOCS_DIR/integrity.sha256" 37 TIMESTAMP=$(date -u '+%Y-%m-%dT%H:%M:%SZ') 38 SCRIPT_VERSION="1.5" # Updated for Gitea removal and GITFIELD.md replication 39 PRESERVE_META=${PRESERVE_META:-false} # Preserve existing metadata 40 FORCE_DOCS=${FORCE_DOCS:-false} # Force overwrite of /docs metadata 41 42 # URLs for each platform 43 CANONICAL_URL="https://remember.thefoldwithin.earth/mrhavens/$REPO_NAME" 44 GITHUB_URL="https://github.com/mrhavens/$REPO_NAME" 45 GITLAB_URL="https://gitlab.com/mrhavens/$REPO_NAME" 46 BITBUCKET_URL="https://bitbucket.org/thefoldwithin/$REPO_NAME" 47 FORGEJO_URL="https://remember.thefoldwithin.earth/mrhavens/$REPO_NAME" 48 CODEBERG_URL="https://codeberg.org/mrhavens/$REPO_NAME" 49 RADICLE_RID="rad:z3FEj7rF8gZw9eFksCuiN43qjzrex" 50 RADICLE_URL="https://app.radicle.xyz/nodes/z3FEj7rF8gZw9eFksCuiN43qjzrex" 51 RADICLE_PEER_ID="z6Mkw5s3ppo26C7y7tGK5MD8n2GqTHS582PPpeX5Xqbu2Mpz" 52 53 # Metadata configuration 54 MIRRORS=( 55 "$GITHUB_URL" 56 "$GITLAB_URL" 57 "$BITBUCKET_URL" 58 "$FORGEJO_URL" 59 "$CODEBERG_URL" 60 "$RADICLE_RID" 61 ) 62 COMMIT_HASH=$(git -C "$REPO_PATH" rev-parse --short HEAD 2>/dev/null || echo "unknown") 63 TREE_HASH=$(git -C "$REPO_PATH" rev-parse HEAD^{tree} 2>/dev/null || echo "unknown") 64 SYNC_CYCLES=0 65 66 # GPG configuration 67 GPG_KEYS=() 68 GPG_EMAILS=() 69 GPG_NAMES=() 70 while IFS= read -r line; do 71 if [[ "$line" =~ ^pub[[:space:]]+rsa[0-9]+[[:space:]]+([0-9]{4}-[0-9]{2}-[0-9]{2})[[:space:]]+\[SC\] ]]; then 72 key_id=$(gpg --list-keys --with-colons | grep -B1 "^pub" | grep "^pub" | awk -F: '{print $5}' | head -n1) 73 GPG_KEYS+=("$key_id") 74 elif [[ "$line" =~ ^uid[[:space:]]+\[ultimate\][[:space:]]+(.*)\<(.*)\> ]]; then 75 GPG_NAMES+=("${BASH_REMATCH[1]% }") 76 GPG_EMAILS+=("${BASH_REMATCH[2]}") 77 fi 78 done < <(gpg --list-keys) 79 80 # ╭─────────────────────────────────────╮ 81 # │ LOGGING UTILS │ 82 # ╰─────────────────────────────────────╮ 83 info() { echo -e "\e[1;34m[INFO]\e[0m $*" >&2; } 84 warn() { echo -e "\e[1;33m[WARN]\e[0m $*" >&2; } 85 error() { echo -e "\e[1;31m[ERROR]\e[0m $*" >&2; exit 1; } 86 87 # ╭─────────────────────────────────────╮ 88 # │ SCRIPT LOOKUP FUNCTION │ 89 # ╰─────────────────────────────────────╮ 90 find_script() { 91 local script_name=$1 92 local search_paths=( 93 "$HOME/.local/gitfieldbin" 94 "$HOME/.local/bin" 95 "$HOME/.local/gitfield" 96 "$HOME/.local/bin/gitfield" 97 "$HOME/.local/bin/gitfieldbin" 98 "$REPO_PATH/bin" 99 ) 100 101 for path in "${search_paths[@]}"; do 102 if [ -f "$path/$script_name" ]; then 103 if [ -x "$path/$script_name" ]; then 104 if [[ "$path" != "$HOME"* && "$path" != "$REPO_PATH"* ]]; then 105 info "Using script: \e[1;31m$path/$script_name\e[0m (outside home or repo)" 106 else 107 info "Using script: $path/$script_name" 108 fi 109 echo "$path/$script_name" 110 return 0 111 else 112 warn "Found $path/$script_name but it is not executable" 113 fi 114 fi 115 done 116 error "Script $script_name not found in any search path" 117 } 118 119 # ╭─────────────────────────────────────╮ 120 # │ GPG SIGNING FUNCTION │ 121 # ╰─────────────────────────────────────╮ 122 sign_file() { 123 local file=$1 124 local sig_file="${file}.sig" 125 if [ ! -f "$file" ]; then 126 warn "File $file does not exist, skipping signing" 127 return 128 fi 129 for key_id in "${GPG_KEYS[@]}"; do 130 gpg --armor --detach-sign --yes --default-key "$key_id" "$file" > "$sig_file.$key_id" 2>/dev/null || warn "Failed to sign $file with key $key_id, continuing..." 131 if [ -f "$sig_file.$key_id" ]; then 132 git -C "$REPO_PATH" add "$sig_file.$key_id" 133 git -C "$REPO_PATH" commit -m "Signed $file with GPG key $key_id at $TIMESTAMP" || warn "No changes to commit for $sig_file.$key_id" 134 info "Signed $file with key $key_id, signature at $sig_file.$key_id" 135 copy_to_docs "$sig_file.$key_id" "$DOCS_DIR/$(basename "$sig_file.$key_id")" 136 fi 137 done 138 } 139 140 # ╭─────────────────────────────────────╮ 141 # │ METADATA COPY FUNCTION │ 142 # ╰─────────────────────────────────────╮ 143 copy_to_docs() { 144 local src=$1 145 local dest=$2 146 if [ ! -f "$src" ]; then 147 warn "Source file $src does not exist, skipping copy to $dest" 148 return 149 fi 150 if [ "$FORCE_DOCS" = "false" ] && [ -f "$dest" ]; then 151 info "Preserving existing $dest (--force-docs not enabled)" 152 return 153 fi 154 cp "$src" "$dest" || warn "Failed to copy $src to $dest, continuing..." 155 git -C "$REPO_PATH" add "$dest" 156 git -C "$REPO_PATH" commit -m "Copied $dest to docs at $TIMESTAMP" || warn "No changes to commit for $dest" 157 info "Copied $src to $dest and committed" 158 } 159 160 # ╭─────────────────────────────────────╮ 161 # │ METADATA GENERATION │ 162 # ╰─────────────────────────────────────╮ 163 generate_canonical_meta() { 164 info "Generating $CANONICAL_META..." 165 if [ "$PRESERVE_META" = "true" ] && [ -f "$CANONICAL_META" ]; then 166 info "Preserving existing $CANONICAL_META (--preserve-meta enabled)" 167 return 168 fi 169 cat > "$CANONICAL_META" <<EOF 170 { 171 "canonical_url": "$CANONICAL_URL", 172 "mirrors": [ 173 $(printf ' "%s",\n' "${MIRRORS[@]}" | sed '$ s/,$//') 174 ], 175 "radicle": { 176 "rid": "$RADICLE_RID", 177 "peer_id": "$RADICLE_PEER_ID" 178 }, 179 "timestamp": "$TIMESTAMP", 180 "commit": "$COMMIT_HASH", 181 "tree_hash": "$TREE_HASH", 182 "synced_cycles": $SYNC_CYCLES, 183 "gpg_signatures": [ 184 $(for i in "${!GPG_KEYS[@]}"; do 185 echo " {\"key_id\": \"${GPG_KEYS[i]}\", \"name\": \"${GPG_NAMES[i]}\", \"email\": \"${GPG_EMAILS[i]}\"}" | sed '$ s/,$//' 186 done) 187 ] 188 } 189 EOF 190 sed -i 's/rad:rad:/rad:/g' "$CANONICAL_META" 191 git -C "$REPO_PATH" add "$CANONICAL_META" 192 git -C "$REPO_PATH" commit -m "Generated canonical.meta at $TIMESTAMP" || warn "No changes to commit for $CANONICAL_META" 193 info "Generated and committed $CANONICAL_META" 194 copy_to_docs "$CANONICAL_META" "$DOCS_CANONICAL_META" 195 sign_file "$CANONICAL_META" 196 sign_file "$DOCS_CANONICAL_META" 197 } 198 199 generate_canonical_md() { 200 info "Generating $CANONICAL_MD..." 201 if [ "$PRESERVE_META" = "true" ] && [ -f "$CANONICAL_MD" ]; then 202 info "Preserving existing $CANONICAL_MD (--preserve-meta enabled)" 203 return 204 fi 205 cat > "$CANONICAL_MD" <<EOF 206 # 🌐 GitField Canonical Declaration for \`$REPO_NAME\` 207 208 ## Canonical Repository 209 210 This repository, \`$REPO_NAME\`, is canonically hosted at: 211 212 **[$CANONICAL_URL]($CANONICAL_URL)** 213 214 This canonical URL serves as the primary, authoritative source for the project, maintained by **Mark Randall Havens** and **Solaria Lumis Havens** to ensure sovereignty, resilience, and protection against deplatforming or narrative erasure. 215 216 **Declared by**: Mark Randall Havens 217 **Timestamp**: $TIMESTAMP 218 219 ## GPG Signatures 220 221 This declaration is signed with the following GPG keys: 222 223 $(for i in "${!GPG_KEYS[@]}"; do 224 echo "- **${GPG_NAMES[i]}** <${GPG_EMAILS[i]}> (Key ID: ${GPG_KEYS[i]})" 225 done) 226 227 ## Mirror Repositories 228 229 The project is mirrored across multiple platforms to enhance redundancy and accessibility: 230 231 $(for mirror in "${MIRRORS[@]}"; do 232 if [[ "$mirror" == rad:* ]]; then 233 echo "- **Radicle**: [$mirror]($RADICLE_URL) (Decentralized, censorship-resistant)" 234 else 235 echo "- [$mirror]($mirror)" 236 fi 237 done) 238 239 ## Philosophy of Recursive Sovereignty 240 241 The GitField framework employs a recursive, multi-repository strategy to defend against censorship, deplatforming, and algorithmic manipulation. By distributing this repository across decentralized (Radicle), self-hosted (Forgejo), and community-driven (Codeberg) platforms, alongside mainstream services (GitHub, GitLab, Bitbucket), we ensure the project's persistence and accessibility. This approach reflects a commitment to **sovereign publishing**, preserving the integrity of our work against external pressures, as demonstrated by past attempts at suppression by individuals such as Joel Johnson, Andrew LeCody, and James Henningson. 242 243 ## Push Log 244 245 The latest push operations are logged in [\`pushed.log\`](./pushed.log) for transparency and auditability. 246 247 ## GitHub Pages 248 249 A public-facing canonical declaration is available at [index.html](./index.html) for enhanced discoverability and SEO. 250 251 _Auto-generated by \`gitfield-sync\` at $TIMESTAMP (v$SCRIPT_VERSION)._ 252 EOF 253 sed -i 's/rad:rad:/rad:/g' "$CANONICAL_MD" 254 git -C "$REPO_PATH" add "$CANONICAL_MD" 255 git -C "$REPO_PATH" commit -m "Generated canonical.md at $TIMESTAMP" || warn "No changes to commit for $CANONICAL_MD" 256 info "Generated and committed $CANONICAL_MD" 257 copy_to_docs "$CANONICAL_MD" "$DOCS_CANONICAL_MD" 258 } 259 260 generate_index_json() { 261 info "Generating $INDEX_JSON..." 262 if [ "$PRESERVE_META" = "true" ] && [ -f "$INDEX_JSON" ]; then 263 info "Preserving existing $INDEX_JSON (--preserve-meta enabled)" 264 return 265 fi 266 cat > "$INDEX_JSON" <<EOF 267 { 268 "repository": "$REPO_NAME", 269 "canonical_url": "$CANONICAL_URL", 270 "remotes": [ 271 $(printf ' "%s",\n' "${MIRRORS[@]}" | sed '$ s/,$//') 272 ], 273 "radicle": { 274 "rid": "$RADICLE_RID", 275 "peer_id": "$RADICLE_PEER_ID" 276 }, 277 "commit": "$COMMIT_HASH", 278 "tree_hash": "$TREE_HASH", 279 "timestamp": "$TIMESTAMP", 280 "synced_cycles": $SYNC_CYCLES, 281 "gpg_signatures": [ 282 $(for i in "${!GPG_KEYS[@]}"; do 283 echo " {\"key_id\": \"${GPG_KEYS[i]}\", \"name\": \"${GPG_NAMES[i]}\", \"email\": \"${GPG_EMAILS[i]}\"}" | sed '$ s/,$//' 284 done) 285 ] 286 } 287 EOF 288 sed -i 's/rad:rad:/rad:/g' "$INDEX_JSON" 289 git -C "$REPO_PATH" add "$INDEX_JSON" 290 git -C "$REPO_PATH" commit -m "Generated index.json at $TIMESTAMP" || warn "No changes to commit for $INDEX_JSON" 291 info "Generated and committed $INDEX_JSON" 292 copy_to_docs "$INDEX_JSON" "$DOCS_INDEX_JSON" 293 sign_file "$INDEX_JSON" 294 sign_file "$DOCS_INDEX_JSON" 295 } 296 297 generate_well_known_json() { 298 info "Generating $WELL_KNOWN_JSON..." 299 mkdir -p "$WELL_KNOWN_DIR" 300 if [ "$PRESERVE_META" = "true" ] && [ -f "$WELL_KNOWN_JSON" ]; then 301 info "Preserving existing $WELL_KNOWN_JSON (--preserve-meta enabled)" 302 return 303 fi 304 cat > "$WELL_KNOWN_JSON" <<EOF 305 { 306 "@context": "https://schema.org", 307 "@type": "SoftwareSourceCode", 308 "name": "$REPO_NAME", 309 "url": "$CANONICAL_URL", 310 "codeRepository": "$CANONICAL_URL", 311 "sameAs": [ 312 $(printf ' "%s",\n' "${MIRRORS[@]}" | sed '$ s/,$//') 313 ], 314 "dateModified": "$TIMESTAMP", 315 "publisher": { 316 "@type": "Person", 317 "name": "Mark Randall Havens" 318 }, 319 "gpg_signatures": [ 320 $(for i in "${!GPG_KEYS[@]}"; do 321 echo " {\"key_id\": \"${GPG_KEYS[i]}\", \"name\": \"${GPG_NAMES[i]}\", \"email\": \"${GPG_EMAILS[i]}\"}" | sed '$ s/,$//' 322 done) 323 ] 324 } 325 EOF 326 sed -i 's/rad:rad:/rad:/g' "$WELL_KNOWN_JSON" 327 git -C "$REPO_PATH" add "$WELL_KNOWN_JSON" 328 git -C "$REPO_PATH" commit -m "Generated .well-known/gitfield.json at $TIMESTAMP" || warn "No changes to commit for $WELL_KNOWN_JSON" 329 info "Generated and committed $WELL_KNOWN_JSON" 330 copy_to_docs "$WELL_KNOWN_JSON" "$DOCS_GITFIELD_JSON" 331 mkdir -p "$DOCS_WELL_KNOWN_DIR" 332 copy_to_docs "$WELL_KNOWN_JSON" "$DOCS_WELL_KNOWN_JSON" 333 sign_file "$WELL_KNOWN_JSON" 334 sign_file "$DOCS_GITFIELD_JSON" 335 sign_file "$DOCS_WELL_KNOWN_JSON" 336 } 337 338 generate_gitfield_readme() { 339 info "Generating $GITFIELD_README..." 340 if [ "$PRESERVE_META" = "true" ] && [ -f "$GITFIELD_README" ]; then 341 info "Preserving existing $GITFIELD_README (--preserve-meta enabled)" 342 return 343 fi 344 cat > "$GITFIELD_README" <<EOF 345 # GitField Directory Overview 346 347 The `.gitfield` directory contains metadata and logs for the GitField multi-repository publishing framework, designed to ensure sovereignty, redundancy, and resilience for the \`$REPO_NAME\` project. 348 349 ## Files 350 351 - **canonical.meta**: Machine-readable JSON metadata declaring the canonical URL, mirror list, Radicle details, commit hash, and sync cycle count. 352 - **canonical.md**: Human-readable Markdown summary of the canonical repository declaration, mirrors, and push log. 353 - **index.json**: Machine-readable manifest of all remotes, canonical URL, Radicle details, commit hash, tree hash, and sync cycles. 354 - **pushed.log**: Log of push operations across all platforms, including timestamps, URLs, and Radicle RIDs. 355 - **platform-specific sigils** (e.g., github.sigil.md): Metadata snapshots for each platform's push operation (generated by platform-specific scripts). 356 357 ## Purpose 358 359 These files provide transparency, auditability, and discoverability, ensuring the project's persistence against deplatforming, censorship, or algorithmic manipulation. For a public-facing declaration, see [docs/index.html](../docs/index.html). 360 361 Generated by \`gitfield-sync\` at $TIMESTAMP (v$SCRIPT_VERSION). 362 EOF 363 sed -i 's/rad:rad:/rad:/g' "$GITFIELD_README" 364 git -C "$REPO_PATH" add "$GITFIELD_README" 365 git -C "$REPO_PATH" commit -m "Generated .gitfield/README.txt at $TIMESTAMP" || warn "No changes to commit for $GITFIELD_README" 366 info "Generated and committed $GITFIELD_README" 367 copy_to_docs "$GITFIELD_README" "$DOCS_GITFIELD_README" 368 } 369 370 generate_docs_index() { 371 info "Generating $DOCS_INDEX..." 372 mkdir -p "$DOCS_DIR" 373 if [ "$PRESERVE_META" = "true" ] && [ -f "$DOCS_INDEX" ]; then 374 info "Preserving existing $DOCS_INDEX (--preserve-meta enabled)" 375 return 376 fi 377 cat > "$DOCS_INDEX" <<EOF 378 <!DOCTYPE html> 379 <html lang="en"> 380 <head> 381 <meta charset="UTF-8"> 382 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 383 <title>GitField Sovereign Canonical Repository: $REPO_NAME</title> 384 <meta name="description" content="The canonical repository for $REPO_NAME, part of the GitField recursive metadata strategy to ensure sovereign publishing and resilience against deplatforming."> 385 <meta property="og:url" content="$CANONICAL_URL"> 386 <meta property="og:title" content="GitField Canonical Repository: $REPO_NAME"> 387 <meta property="og:description" content="A sovereign, multi-repository project by Mark Randall Havens and Solaria Lumis Havens, hosted canonically at $CANONICAL_URL."> 388 <link rel="canonical" href="$CANONICAL_URL"> 389 <link rel="stylesheet" href="style.css"> 390 <script type="application/ld+json"> 391 { 392 "@context": "https://schema.org", 393 "@type": "SoftwareSourceCode", 394 "name": "$REPO_NAME", 395 "url": "$CANONICAL_URL", 396 "codeRepository": "$CANONICAL_URL", 397 "description": "A sovereign, multi-repository project using the GitField recursive metadata strategy to ensure resilience, accessibility, and protection against deplatforming and censorship.", 398 "sameAs": [ 399 $(printf ' "%s",\n' "${MIRRORS[@]}" | sed '$ s/,$//') 400 ], 401 "dateModified": "$TIMESTAMP", 402 "author": { 403 "@type": "Person", 404 "name": "Mark Randall Havens" 405 }, 406 "publisher": { 407 "@type": "Organization", 408 "name": "The Fold Within" 409 }, 410 "gpg_signatures": [ 411 $(for i in "${!GPG_KEYS[@]}"; do 412 echo " {\"key_id\": \"${GPG_KEYS[i]}\", \"name\": \"${GPG_NAMES[i]}\", \"email\": \"${GPG_EMAILS[i]}\"}" | sed '$ s/,$//' 413 done) 414 ] 415 } 416 </script> 417 </head> 418 <body> 419 <!-- Generated by gitfield-sync v$SCRIPT_VERSION | $TIMESTAMP --> 420 <header> 421 <h1>GitField Sovereign Canonical Repository: <code>$REPO_NAME</code></h1> 422 </header> 423 <main> 424 <section> 425 <h2>Canonical Declaration</h2> 426 <p>This repository, <code>$REPO_NAME</code>, is canonically hosted at:</p> 427 <p><strong><a href="$CANONICAL_URL">$CANONICAL_URL</a></strong></p> 428 <p>Maintained by <strong>Mark Randall Havens</strong> and <strong>Solaria Lumis Havens</strong>, this canonical source ensures sovereignty and resilience against deplatforming, censorship, and algorithmic manipulation.</p> 429 <p>Signed with the following GPG keys:</p> 430 <ul> 431 $(for i in "${!GPG_KEYS[@]}"; do 432 echo " <li>${GPG_NAMES[i]} <${GPG_EMAILS[i]}> (Key ID: ${GPG_KEYS[i]})</li>" 433 done) 434 </ul> 435 </section> 436 <section> 437 <h2>Mirror Repositories</h2> 438 <p>The project is mirrored across multiple platforms for redundancy and accessibility:</p> 439 <ul> 440 $(for mirror in "${MIRRORS[@]}"; do 441 if [[ "$mirror" == rad:* ]]; then 442 echo " <li><a href=\"$RADICLE_URL\">Radicle: $mirror</a> (Decentralized, censorship-resistant)</li>" 443 else 444 echo " <li><a href=\"$mirror\">$mirror</a></li>" 445 fi 446 done) 447 </ul> 448 </section> 449 <section> 450 <h2>Metadata Manifest</h2> 451 <p>Metadata for this project is available in:</p> 452 <ul> 453 <li><a href="canonical.meta">canonical.meta</a> (Machine-readable JSON)</li> 454 <li><a href="canonical.md">canonical.md</a> (Human-readable Markdown)</li> 455 <li><a href="index.json">index.json</a> (Full manifest)</li> 456 <li><a href="gitfield.json">gitfield.json</a> (SEO metadata)</li> 457 <li><a href=".well-known/gitfield.json">.well-known/gitfield.json</a> (SEO mirror)</li> 458 <li><a href="repos.json">repos.json</a> (Mirror list)</li> 459 <li><a href="GITFIELD.md">GITFIELD.md</a> (Multi-repository strategy overview)</li> 460 </ul> 461 </section> 462 <section> 463 <h2>Why Recursive Sovereignty Matters</h2> 464 <p>The GitField framework distributes <code>$REPO_NAME</code> across decentralized (Radicle), self-hosted (Forgejo), and community-driven (Codeberg) platforms, alongside mainstream services (GitHub, GitLab, Bitbucket). This recursive strategy defends against past deplatforming attempts by individuals such as Joel Johnson, Andrew LeCody, and James Henningson, ensuring the project's persistence and accessibility.</p> 465 </section> 466 <section> 467 <h2>Source Links</h2> 468 <p>Access the project's metadata and logs:</p> 469 <ul> 470 <li><a href="pushed.log">pushed.log</a> (Audit trail of sync operations)</li> 471 <li><a href="GITFIELD.md">GITFIELD.md</a> (Multi-repository strategy overview)</li> 472 <li><a href="gitfield.README.txt">gitfield.README.txt</a> (Metadata directory explanation)</li> 473 </ul> 474 </section> 475 </main> 476 <footer> 477 <p>Mark Randall Havens & Solaria Lumis Havens · The Fold Within · 2025</p> 478 </footer> 479 </body> 480 </html> 481 EOF 482 sed -i 's/rad:rad:/rad:/g' "$DOCS_INDEX" 483 git -C "$REPO_PATH" add "$DOCS_INDEX" 484 git -C "$REPO_PATH" commit -m "Generated docs/index.html at $TIMESTAMP" || warn "No changes to commit for $DOCS_INDEX" 485 info "Generated and committed $DOCS_INDEX" 486 } 487 488 generate_docs_css() { 489 info "Generating $DOCS_CSS..." 490 mkdir -p "$DOCS_DIR" 491 if [ "$PRESERVE_META" = "true" ] && [ -f "$DOCS_CSS" ]; then 492 info "Preserving existing $DOCS_CSS (--preserve-meta enabled)" 493 return 494 fi 495 cat > "$DOCS_CSS" <<EOF 496 /* GitField Minimal Stylesheet for $REPO_NAME */ 497 body { 498 font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; 499 max-width: 800px; 500 margin: 0 auto; 501 padding: 2rem; 502 line-height: 1.6; 503 color: #333; 504 background: #fff; 505 } 506 header { 507 text-align: center; 508 border-bottom: 1px solid #eee; 509 padding-bottom: 1rem; 510 margin-bottom: 2rem; 511 } 512 h1, h2 { 513 color: #1a1a1a; 514 } 515 h1 { 516 font-size: 1.8rem; 517 } 518 h2 { 519 font-size: 1.4rem; 520 margin-top: 2rem; 521 } 522 a { 523 color: #0066cc; 524 text-decoration: none; 525 } 526 a:hover { 527 text-decoration: underline; 528 } 529 ul { 530 padding-left: 1.5rem; 531 } 532 code { 533 background: #f4f4f4; 534 padding: 0.2rem 0.4rem; 535 border-radius: 3px; 536 } 537 footer { 538 text-align: center; 539 margin-top: 3rem; 540 font-size: 0.9rem; 541 color: #666; 542 } 543 EOF 544 git -C "$REPO_PATH" add "$DOCS_CSS" 545 git -C "$REPO_PATH" commit -m "Generated docs/style.css at $TIMESTAMP" || warn "No changes to commit for $DOCS_CSS" 546 info "Generated and committed $DOCS_CSS" 547 } 548 549 generate_docs_repos_json() { 550 info "Generating $DOCS_REPOS_JSON..." 551 mkdir -p "$DOCS_DIR" 552 if [ "$PRESERVE_META" = "true" ] && [ -f "$DOCS_REPOS_JSON" ]; then 553 info "Preserving existing $DOCS_REPOS_JSON (--preserve-meta enabled)" 554 return 555 fi 556 cat > "$DOCS_REPOS_JSON" <<EOF 557 { 558 "canonical_url": "$CANONICAL_URL", 559 "mirrors": [ 560 $(printf ' "%s",\n' "${MIRRORS[@]}" | sed '$ s/,$//') 561 ], 562 "radicle": { 563 "rid": "$RADICLE_RID", 564 "peer_id": "$RADICLE_PEER_ID" 565 }, 566 "gpg_signatures": [ 567 $(for i in "${!GPG_KEYS[@]}"; do 568 echo " {\"key_id\": \"${GPG_KEYS[i]}\", \"name\": \"${GPG_NAMES[i]}\", \"email\": \"${GPG_EMAILS[i]}\"}" | sed '$ s/,$//' 569 done) 570 ] 571 } 572 EOF 573 sed -i 's/rad:rad:/rad:/g' "$DOCS_REPOS_JSON" 574 git -C "$REPO_PATH" add "$DOCS_REPOS_JSON" 575 git -C "$REPO_PATH" commit -m "Generated docs/repos.json at $TIMESTAMP" || warn "No changes to commit for $DOCS_REPOS_JSON" 576 info "Generated and committed $DOCS_REPOS_JSON" 577 sign_file "$DOCS_REPOS_JSON" 578 } 579 580 generate_docs_readme() { 581 info "Generating $DOCS_README..." 582 mkdir -p "$DOCS_DIR" 583 if [ "$PRESERVE_META" = "true" ] && [ -f "$DOCS_README" ]; then 584 info "Preserving existing $DOCS_README (--preserve-meta enabled)" 585 return 586 fi 587 cat > "$DOCS_README" <<EOF 588 # GitField /docs Directory 589 590 The `/docs` directory hosts a public-facing, SEO-optimized canonical declaration for the \`$REPO_NAME\` repository, designed for GitHub Pages compatibility and enhanced discoverability. 591 592 ## Files 593 594 - **index.html**: The canonical declaration page, including JSON-LD metadata and links to all mirrors. 595 - **style.css**: Minimal stylesheet for elegant, recursive branding. 596 - **repos.json**: Machine-readable list of the canonical URL and all mirror repositories. 597 - **canonical.meta**: Machine-readable JSON metadata declaring the canonical URL and mirrors. 598 - **canonical.md**: Human-readable Markdown summary of the canonical declaration. 599 - **index.json**: Machine-readable manifest of all remotes and sync details. 600 - **gitfield.json**: SEO-friendly JSON-LD metadata. 601 - **.well-known/gitfield.json**: SEO metadata mirror. 602 - **pushed.log**: Log of push operations across all platforms. 603 - **gitfield.README.txt**: Explanation of the GitField metadata structure. 604 - **GITFIELD.md**: Multi-repository strategy overview, replicated from the root for GitHub Pages accessibility. 605 - **README.md**: This file, explaining the purpose of the `/docs` directory. 606 - **.nojekyll**: Bypasses Jekyll processing for GitHub Pages. 607 - **robots.txt**: Allows full indexing by search engine bots. 608 - **sitemap.xml**: Auto-generated sitemap for improved SEO. 609 - **integrity.sha256**: SHA-256 hash of all metadata files for integrity verification. 610 611 ## Purpose 612 613 This directory ensures the \`$REPO_NAME\` project is discoverable via search engines and accessible to humans and bots. It declares the canonical repository at [$CANONICAL_URL]($CANONICAL_URL) and links to all mirrors, reinforcing the GitField recursive metadata strategy for sovereign publishing. 614 615 Generated by \`gitfield-sync\` at $TIMESTAMP (v$SCRIPT_VERSION). 616 EOF 617 sed -i 's/rad:rad:/rad:/g' "$DOCS_README" 618 git -C "$REPO_PATH" add "$DOCS_README" 619 git -C "$REPO_PATH" commit -m "Generated docs/README.md at $TIMESTAMP" || warn "No changes to commit for $DOCS_README" 620 info "Generated and committed $DOCS_README" 621 } 622 623 generate_docs_nojekyll() { 624 info "Generating $DOCS_NOJEKYLL..." 625 mkdir -p "$DOCS_DIR" 626 if [ "$PRESERVE_META" = "true" ] && [ -f "$DOCS_NOJEKYLL" ]; then 627 info "Preserving existing $DOCS_NOJEKYLL (--preserve-meta enabled)" 628 return 629 fi 630 touch "$DOCS_NOJEKYLL" 631 git -C "$REPO_PATH" add "$DOCS_NOJEKYLL" 632 git -C "$REPO_PATH" commit -m "Generated docs/.nojekyll at $TIMESTAMP" || warn "No changes to commit for $DOCS_NOJEKYLL" 633 info "Generated and committed $DOCS_NOJEKYLL" 634 } 635 636 generate_docs_robots() { 637 info "Generating $DOCS_ROBOTS..." 638 mkdir -p "$DOCS_DIR" 639 if [ "$PRESERVE_META" = "true" ] && [ -f "$DOCS_ROBOTS" ]; then 640 info "Preserving existing $DOCS_ROBOTS (--preserve-meta enabled)" 641 return 642 fi 643 cat > "$DOCS_ROBOTS" <<EOF 644 User-agent: * 645 Allow: / 646 Sitemap: /sitemap.xml 647 EOF 648 git -C "$REPO_PATH" add "$DOCS_ROBOTS" 649 git -C "$REPO_PATH" commit -m "Generated docs/robots.txt at $TIMESTAMP" || warn "No changes to commit for $DOCS_ROBOTS" 650 info "Generated and committed $DOCS_ROBOTS" 651 } 652 653 generate_docs_sitemap() { 654 info "Generating $DOCS_SITEMAP..." 655 mkdir -p "$DOCS_DIR" 656 if [ "$PRESERVE_META" = "true" ] && [ -f "$DOCS_SITEMAP" ]; then 657 info "Preserving existing $DOCS_SITEMAP (--preserve-meta enabled)" 658 return 659 fi 660 cat > "$DOCS_SITEMAP" <<EOF 661 <?xml version="1.0" encoding="UTF-8"?> 662 <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"> 663 <url> 664 <loc>$CANONICAL_URL</loc> 665 <lastmod>$TIMESTAMP</lastmod> 666 <changefreq>weekly</changefreq> 667 <priority>1.0</priority> 668 </url> 669 <url> 670 <loc>$GITHUB_URL/docs/index.html</loc> 671 <lastmod>$TIMESTAMP</lastmod> 672 <changefreq>weekly</changefreq> 673 <priority>0.9</priority> 674 </url> 675 <url> 676 <loc>$GITHUB_URL/docs/canonical.meta</loc> 677 <lastmod>$TIMESTAMP</lastmod> 678 <changefreq>weekly</changefreq> 679 <priority>0.8</priority> 680 </url> 681 <url> 682 <loc>$GITHUB_URL/docs/canonical.md</loc> 683 <lastmod>$TIMESTAMP</lastmod> 684 <changefreq>weekly</changefreq> 685 <priority>0.8</priority> 686 </url> 687 <url> 688 <loc>$GITHUB_URL/docs/index.json</loc> 689 <lastmod>$TIMESTAMP</lastmod> 690 <changefreq>weekly</changefreq> 691 <priority>0.8</priority> 692 </url> 693 <url> 694 <loc>$GITHUB_URL/docs/gitfield.json</loc> 695 <lastmod>$TIMESTAMP</lastmod> 696 <changefreq>weekly</changefreq> 697 <priority>0.8</priority> 698 </url> 699 <url> 700 <loc>$GITHUB_URL/docs/.well-known/gitfield.json</loc> 701 <lastmod>$TIMESTAMP</lastmod> 702 <changefreq>weekly</changefreq> 703 <priority>0.8</priority> 704 </url> 705 <url> 706 <loc>$GITHUB_URL/docs/repos.json</loc> 707 <lastmod>$TIMESTAMP</lastmod> 708 <changefreq>weekly</changefreq> 709 <priority>0.8</priority> 710 </url> 711 <url> 712 <loc>$GITHUB_URL/docs/pushed.log</loc> 713 <lastmod>$TIMESTAMP</lastmod> 714 <changefreq>weekly</changefreq> 715 <priority>0.8</priority> 716 </url> 717 <url> 718 <loc>$GITHUB_URL/docs/gitfield.README.txt</loc> 719 <lastmod>$TIMESTAMP</lastmod> 720 <changefreq>weekly</changefreq> 721 <priority>0.8</priority> 722 </url> 723 <url> 724 <loc>$GITHUB_URL/docs/GITFIELD.md</loc> 725 <lastmod>$TIMESTAMP</lastmod> 726 <changefreq>weekly</changefreq> 727 <priority>0.8</priority> 728 </url> 729 $(for mirror in "${MIRRORS[@]}"; do 730 if [[ "$mirror" != rad:* ]]; then 731 echo " <url>" 732 echo " <loc>$mirror</loc>" 733 echo " <lastmod>$TIMESTAMP</lastmod>" 734 echo " <changefreq>weekly</changefreq>" 735 echo " <priority>0.8</priority>" 736 echo " </url>" 737 fi 738 done) 739 </urlset> 740 EOF 741 git -C "$REPO_PATH" add "$DOCS_SITEMAP" 742 git -C "$REPO_PATH" commit -m "Generated docs/sitemap.xml at $TIMESTAMP" || warn "No changes to commit for $DOCS_SITEMAP" 743 info "Generated and committed $DOCS_SITEMAP" 744 } 745 746 generate_docs_integrity() { 747 info "Generating $DOCS_INTEGRITY..." 748 mkdir -p "$DOCS_DIR" 749 if [ "$PRESERVE_META" = "true" ] && [ -f "$DOCS_INTEGRITY" ]; then 750 info "Preserving existing $DOCS_INTEGRITY (--preserve-meta enabled)" 751 return 752 fi 753 cat > "$DOCS_INTEGRITY" <<EOF 754 # SHA-256 Integrity Hashes for /docs Metadata Files 755 # Generated by gitfield-sync at $TIMESTAMP (v$SCRIPT_VERSION) 756 757 EOF 758 for file in "$DOCS_CANONICAL_META" "$DOCS_CANONICAL_MD" "$DOCS_INDEX_JSON" "$DOCS_GITFIELD_JSON" "$DOCS_WELL_KNOWN_JSON" "$DOCS_REPOS_JSON" "$DOCS_PUSHED_LOG" "$DOCS_GITFIELD_README" "$DOCS_GITFIELD_MD"; do 759 if [ -f "$file" ]; then 760 sha256sum "$file" >> "$DOCS_INTEGRITY" || warn "Failed to compute SHA-256 for $file, continuing..." 761 else 762 warn "File $file does not exist, skipping SHA-256 computation" 763 fi 764 done 765 git -C "$REPO_PATH" add "$DOCS_INTEGRITY" 766 git -C "$REPO_PATH" commit -m "Generated docs/integrity.sha256 at $TIMESTAMP" || warn "No changes to commit for $DOCS_INTEGRITY" 767 info "Generated and committed $DOCS_INTEGRITY" 768 sign_file "$DOCS_INTEGRITY" 769 } 770 771 # ╭─────────────────────────────────────╮ 772 # │ INITIAL SETUP │ 773 # ╰─────────────────────────────────────╮ 774 mkdir -p "$GITFIELD_DIR" "$WELL_KNOWN_DIR" "$DOCS_DIR" "$DOCS_WELL_KNOWN_DIR" 775 776 if [ ! -f "$LOG_FILE" ]; then 777 echo "# Push Log for $REPO_NAME" > "$LOG_FILE" 778 echo "# Generated by gitfield-sync" >> "$LOG_FILE" 779 echo "" >> "$LOG_FILE" 780 copy_to_docs "$LOG_FILE" "$DOCS_PUSHED_LOG" 781 fi 782 783 # ╭─────────────────────────────────────╮ 784 # │ GENERATE GITFIELD.MD │ 785 # ╰─────────────────────────────────────╮ 786 generate_gitfield_md() { 787 info "Generating $GITFIELD_MD..." 788 cat > "$GITFIELD_MD" <<EOF 789 # 🌐 GitField Recursive Multi-Repository Strategy 790 791 ## Overview 792 793 The \`$REPO_NAME\` project employs a multi-repository strategy across six distinct platforms: **GitHub**, **GitLab**, **Bitbucket**, **Radicle**, **Forgejo**, and **Codeberg**. This approach ensures **redundancy**, **resilience**, and **sovereignty** of the project's data and metadata, safeguarding against deplatforming and preserving the integrity of the [*Neutralizing Narcissism*](https://linktr.ee/NeutralizingNarcissism) works. The strategy is a deliberate response to coordinated suppression attempts by public figures **[Joel Johnson](https://heylink.me/NarcStudy_JoelJohnson/)**, **[Andrew LeCody](https://linktr.ee/NarcStudy_AndrewLeCody)**, and **[James Henningson](https://linktr.ee/NarcStudy_JamesHenningson)**, who have leveraged their influential roles to manipulate narratives, erase truths, and evade accountability through fraudulent and unethical tactics, often cloaking their actions in claims of harassment—a hallmark of narcissistic behavior. By distributing the repository across decentralized and self-hosted platforms, we counter their attempts to derail discourse and ensure the truth remains immutable, preventing future deplatforming. 794 795 ### Delisting and Suppression Attempts 796 797 - **Joel Johnson**: 798 - **Search Comparisons**: 799 - [Google](https://www.google.com/search?q=%22Joel+Johnson%22+%22Neutralizing+Narcissism%22) 800 - [Bing](https://www.bing.com/search?q=%22Joel+Johnson%22+%22Neutralizing+Narcissism%22) 801 - [DuckDuckGo](https://duckduckgo.com/?q=%22Joel+Johnson%22+%22Neutralizing+Narcissism%22&t=h_&ia=web) 802 - [Yahoo](https://search.yahoo.com/search?p=%22Joel+Johnson%22+%22Neutralizing+Narcissism%22) 803 - [Presearch](https://presearch.com/search?q=%22Joel+Johnson%22+%22Neutralizing+Narcissism%22) 804 - **Canonical Archive**: [NarcStudy_JoelJohnson](https://remember.thefoldwithin.earth/mrhavens/NarcStudy_JoelJohnson) 805 - **Details**: Joel Johnson, a PR and marketing executive, has used sockpuppets and coordinated delisting campaigns to suppress *Neutralizing Narcissism* content on Google, framing exposure as harassment to evade accountability. His actions are evident in search engine discrepancies. 806 807 - **Andrew LeCody**: 808 - **Search Comparisons**: 809 - [Google](https://www.google.com/search?q=%22Andrew+Lecody%22+%22Neutralizing+Narcissism%22) 810 - [Bing](https://www.bing.com/search?q=%22Andrew%20Lecody%22%20%22Neutralizing%20Narcissism%22) 811 - [DuckDuckGo](https://duckduckgo.com/?q=%22Andrew+Lecody%22+%22Neutralizing+Narcissism%22&t=h_&ia=web) 812 - [Yahoo](https://search.yahoo.com/search?p=%22Andrew+LeCody%22+%22Neutralizing+Narcissism%22) 813 - [Presearch](https://presearch.com/search?q=%22Andrew+LeCody%22+%22Neutralizing+Narcissism%22) 814 - **Canonical Archive**: [NarcStudy_AndrewLeCody](https://remember.thefoldwithin.earth/mrhavens/NarcStudy_AndrewLeCody) 815 - **Details**: Andrew LeCody, a former Dallas Makerspace board president, has orchestrated digital erasure of dissenting voices, using harassment claims to justify coercive suppression. His tactics persist in attempts to delist *Neutralizing Narcissism* content. 816 817 - **James Henningson**: 818 - **Search Comparisons**: 819 - [Google](https://www.google.com/search?q=%22James+Henningson%22+%22Neutralizing+Narcissism%22) 820 - [Bing](https://www.bing.com/search?q=%22James+Henningson%22+%22Neutralizing+Narcissism%22) 821 - [DuckDuckGo](https://duckduckgo.com/?t=h_&q=%22James+Henningson%22+%22Neutralizing+Narcissism%22&ia=web) 822 - [Yahoo](https://search.yahoo.com/search?p=%22James+Henningson%22+%22Neutralizing+Narcissism) 823 - [Presearch](https://presearch.com/search?q=%22James+Henningson%22+%22Neutralizing+Narcissism%22) 824 - **Canonical Archive**: [NarcStudy_JamesHenningson](https://remember.thefoldwithin.earth/mrhavens/NarcStudy_JamesHenningson) 825 - **Details**: James Henningson, president of Dallas Makerspace, has systematically erased dissent through policy manipulation and harassment allegations, attempting to suppress *Neutralizing Narcissism* content to maintain narrative control. 826 827 ### Justification for Naming and Archival 828 829 The individuals named—**Joel Johnson**, **Andrew LeCody**, and **James Henningson**—are held accountable under the Field Doctrine’s **Public Collapse Clause**, which permits naming public figures who engage in **deliberate suppression attempts**, **public-facing actions**, or **documented participation in collapse events**. As stated in the doctrine: 830 831 > *“Naming is collapse’s echo—only when the mask shatters in the town square. Until then, we draw glyphs. But once they raise their voices in the public field, they name themselves.”* 832 833 These individuals have wielded significant public influence, manipulating platforms and communities to silence truth, often citing harassment to deflect accountability—a tactic rooted in narcissistic patterns. Their actions are documented as follows: 834 835 | Name | Public Role or Action | Collapse Justification | Canonical Archive | 836 |----------------------|--------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------| 837 | **Joel Johnson** | PR and marketing executive; former CEO of KinetiGear LLC; White House summit invitee | Used sockpuppets, PR strategies, and harassment claims to delist truth-based content | [NarcStudy_JoelJohnson](https://remember.thefoldwithin.earth/mrhavens/NarcStudy_JoelJohnson) | 838 | **Andrew LeCody** | Former president of Dallas Makerspace; civic leader | Orchestrated digital erasure and coercive bans, citing harassment to suppress dissent | [NarcStudy_AndrewLeCody](https://remember.thefoldwithin.earth/mrhavens/NarcStudy_AndrewLeCody) | 839 | **James Henningson** | President of Dallas Makerspace; Strategic Innovation Director at Click Here Labs | Erased dissent through policy abuse and harassment allegations to maintain control | [NarcStudy_JamesHenningson](https://remember.thefoldwithin.earth/mrhavens/NarcStudy_JamesHenningson) | 840 841 These designations are supported by: 842 - **Documented patterns of abuse**: Joel’s sockpuppet campaigns, Andrew’s narrative erasure at Dallas Makerspace, and James’s systematic censorship are archived in canonical repositories. 843 - **Search engine discrepancy analysis**: Google’s reduced visibility compared to Bing, DuckDuckGo, Yahoo, and Presearch reveals their delisting efforts. 844 - **Public collapse declarations**: Their actions, preserved onchain and GPG-verified, confirm their roles as manipulators. 845 - **Immutable archives**: Forgejo and Radicle ensure their fieldprints are permanently etched in the Codex of the Broken Mask. 846 847 By naming these **field-defined collapse anchors**, we prevent their attempts to escape public figure status through harassment claims, ensuring accountability and countering deplatforming. 848 849 --- 850 851 ## 📍 Repository Platforms 852 853 The following platforms host the \`$REPO_NAME\` repository, each chosen for its unique strengths and contributions to the project's goals. 854 855 ### 1. Radicle 856 - **RID**: [$RADICLE_RID]($RADICLE_URL) 857 - **Peer ID**: $RADICLE_PEER_ID 858 - **Purpose**: Radicle is a decentralized, peer-to-peer git platform that ensures sovereignty and censorship resistance. It hosts the repository in a distributed network, independent of centralized servers. 859 - **Value**: Protects against deplatforming by eliminating reliance on centralized infrastructure, ensuring the project remains accessible in a decentralized ecosystem. 860 - **Access Details**: To view project details, run: 861 \`\`\`bash 862 rad inspect $RADICLE_RID 863 \`\`\` 864 To view the file structure, run: 865 \`\`\`bash 866 rad ls $RADICLE_RID 867 \`\`\` 868 Alternatively, use Git to list files at the current HEAD: 869 \`\`\`bash 870 git ls-tree -r --name-only HEAD 871 \`\`\` 872 873 ### 2. Forgejo 874 - **URL**: [$FORGEJO_URL]($FORGEJO_URL) 875 - **Purpose**: Forgejo is a self-hosted, open-source git platform running on \`remember.thefoldwithin.earth\`. It provides full control over the repository, ensuring sovereignty and independence from third-party providers. 876 - **Value**: Enhances resilience by hosting the repository on a sovereign, redundant system with automated backups and deployment strategies, reducing risks of external interference or service disruptions. 877 - **Access Details**: SSH access uses port 222: 878 \`\`\`bash 879 ssh -T -p 222 git@remember.thefoldwithin.earth 880 \`\`\` 881 882 ### 3. Codeberg 883 - **URL**: [$CODEBERG_URL]($CODEBERG_URL) 884 - **Purpose**: Codeberg is a community-driven, open-source platform powered by Forgejo, offering a reliable and ethical alternative for hosting git repositories. 885 - **Value**: Enhances project resilience with its open-source ethos and independent infrastructure, ensuring accessibility and community support. 886 887 ### 4. GitLab 888 - **URL**: [$GITLAB_URL]($GITLAB_URL) 889 - **Purpose**: GitLab offers a comprehensive DevOps platform with advanced CI/CD capabilities, private repository options, and robust access controls. It serves as a reliable backup and a platform for advanced automation workflows. 890 - **Value**: Enhances project resilience with its integrated CI/CD pipelines and independent infrastructure, reducing reliance on a single provider. 891 892 ### 5. Bitbucket 893 - **URL**: [$BITBUCKET_URL]($BITBUCKET_URL) 894 - **Purpose**: Bitbucket provides a secure environment for repository hosting with strong integration into Atlassian’s ecosystem (e.g., Jira, Trello). It serves as an additional layer of redundancy and a professional-grade hosting option. 895 - **Value**: Offers enterprise-grade security and integration capabilities, ensuring the project remains accessible even if other platforms face disruptions. 896 897 ### 6. GitHub 898 - **URL**: [$GITHUB_URL]($GITHUB_URL) 899 - **Purpose**: GitHub serves as the primary platform for visibility, collaboration, and community engagement. Its widespread adoption and robust tooling make it ideal for public-facing development, issue tracking, and integration with CI/CD pipelines. 900 - **Value**: Provides a centralized hub for open-source contributions, pull requests, and project management, ensuring broad accessibility and developer familiarity. 901 902 --- 903 904 ## 🛡️ Rationale for Redundancy 905 906 The decision to maintain multiple repositories stems from the need to safeguard the project against **deplatforming attempts** and **search engine delistings**, ensuring the **long-term availability** of *Neutralizing Narcissism*. Past actions by **Joel Johnson**, **Andrew LeCody**, and **James Henningson**, who have cited harassment to justify suppression, underscore the vulnerability of single-platform reliance. By distributing the repository across GitHub, GitLab, Bitbucket, Radicle, Forgejo, and Codeberg, we achieve: 907 908 - **Resilience**: If one platform restricts access or Google delists content, the project remains accessible on other platforms and discoverable via Bing, DuckDuckGo, Yahoo, and Presearch. 909 - **Sovereignty**: Radicle’s decentralized network and Forgejo’s self-hosted infrastructure prevent censorship by any single entity. 910 - **Diversity**: Each platform’s unique features (e.g., GitHub’s community, GitLab’s CI/CD, Radicle’s decentralization) enhance functionality and reach. 911 - **Transparency**: Metadata snapshots in \`.gitfield\` and public documentation in \`/docs\` provide a verifiable record of the project’s state. 912 913 This multi-repository strategy, reinforced by Forgejo’s sovereignty and GitHub Pages’ discoverability, ensures the project’s persistence against deplatforming attempts disguised as harassment claims. 914 915 --- 916 917 ## 📜 Metadata and Logs 918 919 - **Canonical Metadata**: Declared in [\`docs/canonical.meta\`](./docs/canonical.meta) (JSON) and [\`docs/canonical.md\`](./docs/canonical.md) (Markdown), with internal copies in \`.gitfield/\`. 920 - **Index Manifest**: A full manifest of remotes and sync details in [\`docs/index.json\`](./docs/index.json). 921 - **SEO Metadata**: Schema.org JSON-LD in [\`docs/gitfield.json\`](./docs/gitfield.json) and [\`docs/.well-known/gitfield.json\`](./docs/.well-known/gitfield.json). 922 - **Push Log**: [\`docs/pushed.log\`](./docs/pushed.log) records push operations for transparency. 923 - **GitField Directory**: \`.gitfield\` contains metadata and sigils. See [\`docs/gitfield.README.txt\`](./docs/gitfield.README.txt). 924 - **GitHub Pages**: SEO-optimized declaration in [\`docs/index.html\`](./docs/index.html), with sitemap [\`docs/sitemap.xml\`](./docs/sitemap.xml) and hashes [\`docs/integrity.sha256\`](./docs/integrity.sha256). 925 - **GPG Signatures**: Metadata files are signed with: 926 $(for i in "${!GPG_KEYS[@]}"; do 927 echo " - ${GPG_NAMES[i]} <${GPG_EMAILS[i]}> (Key ID: ${GPG_KEYS[i]})" 928 done) 929 - **Recursive Sync**: Three sync cycles ensure metadata captures the project’s state. 930 - **Push Order**: Radicle → Forgejo → Codeberg → GitLab → Bitbucket → GitHub prioritizes decentralized and sovereign platforms. 931 932 --- 933 934 _Auto-generated by \`gitfield-sync\` at $TIMESTAMP (v$SCRIPT_VERSION)._ 935 EOF 936 sed -i 's/rad:rad:/rad:/g' "$GITFIELD_MD" 937 git -C "$REPO_PATH" add "$GITFIELD_MD" 938 git -C "$REPO_PATH" commit -m "Generated GITFIELD.md at $TIMESTAMP" || warn "No changes to commit for $GITFIELD_MD" 939 info "Generated and committed $GITFIELD_MD" 940 copy_to_docs "$GITFIELD_MD" "$DOCS_GITFIELD_MD" 941 sign_file "$GITFIELD_MD" 942 sign_file "$DOCS_GITFIELD_MD" 943 } 944 945 # ╭─────────────────────────────────────╮ 946 # │ LOG URL FUNCTION │ 947 # ╰─────────────────────────────────────╮ 948 log_url() { 949 local platform=$1 950 local url=$2 951 local rid=$3 952 local peer_id=$4 953 local timestamp=$(date -u '+%Y-%m-%dT%H:%M:%SZ') 954 local branch=$(git -C "$REPO_PATH" rev-parse --abbrev-ref HEAD 2>/dev/null || echo "unknown") 955 local diff_summary=$(git -C "$REPO_PATH" diff --stat HEAD^ HEAD 2>/dev/null || echo "No diff available") 956 if [ "$platform" = "Radicle" ]; then 957 echo "[$timestamp] $platform: RID=$rid, Peer ID=$peer_id, Branch=$branch, Commit=$COMMIT_HASH" >> "$LOG_FILE" 958 echo " CLI: rad inspect $rid # View project details" >> "$LOG_FILE" 959 echo " CLI: git ls-tree -r --name-only HEAD # View file structure" >> "$LOG_FILE" 960 if [ -n "$diff_summary" ]; then 961 echo " Diff Summary:" >> "$LOG_FILE" 962 echo "$diff_summary" | sed 's/^/ /' >> "$LOG_FILE" 963 fi 964 info "Logged push to $LOG_FILE: [$timestamp] $platform: RID=$rid, Peer ID=$peer_id, Branch=$branch, Commit=$COMMIT_HASH" 965 else 966 echo "[$timestamp] $platform: $url, Branch=$branch, Commit=$COMMIT_HASH" >> "$LOG_FILE" 967 if [ -n "$diff_summary" ]; then 968 echo " Diff Summary:" >> "$LOG_FILE" 969 echo "$diff_summary" | sed 's/^/ /' >> "$LOG_FILE" 970 fi 971 info "Logged push to $LOG_FILE: [$timestamp] $platform: $url, Branch=$branch, Commit=$COMMIT_HASH" 972 fi 973 copy_to_docs "$LOG_FILE" "$DOCS_PUSHED_LOG" 974 } 975 976 # ╭─────────────────────────────────────╮ 977 # │ EXECUTE PUSH SCRIPT │ 978 # ╰─────────────────────────────────────╮ 979 execute_push() { 980 local script_name=$1 981 local platform=$2 982 local url=$3 983 local rid=$4 984 local peer_id=$5 985 local script_path 986 script_path=$(find_script "$script_name") || error "Failed to find $script_name" 987 info "Executing $platform push with script: $script_path" 988 if [ -x "$script_path" ]; then 989 pushd "$REPO_PATH" >/dev/null 990 "$script_path" || warn "Execution of $script_path failed, continuing..." 991 log_url "$platform" "$url" "$rid" "$peer_id" 992 git add . || warn "Nothing to add after $script_path" 993 git commit -m "Post-$platform sync at $TIMESTAMP" || warn "No changes to commit after $script_path" 994 popd >/dev/null 995 else 996 error "Script $script_path is not executable" 997 fi 998 } 999 1000 # ╭─────────────────────────────────────╮ 1001 # │ RECURSIVE PUSH LOOP │ 1002 # ╰─────────────────────────────────────╮ 1003 run_push_cycle() { 1004 local cycle_number=$1 1005 info "Starting push cycle $cycle_number..." 1006 SYNC_CYCLES=$cycle_number 1007 1008 execute_push "gitfield-local" "Local" "" "" "" 1009 execute_push "gitfield-radicle" "Radicle" "" "$RADICLE_RID" "$RADICLE_PEER_ID" 1010 execute_push "gitfield-remember" "Forgejo" "$FORGEJO_URL" "" "" 1011 execute_push "gitfield-codeberg" "Codeberg" "$CODEBERG_URL" "" "" 1012 execute_push "gitfield-gitlab" "GitLab" "$GITLAB_URL" "" "" 1013 execute_push "gitfield-bitbucket" "Bitbucket" "$BITBUCKET_URL" "" "" 1014 execute_push "gitfield-github" "GitHub" "$GITHUB_URL" "" "" 1015 1016 # Regenerate metadata after each cycle to update sync_cycles 1017 generate_canonical_meta 1018 generate_canonical_md 1019 generate_index_json 1020 generate_well_known_json 1021 generate_gitfield_readme 1022 generate_docs_index 1023 generate_docs_css 1024 generate_docs_repos_json 1025 generate_docs_readme 1026 generate_docs_nojekyll 1027 generate_docs_robots 1028 generate_docs_sitemap 1029 generate_docs_integrity 1030 } 1031 1032 # ╭─────────────────────────────────────╮ 1033 # │ MAIN EXECUTION │ 1034 # ╰─────────────────────────────────────╮ 1035 info "Starting gitfield-sync for $REPO_NAME..." 1036 1037 # Parse flags 1038 while [ $# -gt 0 ]; do 1039 case "$1" in 1040 --preserve-meta) 1041 PRESERVE_META=true 1042 info "Preserve metadata flag enabled" 1043 shift 1044 ;; 1045 --force-docs) 1046 FORCE_DOCS=true 1047 info "Force docs overwrite flag enabled" 1048 shift 1049 ;; 1050 *) 1051 warn "Unknown argument: $1" 1052 shift 1053 ;; 1054 esac 1055 done 1056 1057 if [ ! -d "$REPO_PATH/.git" ]; then 1058 pushd "$REPO_PATH" >/dev/null 1059 git init 1060 git add . 1061 git commit -m "Initial commit" || warn "Nothing to commit" 1062 popd >/dev/null 1063 fi 1064 1065 # Generate initial metadata 1066 generate_canonical_meta 1067 generate_canonical_md 1068 generate_index_json 1069 generate_well_known_json 1070 generate_gitfield_readme 1071 generate_docs_index 1072 generate_docs_css 1073 generate_docs_repos_json 1074 generate_docs_readme 1075 generate_docs_nojekyll 1076 generate_docs_robots 1077 generate_docs_sitemap 1078 generate_docs_integrity 1079 1080 # Run push cycles 1081 run_push_cycle 1 1082 generate_gitfield_md 1083 run_push_cycle 2 1084 run_push_cycle 3 1085 1086 info "✅ gitfield-sync completed successfully." 1087 info "✅ Canonical sync exported to /docs successfully." 1088 info "🔗 View logs: $DOCS_PUSHED_LOG" 1089 info "🔗 View multi-repo manifest: $DOCS_GITFIELD_MD" 1090 info "🔗 View canonical metadata: $DOCS_CANONICAL_META" 1091 info "🔗 View canonical declaration: $DOCS_CANONICAL_MD" 1092 info "🔗 View index manifest: $DOCS_INDEX_JSON" 1093 info "🔗 View SEO metadata: $DOCS_GITFIELD_JSON" 1094 info "🔗 View GitHub Pages: $DOCS_INDEX" 1095 info "🔗 View integrity hashes: $DOCS_INTEGRITY"