Commit graph

7 commits

Author SHA1 Message Date
4f68ddc40b refactor(machine): drop VITE_LNBITS_HTTP_URL — lnurl now arrives populated from LNbits (#57 gap 2)
Closes gap 2 from coord log 2026-06-01T18:30Z. The LNbits withdraw
extension's nostr-transport RPC now populates `link.lnurl` from
`settings.lnbits_baseurl` (aiolabs/withdraw#1 / commit e9d911e), so the
ATM no longer needs a separate HTTP URL on the wire to compose the
LNURL-withdraw callback itself.

What goes:

- `VITE_LNBITS_HTTP_URL` env var (renderer + Electron main)
- `lnbitsHttpUrl` field on `LightningConfig`, `RuntimeConfig`, and the
  Window mirror in `src/types/electron.d.ts`
- The manual `${lnbitsHttpUrl}/withdraw/api/v1/lnurl/${unique_hash}`
  composition in `generateLnurlWithdraw`
- The `encodeLnurl` bech32 helper in `lightning.ts` (LNbits returns
  bech32-encoded; we just `.toUpperCase()` to match BOLT/LNURL convention)
- `@scure/base` dep from `apps/machine/package.json` (only used by the
  removed helper; clink still uses it directly)
- The `lnbitsHttpUrl` option + `LNBITS_HTTP_URL=…` env var + boot echo
  in `deploy/nixos/bitspire-atm.nix`
- Doc references in CLAUDE.md, README.md, deploy/nixos/README.md,
  docs/architecture-comparison.md, and the lightning-check skill

What stays:

- `link.lnurl` consumption, with an explicit error if LNbits returns
  null (which signals `LNBITS_BASEURL` is unset on the server side —
  better to fail clearly than silently)
- The receiver-side bech32 uppercasing (LNbits returns lowercase per
  the standard library)

Why this is a net win:

- Removes a config-drift surface — if LNbits's external URL moved
  (DNS, port, reverse-proxy rewrite), every ATM in the field would
  stop issuing redeemable LNURL-withdraw QRs until reconfigured.
  Now LNbits derives its own URL from `settings.lnbits_baseurl`,
  one source of truth.
- Removes an extra provisioning step. No more `LNBITS_HTTP_URL=…`
  before running `provision-atm.sh`; the relay + server pubkey suffice.
- Removes the misleading boot echo that triggered the §`18:30Z`
  smoke triage confusion ("LNbits HTTP: <url>" read like ATM-→-LNbits
  connectivity, when it was only ever a URL embedded in customer QRs).

Also adds a `# pragma: allowlist secret` marker above the
`VITE_ATM_PRIVATE_KEY` doc block in `.env.example` so the global
secret scanner stops false-positiving on the documentation prose.

Workspace typecheck + 24/24 apps/machine tests still green.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-01 20:33:28 +02:00
264cc47e0c refactor(deploy): rename system user lamassu → bitspire
System-level half of the lamassu → bitspire rebrand the rest of dev
already did at the path / service / package layers. Touches user/group
declarations, every systemd `User=` block, the udev rules filename, all
chown calls in flake.nix + live.nix, the displayManager autoLogin user,
the trusted-users nix entry, provision-atm.sh's ATM_USER, plus README +
CLAUDE.md doc references.

In-place migration for the Sintra dev unit (which auto-pulls dev at
04:00) lives in `system.activationScripts.bitspire-user-migration` and:
- copies `/home/lamassu/.ssh/authorized_keys` → `/home/bitspire/` once,
  so SSH access survives the rename
- recursively chowns `/var/lib/bitspire` to the new bitspire UID on
  every boot — cheap no-op once done, but covers the case where the
  data dir was written by the now-removed lamassu UID
- leaves `/home/lamassu/` in place as evidence; operator can `rm -rf`
  after confirming bitspire login works

Recovery path if the migration breaks SSH access: root key is still in
configuration.nix:142-144 (padreug@gizmo), so ssh root@<host> works.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-01 19:11:32 +02:00
bac130dbf1 docs: refresh README + CLAUDE.md for LNbits-backend bitSpire on dev
Both top-level docs were stale after the lamassu-next → bitSpire +
Lightning.Pub → LNbits migration shipped on this branch. They still
listed @lamassu/* package scopes, treated Lightning.Pub as the backend,
described cash-in as ndebit/CLINK, and pointed at removed packages.

README.md: rewritten end-to-end. Calls out the branch model (main vs
dev) so contributors don't accidentally affect production ATMs.
Documents the actual cash-out (BOLT11 + subscribe_payments by hash)
and cash-in (LNURL-withdraw + subscribe_payments by tag/link_id) wire
flows. Quick-start uses the dev compose's bundled LNbits with
nostr-transport + the LNbits-internal nostrrelay extension (the relay
endpoint is ws://<host>:5001/nostrrelay/test — no separate strfry
container, this was a pitfall during Sintra provisioning). Disk-image
deployment summary points at deploy/nixos/README for full details.

CLAUDE.md: rewritten to describe dev-branch reality. Lists actual
package names (@bitSpire/*), notes packages/lightning was deleted in
3d, calls out the LightningBackend adapter pattern in services/
lightning.ts, and gives an env-var reference table + a wire-envelope
crib for kind-21000. Sintra-specific hardware notes (UART layout,
initrd modules for the ACPI eMMC controller) bake in everything we
hard-learned during the first flash.

Both docs now include an Acknowledgements / Provenance section that:
  - credits Lamassu Industries AG's open-source lamassu-machine /
    lamassu-server (the v8.1.5 release line) as the prior art the
    HAL drivers and state machine derive from — bitSpire wouldn't
    exist without that foundation
  - explicitly states Lamassu transitioned to a proprietary,
    source-available "Appendix A SLA" on 2024-01-26 with v8.1.6+
    gated behind a paid OSA subscription, and that bitSpire
    incorporates no code from v8.1.6 or later
  - declares bitSpire independent of Lamassu Industries AG
  - in CLAUDE.md specifically: a hard rule that future contributors
    (or future Claude runs) must not pull / port / copy code from
    lamassu-machine at v8.1.6+; only the 8.1.5 tree is in-scope

License clarification: AGPL-3.0 (matches LNbits, which we link
against) — dropped the earlier "matches LNbits + lamassu-machine
pedigree" phrasing since lamassu-machine is no longer under a free
license.

References:
  https://blog.lamassu.is/updates-to-our-lamassu-software-license/
  https://github.com/lamassu/lamassu-machine

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-01 19:08:03 +02:00
219e7e1e4d refactor(rename): branding strings + active-use docs → bitSpire
Final rename commit covering user-facing copy and the docs that
describe current state. The mechanics of the rename are done after
this; the LNbits backend swap (phase 3) is the next concern.

Code branding strings (Lightning invoice descriptions):
  apps/machine/src/services/lightning.ts
  apps/machine/src/stores/atm.ts
  docs/clink-protocol.md  (example code blocks)
    "Lamassu ATM Payment"        → "bitSpire Payment"
    "Lamassu ATM - Cash Out"     → "bitSpire - Cash Out"
    `Lamassu ATM - Buy ${n} sats`→ `bitSpire - Buy ${n} sats`

Top-level docs:
  README.md, CLAUDE.md — title + intro + dir-tree references.
  deploy/nixos/README.md — title + worktree-path commands.
  docs/machine-installation.md — opening line carries the historical
    note ("Lamassu Next" → "bitSpire"). The body still uses
    `/opt/lamassu/` paths and the `lamassu-kiosk` systemd unit
    because the dev branch is moving to NixOS disk-image flash
    (phase 4) — this AppImage-sideload doc represents the legacy
    deploy path. Leaving the LP/lamassu refs in there as part of
    its historical context; a separate doc will describe the
    NixOS path.
  .claude/skills/nostr-check.md — header only.

DELIBERATELY left as "Lamassu Next" (pedagogical / historical):
  - docs/adr/001-hal-architecture.md — frozen ADR; renaming
    distorts the historical decision context.
  - docs/architecture-comparison.md — deliberately contrasts
    "lamassu-server" (prior) with "lamassu-next" (us at the time
    of writing).

NOT done in this commit (deferred to LNbits/clean-up phase):
  - docker/docker-compose.dev.yml container names
    (lamassu-relay, lamassu-bitcoind, etc.) — these belong to the
    LP-bearing dev stack that 3c/3d will significantly reshape.

Verified: pnpm typecheck clean (12/12 cached).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-01 19:08:03 +02:00
Patrick Mulligan
a21865ff20 feat(machine): record failed dispenses and per-cassette tracking
Failed dispenses (sats debited, cash not dispensed) were invisible —
transactions only recorded on 'complete'. Now records on 'dispenseError'
with status ('dispense_error'|'partial'|'complete'), error message, and
per-cassette detail.

Also fixes a bug in both HAL services where dispense results were mapped
by amounts-array index instead of cassette position, causing swapped
denomination counts when cassette order differs from request order.

Schema v3→v4: adds status/error columns to transactions, new
cassette_bills table for per-cassette provisioned/dispensed/rejected.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 17:53:10 -04:00
Patrick Mulligan
c98f126ba7 feat(docker): add dev.sh with auto-funding and ATM app setup
- Add dev.sh script for managing regtest development environment
- Implement cmd_fund to fund ATM app owner via Lightning.Pub API
- Add --fund flag to cmd_up for automatic funding on startup
- Update setup_atm_app to write VITE_APP_ID to machine .env
- Fix Electron IPC to pass appId and extensionApiUrl to renderer
- Restructure repo from nested lamassu-next/ to root

The dev.sh script now supports:
- ./dev.sh up --fund  # Start regtest and auto-fund ATM
- ./dev.sh fund       # Fund existing ATM app
- ./dev.sh status     # Show environment status
- ./dev.sh reset      # Clean restart

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-15 14:19:16 -05:00
Patrick Mulligan
9adee6e37f Initial commit: Lamassu modernization project
- Add lamassu-server, lamassu-machine, lamassu-install as submodules
- Add CLAUDE.md with development guidance
- Add docs/modernization-plan.md with 2026 refactoring roadmap
- Add .gitignore for Node.js/Nix development

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-22 14:19:00 -05:00