Commit graph

31 commits

Author SHA1 Message Date
cadf30b704 chore(release): v1.6.8-aio.4
Some checks failed
lint.yml / chore(release): v1.6.8-aio.4 (push) Failing after 0s
- #68 ticket waves never rendered in the organiser table. The chip built
  its label inline with `LNbits.utils.formatCurrency(...)`, but Vue
  resolves template expressions against the component instance, where the
  `LNbits` global is not in scope. It threw "Cannot read properties of
  undefined (reading 'utils')" and the whole v-for rendered nothing, so
  every event showed an empty wave list however many waves it had.
  Organisers could not see or edit a wave from the LNbits UI at all.

The line came in with the v1.6.8 merge: it is upstream's, and the only
`LNbits.` reference in any template here — display.vue and ticket.vue
have none. `waveSummary` now builds the label in index.js, and trims the
time off wave dates for display.

Frontend only; no Python, no schema, no migration.

Verified in a browser against a two-wave event before tagging: both
chips render with formatted currency and no TypeError.
2026-10-03 21:06:55 +02:00
69c9a4f757 chore(release): v1.6.8-aio.3
Some checks failed
lint.yml / chore(release): v1.6.8-aio.3 (push) Failing after 0s
- #67 honour per-wave fiat when the organiser set an explicit rail list.
  `effective_payment_methods` returned `extra.payment_methods` before
  consulting the wave, so the `wave` argument added for #61 did nothing
  in the common case — the webapp always sets that list. The NIP-52 tag
  advertised `tickets_payment_methods: lightning,fiat` while omitting
  `tickets_allow_fiat`, and the checkout offered a card button that
  `api_ticket_create` then refused. Reported from aio-demo.

Eight lines in `models.py`; no schema change, no migration,
`migrations.py` still byte-identical to upstream v1.6.8.

The organiser-facing symptom is already gone on demo — aiolabs/webapp#179
makes the Card checkbox govern every wave, and re-saving the event
corrected all four. This is the backend half: it stops the published tag
contradicting itself when a wave genuinely cannot take fiat, which the
LNbits admin's per-wave toggles still allow.
2026-10-03 07:51:46 +02:00
fe40d2ab14 chore(release): v1.6.8-aio.2
Some checks failed
lint.yml / chore(release): v1.6.8-aio.2 (push) Failing after 0s
Two wave fixes found while checking whether the webapp had been updated
for v1.6.8.

- #65 keep ticket waves when a client edits an event without them. A
  client that rebuilt the `extra` envelope rather than round-tripping it
  destroyed every wave: the list arrived empty, a single primary wave was
  synthesized from the event-level `amount_tickets`, and a multi-wave
  event silently collapsed into one tier. `promo_codes` had carried the
  same guard since the v1.6.8 merge; `ticket_waves` is the same class of
  organiser state and now carries it too.
- #66 expose `ticket_waves` on public event responses. A buyer cannot
  choose a tier without its id, and nothing public carried one — the
  NIP-52 tags describe the active wave but name no id. Waves move to
  `EventExtraBase`, leaving promo codes as the only organiser-private
  field in `extra`. Buyers can now see upcoming tiers and their prices,
  which is what #61 recorded as the cost of the flat-tag decision.

No schema change; both are model/serialisation only.

Verified against bohm's dev LNbits before tagging: the exact PUT that
collapsed a two-wave event now leaves both intact with the roll-up
unchanged, the public endpoint carries the waves while still hiding
promo codes, and a webapp-shaped edit that writes through to the primary
wave takes effect (139 = 99 + 40) where it was previously discarded.

#66 is a prerequisite for aiolabs/webapp#176, which is merged to dev and
needs this deployed before its wave picker works for anyone but the
organiser.
2026-09-29 09:24:36 +02:00
6bdebe4562 chore(release): v1.6.8-aio.1
Some checks failed
lint.yml / chore(release): v1.6.8-aio.1 (push) Failing after 0s
Rebase onto upstream v1.6.8, so the upstream segment moves and the aio
patch counter resets to 1.

- #63 merge upstream v1.6.8: ticket waves (per-wave price/currency/
  stock/fiat), paginated tickets, the organiser ticket-image template.
  Pricing and inventory now follow the wave the buyer selected rather
  than the primary-wave roll-up; npub checkout and DM delivery kept
  where upstream removed them; `_parse_date` accepts the ISO datetimes
  our closing dates carry.
- #63 drop the SatsPay/watchonly on-chain surface — on-chain will go
  through native LndRest once aiolabs/lnbits#53 lands (#41).
- #63 publish the active wave over Nostr, with `nostr_published_wave_id`
  (fork migration m004) so the reconciliation sweep republishes at wave
  boundaries (#61).
- #64 require a capacity on every ticket wave (#34, #62).

`migrations.py` stays byte-identical to upstream. v1.6.8 adds no
upstream migrations over v1.6.1 — waves live in `extra` JSON — so no
`dbversions` surgery is needed on existing installs; only the fork
namespace advances, `events_fork` 3 -> 4.
2026-09-29 00:04:21 +02:00
ab4175a89a chore(release): v1.6.1-aio.18
Some checks failed
lint.yml / chore(release): v1.6.1-aio.18 (push) Failing after 0s
- #62 `tickets_available` is always published, including zero. Omitting
  it used to mean "unlimited", which nothing else agreed with:
  api_get_event and api_ticket_create both read `amount_tickets < 1` as
  sold out, so a zero-capacity event advertised unlimited tickets on the
  card and returned 410 to every purchase. Three such events were live
  on aio-demo. The admin form no longer offers 0 either.

No schema change. Existing zero-capacity events are not migrated — we
cannot infer whether the organiser meant unlimited or forgot to set a
number — and they will read as sold out once republished. The #55 sweep
will not flag them on its own, so /republish-all is the way to refresh.
2026-09-27 23:12:12 +02:00
68a11bb50e chore(release): v1.6.1-aio.17
Some checks failed
lint.yml / chore(release): v1.6.1-aio.17 (push) Failing after 0s
Ticket availability and publish delivery.

- #58 publishes are confirmed against the relay's NIP-01 `OK` instead of
  the send queue. A publish that never reaches a relay now leaves the row
  flagged for the sweep rather than reporting success and clearing it —
  which had silently reverted a completed repair on cfaun. Verified end
  to end on aio-demo: delivery confirmed, the no-relay failure caught
  with the relay's own diagnostic in the log, and the retry recovering
  once the relay returned.
- #59 `amount_tickets` is the remaining count; `api_ticket_create` no
  longer subtracts `sold` from it. Every event was locking itself as sold
  out at half capacity. 16 of 24 live events on aio-demo were affected,
  3 already refusing sales with stock remaining.

No schema change. Affected events start selling again on upgrade; worth
re-running an availability check per host afterwards.
2026-09-27 22:27:40 +02:00
cac7d16ece chore(release): v1.6.1-aio.16
Some checks failed
lint.yml / chore(release): v1.6.1-aio.16 (push) Failing after 0s
Nostr publish reliability.

- #54 the two paths that skip a NIP-52 publish now log at WARNING
  instead of silently (bare return / debug); publish failures moved to
  ERROR
- #55 `events.nostr_publish_pending` marks a row from before each
  publish attempt until a confirmed success, and a 5-minute sweep
  republishes whatever is still flagged, so drift recovers on its own
  instead of waiting for an operator who knows to run /republish-all
- #55 the NostrClient send loop holds and retries a dequeued req
  (bounded at 3) rather than dropping it

Adds migration m003 (events.nostr_publish_pending). Verified on bohm:
events_fork 1 -> 3, column present, event created and published to a
relay with the flag clearing on success.
2026-09-27 09:27:40 +02:00
7b66588d18 chore(release): v1.6.1-aio.15
Some checks failed
lint.yml / chore(release): v1.6.1-aio.15 (push) Failing after 0s
Since v1.6.1-aio.14: promo codes enforced — active flag, max_uses with
derived used_count, codes hidden from public event records, anonymous
POST /api/v1/promo/validate/{event_id} preview, single basket_totals
pricing path, Stripe metadata.promo_code (#45).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EYwoAkZZmXMMmaBp4WGUBo
2026-09-13 18:55:40 +02:00
4c3b1bca31 chore(release): v1.6.1-aio.14
Some checks failed
lint.yml / chore(release): v1.6.1-aio.14 (push) Failing after 0s
Since v1.6.1-aio.13: "Email sent" column in the admin tickets table (#48).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EYwoAkZZmXMMmaBp4WGUBo
2026-09-13 18:42:39 +02:00
f835766935 feat(admin): event form parity with the webapp (1.6.1-aio.13)
Some checks failed
lint.yml / feat(admin): event form parity with the webapp (1.6.1-aio.13) (pull_request) Failing after 0s
lint.yml / feat(admin): event form parity with the webapp (1.6.1-aio.13) (push) Failing after 0s
The LNbits admin form lagged the webapp's CreateEventDialog:

- Payment methods never rendered. c2d9a96 wired the template to
  `paymentMethodOptions` / `acceptsFiat` but never defined them, so the
  q-option-group got `options=undefined` and the fiat-currency select
  was gated on `undefined`. Rails are now two q-checkboxes; Card is
  disabled with an explanatory tooltip when `g.user.fiat_providers` is
  empty (same rule as the webapp) and names the providers otherwise.
- Location (NIP-52 `location` tag) and Categories (NIP-52 `t` tags,
  same 25-item list as the webapp's category.ts) were missing from the
  form even though the model, CRUD and publisher already carry them.
- Datetimes are stamped with the browser's UTC offset on submit, as the
  webapp does; `_to_unix` treats naive values as UTC, so 18:00 CEST
  entered here went out on Nostr as 18:00 UTC. Table columns render
  "YYYY-MM-DD HH:MM" instead of the raw ISO string.
- Validation: title + start date required, end >= start on the folded
  date+time, fiat currency required when a sat-priced event accepts
  card. Create is enabled once wallet + title + start are set; info,
  closing date, tickets and price were all effectively required before
  because the disable check compared undefined fields to null.
- Labels follow the payment-rails vocabulary: "Unit" -> "Price
  currency", "Fiat checkout currency" -> "Fiat currency"; ticket
  closing date and end date explain their defaults.
- A fiat-priced event mirrors `fiat_currency = currency` on save so the
  payload and the `tickets_fiat_currency` tag stay coherent.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018b1bDExMX7W3a47wcgFUjb
2026-09-10 13:43:53 +02:00
2f8a602bbd feat: attach a self-describing ticket card to the email (1.6.1-aio.10)
Some checks failed
lint.yml / feat: attach a self-describing ticket card to the email (1.6.1-aio.10) (pull_request) Failing after 0s
The v1.6.1-aio.9 mail still scored 8.4/10 on mail-tester: the remaining
deduction was HTML_IMAGE_ONLY (1.8) — an HTML part whose only content of
note is a remote <img>. Remote images are also blocked by default in most
clients until the reader opts in, and a bare QR saved from that mail says
nothing about what it opens.

- New `qr.py` module (QR + logo helpers moved out of views_api) with
  `render_ticket_card`: site title, event name, when/where, the branded
  QR, name on ticket, ticket id and the door instruction, laid out with
  the bundled DejaVu Sans; `format_event_when` gives "Fri 19 Feb 2027,
  16:00 - 20:00"; filenames are `ticket-<event-slug>-<id8>.png`.
- `GET /events/api/v1/ticket-card/{ticket_id}` serves the same PNG
  (anonymous, like the QR endpoint); the email's "Ticket image" link
  now points there.
- The ticket email becomes multipart/mixed: text + HTML alternatives
  (URLs as links, no <img>) plus the card as a PNG attachment, which
  clients show inline at the end of the message and which works offline
  at the door.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EYwoAkZZmXMMmaBp4WGUBo
2026-09-08 16:40:25 +02:00
3a8e0ff591 fix: Date/Message-ID/From-name on ticket emails, richer body (1.6.1-aio.9)
Some checks failed
lint.yml / fix: Date/Message-ID/From-name on ticket emails, richer body (1.6.1-aio.9) (pull_request) Failing after 0s
lint.yml / fix: Date/Message-ID/From-name on ticket emails, richer body (1.6.1-aio.9) (push) Failing after 0s
A tester's ticket email landed in spam. A mail-tester run against demo
scored 8.3/10 with SPF, DKIM and DMARC all passing through the VPS relay,
so the deductions were all in the message: MISSING_DATE (1.4),
HTML_IMAGE_ONLY_04 (0.3), MISSING_MID (0.1) — and Gmail/Outlook weigh a
missing Date/Message-ID as "machine-generated" far more than that.

- `build_ticket_email` sets Date, a Message-ID under the sender domain,
  and a From display name from `lnbits_site_title`.
- The body now carries the event name, dates, location, name on ticket,
  ticket id and the door instruction, so the HTML part is no longer a
  QR with a handful of words.

Upstream candidate: lnbits core `send_email` has the same omissions.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EYwoAkZZmXMMmaBp4WGUBo
2026-09-08 16:19:38 +02:00
a67c6faff3 docs: guest checkout contract, upstream-candidates log; bump 1.6.1-aio.8
Some checks failed
lint.yml / docs: guest checkout contract, upstream-candidates log; bump 1.6.1-aio.8 (pull_request) Failing after 0s
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EYwoAkZZmXMMmaBp4WGUBo
2026-09-06 19:53:05 +02:00
2093e63020 chore: bump config.json version to 1.6.1-aio.7
Some checks failed
lint.yml / chore: bump config.json version to 1.6.1-aio.7 (pull_request) Failing after 0s
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 09:04:02 +02:00
cfc2e38a5e chore: bump config.json version to 1.6.1-aio.6
Some checks failed
lint.yml / chore: bump config.json version to 1.6.1-aio.6 (pull_request) Failing after 0s
Marks the monotonic created_at fix (#26). aio semver stays ahead of the
upstream 1.6.1 tag per fork versioning rules.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 14:13:11 +02:00
1fb96bfe3c chore: bump config.json version to 1.6.1-aio.5
Some checks failed
lint.yml / chore: bump config.json version to 1.6.1-aio.5 (pull_request) Failing after 0s
Releases the door-scanner stats endpoint.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-03 19:48:18 +02:00
66076d6ca7 feat(signer): migrate Nostr publishing off account.prvkey → resolve_for_wallet (#23)
Closes aiolabs/events#23. Pre-cascade prerequisite for aiolabs/lnbits#17
(signer abstraction phase 1), which lands an m002 startup job that
NULLs the legacy `accounts.prvkey` column. After this migration, the
events extension reads no plaintext nsec and works with any
NostrSigner backend (LocalSigner / RemoteBunkerSigner / ClientSideOnlySigner).

## What changed

### nostr_hooks.py — publish_or_delete_nostr_event

Was: pulled `(account.pubkey, account.prvkey)` from the wallet owner,
passed both to `publish_event_to_nostr`. Hard-skipped publish when
`account.prvkey` was None.

Now: calls `await resolve_for_wallet(event.wallet)` (the DRY helper
from aiolabs/lnbits#23 — wallet → account → signer → can_sign-check
in one call, returns None on any soft-fail). Passes the resolved
`NostrSigner` to the publisher. Soft-skip on None (wallet missing,
account unclassified, or ClientSideOnlySigner where the server has
no signing authority) — matching previous "no prvkey" behavior.

### nostr_publisher.py — publish_event_to_nostr

Was: accepted `(account_pubkey, account_prvkey)` and signed via a
local `sign_nostr_event` helper that called `coincurve.PrivateKey
.sign_schnorr` directly on the plaintext nsec.

Now: accepts `signer: NostrSigner`. Builds the unsigned event dict
(`kind`/`created_at`/`tags`/`content`), hands it to
`await signer.sign_event(...)`, reconstructs the local `NostrEvent`
model from the signed dict (`id`/`pubkey`/`sig` fields). The signer
backend (LocalSigner / RemoteBunkerSigner) is transparent.

Removed the `sign_nostr_event` helper entirely — the signer abstraction
handles all signing now.

Dropped the `coincurve` import; no direct crypto in this extension.

## Acceptance

- [x] keypair helper replaced (nostr_hooks no longer touches account.prvkey)
- [x] publish_event_to_nostr accepts NostrSigner instead of (pubkey, prvkey)
- [x] extension-local Schnorr code removed (sign_nostr_event gone)
- [x] re-grep `events/`: zero `account.prvkey` references
- [x] version bumped: 1.6.1-aio.3 → 1.6.1-aio.4

Manual smoke testing + tag + catalog entry follow the migration
landing; will run against the regtest stack with lnbits on
`issue-18-phase-2.3` (which validates both LocalSigner and
RemoteBunkerSigner signing paths end-to-end).

## Cross-references

- aiolabs/events#23 — issue this commit closes
- aiolabs/lnbits#17 — the cascading signer-abstraction PR
- aiolabs/lnbits#23 — the resolve_for_wallet helper this uses
- aiolabs/lnbits#26 — phase 2.3 (sign_event over bunker, validated against
  aiolabs/nsecbunkerd@fb1c239)
- aiolabs/lnbits#21 — umbrella audit identifying 5 affected extensions

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-27 21:55:56 +02:00
37fad05c1f chore: bump config.json version to 1.6.1-aio.3
Some checks failed
lint.yml / chore: bump config.json version to 1.6.1-aio.3 (push) Failing after 0s
2026-05-24 18:56:07 +02:00
27cc8d2f1c chore: rebase onto upstream v1.6.1 + bump to v1.6.1-aio.1
Some checks failed
lint.yml / chore: rebase onto upstream v1.6.1 + bump to v1.6.1-aio.1 (push) Failing after 0s
Rebases the aio fork onto upstream v1.6.1 (4bf867e), pulling in:
- fiat checkout + email/Nostr DM ticket notifications (PR #50)
- currency-conversion fix (v1.5.0)
- custom notification subject/body (v1.6.0)
- resend-email button on the ticket list (PR #51)

Notable merges:
- views_api.api_event_update keeps the explicit-field-list gating from
  the aio.4 security fix, with allow_fiat + fiat_currency added so an
  owner editing a fiat-enabled event keeps the fiat config.
- models.PublicEvent now exposes both upstream's fiat fields and our
  location / categories / status fields.
- migrations.py reverts to byte-identical to upstream v1.6.1 (no aio
  entries); fork schema lives in migrations_fork.py (per aiolabs/lnbits#8).
- Lint reformatted with black + ruff to match upstream style.

Contributors entry adds `padreug` (aio fork maintainer).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-22 09:24:35 +02:00
dni ⚡
4bf867eef0
feat: add resend email button to ticket list (#51)
- resending only possible when ticket is paid.
2026-05-13 11:30:14 +02:00
Tiago Vasconcelos
9e477ac959
feat: make events dynamic (#43)
---------

Co-authored-by: dni <office@dnilabs.com>
2026-05-04 17:01:53 +02:00
dni ⚡
f06bd9a668
chore: prepare release, fix lint and uv warnings (#44)
Some checks failed
/ release (push) Has been cancelled
/ pullrequest (push) Has been cancelled
2026-04-15 17:37:34 +02:00
DoktorShift
1dd6f8b67e
docs: changes to more pages (#42)
* Changes to more pages
* Update description.md

---------

Co-authored-by: dni ⚡ <office@dnilabs.com>
2026-01-28 17:22:09 +01:00
Tiago Vasconcelos
ae827a6545
fix: QR copy button (#38)
Some checks failed
/ release (push) Has been cancelled
/ pullrequest (push) Has been cancelled
* fix QR copy button
* fixup poetry
* rc6 and chore update

---------

Co-authored-by: dni ⚡ <office@dnilabs.com>
2025-09-04 07:10:49 +02:00
dni ⚡
6714dcddc7
feat: update to lnbits 1.0.0 (#36) 2024-10-11 13:52:39 +02:00
benarc
ea3a60ecd4 Added video 2024-05-17 17:39:11 +01:00
Vlad Stan
9c82d9e2df chore: bump min_lnbits_version
Some checks failed
/ release (push) Has been cancelled
/ pullrequest (push) Has been cancelled
2024-05-14 11:37:27 +03:00
benarc
1b1cf72e17 Added extended description 2024-04-30 15:36:05 +01:00
Tiago Vasconcelos
0c371e81df
allow custom path (#17)
Some checks failed
/ release (push) Has been cancelled
/ pullrequest (push) Has been cancelled
* allow custom path

* update to minversion 0.11.0

---------

Co-authored-by: dni ⚡ <office@dnilabs.com>
2023-09-25 15:26:13 +01:00
Tiago Vasconcelos
c8b31d8e3f
[FEAT] add timestamp on register (#15)
* add timestamp on register
2023-08-18 08:17:29 +02:00
Arc
bcde392f41
Add files via upload 2023-02-11 08:06:45 +00:00