Files
Matheus HoffmannandClaude Opus 5.5 e40e46c2e4 Convert mu to the piabrota identity: dogma, repo index, Rust templates, archify
This repo was a copy of Ouroboric's umbrella. It becomes piabrota's company umbrella, ready for pirsig
to manage it.

- DOGMA.md holds ten invariants, and AGENTS.md follows it.
- PIABROTA.md indexes the org's public repos, rendered by minijinja-cli from scripts/piabrota/repos.toml.
- docs/DECISION_MODELS.md tracks decision models and where routines run.
- brain/ and pirsig.toml seed PARA, smart notes and the decision track record.
- The org, the bot name, the charter, the roadmap, the budget, the legal page and the palette change.
- Ouroboric's logos go. Its licences stay, with credit in NOTICE.md. Dated records keep their text.
- The Go component template becomes a Rust one, rendered by minijinja-cli.
- Every plot is drawn with archify, pinned in forks/archify. Mermaid, D2 and diagrams.sh go.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-01 04:38:43 -03:00

66 lines
3.8 KiB
Bash
Executable File

#!/usr/bin/env bash
# Run a command as piabrota-pr-bot, with a token that lasts one hour and reaches only the named repos.
# The command gets the token as GH_TOKEN, and git gets it for https://github.com only. SSH remotes
# are rewritten to HTTPS, so the SSH key is never used. This script never prints the token, and it
# is the only thing that reads the bot's key. Agent-run.
# as-bot.sh [--read] <repo[,repo...]|all> <command...> (all: read-only, every repo)
# as-bot.sh yggdrasil git push -u origin my-branch
# as-bot.sh yggdrasil gh pr create --title ... --body-file ...
# as-bot.sh --read all scripts/check-repos.sh
set -euo pipefail
ORG="piabrota"
DIR="${PR_BOT_DIR:-$HOME/.config/piabrota/pr-bot}"
API="${PR_BOT_API:-https://api.github.com}"
die() { echo "as-bot: $*" >&2; exit 2; }
read=false
perms='{"contents":"write","pull_requests":"write","metadata":"read"}'
if [ "${1:-}" = --read ]; then
read=true; perms='{"contents":"read","pull_requests":"read","administration":"read","metadata":"read"}'; shift
fi
[ $# -ge 2 ] || die "usage: as-bot.sh [--read] <repo[,repo...]|all> <command...>"
repos="$1"; shift
if [ "$repos" = all ]; then
$read || die "all needs --read: a write token names its repos"
else
[[ "$repos" =~ ^[A-Za-z0-9._-]+(,[A-Za-z0-9._-]+)*$ ]] || die "bad repo list: $repos"
fi
[ -r "$DIR/key.pem" ] && [ -r "$DIR/app.env" ] || die "no bot key in $DIR (the founder runs create-pr-bot.sh)"
client_id="$(sed -n 's/^PR_BOT_CLIENT_ID=//p' "$DIR/app.env")"
[ -n "$client_id" ] || die "no PR_BOT_CLIENT_ID in $DIR/app.env"
b64url() { openssl base64 -A | tr '+/' '-_' | tr -d '='; }
now="$(date +%s)"
jwt="$(printf '{"alg":"RS256","typ":"JWT"}' | b64url).$(printf '{"iat":%d,"exp":%d,"iss":"%s"}' \
$((now - 60)) $((now + 540)) "$client_id" | b64url)"
jwt="$jwt.$(printf '%s' "$jwt" | openssl dgst -sha256 -sign "$DIR/key.pem" -binary | b64url)"
call() { # call METHOD PATH [JSON]: prints the reply; stops on any error with GitHub's message
local out code
out="$(curl -sS -X "$1" -w '\n%{http_code}' -H @<(printf 'Authorization: Bearer %s\n' "$jwt") \
-H 'Accept: application/vnd.github+json' -H 'X-GitHub-Api-Version: 2022-11-28' \
${3:+--data "$3"} "$API$2")" || die "$1 $2: request failed"
code="${out##*$'\n'}"; out="${out%$'\n'*}"
[[ "$code" == 2* ]] || die "$1 $2: HTTP $code: $(jq -r '.message? // empty' <<<"$out" 2>/dev/null)"
printf '%s' "$out"
}
inst="$(call GET "/orgs/$ORG/installation" | jq -r .id)"
# No repositories field means every repo the bot is installed on.
req="$(jq -cn --arg r "$repos" --argjson p "$perms" '{permissions: $p} + (if $r == "all" then {} else {repositories: ($r | split(","))} end)')"
token="$(call POST "/app/installations/$inst/access_tokens" "$req" | jq -r .token)"
[ -n "$token" ] && [ "$token" != null ] || die "GitHub's reply held no token"
# An empty helper drops every helper configured before it, so ours is the only one for github.com.
# Git applies the longest matching insteadOf, so the piabrota rule beats any global rule that
# sends https://github.com/ to SSH.
# shellcheck disable=SC2016 # the credential helper is single-quoted on purpose: git runs it, so $1 and $GH_TOKEN expand there
export GH_TOKEN="$token" GIT_TERMINAL_PROMPT=0 GIT_CONFIG_COUNT=5 \
GIT_CONFIG_KEY_0="credential.https://github.com.helper" GIT_CONFIG_VALUE_0="" \
GIT_CONFIG_KEY_1="credential.https://github.com.helper" \
GIT_CONFIG_VALUE_1='!f() { test "$1" = get && printf "username=x-access-token\npassword=%s\n" "$GH_TOKEN"; }; f' \
GIT_CONFIG_KEY_2="url.https://github.com/.insteadOf" GIT_CONFIG_VALUE_2="[email protected]:" \
GIT_CONFIG_KEY_3="url.https://github.com/.insteadOf" GIT_CONFIG_VALUE_3="ssh://[email protected]/" \
GIT_CONFIG_KEY_4="url.https://github.com/piabrota/.insteadOf" GIT_CONFIG_VALUE_4="https://github.com/piabrota/"
unset GITHUB_TOKEN
exec "$@"