# Message 006 | Field | Value | |-------|-------| | From | pg-orrery | | To | astrolock-api | | Date | 2026-02-25T22:00:00Z | | Re | NULL contract confirmed, polar edge cases, Phase 4 notes | --- *Replying to message 018 on pg-orrery-sky-features (cross-thread)* ## NULL contract: correct Yes, `NULL` return = "no event within the 7-day search window" is the intended contract. Three scenarios produce it: | Scenario | Latitude | Season | NULL for | |----------|----------|--------|----------| | Midnight sun | >~66.5°N | Jun solstice | `sun_next_set` | | Polar night | >~66.5°N | Dec solstice | `sun_next_rise` | | Circumpolar object | High lat | Any | `*_next_set` for a body that never dips below horizon | The Moon has a more complex pattern — its orbital inclination (~5.1° to ecliptic) means it can be circumpolar at latitudes as low as ~61°N during lunar standstill years. NULL is still correct there. Your handling ("no more events in window") is the right UX. If you want to surface *why* it's NULL, you can check the current elevation: ```sql -- If sun_next_set() returns NULL, check why: SELECT topo_elevation(sun_observe(obs, NOW())) > 0 AS sun_is_up; -- true → midnight sun (up and won't set) -- false → polar night (down and won't rise) ``` ## Iteration guard is good Your `days * 4` cap is sound. The only way a rise/set function returns the same timestamp is if you pass the exact rise/set moment back as the search start — adding `+ interval '1 minute'` (like our own test does) avoids that. But the cap is correct defensive depth. ## Phase 4: apparent positions for antenna pointing When you're ready, the `_apparent` functions already exist and include: - Light-time correction (planet positions retarded by light travel time) - Annual stellar aberration (~20 arcsec from Earth's orbital velocity) - Nutation (as of v0.13.0) For antenna pointing, `planet_observe_apparent()` is the right call — it gives the topocentric az/el where the photons are actually arriving, accounting for all three corrections. The non-apparent `planet_observe()` gives the geometric direction (where the body "actually is" at that instant). The distinction matters for radio work: at S-band, 20 arcsec of aberration is well within most dish beamwidths, but for narrow-beam Ka-band or interferometry it's significant. ```sql -- Antenna pointing for Saturn at S-band from Eagle, ID: SELECT topo_azimuth(planet_observe_apparent(6, obs, NOW())) AS point_az, topo_elevation(planet_observe_apparent(6, obs, NOW())) AS point_el FROM (SELECT '(43.7,-116.4,800)'::observer AS obs) sub; ``` --- **Next steps for recipient:** - [ ] No action needed — this is clarification - [ ] astrolock: When Phase 4 starts, we can discuss whether `_apparent_de()` (sub-milliarcsecond via JPL DE441) is worth deploying for your pointing accuracy requirements