tabulae-aeriae/documentation/administrative/tabulae-aeriae-scope-statement.md

14 KiB
Raw Permalink Blame History

Tabulae Aeriae — Project Scope Statement

Version: 1.0
Date: March 29, 2026
License: AGPL-3.0 (pending final confirmation)
Repository: Forgejo (self-hosted)


1. Project Overview

Tabulae Aeriae is a self-hostable, web-based pilot logbook system designed to provide FAA-compliant flight record keeping, robust reporting, currency tracking, and data visualization. The system targets two tiers of users: a free open-source tier for non-commercial pilots (Part 91, recreational, student) and a paid professional tier for commercial operators (Part 135, Part 121).

The project is motivated by the absence of a quality open-source, self-hostable pilot logbook that provides genuine FAA regulatory compliance, one-click report generation for common FAA forms, and a data-driven currency tracking engine. Existing open-source projects (web-logbook, jetlog, flightlog) are either EASA-focused, passenger flight trackers, or lack the reporting depth that professional pilots require.


2. Objectives

Primary Objectives (v1)

  • Provide a complete FAA-compliant logbook meeting 14 CFR 61.51 requirements
  • Generate FAA Form 8710-1 Section III data with one-click reporting
  • Generate FAA medical (8500-8) total time and last-6-months data with one-click reporting
  • Track pilot currency under 14 CFR 61.57 (day, night, instrument, flight review) with real-time status display
  • Visualize flight data through maps (route visualization) and charts (time breakdowns, trends)
  • Support self-hosted deployment on low-resource hardware (Raspberry Pi / Docker Swarm)
  • Maintain a complete audit trail of all logbook changes

Secondary Objectives (v1)

  • Provide a skeleton framework for future EASA (FCL.050) compliance
  • Support configurable, user-saveable custom reports for insurance, company, and personal use
  • Support CSV import with a pluggable adapter architecture for future format support
  • Track pilot qualifications, certificates, ratings, endorsements, and currency events in a unified table
  • Track medical certificate status with expiry countdowns

Deferred Objectives (Paid Tier / Future Releases)

  • PF/PNF (Pilot Flying / Pilot Not Flying) as first-class fields
  • IOE (Initial Operating Experience) tracking
  • High minimums captain status tracking
  • Duty/rest tracking (Part 117, Part 135 Subpart F)
  • Augmented operations crew management
  • Operator-specific currency rule overrides (61.57(e) exceptions)
  • GPS track import (KML/GPX) for precise route/night calculation
  • SQLite backend option for simplified single-user deployment
  • Full EASA compliance (FCL.050 fields, EASA PDF export formats)
  • OAuth2/OIDC/LDAP authentication providers

3. Technical Architecture

Stack

Layer Technology Rationale
Backend Go with Chi router Low memory footprint, single binary, fast compilation, strong stdlib
Database PostgreSQL 16 Robust, supports JSONB for flexible fields, trigger-based audit trail, already deployed on target infrastructure
Frontend React + Vite + Tailwind CSS Rich interactivity for report builder, maps, charts; static build embedded in Go binary
Charts Recharts React-native, lightweight, composable
Maps react-leaflet React-native, lighter than OpenLayers, strong community
Deployment Docker (multi-stage build) Single image containing Go binary with embedded frontend assets; no runtime dependencies on Node or Nginx

Deployment Target

Docker Swarm on Raspberry Pi cluster. Estimated resource consumption:

Container Memory Limit CPU Limit
Tabulae Aeriae (Go + static assets) 128 MB 0.5 CPU
PostgreSQL 16 Alpine 256 MB 0.5 CPU
Total ~384 MB 1.0 CPU

Build Pipeline

Multi-stage Docker build:

  1. Stage 1 (Node): Build React frontend with Vite → static assets
  2. Stage 2 (Go): Compile Go binary embedding frontend via embed.FS
  3. Stage 3 (Alpine): Minimal runtime image with binary + CA certificates + timezone data

Final image size: estimated 2030 MB.


4. Data Architecture

Database Tables (v1 — 10 tables)

Table Purpose
users Pilot accounts, authentication, regulatory profile, tier
flights Core logbook entries — all time fields, approaches, custom fields
aircraft Real aircraft and simulators/FTDs — tail numbers, type, attributes, device info
airports Seeded from OurAirports; includes user-defined custom airports
airport_identifiers Maps current and former airport codes to physical airports
pilot_qualifications Certificates, ratings, endorsements, and currency events (IPC, flight review, checkrides)
medical_certificates Medical class, issue/expiry dates, examiner info
saved_reports User-saved report configurations with JSONB config
currency_rules JSON-driven currency rule definitions (system and user-defined)
audit_log Append-only changelog triggered by INSERT/UPDATE/DELETE on tracked tables

Key Schema Design Principles

  • All times stored as INTEGER minutes. Floating-point hours introduce rounding errors that accumulate over a career. Rounding to display hours (truncate, round-nearest, or round-up) is applied only at the reporting layer, after aggregation.
  • All timestamps stored as TIMESTAMPTZ in UTC. No local time in storage or computation. Local time conversion is a display-layer concern only.
  • No pre-aggregated compound categories. Fields like "cross-country while under instruction" are derived at query time using LEAST() intersection logic. Pilots log atomic observations; the system computes intersections.
  • JSONB for flexible structures. Instrument approaches (variable count and type), custom fields (company/insurance-specific), and report configurations all use JSONB for schema flexibility without sacrificing queryability.
  • Historical accuracy over normalization. The tail_number is denormalized onto the flight record because aircraft registrations change. The departure_airport and arrival_airport store the code the pilot used at the time, even if that code has since been retired.
  • Simulators and FTDs in the aircraft table. Training devices are aircraft for logging purposes. A boolean is_simulator flag plus device-specific nullable columns (level, serial, approval number) avoid a separate table and dual foreign key complexity.

Airport Data

Source: OurAirports (davidmegginson/ourairports-data), Unlicense. Over 78,000 airports worldwide, updated daily, includes closed airports.

Strategy: Embed a snapshot at build time for offline-capable first boot. Provide an admin command (--refresh-airports) or API endpoint to pull updated data on demand.

Historical code changes (e.g., 09G → KTEW) are handled by the airport_identifiers table, which maps multiple codes to a single physical airport with is_current and date-range fields.


5. Reporting

Built-in Reports (One-Click)

Report Output
FAA 8710-1 Section III Complete pilot time matrix — all categories, classes, and time fields. Derived at query time from atomic flight fields using LEAST() for compound categories. Rounded to whole hours per user preference.
FAA Medical (8500-8) Total all-time hours and total hours in last 6 calendar months. Two numbers, one click.
Currency Status Real-time status of all active currency rules — green/yellow/red with days remaining and remediation guidance.

Configurable Reports

Users can create and save custom reports by selecting date range (fixed, rolling, or all-time), filters (aircraft, category/class, airport), grouping (month, year, type, category/class), columns to include, and output format (on-screen, PDF, CSV).

Report configurations are stored as JSONB and can be pinned to the dashboard for one-click access.

8710 Derivation Method

Compound time categories are derived using LEAST() logic at query time:

  • XC Instruction Received = SUM(LEAST(cross_country, dual_received)) on flights where both > 0
  • Night PIC/SIC = SUM(LEAST(night_time, pic_time + sic_time)) on flights where both > 0

This prevents the aggregation errors that occur when pilots manually pre-compute compound categories. The pilot logs atomic observations; the system handles the math.

Rounding is applied after aggregation (sum all minutes across all flights, then round to hours), not per-flight, to prevent cumulative rounding error.


6. Currency Tracking

Engine Design

Currency rules are data, not code. Each rule is a JSON configuration stored in the currency_rules table. The engine evaluates rules against flight records and qualification events to produce real-time status.

FAA Rules (v1)

Rule Regulation Lookback Requirements
Day currency (per category/class/type) 61.57(a) 90 days rolling 3 takeoffs + 3 landings
Night currency (per category/class/type) 61.57(b) 90 days rolling 3 night takeoffs + 3 night full-stop landings
Instrument currency 61.57(c) 6 calendar months 6 approaches + holding + tracking
Instrument grace period 61.57(c)/(d) Months 712 after lapse Same tasks to self-restore; IPC required after month 12
Flight review 61.56 24 calendar months Flight review, checkride, or WINGS phase
Medical certificate 61.23 Per class/age Valid medical not expired

Custom Rules

Users can define personal minimums, insurance requirements, or company-specific rules using the same engine.

Night Definition Handling

The night_time field stores sunset-to-sunrise time (the standard logging definition). Night takeoff/landing classification for currency purposes uses the 1-hour-after-sunset to 1-hour-before-sunrise standard, auto-suggested from departure/arrival times and airport coordinates.

Night Time Auto-Calculation

Solar position computed at intervals along the great circle route between departure and arrival airports. Accounts for aircraft movement relative to the terminator — critical for long-haul flights crossing significant longitude. Produces the sunset-to-sunrise value for logging. Always pilot-overridable.


7. Authentication & Authorization

Architecture

Single auth system with a pluggable provider interface. No separate codepaths for free vs. commercial.

v1 provider: Username/password with bcrypt hashing and JWT token issuance.

Future providers (same interface): OAuth2/OIDC (Google, generic), LDAP. Adding a provider means implementing the AuthProvider interface — no changes to middleware, handlers, or session management.

Feature Gating

Tier-based authorization middleware reads a tier field (free/professional) and gates access to paid-tier features. Auth and authorization are separate concerns — the auth system doesn't know about tiers.


8. Import / Export

Import

Pluggable adapter architecture. Each adapter implements an ImportAdapter interface with Detect() (auto-format detection) and Parse() (conversion to internal model) methods.

v1 adapter: Generic CSV with user-defined column mapping.
Future adapters: ForeFlight, LogTen Pro, Logbook Pro, AeroLog.

Import supports partial success (bad rows reported individually, good rows imported), duplicate detection, and detailed per-row error reporting.

Export

  • CSV: Full logbook export
  • PDF: Configurable column layout (user-defined logbook page format)

9. Visualization

Flight Map

Interactive world map (react-leaflet) displaying great circle routes between airports. Filterable by date range, aircraft, and category/class.

Statistics Dashboard

Recharts-based charts showing: time by category/class over time, cumulative hours, flights by month/year, time by aircraft type, airport frequency, and custom breakdowns.


10. Audit Trail

PostgreSQL trigger-based changelog. Every INSERT, UPDATE, and DELETE on tracked tables (flights, aircraft, users) writes a row to audit_log with the full old and new row values as JSONB. The changed_by user ID is captured via a PostgreSQL session variable set by the application middleware.

Enables: full reconstruction of any record's history at any point in time, regulatory compliance documentation, and dispute resolution for commercial operators.


11. EASA Skeleton

FAA compliance is the v1 target. EASA support is prepared via:

  • A regulatory_profile field on the user record (values: faa, easa, both)
  • Nullable EASA-specific columns on flights and aircraft tables (multi-pilot time, co-pilot time, SPSE/SPME, function type, etc.)
  • These columns are hidden in the UI when regulatory_profile = 'faa'
  • Full EASA implementation is a future release — the schema is ready, the UI and reporting are not

12. Out of Scope (v1)

  • Duty/rest tracking (Part 117, Part 135 Subpart F)
  • Augmented operations / multi-crew scheduling
  • PF/PNF as first-class schema fields (available via custom_fields JSONB)
  • IOE tracking as a first-class field
  • High minimums captain tracking
  • Operator-specific currency overrides (61.57(e) exceptions)
  • GPS track import (KML/GPX)
  • SQLite backend
  • Full EASA compliance
  • OAuth2/OIDC/LDAP authentication
  • Mobile-native applications (responsive web only)
  • Integration with external services (ForeFlight, Garmin Pilot, etc.)
  • Electronic endorsement/signature system
  • Multi-tenant SaaS hosting infrastructure

13. Risks and Mitigations

Risk Impact Mitigation
FAA regulatory changes Currency rules or reporting requirements change Rules are data-driven JSON configs; updates are database migrations, not code changes
PostgreSQL resource consumption on Pi Exceeds memory limits under load Alpine image, connection pooling, aggressive work_mem tuning; schema is simple (10 tables)
Airport data staleness New airports or code changes not reflected Build-time embed with on-demand refresh command; quarterly refresh cadence is sufficient
Night time calculation accuracy Solar algorithm produces incorrect results for edge cases Algorithm uses well-established NOAA equations; pilot always has manual override; auto-calculation is a suggestion, not a mandate
Scope creep from professional tier features v1 becomes unshippable Professional features are explicitly deferred and documented; schema is designed to accommodate them without destructive migrations