alexandercerutti / passkit-generator

The easiest way to generate custom Apple Wallet passes in Node.js
MIT License
825 stars 104 forks source link

Supporting iOS 18 Changes #205

Open alexandercerutti opened 2 months ago

alexandercerutti commented 2 months ago

iOS 18 have been announced a few days ago and, a few hours ago, the session including the upcoming changes to Apple Wallet have been published: https://developer.apple.com/videos/play/wwdc2024/10108/

Some new fields have been published to support the new UI for events.

That said, within september, a passkit-generator update will be published. If anyone wants to attempt to generate the new passes with an iOS 18 Beta through passkit-generator, I kindly ask you to leave a comment here, so I'll know if I should publish an alpha version with some changes.

This issue will be soon updated with a summary of the changes in the schemas.

Recap from the discussion until now

alexandercerutti commented 2 months ago
nickwelsh commented 2 months ago

I'm able and willing to test if you're publishing an alpha!

alexandercerutti commented 2 months ago

@nickwelsh Okay great! I'll work on it, probably this weekend.

Before having a stable release, I'll wait for them to publish the updated documentation.

I think these are the new fields but some more could appear possibly.

P.s. Did you leave a 🌟 on the project? 👀

alexandercerutti commented 2 months ago

Schema changes are available in this branch, so you can install the package in NPM from git and build it.

I'll release a version in the next days if I have some time.

If you can successfully test, can you provide me screenshots of the results? I'm very curious!

nickwelsh commented 2 months ago

I built a minimal version using the stable build to make sure things worked:

Code

```TypeScript // index.ts import pk from "passkit-generator" import 'dotenv/config' import fs from "fs" const PKPass = pk.PKPass; try { const pass = await PKPass.from({ model: "./model.pass", certificates: { wwdr: process.env.WWDR, signerCert: process.env.CERT, signerKey: process.env.KEY, signerKeyPassphrase: process.env.CHALLENGE }, }, { // keys to be added or overridden serialNumber: "AAGH44625236dddaffbda" }); const buffer = pass.getAsBuffer(); fs.writeFile('pass.pkpass', buffer, (err) => { if (err) throw err; console.log('Buffer saved to file'); }); } catch (err) { console.error(err) } ``` ```JSON { "organizationName": "My Org", "description": "My Event Description", "teamIdentifier": "******", "passTypeIdentifier": "******", "backgroundColor": "rgb(248,252,252)", "foregroundColor": "rgb(111,162,163)", "labelColor": "rgb(0,52,68)", "formatVersion": 1, "eventTicket": { "preferredStyleSchemes": [ "posterEventTicket", "eventTicket" ] }, "semantics": { "eventType": "PKEventTypeLivePerformance", "eventName": "South Bay Jazz Festival", "eventStartDate": "2024-07-15T10:00:00-06:00", "seats": [ { "seatDescription": "Normal Seat", "seatIdentifier": "112-12-16", "seatNumber": "5", "seatRow" : "3", "seatSection": "100", "venueEntranceGate": "3" } ] } } ```

Which, indeed, builds a pass that works, obviously using the old UI. Swapping out to the alpha you provided throws an error:

error: Object schema cannot be a joi schema
      at /Users/nick/Downloads/passkit/node_modules/passkit-generator/node_modules/@hapi/hoek/lib/error.js:25:1
      at /Users/nick/Downloads/passkit/node_modules/passkit-generator/node_modules/@hapi/hoek/lib/assert.js:19:30
      at method (/Users/nick/Downloads/passkit/node_modules/passkit-generator/node_modules/joi/lib/types/keys.js:413:21)
      at method (/Users/nick/Downloads/passkit/node_modules/passkit-generator/node_modules/joi/lib/types/keys.js:323:15)
      at /Users/nick/Downloads/passkit/node_modules/passkit-generator/lib/schemas/index.js:17:1
      at require (native:1:1)
      at /Users/nick/Downloads/passkit/node_modules/passkit-generator/lib/FieldsArray.js:48:25
      at require (native:1:1)
      at /Users/nick/Downloads/passkit/node_modules/passkit-generator/lib/PKPass.js:677:50
      at require (native:1:1)
alexandercerutti commented 2 months ago

@nickwelsh Are you able to see which property failed to validate?

nickwelsh commented 2 months ago

Seems like it's the new preferredStyleSchemes or rather the newly appended object in the schema. Removing the append() allows the pass to be built, but then preferredStyleSchemes isn't part of the schema and won't be included in the created pass.json.

// schemas/index.ts
// ...
eventTicket: PassFields.disallow("transitType").append(
        Joi.object<PassProps["eventTicket"]>().keys({
            /**
             * New field coming in iOS 18
             * `"eventTicket"` is the legacy style.
             *
             * If used, passkit will try to render following the old style
             * first.
             *
             * Which means that `primaryFields`, `secondaryFields` and
             * so on, are not necessary anymore for the new style,
             * as semantics are preferred.
             */
            preferredStyleSchemes: Joi.array().items(
                Joi.string().allow("posterEventTicket", "eventTicket"),
            ),
        }),
    ),
// ...
alexandercerutti commented 2 months ago

@nickwelsh interesting. Maybe I should have used .concat instead of that .append. What happens if you replace it? I've the commit ready, just in case.

rayriffy commented 2 months ago

I tried replace with .concat, and now PKPass are able to build without crashes. Verified with pass.json payload that data actually written.

Although, I have concerns with preferredStyleSchemes field, since it not as a part of PassFields. It means that I have to override it via .props which could make type-checking a bit tricky.

CleanShot 2024-06-16 at 06 19 46

alexandercerutti commented 2 months ago

@rayriffy Hey, thanks for testing!

Two things:

1) Using .props to edit things it not the suggested way to do that as .props returns a deep clone of pass.json;

2) What Typescript says is tecnically right, eventTicket property might not exist cause your pass might not be of a type eventTicket. In a new version I could try to find a way to make it more safe, but I'm not exactly sure how. I could create and expose some Typescript narrowing guards...

Other than that, I still didn't provide a way to set manually the preferredStyleSchemes just like primaryFields and so on... maybe I should provide a just like the others.

rayriffy commented 2 months ago

thanks, although it's not a blocker though. you can make an improvements to an interface later in future version. for now i will have to forcefully mark that eventTicket actually exists.

pass.props.eventTicket!.preferredStyleSchemes = [...]

also i have another suggestion, currently i help testing your library by manually clone a project because referencing package with gtihub: in package.json does not includes any source code nor built code to use. my suggestion is in files also includes src/ directory, and make a script field prepare to run build:src should do the job

alexandercerutti commented 2 months ago

I've committed .concat and added a new getter/setter .preferredStyleSchemes to access and to set them with validation. Of course, both will throw if the type is not an eventTicket.

also i have another suggestion, currently i help testing your library by manually clone a project because referencing package with gtihub: in package.json does not includes any source code nor built code to use. my suggestion is in files also includes src/ directory, and make a script field prepare to run build:src should do the job

I never used github: protocol in NPM, but I think you can also get rid of it, as explained here and above in the same page: https://docs.npmjs.com/cli/v10/configuring-npm/package-json#github-urls

It should clone and provide the content from the repository. There, you should have the source.

Once you install the package from github, you can just change the directory to the dependency and use npm run build.

Let me know if it works.

Getting back to the pass, so, are you able to generate with with the new format?

rayriffy commented 2 months ago

unfortunately not at this moment, i tried with multiple relevant semantics fields and could not get it to work. lacking of documentation from apple is killing me, my best guess is maybe new event ticket format has not been added to the developer beta 1 yet.

maybe someone else also have a success? i would like to know as well.

CleanShot 2024-06-16 at 07 09 28

alexandercerutti commented 2 months ago

Did you try to open it on a real iPhone? Could it be it is not available on the Simulator yet?

BTW I think it is still early for the documentation to come out. It will get surely updated in the next months.

rayriffy commented 2 months ago

nah doesn't work either, i will drop my pass.json here if anyone has any insights of what's wrong

Code
{
  "formatVersion": 1,
  "passTypeIdentifier": "",
  "teamIdentifier": "",
  "serialNumber": "ahsdg2",
  "organizationName": "Creatorsgarten",
  "description": "Creatorsgarten Event Ticket",
  "foregroundColor": "rgb(255, 255, 255)",
  "backgroundColor": "rgb(0, 0, 0)",
  "labelColor": "rgb(255, 255, 255)",
  "semantics": {
    "eventName": "The โง่ Hackathon ครั้งที่ 8 แห่งประเทศ Thailand",
    "eventType": "PKEventTypeLivePerformance",
    "eventStartDate": "2024-07-13T00:00+07:00",
    "eventEndDate": "2024-07-14T23:59+07:00",
    "relevantDates": [
      {
        "startDate": "2024-07-13T08:00+07:00",
        "endDate": "2024-07-14T23:59+07:00"
      }
    ],
    "admissionLevel": "ElysiaJS"
  },
  "relevantDate": "2024-07-13T01:00:00.000Z",
  "barcodes": [
    {
      "format": "PKBarcodeFormatQR",
      "message": "QGZRQR",
      "altText": "QGZRQR",
      "messageEncoding": "iso-8859-1"
    }
  ],
  "eventTicket": {
    "headerFields": [
      {
        "key": "date",
        "label": "DATE",
        "value": "13 Jul"
      }
    ],
    "primaryFields": [
      {
        "key": "event",
        "label": "EVENT",
        "value": "The โง่ Hackathon ครั้งที่ 8 แห่งประเทศ Thailand"
      }
    ],
    "secondaryFields": [
      {
        "key": "loc",
        "label": "LOCATION",
        "value": "คณะวิศวกรรมศาสตร์ จุฬาลงกรณ์มหาวิทยาลัย"
      }
    ],
    "auxiliaryFields": [],
    "backFields": [],
    "preferredStyleSchemes": [
      "posterEventTicket",
      "eventTicket"
    ]
  }
}
alexandercerutti commented 2 months ago

@rayriffy Did you try to add the venue and seats fields in semantics, like Nick wrote above? For what I understood, they are required to render the new layout...

    "seats": [
      {
        "seatDescription": "Normal Seat",
        "seatIdentifier": "112-12-16",
        "seatNumber": "5",
        "seatRow" : "3",
        "seatSection": "100",
        "venueEntranceGate": "3"
      }
    ]

Also, I can suggest you connecting to Console.app and check if there are any logs about new things.

alexandercerutti commented 2 months ago

Let me add that someone was saying, in Apple Developers Forum, that the video was reporting the availability of some examples as downloadable resources, but it is not available under the video nor in the documentation, as opposed to the changes to Apple Pay.

I wonder if the fact this isn't working and the absence of a resource are due to the same reason, which is the lack of update in the first beta...

nickwelsh commented 2 months ago

I used the pass.json rayriffy provided to generate a pass, renamed .pkpass to .zip, extracted it, and examined the pass.json in the generated pass. It does not include the preferredStyleSchemes field. It's like it's getting stripped out when the pass is being generated, because everything else from the original pass.json is still there.

alexandercerutti commented 2 months ago

@nickwelsh Okay interesting. Did you try with the changes of the last commit (432e3804295253fe786d213ddee192a2af985ee8) or the previous one or both?

You can tell NPM to clone a specific commit id.

That's because I changed the schemas a little bit in the last commit.

rayriffy commented 2 months ago

@nickwelsh fyi i did make an minor code change to reflect alex's new getter setter update from pass.props.eventTicket!.preferredStyleSchemes = [...] to pass.preferredStyleSchemes = [...]

nickwelsh commented 2 months ago

Ah, I only had the style set in the pass.json in my model.pass. Once I explicitly added pass.preferredStyleSchemes to the js, the generated pass.json had the fields.

alexandercerutti commented 2 months ago

Ops! I forgot the possibility to import that field 😅 Last commit (dd085152515a6a2b15a84d29ee742fb9b27188ef) should include it

alexandercerutti commented 2 months ago

I proceeded adding unit tests for preferredStyleSchemes. I can confirm it gets now always added to the pass.json, wherever it comes from.

Let me know if you guys are able to generate and show a new layout event ticket.

Saim-Khan1 commented 2 months ago

Hi everyone! @alexandercerutti great to see you again haha, just thought I’d pop into the repo and leave a message about the iOS 18 Wallet updates but I can see you’re already on it! Great to see :)

@rayriffy mentioned the new event passes may not be on beta 1 - just wanted to confirm through a tweet I saw that they should be there (Apple’s WWDC invite pass updated on the beta), see: https://x.com/frederikriedel/status/1800253419304968439?s=46&t=mbu_2SzVSyE0jhQUv3QWWw

Will definitely be updating my backend and giving these changes a go once I’m free in about a week or so. Fingers crossed someone manages to get one generated and working in the meantime, but thanks a lot Alex, Nick and rayriffy for all of your testing so far :)

alexandercerutti commented 2 months ago

Hey @Saim-Khan1, glad you jumped on here!

So according to the tweet, the update could be already available in the first beta.

Perhaps only Venue data are required along with preferred schemas?

rayriffy commented 2 months ago

I tried adding venue information venueName, venueRegionName, venueLocation but doesn't work either. If WWDC pass actually proof that new layout is already added in developer beta I would like to see Apple's approach on .pkpass as well.

alexandercerutti commented 2 months ago

@rayriffy I’m asking around to folks who went to WWDC if they can share theirs with us… keep experimenting in the meantime

alexandercerutti commented 2 months ago

@rayriffy

nah doesn't work either, i will drop my pass.json here if anyone has any insights of what's wrong

I was looking again at the differences between your attempt on Simulator and your attempt on real device. On the code you show for real device, I don't see the new semantics.seats[].venueEntrance nor the whole seats structure. Perhaps that's the key?

Saim-Khan1 commented 2 months ago

I’m asking around to folks who went to WWDC if they can share theirs with us

Awesome, I think that would definitely go a long way – having a working example would be great!

alexandercerutti commented 2 months ago

I feel like the lack of secondaryLogo asset, could be a critical point, just like what happens with icon on different Apple OSs.

rayriffy commented 2 months ago

I just did both venueEntrance, seats, and secondaryLogo logo but wouldn't achive either. At this point I will also provide my exported pass here, but you've to rename file extension to .pkpass yourself. Also here's sample repo I'm currently playing with https://github.com/rayriffy/garden-pass

pkpass.zip

alexandercerutti commented 2 months ago

Thank you @rayriffy! I don't see anything wrong for what we know right now. Maybe someone else can figure out something I didn't see.

Saim-Khan1 commented 2 months ago

Fingers crossed. I'm sure Apple are already aware but I have submitted feedback (FB13947815) to the PassKit team asking for updated documentation, might be worth you guys doing so too if you haven't already – hopefully we get something by beta 2!

alexandercerutti commented 2 months ago

I had the chance to talk with a person that went to WWDC. Seems like the pass Apple issues is not sharable (probably due to "sharingProhibited": true or maybe the fact that it is an NFC pass, not sure). A "share button" is available in a place but not in another and, when tapped, seems to not do anything, so I can suspect that might be either a bug in Apple Wallet or I don't know.

There could be other ways to extract information from the pass, maybe by connecting the iPhone to Console.app, but I didn't want to bother the other person.

So, guys, I guess it is matter of waiting for the documentation and perhaps waiting for a new beta.

One last note: I fear we won't able to generate one, because it could be strictly related to NFC Passes.

Which would technically make sense, as one of the main questions I had when I saw first the new model was: how do gates for an event, get passed if you cannot scan a QRCode or such, like in the legacy model?

But the answer to my question is provided in the video, at the minute 11:07...

Just like today, you'll need your pass to be signed with the NFC entitlement in order for ticket holders to be able to use their passes for contactless entry

My hope is vanishing...

Saim-Khan1 commented 2 months ago

Ahh no! Sadly you may be right, I haven't seen a single example of the new event pass with a barcode or QR code, and you're right the NFC symbol doesn't seem to show anymore so that may well be an indicator. But, there may still be some hope since they said

Download the sample code below to see all the new pass ticketing updates in action

in the session (also mentioned on this forum post), so the fact they would (in theory, it's not actually there...) be giving us a sample pass might mean that it isn't NFC restricted, otherwise not that many devs would really be able to use it anyway??

Also in your quote they seem to be saying you need NFC entitlement for passes to enable contactless entry (which is currently the case too) but there doesn't seem to be any allusion to the new event passes being exclusive to passes with contactless entry? Unless there's something I missed

I really do hope so at least but I do think we'll just have to wait and see now with beta 2. Fingers crossed!

alexandercerutti commented 2 months ago

there doesn't seem to be any allusion to the new event passes being exclusive to passes with contactless entry?

I'm not sure, but the quote I reported is from the "Enhanced Ticket requirements" section (11:07). Unless "enhanced" is meant to be a "layer above that", but I don't think so.

The fact that they should provide an example is weird. I read it and heard it too.

Masha said:

This year we worked on improving the experience for the NFC eventTickets representing these events

So, according to this phrase, NFC is already available in eventTickets (as we noticed), but now there's a new experience for these kind of passes (NFC only).


Providing an example, however, could work: an NFC Pass with encryptionPublicKey but without anything else, especially the private key.

PassKit (the company) also has a link where it generates NFC Passes for free, but the fact the private key is missing, I guess is a big deal to make it work in a real life situation.

For the purpose of setting up passkit-generator in order to make it available for such use case, we don't care for it to work in a real life situation.

For other case, that might be a problem. Unless a working example is released, most of us will never have the chance to see it or use it IMHO.

otherwise not that many devs would really be able to use it anyway??

I don't think they really care enough. From some sources, I've heard they are very keptive in providing such authorization (NFC, I mean) and they try to find first a different way to achieve what you are trying to achieve before giving you access to resources about VAS and NFC.

So the fact that only a few developers/companies would issue it, could be only better for them.

Saim-Khan1 commented 2 months ago

Hey! I've got some more time now so just watched the session for myself (finally!) and yes I do think you're absolutely right, from what they said in the session it definitely seems as though these updates are all exclusive to NFC passes, so I assume an example pass like you described with just the public key is probably what they would have provided too.

You mentioned the company PassKit – from your experience and understanding, can anyone just go onto their service and generate an NFC pass? As in, have they, as developers, been given an NFC entitlement to allow companies etc. to generate NFC passes with their service, or do people still need to apply for their own certificate still to use their service?

If you don't mind me asking for your advice – essentially my use case (as you may well have already seen from the Firebase example we worked on) is an app to allow people to generate their own Wallet Passes on device. So if I (through a company developer account, in theory) were to apply for an NFC entitlement, do you think that would work to allow anyone to go into the app and generate their own NFC passes, in theory? Or do you think it is very much restricted to businesses etc.

I suppose if not, it may still be worth giving users the option to generate these new passes (without a private key, as you say) to, if nothing else, purely use as an event guide.

One other thing – relevantDates seems to be updated to now allow a timespan of dates, I wonder if this is only for the new event passes or if this is a thing generally?

Either way, beta 2 should be out in a couple of hours or so, so hopefully Apple will have updated the documentation and sample resources then 🤞

alexandercerutti commented 2 months ago

You mentioned the company PassKit – from your experience and understanding, can anyone just go onto their service and generate an NFC pass? As in, have they, as developers, been given an NFC entitlement to allow companies etc. to generate NFC passes with their service, or do people still need to apply for their own certificate still to use their service?

This is the page to generate an NFC Pass signed by them: https://pub1.pskt.io/38dtneICbxxjedghHHxseI Yeah, maybe an event pass with iOS 18 with their NFC signatures could be generated. You could try if you want.

If you don't mind me asking for your advice – essentially my use case (as you may well have already seen from the Firebase example we worked on) is an app to allow people to generate their own Wallet Passes on device. So if I (through a company developer account, in theory) were to apply for an NFC entitlement, do you think that would work to allow anyone to go into the app and generate their own NFC passes, in theory? Or do you think it is very much restricted to businesses etc.

I think that would work. The NFC public key should then match with terminal signature / private key I guess.

The fact that it could be reserved to business'... shouldn't be your business :P I mean, it's Apple that decides if entitlements should be provided. You, as a passkit-generator user, just need to receive it and forward it to the pass json file. But this is OT.

I suppose if not, it may still be worth giving users the option to generate these new passes (without a private key, as you say) to, if nothing else, purely use as an event guide.

I'm not very sure about what is your idea here...

I suppose if not, it may still be worth giving users the option to generate these new passes (without a private key, as you say) to, if nothing else, purely use as an event guide.

It seems to be an entirely new thing. As it is for semantics, I could guess it will be available also for other tickets, but I'm not sure yet. Could be there only for some details in the details menù shown in the video (along with map and wether).

Saim-Khan1 commented 2 months ago

This is the page to generate an NFC Pass signed by them: https://pub1.pskt.io/38dtneICbxxjedghHHxseI Yeah, maybe an event pass with iOS 18 with their NFC signatures could be generated. You could try if you want.

Oh great! May be worth giving that a go then

I think that would work. The NFC public key should then match with terminal signature / private key I guess. The fact that it could be reserved to business'... shouldn't be your business :P I mean, it's Apple that decides if entitlements should be provided. You, as a passkit-generator user, just need to receive it and forward it to the pass json file. But this is OT.

Haha no you're absolutely right, I meant more do you think Apple would give out an entitlement to a developer like us that wants to allow other people to generate NFC passes, as opposed to for one specific use case. But I suppose considering services such as PassKit exist and offer that, it may be worth applying...

I'm not very sure about what is your idea here...

As in if Apple didn't grant us an entitlement, we could generate NFC passes that don't actually work in a real-life situation, but still display the new UI? Just so that users can have access to making their own event guides etc. and the new features that come with those passes, even if the NFC aspect doesn't actually work. That was the idea anyway, I may well have misunderstood something though so if these can't be generated at all then fair enough.

It seems to be an entirely new thing. As it is for semantics, I could guess it will be available also for other tickets, but I'm not sure yet. Could be there only for some details in the details menù shown in the video (along with map and wether).

Yeah makes sense, hopefully we'll find out in just over an hour or so!

alexandercerutti commented 2 months ago

Haha no you're absolutely right, I meant more do you think Apple would give out an entitlement to a developer like us that wants to allow other people to generate NFC passes, as opposed to for one specific use case. But I suppose considering services such as PassKit exist and offer that, it may be worth applying...

I already tried in the past and they denied it to me... I don't think they are willing to provide one for OSS. Also because: can it be helpful to us? We don't have the terminals for VAS.

As in if Apple didn't grant us an entitlement, we could generate NFC passes that don't actually work in a real-life situation, but still display the new UI?

I think the UI in indipendent from the actual validity or usability of the NFC entitlement, unless they perform a some kind of local validation when an NFC pass is added.

However, using a PassKit-provided NFC signature should be fine for this purpose IMHO.

Saim-Khan1 commented 2 months ago

Makes sense, so that'll probably be the way to go then in terms of generating them for the time being. Really appreciate your insight, it's definitely helped me get a better understanding of how the NFC side of things works for Wallet passes so thanks a lot for the discussion!

Guess we may as well wait the 50 minutes or so left now until beta 2 (at least, they usually drop around then – 6pm UK time for me!) so hopefully see you then with some updated docs and resources :)

alexandercerutti commented 2 months ago

I tried to download a pass from PassKit and that surprised me. There are things that I didn't know existed.

The first that sees new things, will comment here I guess ahah

Saim-Khan1 commented 2 months ago

https://developer.apple.com/documentation/walletpasses

Still no update to the docs unfortunately 😢

alexandercerutti commented 2 months ago

@Saim-Khan1 yep...

So I think now it is just a matter of trying to generate one with the NFC signature of PassKit.

@nickwelsh @rayriffy @Saim-Khan1 do you guys have the chance to generate one?

Saim-Khan1 commented 2 months ago

Hey, was just trying to give it a go now – slightly off topic from this thread but I keep getting

Invalid data error reading pass
The passTypeIdentifier or teamIdentifier provided may not match your certificate, or the certificate trust chain could not be verified.

when trying to generate any pass, which is strange because everything was working perfectly a few months back when I was last working on the app, and I haven’t changed any certificates (and even reverted all changes to my backend after tinkering with the iOS 18 stuff) but still keep getting it.

Have you seen this kind of thing before, and if so any idea what I should do? I did try grabbing another wwdr cert but that didn’t seem to do anything

alexandercerutti commented 2 months ago

Yeah, that's OT. Check in the Generating Certificates wiki page. There's a paragraph with such a message

Saim-Khan1 commented 2 months ago

Yep thank you, all sorted now. But, unfortunately it doesn't seem to let you generate NFC passes at all, unless I'm missing something? To even generate for testing purposes...

Invalid data error reading pass. Passes with an NFC dictionary or a Personalization JSON file must be signed with an enhanced Passbook certificate.
alexandercerutti commented 2 months ago

@Saim-Khan1 you got this from Console.app? 😮

Saim-Khan1 commented 2 months ago

Yeah!

alexandercerutti commented 2 months ago

Uh, that's interesting. Never tried to generate one, but apparently there's something else we didn't consider. I even ask myself if passkit-generator supports it...