the engine · Go · MIT · github.com/adamf/jetway

Every feature of jetway

jetway is a messaging gateway for airline and global distribution system (GDS) reservation traffic. It terminates carrier links and decodes the messages that arrive on them. It keeps passenger name records (PNRs) and sends the replies. It is also a distribution system, a seat inventory and a departure control system (DCS). It is a datalink endpoint, an Aeronautical Fixed Telecommunication Network (AFTN) endpoint, a fare engine and a switch. wholesky needs each of those systems. Each system is usable on its own.

the inventory

The whole stack in one Go module

This is the function list of a reservations system, a GDS, a DCS and a Type B network. Every row is implemented and tested. A simulation of the world's schedule exercises every row daily.

Messages jetway sends and receives

domainmessages
reservations · Type BAIRIMP sell, reply, cancel, change · SSR · OSI · OSI/locator exchange · ticket numbers · remarks · received-from
reservations · EDIFACTPAOREQ · PAORES · TKCREQ · TKCRES · CONTRL
settlement · fileBSP HOT (DISH 23): BFH01 BCH02 BOH03 · BKT06 BKS24 BKS30 BKS39 BKI63 BAR64 BAR65 BKP84 · BOT93 BOT94 BCT95 BFT99
government · EDIFACTPAXLST (APIS, WCO/IATA/ICAO guide) · PNRGOV push (PADIS guide, with the check-in group)
airport ↔ airport · EDIFACTDCQCKI · DCRCKA (IATCI through check-in)
distribution · HTTPNDC OrderCreateRQ · OrderRetrieveRQ · OrderCancelRQ · OrderViewRS
availability & scheduleAVS · SSM · ASM (CNL, EQT, TIM applied) · SSIM
reservations → airportPNL (multi-part) · ADL
airport → worldPFS · PTM · PSM · ETL · LDM · CPM · BSM · BPM · BUM (rush bag) · AHL · OHD · FWD (tracing files) · loadsheet (AHM 560)
Network Manager → worldSAM · SRM · SLC · FLS · DES (ATFM slots, ADEXP) · SMM · REA · FCM · SPA · SRJ · RFI · SWM (the operator's replies)
aircraft & operationsMVT · MVA · DIV · ACARS OOOI (OUT OFF ON IN)
air traffic servicesAFTN envelope · FPL · DEP · ARR · DLA · CNL · CHG
transportsType B over framed TCP · MATIP (RFC 2351) · EDIFACT over TCP · HTTPS with mutual TLS · file drop · dialled trunk links between switches (link_dial + via routing)

Reservations system functions

  • Booking spans carriers and dialects in one record. The gateway free-sells from the availability cache. Otherwise it sends a request and waits for the answer.
  • Segment statuses are the codes the industry uses: NN SS HK HL HN HX KK KL UC UN US UU TK TL NO XX.
  • Pricing happens at booking under filed rules and taxes. The record carries the fare basis and the amounts.
  • Ticketing issues tickets with coupons and check digits. The gateway issues electronic miscellaneous documents (EMDs). It exchanges ticket control with the operating carrier.
  • Divide splits a booking into two records. Cancel ends a booking and advises every holder. The gateway can add and drop segments. A sweeper enforces ticketing time limits.
  • A refund of a document returns the open coupons to the purchaser. Used coupons stay used. The settlement plan reports the refund with the amounts reversed. The gateway sends every carrier its ticket numbers, over EDIFACT ticket control or on a teletype link as the special service request (SSR) TKNE.
  • Interline and codeshare bookings exist at both carriers. The marketing carrier and the operating carrier each hold a record, and each record carries the other's locator.
  • Queues hold confirmations, waitlists, unables, schedule changes, ticketing and divergence. IROPS rebooking, for irregular operations, sends requests and waits for the answers.
  • Availability is a set of claims, each with an age and a provenance. The gateway broadcasts and consumes them.
  • Special services travel on the record, and departure control honours them at the airport. The codes include WCHR WCHS WCHC UMNR INFT CHLD CBBG VGML DOCS MEDA BLND DEAF.

Departure control system functions

  • The DCS opens the flight from the name list. It checks in passengers with seat assignments by cabin and with bag tags. It applies ADL amendments from the additions and deletions list.
  • It boards the flight and closes the counter and the door at the scheduled times. It sends PFS, PTM, PSM, ETL, LDM, CPM messages to their addresses.
  • Load control uses the AHM 560/565 index method. It produces a legal loadsheet for each departure.
  • It reconciles the hold against the cabin at the door. A loaded bag whose passenger did not board holds the flight until that bag comes off. The DCS names a boarded passenger's unloaded bag for the rush, and a BUM announces it to the arrival station before it arrives. The station traces the bag with an AHL when the passenger arrives without it, and with an OHD when the bag arrives alone. It matches the two files on the tag and forwards them. The tracing messages are a profile, because WorldTracer's formats belong to the vendor. The DCS offloads the flight on cancellation.
  • Through check-in works across carriers over IATCI. The DCS accepts another airline's connecting passengers by name, seats them and answers per passenger. It requests check-in for its own passengers from the onward carrier and records the seat that carrier gave.
  • It changes the aircraft under a checked-in flight. It rebuilds the cabin from the new type and keeps every seat that still exists. It re-seats the other passengers. Passengers who no longer fit go on standby with a denied-boarding alert.
  • It reports to the state. It sends the Advance Passenger Information System (APIS) list as PAXLST at the door. It pushes the PNR as PNRGOV with each traveller's seat, sequence and bags. Both messages follow the public guides.
  • It derives MVT movement messages from the aircraft's out, off, on and in (OOOI) reports. It files the flight plan and receives the towers' replies.

Switch functions

  • A trunk connects two switches. The switch holds a dialled, bidirectional link open to a second switch and routes that switch's subscribers via the trunk. A message between carriers on different switches crosses the trunk once. The switch never carries a message back to its origin.
  • The switch terminates hundreds of circuits. It relays by address line and by UNB recipient to every addressee a message names.
  • It captures before interpreting. It keeps possible duplicates marked, and counts sequence gaps and repeats per peer.
  • It spools a message before it acknowledges it. It redelivers with backoff when a link comes back. When a peer stops reading, the switch refuses sends to that peer and does not stall behind it.
  • Rate limits apply per peer under a shared cap. A lease lets a standby take over. The switch reloads peers while running and applies retention by daily partition.
  • The switch peaks above 16,000 messages a second on one 4-vCPU machine under the world's departure banks.

The API

recordsPOST /api/book · GET /api/pnrs · GET /api/pnr/{locator} · POST /api/pnr/{locator}/ticket · /emd · /split · /cancel
messagesGET /api/messages · GET /api/message/{id} · POST /api/message/{id}/replay · GET /api/stream
sellingGET /api/availability · GET /api/flights · GET /api/journeys · POST /ndc
workGET /api/queues · GET /api/queue/{name} · POST /api/queue/item/{id}/work
carriersGET /api/carrier/{designator}/pnrs · GET /api/carrier/{designator}/inventory · GET /api/insights
operatingGET /healthz · GET /readyz · GET /metrics · GET /api/status · POST /api/admin/retire · GET /api/admin/export
the wire

Wire formats

The wire syntax is exact, and the message grammar is a profile. The envelope layers validate strictly, because ISO 9735 and the Type B envelope are universal. The layers above them vary by carrier and by bilateral agreement. Those layers are ordered recognisers, and you replace them per link without a fork. An unknown message still decodes at the syntax layer. The switch can capture, route and replay it even when no higher layer recognises it.

Type B and AIRIMP envelope specified

Type B is the teletype format that the SITA and ARINC store-and-forward networks carry.

  • The envelope follows IATA's public Type B whitepaper. It covers the priority and address lines, the origin line, the character repertoires, the 4 KB cap and possible-duplicate marking. The switch edits an envelope textually and never regenerates the raw bytes.
  • The AIRIMP grammar is an extensible recogniser profile. It covers sells, replies with KK, US, UC, UN and NO, cancels, and name and segment changes. It also covers SSRs and other service information (OSI) elements, ticket numbers, and locators exchanged both ways.
  • Long items fold at 63 characters, and parts paginate at 60 lines. A family of 4 on a filled 737 overran both limits.
  • Relay by address line delivers one message to every addressee it names.

UN/EDIFACT and PADIS syntax specified

jetway handles ISO 9735 interchanges that carry IATA Passenger and Airport Data Interchange Standards (PADIS) messages such as PAOREQ and PAORES. It sends and consumes CONTRL.

  • The syntax layer handles UNA service characters, release characters and repetitions. It validates the envelope, and fuzzed round trips test it.
  • PADIS is a segment-handler profile. The free PNRGOV implementation guide corrected 4 bugs whose tests had encoded the same guess as the code. The guide also describes how a divided booking is represented, with EQN and RCI.
  • Both dialects settle the same booking. One carrier receives the request over EDIFACT and another over Type B. Each answers separately and returns its own locator.

MATIP RFC 2351

MATIP is the airline transport for teletype over IP. jetway implements the packet format and the Type B session handshake for the partners that connect this way.

NDC schemas public

NDC carries IATA order messages over HTTP. jetway supports create, retrieve, cancel and the order view. It maps them onto the same record store as the teletype and EDIFACT traffic. It refuses payloads that carry card numbers before capture. There is no encryption at rest.

Availability AVS inferred

Availability status (AVS) messages are a per-link profile. They feed a cache in which every entry carries its age and its source. An entry older than the trust window no longer counts, and the booking sends a request instead. The gateway free-sells where the cache offers a seat. It sends a request to the carrier where the cache does not.

Schedules SSIM inferred

SSM and ASM schedule messages are an extensible profile, and jetway reads and writes the SSIM chapter 7 schedule file. The file has header, carrier, flight leg and segment data records in the 200-column layout, with codeshares tied by DEI 010/050. A cancellation sent as ASM reaches distribution and the airport, and bookings under a marketing carrier's code receive the advice under that code. An equipment change (EQT) queues the holdings for reprotection. A time change (TIM) moves the held segments to the new times at TK and queues the advice. When the message gives the times in UTC, jetway converts them to the station's clock.

records and selling

Records and the operations on them

The passenger name record is an event-sourced projection with optimistic concurrency. Every change is an event that names the message that caused it. A write carries the version it read. The store refuses a stale write, and the write cannot overwrite a state it never saw. A gateway and a carrier can modify one record at the same instant, and that case is normal.

The pipeline

capture ▸ classify ▸ decode ▸ dedupe ▸ apply ▸ queue ▸ respond. The gateway makes the raw bytes durable before any stage interprets them. After a parser fix, the operator can replay the traffic that failed, and the partner does not need to retransmit. Unrecognised lines become fragments on the record. Undecodable messages go to the dead-letter queue with their bytes intact. The gateway discards no message.

Booking

  • A sell covers one or many segments across carriers in either dialect. It carries SSRs, contacts, received-from and channel. The record holds every carrier's locator for the same booking.
  • Answers record the carriers' replies. HK means held and HL means waitlisted. UC means refused, and the gateway cancels the record behind it. UN means the requester's schedule is wrong.
  • Locators come from a keyed permutation per system. Filled and live records cannot collide.
  • Pricing runs at booking time against the gateway's tariff. It puts a fare basis on each segment and the amounts on the record.

Documents

  • Tickets come per passenger, with a coupon per segment. The ticket number carries the airline code and a check digit. The check digit is advisory, because public sources disagree. The gateway exchanges ticket control with the carrier that flies the passenger.
  • EMDs can be standalone or associated. The free EMD guide corrected the coupon status vocabulary.
  • Ticket-not-advised and every other gap a partner leaves land on the divergence queue, each with a name.

Changing the record

  • Cancel ends a booking and advises every holder. An unreachable carrier becomes a queue item.
  • Divide splits one booking into two, and the seats go with the passengers. Each carrier holds one record until it receives the advice. The AIRIMP divide message is the most expensive missing document.
  • Add and drop segments change an itinerary. A marketing carrier forwards a confirmed codeshare sell to the operating carrier as an interline sell.
  • Ticketing deadlines have a sweeper. An unticketed booking cancels when its limit passes.

Work queues

There are confirmation, waitlist, unable, schedule change, ticketing and divergence queues. The pipeline places items on them. A time-based sweeper catches a request nobody answered and a deadline that passed. Each queue reports a count. An external-publisher seam is available.

Irregular operations

The IROPS engine works the schedule-change queue. It looks at the next flights over the same city pair, the carrier's own flights first. It free-sells where the cache offers a seat, sends a request where it does not, and waits for each request until the carrier answers. A confirmed seat replaces the dead leg, with a sell and a cancel on the wire. The engine keeps and names a waitlist. A booking that no flight can carry stays on the queue for a person.

fares and inventory

Fares, operations and seat control

pkg/fare structure inferred · data none

The package has the structure of a fare filing and carries no fares. ATPCO fares are licensed. Callers supply a tariff.

  • Filings are per market and class, each with a fare basis. Rules cover advance purchase, minimum and maximum stay, seasons, and change and refund fees.
  • Taxes have a kind. A tax is a percentage, per segment, per ticket or per enplanement.
  • Passenger types ADT, CHD and INF each have a discount.
  • Pricing sells each segment under the cheapest fare whose rules the trip meets on the purchase date. When no fare fits, pricing reports the reason.

pkg/ops practice

The package is a carrier's operations desk for a node that runs the carrier. It loads the schedule from the carrier's SSIM file. It runs departure control at the carrier's stations as the gateway's Ground, and the carrier's own name lists open its flights. It turns the OOOI reports into the MVT messages the network reads, with the AD and its ETA, the AA and the delay against schedule. It files the towers' and the Network Manager's messages against the callsign. ops: in the configuration turns a gateway into an airline, and lets an operator's own jetwayd fly one of wholesky's carriers.

pkg/atfm ATFCM Users Manual specified

The package covers air traffic flow management. It handles the Network Manager's slot allocation (SAM) with its calculated take-off time. It handles the revision, the cancellation of a slot requirement, the suspension and de-suspension of a flight, and the operator's replies. The messages are in ADEXP to EUROCONTROL's public manual, and tests check them against the manual's examples verbatim. The regulation cause combines the cause letter, the phase of flight and the IATA delay code, correlated as Annex D of the manual has them. A slot inside an AFTN envelope reaches an operations centre through the gateway's Ground seam.

pkg/crew 14 CFR 117 specified

The package checks flight crew legality against the flight time and flight duty period limits by report time and number of segments. It also holds the 2 hour extension for unforeseen circumstances and the 10 hour rest. The values are transcribed from the public rule and tested value by value. A duty is a report and its legs at their current times. The check returns legal, legal only on the extension, or timed out. It also gives the latest departure time before the crew times out.

pkg/bsp DISH 23 specified

Settlement runs on the Airline Accounting/Sales data file (HOT), which a Billing and Settlement Plan hands each airline for its agents' sales. The package writes and reads that file to IATA's public handbook, column by column, and tests check it against the handbook's own worked figures. It covers sales and refunds, over-punch signing, the document-amount, commission and remittance arithmetic of section 6.7, and office, cycle and file totals. Exchanges carry their original issue (BKS46), and agency debit and credit memos name the document they correct (BKS45). The package also writes and reads the agents' side, the RET of chapter 5. Ticket numbers reach teletype carriers as SSR TKNE, which lets their books reconcile.

pkg/prorate method public · provisos not

The package holds the arithmetic of interline billing. It divides a through fare between the coupons of an itinerary by mileage. This method is straight rate proration. It rounds on the last coupon, and the shares add up to the fare. It computes the interline service charge that the carrier that flew keeps back. The Prorate Manual's minima, factors and special agreements are sold, and the package does not reproduce them.

pkg/inventory method specified

The package is leg-based seat control as the textbooks describe it. The caller supplies the numbers.

  • Cabins per leg are keyed by carrier, flight, date, boarding point and compartment. Booking classes map onto the cabins the aircraft has.
  • Nested class authorisations control the sale. A full cabin waitlists the request. A closed class refuses the request when the cabin still has seats. The last seats sell at the higher fares.
  • Revenue management uses an EMSR-b controller. The controller sets the authorisations from a demand forecast by class, with a fare, a mean and a spread for each class. It pools the classes above each discount and protects seats until the marginal seat's value falls below the discount in hand. It re-optimises on every question and receives what each class has sold. A forecaster that reads the booking curve can therefore move the ladder through the day. Tests check the controller against the normal table rather than the code. Network control requires a connecting itinerary to cover the sum of its legs' bid prices. The bid prices are the ladders' displacement costs, or the duals of the deterministic network programme when the caller supplies them. The programme is a plain simplex over legs, itineraries and demand.
  • Waitlists are a tenth of the cabin deep, with a minimum of 2. Each class can override the depth.
  • The package is rebuilt from the book of record at boot. A system that keeps sold seats only in memory oversells after a restart. The package publishes per-carrier sold, waitlisted and full-cabin gauges, and it counts every answer by status.
the airport and the aircraft

Departure control, movements and air traffic services

Reservations to the airport PNL/ADL inferred, closely

The gateway sends the passenger name list at T−180, in as many parts as the list needs. It sends the additions and deletions list at T−60. Per-passenger elements name the passenger they belong to, for example a child or a cabin bag with its own seat. Ticket numbers are hyphenated. Pagination counts rendered lines rather than items.

Departure control practices inferred from worked examples

  • The manifest opens from the name list. Check-in runs in waves, with seat assignments by cabin and bag tags sent to sortation (BSM). The hold then reports the bags loaded (BPM).
  • Boarding and close follow the clock. The counter closes at 45, the gate boards from 30, and the door closes at 10. The airport then sends its messages to the addresses that receive them. These are PFS for final sales, PTM for transfers and PSM for special services. ETL carries the ticket list, LDM the load and CPM the containers and pallets.
  • Load control uses the AHM 560/565 index method with a representative fleet. It produces a legal loadsheet with fuel, trim and limits.
  • Bag reconciliation runs at the door. Every bag the hold reports loaded must belong to a boarded passenger. The system names unaccompanied bags and removes them from the load. It names short-shipped bags to follow. The door can wait until the hold matches the cabin.
  • Cancellation offloads every checked-in passenger and pulls their bags. The system releases the manifest at the hour the flight would have landed.
  • Aircraft substitution puts a smaller type on a checked-in flight. The system rebuilds the cabin. It keeps the seats that exist on the new type and re-seats the rest. It denies boarding to the overflow by name. Distribution receives the ASM EQT under every code the flight sells under.
  • Through check-in (IATCI, DCQCKI/DCRCKA) lets the delivering station check connecting passengers in onto another carrier's flight. Refusals are per passenger and use the standard vocabulary. The manifest records the onward seat.
  • The state's messages are the APIS list and the PNRGOV push. The APIS list goes at the door and follows the WCO/IATA/ICAO PAXLST guide. The PNRGOV push follows the IATA PADIS guide. It sends the records as booked before departure, and again at the door with the check-in group. Tests run both on the guides' own worked examples.

Movements and datalink AHM 780 · ARINC 620, from published tables

  • ACARS OOOI reports cover out, off, on and in. They arrive in the form a datalink provider forwards to the airline.
  • MVT/MVA/DIV messages derive from the reports. The gateway does not assert them. They cover departures, arrivals, delays with their codes, and diversions to the field where the aircraft landed.

Air traffic services Annex 10 · Doc 4444 via FAA reproductions

  • AFTN envelope handling covers the priority, 8-letter addressee indicators, the origin, ZCZC and NNNN. Tests check it against the Annex's own example.
  • ATS messages are FPL, DEP, ARR, DLA, CNL and CHG. The gateway files a flight plan with the towers, and their DEP and ARR come back.
The flight panel in wholesky for one flight. It shows the name list parts, the seat map, the load and loadsheet, the flight plan, the towers' replies and the manifest.

The output of one departure's closure, as wholesky shows it. Every item comes from jetway's departure-control, movement and AFTN packages.

operating it

Running the gateway

pkg/node is one assembly that both jetwayd and the scenario suite build. The tests drive the same assembly that the binary runs. Everything under pkg/ is importable. This lets wholesky host 518 gateways in one process.

Ingress and identity

  • Listeners cover framed TCP, MATIP, HTTPS with mutual TLS, and a file drop.
  • Identity comes from the presented certificate or the arrival circuit. It never comes from an asserted name.
  • Rate limits pace each peer's reader, and the partner's own circuit pushes back. Each ingress has a shared cap. A partner that needs one gets its own share.
  • Outbox per link is a bounded queue with a writer goroutine. A read loop never waits on a peer's window. A peer that stops reading receives refusals, and the link does not stall. The gateway keeps frames sent in the same burst as a hello.

Durability

  • Spool fsyncs the raw bytes locally before the gateway acknowledges the partner. A drainer moves them into the store and retries until it succeeds. The spool is bounded. A full spool refuses a message and does not promise delivery.
  • Store holds an append-only message log and event-sourced records, in memory or in Postgres. Records are partitioned by retirement day. The store drops a day's partitions when the day wraps. A partition that the store cannot create never stops a write. Bulk load uses COPY.
  • Egress has backoff and restart recovery. It redelivers when a link comes back.

Operation in production

  • A lease lets a standby node take over when the holder stops renewing. The holder releases the lease after a drain.
  • Readiness pings the store and fails while the node stands by. Drains wait for in-flight work.
  • Hot peer reload happens on SIGHUP. Peers are keyed by name, with a format, a transport and addresses.
  • Retention and archive have two commands. jetwayctl retire --before drops the day. jetwayctl export --out streams every record as newline-delimited JSON for the archive a regulator asks about years later.
  • Metrics use Prometheus exposition with no client library. Tracing uses OpenTelemetry with a hand-rolled OTLP/JSON exporter. A production plan for GCP is in docs/production-gcp.md.

The console

  • Message flow shows every link and every message on the tape. You can open a message and read it field by field, with the raw bytes beside the decode.
  • Records are searchable by passenger. The view marks interline records, and shows their locators and the status as the carriers reported it. The fare card shows the base, the taxes, the total and each passenger's fare bases.
  • Queues shows confirmations, refusals, waitlists, and the divergence queue with each gap named.
  • Insights covers selling, documents, records and traffic. Departures shows a flight during check-in, its manifest and seat map, and the messages from the closure.

The command line

  • jetwayd is the gateway. By default it runs 3 simulated carriers and the console at :8080. Relay mode makes it a switch.
  • jetwayctl decode captured.tty decodes any captured message. jetwayctl retire handles retention.
  • jetwayload runs the scenario suite concurrently and reports latency.

Testing

  • Fixtures are written by hand from the specification. Every codec has fuzzed round trips. Conformance tests run against both store backends.
  • End-to-end scenarios run through the full assembly over TCP. The load driver reuses them.
  • A new test counts only after it has failed against the old behaviour.
  • wholesky is the load test. It runs a day of the world at warp 1, and an invariant suite is the pass criterion.
the standing table

Specified and inferred layers

Paid IATA publications define most of these formats, and the project did not buy them. The table below states which layers are specified and which are inferred.

specified the document is public and tests check conformance · inferred built from free reproductions and worked examples · no data structure only
layerstandingsource
edifact · CONTRL · matipspecifiedISO 9735, RFC 2351
typeb limits · PDMspecifiedIATA's public Type B whitepaper
padispartlythe free PNRGOV implementation guide
ndcspecifiedpublic schemas and carrier examples
aftnspecifiedICAO Annex 10 Vol II
atsspecifiedFAA reproductions of Doc 4444 forms
inventorymethod specifiedleg-based nested authorisations, with the caller's numbers
dcs load controlmethod specifiedAHM 560/565 arithmetic and representative fleet data
mvt · acars · PSM PTM LDM CPMinferred, closelyOAG tables, verbatim examples and airports' reproductions of the practices
airimp · avs · ssim · PFS · ETLinferredprofiles without conformance, because AIRIMP and SSIM are paywalled
farestructure onlythe structure of ATPCO filings and tickets. The filings are licensed and the package carries none

The roadmap names each paid document and the cost of its absence. The documents therefore form one procurement decision. The AIRIMP divide message is the most expensive single absence. Without it, the gateway cannot advise a split booking to its carriers.