morphit/docs/AUTOMATION-AUDIT.md

395 lines
15 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Morphit — automation audit of manual interventions (Q6)
**Last reviewed:** 2026-05-01
This catalog enumerates every place in Morphit where a human
operator, admin, or user has to do something manually that
could potentially be automated. For each item: the current
state, the automation potential (HIGH / MEDIUM / LOW), the
cost, and the recommendation.
The goal isn't to automate everything — some manual gates
exist deliberately to preserve operator control over
expensive, irreversible, or high-trust actions. The goal is
to surface where automation would meaningfully reduce
operator load without increasing risk.
This audit complements `docs/OPERATIONS.md` (the operator
runbook) and `docs/RUN-A-MORPHIT-NODE.md` (the new-operator
walkthrough). Both must stay aligned with this catalog.
---
## 1. Operator-side manual tasks
### 1.1 Weekly ACT minting ceremony — ❌ REMOVED (beta.28 / cp329)
**There is no ACT minting task any more, so there is nothing to
automate here.** Blurt disabled `claim_account` /
`create_claimed_account` at hard fork 2, so Account Creation
Tokens cannot be minted at all. As of beta.28 (ADR-0010, as
amended 2026-06) the relay creates each account with a direct
`account_create` op, paying the ~100 BLURT `account_creation_fee`
**inline** from its liquid BLURT at signup time. The
`mint-acts.ts` script, the `morphit-relay-mint-acts.{service,timer}`
units, and the `MORPHIT_RELAY_WEEKLY_ACT_COUNT` /
`MORPHIT_RELAY_AUTOMINT_*` config knobs have all been removed.
**Operator-side, the only standing task is funding** — keep
`@morphit-relay` topped up with enough liquid BLURT to cover
signups (see OPERATIONS §0a for the sizing math and §16 for the
`relay_low_balance_for_signups` Matrix alert). That funding is
itself "automatable" via a recurrent on-chain transfer (§1.2),
and the low-balance alerting is already automated (§1.6), so no
new automation is owed here.
**STATUS**: ✅ Implemented 2026-05-01. See OPERATIONS.md §2
"Unattended mode" for the operator-facing setup steps.
---
### 1.1-archive: original framing (preserved for ADR-0010 traceability)
**Why manual originally**: ADR-0010 §4 framed this as a
deliberate operator-in-the-loop step so the relay's working
BLURT balance stays small and a compromised relay can't drain
unbounded BLURT into ACTs. The 2026-05 review concluded the
caps still hold under timer-driven minting (§1.1 above), so
the in-the-loop confirmation became a cron job.
---
### 1.2 Recurrent BLURT top-up to relay — ALREADY AUTOMATED
**Today**: ADR-0010 §3 ships a `recurrent_transfer` op the
operator broadcasts ONCE at setup time. Blurt natively
recurses the transfer weekly for `executions=52` (one year).
**Why this is good**: Native chain primitive. No off-chain
cron, no hot key on a server. The operator re-broadcasts
once a year (or sooner if their fee-account address changes)
— that's a quarterly-or-better cadence, not weekly.
**STATUS**: Already automated; no work to do.
---
### 1.3 TLS certificate renewal — ALREADY AUTOMATED
**Today**: certbot installs a systemd timer that runs twice
daily and auto-renews when the cert is within 30 days of
expiry.
**Recommended addition**: a weekly `cron.weekly` job that
checks expiry and pages the operator if certs ARE near
expiry but renewals haven't fired (catches certbot
configuration drift). This is in OPERATIONS.md §16 (the
`morphit-certbot-monitor` renewal-stall detector) already.
**STATUS**: Already automated; the optional alert wrapper
is documented but not shipped as a default unit.
---
### 1.4 Witness fee change response — MEDIUM automation potential
**Today**: When Blurt witnesses change `account_creation_fee`,
the operator sees an alert and manually updates
`MORPHIT_INDEXER_ACCOUNT_CREATION_FEE_BLURT` and
`MORPHIT_RELAY_ACCOUNT_CREATION_FEE_BLURT` env vars,
restarts services.
**Why manual today**: Setting a wrong fallback value silently
breaks signup. Operator-in-the-loop catches misreads.
**Why automation is constrained**: The fallback is exactly
that — a fallback for when chain RPCs are unreachable.
Auto-updating it from the chain would create a
self-referential bootstrap problem if the auto-update path
itself relies on chain RPCs.
**Recommended partial automation**:
- Indexer + relay should both observe `account_creation_fee`
changes via their normal block-walk and EMIT a structured
log line at WARN level when the observed fee differs from
the configured fallback by more than 10%. This is already
partly there for the indexer (chain-fee tracker); not yet
for the relay.
- Operator gets an alert via their journald-watching pipeline
when the warning fires; manual restart is fast.
**Cost**: ~20 lines (relay-side warn-log of fee divergence).
**STATUS**: ✅ Both shipped. Indexer-side tracker existed at
audit time; relay-side warn-log shipped in Part 117 —
`apps/relay/src/blurt/client.ts:157` defines
`FEE_DIVERGENCE_WARN_THRESHOLD = 0.1` and
`analyzeFeeDivergence()` at line 168 emits a structured
`chain_props_account_creation_fee_diverges_from_config`
warn-log when the observed fee differs from the configured
fallback by more than 10%, throttled once-per-process-startup.
Smoke regression at `apps/relay/scripts/fee-divergence-smoke.ts`
registered in `scripts/run-smokes.sh`.
---
### 1.5 Stale price feed alert — ALREADY AUTOMATED
**Today**: Indexer's price source emits `stale=true` after
N minutes without a successful upstream fetch. The frontend
hides the USD echo when stale. Operator sees journald
`price.fetch.failed` lines.
**STATUS**: Already automated; alerting is via the
operator's normal journald pipeline.
---
### 1.6 Operator-account balance monitoring — ALREADY AUTOMATED
**Today**: Indexer scans operator-fees balances and emits
structured alerts when below operator-configured thresholds.
Documented at OPERATIONS.md §16.
**STATUS**: Already automated.
---
### 1.7 Relay queue stuck — MEDIUM automation potential
**Today**: A signup queue entry can get stuck (network errors,
RC depletion, etc.). The operator manually nulls the
`broadcast_at` to retry.
**Why manual today**: Stuck entries can mask deeper relay
problems (RC depletion, key issues, broken endpoints). An
automated retry loop could mask these.
**Recommended partial automation**:
- Auto-retry up to 3 times with exponential backoff (1m, 5m,
15m). After 3 failures, the entry stays stuck and waits
for operator review.
- Today the relay does retry on transient network errors but
not on the stuck-entry flagged-for-manual case.
**Cost**: ~80 lines (queue-entry retry counter + scheduler).
**STATUS**: Documented as a future hardening pass. Not
urgent — operator manual flow is rare and well-documented.
---
### 1.8 Schema migrations — ALREADY AUTOMATED
**Today**: Indexer auto-runs migrations on boot via
`apps/indexer/src/db/migrations.ts`. v17 has a brief
sequential-scan window during the upgrade documented at
OPERATIONS.md §21; otherwise transparent to the operator.
**STATUS**: Already automated.
---
### 1.9 Server OS package updates — DOCUMENTED + RECOMMENDED
**Today**: OPERATIONS.md §37.2 recommends `unattended-upgrades`
for security patches. Operator chooses to enable.
**STATUS**: Documented; not enforced by Morphit's installer
because the installer doesn't exist as a single thing — the
operator runs through RUN-A-MORPHIT-NODE.md. The walkthrough
SHOULD include enabling unattended-upgrades as a checklist
item. (See §3.3 below.)
---
## 2. User-side manual tasks (Q9 setup-checklist territory)
These are the user/operator's checklist responsibilities
during account setup or daily use. Q9's "operator setup
checklist + nudges" answer expands on this — see that
section.
### 2.1 Backup the 12-word seed — ✅ AUTOMATED 2026-05-01
**Today**: Signup flow displays the seed once with a "I've
saved it" gate. Plus, after 7 days of active use on this
device, a soft amber banner appears at the top of every page
asking "have you backed up your seed somewhere durable?" with
a "Show me how →" link to the recovery FAQ and a one-tap
permanent dismissal.
**Implementation**:
- localStorage anchor `morphit.keystore.first_persist_at`
stamped on first successful `writeEnvelope` (in
`apps/web/src/lib/crypto/persistentKeystore.ts`).
- Banner component `SeedBackupNudge.svelte` calls
`shouldShowSeedBackupNudge()` on mount; renders only when
≥7 days since first persist AND not dismissed.
- "Got it" sets `morphit.keystore.backup_nudge_dismissed = '1'`,
hiding the banner permanently on this device.
- Full sign-out (`clearKeystore`) wipes both anchors so
re-onboarding restarts the prompt schedule.
**STATUS**: Shipped.
---
### 2.2 Verify counterparty's chat-pub on first contact — ✅ SHIPPED
**Today**: `apps/web/src/lib/components/VerifyPeerPanel.svelte`
renders an explicit Verify-peer panel inside `ConversationView`
showing the deterministic `(my_chat_pub, peer_chat_pub)`
fingerprint pair (computed in `apps/web/src/lib/chat/fingerprint.ts`).
Users compare fingerprints out-of-band (voice, in-person,
side-channel) and confirm. That's a manual user action by
design — the machine can't out-of-band compare.
**STATUS**: Shipped (panel + fingerprint helper + locale
strings in all 10 locales).
---
### 2.3 Mark trade complete + leave feedback — MANUAL BY DESIGN
**Today**: After receiving funds, the buyer/seller manually
clicks "Trade complete" and "Leave feedback". This is
deliberately manual — Morphit doesn't run any wallet, so
"funds received" is something only the user can attest to.
**STATUS**: Cannot be automated without breaking the
non-custodial design. Already as automated as it can be.
---
## 3. Operator setup tasks (Q9 territory — feeds into the checklist)
### 3.1 Enable unattended-upgrades — should be in setup checklist
**Cost**: 1 command in the walkthrough.
**STATUS**: Documented in OPERATIONS.md §37.2. Should be
flagged in `ops-cli init` as a checkbox + ufw / fail2ban /
SSH key-only mode.
### 3.2 Configure systemd timers for auto-tasks — should be in setup checklist
The weekly ACT-mint timer referenced here historically was
removed at beta.28 (see §1.1). The remaining auto-task timers the
setup wizard should install + enable alongside the relay are the
monitoring/backup units (TLS renewal, balance alerts, backups) —
none of them touch account creation, which now pays its fee
inline per signup.
### 3.3 ops-cli should verify everything's in place — Q9 deliverable
The `ops-cli init` wizard already does: chain RPC reachability,
account existence check, key-file perms check, fee-address
viewkey verification, etc. It should ALSO run a final
checklist verification step that pings each of these and
prints "✅ done" or "⚠ missing — run X to fix":
| Check | Today | Recommended |
|---|---|---|
| `morphit-fees` account exists | ✅ done | Keep |
| Active-key file mode 0400 | ✅ done | Keep |
| Indexer DB connection works | ✅ done | Keep |
| RPC endpoint reachability | ✅ done | Keep |
| Relay BLURT balance > floor | ✅ done | Keep |
| TLS cert valid + auto-renew configured | ✅ done | Keep |
| `unattended-upgrades` installed + enabled | ❌ not yet | **Add** |
| `ufw` enabled + correct ruleset | ❌ not yet | **Add** |
| SSH `PasswordAuthentication no` | ❌ not yet | **Add** |
| `fail2ban` installed + sshd jail enabled | ❌ not yet | **Add** |
| journald disk cap configured | ❌ not yet | **Add** |
| weekly-mint timer installed (§1.1 shipped 2026-05-01) | ❌ not yet | **Add** |
| witness-fee-divergence warn-log configured | ❌ not yet | **Add** |
| frontend CSP headers verified | ✅ done (§15) | Keep |
| Tor onion mirror reachability | ❌ not yet | **Add** |
This expanded checklist becomes Q9's deliverable — see the
Q9 plan in this session's notes.
---
## 4. What we deliberately do NOT automate
A list of "could automate, but shouldn't":
- **Trade matching.** Buyers and sellers pick each other based
on reputation, terms, location. Auto-matching breaks the
trust model.
- **Dispute resolution.** Morphit has no arbitrator role
(FAQ `no_escrow_arbitration`). A bot that "decides who's
right" would be a centralization vector.
- **Fund release.** Non-custodial means the seller releases
funds when the buyer pays. No bot can decide when payment
has arrived in a non-custodial flow — only the human
actually receiving the funds knows.
- **Reputation moderation.** Feedback is permanent and
signed. A bot that "removes spam reviews" is a
centralization vector. (Operators can suppress display on
their own instance; the chain record is permanent.)
- **Owner-key rotation.** OPERATIONS.md §8 — must be human
with cold-storage backups verified.
- **Initial ACT-key passphrase entry on relay first boot.**
Documented in OPERATIONS.md §3. Subsequent reboots can use
systemd `LoadCredentialEncrypted=` if the operator chooses;
first boot is human.
---
## 5. Cross-cutting automation ideas
### 5.1 Health endpoints for external monitoring
The indexer already exposes `/v1/health`. The relay should
too (today it has a `/v1/health` but coverage is thin).
Operators can wire these into their existing monitoring
(Uptime Kuma, Statping, etc.).
### 5.2 Structured log shipping
Both indexer and relay log to journald. Operators wanting
remote log aggregation can ship via journald → Vector → any
sink. Documented in OPERATIONS.md.
### 5.3 Automated backup of operator config + key envelopes
Encrypted active-key envelopes are at `/etc/morphit/*.key.enc`.
The operator should back these up off-host (not the relay's
own filesystem). OPERATIONS.md should add a recommendation
for an automated nightly rsync to a backup destination,
encrypted at rest. Currently silent on this.
---
## Summary table
| # | Task | Auto today? | Recommend automating? | Effort |
|---|---|---|---|---|
| 1.1 | Weekly ACT minting | ❌ Removed (beta.28) | n/a — task no longer exists | done |
| 1.2 | Recurrent BLURT top-up | ✅ Native chain | n/a | done |
| 1.3 | TLS renewal | ✅ certbot | n/a | done |
| 1.4 | Witness fee change response | ❌ Manual | 🟡 Partial — log warn | ~20 lines |
| 1.5 | Stale price feed | ✅ stale flag + log | n/a | done |
| 1.6 | Operator-account balance | ✅ scanner + alerts | n/a | done |
| 1.7 | Relay queue stuck | ❌ Manual | 🟡 Partial — auto-retry 3× | ~80 lines |
| 1.8 | Schema migrations | ✅ on-boot | n/a | done |
| 1.9 | OS package updates | 🟡 Documented | ✅ Add to setup checklist | doc only |
| 2.1 | Backup-seed nudge | ❌ Manual | ✅ Add a 7-day prompt | ~30 lines |
| 2.2 | Counterparty pub verify | ❌ Manual UX gap | 🟡 Tracked (Option 6) | ~150 lines |
| 2.3 | Mark trade complete | ❌ Manual by design | ❌ Cannot — non-custodial | n/a |
| 3.x | Setup checklist | 🟡 Partial | ✅ Q9 deliverable | ~200 lines |
---
## Next steps
1. Implement §3.3 (expanded setup checklist) as part of Q9.
2. Implement §2.1 (7-day backup-seed nudge). Small.
4. Document §1.9 + §5.3 in OPERATIONS.md and
RUN-A-MORPHIT-NODE.md.
These can be picked up in any order; they don't depend on
each other.