feat(v2): operator-scoped CRUD + stub legacy entry points
Replaces v1's super-only single-config CRUD with the v2 operator-scoped data
layer that matches the m005 schema:
- Machines: create/get/get_by_npub/list_for_operator/update/delete
- Clients: scoped per (machine, user). Adds list_for_operator (across an
operator's fleet) and list_for_user (LP cross-operator view), plus
get_flow_mode_clients_for_machine for the distribution algorithm.
- Deposits: now carry machine_id and creator_user_id; per-operator listing.
- Settlements: create_settlement_idempotent treats bitspire_event_id as the
uniqueness key, returning the existing row on replay so subscription
re-delivery is safe by construction. mark_settlement_status drives the
pending → processed/partial/refunded/errored lifecycle.
- Commission splits: replace_commission_splits is an atomic per-scope
replace; the SetCommissionSplitsData model already validates legs sum
to 1.0 at the boundary. get_effective_commission_splits handles the
per-machine-override-or-operator-default precedence.
- Payments: leg-typed (dca / super_fee / operator_split / settlement /
autoforward / refund) with helpers for settlement/client/operator scopes.
- Balance summary: sums confirmed deposits minus completed dca legs.
- Telemetry: upsert_beacon_snapshot uses COALESCE so today's sparse
kind-30078 payload doesn't clobber post-#43 fields when they start
arriving. upsert_fleet_snapshot stores raw JSON until lamassu-next#42
fixes the kind-30079 schema.
- Super config: singleton get/update.
Also stubs three legacy entry points so __init__.py imports cleanly while
the rest of P0/P1 is in flight:
- tasks.py: no-op stubs for wait_for_paid_invoices + hourly_transaction_polling.
Real Nostr subscription manager lands in P1.
- views_api.py: a single /api/v1/dca/{...} catch-all returns 503 with a
precise message. v2 endpoints land in P1+.
- views.py: drops the super-only check on the index page (v2 is
operator-installable); platform-fee config moves to a super-only API in P1.
transaction_processor.py is left untouched but is now orphaned (no one
imports it) — gets a full rewrite in P1.
Refs: plan at ~/.claude/plans/snug-gliding-shamir.md
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
013e3d5f6b
commit
937749f149
4 changed files with 798 additions and 969 deletions
18
views.py
18
views.py
|
|
@ -1,8 +1,10 @@
|
|||
# Description: DCA Admin page endpoints.
|
||||
# Satoshi Machine v2 — page route.
|
||||
#
|
||||
# v2 is operator-installable (any LNbits user, not super-only). The super-only
|
||||
# check in v1's index() is gone. Super-only controls (platform fee config)
|
||||
# move to a dedicated API endpoint protected by check_super_user in P1.
|
||||
|
||||
from http import HTTPStatus
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, Request
|
||||
from fastapi import APIRouter, Depends, Request
|
||||
from fastapi.responses import HTMLResponse
|
||||
from lnbits.core.models import User
|
||||
from lnbits.decorators import check_user_exists
|
||||
|
|
@ -15,13 +17,9 @@ def satmachineadmin_renderer():
|
|||
return template_renderer(["satmachineadmin/templates"])
|
||||
|
||||
|
||||
# DCA Admin page - Requires superuser access
|
||||
@satmachineadmin_generic_router.get("/", response_class=HTMLResponse)
|
||||
async def index(req: Request, user: User = Depends(check_user_exists)):
|
||||
if not user.super_user:
|
||||
raise HTTPException(
|
||||
HTTPStatus.FORBIDDEN, "User not authorized. No super user privileges."
|
||||
)
|
||||
return satmachineadmin_renderer().TemplateResponse(
|
||||
"satmachineadmin/index.html", {"request": req, "user": user.json()}
|
||||
"satmachineadmin/index.html",
|
||||
{"request": req, "user": user.json()},
|
||||
)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue