From ec2fd299541fcafd45daff1eb738c97798a4d800 Mon Sep 17 00:00:00 2001 From: "ipfs.kane-il.us publisher" Date: Fri, 29 Aug 2025 18:03:37 +0000 Subject: [PATCH] docs: add CONVENTIONS_v1.md; tools: add publish-rename.sh --- CONVENTIONS_v1.md | 117 ++++++++++++++++++++++++++++++++ tools/publish-rename.sh | 143 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 260 insertions(+) create mode 100644 CONVENTIONS_v1.md create mode 100755 tools/publish-rename.sh diff --git a/CONVENTIONS_v1.md b/CONVENTIONS_v1.md new file mode 100644 index 0000000..a3bdbc7 --- /dev/null +++ b/CONVENTIONS_v1.md @@ -0,0 +1,117 @@ +# ipfs.kane-il.us — Content & Path Conventions (v1) + +## 0. Scope +- Public-only repository for IPFS gateway publishing. +- Text formats only: `*.md`, `*.txt`, `*.jsonl`. +- No binaries (pdf, images, video, archives) — describe them in markdown for accessibility. +- All timestamps are **UTC**. + +## 1. Top-level categories (roots) +``` +/legal +/civics +/naics +/barter +/w3pbs +/onet +/_log # public minimal publish log +``` +- Root-level design documents (e.g. CONVENTIONS, README, checklists) may be placed directly at repo root. +- To avoid collisions, these use versioned filenames like `CONVENTIONS_v1.md`, `CONVENTIONS_v2.md`. + +## 2. Naming rules (files & dirs) +- **Lowercase**, **ASCII**, **underscores** for word separators. +- Filenames must start with **digits-only ISO UTC timestamp**: + - `YYYYMMDDThhmmssZ_.md` +- Exception: root design documents, which follow `_vN.md`. + +## 3. Immutability +- No “latest” aliases, no mutable pointers. +- No per-directory index files; rely on gateway directory listing. +- Every publish is additive; removals are exceptional (court/admin error). + +## 4. LEGAL +### 4.1 research (jurisdiction-first, typed entities) +Path template: +``` +/legal/research/{scope}/{segment}/{subject}/... +``` +- `scope ∈ {county|town|township|individual|organization}` +- If `scope=organization` or `individual`, use typed entity layering: + ``` + /legal/research/{scope}/{kind}/{name}/{subject}/... + kind ∈ {governance|economic|domestic|technical|infrastructure|virtual} + ``` +- Otherwise: + ``` + /legal/research/{scope}/{jurisdiction_name}/{subject}/... + ``` + +### 4.2 court → cases +Path template: +``` +/legal/court/{court_id}/{case_id}/(filings|evidence|orders|docket|notes|transcripts|exhibits)/ +``` +- `court_id` will follow Kane County authoritative naming. +- `case_id` sanitized to lowercase/underscores; original case identifier stored inside the markdown. + +## 5. Other categories +- **civics/**: governance, policy, licenses, standards → plain markdown. +- **naics/**: subdirectories by NAICS code. +- **barter/**: web2py assets and git-oriented text/config (no binaries). +- **w3pbs/**: mailing lists, streaming, chat, forums; html/gemini as text or markdown summaries. +- **onet/**: O*NET taxonomy (latest), directories from O*NET categories. + +## 6. Publish log (public, minimal) +- Location: `/_log/publish.jsonl` +- One JSON object per line with fields: + - `ts` (UTC string), + - `event` (e.g. `"publish"`), + - `man` (manifest path), + - `sig` (signature path), + - `signer` (e.g. publisher@ipfs.kane-il.us), + - `ns` (signature namespace, canonical = `ipfspublish`), + - `repo` (e.g. `w3pbs/ipfs.kane-il.us`), + - `commit` (git hash). +- Past entries retained forever. +- Fields like `manifest_cid`, `paths`, and `tag` may be added in future expansions. + +## 7. Signatures +- All manifests are signed with **SSH-sig** using the deploy key. +- Canonical namespace: **`ipfspublish`**. +- Verification uses `allowed_signers` file with principal `publisher@ipfs.kane-il.us`. + +## 8. Guardrails (deny) +- Private/staging content never enters this repo. +- Deny common tool dirs: `.git/`, `.github/`, `.vscode/`, caches, temp files. +- Deny binaries by extension (see `.gitignore`). + +## 9. Accessibility +- For any non-text source (e.g., a PDF elsewhere), store a **descriptive .md**: what it is, where it exists, date, and an accessible summary. + +## 10. Examples +``` +/legal/research/county/kane/zoning/20250828T140000Z_buffer_requirements.md +/legal/court/il_kane_circuit/23_ch_000123/filings/20250828T142500Z_plaintiff_motion.md +/naics/541611/20250828T150000Z_procurement_policy.md +/onet/architecture_and_engineering/20250828T160000Z_job_function_overview.md +``` + +## 11. Operator Utilities +* **Primary interface:** Operators are expected to use **Midnight Commander (`mc`)** as the daily driver for browsing, staging, and publishing files. +* **Backup scripts:** Deterministic shell scripts are maintained under `/tools/`. + + * Purpose: fallback when `mc` is unavailable, misconfigured, or fails mid-operation. + * Behavior: scripts normalize filenames, run publish steps, and include `--dry-run` modes. + * Example: + + * `publish-rename` → normalize names to required conventions. + * `publish-doc` (planned) → chain the full publishing flow. +* **mc integration:** These scripts may also be bound to the mc user menu (`~/.config/mc/mc.menu`) so that the same deterministic actions can be triggered via `F2`. +* **Automation:** Because they are standalone, scripts can also be called in batch or from other automation tooling if desired. + +**Principle:** + +* **mc = primary operator UX** (interactive, user-friendly). +* **scripts = deterministic backup + automation hooks**. +* Both are valid, auditable, and kept in sync with these conventions. diff --git a/tools/publish-rename.sh b/tools/publish-rename.sh new file mode 100755 index 0000000..065ccef --- /dev/null +++ b/tools/publish-rename.sh @@ -0,0 +1,143 @@ +#!/usr/bin/env bash +# publish-rename: normalize filenames for ipfs.kane-il.us publishing +# - Category content: //YYYYMMDDThhmmssZ_. +# - Root design docs: /_vN.md + +set -euo pipefail + +VERSION="1.0" + +# ---------- config ---------- +ALLOWED_EXT_REGEX='^(md|txt|jsonl)$' +UTC_FMT='+%Y%m%dT%H%M%SZ' + +# ---------- helpers ---------- +err(){ printf 'error: %s\n' "$*" >&2; exit 1; } +note(){ printf '%s\n' "$*" >&2; } +ts(){ date -u "${UTC_FMT}"; } + +slugify(){ + # lower, spaces->_, remove disallowed chars, collapse repeats, trim underscores + printf '%s' "$1" \ + | tr '[:upper:] ' '[:lower:]_' \ + | sed -E 's/[^a-z0-9_]+/_/g; s/_+/_/g; s/^_+//; s/_+$//' +} + +print_man(){ +cat <<'MAN' +NAME + publish-rename — normalize filenames for publishing to ipfs.kane-il.us + +SYNOPSIS + publish-rename category [--dry-run] + publish-rename root [--dry-run] --version + +DESCRIPTION + Renames content into the repository’s required shapes: + + 1) CATEGORY MODE + Target: //YYYYMMDDThhmmssZ_. + - must be one of: legal, civics, naics, barter, w3pbs, onet + - must be md|txt|jsonl (unchanged from ) + - is normalized (lowercase, underscores, ASCII) + + 2) ROOT MODE (design docs) + Target: /_vN.md (no timestamp) + - is normalized (e.g., CONVENTIONS -> conventions) + - --version N is required (integer >= 1) + - Extension forced to .md + +OPTIONS + --dry-run Print the rename that would occur; do not move files. + --version N Root mode only: version number N (e.g., 1, 2, 3...) + -h, --help Show this help. + +EXAMPLES + # Category: rename to legal/20250829T171500Z_conventions_v1.md + publish-rename category legal CONVENTIONS_v1.md conventions_v1 + + # Category: rename a text file into naics with a slug + publish-rename category naics notes.txt procurement_policy_notes + + # Root: versioned design doc at repo root (CONVENTIONS_v1.md) + publish-rename root --version 1 CONVENTIONS.md CONVENTIONS + +NOTES + - This tool changes only the filename/location; it does not git add/commit. + - For legal citations, always use the CID after publishing; the repo path + is for structure and operator convenience only. + +AUTHOR + vMAN 1.0 — tailored for ipfs.kane-il.us + +MAN +} + +# ---------- argparse ---------- +[[ $# -lt 1 ]] && { print_man; exit 1; } + +mode="$1"; shift || true + +dry_run=0 +root_version='' +while [[ $# -gt 0 ]]; do + case "$1" in + --dry-run) dry_run=1; shift;; + -h|--help) print_man; exit 0;; + --version) shift; root_version="${1:-}"; [[ -z "$root_version" ]] && err "--version requires a number"; shift;; + *) break;; + esac +done + +case "$mode" in + category) + [[ $# -ne 3 ]] && { print_man; err "category mode requires "; } + category_raw="$1"; file="$2"; slug_raw="$3" + + category="$(slugify "$category_raw")" + case "$category" in + legal|civics|naics|barter|w3pbs|onet) : ;; + *) err "invalid category '$category_raw' (expected: legal|civics|naics|barter|w3pbs|onet)";; + esac + + [[ -f "$file" ]] || err "file not found: $file" + ext="${file##*.}"; [[ "$ext" =~ $ALLOWED_EXT_REGEX ]] || err "extension '.$ext' not allowed (md|txt|jsonl)" + + slug="$(slugify "$slug_raw")"; [[ -n "$slug" ]] || err "slug normalization produced empty value" + stamp="$(ts)" + dest_dir="$category" + dest_file="${stamp}_${slug}.${ext}" + dest_path="${dest_dir}/${dest_file}" + + [[ $dry_run -eq 1 ]] && { printf 'DRY-RUN: %s -> %s\n' "$file" "$dest_path"; exit 0; } + + mkdir -p "$dest_dir" + mv -- "$file" "$dest_path" + printf 'Renamed %s -> %s\n' "$file" "$dest_path" + ;; + + root) + # root design docs: _vN.md at repo root + [[ -z "$root_version" ]] && { print_man; err "root mode requires --version "; } + [[ $# -ne 2 ]] && { print_man; err "root mode requires "; } + + file="$1"; name_raw="$2" + [[ -f "$file" ]] || err "file not found: $file" + + # version must be integer >=1 + [[ "$root_version" =~ ^[0-9]+$ ]] || err "version must be an integer" + [[ "$root_version" -ge 1 ]] || err "version must be >= 1" + + name="$(slugify "$name_raw")"; [[ -n "$name" ]] || err "name normalization produced empty value" + dest_path="${name}_v${root_version}.md" + + [[ $dry_run -eq 1 ]] && { printf 'DRY-RUN: %s -> %s\n' "$file" "$dest_path"; exit 0; } + + mv -- "$file" "$dest_path" + printf 'Renamed %s -> %s\n' "$file" "$dest_path" + ;; + + *) + print_man; err "unknown mode '$mode' (use 'category' or 'root')" + ;; +esac