@nokinc-flur/sdk 2.1.0 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -4294,7 +4294,10 @@ var ARTIFACT_TYPES = {
4294
4294
  LEDGER_JOURNAL_ENTRY: "ledger_journal_entry",
4295
4295
  STATEMENT: "statement",
4296
4296
  PASS: "pass",
4297
- IDENTITY: "identity"
4297
+ IDENTITY: "identity",
4298
+ // Tier B: holder-signed identity attestation for offline trust. The
4299
+ // envelope.iat / envelope.exp express the card's canonical lifetime.
4300
+ PAY_CARD: "pay_card"
4298
4301
  };
4299
4302
  var HexString = (length) => z17.string().regex(
4300
4303
  new RegExp(`^[0-9a-fA-F]{${length * 2}}$`),
@@ -4432,6 +4435,12 @@ var IdentityArtifactSchema = z17.object({
4432
4435
  claimValueHash: HexString(32),
4433
4436
  attestedAtMs: PositiveInt
4434
4437
  });
4438
+ var PayCardArtifactSchema = z17.object({
4439
+ userId: ShortId,
4440
+ phoneE164: z17.string().regex(/^\+[1-9]\d{7,14}$/, "phoneE164 must be normalised E.164"),
4441
+ displayName: z17.string().min(1).max(64),
4442
+ devicePubKeySpkiB64: z17.string().min(64).max(256).regex(/^[A-Za-z0-9+/]+=*$/, "devicePubKeySpkiB64 must be standard base64")
4443
+ });
4435
4444
  var ARTIFACT_BODY_SCHEMAS = {
4436
4445
  [ARTIFACT_TYPES.OFFLINE_PAYMENT_AUTHORIZATION]: OfflinePaymentAuthorizationArtifactSchema,
4437
4446
  [ARTIFACT_TYPES.RECEIPT]: ReceiptArtifactSchema,
@@ -4443,7 +4452,8 @@ var ARTIFACT_BODY_SCHEMAS = {
4443
4452
  [ARTIFACT_TYPES.LEDGER_JOURNAL_ENTRY]: LedgerJournalEntryArtifactSchema,
4444
4453
  [ARTIFACT_TYPES.STATEMENT]: StatementArtifactSchema,
4445
4454
  [ARTIFACT_TYPES.PASS]: PassArtifactSchema,
4446
- [ARTIFACT_TYPES.IDENTITY]: IdentityArtifactSchema
4455
+ [ARTIFACT_TYPES.IDENTITY]: IdentityArtifactSchema,
4456
+ [ARTIFACT_TYPES.PAY_CARD]: PayCardArtifactSchema
4447
4457
  };
4448
4458
  var HARDENED_ARTIFACT_TYPES = /* @__PURE__ */ new Set([
4449
4459
  ARTIFACT_TYPES.OFFLINE_PAYMENT_AUTHORIZATION,
@@ -4456,7 +4466,8 @@ var HARDENED_ARTIFACT_TYPES = /* @__PURE__ */ new Set([
4456
4466
  ARTIFACT_TYPES.LEDGER_JOURNAL_ENTRY,
4457
4467
  ARTIFACT_TYPES.STATEMENT,
4458
4468
  ARTIFACT_TYPES.PASS,
4459
- ARTIFACT_TYPES.IDENTITY
4469
+ ARTIFACT_TYPES.IDENTITY,
4470
+ ARTIFACT_TYPES.PAY_CARD
4460
4471
  ]);
4461
4472
  function isKnownArtifactType(t) {
4462
4473
  return Object.values(ARTIFACT_TYPES).includes(t);
@@ -4541,6 +4552,130 @@ function createOfflinePaymentAuthorizationArtifactUri(input) {
4541
4552
  type: ARTIFACT_TYPES.OFFLINE_PAYMENT_AUTHORIZATION
4542
4553
  });
4543
4554
  }
4555
+
4556
+ // src/artifacts/paycard.ts
4557
+ var PAY_CARD_DEFAULT_TTL_MS = 90 * 24 * 60 * 60 * 1e3;
4558
+ var PAY_CARD_REFRESH_THRESHOLD_MS = 30 * 24 * 60 * 60 * 1e3;
4559
+ var PAY_CARD_URI_PREFIX = `${FLUR_ARTIFACT_URI_PREFIX}${ARTIFACT_TYPES.PAY_CARD}/`;
4560
+ function createPayCardArtifactUri(input) {
4561
+ if (input.data.userId !== input.issuer) {
4562
+ throw new FlurArtifactError(
4563
+ "pay_card.data.userId must equal envelope issuer",
4564
+ "INVALID_BODY"
4565
+ );
4566
+ }
4567
+ const iat = input.issuedAtSeconds ?? Math.floor(Date.now() / 1e3);
4568
+ const exp = input.expiresAtSeconds ?? iat + Math.floor(PAY_CARD_DEFAULT_TTL_MS / 1e3);
4569
+ return createArtifactUri({
4570
+ type: ARTIFACT_TYPES.PAY_CARD,
4571
+ issuer: input.issuer,
4572
+ keyId: input.keyId,
4573
+ privateKey: input.privateKey,
4574
+ nonce: input.nonce,
4575
+ issuedAtSeconds: iat,
4576
+ expiresAtSeconds: exp,
4577
+ data: input.data
4578
+ });
4579
+ }
4580
+ function isPayCardArtifactUri(uri) {
4581
+ return typeof uri === "string" && uri.startsWith(PAY_CARD_URI_PREFIX);
4582
+ }
4583
+ function decodePayCardArtifact(uri) {
4584
+ if (!isPayCardArtifactUri(uri)) {
4585
+ throw new FlurArtifactError(
4586
+ `URI does not start with ${PAY_CARD_URI_PREFIX}`,
4587
+ "INVALID_URI"
4588
+ );
4589
+ }
4590
+ const decoded = decodeArtifactUri(uri);
4591
+ if (decoded.type !== ARTIFACT_TYPES.PAY_CARD) {
4592
+ throw new FlurArtifactError(
4593
+ `Expected pay_card, got ${decoded.type}`,
4594
+ "TYPE_MISMATCH"
4595
+ );
4596
+ }
4597
+ const parsed = PayCardArtifactSchema.safeParse(decoded.body.data);
4598
+ if (!parsed.success) {
4599
+ throw new FlurArtifactError(
4600
+ `pay_card body invalid: ${parsed.error.message}`,
4601
+ "INVALID_BODY"
4602
+ );
4603
+ }
4604
+ if (parsed.data.userId !== decoded.body.iss) {
4605
+ throw new FlurArtifactError(
4606
+ "pay_card.data.userId must equal envelope issuer",
4607
+ "INVALID_BODY"
4608
+ );
4609
+ }
4610
+ return {
4611
+ body: {
4612
+ ...decoded.body,
4613
+ data: parsed.data
4614
+ },
4615
+ sig: decoded.sig,
4616
+ decoded
4617
+ };
4618
+ }
4619
+ function verifyPayCardArtifact(uri, publicKeySpkiB64, options = {}) {
4620
+ if (!isPayCardArtifactUri(uri)) {
4621
+ throw new FlurArtifactError(
4622
+ `URI does not start with ${PAY_CARD_URI_PREFIX}`,
4623
+ "INVALID_URI"
4624
+ );
4625
+ }
4626
+ const verified = verifyArtifactUri(
4627
+ uri,
4628
+ publicKeySpkiB64,
4629
+ options
4630
+ );
4631
+ if (verified.decoded.type !== ARTIFACT_TYPES.PAY_CARD) {
4632
+ throw new FlurArtifactError(
4633
+ `Expected pay_card, got ${verified.decoded.type}`,
4634
+ "TYPE_MISMATCH"
4635
+ );
4636
+ }
4637
+ if (verified.body.data.userId !== verified.body.iss) {
4638
+ throw new FlurArtifactError(
4639
+ "pay_card.data.userId must equal envelope issuer",
4640
+ "INVALID_BODY"
4641
+ );
4642
+ }
4643
+ return {
4644
+ body: verified.body,
4645
+ sig: verified.sig,
4646
+ decoded: verified.decoded
4647
+ };
4648
+ }
4649
+ function inspectPayCardFreshness(decoded, nowMs = Date.now()) {
4650
+ const exp = decoded.body.exp;
4651
+ if (exp === void 0) return "no_expiry";
4652
+ const remainingMs = exp * 1e3 - nowMs;
4653
+ if (remainingMs <= 0) return "expired";
4654
+ if (remainingMs <= PAY_CARD_REFRESH_THRESHOLD_MS)
4655
+ return "refresh_recommended";
4656
+ return "fresh";
4657
+ }
4658
+ function buildPayCardSigningInput(input) {
4659
+ if (input.data.userId !== input.issuer) {
4660
+ throw new FlurArtifactError(
4661
+ "pay_card.data.userId must equal envelope issuer",
4662
+ "INVALID_BODY"
4663
+ );
4664
+ }
4665
+ const parsedData = PayCardArtifactSchema.parse(input.data);
4666
+ const iat = input.issuedAtSeconds ?? Math.floor(Date.now() / 1e3);
4667
+ const exp = input.expiresAtSeconds ?? iat + Math.floor(PAY_CARD_DEFAULT_TTL_MS / 1e3);
4668
+ const body = buildArtifactBody({
4669
+ type: ARTIFACT_TYPES.PAY_CARD,
4670
+ issuer: input.issuer,
4671
+ keyId: input.keyId,
4672
+ data: parsedData,
4673
+ nonce: input.nonce,
4674
+ issuedAtSeconds: iat,
4675
+ expiresAtSeconds: exp
4676
+ });
4677
+ return { body, bodyBytes: canonicalJSONBytes(body) };
4678
+ }
4544
4679
  export {
4545
4680
  ACCOUNT_FUNDED_OAC_MAX_TTL_MS,
4546
4681
  ACCOUNT_STATUSES,
@@ -4634,6 +4769,9 @@ export {
4634
4769
  PASS_STATES,
4635
4770
  PAYLOAD_FORMAT_INDICATOR_VALUE,
4636
4771
  PAYOUT_DESTINATION_STATUSES,
4772
+ PAY_CARD_DEFAULT_TTL_MS,
4773
+ PAY_CARD_REFRESH_THRESHOLD_MS,
4774
+ PAY_CARD_URI_PREFIX,
4637
4775
  POINT_OF_INITIATION,
4638
4776
  PartnerFundingEventInputSchema,
4639
4777
  PartnerFundingSchema,
@@ -4641,6 +4779,7 @@ export {
4641
4779
  PassArtifactSchema,
4642
4780
  PassMetadataSchema,
4643
4781
  PassSchema,
4782
+ PayCardArtifactSchema,
4644
4783
  PayCollectionInputSchema,
4645
4784
  PaymentClaimSchema,
4646
4785
  PaymentIntentArtifactSchema,
@@ -4679,6 +4818,7 @@ export {
4679
4818
  buildConsumerPaymentRequest,
4680
4819
  buildOAC,
4681
4820
  buildPass,
4821
+ buildPayCardSigningInput,
4682
4822
  buildPaymentRequest,
4683
4823
  buildReceipt,
4684
4824
  buildRedemption,
@@ -4712,6 +4852,7 @@ export {
4712
4852
  createPartnerFundingClient,
4713
4853
  createPartnerProfileAdminClient,
4714
4854
  createPassesClient,
4855
+ createPayCardArtifactUri,
4715
4856
  createReceiptArtifactUri,
4716
4857
  createReceiptsClient,
4717
4858
  createSoftwareP256Signer,
@@ -4721,6 +4862,7 @@ export {
4721
4862
  decodeConsumerSettlementReceiptQR,
4722
4863
  decodeOfflineClaimSmsMessage,
4723
4864
  decodeOfflineSmsSettleToken,
4865
+ decodePayCardArtifact,
4724
4866
  decodePaymentRequestQR,
4725
4867
  decodeUnverifiedConsumerSettlementReceiptQR,
4726
4868
  derToRawP256Signature,
@@ -4738,10 +4880,12 @@ export {
4738
4880
  generateDynamicQR,
4739
4881
  generateStaticQR,
4740
4882
  init,
4883
+ inspectPayCardFreshness,
4741
4884
  isConsumerPaymentRequestExpired,
4742
4885
  isHardenedArtifactType,
4743
4886
  isKnownArtifactType,
4744
4887
  isPassWithinValidity,
4888
+ isPayCardArtifactUri,
4745
4889
  moneyMinorToNumber,
4746
4890
  normalizeE164,
4747
4891
  parseAmountInput,
@@ -4769,6 +4913,7 @@ export {
4769
4913
  verifyOAC,
4770
4914
  verifyOfflineSmsSettleToken,
4771
4915
  verifyPass,
4916
+ verifyPayCardArtifact,
4772
4917
  verifyPaymentRequest,
4773
4918
  verifyReceipt,
4774
4919
  verifyRedemption,