Skip to content

SalahKit 0.1.0

Choose a tag to compare

@omar-hanafy omar-hanafy released this 13 Oct 23:23
· 101 commits to main since this release

The first SalahKit release: SalahCore's schedule, SalahCalculation over SalahTimes 0.1, SalahFixtures, and two example apps that prove them through the public API. CHANGELOG · Documentation · RFC 0001 · RFC 0002

Proven

  • CI on the release commit (run 38482091879):
    • macOS with Xcode 26: build, 201 tests, and builds for the iOS, watchOS, tvOS and visionOS simulators;
    • Linux with swift:6.2-noble and swift:latest: build and tests, SalahCalculation included;
    • both default-isolation settings, and swift-format lint;
    • MosqueBoard: the generated project matches project.yml, the app builds under MainActor and nonisolated isolation, unit tests and journeys pass on an iPad simulator, and a link check passes;
    • CalculatedPhone: the generated project matches project.yml, the app builds under both isolation settings, and unit tests and journeys pass on an iPhone simulator.
  • Local runs on macOS 27, Xcode 27.0 and Swift 6.4:
    • swift test: 201 tests (129 SalahCore, 38 SalahCalculation, 34 SalahFixtures), and the build with MainActor default isolation;
    • the documentation site builds with warnings as errors;
    • MosqueBoard: 15 unit tests and 7 journeys on an iPad (A16) simulator with iOS 27;
    • CalculatedPhone: 28 unit tests and 9 journeys on an iPhone 17 simulator with iOS 27.
  • Vectors:
    • 159 Core vectors, written from RFC 0001 before the implementation;
    • 94 calculation vectors in Vectors/calculation/, whose instants come from SalahTimes' independent Python reference;
    • SalahTimes 0.1.0's 1,196 prayer-time vectors, run through CalculationSource. Every instant it keeps equals SalahTimes'. Each of its 465 missing kinds has a documented reason: 443 don't occur, 9 Ishas follow a later day's first event, 4 Ishas aren't after Maghrib, 3 times fall outside their owning span, and 6 are on Apia's skipped date.
  • The calculated consumer.
    • CalculatedPhone runs on an iPhone simulator through the public SalahCore and SalahCalculation API.
    • It shows calculated schedules and the state across midnight: Kashgar's Isha after midnight, and Kazan's Fajr before midnight.
    • It exercises custom calculation parameters.
    • Its journeys inject the clock and location through launch arguments and assert the text on screen.
  • The timetable consumer.
    • MosqueBoard runs on an iPad simulator with MUIS's published timetable and iqama, through SalahCore's public API.
    • It shows partial and expired coverage, events after midnight and an explicitly declared Friday observance, without inventing missing values.
    • It links neither SalahCalculation nor SalahTimes. CI checks this on every run, in xcodebuild's target graph and in the binary's symbols and strings, and tests that each of those checks fails on a build that breaks it.
  • Parity with adhan-swift (docs/calculation-parity.md): SalahCalculation against the times the Salah app computed with adhan-swift over 2026, in 323 configurations at 22 places, including every method under each high-latitude rule at six places from 51.5° to 69.6°, and adjustments at high latitudes. Each of the 39,336 kind-days that differ by more than a minute falls into one of seven explained classes, and a model of adhan-swift's behaviors reproduces Salah within a minute on all 638,873 kind-days where both give a time. Its list of what Salah's users will see after migrating is checked against a generated table of every change by place, method, rule and kind.
  • Fixed before the release:
    • a CI step that could pass a failed build, because it ran without pipefail;
    • a link check that an early match turned into a pass;
    • cross-day order, with a lead, that wasn't kept past a day without events;
    • a series of corrections to the parity report's classes and to its list of what Salah's users will see.

Pending

These need a person or a device. Each item links the issue that tracks it, with the steps.

  1. Outside API review of RFC 0001 and RFC 0002 by an adopter who isn't building Salah (#43).
  2. Native-speaker review:
    • the catalog drafts for ur, fa, bn, tr, id and ms (#36, #37, #38, #39, #40, #41);
    • the Arabic UI strings of MosqueBoard and CalculatedPhone (#35, #32);
    • RFC 0001 §9 #2: should Maghreb Arabic keep Latin digits? (#42)
  3. Real devices:
    • MosqueBoard on an iPad, in both orientations and at the largest text size (#26);
    • CalculatedPhone on an iPhone, with the largest text size and VoiceOver (#30).

Settled since this release. These were pending when 0.1.0 was released:

  • MUIS data: confirm the Asr convention, that the times are local wall-clock times, and that bundling the SODL v1.0 data with attribution is acceptable. Settled in Timetables.md: MosqueBoard shows the published Asar times without assuming a convention, reads the rows as Singapore wall-clock times, and keeps the data under the SODL with attribution.
  • Edinburgh timetable: check how northern UK timetables print an Isha after midnight. Settled: the Edinburgh board is a labelled synthetic fixture for the after-midnight case, and Timetables.md links a real mosque's published summer policy for comparison.
  • Contrast: check both examples' colors with SalahUI's ContrastCheck once it exists. Settled: the examples keep the platform's semantic secondary text, a limit that RFC 0004 §8 #6 and the 0.4.0 release notes document.
  • Salah's migration: two product decisions from the parity report: Qatar's Ramadan toggle, and how Tehran's high-latitude nights are shown. Decided: Salah's choices records them.

Known limitations

  • SalahCore (RFC 0001 §9):
    • a Dhuhr holds one Jumu'ah congregation;
    • a discarded iqama isn't reported;
    • while the state is unavailable it has no statuses;
    • an expired timetable reads as one gap per day;
    • two events at the same instant get different statuses;
    • wall times on days whose clocks went back across midnight (historic only) aren't handled;
    • a state doesn't see a contradiction that a source makes with a day before its context (only a source that breaks the contract can make one);
    • no public initializers for gaps and coverage.
  • SalahCalculation (RFC 0002 §9):
    • a Maghrib and Isha at the same instant leave Isha missing (Tehran's method from about 58°);
    • of an inverted pair, the later kind is the one dropped;
    • a prayer that doesn't occur is reported like an unknown one;
    • there's no way to tell a method's parameters from the user's;
    • there are no adjustments by prayer kind.
  • Isolation: apply MainActor default isolation per target (.defaultIsolation(MainActor.self) in SwiftPM, or the build setting on your app's own targets). A global -default-isolation MainActor, or SWIFT_DEFAULT_ACTOR_ISOLATION passed on the xcodebuild command line, also reaches SalahTimes and breaks the build (RFC 0001 §6.3).
  • Versions: SalahKit 0.1 depends on SalahTimes .upToNextMinor(from: "0.1.0"), so it never resolves a SalahTimes 0.2 it wasn't built against. CI runs Xcode 26, because hosted runners don't offer Xcode 27 yet.
  • Linux: ICU data differs slightly from Apple platforms, for example in a few localized words and default digits (RFC 0001 §6.2).