lib

Core libraries for Radroots
git clone https://radroots.dev/git/lib.git
Log | Files | Refs | README

README.md (4825B)


      1 # radroots_geonames
      2 
      3 `radroots_geonames` is the concrete GeoNames data provider for Radroots. It
      4 owns a pinned asset specification, explicit integrity-checked acquisition,
      5 read-only database lifecycle, and deterministic forward, reverse, feature, and
      6 country queries through provider-owned types.
      7 
      8 The crate does not choose cache or runtime paths, download during construction,
      9 create an async runtime, spawn a crate-owned task, install a timer, expose
     10 SQLite or HTTP client types, or define a generic geocoder SPI. Publication
     11 remains disabled during the `0.1.0-alpha` refactor.
     12 
     13 The authoritative package charter is the
     14 [`radroots_geonames` section of the Release V1 specification](../../contracts/crates/release_v1/radroots_crates_release_v1.toml).
     15 The reviewed Rust surface is recorded in the
     16 [public API baseline](../../contracts/api_baselines/radroots_geonames.txt).
     17 
     18 ## Prepare a query without I/O
     19 
     20 Construction is validated and inert:
     21 
     22 ```rust
     23 use radroots_geonames::{Point, Query};
     24 
     25 let locality = Query::locality("Victoria")?
     26     .with_region("BC")?
     27     .with_country("CA")?
     28     .with_limit(5)?;
     29 assert_eq!(locality.limit(), 5);
     30 
     31 let reverse = Query::reverse(Point::new(48.4284, -123.3656)?)
     32     .with_radius_degrees(0.25)?;
     33 assert_eq!(reverse.limit(), 1);
     34 # Ok::<(), radroots_geonames::Error>(())
     35 ```
     36 
     37 A runnable inert example is available at
     38 [`examples/prepare_query.rs`](examples/prepare_query.rs).
     39 
     40 ## Asset identity and acquisition
     41 
     42 [`asset::official_asset_spec`](crate::asset::official_asset_spec) returns the
     43 byte-pinned official version, file name, HTTPS source and authority, exact
     44 length, and SHA-256. Hosts may construct another [`AssetSpec`] only with one
     45 safe destination file name and an HTTPS URL whose authority matches exactly;
     46 userinfo, query strings, fragments, non-default ports, and plaintext sources
     47 are rejected.
     48 
     49 [`asset::inspect`](crate::asset::inspect) is passive. It reports missing,
     50 available, or invalid bytes and never repairs or downloads them.
     51 [`download::acquire`](crate::download::acquire) must be called explicitly with
     52 an existing host-selected directory and a host-owned [`download::Fetcher`].
     53 The crate bounds the stream before writing, stages in that same directory,
     54 checks exact size and SHA-256, synchronizes it, and atomically replaces the
     55 destination under an advisory lock. Symlink destinations fail closed.
     56 
     57 The fetcher owns DNS, network deadlines, and cancellation. Its typed failure
     58 phase cannot carry source URLs, credentials, or upstream error strings across
     59 the public boundary. The final rename is the local acquisition commit point;
     60 an interruption before it leaves the existing destination unchanged.
     61 
     62 ## Database and query behavior
     63 
     64 [`Geocoder::open`] accepts only an explicit regular file matching its
     65 [`AssetSpec`]. It opens SQLite read-only and query-only, runs an integrity
     66 check, and validates the required `geonames` and `coordinates` table columns.
     67 Opening, querying, and closing are caller-driven async operations. The caller
     68 provides the async runtime; this crate does not create one or spawn crate-owned
     69 tasks. Use [`Geocoder::close`] when an explicit terminal close result is
     70 required.
     71 
     72 [`Geocoder::query`] supports:
     73 
     74 - structured locality filters by locality, region, and country;
     75 - comma-separated free-form locality input;
     76 - exact GeoNames feature identifiers;
     77 - bounded reverse lookup with antimeridian and polar handling; and
     78 - deterministic country lists with provider-derived center points.
     79 
     80 Every candidate order has explicit tie-breakers. Numeric or text SQLite
     81 administrative identifiers become opaque strings at the private row boundary.
     82 Candidate, country, point, query, and result fields remain private and are
     83 read through accessors.
     84 
     85 ## Errors, serialization, and side effects
     86 
     87 [`Error`] exposes stable package-owned categories without paths, SQL, hashes,
     88 URLs, credentials, SQLx errors, or fetch-client errors. Host diagnostics
     89 should add their own path and transport context only at an access-controlled
     90 application boundary.
     91 
     92 The package defines no Cargo features and no stable serialized form. Persist
     93 host configuration in a host-owned versioned contract, then reconstruct
     94 `AssetSpec` and `Query` through validating constructors. Merely importing the
     95 crate, obtaining the official specification, or constructing a query performs
     96 no network, filesystem, database, runtime, clock, or process-global work.
     97 
     98 ## Intended consumers
     99 
    100 - `radroots_sdk` composes GeoNames as an explicit optional capability.
    101 - CLI and geocoding applications may acquire and query an asset directly.
    102 - Ordinary applications normally use the curated `radroots` package.
    103 
    104 ## Copyright
    105 
    106 Except as otherwise noted, all files in the `radroots_geonames` distribution
    107 are copyright (c) 2025 Tyson Lupul. See `LICENSE` for usage, redistribution,
    108 and warranty terms.