Skip to content

Repository files navigation

WB Platform — Weight & Balance and Load Control

A Python platform for aircraft weight & balance, load planning, loadsheet generation, IATA post-flight messaging (LDM, MVT, UCM, CPM, NOTOC), EFB pilot acceptance, and audit / retention / DR hardening — for a 40-aircraft mixed-fleet carrier (A320 family, B787-8/9, Embraer E2).

End-to-end load control workflow:

  • math_core — pure AHM 560 functions (Index, MAC, DOW, envelope, stab trim)
  • aircraft_types — JSON catalog + SQLAlchemy 2 + FastAPI CRUD
  • flights — schedule, multi-leg, activity plan (T-XX templates)
  • load_planning — EZFW statistical v1 (per (route, type, season, dow) + Bayesian shrinkage) + ML v2 (GradientBoostingRegressor)
  • distribution_solver — CP-SAT autoload (OR-Tools) for narrow-body bulk loading
  • loadsheet — AHM 517 (Loadsheet) + AHM 519 (Trim Sheet) + LIR + NOTOC as PDF
  • messages — AHM 583/780/424/587/382 generators + Type-B wire format + outbox
  • messages/transports — SITA, Email, ACARS, AIDL, Test transports + worker
  • messages/inbound — BSM (AHM 565) + PNL (AHM 588) parsers + inbox with idempotency
  • efb — captain acceptance/decline with signature + GPS, audit chain
  • hardening — append-only audit log, ISAGO 7-year retention, API keys, deep health check, backup/restore scripts

Layout

src/wb_platform/
├── math_core/                 # Phase 0
├── aircraft_types/            # Phase 1
├── flights/                   # Phase 2.1
├── load_planning/             # Phase 2.2
│   ├── ml/                    # Phase 8 (GradientBoostingRegressor)
│   └── reconciliation.py      # Phase 7
├── distribution_solver/       # Phase 3.1
├── loadsheet/                 # Phase 3.2
├── messages/                  # Phase 4
│   ├── transports/            # Phase 5
│   └── inbound/               # Phase 7
├── efb/                       # Phase 6
├── hardening/                 # Phase 10
├── main.py
alembic/                       # migrations
data/                          # JSON seed data
scripts/                       # backup.sh, restore.sh
tests/                         # 510 tests
docker-compose.yml             # PostgreSQL dev
frontend/                      # React + Vite operator UI (Phase 9)

Install (dev)

cd wb_platform
pip install -e ".[dev]"

Run tests

pytest                          # 510 tests

Run the API

PYTHONPATH=src WB_DATABASE_URL=sqlite:///./wb.db alembic upgrade head
PYTHONPATH=src python3 -m uvicorn wb_platform.main:app --reload

To run with PostgreSQL instead:

docker compose up -d postgres
WB_DATABASE_URL=postgresql+psycopg://wb:wb@localhost:5432/wb \
  PYTHONPATH=src alembic upgrade head
WB_DATABASE_URL=postgresql+psycopg://wb:wb@localhost:5432/wb \
  PYTHONPATH=src uvicorn wb_platform.main:app --reload

API surface (highlights)

Aircraft types, registrations, flights, load plans, EZFW, loadsheets (Phases 1-3)

Messages (Phase 4)
POST   /messages/address-book                    # add SITA / email / ACARS address
GET    /messages/address-book/{registration}     # list for one aircraft
GET    /messages/address-book                    # list all
POST   /messages/build/ldm/{flight_id}          # build a LDM (Type-B encoded)
POST   /messages/build/mvt/{flight_id}?event_code=AX
POST   /messages/build/ucm/{flight_id}?direction=OUT  [+ ULD list]
POST   /messages/build/cpm/{flight_id}          [+ ULD list with positions]
POST   /messages/build/notoc/{flight_id}        [+ special loads]
POST   /messages/queue/ldm/{flight_id}          # build + queue in outbox
GET    /messages/outbox                          # list (filter by flight_id, status)
POST   /messages/outbox/{id}/send                # mark sent, write to log
GET    /messages/log?flight_id=...               # list logs
GET    /messages/log/{id}                        # log details (with formatted text)

Transports (Phase 5)
GET    /messages/transports                      # list available transports + health
POST   /messages/outbox/{id}/send?transport=TEST # send via a specific transport
POST   /messages/outbox/process?transport=SITA   # drain the outbox
GET    /messages/transports/test/captured        # inspect TEST-captured messages
DELETE /messages/transports/test/captured        # clear TEST capture

EFB (Phase 6)
POST   /efb/loadsheets/{flight_id}/create-acceptance  # ops creates PENDING
POST   /efb/acceptances/{id}/deliver                  # mark DELIVERED
GET    /efb/inbox[?captain=...]                       # captain's pending
GET    /efb/acceptances/{id}                          # view record
POST   /efb/acceptances/{id}/accept                   # captain signs ACCEPT
POST   /efb/acceptances/{id}/decline                  # captain signs DECLINE
GET    /efb/acceptances/{id}/verify                   # verify SHA-256 signature
GET    /efb/flights/{flight_id}                       # latest acceptance for flight
POST   /loadsheets/{flight_id}/v/{version}/create-efb-acceptance  # one-shot

Inbound (Phase 7)
POST   /inbox/receive                                # parse raw Type-B → inbox
GET    /inbox[?flight_id=&unapplied_only=]           # list
GET    /inbox/{id}                                   # view
POST   /inbox/{id}/apply                             # mark applied (audit hook)
GET    /inbox/flight/{flight_id}                     # list for a flight
GET    /load-plans/{flight_id}/reconcile             # PNL/BSM vs plan

ML EZFW (Phase 8)
GET    /ezfw/ml/model                                # current model info
POST   /ezfw/ml/train                                # train (or retrain) the ML model
POST   /ezfw/ml/predict                              # predict ZFW (ML or v1 fallback)

Admin / Hardening (Phase 10)
GET    /health                                       # liveness
GET    /health/deep                                  # DB + transports + audit chain
GET    /admin/audit                                  # list audit entries
GET    /admin/audit/verify                           # walk the hash chain
GET    /admin/retention/status                       # compliance dashboard
POST   /admin/retention/archive                      # archive > retention

Operator UI

A small React + Vite SPA for load controllers lives in frontend/. Five pages, no business logic in the browser — the API is the source of truth.

cd frontend
npm install
npm run dev            # http://localhost:5173 (proxies /api → :8000)
npm run build          # static build into dist/

See frontend/README.md for layout, conventions, and screenshots.

Transports

Transport Real impl Dev impl
SITA SITA Messaging API or telex terminal Writes sita_outbox/TS_ADDR_MSG.txt
EMAIL SMTP via smtplib Writes email_outbox/TS_ADDR.eml
ACARS ARINC / SITA datalink Writes acars_outbox/TS_REG.arl (with Q1 envelope)
AIDL ARINC 633 / EFB vendor Writes aidl_outbox/TS_REG.aidl (XML envelope)
TEST n/a In-memory capture for assertions

To enable real SMTP for EMAIL, set SMTP_HOST / SMTP_PORT / SMTP_USER / SMTP_PASSWORD in the environment.

EFB acceptance

Captain reviews the loadsheet on the EFB tablet, signs it with their name + EFB device id + GPS coordinates. The signature is a SHA-256 hash of the canonical record (flight_id + version + captain + decision + signed_at + GPS). Stored in efb_acceptance with a signature_hash column; the original record is tamper-evident (modifying any field breaks the signature).

Decline requires a reason (e.g. CG_OUT_OF_ENVELOPE, FUEL_MISMATCH).

Hardening

  • Audit log: append-only table with SHA-256 hash chain. /admin/audit/verify walks the chain and reports any tampering.
  • Retention: ISAGO 7-year retention policy. /admin/retention/status reports violations; /admin/retention/archive moves them to <table>_archive tables. Strict policies (audit log, EFB acceptance) require explicit approve_strict=true.
  • API key auth: set WB_API_KEYS=key:name:scope1,scope2;... to enable. Empty = dev mode (no auth).
  • Deep health: /health/deep checks DB connectivity, transport health, and audit chain integrity.
  • Backup/restore: scripts/backup.sh and scripts/restore.sh work for both SQLite and PostgreSQL.
  • PostgreSQL: docker compose up -d postgres spins up a 16-alpine Postgres with the wb schema and user. All SQLAlchemy 2 code is database-agnostic; no schema changes are needed.

Roadmap

  • Phase 0 (done): math_core
  • Phase 1 (done): aircraft_types
  • Phase 2 (done): flights + load_planning
  • Phase 3 (done): distribution_solver + loadsheet
  • Phase 4 (done): messages + Type-B encoder + outbox
  • Phase 5 (done): transports (SITA, Email, ACARS, AIDL) + outbox worker
  • Phase 6 (done): EFB acceptance (signature + GPS + decline reason)
  • Phase 7 (done): inbound BSM/PNL parsers + inbox + reconciliation
  • Phase 8 (done): ML EZFW (GradientBoostingRegressor with v1 fallback)
  • Phase 9 (skipped): LPM, SLS, DIV, RQM — deferred (more parsers, no new architecture)
  • Phase 10 (done): hardening (audit chain, ISAGO retention, auth, deep health, backup/restore, PostgreSQL)

ML EZFW

The load_planning/ml/ module provides a v2 ZFW predictor that uses scikit-learn's GradientBoostingRegressor. The v1 statistical predictor is still available as a fallback.

Features (built from FlightContext):

  • route hash, iata_type hash
  • season (one-hot), day-of-week (one-hot), hour of day
  • capacity_kg, pax_booked, payload_capacity_kg, load_factor
  • route history mean ZFW and n

Training: POST /ezfw/ml/train?n_samples=300&n_estimators=100&max_depth=4 synthesizes training data and trains a model. In production this would read from actual ZFW measurements (one row per flight, joining PNL/BSM data with the loadsheet).

Inference: POST /ezfw/ml/predict with flight_id, route, iata_type, std_utc, pax_booked, capacity_kg, payload_capacity_kg returns a prediction with 95% CI and confidence score.

Model persistence: Models are saved to WB_EZFW_MODEL_PATH (default ./models/ezfw_v1.pkl). The predictor lazy-loads the model on first predict, and persists each retrain.

About

Weight & Balance and Load Control platform for a 40-aircraft mixed-fleet carrier (A320, A321, B787, E-jets). IATA AHM 560/565/583/587/780/424/382/519/517 conformant.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages