The plugin is a single namespace (FSHIPPING\) with a custom SPL autoloader — no Composer runtime dependency. feedex-shipping.php maps class names to files: FSHIPPING\HTTP\Rates → includes/HTTP/Rates.php.

Layers

Bootstrap order (includes/Main.php)

Main::instance()->init() wires, in order: Freemius, Menu, OrderStatuses, OpenShipDraftsPage, OpenShipOrderMetaBox, OpenShipAjaxHandler, Settings, Email\ShipmentConfirmation, Schedule\Shipment, Checkout, Assets, CPT\Shipments, Ajax, Order; then frontend-group: Shortcodes, Widget, TrackingWebhookReceiver, DeliveryUpdates, CustomsAlerts, ShipmentGuard, SpecialServicesInjector, ETDOrchestrator, RateQuoteEndpoint; then PickupHistoryPage, ProductBoxPage, TrackingTimelineRecorder, AdvancedServicesInjector, ProductBoxPayloadInjector, RuntimeIntegrator, CommercialInvoiceBuilder, OneRateComparator, ReturnPortalHandler. Nearly everything is a SingletonTrait class with an init() that attaches hooks — grep for instance()->init() to find the full graph.

The HTTP layer

includes/HTTP/ holds one class per FedEx endpoint family (Rates, Shipment, OpenShip, Tracking, Locations, Pickup, AddressValidation, ReturnTag, TradeDocuments, GlobalTrade, FreightLTL, …). Clients extend a shared BaseClient (bundled kit/ submodule, with includes/Compat/BaseClient.php as a fallback when the submodule is absent — e.g. in .org distributions). Methods never throw: they return [] / '' on failure.

Developer-only clients (no UI)

These classes exist and work but nothing in wp-admin calls them yet — wire them with your own code: Similarly, Frontend\SavingsMeter records residential/commercial classification savings internally but renders nothing in the current version, and checkout shows prices only (no delivery-date UI).

Admin menu

The top-level admin menu is FedEx Shipping (includes/Menu.php, capability manage_options, slug fedex_shipping, dashicon dashicons-airplane). Submenus: Shipments & Printings (instant mode only), Settings, plus Open Shipments (advanced mode only), Pickup History, and Product Box.

Data model

  • fedex_shipping CPT — one post per purchased label (tracking number, label file, status, order link). Registered non-public and REST-hidden (includes/CPT/Shipments.php:810-832): 'public' => false, 'publicly_queryable' => false, 'show_ui' => true, 'show_in_menu' => false, 'query_var' => false, 'rewrite' => false, 'has_archive' => false, 'show_in_rest' => false, 'map_meta_cap' => true. There are no frontend single pages, archives, or sitemap entries — the admin list table (show_ui) is the only surface. Deleting a canceled shipment permanently deletes the linked WooCommerce order (see Delete cascade).
  • fshipping_options — all settings (see Options).
  • Transients — OAuth bearer tokens are cached, not minted per call: fshipping_auth_token_<md5(endpoint|client_id|client_secret)> and fshipping_track_auth_token_<md5(...)>, TTL = FedEx expires_in − 300 s (minimum 60 s), so switching credentials or environment mints a fresh token immediately (Auth/Authorization.php:34-66 and :86-116). Other transients: checkout rate quotes (fshipping_rates_<md5>, 10 min), public rate-widget cache (fshipping_rq_<md5>, 15 min) with its per-IP limiter (fshipping_rq_ip_<md5(ip)>, 1 h), webhook replay guards (fshipping_aiv_seen_<hash32> / fshipping_aiv_eid_<md5>, 24 h), per-IP rate-limit counters (fshipping_rl_<bucket>_<md5(ip)>, 1 h), service availability (fshipping_service_avail_<md5>, 1 day), postal-code validation (fshipping_postalcode_<md5>, 1 week on hit / 1 h on miss). Full list in Options, quota & data model.

Logging

Log sources, the WP_DEBUG gates, and order notes as the operational log.

Hooks & filters

The payload chain and every filter the layers above fire.