## ADDED Requirements ### Requirement: RawStar shape The system SHALL export a `RawStar` interface with catalog ID, RA, Dec, apparent magnitude, spectral type, optional distance, proper motion, and parallax. #### Scenario: Raw star validation - **WHEN** a `RawStar` with all required fields is parsed - **THEN** validation succeeds - **AND** omitting `catalogId` causes validation to fail ### Requirement: StarCatalogSource interface The system SHALL export a `StarCatalogSource` interface with `id`, `magnitudeLimit`, `starCount`, `queryCone`, and `getById`. #### Scenario: Source query - **WHEN** `queryCone` is called on a source with RA, Dec, radius, and options - **THEN** the returned `RawStar[]` contains only stars within the cone ### Requirement: BSC5 bundled catalog The system SHALL export `createBsc5Source` returning a `StarCatalogSource` with ~9,096 stars, requiring no network or configuration. #### Scenario: BSC5 offline query - **WHEN** `createBsc5Source()` is created and `queryCone(0, 0, 1)` is called - **THEN** the promise resolves with an array of `RawStar` entries - **AND** the source `id` equals `"bsc5"` ### Requirement: StarProvider implementation The system SHALL export `StarProviderImpl` implementing `StarProvider` with priority-ordered catalog sources. #### Scenario: Visible stars query - **WHEN** `getVisibleStars` is called with a surface observer and default options - **THEN** the result is an `ObservedStar[]` sorted by brightness (brightest first) - **AND** every entry has `altitude` and `azimuth` populated ### Requirement: Horizon frame computation The system SHALL compute the local horizon frame from `ObserverPosition` for star altitude/azimuth calculation. #### Scenario: Zenith star altitude - **WHEN** a star with RA/Dec matching the observer's zenith is queried - **THEN** the returned `altitude` is approximately `90` - **AND** `azimuth` is `0` or `180` depending on convention ### Requirement: Atmospheric extinction The system SHALL apply Pogson's extinction formula using the Kasten–Young air mass when the observer has an `AtmosphereConfig`. #### Scenario: Extinction at low altitude - **WHEN** `getVisibleStars` is called for a surface observer on a planet with atmosphere - **THEN** stars near the horizon have `extinctedMagnitude > apparentMagnitude` - **AND** stars at the zenith have `extinctedMagnitude ≈ apparentMagnitude` ### Requirement: No extinction in vacuum The system SHALL NOT apply extinction for `SpacePosition` observers or planets without `AtmosphereConfig`. #### Scenario: Space observer magnitudes - **WHEN** `getVisibleStars` is called for a `SpacePosition` observer - **THEN** `extinctedMagnitude` equals `apparentMagnitude` for all stars ### Requirement: Cone query returns catalog stars The system SHALL return `CatalogStar[]` (without altitude/azimuth) from `queryCone`. #### Scenario: Catalog cone query - **WHEN** `queryCone(ra, dec, radiusDeg)` is called - **THEN** the result contains `CatalogStar` entries without `altitude` or `azimuth` ### Requirement: SurrealDB adapter interface The system SHALL export `SurrealAdapterLike`, `SurrealStarProviderOptions`, and `createSurrealStarSource` as a structural interface with no hard dependency on `@suaveplan/surrealdb`. #### Scenario: Structural satisfaction - **WHEN** an object with a `query` method matching `SurrealAdapterLike` is passed to `createSurrealStarSource` - **THEN** the returned object satisfies `StarCatalogSource` ### Requirement: Deferred catalog interfaces The system SHALL export type signatures for `createHipparcosSource`, `createTycho2Source`, and `createGaiaSource` with injectable `fetchFn` and optional `cacheFn`. #### Scenario: Interface existence - **WHEN** the public API surface of `@suaveplan/stars` is inspected - **THEN** the three deferred factory function types are present - **AND** their option types include `fetchFn` and `cacheFn` fields