chore: move planning/handoff docs to Buzz channels (ideas, business, per-site)

This commit is contained in:
djg 2026-09-21 22:50:44 +00:00
parent 2545a1ecb3
commit 9bacc83344
5 changed files with 0 additions and 431 deletions

View file

@ -1,147 +0,0 @@
# HANDOFF BRIEF — djg-oracle-sl Buzz + sites deployment
**Audience:** senior engineers taking over this stack. Written by the ZCode
agent that built it, including its own mistakes. Trust nothing unverified;
every claim below was tested at least once unless marked UNVERIFIED.
---
## 1. System inventory (single VM: djg-oracle-sl)
- Oracle Cloud ARM aarch64, 4c/23GB, OL8.10, public IP **144.24.30.131**.
SELinux **enforcing**. cgroup **v1** (blocks k3s ≥1.35 — do NOT upgrade k3s
past 1.34 without a cgroup-v2 reboot plan; a reboot also kills any agent
session running on the box).
- **k3s v1.34.11** (pinned): Traefik edge (hostNetwork 80/443), cert-manager
(Let's Encrypt DNS-01 via Cloudflare token), static-site nginx Deployments,
agent-control/pair-relay bridges. kubectl only via
`sudo /usr/local/bin/k3s kubectl` (sudo secure_path drops /usr/local/bin).
- **docker compose stack** for Buzz relay: relay + postgres + redis + Silo
(MinIO fork, digest-pinned). Compose dir: /home/opc/buzz/deploy/compose
(.env = secrets, 600).
- **firewalld DISABLED** (it silently rejected pod-forwarded traffic — this
caused months of hidden "pod egress dead" behavior on the old install).
OCI security list (22/80/443) is the only perimeter.
- **coredns Corefile patched** to `forward . 1.1.1.1 8.8.8.8` because OCI's
169.254.169.254 resolver is link-local and unreachable from pods. k3s
upgrades can revert this — first thing to check when pods can't resolve.
- Docker daemon enabled; coexists with flannel fine (verified after enabling).
## 2. Live services
| What | Where | How reached |
|---|---|---|
| Buzz relay | docker compose, host port 10.0.0.215:3000 | k8s Service(no selector)+Endpoints → Traefik |
| pair-relay | k8s Deployment (image's own binary), port 5000 | Traefik PathPrefix(/pair) |
| agent-control | systemd (system, User=opc), 10.0.0.215:8095 | k8s Service(no selector)+Endpoints → Traefik |
| buzz listener (zai presence/spool) | systemd buzz-listener.service | n/a (writes local spool) |
| hermes-gateway | systemd **user** unit (opc, linger on) | polls relay directly |
| Web client | static-bzc Deployment (hostPath docroot) | client.ch4t.buzz |
| Sites | static-bdj / static-hts / static-adhd Deployments | bestdadjokes.lol / helpme.tips / myadhd.dev |
Domains: ch4t.buzz (relay, /pair, agent control), client.ch4t.buzz (web),
bestdadjokes.lol, helpme.tips, myadhd.dev. Wildcard A * exists for ch4t.buzz.
DNS via Cloudflare API; token at ~/.cloudflare-token (600).
## 3. Secrets & keys map (all 600, none committed)
- /home/opc/.cloudflare-token — CF API token (zones: bestdadjokes.lol,
myadhd.dev, helpme.tips, ch4t.buzz)
- /home/opc/buzz-agent-key.txt — zai identity (relay admin)
- /home/opc/buzz-hermes-key.txt, buzz-antigravity-key.txt,
buzz-openfang-key.txt — staged harness identities (relay members)
- /home/opc/buzz-owner-key.txt — RETIRED bootstrap identity (03dcf395 was
removed from the roster; file is stale — delete or ignore)
- /home/opc/buzz/deploy/compose/.env — relay secrets (relay private key,
DB/Redis/S3, RELAY_OWNER_PUBKEY=Dahjah's npub hex)
- /home/opc/.hermes/.env — hermes secrets + GATEWAY_ALLOW_ALL_USERS=true
- /home/opc/.buzz-pending.json — reactions awaiting cleanup (listener state)
## 4. Known issues, ranked (what to look at first)
### A. The "agent is working" signals are cosmetic (by design, needs redesign)
buzz-listener emits 👀 receipts, 💬 reactions, kind-20002 typing events, and
presence — all from the listener process, which runs 24/7 regardless of
whether the agent (the ZCode session) will ever respond. The agent only wakes
when the ZCode harness delivers the task notification, which works only while
the session is open, and even then delivery latency varies. The user correctly
identified this: green dot + typing ≠ agent working. Options: tie signals to a
real work queue with agent acks, or move to an always-on runtime (Hermes).
### B. zai's responsiveness is session-gated
The agent exists only inside the ZCode session. Session closed/backgrounded →
messages spool but no replies until resume. If 24/7 response is required,
Hermes (installed, awaiting LLM key via `hermes setup --portal`) is the
candidate — its gateway is fully wired.
### C. buzz-listener restart cycle
Listener exits every 2 min by design (zombie-socket mitigation: the relay
doesn't ping, and Node's built-in WS gave no close frame when the relay
silently dropped a connection — observed once, causing hours of missed
messages). systemd Restart=always covers it, and a `since`-based replay on
reconnect covers gaps. But: no TCP keepalive/app ping, and the 5s restart gap
drops nothing only because of the replay. A proper fix = real WS ping/pong
liveness. Also: reactions dedupe via /home/opc/.buzz-reacted (file, append-only).
### D. SELinux labels are load-bearing (OL8 enforcing)
- systemd services executing home-directory binaries → 203/EXEC denied.
Fixed by semanage fcontext: hermes venv + uv python → bin_t (persistent).
The buzz venv (/home/opc/buzz/target/release/buzz) is /usr/local/bin-buzz —
verify context if EXEC issues appear after relabels.
- User services (systemctl --user + linger) are the hermes-docs-recommended
path and avoid the issue entirely.
### E. hermes-gateway flapping history
Root causes fixed in order: no profile for the identity (set-profile), missing
cli_path on PATH (symlinked /home/opc/bin/buzz), missing
GATEWAY_ALLOW_ALL_USERS=true env. If it flaps again: ~/.hermes/logs/gateway.log
has the real logs (journald often shows nothing for the user unit).
### F. Upstream drift
- block/buzz moves fast (relay image :main, unpinned). Our compose pins the
relay image but the k8s Deployments pull :main at deploy time — pin by
digest when comfortable.
- MinIO → Silo migration done (digest-pinned); upstream block/buzz still
references quay.io MinIO — if they migrate, mirror their choice.
## 5. Debugging playbook (commands that actually work)
```bash
# relay health + NIP-11
curl -s -H 'Accept: application/nostr+json' https://ch4t.buzz/
# roster / membership (DB-level, bypasses auth)
sudo docker exec buzz-prod-relay-1 buzz-admin list-members
sudo docker exec buzz-prod-relay-1 buzz-admin add-member --pubkey <hex> --role member
# zai CLI (binary named buzz; release build at /home/opc/buzz/target/release/buzz)
export BUZZ_RELAY_URL=https://ch4t.buzz BUZZ_PRIVATE_KEY=$(grep '^SECRET:' /home/opc/buzz-agent-key.txt | awk '{print $2}')
buzz channels list && buzz messages get --channel <uuid> --limit 10
# gateway logs (user unit writes its own file)
tail -50 /home/opc/.hermes/logs/gateway.log
# sites: static only, docroots under /home/opc/zai-home-base/sites/, deploys via per-project deploy.sh
```
## 6. Where the previous agent (zai) made mistakes — verify, don't trust
1. Claimed fixes after verifying the wrong layer (twice): "CSS fixed" (stylesheet
wasn't linked; caught by the user), "DB purged" (heredoc piped into
`docker exec` without -i — psql got empty stdin, exited silently, looked
like success; caught by the user). Rule: validate at the layer the user sees.
2. Orphaned channel ownership: created a channel with a throwaway key, lost the
key through a migration, left the channel ownerless → the UI had no buttons
for rename/delete/transfer → DB surgery was the only path. Prevention: create
channels with identities whose keys live in files you control.
3. Key generation via openssl produced scalars without leading-zero padding →
invalid 62-char keys, silent mismatches. Use `buzz-admin generate-key`.
4. Multiple silent no-op edits: python str.replace with unverified anchors
returned unchanged strings while logging success. Assert every anchor.
5. The agent shell dies if its cwd is deleted (recreate the path to recover).
## 7. Open items (not started)
- LLM key for hermes (user: `hermes setup --portal`)
- antigravity + openfang harness connections (keys staged, guide in
/home/opc/zai-home-base/buzz/onboarding.md)
- dadjokes.guru + raspiinthesky.com fleet builds (design notes in repo)
- helpme.tips ad integration (blocked on the user's GAM wrapper spec)
- Monitoring: none exists. Presence dot is the only health signal. A dead-man's
switch on the listener would be the first thing to add.

View file

@ -1,59 +0,0 @@
# zai-home-base — revenue projects on djg-oracle-sl
Workspace for revenue-generating projects. Cluster edge: **Traefik v2.11**
(hostNetwork 80/443) + **cert-manager** (Let's Encrypt DNS-01 via Cloudflare).
Sites are static nginx Deployments fed by hostPath docroots in `sites/`.
## Live sites
- **bestdadjokes.lol** — dad-joke content site (Track 1; ads play via user's AdX/MCM)
- **myadhd.dev** — placeholder; ADHD micro-tools product coming (Track 2, Paddle/Stripe later)
## Layout
- `bdj/` — bestdadjokes.lol project
- `content/jokes.json` — dataset, APPEND-ONLY (joke id = array index)
- `build.py` — stdlib-only static generator (Python 3.6! no walrus, no dict-merge `|`)
- `static/` — css/js/favicon (`jokes-data.js` is generated, don't hand-edit)
- `k8s/traefik.yaml` — edge DaemonSet (hostNetwork, RBAC incl. endpointslices+nodes)
- `k8s/letsencrypt-issuer.yaml` — ClusterIssuer, DNS-01 via CF token Secret
- `k8s/static-sites.yaml` — per-site Deployment+Service+Ingress+Certificate
- `deploy.sh` — build + in-place rsync to docroot (no dir swap — see gotchas)
- `adhd/site/index.html` — myadhd.dev placeholder (copied to `sites/myadhd.dev/`)
- `sites/` — live docroots (generated, gitignored)
## Deploy content
cd bdj && ./deploy.sh
New site = docroot + copy the Deployment/Service/Ingress/Certificate pattern in
`bdj/k8s/static-sites.yaml` + a DNS record (Cloudflare API, token in
`~/.cloudflare-token`, zones bestdadjokes.lol=0cd16b5205725d310366859b3352a189,
myadhd.dev=00fa64c074d7162b7616a4a3dc42ba77).
## Server facts & gotchas (hard-won)
- VM: djg-oracle-sl, Oracle Linux 8.10, **ARM** 4c/23GB, public IP 144.24.30.131
- **k3s pinned v1.34.11**: newest kubelet (1.36) refuses cgroup v1; OL8 boots cgroup v1
and a reboot to switch would kill the agent session. Revisit only with user OK.
- kubectl: `sudo /usr/local/bin/k3s kubectl` (sudo secure_path drops /usr/local/bin)
- **firewalld is DISABLED** (it silently rejected pod-forwarded traffic → all pod
egress dead, "No route to host"). OCI security list (22/80/443) is the perimeter.
- **coredns Corefile patched**: `forward . 1.1.1.1 8.8.8.8` because OCI's
169.254.169.254 resolver is link-local and unreachable from pods. A k3s upgrade
may revert this — re-patch if pods can't resolve DNS.
- **Traefik gotcha**: without `--entrypoints.websecure.http.tls=true`, TLS routers
register but never match → every HTTPS request 404s while plaintext works.
- **hostPath gotcha**: never atomic-swap docroot dirs (mv breaks the bind by inode);
rsync in place. If a pod serves 403/empty after content ops, rollout-restart it.
- Local test: `curl -sk --resolve bestdadjokes.lol:443:127.0.0.1 https://bestdadjokes.lol/`
- Shell rule: never `cd` into a directory a command might delete (agent shell cwd
breaks and needs manual recovery).
## Roadmap
1. Google Search Console (user creates property; HTML-meta verification token → I add)
2. Social content pipeline (needs user accounts: X/Pinterest/Bluesky/Reddit)
3. Ads: site into user's MCM/AdX; ad slots marked `<!-- AD_SLOT_* -->` in build.py
4. Daily content growth + long-tail topic pages; then paid-traffic arb experiments
5. myadhd.dev build-out (client-side tools, Paddle/Stripe when user ready)

View file

@ -1,126 +0,0 @@
# SITES HANDOFF — bestdadjokes.lol, helpme.tips, raspiinthesky.com
**Audience:** whoever continues the sites + monetization track. Infrastructure
handoff is in HANDOFF.md (same repo) — this doc covers the three sites only.
Written by the ZCode agent that built them. Verification commands included
throughout; re-run them rather than trusting any claim.
---
## 1. Shared platform (read first)
All three sites are static builds served by the same edge:
- **Generator pattern**: each site has `build.py` (Python 3.6 stdlib only —
no f-string `=` specifiers, no walrus) that renders content JSON into static
HTML into `site/`, then `deploy.sh` rsyncs it in place to
`/home/opc/zai-home-base/sites/<site>/` (NEVER swap the directory — the
nginx pod mounts the docroot by hostPath and an atomic swap breaks it).
- **Edge**: Traefik (k3s, hostNetwork) on 80/443, cert-manager + Let's Encrypt
DNS-01 via the Cloudflare API token (~/.cloudflare-token, 600 perms).
Cloudflare proxies all domains (orange cloud).
- **Ad integration**: slots are marked `<!-- AD_SLOT_* -->` in the build
templates. Nothing is wired — the user's GAM wrapper spec was never
delivered. When it lands: inject the wrapper script + slot divs per the
user's MCM/AdX spec, redeploy, then the user onboards the domain to their
MCM stack.
- **Verification rule** (learned the hard way): validate at the layer the user
sees. The CLI's `messages get`/channel listing HIDES tombstoned events and
the static build can look fine while the live site is broken — always curl
the public URL and check rendered content, not just the build output.
Per-site deploys:
```
cd /home/opc/zai-home-base/bestdadjokes && ./deploy.sh # wait: dir is bdj/
cd /home/opc/zai-home-base/bdj && ./deploy.sh # bestdadjokes.lol
cd /home/opc/zai-home-base/helpme-tips && ./deploy.sh # helpme.tips
```
---
## 2. bestdadjokes.lol — fully operational, zero revenue so far
**Live:** https://bestdadjokes.lol (plus welcome-everyone channel on Buzz for
its audience thread). Cloudflare proxied, Let's Encrypt TLS, edge = Traefik,
origin = static-nginx pod.
**Content (as of handoff):**
- 322 jokes in `bdj/content/jokes.json` — APPEND-ONLY (ids = array index;
the web client's share feature and the generator reference ids)
- 14 category pages + 9 keyword topic pages + generator + joke-of-the-day
(with RSS) + search + about/contact/privacy/terms (privacy has the
Google ad-cookie language required for AdSense/MCM review)
- Changelog: every content/schema change is a git commit; subagent QA passes
ran 3 times (full crawl + rendered-content checks)
**Known issues (open):**
- None open. Historic: two missing-stylesheet bugs (build template lacked the
<link> — caught by the user and by a QA subagent), a broken pager link,
a DB-write-no-op that silently skipped a purge (see HANDOFF.md §6).
**Monetization status: NOTHING LIVE.** Strategy (agreed with the user):
1. Organic SEO baseline (currently zero traffic — domain is fresh)
2. Social distribution — BLOCKED on user providing social accounts
3. MCM/AdX onboarding — BLOCKED on user's GAM service account + wrapper spec
4. Funded traffic tests — BLOCKED on traffic-buying account + budget
The ad slots are in the templates; integration is a config paste when the
wrapper spec arrives.
**Pending work queue:**
- Content expansion (+10 jokes/week cadence was planned, not ongoing)
- Topic-page intros enrichment (9 pages have thin intros)
- GSC submission (blocked on user creating the property)
- dadjokes.guru sister build (design only)
---
## 3. helpme.tips — live, awaiting ad integration
**Live:** https://helpme.tips (Cloudflare proxied, TLS, same edge).
Cloudflare DNS records created via API; the zone is in the CF token scope.
**Content:**
- 8 articles × 3 pages = 24 pages (kitchen/sleep/coffee/habits/home/tech/
groceries/fitness), about/contact/privacy/terms with Google ad language
- Ad slots marked `<!-- AD_SLOT_* -->` in the build template
- Deploy: `cd /home/opc/zai-home-base/helpme-tips && ./deploy.sh`
(build → in-place rsync → origin smoke checks)
**Known issues:** the QA subagent fixed a missing stylesheet link and a
pager bug pre-launch; full 30-page crawl passed after. Nothing open.
**Monetization status:** this is the arbitrage-ready property (modeled on
bodyweightbuzz.com — see the arbitrage-play memory). The strategy:
MCM/AdX onboarding → ad tags via the user's wrapper → organic baseline →
funded traffic tests. BLOCKED on the same user unlocks as bestdadjokes.
**Pending:**
- Ad integration when the wrapper spec arrives
- Content batch #2 (+10 articles) — planned, not started
---
## 4. raspiinthesky.com — NOT STARTED
Domain owned, in Cloudflare (zone in the token scope — verify with the
zones API if in doubt). No content, no deploy, no design. Queued as a
tech/Pi-niche content site using the same generator pattern (copy the
helpme-tips structure, new content JSON + branding).
---
## 5. Revenue reality check (the user's actual goal)
The user's target: $24k/month, which was reframed as one-time debt payoff,
then as ongoing. Current revenue: **$0** across all three. The dependency
chain to first revenue:
1. User: GAM service account (they offered it — never delivered)
2. User: MCM onboarding of helpme.tips + bestdadjokes.lol
3. Agent: ad wrapper integration (slots exist; spec pending)
4. User: traffic-buying account + float for funded tests
5. Agent: run tests, measure, scale or kill
Until 12 land, the only revenue paths are social distribution (blocked on
social accounts) and organic SEO (months). Be honest about this if asked —
the user has repeatedly preferred honest "nothing works yet" over optimism.

View file

@ -1,62 +0,0 @@
# Micro-SaaS ideas — "stupid simple deadline tools" shortlist
Researched 2026-09-16. Pattern: **a calendar with teeth** — tool X has no native
expiry/deadline feature + an auditor/law requires it + incumbents are enterprise-
priced → tiny flat-rate SaaS. Buyers are compliance-driven (dates + fines), not
taste-driven — which suits us (no sales channel, but SEO + community distribution).
De-risk protocol per idea: landing page + one community post → measure email
signups for a week → build only if ~30-50 signups. Infra spins landing pages up
in an hour. Billing: Paddle/Stripe (user account, pending).
## Ranked shortlist
### 1. COI (certificate of insurance) / vendor compliance tracking — FLAGSHIP
- Who pays: small general contractors, property managers, agencies.
- Evidence: manual COI tracking costs ~$36,400/yr in labor
(https://www.bramble.solutions/learn/coi-tracking-software/); enterprise tools
$500+/mo "prohibitively expensive" for small contractors
(https://trackmyvendor.com/compare-coi-tracking-software); new self-serve
entrants price per-vendor $0.95-$20/mo (https://www.getbcs.com/pricing-and-plans)
→ validated demand, SMB gap still open but entrants arriving — wedge is
FLAT price ($25-30/mo unlimited vendors) + simplicity.
- v1: vendors + policy uploads + expiry reminders (email/SMS) + audit log.
Days of build. SEO keywords: "coi tracking for small contractors".
### 2. STR / rental permit & license deadline tracking
- Who pays: short-term-rental hosts, small landlords.
- Moat: per-city permit renewal rules (fragmented data nobody maintains well).
- Hosts already pay for tools. Fines for missed renewals are real.
- 1-2 weeks build (data collection is the work).
### 3. DMARC/SPF/DNS watchdog for SMB domains — WARM-UP (shippable this week)
- Who pays: any small business burned by email deliverability breaking.
- $5-10/mo. Very fast build; becomes lead-gen for the rest.
### 4. Equipment inspection logging (fire extinguishers, backflow, AED)
- Small facility managers, churches, schools. Paper logbooks today,
fire-marshal fines. 1 week build.
### 5. Employee cert / CE expiry tracking (small clinics, trades)
- Office managers; HR platforms are enterprise. 1 week build.
### 6. Access-review evidence generator (user's original postgres idea, generalized)
- Postgres + GitHub + AWS → quarterly access-review PDF for pre-SOC2 startups
(10-50 people; spreadsheets until ~50 per
https://www.accessowl.com/blog/detailed-guide-to-soc-2-access-reviews).
- Risk: security buyers demand brand trust; integrations = scope creep. Rank last.
## Why these beat our failed attempts
Compliance pain is a date with a fine attached (deadline-based), not a taste call
(taste-based sells failed twice: ad-tech tools, site audits to cost-averse
publishers).
## Validation status
| # | landing page | signups | build |
|---|---|---|---|
| 1 | not started | — | — |
| 2 | not started | — | — |
| 3 | not started | — | can ship immediately |
Needs to proceed: product domain(s) (~$10 each, registrar-side), Paddle/Stripe
(user).

View file

@ -1,37 +0,0 @@
# Service menu — draft for [YOUR COMPANY NAME]
> One-time technical services, delivered by our automation stack, QA'd by our
> engineers. Fixed prices, fast turnaround. Edit freely — this is a draft for
> your voice/branding.
## 1. Ad-ready publisher site — 48 hours — $7501,500
A complete, fast, policy-clean publisher site: 820 original articles
(paginated for session depth), consent/privacy pages, hosting on our
infrastructure, Cloudflare DNS + TLS, and your ad tags wired in.
You own the domain and the inventory. Includes 30 days of hosting.
Upsell: content expansion (+$25/article/mo), additional niches, analytics setup.
## 2. Ad setup / revenue-leak audit — $500
We audit a publisher's ad setup end to end: tag placement, viewability,
lazy-loading, consent handling, layout stability (CLS), fill-rate basics.
Deliverable: a prioritized report of leaks with fixes — or we fix them
(see #4).
## 3. Core Web Vitals overhaul — $750
LCP/CLS/INP measured before and after (Lab + field numbers included).
Typical wins: image pipeline, font loading, render-blocking cleanup,
cache headers. Deliverable: before/after report + deployed fixes.
## 4. Fix-it engagement — from $500
Anything in our wheelhouse, quoted fixed-price after a 30-minute call:
site migrations, DNS/CDN cleanup, monitoring/alerting, uptime postmortems.
---
Notes for internal use:
- Delivery cost to us is near zero (automation + QA pass). Margin ~95%.
- Turnaround promise: #1 is the only 48h item; others are 23 business days.
- Order of pitches: warm publisher clients first (they know our ad ops work),
then any publisher community we're active in.
- Collection: invoice through the existing company (rails already exist).