Closes the largest set of PROFILE-DISTRIBUTION-PROTOCOL §7 readiness gaps
surfaced in the 2026-05-23 audit. Profile goes from 4/8 to expected 8/8
once skills/proton-tools/ is committed.
New files:
credbridge.sh Personal-assistant variant of the shared-core
credbridge pattern. Three credentials in scope:
google-workspace (Gmail/Calendar/Contacts),
proton-bridge (himalaya IMAP/SMTP), perplexity
(raw WebSearch). Plan B marketing platforms
explicitly OUT OF SCOPE per CLAUDE.md hard rule.
validate_access.sh Emits PASS/BLOCKED/FAIL JSON line per credential.
Sourceable from install.sh and standalone. Exit
code always 0; status is in the JSON.
distribution.yaml Native Hermes install contract (`hermes profile
install` reads this). Mirrors cmo/ceo pattern.
Documents personal/agnostic naming exception
per FRAMEWORK §6.1 — no org suffix because there
is exactly one principal.
cron/steev-daily-briefing.json.template
06:30 daily briefing skeleton, ships disabled.
Aggregates calendar + flagged emails + due tasks
+ carried items + brief news scan into a single
digest in JP's voice. NEVER auto-sends, NEVER
touches business comms (CEO → CMO surface).
manifest.yaml fully rewritten:
- Added `contract: CONTRACT.md` pointer (was missing)
- Added inline comment explaining intentional `org:` omission
- Declared skills/proton-tools (on disk via JP's untracked WIP; declared
here so manifest matches disk truth once JP commits it)
- Added `lib:` block (credbridge.sh + validate_access.sh)
- Added `expected_external_skills:` informational list (google-workspace,
apple-*, obsidian, himalaya, imessage, perplexity) — these come from
Hermes' global skills tree per CLAUDE.md "reuse existing core skills"
- Added `optional_tools:` block (4 MCP servers: proton-calendar/-email/
-contacts, perplexity)
- Added `credentials:` block listing the 3 creds + resolution path
- Promoted `cron:` from empty list to a single steev-daily-briefing
entry (disabled_on_install: true)
- Added `sovereignty:` block (qwen3.6-35b-a3b on DGX Spark)
CONTRACT.md frontmatter migrated from legacy `tier: S` to T1 per
FRONTMATTER-SPEC. Added required fields (name, last_reviewed,
description, depends_on).
skills/proton-tools/ left untracked — that's JP's WIP, not mine to
commit.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
95 lines
4.1 KiB
Bash
Executable File
95 lines
4.1 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# credbridge.sh — resolve credctl credentials into env vars for steev's
|
|
# personal-flow tools, then exec the CLI. Secrets NEVER echoed, logged, or
|
|
# written to disk.
|
|
#
|
|
# Usage: credbridge.sh <tool> [args...]
|
|
# tools: google-workspace | proton-bridge | perplexity
|
|
#
|
|
# Per PROFILE-DISTRIBUTION-PROTOCOL §3 (shared core, "credbridge" row) and §6
|
|
# (Conventions → Secrets), every profile distribution exposes credentials via
|
|
# this verb chain: credctl set → credenv → exec, with secrets per-call only.
|
|
#
|
|
# This is the personal-assistant variant of the credbridge pattern. Steev's
|
|
# cred surface is narrow by design:
|
|
#
|
|
# - google-workspace: Gmail + Calendar + Contacts (OAuth blob from credctl)
|
|
# - proton-bridge: IMAP/SMTP password for the local Proton Bridge T6
|
|
# sidecar — gives Steev access to JP's Proton mail via
|
|
# himalaya (cleartext on 127.0.0.1 only)
|
|
# - perplexity: Perplexity API key for WebSearch toolset (lightweight
|
|
# — most Steev work uses the perplexity MCP instead)
|
|
#
|
|
# Plan B marketing platforms (WooCommerce, Mailchimp, Meta, GA4, etc.) are OUT
|
|
# OF SCOPE here — that's cmo-planb's credbridge. Steev MUST NEVER resolve a
|
|
# marketing platform credential. The CLAUDE.md "no access to Plan B marketing
|
|
# platform credentials" rule is enforced by omission from this case statement.
|
|
#
|
|
# Design notes (same as cmo/credbridge.sh — shared core):
|
|
# - credctl values read into local vars, exported straight to the child env
|
|
# - JSON-valued creds (google-workspace OAuth) parsed via `node -e` reading
|
|
# from stdin so the value never lands on argv / process list
|
|
# - No `echo $secret`. set +x stays off.
|
|
|
|
set -euo pipefail
|
|
|
|
# Paths env-overridable for portability; defaults match the JP install.
|
|
CREDCTL="${CREDCTL:-/home/svrnty/workspaces/cortex/L6-svrnty.core-credentials/credctl}"
|
|
STEEV_LIB="${STEEV_LIB:-/home/svrnty/.hermes/steev}"
|
|
|
|
die() { printf '{"error":"%s"}\n' "$1" >&2; exit 1; }
|
|
|
|
[ $# -ge 1 ] || die "usage: credbridge.sh <google-workspace|proton-bridge|perplexity> [args...]"
|
|
TOOL="$1"; shift
|
|
|
|
[ -x "$CREDCTL" ] || die "credctl not found/executable at $CREDCTL"
|
|
|
|
# cred_raw <name> — print unmasked credential value to stdout. Caller captures
|
|
# into a var; value never displayed. Strips the "Value:" header from credctl.
|
|
cred_raw() {
|
|
"$CREDCTL" get "$1" --unmask 2>/dev/null \
|
|
| sed -n '/^Value:/,$p' | sed '1s/^Value:[[:space:]]*//'
|
|
}
|
|
|
|
# json_field <json> <key> — extract a string field via node; value never on argv.
|
|
json_field() {
|
|
printf '%s' "$1" | node -e '
|
|
let s="";process.stdin.on("data",d=>s+=d);
|
|
process.stdin.on("end",()=>{try{const o=JSON.parse(s);
|
|
const v=o[process.argv[1]];process.stdout.write(v==null?"":String(v));
|
|
}catch(e){process.stdout.write("");}});' "$2"
|
|
}
|
|
|
|
case "$TOOL" in
|
|
google-workspace)
|
|
# Gmail Data API + Calendar API + People API all expect a bearer token
|
|
# minted from this service-account / OAuth blob. The blob is JSON; we
|
|
# export the whole document so the child CLI can introspect scope.
|
|
GW_JSON="$(cred_raw google-workspace)"
|
|
[ -n "$GW_JSON" ] || die "credctl: google-workspace not set"
|
|
export GOOGLE_WORKSPACE_CREDENTIALS_JSON="$GW_JSON"
|
|
exec "$@"
|
|
;;
|
|
proton-bridge)
|
|
# Steev reads JP's Proton inbox via the local Proton Bridge IMAP daemon
|
|
# (T6 sidecar — see PROFILE-DISTRIBUTION-PROTOCOL §4.T6). credctl stores
|
|
# the bridge password (rotates when JP rotates the bridge).
|
|
PB_PASS="$(cred_raw proton-bridge-imap)"
|
|
[ -n "$PB_PASS" ] || die "credctl: proton-bridge-imap not set"
|
|
export PROTON_BRIDGE_IMAP_PASSWORD="$PB_PASS"
|
|
exec "$@"
|
|
;;
|
|
perplexity)
|
|
# Lightweight WebSearch path. Most Steev research goes through the
|
|
# perplexity MCP server (which holds its own key); this credbridge entry
|
|
# exists for scripts that need a raw key (rare).
|
|
PPL_KEY="$(cred_raw perplexity-api)"
|
|
[ -n "$PPL_KEY" ] || die "credctl: perplexity-api not set"
|
|
export PERPLEXITY_API_KEY="$PPL_KEY"
|
|
exec "$@"
|
|
;;
|
|
*)
|
|
die "unknown tool: $TOOL (allowed: google-workspace|proton-bridge|perplexity)"
|
|
;;
|
|
esac
|