Commit Graph

872 Commits

Author SHA1 Message Date
thgO.O
ec4359ec1c
Merge pull request #226 from r1ckstardev/btcmap-import-rpc-v1
Some checks failed
PluginBuilder Tests / test (push) Has been cancelled
Publish Docker image / Push Docker image to Docker Hub (push) Has been cancelled
BTCMaps v2: add btcmap import-RPC submit path alongside directory submission
2026-06-03 21:39:05 -03:00
r1ckstardev
62d160a29b BTCMaps v2: drop hardcoded Status field on BtcMapResult
Per rollforsats feedback on PR #226 msg 82: the Status field on
BtcMapsBtcMapResult was a hardcoded 'submitted-for-review' constant
that didn't reflect anything the btcmap RPC actually returned.
submit_place's result envelope contains id / origin / external_id;
the queued-for-reviewer-workflow semantics are documented on the
BTC Map side, not signalled per-response. Carrying it on every
response was misleading.
2026-05-27 16:33:16 +00:00
r1ckstardev
2119281141 BTCMaps v2: tighten /apis/btcmaps/v1/submit rate limit to 3/24h per IP
Per CREATOR direction on PR #226. Tightening the existing endpoint-wide
fixed-window from 5/24h to 3/24h per source IP. The BTC Map import-RPC
lane forwards submissions into the upstream reviewer queue (not an
instant publish), and rate-limit is the primary spam control on the
public endpoint.
2026-05-25 17:30:22 +00:00
r1ckstardev
cac72c5682 BTCMaps v2: osm: prefix on payment-rail markers
Per rollforsats msg 76 + Hermes finding #4 on PR #226. payment:onchain
and payment:lightning are OSM-style custom tags, so they follow the
osm:<tag_name> convention btcmap documents for additional tags in
extra_fields. Emit as osm:payment:onchain / osm:payment:lightning.
2026-05-25 16:58:20 +00:00
r1ckstardev
034b272882 BTCMaps v2: status='submitted-for-review' on BtcMap result
Per Hermes finding #5 on PR #226. BTC Map's import RPC routes
submitted places into a reviewer queue rather than instant publish.
Successful submit_place means 'submission accepted for review', not
'place live on the directory map.'

Add a Status field on BtcMapsBtcMapResult defaulting to
'submitted-for-review' so clients reading the response shape get
the workflow semantics by default. Constant value clients can key
off if they want to surface the queued state in UX.
2026-05-25 16:41:46 +00:00
r1ckstardev
90bd954a47 BTCMaps v2: lane-conditional validation + reject GLOBAL country on btcmap lane
Per Hermes review findings #2 and #3 on PR #226.

#2 - Url / Description / Type were required unconditionally. BTC Map
submit_place needs none of those (its required-fields are origin +
external_id + lat + lon + category + name). Wrap the directory-lane
required-field checks in if(request.SubmitToDirectory) so a caller
with SubmitToBtcMap=true + SubmitToDirectory=false doesn't have to
populate unrelated directory metadata.

Name validation stays unconditional - both lanes need it.

#3 - Country=GLOBAL is the directory's pseudonym for online-only /
multi-region merchants; it has no meaning for the btcmap directory
map (every place is physically geocoded). Reject Country=GLOBAL when
SubmitToBtcMap=true so we don't forward osm:addr:country=GLOBAL to
btcmap. Directory-only callers keep the existing GLOBAL semantics.
2026-05-25 16:39:15 +00:00
r1ckstardev
373c1cbd6a BTCMaps v2: drop stale coordination-history comment
Per rollforsats msg 73 on PR #226. The comment narrated decision
history from an earlier review pass that subsequent iterations
partially reverted, so the running narrative is now misleading.
Keep the load-bearing JSON-RPC envelope reference, drop the rest.
2026-05-25 16:21:43 +00:00
r1ckstardev
edd7e8d2ed BTCMaps v2: add osm:addr:country + email + twitter back, gate payment rails behind caller flags
Per rollforsats msg 71 on PR #226. Iterating on extra_fields shape:

- Re-add osm:addr:country mapping (existing Country field, now using the
  granular osm:addr:* prefix in line with the other address fields).
- Re-add twitter mapping, but using the first-class `twitter` URL key
  per btcmap rest/v4/places.md (not contact:twitter). Normalize @handle
  vs URL input shapes.
- Add Email first-class field (`email` key in btcmap doc).
- Replace always-emit payment:onchain + payment:lightning with caller-
  controlled bool flags AcceptsOnchain + AcceptsLightning. Each emits
  the corresponding payment:<rail>=yes marker only when explicitly true.
  Lightning-only or on-chain-only stores can now signal accurately.
2026-05-25 16:07:00 +00:00
r1ckstardev
5faf9ce9c0 BTCMaps v2: extra_fields shape revisions per rollforsats review
Per rollforsats feedback on PR #226: trim the extra_fields surface to
what's directly useful for the btcmap directory map, and add granular
address tags + per-rail payment markers.

Drops:
- contact:twitter / contact:github / contact:onion - these channels
  aren't surfaced on the btcmap directory map; the rollforsats plugin
  side can iterate later if a use case surfaces.
- addr:country - replaced by the granular osm:addr:* fields below.
  Bare "addr:" prefix is not the btcmap-documented convention; their
  doc specifies osm:<tag_name> for OSM-style tags.
- payment:bitcoin=yes - replaced by the per-rail markers below; one
  yes/no is less informative than telling the directory which rails
  the merchant accepts.

Adds:
- HouseNumber, Street, City, Postcode fields on BtcMapsSubmitRequest;
  plugin captures these alongside lat/lon. Forwarded as
  osm:addr:housenumber / osm:addr:street / osm:addr:city /
  osm:addr:postcode per the btcmap rest/v4/places.md osm:<tag_name>
  convention (https://github.com/teambtcmap/btcmap-api/blob/master/docs/rest/v4/places.md).
- payment:onchain=yes + payment:lightning=yes always emitted. BTCPay
  merchants run both rails by default; granular per-rail flags can
  follow if a store-level disable becomes useful.

Keeps: website, description, phone.
2026-05-25 15:43:24 +00:00
r1ckstardev
717f55d2a6 BTCMaps v2: enforce https on BtcMap import endpoint before bearer auth
Per CodeRabbit review on PR #226. A misconfigured
BTCMAPS:BtcMapImportEndpoint over http:// would silently leak the
scoped token to anyone on the network path between plugin-builder
and btcmap. Parse the configured value as an absolute https URI
before building the request, throwing InvalidOperationException
with the offending value if the parse / scheme check fails. The
exception fires before SendAsync, so the token never reaches a
HttpRequestMessage header.

Adds 3 tests: http-rejected, non-absolute-rejected, token-missing
maps to BtcMapTokenMissingException (controller-ladder regression
guard). 40/40 BtcMapsServiceTests passing.
2026-05-25 15:06:27 +00:00
r1ckstardev
3836fe6b38 BTCMaps v2: add btcmap import-RPC submit path alongside directory submission
Adds a second downstream lane to /apis/btcmaps/v1/submit that forwards
the merchant payload to teambtcmap/btcmap-api's submit_place RPC
(merged 2026-05-24 in teambtcmap/btcmap-api#91).

Request schema:

- New fields Lat, Lon, Category, ExternalId on BtcMapsSubmitRequest,
  required iff SubmitToBtcMap=true. Validator enforces lat/lon
  ranges, lowercase-identifier category, and 1-200 char external_id.
  Plugin side (rollforsats/BTCPayServerPlugins) composes external_id
  as hostname:storeId so the namespace stays unique per BTCPay
  instance.
- New SubmitToDirectory + SubmitToBtcMap routing flags. The
  directory flag defaults true to preserve existing callers; btcmap
  defaults false so new callers must opt in.
- New Phone field forwarded as OSM Key:phone in extra_fields.

Service layer:

- BtcMapsService.SubmitToBtcMapAsync POSTs a JSON-RPC 2.0 envelope
  ({jsonrpc, method, params, id}) to BTCMAPS:BtcMapImportEndpoint
  (default https://api.btcmap.org/rpc) with method=submit_place,
  origin=btcpayserver, and the merchant payload mapped to the
  documented param shape. Bearer auth from BTCMAPS:BtcMapImportToken.
- Optional fields (website, description, twitter, github, onion,
  phone, country) ride along in extra_fields using OSM tag keys
  (contact:twitter, addr:country, etc.) plus the implicit
  payment:bitcoin=yes marker.
- New BtcMapTokenMissingException parallels the existing
  DirectoryTokenMissingException so the controller can return 503
  with a distinct error code when ops haven't provisioned the
  scoped token yet.

Controller:

- /apis/btcmaps/v1/submit branches on SubmitToDirectory +
  SubmitToBtcMap. At least one must be true (rejected 400 otherwise).
- Each lane has its own exception ladder symmetric to the existing
  directory path: token-missing 503 (directory-not-configured /
  btcmap-not-configured), caller-cancel rethrow, upstream-timeout
  504, generic-failure 502 - error codes namespaced by lane so ops
  can tell them apart.

HttpClient registration:

- New HttpClientNames.BtcMap named client registered with 15s
  per-call timeout and JSON Accept header, matching the
  BtcMapsDirectory budget for bounded worst-case behavior.

Tests:

- 12 new validation tests in BtcMapsServiceTests covering the
  SubmitToBtcMap=true required-field paths (Lat / Lon / Category /
  ExternalId; range checks; lowercase-identifier policy; overlong
  external_id) plus the default-false directory-only-still-works
  baseline. 37/37 BtcMapsServiceTests passing.
2026-05-25 14:45:46 +00:00
r1ckstardev
d34405970b Pre-stage: Phone field on submit request + BtcMap http client name
Invariant scaffolding for the btcmap import-RPC integration. Both
changes are additive (Phone is optional, BtcMap constant unreferenced
until impl). Build clean.

Pending coordination Qs from rollforsats (lat/lon source, category
mapping, external_id namespace) before service + controller wiring.
2026-05-24 16:59:59 +00:00
thgO.O
8ffea888af
Merge pull request #222 from btcpayserver/ft/request_listing_flow
Some checks failed
PluginBuilder Tests / test (push) Has been cancelled
Improve plugin listing request flow
2026-05-18 11:02:33 -03:00
thgO.O
19d6c58325
fix: mark request listing nav active 2026-05-18 00:31:18 -03:00
thgO.O
474264419a
chore: remove reviewer feedback leftovers 2026-05-18 00:30:59 -03:00
thgO.O
3d4068aa43
fix: keep listing rejection pending-only 2026-05-18 00:30:26 -03:00
thgO.O
ad5bb7bdc3
Merge pull request #224 from btcpayserver/btcmaps-v1-directory-only
Some checks failed
PluginBuilder Tests / test (push) Has been cancelled
Publish Docker image / Push Docker image to Docker Hub (push) Has been cancelled
2026-05-14 11:46:25 -03:00
Chukwuleta Tobechi
0dea08d032 remove reviewer_feedback 2026-05-14 11:59:58 +01:00
Chukwuleta Tobechi
61218fa8bb fix code rabbit suggestion 2026-05-14 11:42:35 +01:00
Chukwuleta Tobechi
21c2a93fdd revert changes 2026-05-14 11:21:20 +01:00
r1ckstardev
170d56d6d8 btcmaps v1: timeout vs caller-cancel split + canonical-case type/subType on write
Addresses thgO-O review id 4274558448 (PR #224) items #2 and #3.

#2 OperationCanceledException vs HttpClient.Timeout: the prior
catch-when filter excluded OCE wholesale to avoid swallowing client
disconnects, but HttpClient.Timeout surfaces as TaskCanceledException
(inherits from OCE) so an upstream GitHub timeout slipped through and
fell out as a 500 instead of the intended 502. Now split into three
arms: caller-cancel rethrows (info-log + drop the connection),
upstream-timeout returns 504 with discriminant directory-upstream-
timeout, anything else still 502 directory-upstream-failed.

#3 type/subType case normalization on write: ValidTypes +
ValidMerchantSubTypes match OrdinalIgnoreCase at validation, but the
write at BuildMerchantEntry preserved the user-submitted casing. A
submission of "Merchants" / "Books" would pass validation and land
non-canonical in merchants.json. Normalize to ToLowerInvariant on
write so the file stays in the lowercase convention. Country is
already validated against a case-sensitive Ordinal set so the
validator rejects non-uppercase before reaching the writer; no write-
path change needed there.
2026-05-13 12:42:50 +00:00
Chukwuleta Tobechi
5c29872ca4 resolve test failure 2026-05-11 21:33:38 +01:00
Chukwuleta Tobechi
66d9d5e172 Remove feedback and move request listing to side nav 2026-05-11 21:12:01 +01:00
r1ckstardev
b84538f2c2 btcmaps v1: IHttpClientFactory + markdown-safe PR body + idempotent branch + ISO whitelist
Addresses post-#224 review feedback from @rollforsats + CodeRabbit:

- IHttpClientFactory + named HttpClientNames.BtcMapsDirectory client
  replaces per-request `new HttpClient()`. 15s per-call timeout caps the
  ~5-7 GitHub round-trips at a bounded worst case instead of the default
  100s x N. Bearer token stays per-request (the BTCMAPS token is distinct
  from the global PluginBuilder GitHub token; must not leak into the
  singleton handler).
- Markdown injection guard on the PR body. User fields (Name, Type,
  SubType, Country, Twitter, GitHub) are wrapped in inline code spans
  with backtick-escape so a doctored merchant name can't render as a
  clickable link in the maintainer-facing PR description. Description
  goes inside a fenced code block. URL is rendered as <bare-url> autolink
  so the maintainer always sees the actual destination.
- Idempotent branch name: SHA-1-derived suffix from the normalized URL
  replaces the random GUID. Two concurrent same-URL submissions now
  collide on `git/refs` create instead of racing through preflight and
  opening duplicate PRs. The 422 "Reference already exists" surface is
  caught and mapped to the open-PR lookup or `branch-exists-no-open-pr`.
- NormalizeUrl lowercases scheme + host only and preserves path + query
  case verbatim. Lowercasing the whole URL falsely de-duplicates
  case-sensitive paths.
- Country code validation moves to an actual ISO 3166-1 alpha-2 set
  built from CultureInfo at startup. Replaces the
  `length==2 && IsUpper` shape that accepted reserved/unassigned codes
  like ZZ.
- Missing BTCMAPS:DirectoryGithubToken throws
  DirectoryTokenMissingException at the service layer; controller maps
  it to 503 with `directory-not-configured`. Previously surfaced as a
  200 OK with `Skipped` which a client could misread as "accepted".

5 new tests:
- Validate_RejectsNonAssignedTwoLetterCountry (ZZ)
- NormalizeUrl_PreservesPathCase
- NormalizeUrl_PreservesQueryCase
- BuildBranchName_DeterministicForSameUrl
- BuildBranchName_DiffersForDifferentUrls

25/25 BtcMapsServiceTests pass on Release build.
2026-05-11 16:32:04 +00:00
r1ckstardev
33148aafcd BTCMaps v1: directory-only submission API
Supersedes PR #211. Per-store OSM OAuth moves to the BTC Map
plugin side (rollforsats/BTCPayServerPlugins PR #5); the
plugin-builder side keeps only the directory PR submission.

Drops vs PR #211:
- TagOnOsmAsync / UnlistFromOsmAsync service paths and all
  OSM XML + changeset infrastructure (~430 lines)
- TagOnOsm / UnlistFromOsm / OsmNodeId / OsmNodeType /
  Latitude / Longitude / OsmCategory / AcceptsLightning
  request fields
- BtcMapsOsmResult response shape + Address sub-model
- OSM-specific validators

Keeps:
- POST /apis/btcmaps/v1/submit opens a PR against
  btcpayserver/directory.btcpayserver.org's merchants.json
- GET /apis/btcmaps/v1/ping
- Rate limit: 5 submissions / 24h per source IP
- Validation for name / url / description / type / subType /
  country / twitter / github / onionUrl

Build clean (Release); 20 unit tests cover validation, slug,
URL normalization.
2026-05-10 18:52:16 +00:00
thgO.O
4480aa01d4
Merge pull request #223 from ak91456/master
Some checks failed
PluginBuilder Tests / test (push) Has been cancelled
add Unlisted badge to plugin cards in public directory search results
2026-05-09 01:07:30 -03:00
thgO.O
4616f040dd
refactor: use visibility enum for unlisted check 2026-05-09 00:47:56 -03:00
thgO.O
1901893d69
style: refine unlisted badge placement 2026-05-09 00:28:35 -03:00
Khushvendra Singh
e0c8972366
Align antiforgery error details flow with BTCPay UI handling (#196) (#197)
* Align antiforgery error details flow with BTCPay UI handling (#196)

- add UIControllerAntiforgeryTokenAttribute equivalent and register it globally in MVC\n- populate UIErrorController.ErrorDetailsKey on antiforgery validation failures\n- keep UI-only/non-safe-method antiforgery behavior aligned with BTCPay policy semantics\n- add focused unit tests for validation, existing failure enrichment, GET bypass, API bypass, and IgnoreAntiforgeryToken bypass\n- add integration-style error page test to verify generic UI error view renders CSRF details

* Align antiforgery policy precedence for UI error handling

* Fix antiforgery error details and exempt NIP-07 verify endpoint

* Preserve detailed antiforgery error messages

* Keep antiforgery PR focused

* fix: keep antiforgery details generic

* test: focus antiforgery coverage

---------

Co-authored-by: thgO.O <thgo.o.btc@proton.me>
2026-05-08 18:40:12 -03:00
Psycological
d3af9746b8 add Unlisted badge to plugin cards in public directory search results 2026-05-08 08:10:39 +05:30
Chukwuleta Tobechi
0750690a44 Include tests 2026-05-06 16:48:14 +01:00
Chukwuleta Tobechi
85a8581e06 Improve plugin listing request flow 2026-05-06 15:47:46 +01:00
thgO.O
cf99e25872
Merge pull request #214 from makeentosch/feature/api-validation
Some checks failed
PluginBuilder Tests / test (push) Has been cancelled
Api validation implemented
2026-05-04 18:01:08 -03:00
thgO.O
68058ed408
test: assert api build validation does not create build 2026-05-04 17:22:31 -03:00
makeentosch
53472297c1 fix: tests 2026-05-04 21:18:42 +03:00
Chukwuleta Tobechi
05011e0fc5
Merge pull request #219 from btcpayserver/fx/request_listing_revamp
Some checks are pending
PluginBuilder Tests / test (push) Waiting to run
request listing view update
2026-05-03 21:42:09 +01:00
Chukwuleta Tobechi
95f67b3fda resolve code rabbit suggeston 2026-05-03 21:27:47 +01:00
Chukwuleta Tobechi
4582d96b3d request listing view update 2026-05-03 21:09:03 +01:00
makeentosch
ee45a5464c tests implementation 2026-05-03 21:20:07 +03:00
Chukwuleta Tobechi
8c42cf7d70
Merge pull request #206 from SusanGithaigaN/versions
Some checks failed
PluginBuilder Tests / test (push) Has been cancelled
add select plugin version option
2026-05-01 18:46:48 +01:00
Chukwuleta Tobechi
7518da1cc6 retest 2026-05-01 18:31:16 +01:00
Chukwuleta Tobechi
fd49a37c63 resolve test failure 2026-05-01 18:12:36 +01:00
Chukwuleta Tobechi
ac1dc009cd asome minor fixes 2026-05-01 17:40:07 +01:00
Chukwuleta Tobechi
3752a94d6c
Merge pull request #212 from btcpayserver/fix/local-download-loopback
Some checks are pending
PluginBuilder Tests / test (push) Waiting to run
Handle local loopback plugin downloads
2026-04-29 20:15:46 +01:00
makeentosch
5ee5f70c6d api validation implemented 2026-04-28 20:06:28 +03:00
thgO.O
04a64d9178
Handle local loopback plugin downloads
Add an explicit local artifact download proxy flag for development and tests.

Keep the public download endpoint as a redirect while routing enabled loopback artifacts through the internal proxy.
2026-04-26 12:45:37 -03:00
susan githaiga
650f74781d add select plugin version option 2026-04-22 18:11:02 +03:00
Chukwuleta Tobechi
645f28c7d8
Merge pull request #209 from itsneruta/fix/logo-dark-mode-208
Some checks failed
PluginBuilder Tests / test (push) Has been cancelled
Publish Docker image / Push Docker image to Docker Hub (push) Has been cancelled
Fix "Review markup logo not visible on dark mode"
2026-04-21 21:18:04 +01:00
Chukwuleta Tobechi
fa9e2673d9
Merge pull request #207 from btcpayserver/ft/remove_logo_on_Create_plugin
clean up create plugin page
2026-04-21 21:00:46 +01:00
thgO.O
02df725394
Merge pull request #210 from btcpayserver/fix/flaky-rate-limit-test
Some checks are pending
PluginBuilder Tests / test (push) Waiting to run
Fix flaky rate limit window reset test
2026-04-21 15:12:45 -03:00