Overview › Certifications & eCard

Certifications & eCard

Area: 02 Certifications & eCard · 2 items · Source: PADI Mobile Scope Alignment v-ceb35f4d Subject: the unified PADI app — Expo React Native. Every verdict below is about what that app can build, not about what today's apps do.

What this card covers, and what it does not

The area holds 9 items, split across all three release lanes. This card is the two in the Q1 2027 Delta laneCERT-01 and CERT-05.

Two more are carried forward from webMYP-03 and MYP-10. Both are analysed in full under Logged In Experience and are restated here in one line each, so the area reads as one page.

The remaining five — CERT-02, CERT-03, CERT-06, CERT-07, CERT-08 — are in the Post Q1 2027 lane and are not analysed here.

CERT-04 does not exist. The IDs run 01, 02, 03, then 05 to 08 — the same discontinuity as AUTH-07. Anyone reconciling item counts against this card should expect seven CERT items, not eight.

Neither of the two has a detail drawer. Both arrive as a title and a set of flags, and the flags carry the whole brief:

  • CERT-01 carries Nowconfirmed for Q1 2027. It is the only item in this area with that flag, and one of only 26 in the whole artefact.
  • CERT-05 carries PRK, SPK, DEP and IAP. Four flags on one unspecified line is the artefact asking a question rather than stating a requirement.

How to read the evidence in this card

The unified app is a new client. It inherits no code from kms-ios-padi or kms-android-padi — those apps are being replaced, and nothing in them is a head start on implementation.

What they are is proof that an endpoint answers a mobile client holding a diver's token. That is worth a great deal when the alternative is a requirement with no named API, and it is the only reason they appear below. Where this card says "already shipping", read it as "the endpoint is proven callable and the data shape is known" — never as "the work is done".

The one exception is a POC, which is the unified app's stack. Code in poc/ is written in Expo React Native against PADI's real hosts, so it establishes both that the endpoint works and that the client can do the job. That is why it outranks everything else in the evidence order.


Certifications are read-only, and that decides the shape of the build

A certification is issued by PADI's back-office systems — LMS, M2-Macola, Salesforce — and no client ever edits one. The unified app only reads.

That single fact removes the hardest problem in offline work. Everywhere else in this scope, "offline" obliges the app to queue writes, detect conflicts and replay them — the missing capability ID-04 and ID-06 both fail on, and the reason PLT-01 exists. Here the app needs a durable local cache that reconciles pull-only. No outbox, no conflict policy, no merge UI.

This is a direct input to PLT-01's scope, and it needs to land before that estimate. PLT-01"Shared offline foundation (save + sync + conflict handling)" — is committed for Q1. Certifications consume only its read half. If the foundation is specified from the dive-log side alone, the unified app will be given write machinery this area cannot use, and CERT-01 will queue behind work it does not need. The read half is already built and tested in padi-cert-offline-poc; it should be named in the PLT-01 estimate rather than re-derived.


CERT-01 — Certification history — offline access

Flags Now — confirmed for Q1 2027 Verdict for the unified app: build it. This is the most de-risked item in the study. API status: POC-proven

What the unified app has to deliver

A diver opens the app with no connectivity — on a boat, in a resort with no roaming — and sees every certification they hold, with the eCard artwork, exactly as they would online.

What it can rely on

The endpoints are known, and the unified app's own POC already calls them. Four list endpoints, a 2×2 of audience × card kind, resolved by endpointFor(isPro, cardKind):

eCard (digital) P-Card (physical)
Pro eCard/GeteCardListPro eCard/GetAllCardListPro
Consumer eCard/GeteCardListConsumer eCard/GetCardListConsumer

Base ecard.global-prod.padi.com/api/ (ecard-stage.global-np.padi.com/api/ staging). Full inventory in API inventory §5.

And the offline behaviour is already implemented on the target stack. padi-cert-offline-poc is Expo + Realm, with the reconcile core written as pure functions and unit-tested against an in-memory repository — the same logic that runs on-device. What it settles, beyond "it caches":

  • a failed pull never mutates or deletes the cache; records are flagged stale
  • a card the server stops returning is retained and flagged archived, not deleted
  • change detection runs on server version, falling back to updatedAt, so an unchanged card produces zero writes and zero redundant image downloads
  • eCard images live on the file system rather than in the database, so when a card's photo URL changes the old image is dropped and re-fetched — closing the stale-eCard defect named in discovery

Two independent confirmations that the endpoints answer a mobile client holding a diver's token: today's iOS app persists cards in SQLite and refreshes them through two background tasks (DatabaseRepository.swift:24-42, BackgroundTasksRepositoryImpl.swift:372-401); Android persists the same payload in Room (AppDataBase.kt:18,36,52, ECardsApi.kt:9-14). No unified-app code comes from either — they establish that the data is reachable and what shape it arrives in.

What the unified app still has to build

Integration, not invention:

  1. Lift the POC's sync core into the product app — it is written to be portable, but it currently lives in a standalone project with its own navigation and Settings-driven mock mode.
  2. Pin the ECardInfo field mapping. The POC ships in Mock mode and says so: mapECard() needs pinning "once PADI shares a sample EcardsResponse". The ~55 fields documented on the Android model (ECardInfo.kt:14-68) are reverse-engineered from client code, not a PADI contract.
  3. Real token acquisition. The POC takes a bearer token typed into Settings; the app has to source it from the session.
  4. Card artwork at scale. Artwork comes from Cloudinary (padi/resources/search); the POC proves the lifecycle on a handful of cards, not a Pro member's full wall.

What could still move it

PADI-1. The eCard family is named in this study as sitting on the legacy surface PADI has confirmed is being rebuilt, with no list of affected endpoints. A path change is a rename and cheap; a change to the card model would land on the field mapping above.

The one product decision outstanding

What "offline access" means — and the two existing implementations disagree, so this cannot be inferred:

  • today's iOS app is opt-in: a Download eCard control on the detail screen (ECardDetailV2ViewController.swift:18-19), with the repository speaking of "downloaded" cards throughout
  • the POC is automatic: every card, on launch and on reconnect

Opt-in costs less storage and surprises nobody; automatic is the only version that helps a diver who did not think to prepare — which is the case the feature exists for. CERT-01 is flagged Now, so this wants answering before Q1 estimation, not during it — SCOPE-30.

Questions: SCOPE-30 (automatic or opt-in) · PADI-1 (is the eCard family being rebuilt)


CERT-05 — eCard wallet integration (Apple / Google Wallet)

Flags PRK parking, SPK, DEP, IAP Verdict for the unified app: cannot be delivered, and not because of anything in the app. API status: Gap — server side

The SPK flag asks for a feasibility check. The answer splits in two, and the halves have opposite answers.

What the unified app has to deliver

A diver taps Add to Apple Wallet (or Google Wallet) on an eCard and the credential lands in the phone's wallet, staying correct as it renews or expires.

What it can rely on

The device-side capability is ordinary work in Expo React Native — presenting a pass is a well-trodden library integration on both platforms, and no PADI API is involved in that step.

And the data is already on the device, put there by CERT-01. The cert POC scoped pass generation out deliberately, with a note that says exactly this: wallet pass generation is "a separate integration; the local record is the same source it would feed" (padi-cert-offline-poc/ARCHITECTURE.md:111-113).

Worth knowing as a lower bound on risk: today's iOS app already consumes passes. Its shared webview matches application/vnd.apple.pkpass (PDWebViewController+Helpers.swift:72-77) and presents PKAddPassesViewController (+Delegate.swift:121-136) — generically, for any PADI page that serves one. Android has no equivalent: no PayClient, no Google Wallet dependency anywhere in kms-android-padi/app/src. This is not code the unified app inherits. It is evidence that the platform hand-off is routine and that nobody hit a blocker on it.

What the unified app cannot build, at any price

A wallet pass is a signed server artefact. An .pkpass is a bundle signed with an Apple-issued Pass Type ID certificate; a Google Wallet object is a signed JWT issued against a Google Wallet API issuer account. No client can mint either. It can only receive one and present it.

Nothing in PADI's estate produces one. Searched pkpass, walletobjects and Google's save link across all eleven web repositories — account.padi.com, club.padi.com, pro.padi.com, learning.padi.com, padi.com, diviac, customer-padi and the Drupal trio: zero source matches. The only hits in the entire tree are the iOS consumer code above and a bundled MIME-type table.

So the DEP flag is right, and the dependency is precise. PADI needs, and does not have:

  • an Apple Pass Type ID certificate and a signing service, plus a Google Wallet issuer account and JWT signer
  • an endpoint that issues a pass for a given credential, and a policy for what it carries — name, level, cert number, the qrCode value already on the record, an expiry
  • pass updates — a wallet pass is a live object, so a renewed or revoked credential needs a push through APNs' pass-update channel, not a fresh download. This is the half that gets underestimated, and it is larger than issuance.

Per the SOW, Axelerant cannot close this — PADI-25.

And a second blocker the flags name

IAP. Somebody has already hit a store-policy problem here. The eCard purchase path in today's iOS app is built and deliberately switched off: the link-out to Constant.ECardBuyCertUrl (WebViewInputType.swift:130) is commented out at every call site —

  • ECardsViewControllerV2+Delegate.swift:26-31
  • CertificationDetailViewController.swift:47-52
  • ECardDetailV2ViewController+Actions.swift:52
  • AllECardsListViewController.swift:361-363, where the handler is now a print and a comment reading "Handle purchase eCard action"

— and the button is hidden even where it is still added to the view (ECardDetailV2ViewController+SetUp.swift:165-171).

Disabling a working flow rather than deleting it is what a policy problem looks like in source. The unified app will meet the same rule, and it is the same unresolved decision gating MYP-05's purchase half — PADI-7, open since April with no date. Whether a wallet pass is itself affected depends on whether PADI intends to sell the eCard or issue it with the credential, which nobody has stated — SCOPE-31.

Verdict. Correctly parked — but not for the reason the flags imply. The unified app's share of this item is small and unblocked. What is missing is a pass-issuing service PADI has not built and a commercial decision PADI has not taken. Estimating client effort here would price the cheapest part of the item.

Questions: PADI-25 (does any PADI system issue a wallet pass) · SCOPE-31 (is the eCard sold or issued) · PADI-7 (the IAP decision)


Carried forward into this area

Both are analysed in full under Logged In Experience; verdicts restated, not re-derived.

  • MYP-03 — Certifications & Digital eCard Display · W26 SPK DEP · Existing — mobile, buildable with one auth caveat. The only item in this area with a detail drawer, and the read that CERT-01 caches.
  • MYP-10 — Certification path tracker · W26 SPK DEP · Existing — web (unverified fit), requirement missing. No progression endpoint exists in either mobile app; the web-captured {PRO_API}/journey/routing/othercourses is the only candidate, and §11 of the inventory adds GET /c/credentials/{id}.

Summary

Item Verdict for the unified app Blocked on
CERT-01 Build it — POC-proven on the target stack one product decision (SCOPE-30)
CERT-05 Cannot be delivered — the app's half is small and unblocked a PADI platform build (PADI-25) and a commercial decision (SCOPE-31 / PADI-7)

One of the two is the safest thing in Q1; the other is not an engineering problem at all.

What has to be answered

  1. Does offline mean automatic, or opt-in? (SCOPE-30) Both shipped implementations disagree. Only one is what CERT-01 means, and it is flagged Now.
  2. Will PADI issue wallet passes? (PADI-25) Nothing in the estate signs one, and only PADI can hold the credentials that would.
  3. Is the eCard a product or an artefact? (SCOPE-31) The disabled purchase flow says somebody already met this question; PADI-7 has to land before it can be answered.

What this area contributes to PLT-01

The unified app needs only the read half of the shared offline foundation for certifications — durable cache, reconcile, archive-not-delete, image lifecycle. All four are implemented and unit-tested in padi-cert-offline-poc, in Expo React Native. Name that POC in the PLT-01 estimate as the reference implementation for its read path, and scope the write path from the dive-log side where it is actually needed.