Dorian 07e46dce56 feat: add YAML frontmatter, bitcoin-conventions skill, path rules, and Gitea CI
- Added YAML frontmatter to all 8 polish-* skills and sweep skill
  so Claude can auto-invoke them
- New bitcoin-conventions skill with PROUX UX methodology, sats display,
  address validation, Tor preferences, Lightning patterns
- Path-specific rules for containers (security hardening) and frontend
  (Vue/glassmorphism conventions)
- Gitea Actions: nightly security review and weekly dependency audit

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 12:35:17 +00:00

114 lines
3.6 KiB
Markdown

---
name: bitcoin-conventions
description: Bitcoin development conventions for Archipelago. Covers sats display (integers, never float), address type detection, Tor/onion endpoint preference, Bitcoin RPC error handling, and Lightning patterns. Use when working with Bitcoin amounts, addresses, RPC calls, Lightning channels, or onion services.
---
# Bitcoin Development Conventions
## Critical Rules
- **NEVER use floating point for Bitcoin amounts.** Sats are always `u64` (Rust) or `BigInt`/integer (TypeScript).
- **NEVER log private keys, seeds, or mnemonics.** Not even at debug/trace level.
- **Prefer Tor/onion endpoints** for all Bitcoin network services when available.
## Amount Display
### Rust
```rust
// Amount is always in sats as u64
pub fn format_sats(sats: u64) -> String {
if sats >= 100_000_000 {
let btc = sats / 100_000_000;
let remainder = sats % 100_000_000;
if remainder == 0 {
format!("{} BTC", btc)
} else {
format!("{}.{:08} BTC", btc, remainder)
}
} else {
format!("{} sats", sats)
}
}
```
### TypeScript
```typescript
// Never: amount * 0.00000001
// Always: integer arithmetic or BigInt
function formatSats(sats: number): string {
if (sats >= 100_000_000) {
const btc = Math.floor(sats / 100_000_000)
const remainder = sats % 100_000_000
return remainder === 0 ? `${btc} BTC` : `${btc}.${String(remainder).padStart(8, '0')} BTC`
}
return `${sats.toLocaleString()} sats`
}
```
## Address Types
Detect and display address type:
- `1...` — P2PKH (Legacy)
- `3...` — P2SH (SegWit-compatible)
- `bc1q...` — P2WPKH (Native SegWit)
- `bc1p...` — P2TR (Taproot)
Always validate addresses before any operation. Use network-appropriate validation (mainnet `bc1`, testnet `tb1`, regtest `bcrt1`).
## Bitcoin RPC Error Handling
```rust
match rpc_response.error {
Some(err) => {
// Standard Bitcoin Core RPC error codes
match err.code {
-1 => /* miscellaneous error */,
-5 => /* invalid address or key */,
-6 => /* insufficient funds */,
-25 => /* transaction verification failed */,
-26 => /* transaction rejected by policy */,
-27 => /* transaction already in chain */,
-28 => /* client still warming up */,
_ => /* unknown error */,
}
}
None => { /* success */ }
}
```
Always set explicit timeouts on RPC calls (10s default, 30s for heavy operations like `rescanblockchain`).
## Tor/Onion Preferences
When configuring Bitcoin services:
1. Check for Tor SOCKS proxy (default: `127.0.0.1:9050`)
2. If available, route Bitcoin P2P and RPC through Tor
3. Prefer `.onion` endpoints for block explorers, electrum servers
4. Set `proxy=127.0.0.1:9050` in `bitcoin.conf`
5. Set `onlynet=onion` for maximum privacy (if full Tor mode)
## Lightning (LND/CLN) Patterns
### BOLT11 Invoice handling
- Always validate invoice before displaying to user
- Show: amount, description, expiry, destination pubkey
- Never auto-pay without user confirmation
### Channel States
Display human-readable channel state:
- `PENDING_OPEN` → "Opening..."
- `OPEN` → "Active"
- `PENDING_CLOSE` / `FORCE_CLOSING` → "Closing..."
- `CLOSED` → "Closed"
### Macaroon handling
- Never log macaroon contents
- Store with restrictive permissions (0600)
- Use read-only macaroon for queries, admin macaroon only for mutations
## Container Images for Bitcoin Services
- **Always pin by SHA256 digest**, never by tag alone
- Example: `docker.io/lnzap/lnd@sha256:abc123...` not `lnzap/lnd:latest`
- Verify image signatures when available (cosign/notary)