Commit graph

4 commits

Author SHA1 Message Date
a059e3f596 refactor: rename extension identity to spirekeeper
Fork of satmachineadmin's v2-bitspire line into its own repo. Renames
both identifiers so this extension is fully independent of the original
satmachineadmin install (which remains in service):

  - extension id   satmachineadmin -> spirekeeper
    (router prefix, static path/static_url_for, module symbols, task
     names, templates dir, config/manifest paths)
  - database name  satoshimachine  -> spirekeeper
    (Database(ext_spirekeeper), all schema-qualified table refs)

Also resets versioning to 0.1.0, sets the display name + manifest to
spirekeeper/aiolabs, and fixes the placeholder pyproject description.
Historical aiolabs/satmachineadmin#N issue references in comments are
left pointing at the original repo where those issues live.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-13 22:30:05 +02:00
d448fab0d2 chore(v2): lint pass — black + ruff auto-fix + mypy regressions (#29 v1.1)
Pre-merge lint hygiene on the PR #30 touched files:

- `black` reformatted 9 files (cassette_transport, crud, models, tasks,
  views_api, nip44, all 3 cassette test files, migrations). Cosmetic:
  line lengths, trailing commas, multi-line argument layout.
- `ruff check --fix` cleared 176 of 202 errors auto-fixed. Mostly
  `UP006` `typing.Optional` → `| None` modernization, `I001` import
  sort order, `UP035` typing-extensions cleanup.
- Two new mypy regressions introduced by the migration commit dcb7de0
  fixed:
  - `crud.py:apply_bootstrap_state` — annotated `existing_first: dict
    | None` on the dedup fetch.
  - `tasks.py:_cassette_consumer_tick` — `# type: ignore[arg-type]` on
    the `nostr_client.relay_manager.add_subscription` call; nostrclient's
    upstream typing declares `list[str]` for filters but the actual
    Nostr protocol takes `list[<filter-dict>]`. The runtime accepts it
    (live smoke at 13:43Z dispatched `nip44_decrypt` cleanly through
    this subscription); the typing mismatch is upstream's.

Remaining lint state, intentionally not addressed in this commit
(all pre-existing baseline, not regressions):
- 8 mypy errors in `calculations.py` + the unchanged-by-this-PR parts
  of `crud.py` — pre-existing on v2-bitspire.
- 26 ruff style warnings: 14 are N805 false-positives on Pydantic
  validators (`cls` first-arg is correct for `@validator`-decorated
  methods); 4 are N818 exception-name-suffix preferences on my new
  exception classes (renaming would touch many call sites; keep
  `OperatorIdentityMissing` / `SignerUnavailable` / `RelayUnavailable`
  / `_NostrclientUnavailable` as-is for clarity); 5 are E501 line-too-
  long on docstrings (the long lines are formatted for clarity);
  1 RUF002 unicode-minus in a docstring.

Tests: 155 passed, 1 pre-existing async-plugin failure unchanged.
Live smoke (both publish + consume directions through the bunker)
unaffected — this is purely a code-style pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-31 15:50:14 +02:00
1cebefcde5 test(v2): rewrite cassette tests for v1.1 position-keyed wire shape (#29 v1.1)
The wire-shape pivot (m007 denomination-keyed → m008 position-keyed)
needs the unit test surface re-written to match:

  test_cassette_configs.py
    - PublishCassettesPayload tests pivot to positions-keyed input.
      Validators reject non-int / non-positive position keys, negative
      denom, negative count. Zero count allowed (empty cassette).
    - NEW: test_accepts_multiple_same_denomination_cassettes — pins the
      v1.1 operational requirement (real machines load 4×$20 for cash-out
      throughput) per coord-log 18:45Z. No denom-unique validator.
    - CassettePayloadRow tests pivot to the new field shape
      (denomination + count, no position).
    - UpsertCassetteConfigData tests cover edit-denomination (the v1.1
      "operator swaps a cartridge during refill" scenario) and edit-count.
      Position no longer in the model.

  test_cassette_state_consumer.py
    - _make_state_event helper builds {"positions": {...}} ciphertext.
    - Happy-path assertion checks p.positions keys + denomination/count
      per row.
    - NEW: test_round_trips_multiple_same_denomination — covers the v1.1
      four-of-the-same case through encrypt → decrypt → parse.
    - All negative paths (tamper, wrong privkey, malformed pubkey,
      missing fields, garbage JSON, wrong shape) carry over with the new
      payload shape.
    - d-tag tests unchanged (position vs denomination isn't on the d-tag).

  test_nip44_v2.py
    - TestBitspireCrossTest temporarily re-skipped at the class level: the
      13:15Z fixture is encoded with the v1 denomination-keyed shape;
      bitspire's posting a v1.1 fixture and commit g will swap +
      unskip.

Total: 148 passed, 3 skipped (bitspire cross-test pending the v1.1
fixture from bitspire), 1 pre-existing async-plugin failure unchanged.

Branch tip is now functionally green (the pre-existing async failure
predates this PR + can't be addressed without a pytest plugin install).
Pending commit g for the cross-test fixture re-wire when bitspire posts.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-30 22:31:08 +02:00
9b8008db1f feat(v2): cassette_configs CRUD + unit tests (#29 v1)
Wire up the cassette_configs storage layer:
  - get_cassette_config / list_cassette_configs_for_machine — reads
  - update_cassette_config — operator UI per-row edit (count + position).
    Refuses to create new rows; the denomination set is hardware-determined
    per #29 row lifecycle.
  - apply_bootstrap_state — consumer-side upsert from an ATM-published
    kind-30078 bitspire-cassettes-state event. Populates both the
    operator-believed columns and the v2 reverse-channel columns
    (state_count, state_at, state_event_id) in one transaction. Returns
    False on relay re-delivery (any existing row's state_event_id matches
    the incoming event_id).
  - _should_apply_bootstrap_state — pure-function dedup gate extracted
    from apply_bootstrap_state so the relay-re-delivery decision is
    unit-testable without a database round-trip.

23 new pure-function/model tests in tests/test_cassette_configs.py
covering the wire-shape validators (denomination key coercion, no-duplicate-
positions, int ranges, wire-dict round-trip) and the dedup-helper logic.
DB-touching CRUD follows the existing project convention (see
test_deposit_currency.py rationale): smoke-tested manually via the dev
container, integration tests deferred.

Total: 98 passed, 1 pre-existing async-plugin failure unchanged.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-30 18:03:52 +02:00