Compare commits

..

11 Commits

Author SHA1 Message Date
ipfs.kane-il.us publisher b2061803c3 log/index: publish 20250831T003240Z (CID bafkreibjg...ormi) 2025-08-31 00:52:08 +00:00
ipfs.kane-il.us publisher 121464dd4c log: manifest 20250831T003240Z (CID bafkreibjg...ormi) + signed 2025-08-31 00:35:08 +00:00
ipfs.kane-il.us publisher 0a2fd201df publish: add civics/20250831T002911Z_democratic_party_language_case_study.md 2025-08-31 00:30:41 +00:00
ipfs.kane-il.us publisher 0cc6cc4623 publish: manifest + signature + log for 20250829T180505Z 2025-08-29 18:09:43 +00:00
ipfs.kane-il.us publisher ec2fd29954 docs: add CONVENTIONS_v1.md; tools: add publish-rename.sh 2025-08-29 18:03:37 +00:00
ipfs.kane-il.us publisher d813b101d8 gitignore: allow tools/*.sh (operator utilities) 2025-08-29 17:56:36 +00:00
ipfs.kane-il.us publisher 73155d7d5c chore(manifests): relocate to _log/manifests and normalize log perms 2025-08-29 16:30:26 +00:00
ipfs.kane-il.us publisher 49d83cdff8 publish: manifest + signature + log for 20250827T191034Z 2025-08-29 16:28:21 +00:00
ipfs.kane-il.us publisher 89fe77fcc3 publish: add legal/20250827T191034Z_ipfs_in_plain_english.md 2025-08-29 16:21:14 +00:00
ipfs.kane-il.us publisher ff84b47668 chore(manifests): align .sshsig to canonical ipfspublish namespace 2025-08-29 16:06:58 +00:00
ipfs.kane-il.us publisher 88a01c3c14 chore: normalize manifest sig namespace to ipfspublish 2025-08-29 16:05:30 +00:00
14 changed files with 1446 additions and 6 deletions

3
.gitignore vendored
View File

@ -55,3 +55,6 @@ Thumbs.db
!/_log/ !/_log/
!/_log/manifests/ !/_log/manifests/
!/_log/manifests/** !/_log/manifests/**
# track operator scripts
!tools/*.sh

117
CONVENTIONS_v1.md Normal file
View File

@ -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_<slug>.md`
- Exception: root design documents, which follow `<NAME>_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.

1
_log/index.jsonl Normal file
View File

@ -0,0 +1 @@
{"ts":"20250831T003240Z","path":"civics/20250831T002911Z_democratic_party_language_case_study.md","cid":"bafkreibjgfwfaeltz2ftdp4yiscz2qpsoml26f33vq5xp3hdxmkb7aormi","sha256":"29316c501173ce8b31bf9844859d41f27317af177bac3b77ece3bb141f81d162","commit":"121464dd4c80f558ebd3e88dc08ec992297016a4","tag":"publish-20250831T003240Z"}

View File

@ -1,6 +1,6 @@
-----BEGIN SSH SIGNATURE----- -----BEGIN SSH SIGNATURE-----
U1NIU0lHAAAAAQAAADMAAAALc3NoLWVkMjU1MTkAAAAgVEY8m5hZXa43Z7YkjG2RtiOE46 U1NIU0lHAAAAAQAAADMAAAALc3NoLWVkMjU1MTkAAAAgVEY8m5hZXa43Z7YkjG2RtiOE46
P3nB4hMQ6JF5TaDYUAAAAEZmlsZQAAAAAAAAAGc2hhNTEyAAAAUwAAAAtzc2gtZWQyNTUx P3nB4hMQ6JF5TaDYUAAAALaXBmc3B1Ymxpc2gAAAAAAAAABnNoYTUxMgAAAFMAAAALc3No
OQAAAEDeM28XOIf7rTSmct7Ya7M7ciCdYYkL4d+vkfkIPYr6VKhL1BAI54locaojTrRjXG LWVkMjU1MTkAAABAdBDY+Y/J4YsdzIr3RHMugVe09h0+dTdm+mTnJHEcBi8xC11FfIl+v0
KVSKRXP8GQdyNrB3VnZOwB NmblDyv2caH/WsNkktIOEgyr7tgN/eBQ==
-----END SSH SIGNATURE----- -----END SSH SIGNATURE-----

View File

@ -0,0 +1,6 @@
{
"ts":"20250827T191034Z",
"repo":"w3pbs/ipfs.kane-il.us",
"commit":"89fe77fcc326bf151108ca8b219a564b0c59b530",
"items":[{"path":"legal/20250827T191034Z_ipfs_in_plain_english.md","cid":"QmRmHDBzZTUqfeE2wWyVEd5PnNqnpzjPSPQwXbaaTZCGp8"}]
}

View File

@ -0,0 +1,6 @@
-----BEGIN SSH SIGNATURE-----
U1NIU0lHAAAAAQAAADMAAAALc3NoLWVkMjU1MTkAAAAgVEY8m5hZXa43Z7YkjG2RtiOE46
P3nB4hMQ6JF5TaDYUAAAALaXBmc3B1Ymxpc2gAAAAAAAAABnNoYTUxMgAAAFMAAAALc3No
LWVkMjU1MTkAAABAlTSP/burd+AMvLcUjvfuJa3nDEl6UavvfY3d9VVB83Xb+CedPvNvZJ
heZsoQB+6nQWHwHPAVh8jKFtmvdU/9Dg==
-----END SSH SIGNATURE-----

View File

@ -0,0 +1,6 @@
{
"ts":"20250829T180505Z",
"repo":"w3pbs/ipfs.kane-il.us",
"commit":"ec2fd299541fcafd45daff1eb738c97798a4d800",
"items":[{"path":"CONVENTIONS_v1.md","cid":"QmUjJu7h659MgodabF1MvuPEsMmyGAr3PchbmvcEARiEhq"}]
}

View File

@ -0,0 +1,6 @@
-----BEGIN SSH SIGNATURE-----
U1NIU0lHAAAAAQAAADMAAAALc3NoLWVkMjU1MTkAAAAgVEY8m5hZXa43Z7YkjG2RtiOE46
P3nB4hMQ6JF5TaDYUAAAALaXBmc3B1Ymxpc2gAAAAAAAAABnNoYTUxMgAAAFMAAAALc3No
LWVkMjU1MTkAAABAQdbocMCKN6BEL0Nsrjh6rckUTe9bYmGRzn+JquumdGdvbwvddyc1yU
Iyc5wVf9QvgGjkh8o7MTAKAvx7gIkaBw==
-----END SSH SIGNATURE-----

View File

@ -0,0 +1,12 @@
{
"ts": "20250831T003240Z",
"repo": "w3pbs/ipfs.kane-il.us",
"commit": "0a2fd201dfe66aec768ef5fe102054fdfee8b4ce",
"items": [
{
"path": "civics/20250831T002911Z_democratic_party_language_case_study.md",
"cid": "bafkreibjgfwfaeltz2ftdp4yiscz2qpsoml26f33vq5xp3hdxmkb7aormi",
"sha256": "29316c501173ce8b31bf9844859d41f27317af177bac3b77ece3bb141f81d162"
}
]
}

View File

@ -0,0 +1,6 @@
-----BEGIN SSH SIGNATURE-----
U1NIU0lHAAAAAQAAADMAAAALc3NoLWVkMjU1MTkAAAAgVEY8m5hZXa43Z7YkjG2RtiOE46
P3nB4hMQ6JF5TaDYUAAAALaXBmc3B1Ymxpc2gAAAAAAAAABnNoYTUxMgAAAFMAAAALc3No
LWVkMjU1MTkAAABAs9X/pD2rZQECR7YvmmCm2V7FM2dXtqheS0UjVuyQFeGvZOTAL5Cac2
d4EM6jWvLB4cWdZRUOORKtcOlDL35yBg==
-----END SSH SIGNATURE-----

View File

@ -1,3 +1,2 @@
{"event":"init","utc":"1970-01-01T00:00:00Z","note":"publish log created"}{"event":"publish","utc":"2025-08-28T20:03:39Z","cid":"Qmcd9786Mz86sRAZbgEsf6trZUfhNXDPzhXCjfqePKP7vo","path":"/legal/research/county/kane/zoning/20250828T185238Z_zoning_buffer_requirements.md","gateway":"https://ipfs.kane-il.us/ipfs/Qmcd9786Mz86sRAZbgEsf6trZUfhNXDPzhXCjfqePKP7vo","tag":"publish-20250828T200339Z"} {"ts":"20250829T180505Z","event":"publish","man":"_log/manifests/20250829T180505Z.json","sig":"_log/manifests/20250829T180505Z.json.sshsig","signer":"publisher@ipfs.kane-il.us","ns":"ipfspublish","repo":"w3pbs/ipfs.kane-il.us","commit":"ec2fd299541fcafd45daff1eb738c97798a4d800"}
{"event":"publish","utc":"2025-08-28T20:10:08Z","cid":"OK:","path":"/legal/research/county/kane/zoning/20250828T185238Z_zoning_buffer_requirements.md","gateway":"https://ipfs.kane-il.us/ipfs/OK:","tag":"publish-20250828T201008Z"} {"ts":"20250831T003240Z","event":"publish","man":"_log/manifests/20250831T003240Z.json","sig":"_log/manifests/20250831T003240Z.json.sshsig","repo":"w3pbs/ipfs.kane-il.us","commit":"0a2fd201dfe66aec768ef5fe102054fdfee8b4ce"}
{"event":"publish","utc":"2025-08-28T20:15:54Z","cid":"Qmcd9786Mz86sRAZbgEsf6trZUfhNXDPzhXCjfqePKP7vo","path":"/legal/research/county/kane/zoning/20250828T185238Z_zoning_buffer_requirements.md","gateway":"https://ipfs.kane-il.us/ipfs/Qmcd9786Mz86sRAZbgEsf6trZUfhNXDPzhXCjfqePKP7vo","tag":"publish-20250828T201554Z"}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,67 @@
# IPFS in Plain English (for legal readers)
Host: https://ipfs.kane-il.us · Repository: `w3pbs/ipfs.kane-il.us` (Gitea, branch `main`) · Version: v1.0 · Generated (UTC): 2025-08-27 19:10:34Z
---
## What IPFS does
- IPFS gives every document a CID (content ID) that is a fingerprint of the exact bytes.
- If anything changes—even one character—the document gets a different CID.
- Example: if a body of text contains `01/01/1978` and that changes to `01/01/1987`, the CID changes. The original text keeps its original CID and remains retrievable at that CID.
---
## Why this matters in legal settings
- **Integrity:** Opening the same `/ipfs/<CID>` always returns the same document. If the bytes were different, the CID would be different.
- **Stable citations:** Every publish is timestamped and logged. CIDs never change, so filings can cite them permanently.
- **Audit trail:** Each publish has a signed manifest (path ↔ CID) and an entry in the permanent log at `/_log/publish.jsonl`. This log, not transient web pages, is the provenance record.
- **Court admissibility:** The CID itself is the authoritative reference. Filings should cite the CID to guarantee immutability, not just a URL or repository path.
---
## Repository vs. Immutable Retrieval
- **Repository (Gitea):** The repo at [gitea.barternetwork.us](https://gitea.barternetwork.us/w3pbs/ipfs.kane-il.us) holds the structured hierarchy (`/legal`, `/civics`, `/naics`, etc.). It provides human-readable organization, history, and convenience for operators.
- **Immutable files:** For authentic, court-admissible retrieval, always use the **CID**. The Gitea repo structures the files, but the CID guarantees their identity forever.
---
## Snapshots and navigation
- There is **no mutable “latest” pointer** (no IPNS, no DNSLink).
- Each published file is permanent, timestamped in its filename (`YYYYMMDDThhmmssZ_<slug>.md`), and referenced in the manifest/log.
- Gateway directory listings under `https://ipfs.kane-il.us` expose these timestamped files directly.
---
## How to verify (no installs needed)
1. Open `https://ipfs.kane-il.us/_log/publish.jsonl` (or the manifest for the filings date).
2. Find the file path and note its CID (and, if provided, SHA-256).
3. Confirm the CID matches the value on the filings cover sheet.
4. *(Optional)* Fetch the same `/ipfs/<CID>` via a second public gateway to cross-check—it will return the same bytes for the same CID.
---
## Scope & privacy
- Only court-public materials are published. Private or sealed content is not placed on IPFS.
---
## Terms (brief)
- **CID:** Content ID (hash of the exact bytes).
- **Manifest:** JSON file mapping file paths to their CIDs; cryptographically signed.
- **Publish log:** Append-only JSONL file at `/_log/publish.jsonl` recording each publish.
- **Snapshot:** Timestamped file committed once, never changed.
- **Gitea repo:** Source of structure and convenience; not itself proof of immutability.
---
## Email-sized blurbs (pick one)
**Ultra-plain (2 sentences):** IPFS assigns each document a unique CID that is a fingerprint of its exact text. If anything changes—even one character—the CID changes, so opening the same CID always returns the original document.
**With date example:** IPFS identifies each document by a CID. If `01/01/1978` is changed to `01/01/1987`, that small change produces a new CID—so the original text keeps its original CID and can always be retrieved.
**With “repo vs CID”:** The Gitea repo provides the folder structure, but the CID is the legal proof. For citations, always use the CID—because the CID is immutable, permanent, and court-admissible.
---
*Disclaimer: This explainer is informational, not legal advice, and does not represent any government.*

143
tools/publish-rename.sh Executable file
View File

@ -0,0 +1,143 @@
#!/usr/bin/env bash
# publish-rename: normalize filenames for ipfs.kane-il.us publishing
# - Category content: /<category>/YYYYMMDDThhmmssZ_<slug>.<ext>
# - Root design docs: /<NAME>_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] <category> <file> <slug>
publish-rename root [--dry-run] --version <N> <file> <name>
DESCRIPTION
Renames content into the repositorys required shapes:
1) CATEGORY MODE
Target: /<category>/YYYYMMDDThhmmssZ_<slug>.<ext>
- <category> must be one of: legal, civics, naics, barter, w3pbs, onet
- <ext> must be md|txt|jsonl (unchanged from <file>)
- <slug> is normalized (lowercase, underscores, ASCII)
2) ROOT MODE (design docs)
Target: /<NAME>_vN.md (no timestamp)
- <NAME> 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> <file> <slug>"; }
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: <NAME>_vN.md at repo root
[[ -z "$root_version" ]] && { print_man; err "root mode requires --version <N>"; }
[[ $# -ne 2 ]] && { print_man; err "root mode requires <file> <name>"; }
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