@peektravel/app-utilities 0.6.1 → 0.7.1
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/README.md +51 -50
- package/dist/index.cjs +43 -46
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +100 -84
- package/dist/index.d.ts +100 -84
- package/dist/index.js +43 -46
- package/dist/index.js.map +1 -1
- package/docs/webhooks.md +107 -128
- package/llms.txt +27 -27
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -1926,9 +1926,10 @@ declare class PeekAccessService {
|
|
|
1926
1926
|
* decoded claims.
|
|
1927
1927
|
*
|
|
1928
1928
|
* Validates the HMAC signature (using this service's `jwtSecret`), the token
|
|
1929
|
-
* expiry, the `"app_registry_v2"` issuer, and the `"Joken"` audience.
|
|
1930
|
-
*
|
|
1931
|
-
*
|
|
1929
|
+
* expiry, the `"app_registry_v2"` issuer, and the `"Joken"` audience. Pass the
|
|
1930
|
+
* raw `x-peek-auth` request header value — a leading `Bearer ` prefix, if
|
|
1931
|
+
* present, is stripped for you. Throws from the `jsonwebtoken` library on any
|
|
1932
|
+
* failure — callers should catch to distinguish error kinds:
|
|
1932
1933
|
*
|
|
1933
1934
|
* - `JsonWebTokenError` — signature invalid, wrong issuer/audience, or token
|
|
1934
1935
|
* malformed
|
|
@@ -2426,41 +2427,21 @@ interface Waiver {
|
|
|
2426
2427
|
declare function parseWaiverWebhook(payload: unknown, options?: AccessOptions): Waiver;
|
|
2427
2428
|
|
|
2428
2429
|
/**
|
|
2429
|
-
*
|
|
2430
|
+
* The clean data model for an app-store **install lifecycle event** — the single
|
|
2431
|
+
* flat object `parseInstallWebhook` returns for the webhook Peek's app registry
|
|
2432
|
+
* POSTs when an app is installed, uninstalled, or updated.
|
|
2430
2433
|
*
|
|
2431
|
-
*
|
|
2432
|
-
*
|
|
2433
|
-
*
|
|
2434
|
-
*
|
|
2435
|
-
*
|
|
2436
|
-
*
|
|
2437
|
-
*
|
|
2438
|
-
* - `JsonWebTokenError` — signature invalid, wrong issuer/audience, or malformed
|
|
2439
|
-
* - `TokenExpiredError` — past `exp`
|
|
2440
|
-
* - `NotBeforeError` — before `nbf`
|
|
2441
|
-
*
|
|
2442
|
-
* @param token the raw JWT delivered by the install webhook (no `Bearer` prefix)
|
|
2443
|
-
* @param secret the app's HMAC signing secret (the `jwtSecret` you construct
|
|
2444
|
-
* `PeekAccessService` with)
|
|
2445
|
-
* @throws {JsonWebTokenError} signature invalid or token malformed
|
|
2446
|
-
* @throws {TokenExpiredError} token has expired
|
|
2447
|
-
* @throws {NotBeforeError} token not yet valid
|
|
2448
|
-
*/
|
|
2449
|
-
declare function verifyInstallWebhook(token: string, secret: string): InstallWebhookClaims;
|
|
2450
|
-
|
|
2451
|
-
/**
|
|
2452
|
-
* The clean data model for an app-store **install lifecycle event** — the JSON
|
|
2453
|
-
* webhook body Peek's app registry POSTs when an app is installed, uninstalled,
|
|
2454
|
-
* or updated.
|
|
2455
|
-
*
|
|
2456
|
-
* This is the sibling of the signed-JWT channel behind `verifyInstallWebhook`
|
|
2457
|
-
* (see `models/peek/auth-token.ts`). The two carry the same event; this one is
|
|
2458
|
-
* the richer of the pair, because only it reports the account **name**,
|
|
2459
|
-
* **platform**, and **test** flag.
|
|
2434
|
+
* That delivery carries two things at once: a **signed `app_registry_v2` JWT**
|
|
2435
|
+
* (the security boundary) and a plain **JSON body** (the enrichment channel).
|
|
2436
|
+
* `parseInstallWebhook` verifies the JWT and merges both into this shape, so a
|
|
2437
|
+
* consumer sees one clean, flat, JSON-safe record instead of two differently
|
|
2438
|
+
* shaped payloads. The verified JWT is authoritative for the fields it carries
|
|
2439
|
+
* (`installId`, `accountId`, `status`, `displayVersion`, `user`); the JSON body
|
|
2440
|
+
* is the only source of `accountName`, `platform`, and `isTest`.
|
|
2460
2441
|
*
|
|
2461
2442
|
* It is also the single origin of the account id in the whole system: no
|
|
2462
|
-
* GraphQL read
|
|
2463
|
-
*
|
|
2443
|
+
* GraphQL read returns it, so whatever a consumer persists from this event is
|
|
2444
|
+
* all it will ever have.
|
|
2464
2445
|
*/
|
|
2465
2446
|
|
|
2466
2447
|
/**
|
|
@@ -2471,21 +2452,27 @@ declare const INSTALL_STATUSES: readonly ["installed", "uninstalled", "update_in
|
|
|
2471
2452
|
/** Install lifecycle status. */
|
|
2472
2453
|
type InstallStatus = (typeof INSTALL_STATUSES)[number];
|
|
2473
2454
|
/**
|
|
2474
|
-
*
|
|
2455
|
+
* A verified install lifecycle event — what happened, to which install, and who
|
|
2456
|
+
* (if anyone) triggered it — as one flat, JSON-safe record.
|
|
2457
|
+
*
|
|
2458
|
+
* This is the shape `parseInstallWebhook` returns. It is flat by design: it
|
|
2459
|
+
* round-trips through a datastore unchanged, so the same shape the parser
|
|
2460
|
+
* returns is the shape a consumer persists and later rehydrates. There is
|
|
2461
|
+
* deliberately no nested identity object and no second representation.
|
|
2475
2462
|
*
|
|
2476
|
-
*
|
|
2477
|
-
*
|
|
2478
|
-
*
|
|
2463
|
+
* Fields sourced from the **verified JWT** (`installId`, `accountId`, `status`,
|
|
2464
|
+
* `rawStatus`, `displayVersion`, `user`) are trustworthy; the enrichment fields
|
|
2465
|
+
* (`accountName`, `platform`, `isTest`) come from the unauthenticated JSON body.
|
|
2479
2466
|
*/
|
|
2480
|
-
interface
|
|
2481
|
-
/** Install ID — Peek-assigned UUID. Also the subject
|
|
2467
|
+
interface InstallWebhook {
|
|
2468
|
+
/** Install ID — Peek-assigned UUID. Also the JWT subject (`sub`). */
|
|
2482
2469
|
installId: string;
|
|
2483
2470
|
/**
|
|
2484
2471
|
* Stable Peek account id — the same value Peek calls the **partner ID**.
|
|
2485
2472
|
* This event is its only source; it cannot be re-fetched later.
|
|
2486
2473
|
*/
|
|
2487
2474
|
accountId: string;
|
|
2488
|
-
/** Partner display name. */
|
|
2475
|
+
/** Partner display name. `""` when the JSON body omits it. */
|
|
2489
2476
|
accountName: string;
|
|
2490
2477
|
/**
|
|
2491
2478
|
* Which Peek platform owns the install, or `null` when the registry reported
|
|
@@ -2503,9 +2490,6 @@ interface InstallIdentity {
|
|
|
2503
2490
|
platform: PeekPlatform | null;
|
|
2504
2491
|
/** Whether this is a test account. Defaults to `false` when not reported. */
|
|
2505
2492
|
isTest: boolean;
|
|
2506
|
-
}
|
|
2507
|
-
/** A parsed install lifecycle event: what happened, to which install. */
|
|
2508
|
-
interface InstallEvent {
|
|
2509
2493
|
/**
|
|
2510
2494
|
* The lifecycle status, or `null` when the registry sent a status this
|
|
2511
2495
|
* version of the package does not know. Handle `null` explicitly — treating
|
|
@@ -2516,59 +2500,91 @@ interface InstallEvent {
|
|
|
2516
2500
|
rawStatus: string;
|
|
2517
2501
|
/** App display version at the time of the event. */
|
|
2518
2502
|
displayVersion: string;
|
|
2519
|
-
/**
|
|
2520
|
-
|
|
2503
|
+
/**
|
|
2504
|
+
* The user that triggered the event, or `null` for system-initiated events
|
|
2505
|
+
* (install lifecycle changes are often system-initiated). From the JWT.
|
|
2506
|
+
*/
|
|
2507
|
+
user: PeekAuthTokenUser | null;
|
|
2521
2508
|
}
|
|
2522
2509
|
|
|
2523
2510
|
/**
|
|
2524
|
-
*
|
|
2525
|
-
*
|
|
2511
|
+
* Verifies an install-status webhook token and merges it with the delivered
|
|
2512
|
+
* JSON body into one flat {@link InstallWebhook}.
|
|
2526
2513
|
*
|
|
2527
|
-
*
|
|
2528
|
-
* `
|
|
2529
|
-
*
|
|
2530
|
-
*
|
|
2531
|
-
*
|
|
2514
|
+
* The **verified token** is the authoritative source of `installId`,
|
|
2515
|
+
* `accountId`, `status`, `displayVersion`, and `user`. The **JSON body** — which
|
|
2516
|
+
* is not signed and so is trusted only for fields the token cannot carry —
|
|
2517
|
+
* supplies `accountName`, `platform`, and `isTest`. A missing or malformed body
|
|
2518
|
+
* degrades those three to `""`/`null`/`false`; it never overrides an
|
|
2519
|
+
* authenticated field and never throws.
|
|
2532
2520
|
*
|
|
2533
|
-
*
|
|
2534
|
-
*
|
|
2535
|
-
*
|
|
2536
|
-
*
|
|
2537
|
-
*
|
|
2538
|
-
* **It never throws.** The sender is first-party and the payload contract is
|
|
2539
|
-
* Peek's own, so defending against malformed input would be defending against a
|
|
2540
|
-
* case that does not arise. What the parser does guard is the contract
|
|
2541
|
-
* *growing*: an unrecognised `status` or `platform` surfaces as `null` rather
|
|
2542
|
-
* than being coerced into a known value, so a newer registry can never be
|
|
2543
|
-
* silently mistaken for an older one.
|
|
2544
|
-
*/
|
|
2545
|
-
|
|
2546
|
-
/**
|
|
2547
|
-
* Parses a delivered install-event webhook body into a clean
|
|
2548
|
-
* {@link InstallEvent}.
|
|
2521
|
+
* Signature verification is strict: the HMAC signature (with `secret`), the
|
|
2522
|
+
* token expiry, the `"app_registry_v2"` issuer, and the `"Joken"` audience are
|
|
2523
|
+
* all checked — the same checks as {@link PeekAccessService.verifyPeekAuthToken}.
|
|
2524
|
+
* Any failure throws from the `jsonwebtoken` library, so callers can branch on
|
|
2525
|
+
* the error kind:
|
|
2549
2526
|
*
|
|
2550
|
-
*
|
|
2551
|
-
*
|
|
2552
|
-
* `
|
|
2527
|
+
* - `JsonWebTokenError` — signature invalid, wrong issuer/audience, or malformed
|
|
2528
|
+
* - `TokenExpiredError` — past `exp`
|
|
2529
|
+
* - `NotBeforeError` — before `nbf`
|
|
2553
2530
|
*
|
|
2554
|
-
*
|
|
2555
|
-
*
|
|
2556
|
-
* not
|
|
2531
|
+
* An unrecognised `status` or `platform` maps to `null` (with the wire status
|
|
2532
|
+
* preserved on {@link InstallWebhook.rawStatus}) rather than being coerced —
|
|
2533
|
+
* Peek treats any 2xx as delivered and does not redeliver, so handle a `null`
|
|
2534
|
+
* `status` explicitly:
|
|
2557
2535
|
*
|
|
2558
2536
|
* ```ts
|
|
2559
|
-
* const event =
|
|
2537
|
+
* const event = parseInstallWebhook(token, req.body, secret);
|
|
2560
2538
|
* switch (event.status) {
|
|
2561
|
-
* case "installed": return provision(event
|
|
2562
|
-
* case "uninstalled": return deprovision(event
|
|
2563
|
-
* case "update_installed": return recordVersion(event
|
|
2539
|
+
* case "installed": return provision(event);
|
|
2540
|
+
* case "uninstalled": return deprovision(event);
|
|
2541
|
+
* case "update_installed": return recordVersion(event);
|
|
2564
2542
|
* default: throw new Error(`unknown install status: ${event.rawStatus}`);
|
|
2565
2543
|
* }
|
|
2566
2544
|
* ```
|
|
2567
2545
|
*
|
|
2568
|
-
*
|
|
2569
|
-
*
|
|
2546
|
+
* @param token the JWT delivered by the install webhook. Pass the raw
|
|
2547
|
+
* `x-peek-auth` header value directly — a leading `Bearer ` prefix, if
|
|
2548
|
+
* present, is stripped for you.
|
|
2549
|
+
* @param body the delivered JSON body (raw object or a JSON string)
|
|
2550
|
+
* @param secret the app's HMAC signing secret (the `jwtSecret` you construct
|
|
2551
|
+
* `PeekAccessService` with)
|
|
2552
|
+
* @throws {JsonWebTokenError} signature invalid or token malformed
|
|
2553
|
+
* @throws {TokenExpiredError} token has expired
|
|
2554
|
+
* @throws {NotBeforeError} token not yet valid
|
|
2570
2555
|
*/
|
|
2571
|
-
declare function
|
|
2556
|
+
declare function parseInstallWebhook(token: string, body: unknown, secret: string): InstallWebhook;
|
|
2557
|
+
/**
|
|
2558
|
+
* Verifies an install-status webhook token and returns its clean claims.
|
|
2559
|
+
*
|
|
2560
|
+
* @deprecated Use {@link parseInstallWebhook} instead. This verifier reads only
|
|
2561
|
+
* the signed token, so it cannot report the account **name**, **platform**, or
|
|
2562
|
+
* **test** flag that the webhook's JSON body also carries — the caller was left
|
|
2563
|
+
* to parse that body separately and stitch the two shapes together.
|
|
2564
|
+
* `parseInstallWebhook(token, body, secret)` verifies the same token and returns
|
|
2565
|
+
* one flat {@link InstallWebhook} with every field. This function remains only
|
|
2566
|
+
* for backwards compatibility.
|
|
2567
|
+
*
|
|
2568
|
+
* Validates the HMAC signature (with `secret`), the token expiry, the
|
|
2569
|
+
* `"app_registry_v2"` issuer, and the `"Joken"` audience — the same checks as
|
|
2570
|
+
* {@link PeekAccessService.verifyPeekAuthToken} — then maps the payload to
|
|
2571
|
+
* {@link InstallWebhookClaims}, tolerating a `null` `user` (system events).
|
|
2572
|
+
* Throws from the `jsonwebtoken` library on any verification failure:
|
|
2573
|
+
*
|
|
2574
|
+
* - `JsonWebTokenError` — signature invalid, wrong issuer/audience, or malformed
|
|
2575
|
+
* - `TokenExpiredError` — past `exp`
|
|
2576
|
+
* - `NotBeforeError` — before `nbf`
|
|
2577
|
+
*
|
|
2578
|
+
* @param token the JWT delivered by the install webhook. Pass the raw
|
|
2579
|
+
* `x-peek-auth` header value directly — a leading `Bearer ` prefix, if
|
|
2580
|
+
* present, is stripped for you.
|
|
2581
|
+
* @param secret the app's HMAC signing secret (the `jwtSecret` you construct
|
|
2582
|
+
* `PeekAccessService` with)
|
|
2583
|
+
* @throws {JsonWebTokenError} signature invalid or token malformed
|
|
2584
|
+
* @throws {TokenExpiredError} token has expired
|
|
2585
|
+
* @throws {NotBeforeError} token not yet valid
|
|
2586
|
+
*/
|
|
2587
|
+
declare function verifyInstallWebhook(token: string, secret: string): InstallWebhookClaims;
|
|
2572
2588
|
|
|
2573
2589
|
/**
|
|
2574
2590
|
* Typed errors thrown by the package. Each mirrors a failure mode of the Peek
|
|
@@ -2681,4 +2697,4 @@ declare class AcmeApiError extends Error {
|
|
|
2681
2697
|
constructor(statusCode: number, body: unknown, message?: string);
|
|
2682
2698
|
}
|
|
2683
2699
|
|
|
2684
|
-
export { ACTIVITY_PRODUCT_TYPE, ADD_ON_PRODUCT_TYPE, type AccessOptions, type AccountUser, AccountUserService, type AccountUserServiceOptions, AcmeAccessService, type AcmeAccessServiceConfig, type AcmeActivity, type AcmeActivityTicket, AcmeApiError, AcmeProductService, type Activity, type ActivityOverrides, type ActivityTicket, type AddAddonInput, AdminAccountRequiredError, type Agent, type AssignGuideResult, type AssignedActivity, type AssignedResource, type Availability, AvailabilityService, type AvailabilityTime, type AvailabilityTimesQuery, type Booking, type BookingAddon, type BookingAddonMoney, type BookingAddonOption, type BookingAddons, type BookingAddonsMutationResult, type BookingPaymentsOnFile, type BookingReadOptions, type BookingSearchBy, BookingService, type BookingServiceOptions, type BookingTimeRangeSearch, type CancelBookingResult, type Channel, type ClearOverridesInput, CngAccessService, type CngAccessServiceConfig, CngApiError, CngProductService, type CreateBookingGuest, type CreateBookingInput, type CreateBookingTicket, type CreateEngineInput, type CreatePromoCodeInput, type CreatedBooking, type CreatedPricingEngine, type CreatedPromoCode, type CustomQuestionAnswer, type DailyNote, DailyNoteService, type Duration, type Guest, type GuestMetadata, type Guide, type GuideAssignment, INSTALL_STATUSES, type
|
|
2700
|
+
export { ACTIVITY_PRODUCT_TYPE, ADD_ON_PRODUCT_TYPE, type AccessOptions, type AccountUser, AccountUserService, type AccountUserServiceOptions, AcmeAccessService, type AcmeAccessServiceConfig, type AcmeActivity, type AcmeActivityTicket, AcmeApiError, AcmeProductService, type Activity, type ActivityOverrides, type ActivityTicket, type AddAddonInput, AdminAccountRequiredError, type Agent, type AssignGuideResult, type AssignedActivity, type AssignedResource, type Availability, AvailabilityService, type AvailabilityTime, type AvailabilityTimesQuery, type Booking, type BookingAddon, type BookingAddonMoney, type BookingAddonOption, type BookingAddons, type BookingAddonsMutationResult, type BookingPaymentsOnFile, type BookingReadOptions, type BookingSearchBy, BookingService, type BookingServiceOptions, type BookingTimeRangeSearch, type CancelBookingResult, type Channel, type ClearOverridesInput, CngAccessService, type CngAccessServiceConfig, CngApiError, CngProductService, type CreateBookingGuest, type CreateBookingInput, type CreateBookingTicket, type CreateEngineInput, type CreatePromoCodeInput, type CreatedBooking, type CreatedPricingEngine, type CreatedPromoCode, type CustomQuestionAnswer, type DailyNote, DailyNoteService, type Duration, type Guest, type GuestMetadata, type Guide, type GuideAssignment, INSTALL_STATUSES, type InstallStatus, type InstallWebhook, type InstallWebhookAccount, type InstallWebhookClaims, InvalidPeekTokenError, type InvoiceLinkResult, type Logger, type MakePaymentInput, type MakePaymentResult, type Membership, type MembershipPurchaseInput, MembershipService, type NoteMode, type Payment, type PaymentSource, PeekAccessService, type PeekAccessServiceConfig, type PeekAuthTokenClaims, type PeekAuthTokenUser, PeekGraphQLError, PeekHttpError, type PeekPlatform, PiiAccessDisabledError, type Price, type PricingActivityContext, type PricingEngine, type PricingMoney, type PricingNamedRef, type PricingOverride, type PricingOverrideFilter, PricingService, type Product, type ProductMeetingLocation, ProductService, type ProductServiceOptions, type ProductTicket, type PromoCode, type PromoCodeFixedAmount, PromoCodeService, type PromoCodeServiceOptions, type PurchasedMembership, RENTAL_PRODUCT_TYPE, RateLimitError, type RefundInput, type RefundResult, ResellerService, type ResolvedOverride, type ResolvedPricingOverride, type ResolvedResourceOption, type Resource, type ResourceOptionOverride, type ResourceOptionQuantity, type ResourcePool, type ResourcePoolAccountUser, type ResourcePoolAssignment, type ResourcePoolMode, ResourcePoolService, type Review, ReviewService, type Ticket, type Timeslot, type TimeslotFilter, TimeslotService, type UpdateEngineInput, type UpdateTimeslotResult, type UpsertOverridesInput, type UpsertOverridesResult, type Waiver, noopLogger, parseBookingWebhook, parseInstallWebhook, parseWaiverWebhook, verifyInstallWebhook };
|
package/dist/index.d.ts
CHANGED
|
@@ -1926,9 +1926,10 @@ declare class PeekAccessService {
|
|
|
1926
1926
|
* decoded claims.
|
|
1927
1927
|
*
|
|
1928
1928
|
* Validates the HMAC signature (using this service's `jwtSecret`), the token
|
|
1929
|
-
* expiry, the `"app_registry_v2"` issuer, and the `"Joken"` audience.
|
|
1930
|
-
*
|
|
1931
|
-
*
|
|
1929
|
+
* expiry, the `"app_registry_v2"` issuer, and the `"Joken"` audience. Pass the
|
|
1930
|
+
* raw `x-peek-auth` request header value — a leading `Bearer ` prefix, if
|
|
1931
|
+
* present, is stripped for you. Throws from the `jsonwebtoken` library on any
|
|
1932
|
+
* failure — callers should catch to distinguish error kinds:
|
|
1932
1933
|
*
|
|
1933
1934
|
* - `JsonWebTokenError` — signature invalid, wrong issuer/audience, or token
|
|
1934
1935
|
* malformed
|
|
@@ -2426,41 +2427,21 @@ interface Waiver {
|
|
|
2426
2427
|
declare function parseWaiverWebhook(payload: unknown, options?: AccessOptions): Waiver;
|
|
2427
2428
|
|
|
2428
2429
|
/**
|
|
2429
|
-
*
|
|
2430
|
+
* The clean data model for an app-store **install lifecycle event** — the single
|
|
2431
|
+
* flat object `parseInstallWebhook` returns for the webhook Peek's app registry
|
|
2432
|
+
* POSTs when an app is installed, uninstalled, or updated.
|
|
2430
2433
|
*
|
|
2431
|
-
*
|
|
2432
|
-
*
|
|
2433
|
-
*
|
|
2434
|
-
*
|
|
2435
|
-
*
|
|
2436
|
-
*
|
|
2437
|
-
*
|
|
2438
|
-
* - `JsonWebTokenError` — signature invalid, wrong issuer/audience, or malformed
|
|
2439
|
-
* - `TokenExpiredError` — past `exp`
|
|
2440
|
-
* - `NotBeforeError` — before `nbf`
|
|
2441
|
-
*
|
|
2442
|
-
* @param token the raw JWT delivered by the install webhook (no `Bearer` prefix)
|
|
2443
|
-
* @param secret the app's HMAC signing secret (the `jwtSecret` you construct
|
|
2444
|
-
* `PeekAccessService` with)
|
|
2445
|
-
* @throws {JsonWebTokenError} signature invalid or token malformed
|
|
2446
|
-
* @throws {TokenExpiredError} token has expired
|
|
2447
|
-
* @throws {NotBeforeError} token not yet valid
|
|
2448
|
-
*/
|
|
2449
|
-
declare function verifyInstallWebhook(token: string, secret: string): InstallWebhookClaims;
|
|
2450
|
-
|
|
2451
|
-
/**
|
|
2452
|
-
* The clean data model for an app-store **install lifecycle event** — the JSON
|
|
2453
|
-
* webhook body Peek's app registry POSTs when an app is installed, uninstalled,
|
|
2454
|
-
* or updated.
|
|
2455
|
-
*
|
|
2456
|
-
* This is the sibling of the signed-JWT channel behind `verifyInstallWebhook`
|
|
2457
|
-
* (see `models/peek/auth-token.ts`). The two carry the same event; this one is
|
|
2458
|
-
* the richer of the pair, because only it reports the account **name**,
|
|
2459
|
-
* **platform**, and **test** flag.
|
|
2434
|
+
* That delivery carries two things at once: a **signed `app_registry_v2` JWT**
|
|
2435
|
+
* (the security boundary) and a plain **JSON body** (the enrichment channel).
|
|
2436
|
+
* `parseInstallWebhook` verifies the JWT and merges both into this shape, so a
|
|
2437
|
+
* consumer sees one clean, flat, JSON-safe record instead of two differently
|
|
2438
|
+
* shaped payloads. The verified JWT is authoritative for the fields it carries
|
|
2439
|
+
* (`installId`, `accountId`, `status`, `displayVersion`, `user`); the JSON body
|
|
2440
|
+
* is the only source of `accountName`, `platform`, and `isTest`.
|
|
2460
2441
|
*
|
|
2461
2442
|
* It is also the single origin of the account id in the whole system: no
|
|
2462
|
-
* GraphQL read
|
|
2463
|
-
*
|
|
2443
|
+
* GraphQL read returns it, so whatever a consumer persists from this event is
|
|
2444
|
+
* all it will ever have.
|
|
2464
2445
|
*/
|
|
2465
2446
|
|
|
2466
2447
|
/**
|
|
@@ -2471,21 +2452,27 @@ declare const INSTALL_STATUSES: readonly ["installed", "uninstalled", "update_in
|
|
|
2471
2452
|
/** Install lifecycle status. */
|
|
2472
2453
|
type InstallStatus = (typeof INSTALL_STATUSES)[number];
|
|
2473
2454
|
/**
|
|
2474
|
-
*
|
|
2455
|
+
* A verified install lifecycle event — what happened, to which install, and who
|
|
2456
|
+
* (if anyone) triggered it — as one flat, JSON-safe record.
|
|
2457
|
+
*
|
|
2458
|
+
* This is the shape `parseInstallWebhook` returns. It is flat by design: it
|
|
2459
|
+
* round-trips through a datastore unchanged, so the same shape the parser
|
|
2460
|
+
* returns is the shape a consumer persists and later rehydrates. There is
|
|
2461
|
+
* deliberately no nested identity object and no second representation.
|
|
2475
2462
|
*
|
|
2476
|
-
*
|
|
2477
|
-
*
|
|
2478
|
-
*
|
|
2463
|
+
* Fields sourced from the **verified JWT** (`installId`, `accountId`, `status`,
|
|
2464
|
+
* `rawStatus`, `displayVersion`, `user`) are trustworthy; the enrichment fields
|
|
2465
|
+
* (`accountName`, `platform`, `isTest`) come from the unauthenticated JSON body.
|
|
2479
2466
|
*/
|
|
2480
|
-
interface
|
|
2481
|
-
/** Install ID — Peek-assigned UUID. Also the subject
|
|
2467
|
+
interface InstallWebhook {
|
|
2468
|
+
/** Install ID — Peek-assigned UUID. Also the JWT subject (`sub`). */
|
|
2482
2469
|
installId: string;
|
|
2483
2470
|
/**
|
|
2484
2471
|
* Stable Peek account id — the same value Peek calls the **partner ID**.
|
|
2485
2472
|
* This event is its only source; it cannot be re-fetched later.
|
|
2486
2473
|
*/
|
|
2487
2474
|
accountId: string;
|
|
2488
|
-
/** Partner display name. */
|
|
2475
|
+
/** Partner display name. `""` when the JSON body omits it. */
|
|
2489
2476
|
accountName: string;
|
|
2490
2477
|
/**
|
|
2491
2478
|
* Which Peek platform owns the install, or `null` when the registry reported
|
|
@@ -2503,9 +2490,6 @@ interface InstallIdentity {
|
|
|
2503
2490
|
platform: PeekPlatform | null;
|
|
2504
2491
|
/** Whether this is a test account. Defaults to `false` when not reported. */
|
|
2505
2492
|
isTest: boolean;
|
|
2506
|
-
}
|
|
2507
|
-
/** A parsed install lifecycle event: what happened, to which install. */
|
|
2508
|
-
interface InstallEvent {
|
|
2509
2493
|
/**
|
|
2510
2494
|
* The lifecycle status, or `null` when the registry sent a status this
|
|
2511
2495
|
* version of the package does not know. Handle `null` explicitly — treating
|
|
@@ -2516,59 +2500,91 @@ interface InstallEvent {
|
|
|
2516
2500
|
rawStatus: string;
|
|
2517
2501
|
/** App display version at the time of the event. */
|
|
2518
2502
|
displayVersion: string;
|
|
2519
|
-
/**
|
|
2520
|
-
|
|
2503
|
+
/**
|
|
2504
|
+
* The user that triggered the event, or `null` for system-initiated events
|
|
2505
|
+
* (install lifecycle changes are often system-initiated). From the JWT.
|
|
2506
|
+
*/
|
|
2507
|
+
user: PeekAuthTokenUser | null;
|
|
2521
2508
|
}
|
|
2522
2509
|
|
|
2523
2510
|
/**
|
|
2524
|
-
*
|
|
2525
|
-
*
|
|
2511
|
+
* Verifies an install-status webhook token and merges it with the delivered
|
|
2512
|
+
* JSON body into one flat {@link InstallWebhook}.
|
|
2526
2513
|
*
|
|
2527
|
-
*
|
|
2528
|
-
* `
|
|
2529
|
-
*
|
|
2530
|
-
*
|
|
2531
|
-
*
|
|
2514
|
+
* The **verified token** is the authoritative source of `installId`,
|
|
2515
|
+
* `accountId`, `status`, `displayVersion`, and `user`. The **JSON body** — which
|
|
2516
|
+
* is not signed and so is trusted only for fields the token cannot carry —
|
|
2517
|
+
* supplies `accountName`, `platform`, and `isTest`. A missing or malformed body
|
|
2518
|
+
* degrades those three to `""`/`null`/`false`; it never overrides an
|
|
2519
|
+
* authenticated field and never throws.
|
|
2532
2520
|
*
|
|
2533
|
-
*
|
|
2534
|
-
*
|
|
2535
|
-
*
|
|
2536
|
-
*
|
|
2537
|
-
*
|
|
2538
|
-
* **It never throws.** The sender is first-party and the payload contract is
|
|
2539
|
-
* Peek's own, so defending against malformed input would be defending against a
|
|
2540
|
-
* case that does not arise. What the parser does guard is the contract
|
|
2541
|
-
* *growing*: an unrecognised `status` or `platform` surfaces as `null` rather
|
|
2542
|
-
* than being coerced into a known value, so a newer registry can never be
|
|
2543
|
-
* silently mistaken for an older one.
|
|
2544
|
-
*/
|
|
2545
|
-
|
|
2546
|
-
/**
|
|
2547
|
-
* Parses a delivered install-event webhook body into a clean
|
|
2548
|
-
* {@link InstallEvent}.
|
|
2521
|
+
* Signature verification is strict: the HMAC signature (with `secret`), the
|
|
2522
|
+
* token expiry, the `"app_registry_v2"` issuer, and the `"Joken"` audience are
|
|
2523
|
+
* all checked — the same checks as {@link PeekAccessService.verifyPeekAuthToken}.
|
|
2524
|
+
* Any failure throws from the `jsonwebtoken` library, so callers can branch on
|
|
2525
|
+
* the error kind:
|
|
2549
2526
|
*
|
|
2550
|
-
*
|
|
2551
|
-
*
|
|
2552
|
-
* `
|
|
2527
|
+
* - `JsonWebTokenError` — signature invalid, wrong issuer/audience, or malformed
|
|
2528
|
+
* - `TokenExpiredError` — past `exp`
|
|
2529
|
+
* - `NotBeforeError` — before `nbf`
|
|
2553
2530
|
*
|
|
2554
|
-
*
|
|
2555
|
-
*
|
|
2556
|
-
* not
|
|
2531
|
+
* An unrecognised `status` or `platform` maps to `null` (with the wire status
|
|
2532
|
+
* preserved on {@link InstallWebhook.rawStatus}) rather than being coerced —
|
|
2533
|
+
* Peek treats any 2xx as delivered and does not redeliver, so handle a `null`
|
|
2534
|
+
* `status` explicitly:
|
|
2557
2535
|
*
|
|
2558
2536
|
* ```ts
|
|
2559
|
-
* const event =
|
|
2537
|
+
* const event = parseInstallWebhook(token, req.body, secret);
|
|
2560
2538
|
* switch (event.status) {
|
|
2561
|
-
* case "installed": return provision(event
|
|
2562
|
-
* case "uninstalled": return deprovision(event
|
|
2563
|
-
* case "update_installed": return recordVersion(event
|
|
2539
|
+
* case "installed": return provision(event);
|
|
2540
|
+
* case "uninstalled": return deprovision(event);
|
|
2541
|
+
* case "update_installed": return recordVersion(event);
|
|
2564
2542
|
* default: throw new Error(`unknown install status: ${event.rawStatus}`);
|
|
2565
2543
|
* }
|
|
2566
2544
|
* ```
|
|
2567
2545
|
*
|
|
2568
|
-
*
|
|
2569
|
-
*
|
|
2546
|
+
* @param token the JWT delivered by the install webhook. Pass the raw
|
|
2547
|
+
* `x-peek-auth` header value directly — a leading `Bearer ` prefix, if
|
|
2548
|
+
* present, is stripped for you.
|
|
2549
|
+
* @param body the delivered JSON body (raw object or a JSON string)
|
|
2550
|
+
* @param secret the app's HMAC signing secret (the `jwtSecret` you construct
|
|
2551
|
+
* `PeekAccessService` with)
|
|
2552
|
+
* @throws {JsonWebTokenError} signature invalid or token malformed
|
|
2553
|
+
* @throws {TokenExpiredError} token has expired
|
|
2554
|
+
* @throws {NotBeforeError} token not yet valid
|
|
2570
2555
|
*/
|
|
2571
|
-
declare function
|
|
2556
|
+
declare function parseInstallWebhook(token: string, body: unknown, secret: string): InstallWebhook;
|
|
2557
|
+
/**
|
|
2558
|
+
* Verifies an install-status webhook token and returns its clean claims.
|
|
2559
|
+
*
|
|
2560
|
+
* @deprecated Use {@link parseInstallWebhook} instead. This verifier reads only
|
|
2561
|
+
* the signed token, so it cannot report the account **name**, **platform**, or
|
|
2562
|
+
* **test** flag that the webhook's JSON body also carries — the caller was left
|
|
2563
|
+
* to parse that body separately and stitch the two shapes together.
|
|
2564
|
+
* `parseInstallWebhook(token, body, secret)` verifies the same token and returns
|
|
2565
|
+
* one flat {@link InstallWebhook} with every field. This function remains only
|
|
2566
|
+
* for backwards compatibility.
|
|
2567
|
+
*
|
|
2568
|
+
* Validates the HMAC signature (with `secret`), the token expiry, the
|
|
2569
|
+
* `"app_registry_v2"` issuer, and the `"Joken"` audience — the same checks as
|
|
2570
|
+
* {@link PeekAccessService.verifyPeekAuthToken} — then maps the payload to
|
|
2571
|
+
* {@link InstallWebhookClaims}, tolerating a `null` `user` (system events).
|
|
2572
|
+
* Throws from the `jsonwebtoken` library on any verification failure:
|
|
2573
|
+
*
|
|
2574
|
+
* - `JsonWebTokenError` — signature invalid, wrong issuer/audience, or malformed
|
|
2575
|
+
* - `TokenExpiredError` — past `exp`
|
|
2576
|
+
* - `NotBeforeError` — before `nbf`
|
|
2577
|
+
*
|
|
2578
|
+
* @param token the JWT delivered by the install webhook. Pass the raw
|
|
2579
|
+
* `x-peek-auth` header value directly — a leading `Bearer ` prefix, if
|
|
2580
|
+
* present, is stripped for you.
|
|
2581
|
+
* @param secret the app's HMAC signing secret (the `jwtSecret` you construct
|
|
2582
|
+
* `PeekAccessService` with)
|
|
2583
|
+
* @throws {JsonWebTokenError} signature invalid or token malformed
|
|
2584
|
+
* @throws {TokenExpiredError} token has expired
|
|
2585
|
+
* @throws {NotBeforeError} token not yet valid
|
|
2586
|
+
*/
|
|
2587
|
+
declare function verifyInstallWebhook(token: string, secret: string): InstallWebhookClaims;
|
|
2572
2588
|
|
|
2573
2589
|
/**
|
|
2574
2590
|
* Typed errors thrown by the package. Each mirrors a failure mode of the Peek
|
|
@@ -2681,4 +2697,4 @@ declare class AcmeApiError extends Error {
|
|
|
2681
2697
|
constructor(statusCode: number, body: unknown, message?: string);
|
|
2682
2698
|
}
|
|
2683
2699
|
|
|
2684
|
-
export { ACTIVITY_PRODUCT_TYPE, ADD_ON_PRODUCT_TYPE, type AccessOptions, type AccountUser, AccountUserService, type AccountUserServiceOptions, AcmeAccessService, type AcmeAccessServiceConfig, type AcmeActivity, type AcmeActivityTicket, AcmeApiError, AcmeProductService, type Activity, type ActivityOverrides, type ActivityTicket, type AddAddonInput, AdminAccountRequiredError, type Agent, type AssignGuideResult, type AssignedActivity, type AssignedResource, type Availability, AvailabilityService, type AvailabilityTime, type AvailabilityTimesQuery, type Booking, type BookingAddon, type BookingAddonMoney, type BookingAddonOption, type BookingAddons, type BookingAddonsMutationResult, type BookingPaymentsOnFile, type BookingReadOptions, type BookingSearchBy, BookingService, type BookingServiceOptions, type BookingTimeRangeSearch, type CancelBookingResult, type Channel, type ClearOverridesInput, CngAccessService, type CngAccessServiceConfig, CngApiError, CngProductService, type CreateBookingGuest, type CreateBookingInput, type CreateBookingTicket, type CreateEngineInput, type CreatePromoCodeInput, type CreatedBooking, type CreatedPricingEngine, type CreatedPromoCode, type CustomQuestionAnswer, type DailyNote, DailyNoteService, type Duration, type Guest, type GuestMetadata, type Guide, type GuideAssignment, INSTALL_STATUSES, type
|
|
2700
|
+
export { ACTIVITY_PRODUCT_TYPE, ADD_ON_PRODUCT_TYPE, type AccessOptions, type AccountUser, AccountUserService, type AccountUserServiceOptions, AcmeAccessService, type AcmeAccessServiceConfig, type AcmeActivity, type AcmeActivityTicket, AcmeApiError, AcmeProductService, type Activity, type ActivityOverrides, type ActivityTicket, type AddAddonInput, AdminAccountRequiredError, type Agent, type AssignGuideResult, type AssignedActivity, type AssignedResource, type Availability, AvailabilityService, type AvailabilityTime, type AvailabilityTimesQuery, type Booking, type BookingAddon, type BookingAddonMoney, type BookingAddonOption, type BookingAddons, type BookingAddonsMutationResult, type BookingPaymentsOnFile, type BookingReadOptions, type BookingSearchBy, BookingService, type BookingServiceOptions, type BookingTimeRangeSearch, type CancelBookingResult, type Channel, type ClearOverridesInput, CngAccessService, type CngAccessServiceConfig, CngApiError, CngProductService, type CreateBookingGuest, type CreateBookingInput, type CreateBookingTicket, type CreateEngineInput, type CreatePromoCodeInput, type CreatedBooking, type CreatedPricingEngine, type CreatedPromoCode, type CustomQuestionAnswer, type DailyNote, DailyNoteService, type Duration, type Guest, type GuestMetadata, type Guide, type GuideAssignment, INSTALL_STATUSES, type InstallStatus, type InstallWebhook, type InstallWebhookAccount, type InstallWebhookClaims, InvalidPeekTokenError, type InvoiceLinkResult, type Logger, type MakePaymentInput, type MakePaymentResult, type Membership, type MembershipPurchaseInput, MembershipService, type NoteMode, type Payment, type PaymentSource, PeekAccessService, type PeekAccessServiceConfig, type PeekAuthTokenClaims, type PeekAuthTokenUser, PeekGraphQLError, PeekHttpError, type PeekPlatform, PiiAccessDisabledError, type Price, type PricingActivityContext, type PricingEngine, type PricingMoney, type PricingNamedRef, type PricingOverride, type PricingOverrideFilter, PricingService, type Product, type ProductMeetingLocation, ProductService, type ProductServiceOptions, type ProductTicket, type PromoCode, type PromoCodeFixedAmount, PromoCodeService, type PromoCodeServiceOptions, type PurchasedMembership, RENTAL_PRODUCT_TYPE, RateLimitError, type RefundInput, type RefundResult, ResellerService, type ResolvedOverride, type ResolvedPricingOverride, type ResolvedResourceOption, type Resource, type ResourceOptionOverride, type ResourceOptionQuantity, type ResourcePool, type ResourcePoolAccountUser, type ResourcePoolAssignment, type ResourcePoolMode, ResourcePoolService, type Review, ReviewService, type Ticket, type Timeslot, type TimeslotFilter, TimeslotService, type UpdateEngineInput, type UpdateTimeslotResult, type UpsertOverridesInput, type UpsertOverridesResult, type Waiver, noopLogger, parseBookingWebhook, parseInstallWebhook, parseWaiverWebhook, verifyInstallWebhook };
|