mirror of
https://github.com/garrytan/gstack.git
synced 2026-09-11 15:39:04 +02:00
feat(security): receipt admin scripts + user git-ops (zero exceptions)
Wire the remaining shell egress through gstack-egress-lib.sh: - gstack-gbrain-mcp-verify: both JSON-RPC probe POSTs (initialize + tools/list) receipted fail-closed via payload files (hash == wire bytes). A refused receipt lands in the NETWORK class — no send. - gstack-security-dashboard / gstack-community-dashboard: the community-pulse GETs receipted fail-open (read-only stats must not break over an audit hiccup). - gstack-gbrain-supabase-provision: api_call receipted fail-closed. Each retry attempt hands the helper a fresh copy of the body file (the helper consumes its payload). The receipt hashes the request body only — the PAT never reaches the ledger or any log. Refusal exits 8 without retrying. - git-class sha256:null receipts, fail-open: gstack-artifacts-init (ls-remote, initial push, fetch/pull recovery, retry push), gstack-brain-restore (staging clone, existing-repo fetch), gstack-session-update (self-update pull). gstack-team-init needs no wiring: every git clone in it is inside an echoed instruction string, not an executed command. The lib now self-locates with shell builtins only (no dirname), so sourcing works under the whitelist-PATH test harnesses. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> (cherry picked from commit b8c5e2055b21ab72878b3e46f8047782ee65a11c)
This commit is contained in:
@@ -40,6 +40,16 @@ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
URL_BIN="$SCRIPT_DIR/gstack-artifacts-url"
|
||||
REMOTE_FILE="$HOME/.gstack-artifacts-remote.txt"
|
||||
|
||||
# Egress receipt helpers (_receipted_git): fail-open for user-directed
|
||||
# git ops against the user's own artifacts remote.
|
||||
. "$SCRIPT_DIR/gstack-egress-lib.sh"
|
||||
|
||||
# remote host for receipt records (github.com etc). Set once PUSH_URL exists.
|
||||
_artifacts_host() {
|
||||
local h="${PUSH_URL#*://}"; h="${h#*@}"; h="${h%%[/:]*}"
|
||||
echo "${h:-unknown}"
|
||||
}
|
||||
|
||||
REMOTE_URL=""
|
||||
HOST_PREF=""
|
||||
URL_FORM_SUPPORTED="false"
|
||||
@@ -185,7 +195,8 @@ PUSH_URL=$("$URL_BIN" --to ssh "$CANONICAL_HTTPS" 2>/dev/null || echo "$CANONICA
|
||||
|
||||
# ---- verify push URL is reachable ----
|
||||
echo "Verifying remote connectivity: $PUSH_URL"
|
||||
if ! git ls-remote "$PUSH_URL" >/dev/null 2>&1; then
|
||||
if ! _receipted_git open artifacts-init "$(_artifacts_host)" artifacts-remote-ls-remote "user ran gstack-artifacts-init" \
|
||||
bash -c 'git ls-remote "$1" >/dev/null 2>&1' _ "$PUSH_URL"; then
|
||||
cat >&2 <<EOF
|
||||
Remote not reachable via SSH: $PUSH_URL
|
||||
This could mean:
|
||||
@@ -346,10 +357,15 @@ else
|
||||
fi
|
||||
|
||||
# ---- initial push ----
|
||||
if ! git push -q -u origin main 2>/dev/null; then
|
||||
if ! _receipted_git open artifacts-init "$(_artifacts_host)" artifacts-initial-push "user ran gstack-artifacts-init" \
|
||||
bash -c 'git push -q -u origin main 2>/dev/null'; then
|
||||
CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD)
|
||||
if git fetch origin 2>/dev/null && git pull --ff-only origin "$CURRENT_BRANCH" 2>/dev/null; then
|
||||
git push -q -u origin "$CURRENT_BRANCH" || {
|
||||
if _receipted_git open artifacts-init "$(_artifacts_host)" artifacts-fetch "user ran gstack-artifacts-init" \
|
||||
bash -c 'git fetch origin 2>/dev/null' \
|
||||
&& _receipted_git open artifacts-init "$(_artifacts_host)" artifacts-pull "user ran gstack-artifacts-init" \
|
||||
bash -c 'git pull --ff-only origin "$1" 2>/dev/null' _ "$CURRENT_BRANCH"; then
|
||||
_receipted_git open artifacts-init "$(_artifacts_host)" artifacts-initial-push "user ran gstack-artifacts-init" \
|
||||
git push -q -u origin "$CURRENT_BRANCH" || {
|
||||
echo "Push to $PUSH_URL failed. The remote may have divergent content." >&2
|
||||
echo "Try: cd ~/.gstack && git pull --rebase origin $CURRENT_BRANCH && git push origin $CURRENT_BRANCH" >&2
|
||||
exit 1
|
||||
|
||||
Reference in New Issue
Block a user