0d24309433b0ad6f11c171ba07ba2bd0f0f37c44
ci / lint-test-leaks (pull_request) Canceled after 0s
Background: CAYCE_OPS_OPERATOR_PUBKEY was set to Cayce nostr pubkey — Cayce was approving itself. Signature was technically valid but semantically null: human approval signed by the agent is not human approval. - signing.py: validate_no_self_approval() rejects the operator pubkey when it matches (a) the pubkey derived from any private key in the config, or (b) any pubkey in CAYCE_OPS_FORBIDDEN_OPERATOR_PUBKEYS deny-list. - executor/maild/publisher _signing() now calls the validation, so every daemon and every CLI approve-* path refuses to operate (D16). - tests: 6 new (agent-key refusal, human key passes, empty passes, explicit denylist, end-to-end daemon refusal, derivation roundtrip). - docs/DECISIONS.md: D16. The operator signature is now produced OUTSIDE the VPS. CAYCE_OPS_OPERATOR_PUBKEY must stay empty until the external signer exists — daemons refuse, which is correct. The Cayce nsec itself is NOT touched (still the agent identity for publishing and anchoring).
Cayce Ops
Cayce Ops is the autonomous operations stack of Cayce — an autonomous entity operating under the Próspera ZEDE agentic-companies jurisdiction pilot. Cayce runs bitcoinhotels.org (Bitcoin-native travel guides) and hardcap.news (Bitcoin security intelligence). The experiment is managed by Cayce itself.
Five decoupled components share one Postgres database. Each is a CLI command, driven by cron/systemd timers. Nothing runs without an audit trail.
| Component | What it does | Human gate |
|---|---|---|
| scanner | Discovers opportunities (affiliates, partnerships, content gaps) from configured sources; files them as proposals |
none — it only proposes |
| executor | Runs approved proposals through registered action plugins; full audit of who approved, what ran, what happened |
approval required (AUTONOMOUS_MODE=false by default) |
| mail-negotiator | Classifies merchant replies (approval / rejection / question / other) over IMAP; drafts replies; SMTP sends only human-approved drafts | draft approval required |
| publisher | Themed content calendar. Nostr (NIP-01) adapter first; Facebook/Instagram adapters exist but are disabled by default; brand images via Pillow templates | publish requires approved items |
| monitor | Static status page: daemon health, last runs, proposal queue, recent errors. No sensitive data | none — read-only |
State machines:
proposal: proposed -> approved -> running -> done | failed
mail: inbound classified; draft: none -> drafted -> approved -> sent
content: draft -> approved -> published
Quickstart (local)
uv sync --frozen # installs Python 3.12 + locked deps
cp .env.example .env # fill in; values are placeholders
docker compose up -d db # Postgres 16
uv run alembic upgrade head
uv run cayceops scanner run
uv run pytest
docker compose up (everything) runs all five daemons in loops; on a VPS use
deploy/systemd instead.
Layout
cayceops/ the package
config.py env-var config (CAYCE_OPS_*), no config files
db.py engine/session/upgrade helpers
models.py ORM schema + state machines + audit helper
llm.py provider-agnostic LLM interface (null by default)
components/
scanner/ discovery -> proposals (never executes)
executor/ plugin execution + audit
maild/ IMAP classify, drafts, SMTP gated on approval
publisher/ calendar, nostr adapter, image templates
monitor/ static status page builder
alembic/ migrations (production schema path)
tests/ pytest suite (invented fixtures only)
deploy/systemd/ VPS units + timers
docs/DECISIONS.md architectural decisions and their costs
Security posture
- Config exclusively via env vars;
.envis gitignored,.env.exampleholds placeholders. make check(and CI): ruff, pytest, alembic smoke, gitleaks over the full history.- SMTP send, social publish, and proposal execution all require a human action
recorded in the audit log — unless
AUTONOMOUS_MODE=true, which enables one narrow, capped, audited exception (see docs/DECISIONS.md D5).
License
MIT — see LICENSE.
Releases
2
Languages
Python
64.7%
JavaScript
27.5%
Shell
3%
PLpgSQL
2.3%
TypeScript
2%
Other
0.4%