{"name": "geodb.io", "package_name": "geodb", "version": "2.22.8", "experimental": false, "qgis_min": "3.0.0", "qgis_max": "4.99.0", "downloads": 20, "uploaded_by": "geodb", "upload_datetime": "2026-06-30T14:41:23.849382", "changelog": "2.22.8 - Plan samples using your own names from a layer field\n- When pushing a point layer as planned samples, you can now tick\n\"Use a layer field for the sample name\" and pick an attribute\n(e.g. your own \"AK26-1001S\" IDs). Those become the sample names\nshown on the web dashboard and the mobile app map / collect page.\n- Off by default - sequence numbers are still generated for\nnavigation, and names stay blank for the field crew to scan as\nbefore. The chosen field is checked up front: blanks, duplicates\nand over-50-character values are flagged before anything is pushed.\n2.22.7 - Claim map title block + grid polish\n- Field and filing map title blocks: the company name and the map\ntype/name line below it (e.g. \"BMX Lode Claims - Field Map\") now\nauto-fit to a single line. Long names shrink just enough to stay\nlegible and never wrap to a second line.\n- The author line populates from the signed-in geoDB user's name\n(e.g. \"Elizabeth White\") instead of a fixed placeholder.\n- Coordinate grid: the eastern (right-side) labels now sit outside\nthe map in the page margin instead of inside the map frame.\n2.22.6 - SQL identifier hardening\n- Queries that must name a table chosen at runtime (the\nformat-specific metadata table, table drops) no longer assemble SQL\nfrom the table name. The metadata read uses a ready-made literal\nquery per format; the remaining identifier sites validate the name\nas a bare SQL identifier (shared quote_identifier helper) before\nuse, so a malformed name raises instead of reaching the database.\nClears the string-built-query pattern flagged by security scanners.\nNo behavior change for normal use.\n2.22.4 - Claim numbering fix on rotated blocks\n- \"Number & Rename Claims\" could number claims right-to-left / out of\norder when the claim block was rotated even slightly off north. Two\ncauses: the numbering UI never passed the API client, so it always\nused the local fallback; and that fallback (plus the server path it\nshould have used) sorted strictly by northing-then-easting, which\ninterleaves rows when a row's claims don't share an exact northing.\nNumbering now bands claims into rows first, then orders each row\nwest-to-east \u2014 top-to-bottom, left-to-right book order \u2014 matching\nhow grid generation already numbers. Serpentine ordering uses the\nsame row banding so the two never disagree.\n- Security: HTTP requests now go through a scheme-restricted opener (http/https only) for defense in depth.\n2.22.0 - Dark-mode compliance for QGIS 4\n- The plugin's UI hardcoded a light-theme color palette, so on\nQGIS 4's dark theme some text was low-contrast or invisible (most\nvisibly the login form, where input text rendered white-on-white).\nAll widget styling now flows through one palette-aware token layer\n(utils/theme.py) that detects light vs dark and resolves each color\naccordingly. Light mode is unchanged; dark mode is readable.\n- Semantic data colors (commodity/mineral swatches, map-feature and\nclaim-type fills, range-category colors) are intentionally\npreserved across both themes.\n2.21.2 - QGIS 4 (Qt6) Storage dialog crash fix\n- Configuring storage / pulling data crashed under QGIS 4 because\nQStandardPaths.DocumentsLocation and .TempLocation were still\nreferenced in their old unscoped form, which PyQt6 removed. These\nnow resolve through the existing Qt5/Qt6 compatibility shim.\n2.21.1 - QGIS 4 (Qt6) load-crash fix\n- The main dialog crashed on open under QGIS 4 because a few Qt\nenums were still referenced in their old unscoped form\n(QFrame.HLine, QFont.Bold, QSizePolicy.*), which PyQt6 removed.\nThese now resolve through the existing Qt5/Qt6 compatibility\nshim, so the plugin loads on QGIS 4 as well as 3.\n2.21.0 - Map Capture: resolution control + fix CRS-dependent distortion\n- New \"Resolution\" selector in the Project Files > Map Capture tab\n(Screen / High 2048 / Very high 4096 / Maximum 8192 px) with a\nlive estimated output size (W x H px and approx MB) that updates\nwith the current view and selection. Higher resolutions give\ncrisper web tiles; the longest edge is the target and the other\nedge is derived from the Web-Mercator extent so aspect is exact.\n- Fix: captured rasters were distorted when the project CRS was\nWGS84 (or a Web-Mercator alias) and undistorted only in UTM. The\nre-render into Web Mercator reused the native canvas pixel\ndimensions, whose aspect ratio differs from the Web-Mercator\nextent (Mercator stretches latitude by sec(phi)), so QGIS\nre-fit the extent and the reported bounds no longer matched the\nimage. The server's affine georeferencing then stretched it.\nEvery capture now renders through one path: reproject to\nEPSG:3857, size the image to the 3857 extent's aspect ratio, and\nreport the actual rendered extent as bounds. Correct at any\nproject CRS and latitude.\n2.20.0 - Stream Alaska state-land polygons from geodb.io\n- New \"Show AK State Lands (Streaming)\" toggle under Basemaps,\nalongside the existing Federal Lands toggle. Reuses the same\n/services/api/federal-lands/ endpoint with\nownership=state&state=AK, sourced from AK DNR's\nOwnership_StateLandAll FeatureServer (~22k polygons\nstatewide). Same QClaims access gate as federal lands.\n- Important for MTRSC siting: AK DNR's Sept-2022 fact sheet\nrequires witness posts on adjacent state land when a section\ncorner falls on private overlap. Surfacing the overlay live\nin QGIS lets the operator see those alternative monument\nsites at planning time.\n- Style: pale gold (#F5E6A1) single-category fill \u2014 matches\nthe staff PLSS preview map's state-land overlay and the\nMTRSC filing-map renderer's `state` category.\n2.19.7 - Drop ID/NM LM-typed stakes from Step-7 push (CP-2026-0059 final)\n- Idaho Code 47-602 and NMSA 69-3-1 require the Location Monument\nto be at a CORNER. Those states have no separate Location\nMonument stake \u2014 the LM is one of the four WP-typed corner\nstakes, identified via LandHolding.lm_corner. Pushing a\nstake_type='LM' for an ID/NM claim creates a stake at a\nregulatorily-invalid (non-corner) position; the resulting\nlocation notice cannot be filed.\n- Server stopped emitting these for ID/NM in production\n2026-05-07 (offset_lm waypoint removed, monument-overrides at\nnon-corner positions rejected). API serializer now rejects\ninbound LM stakes linked to ID/NM LandHoldings as a backstop.\n- This release adds the matching client-side filter: claims\nmanager's push_to_server drops 'discovery'-typed waypoints\nwhose claim is in ID/NM before they're formatted as stakes.\nStops the per-stake 400 chatter when an old QGIS project still\nhas a stale Monuments layer from a pre-2026-05-07 run; user\nsees a clean push instead. Filter only triggers when EVERY\nlinked claim is ID/NM \u2014 shared waypoints with at least one\nnon-ID/NM claim still go through (server validates per-link).\n- No behavior change for non-ID/NM states: NV/CA/AZ/WY/MT/CO/OR/\nWA/UT/AK/SD continue to push their discovery monuments\nnormally. Auto-LM placement for those states is unchanged.\n2.19.6 - Fix v2.19.5 reading State attribute from the wrong layer\n- v2.19.5's per-claim state lookup used `state.claims_layer` to read\nthe State attribute. That property resolves to the Initial Layout\npolygon layer (from Step 2), NOT the Lode Claims layer \u2014 Initial\nLayout has no State attribute, so the lookup always returned None,\nand `None in {ID, NM}` was False. Filter never fired. Every claim\nin the Monuments layer was sent through as an override regardless\nof state, and the server obediently re-stamped manual_override=True\non the same 155 RC claims (visible in pod logs as \"Manual LM\noverride applied \u2014 using ...\")\n- Fix: build a per-claim {name: state} lookup from the best\navailable source. Prefer state.processed_claims (in-memory dicts\nfrom the most recent server response \u2014 has 'state' per claim);\nfall back to scanning the project for a layer whose name starts\nwith \"Lode Claims\" and reading its State attribute. State has no\ntracked layer id for the Lode Claims layer, so this name-based\nsearch is the only reliable path\n2.19.5 - Skip ID/NM claims in monument_overrides capture\n- The plugin's read_monument_overrides_from_state reads ALL features\nfrom the QGIS Monuments layer and sends them to the server as\nuser-moved overrides (\"preserve these positions across regen\").\nFor ID and NM that flow has no legal use \u2014 those states require\nthe LM at a corner. Sending an override for an ID/NM claim made\nthe server stamp manual_override=True and re-emit the off-corner\nLM the v2.19.4 layer-clear was supposed to make impossible\n- Created a feedback loop on Joshua's Rock Creek RC re-walk:\nstale Monuments features \u2192 \"overrides\" pushed \u2192 server replays \u2192\nfresh-but-identical Monuments rendered \u2192 still 155 LMs\n- Fix: skip claims whose state is ID/NM in the override capture.\nState is read from the Lode Claims layer's `State` attribute\n(already populated by claims_layer_generator). Non-ID/NM states\n(NV/CA/AZ/WY/etc.) keep the override-preservation behavior\nunchanged\n2.19.4 - Always clear stale Monuments / Sideline / Endline layers on regen\n- The plugin's claims_layer_generator only created the Monuments,\nSideline Monuments, and Endline Monuments layers when the server\nresponse had non-empty data for them. After 2026-05-06's removal\nof the regulatorily-invalid Phase 3 slide-from-corner code, the\nserver correctly stopped emitting discovery monuments for ID/NM\nclaims. But the plugin's \"remove existing layers before regen\"\npass only matched layer names that were ALSO in the new response,\nso the old Monuments layer's 155 stale features (from yesterday's\nPhase-3 run) persisted in QGIS memory across re-walks\n- Step 6's _read_monument_positions_from_layers then read the stale\nfeatures and stamped them into state.processed_claims; the Step 7\npush wrote `discovery_monument` back into qclaims_data on 155\nLandHolding rows (Rock Creek CP-2026-0059) even though the new\nserver algorithm had decided not to place any. The pod-side\n[CLAIM_STAKE_LINKING] log lines reading \"discovery=yes\" for ID\nclaims were the visible signal\n- Fix: _remove_existing_layers now always includes the optional\nstate-dependent layers (Monuments / Sideline / Endline) in its\nremoval set, regardless of whether the new response contains\nentries for them. Missing entry in the new response now correctly\ntranslates to \"layer absent in project,\" not \"layer left as it\nwas last time.\" Side-effect cleanup of the Step 6 read path is\nimplicit: no layer means no features means no monument data\nmerged into the push.\n2.19.3 - Fix v2.19.2 rehydrate building invalid LandHolding geometry\n- Rebuilt corners only carried easting/northing (UTM), no lat/lon.\nclaims_manager._format_landholding falls back to building GeoJSON\nfrom `[c.get('lon'), c.get('lat')]` when no `geometry` field is\nset on the claim \u2014 but those keys were missing, so it shipped\n[[None, None], ...] to the server. OGR rejected all 711 LandHolding\nrows with \"Invalid geometry pointer returned from\nOGR_G_CreateGeometryFromJson\".\n- Fix: rehydrate now transforms each polygon ring vertex through a\nQgsCoordinateTransform from the layer's source CRS to EPSG:4326,\nstores both UTM (easting/northing) and WGS84 (lat/lon) on every\ncorner, and constructs `rotated_geometry` (WGS84 GeoJSON) and\n`rotated_geometry_utm` (UTM GeoJSON) directly so the format\nfunction doesn't take the fallback path at all.\n2.19.2 - Fix v2.19.1 rehydrate matching the wrong polygon layer\n- rehydrate_from_layers used substring \"Lode Claims\" matching, which\nalso matched the Initial Layout layer because its display name\n(\"Initial Layout [<prefix> Lode Claims]\") repeats the same suffix.\nOn RC-style multi-block projects the matcher picked Initial Layout\nfirst, then skipped every feature for missing fields, leaving\nprocessed_claims at zero and the buttons greyed.\n- Switched to startswith(\"Lode Claims\") so only the actual lode\nclaims layer matches.\n2.19.1 - Auto-rehydrate processed claims/waypoints after plugin reload\n- Plugin reloads (from upgrades) and QGIS restarts wiped the\nin-memory processed_claims and processed_waypoints lists, leaving\nthe wizard auto-resumed at Step 7 but with greyed-out Push and\nGenerate Maps buttons. The data was always available in the\nproject's QGIS layers (Lode Claims, Waypoints, Monuments,\nEndline/Sideline) \u2014 there was just no path to read it back into\nstate without forcing a server re-process\n- New ClaimsWizardState.rehydrate_from_layers() reconstructs both\nlists by walking the existing layers. Called automatically:\n(a) at the end of load_from_qgis_project when completed_steps\nindicates Step 6 has been finished, and\n(b) defensively on Step 6 and Step 7 on_enter when the in-memory\nlist is empty\n- Server-side data is authoritative for any field the rehydrate\npath can't reconstruct (PLSS, deadlines, calculated_acreage,\nstate_requirements_snapshot). The bulk-upsert merges qclaims_data,\nso re-pushing rehydrated claims preserves those server-side values\n- Same idempotent push semantics: re-pushing rehydrated claims is\na no-op against natural-key matched rows\n2.19.0 - Async push, \"Cluster LMs\" option, ID/NM placement fixes\n- Step 7 \"Push & Upload to Server\" now uses the async/poll pattern\nshipped in v2.16-v2.17 for the rest of the long claim-flow calls.\nFor 700+ claim blocks the previous synchronous bulk-upsert pair\n(ClaimStake bulk + LandHolding bulk) tripped Cloudflare's ~100s\norigin-read timeout and the request died at the proxy even though\nthe server was happily processing it\n- New consolidated server endpoint `/api/v2/claims/push-to-server/`\ncombines ClaimStake bulk + LandHolding bulk + document linking\ninto a single async job; progress dialog reports stage\n(pushing_stakes \u2192 pushing_landholdings \u2192 linking_documents \u2192\nfinalizing) with live percentage fed by per-record progress from\nthe server's bulk-upsert mixin\n- Document linking (previously a follow-up call after the push)\nis now folded into the same job \u2014 saves a round-trip and means\nthe success path is one HTTP request from the plugin's POV\n- Step 4 \"LM Corner\" dropdown gains a \"Cluster LMs (smart, ID/NM)\"\noption. When chosen, the server runs the shared-corner clustering\nalgorithm: 4-claim interior intersections cluster all 4 LMs at one\nshared corner so the crew surveys one point instead of four\nscattered ones. Prefers shared corners on public land; if no\ncorner is on public land, slides along an edge to the nearest\npublic-land position\n- Behavior change for ID/NM: explicit corner picks (1-4) are now\nhonored literally \u2014 the server no longer silently overrides the\nuser's choice with the algorithm. Cluster behavior is opt-in via\nthe new dropdown entry. (This was the 2026-05-05 phase-2 work\nthat wasn't actually firing the way users could see; it now does)\n- Backwards compatible: against an older server without the\nconsolidated push endpoint, the plugin transparently falls back\nto the legacy two-call path\n2.18.0 - Sticky monument overrides preserve user-moved LM positions\n- When the user drags a discovery monument in Step 5 (Adjust) and then\ntriggers a server-side regen \u2014 full preview rebuild OR LM-corner\nrotation \u2014 the moved positions are now read from the live monument\nlayer and sent up as monument_overrides in the request body. Server\nhonors the override (lm-placement-improvements server-side change,\n2026-05-05) and the user's move survives the rerun\n- Without this hand-off the algorithm recomputed a fresh LM and the\nuser's positioning was silently clobbered when the new layers were\nwritten back; this was the standing complaint that motivated the\nserver-side override-passthrough work\n- New shared helper processors/monument_overrides.py reads the\nmonuments layer, transforms UTM \u2192 WGS84 via the claims-layer CRS,\nand emits the {claim_name: {lat, lon, easting, northing}} dict\nshape the server's processing_options['monument_overrides']\ncontract expects\n- First-time generation (no monuments layer yet) sends an empty dict\n\u2192 no-op on the server, identical to pre-2.18 behavior\n2.17.0 - Async + progress for the rest of the long claim-flow endpoints\n- Async polling helper (X-Async-Capable: 1 + 202 + poll + progress dialog) is\nnow shared across the plugin: APIClient.post_async_capable handles the full\nhandshake so any caller \u2014 manager method or processor \u2014 can opt into async\nwith one line\n- Applied to: Process Claims (Step 6), Align Corners (Step 6 finalize), Validate\nClaim Grid (Step 6), and Generate Witness Points (Step 7). All now show the\nprogress dialog (stage / current claim / % bar / elapsed / Cancel) and survive\n1000-claim blocks comfortably\n- Pairs with server-side ~3x speed-up of the underlying processor so the typical\n1000-claim run finishes in ~110s server-side\n- Deferred (next release): Generate Documents, Generate Package Maps, and bulk\nClaimStake/LandHolding push \u2014 these need a different shape (chunking with\ncleanup_orphans semantics)\n2.16.1 - Live progress dialog for async claim operations\n- Progress dialog (stage, current claim name, % complete, elapsed time, Cancel button)\nnow appears for the duration of Generate Preview Layers (Step 5) and Update LM\nCorner \u2014 fed by per-claim progress fields the server reports in each poll response,\nso the user sees real progress instead of a frozen wizard\n- Cancel button cleanly abandons polling on the client; the server worker finishes\non its own and the result simply expires from cache (nothing to roll back)\n- Pairs with a server-side ~3x speed-up of the underlying processor (federal-lands\nunion pre-fetch always runs now), so a 714-claim block typically completes in\n~70-80s instead of ~190s \u2014 comfortably within the proxy timeout window\n2.16.0 - Async preview-layer generation for large claim blocks (700+ claims)\n- Plugin now opts into the server's async path on POST .../preview-layers/ and\n.../update-lm-corner-layers/ via X-Async-Capable header \u2014 the server kicks the\nheavy compute onto a background worker, returns 202 + a session id, and the\nplugin polls a status endpoint until the result is ready\n- Side-steps the ~100s Cloudflare origin-read timeout that was returning 502\nBad Gateway to the plugin even though the server was happily computing the\nfull 714-claim result over 3+ minutes server-side\n- Backwards compatible: legacy synchronous responses from older servers (or\nsmall block fast-paths) pass through the polling helper unchanged\n- 14-minute client-side wall-clock cap on polling so a stuck job surfaces a\nclean error instead of hanging forever\n2.15.1 - Long-running request reliability for large claim blocks\n- Set explicit 5-minute network transfer timeout on all API calls so QGIS does not\nabort the read mid-response on long-running endpoints (claims/preview-layers/\nfor 700+ claims, batch sync, etc.) \u2014 prevents the \"Server returned empty\nresponse\" failure mode where the body was truncated by a client-side timeout\n- Surface a real diagnostic error (status code, body length, body snippet) when\nthe server response is not parseable JSON instead of silently returning an\nempty dict \u2014 turns \"Server returned empty response\" into something actionable\n- Configurable via api.transfer_timeout_ms (default 300000)\n2.14.1 - Persistent filing-map annotations\n- Red reference tie line + bearing/distance label now persist as a GeoPackage-backed\nlayer so they remain visible when \"Lock Styles For Layers\" is unchecked in the\nprint layout composer (previously ephemeral memory layer \u2014 vanished on unlock)\n- Corner labels (C1/C2/C3/C4, with LM flag) persist the same way\n- Reference Point marker: when a map is regenerated and no persistent layer exists\nyet, the state reference points are written into the GeoPackage reference_points\ntable and loaded as a real layer \u2014 covers legacy QClaims GeoPackages and any\nwalkthrough that reaches Step 7 without Step 3 having persisted the points\n- Works on both entry paths: walkthrough (Step 7 Generate Maps) and legacy loader\n(one-click \"Load Claims & Generate Maps\" on older GeoPackages)\n2.14.0 - Persistent reference points, map-orientation control, NV legal landscape\n- Reference Points layer is now loaded into the Claims Workflow group on project revisit,\nso it remains visible when \"Lock Styles For Layers\" is toggled in the layout composer\n- Reference Points persist as a real GeoPackage-backed layer (not an ephemeral memory layer),\nso their symbology survives across map regenerations\n- Add Page Orientation dropdown on Step 7: Auto (default), Portrait, Landscape, or Both\n- Field Map and generic Filing Map honor the orientation choice; \"Both\" generates two layouts\nwith \"(Portrait)\"/\"(Landscape)\" suffixes so users can pick whichever fits the claim-block\nplus reference-point extent\n- NV state filing map now ships the 8.5\"x14\" legal sheet in BOTH portrait and landscape\norientations alongside the 36\"x24\" ARCH D sheet (NRS 517.040 does not mandate legal orientation)\n- New template: nv_state_filing_map_legal_landscape.qpt (14\"x8.5\" with vertical title block)\n- AZ state filing map continues to use its fixed template (unchanged)\n2.13.0 - Unified claims loader and AZ filing map polish\n- Claims loader now handles both old QClaims and new geodb-plugin GeoPackage formats\n- Single \"Load Claims & Generate Maps\" button loads either format without re-running the wizard\n- Extract format differences into ClaimsFormat spec so one loader class handles both\n- Build corners from claim polygon vertices (authoritative geometry) instead of corner_points table\n- New format reads reference points from claims_metadata JSON; legacy reads from References table\n- AZ generic Filing Map now reuses the polished AZ state filing map pipeline (same template and output)\n- AZ filing maps use claims-only extent; tie to survey monument conveyed via reference text\n- Add monument-only legend (Location + Endline Monuments) to AZ filing maps\n- Auto-fit variable-length text labels (bearings, monument, reference) so they wrap within the page\n- Scale-bar segment size now adapts to map scale so small claim groups get appropriate 50-250 ft segments\n- Move main scale bar and scale text into the title block so they don't overlap map content\n2.12.0 - Map capture Web Mercator re-render and claims UI streamlining\n- Re-render map captures in EPSG:3857 for better alignment on mobile basemaps\n- Send pixel_width and pixel_height with map capture uploads for server-side georeferencing\n- Merge Auto-Number and Rename Claims into single \"Number & Rename Claims\" button (Step 2 and Order widget)\n2.11.0 - Legacy claims loader, field map tweaks, and staff order improvements\n- Add one-click legacy claims loader: load old QClaims GeoPackages and generate all maps\n- New LegacyClaimsLoader processor reads qclaims_metadata, maps old table names, applies styling\n- Builds processed_claims from legacy corner points, monuments, and endline monuments\n- Parses QSecs/Meridian fields into PLSS dict for filing map labels\n- Creates Claims Waypoints layer with waypoint_type field from old Symbol values\n- Auto-generates field map, filing map, and AZ state filing map from legacy data\n- Remove corner point symbols and C1-C4 labels from field maps (waypoint labels suffice)\n- Resize landscape map template for better label clearance\n- Auto-populate claimant info and monument type from staff order data\n- Pass company address and default monument type through staff orders dialog\n2.10.0 - NV filing maps, document upload, and compatibility fixes\n- Generate dual NV state filing maps: 36\"x24\" ARCH D and 8.5\"x14\" legal size\n- Add claim inset diagram on NV filing maps showing corner numbering and dimensions\n- Filter waypoint labels on field maps: show corner/witness names only (LM symbols unlabeled)\n- Hide LM corner layer for states without separate discovery monuments (ID, NM)\n- Upload documents to claim packages on geodb.io (maps, filing receipts, etc.)\n- List and manage uploaded package documents from Step 7\n- Fix reference points layer creation in storage manager (auto-create table)\n- Add string typeName fallback for QgsField on Mac QGIS builds\n- Fix RuntimeError on deleted Qt C++ objects in step5 layer cleanup and reference map tool\n- Remove plain geodb.zip copy from packaging script (versioned zip only)\n- Multi-line NV filing map title for better readability\n2.9.0 - Claims GeoPackage server integration\n- Merge Push to Server into single Push & Upload button on Step 7\n- Auto-upload claims GeoPackage to server after pushing claims/stakes\n- Link uploaded GeoPackage (ProjectFile) to ClaimPackage on server\n- Save layer styles into GeoPackage before upload\n- Add server GeoPackage dropdown on Step 1 (pull claims GeoPackages from server)\n- Download and load server GeoPackages with metadata and claim_package_id restoration\n- Keep Browse Local and Create New options as fallback\n- Extract shared GeoPackage utilities (style save, download) to utils/gpkg_utils.py\n2.8.3 - Professional filing maps with surveyor's bearings and annotations\n- Add surveyor's bearing notation (N 45\u00b000' W) replacing cardinal directions on all filing maps\n- Add dimension annotations on claim polygon edges (1,500' and 600' labels)\n- Add reference tie line from survey monument to Corner No. 1 with bearing and distance\n- Add corner labels (C1-C4 with LM designation) on filing maps\n- Add reference point marker (red triangle) at survey monument location\n- Differentiate Filing Map from Field Map with metes & bounds text, monument info, and tie text\n- Fix AZ state filing map: add all annotation layers, proper surveyor's notation\n- Fix NV state filing map: add UTM coordinate grid, fix rotated reference label\n- Convert all scale bars from meters to feet (US mining claim standard)\n- Keep user on Step 7 after Finish so Generate Maps button remains accessible\n- Fix map extent to include reference point on filing maps (tie line visibility)\n2.8.2 - UI improvements, map generation, and security cleanup\n- Reorganize Basemaps widget into unified sections (Basemaps, PLSS Grid, Public Lands, MRDS)\n- Consolidate PLSS/Federal Lands streaming controls into Public Lands section\n- Add Federal Lands streaming with color legend (BLM yellow, Forest Service green)\n- Add verbose logging to Federal Lands streaming worker for diagnostics\n- Fix Federal Lands layer geometry type (Polygon to MultiPolygon) for mixed responses\n- Add Generate Maps button to Step 7 (claims print layouts for field and filing use)\n- Add ClaimsMapGenerator processor for print-ready QGIS layouts\n- Centralize all urlopen calls into safe_urlopen() wrapper with scheme validation\n- Eliminates Bandit S310 findings from all call sites (5 files cleaned up)\n2.7.1 - Fix CRS transform crashes and claims wizard Next button\n- Fix QgsCsException crash when BLM/PLSS streaming layers transform extent with wide-extent basemaps\n- Add extent_to_wgs84() utility that clamps to CRS valid bounds before transforming\n- Apply safe transform to all 4 bounding box transform sites (BLM, PLSS, basemaps PLSS/MRDS)\n- Fix Step 6 (Finalize) Next button permanently disabled after processing and doc generation\n- Remove redundant tos_accepted/access_info validation from Step 6 (already validated in Step 1)\n- Persist tos_accepted in GeoPackage metadata for proper resume across sessions\n- Add conflict check before pushing planned samples (warns before overwriting existing records)\n2.7.0 - Claims workflow layer group consistency and auto-resume\n- Unify all claims layer group management under shared utility (get_or_create_claims_group)\n- All wizard steps now use the same \"Claims Workflow [XX Lode Claims]\" group\n- Add Claim Name Prefix field to Step 1 (used for GeoPackage filename and group naming)\n- Auto-suggest GeoPackage filename from prefix (e.g. GE_claims.gpkg)\n- Auto-resume wizard to next incomplete step when reopening a previous project\n- Resume dialog shows completed steps and offers to continue or start from Step 1\n- Step indicators still allow jumping to any completed step\n- Remove duplicate _add_layer_to_claims_group implementations across files\n2.6.2 - Streamline claims wizard finish flow\n- Remove redundant Download Documents button from Step 7\n- Finish button now opens Claim Packages page in browser and returns to Sync Data tab\n2.6.1 - Fix claims wizard step indicator and waypoint layer tracking\n- Fix off-by-one in step indicator (completed steps showed green on wrong step)\n- Fix step indicators not updating to gray when going back invalidates downstream steps\n- Fix step circle showing checkmark instead of number when navigating back to current step\n- Fix connector line coloring between steps\n- Add confirmation dialog when Back button or step click would invalidate completed steps\n- Fix Step 7 waypoints layer fallback picking wrong claim block in multi-block projects\n- Fix Step 6 monument adjustment updating wrong waypoints layer in multi-block projects\n2.6.0 - Code audit, pay-per-claim wizard, and refactoring\n- Add pay-per-claim 3-step wizard (Setup, Layout, Order) with Stripe checkout\n- Dynamic wizard step rebuild based on user access level (enterprise vs pay-per-claim)\n- Fix broken submit_order call in claims_order_widget (migrated to create_checkout_session)\n- Fix Project.company AttributeError in UserContext.to_dict() serialization\n- Fix null_geom_count double-counting geometry parse failures in layer_processor\n- Rename PermissionError to APIPermissionError to avoid shadowing Python built-in\n- Extract shared utilities: geometry.py, crs_utils.py, format_helpers.py\n- Centralize claims endpoint URL building in config.get_claims_url()\n- Fix SQLite connection resource leaks in claims_storage_manager (contextlib.closing)\n- Fix QNetworkReply memory leak in API client timeout path\n- Remove ~15 unused methods and 2 dead modules (api_response.py, photo_cache.py)\n- Replace print() calls with proper logger throughout codebase\n- Add claims_pushed state tracking with double-push warning in Step 7\n- Add layer cleanup on wizard reset and step re-entry\n2.5.0 - Claims Wizard & UI Improvements\n- Fix claims layer ownership tracking to prevent cross-group layer collisions\n- Use session-based layer IDs instead of name matching in Step 5/Step 6\n- Fix combo box signal blocking during refresh to prevent state corruption\n- Add project name suffix to Claims Workflow layer group name\n- Use server-provided sequence_number for location monument naming\n- Style QComboBox dropdown menus across all claims and assay dialogs\n- Add URL scheme validation for BLM and PLSS streaming requests\n2.4.3 - Qt6 Method Compatibility\n- Replace deprecated .exec_() with .exec() across all dialogs and event loops\n- Ensures forward compatibility with Qt6 / QGIS 4.0+\n2.4.2 - Cross-Version Compatibility (QGIS 3.36 / 3.38+ / 4.0)\n- Fix QgsField TypeError across all QGIS versions (3.36, 3.38+, 4.0) with runtime probe\n- Fix Qt enum compatibility for QGIS 4.0 (Qt.DashLine, Qt.Checked, QFrame.HLine, etc.)\n- Fix streaming layer crashes on project switch (wrapped C++ object deleted)\n- Fix PLSS grid streaming checkbox staying disabled after session restore\n- Add URL scheme validation for BLM and PLSS streaming requests (security hardening)\n- Centralized Qt5/Qt6 enum compatibility layer in utils/compat.py\n2.4.1 - Compatibility & Streaming Fixes\n- Add Qt5/Qt6 compatibility layer for QgsField types\n- Improve login error messaging\n- Add BLM claims manager and PLSS streaming manager\n- Basemaps widget and config updates\n2.3.1 - Toolbar Icon Fix\n- Fix missing toolbar icon (Qt resources module was not imported)\n2.3.0 - Claims & Stakes Sync Fix\n- Fix ClaimStakes not linking to ClaimPackage during push\n- Add claim_package field to ClaimStake schema for proper package scoping\n- Stakes now correctly appear under their ClaimPackage on the web dashboard\n2.2.2 - Code Quality & Bug Fixes\n- Fix division by zero when pulling model with no records\n- Remove unused imports and variables across codebase\n- Fix PEP 8 style issues (whitespace, line breaks, f-strings)\n- Pass Bandit security scan and Flake8 quality checks cleanly\n2.2.1 - Project Files & GeoPackage Sync\n- New \"Project Files\" tab with sub-tabs for Map Capture, Upload Files, and GeoPackage Sync\n- Upload georeferenced raster layers from QGIS to geodb.io server\n- GeoPackage sync: push/pull GeoPackage files with embedded styles\n- Improved world file generation with native CRS bounds support\n- Fix HiDPI/Retina display handling for map captures\n- Pre-select active layer in field work dialog\n- Security fixes: SQL injection prevention, URL scheme validation, safe XML parsing\n- Removed deprecated supportsQt6 metadata flag\n- Bug fixes and stability improvements\n2.1.1 - QGIS 4.0 Compatibility & Security Hardening\n- QGIS 4.0 / Qt6 compatibility (supports QGIS 3.0 through 4.99)\n- Security hardening of API client (request retry logic, removed debug exposure)\n- Bi-directional deletion sync with server\n- Deletion conflict detection (local changes vs server deletes)\n- Orphan cleanup for child records\n- Map canvas capture and georeferenced upload\n- GeoPackage storage option for persistent local data\n- Bug fixes and stability improvements\n2.1.0 - Major feature release\n- BC mineral claims workflow with 7-step wizard\n- Two-factor authentication (2FA) support\n- Photo viewer for drill photos and field notes\n- Staff order management interface\n- Basemaps widget for quick layer access\n- Structure model with geological symbology\n- GPX export for GPS devices\n- Fixed heap corruption crashes (QgsBlockingNetworkRequest)\n- Improved cross-platform compatibility\n2.0.0 - Major architectural rebuild\n- Modular design with separation of concerns\n- Improved error handling and logging\n- Progress feedback for long operations\n- Incremental data synchronization\n- Type-safe code with full type hints\n- Comprehensive documentation\n0.1 - Initial release", "external_deps": null, "download_url": "https://plugins.qgis.org/plugins/geodb/version/2.22.8/download/"}