@voyantjs/bookings 0.9.0 → 0.11.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.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/markets-ref.d.ts +151 -0
- package/dist/markets-ref.d.ts.map +1 -0
- package/dist/markets-ref.js +19 -0
- package/dist/pii-redaction.d.ts +89 -0
- package/dist/pii-redaction.d.ts.map +1 -0
- package/dist/pii-redaction.js +120 -0
- package/dist/pii.d.ts +1 -0
- package/dist/pii.d.ts.map +1 -1
- package/dist/pii.js +20 -1
- package/dist/routes-groups.d.ts +3 -2
- package/dist/routes-groups.d.ts.map +1 -1
- package/dist/routes-public.d.ts +11 -13
- package/dist/routes-public.d.ts.map +1 -1
- package/dist/routes-public.js +3 -3
- package/dist/routes.d.ts +232 -22
- package/dist/routes.d.ts.map +1 -1
- package/dist/routes.js +100 -24
- package/dist/schema/travel-details.d.ts +37 -0
- package/dist/schema/travel-details.d.ts.map +1 -1
- package/dist/schema/travel-details.js +6 -0
- package/dist/schema-core.d.ts +17 -17
- package/dist/schema-core.d.ts.map +1 -1
- package/dist/schema-core.js +8 -2
- package/dist/schema-items.d.ts.map +1 -1
- package/dist/schema-items.js +6 -1
- package/dist/schema-operations.d.ts +2 -2
- package/dist/schema-shared.d.ts +1 -1
- package/dist/schema-shared.d.ts.map +1 -1
- package/dist/schema-shared.js +3 -0
- package/dist/service-public.d.ts +0 -6
- package/dist/service-public.d.ts.map +1 -1
- package/dist/service-public.js +0 -4
- package/dist/service.d.ts +232 -56
- package/dist/service.d.ts.map +1 -1
- package/dist/service.js +469 -137
- package/dist/state-machine.d.ts +29 -0
- package/dist/state-machine.d.ts.map +1 -0
- package/dist/state-machine.js +39 -0
- package/dist/validation-public.d.ts +0 -6
- package/dist/validation-public.d.ts.map +1 -1
- package/dist/validation-public.js +0 -2
- package/dist/validation.d.ts +25 -16
- package/dist/validation.d.ts.map +1 -1
- package/dist/validation.js +17 -6
- package/dist/workflows/refund-booking.d.ts +87 -0
- package/dist/workflows/refund-booking.d.ts.map +1 -0
- package/dist/workflows/refund-booking.js +210 -0
- package/package.json +7 -6
package/dist/index.d.ts
CHANGED
|
@@ -2,9 +2,11 @@ import type { LinkableDefinition, Module } from "@voyantjs/core";
|
|
|
2
2
|
import type { HonoModule } from "@voyantjs/hono/module";
|
|
3
3
|
export { bookingsSupplierExtension } from "./extensions/suppliers.js";
|
|
4
4
|
export { type BookingPiiAuditEvent, type BookingPiiService, type BookingPiiServiceOptions, createBookingPiiService, type UpsertBookingTravelerTravelDetailInput, } from "./pii.js";
|
|
5
|
+
export { type PiiAccessContext, redactBookingContact, redactEmail, redactPhone, redactString, redactTravelerIdentity, shouldRevealBookingPii, } from "./pii-redaction.js";
|
|
5
6
|
export type { ConvertProductData } from "./service.js";
|
|
6
7
|
export { bookingsService } from "./service.js";
|
|
7
8
|
export { type AddBookingGroupMemberInput, type BookingGroupListQuery, type BookingGroupMemberWithBooking, bookingGroupsService, type CreateBookingGroupInput, listGroupBookingTravelers, type UpdateBookingGroupInput, } from "./service-groups.js";
|
|
9
|
+
export type { BookingStatus } from "./state-machine.js";
|
|
8
10
|
export { type ExpireStaleBookingHoldsInput, type ExpireStaleBookingHoldsResult, expireStaleBookingHolds, } from "./tasks/index.js";
|
|
9
11
|
export declare const bookingLinkable: LinkableDefinition;
|
|
10
12
|
export declare const bookingsLinkable: {
|
|
@@ -23,5 +25,5 @@ export { bookingTravelerDietarySchema, bookingTravelerIdentitySchema, bookingTra
|
|
|
23
25
|
export type { Booking, BookingActivity, BookingAllocation, BookingDocument, BookingFulfillment, BookingGroup, BookingGroupMember, BookingItem, BookingItemTraveler, BookingNote, BookingPiiAccessLog, BookingRedemptionEvent, BookingSessionState, BookingStaffAssignment, BookingSupplierStatus, BookingTraveler, NewBooking, NewBookingActivity, NewBookingAllocation, NewBookingDocument, NewBookingFulfillment, NewBookingGroup, NewBookingGroupMember, NewBookingItem, NewBookingItemTraveler, NewBookingNote, NewBookingPiiAccessLog, NewBookingRedemptionEvent, NewBookingSessionState, NewBookingStaffAssignment, NewBookingSupplierStatus, NewBookingTraveler, } from "./schema.js";
|
|
24
26
|
export { bookingActivityLog, bookingAllocations, bookingDocuments, bookingFulfillments, bookingGroupKindEnum, bookingGroupMemberRoleEnum, bookingGroupMembers, bookingGroups, bookingItems, bookingItemTravelers, bookingNotes, bookingPiiAccessLog, bookingRedemptionEvents, bookingSessionStates, bookingStaffAssignments, bookingSupplierStatuses, bookings, bookingTravelers, } from "./schema.js";
|
|
25
27
|
export { publicBookingsService, resolveSessionPricingSnapshot } from "./service-public.js";
|
|
26
|
-
export { addBookingGroupMemberSchema, bookingGroupKindSchema, bookingGroupListQuerySchema, bookingGroupMemberRoleSchema, bookingListQuerySchema, cancelBookingSchema, confirmBookingSchema, convertProductSchema, createBookingSchema, expireBookingSchema, expireStaleBookingsSchema, extendBookingHoldSchema, insertBookingAllocationSchema, insertBookingDocumentSchema, insertBookingFulfillmentSchema, insertBookingGroupSchema, insertBookingItemSchema, insertBookingItemTravelerSchema, insertBookingNoteSchema, insertBookingSchema, insertBookingTravelerDocumentSchema, insertSupplierStatusSchema, insertTravelerSchema, internalBookingOverviewLookupQuerySchema, pricingPreviewSchema, publicBookingOverviewLookupQuerySchema, publicBookingSessionMutationSchema, publicBookingSessionRepriceItemSchema, publicBookingSessionRepriceResultSchema, publicBookingSessionRepriceSummarySchema, publicBookingSessionStateSchema, publicCreateBookingSessionSchema, publicRepriceBookingSessionSchema, publicUpdateBookingSessionSchema, publicUpsertBookingSessionStateSchema, recordBookingRedemptionSchema, reserveBookingFromTransactionSchema, reserveBookingSchema, updateBookingAllocationSchema, updateBookingFulfillmentSchema, updateBookingGroupSchema, updateBookingItemSchema, updateBookingSchema,
|
|
28
|
+
export { addBookingGroupMemberSchema, bookingGroupKindSchema, bookingGroupListQuerySchema, bookingGroupMemberRoleSchema, bookingListQuerySchema, cancelBookingSchema, completeBookingSchema, confirmBookingSchema, convertProductSchema, createBookingSchema, expireBookingSchema, expireStaleBookingsSchema, extendBookingHoldSchema, insertBookingAllocationSchema, insertBookingDocumentSchema, insertBookingFulfillmentSchema, insertBookingGroupSchema, insertBookingItemSchema, insertBookingItemTravelerSchema, insertBookingNoteSchema, insertBookingSchema, insertBookingTravelerDocumentSchema, insertSupplierStatusSchema, insertTravelerSchema, internalBookingOverviewLookupQuerySchema, overrideBookingStatusSchema, pricingPreviewSchema, publicBookingOverviewLookupQuerySchema, publicBookingSessionMutationSchema, publicBookingSessionRepriceItemSchema, publicBookingSessionRepriceResultSchema, publicBookingSessionRepriceSummarySchema, publicBookingSessionStateSchema, publicCreateBookingSessionSchema, publicRepriceBookingSessionSchema, publicUpdateBookingSessionSchema, publicUpsertBookingSessionStateSchema, recordBookingRedemptionSchema, reserveBookingFromTransactionSchema, reserveBookingSchema, startBookingSchema, updateBookingAllocationSchema, updateBookingFulfillmentSchema, updateBookingGroupSchema, updateBookingItemSchema, updateBookingSchema, updateSupplierStatusSchema, updateTravelerSchema, upsertTravelerTravelDetailsSchema, } from "./validation.js";
|
|
27
29
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -3,6 +3,7 @@ import { bookingRoutes } from "./routes.js";
|
|
|
3
3
|
import { publicBookingRoutes } from "./routes-public.js";
|
|
4
4
|
export { bookingsSupplierExtension } from "./extensions/suppliers.js";
|
|
5
5
|
export { createBookingPiiService, } from "./pii.js";
|
|
6
|
+
export { redactBookingContact, redactEmail, redactPhone, redactString, redactTravelerIdentity, shouldRevealBookingPii, } from "./pii-redaction.js";
|
|
6
7
|
export { bookingsService } from "./service.js";
|
|
7
8
|
export { bookingGroupsService, listGroupBookingTravelers, } from "./service-groups.js";
|
|
8
9
|
export { expireStaleBookingHolds, } from "./tasks/index.js";
|
|
@@ -39,4 +40,4 @@ export { publicBookingRoutes } from "./routes-public.js";
|
|
|
39
40
|
export { bookingTravelerDietarySchema, bookingTravelerIdentitySchema, bookingTravelerTravelDetailInsertSchema, bookingTravelerTravelDetailSelectSchema, bookingTravelerTravelDetails, bookingTravelerTravelDetailUpdateSchema, decryptedBookingTravelerTravelDetailSchema, } from "./schema/travel-details.js";
|
|
40
41
|
export { bookingActivityLog, bookingAllocations, bookingDocuments, bookingFulfillments, bookingGroupKindEnum, bookingGroupMemberRoleEnum, bookingGroupMembers, bookingGroups, bookingItems, bookingItemTravelers, bookingNotes, bookingPiiAccessLog, bookingRedemptionEvents, bookingSessionStates, bookingStaffAssignments, bookingSupplierStatuses, bookings, bookingTravelers, } from "./schema.js";
|
|
41
42
|
export { publicBookingsService, resolveSessionPricingSnapshot } from "./service-public.js";
|
|
42
|
-
export { addBookingGroupMemberSchema, bookingGroupKindSchema, bookingGroupListQuerySchema, bookingGroupMemberRoleSchema, bookingListQuerySchema, cancelBookingSchema, confirmBookingSchema, convertProductSchema, createBookingSchema, expireBookingSchema, expireStaleBookingsSchema, extendBookingHoldSchema, insertBookingAllocationSchema, insertBookingDocumentSchema, insertBookingFulfillmentSchema, insertBookingGroupSchema, insertBookingItemSchema, insertBookingItemTravelerSchema, insertBookingNoteSchema, insertBookingSchema, insertBookingTravelerDocumentSchema, insertSupplierStatusSchema, insertTravelerSchema, internalBookingOverviewLookupQuerySchema, pricingPreviewSchema, publicBookingOverviewLookupQuerySchema, publicBookingSessionMutationSchema, publicBookingSessionRepriceItemSchema, publicBookingSessionRepriceResultSchema, publicBookingSessionRepriceSummarySchema, publicBookingSessionStateSchema, publicCreateBookingSessionSchema, publicRepriceBookingSessionSchema, publicUpdateBookingSessionSchema, publicUpsertBookingSessionStateSchema, recordBookingRedemptionSchema, reserveBookingFromTransactionSchema, reserveBookingSchema, updateBookingAllocationSchema, updateBookingFulfillmentSchema, updateBookingGroupSchema, updateBookingItemSchema, updateBookingSchema,
|
|
43
|
+
export { addBookingGroupMemberSchema, bookingGroupKindSchema, bookingGroupListQuerySchema, bookingGroupMemberRoleSchema, bookingListQuerySchema, cancelBookingSchema, completeBookingSchema, confirmBookingSchema, convertProductSchema, createBookingSchema, expireBookingSchema, expireStaleBookingsSchema, extendBookingHoldSchema, insertBookingAllocationSchema, insertBookingDocumentSchema, insertBookingFulfillmentSchema, insertBookingGroupSchema, insertBookingItemSchema, insertBookingItemTravelerSchema, insertBookingNoteSchema, insertBookingSchema, insertBookingTravelerDocumentSchema, insertSupplierStatusSchema, insertTravelerSchema, internalBookingOverviewLookupQuerySchema, overrideBookingStatusSchema, pricingPreviewSchema, publicBookingOverviewLookupQuerySchema, publicBookingSessionMutationSchema, publicBookingSessionRepriceItemSchema, publicBookingSessionRepriceResultSchema, publicBookingSessionRepriceSummarySchema, publicBookingSessionStateSchema, publicCreateBookingSessionSchema, publicRepriceBookingSessionSchema, publicUpdateBookingSessionSchema, publicUpsertBookingSessionStateSchema, recordBookingRedemptionSchema, reserveBookingFromTransactionSchema, reserveBookingSchema, startBookingSchema, updateBookingAllocationSchema, updateBookingFulfillmentSchema, updateBookingGroupSchema, updateBookingItemSchema, updateBookingSchema, updateSupplierStatusSchema, updateTravelerSchema, upsertTravelerTravelDetailsSchema, } from "./validation.js";
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Local reference to `markets.exchange_rates`. Bookings reads this
|
|
3
|
+
* table to convert per-item totals into the booking's base currency,
|
|
4
|
+
* but doesn't pull the markets package as a hard dep — the FK rule
|
|
5
|
+
* (intra-domain FKs OK, cross-domain MUST use plain text + links)
|
|
6
|
+
* means we mirror the columns we need with a `Ref`.
|
|
7
|
+
*/
|
|
8
|
+
export declare const exchangeRatesRef: import("drizzle-orm/pg-core").PgTableWithColumns<{
|
|
9
|
+
name: "exchange_rates";
|
|
10
|
+
schema: undefined;
|
|
11
|
+
columns: {
|
|
12
|
+
id: import("drizzle-orm/pg-core").PgColumn<{
|
|
13
|
+
name: string;
|
|
14
|
+
tableName: "exchange_rates";
|
|
15
|
+
dataType: "string";
|
|
16
|
+
columnType: "PgText";
|
|
17
|
+
data: string;
|
|
18
|
+
driverParam: string;
|
|
19
|
+
notNull: true;
|
|
20
|
+
hasDefault: true;
|
|
21
|
+
isPrimaryKey: true;
|
|
22
|
+
isAutoincrement: false;
|
|
23
|
+
hasRuntimeDefault: true;
|
|
24
|
+
enumValues: [string, ...string[]];
|
|
25
|
+
baseColumn: never;
|
|
26
|
+
identity: undefined;
|
|
27
|
+
generated: undefined;
|
|
28
|
+
}, {}, {}>;
|
|
29
|
+
fxRateSetId: import("drizzle-orm/pg-core").PgColumn<{
|
|
30
|
+
name: string;
|
|
31
|
+
tableName: "exchange_rates";
|
|
32
|
+
dataType: "string";
|
|
33
|
+
columnType: "PgText";
|
|
34
|
+
data: string;
|
|
35
|
+
driverParam: string;
|
|
36
|
+
notNull: true;
|
|
37
|
+
hasDefault: false;
|
|
38
|
+
isPrimaryKey: false;
|
|
39
|
+
isAutoincrement: false;
|
|
40
|
+
hasRuntimeDefault: false;
|
|
41
|
+
enumValues: [string, ...string[]];
|
|
42
|
+
baseColumn: never;
|
|
43
|
+
identity: undefined;
|
|
44
|
+
generated: undefined;
|
|
45
|
+
}, {}, {}>;
|
|
46
|
+
baseCurrency: import("drizzle-orm/pg-core").PgColumn<{
|
|
47
|
+
name: "base_currency";
|
|
48
|
+
tableName: "exchange_rates";
|
|
49
|
+
dataType: "string";
|
|
50
|
+
columnType: "PgText";
|
|
51
|
+
data: string;
|
|
52
|
+
driverParam: string;
|
|
53
|
+
notNull: true;
|
|
54
|
+
hasDefault: false;
|
|
55
|
+
isPrimaryKey: false;
|
|
56
|
+
isAutoincrement: false;
|
|
57
|
+
hasRuntimeDefault: false;
|
|
58
|
+
enumValues: [string, ...string[]];
|
|
59
|
+
baseColumn: never;
|
|
60
|
+
identity: undefined;
|
|
61
|
+
generated: undefined;
|
|
62
|
+
}, {}, {}>;
|
|
63
|
+
quoteCurrency: import("drizzle-orm/pg-core").PgColumn<{
|
|
64
|
+
name: "quote_currency";
|
|
65
|
+
tableName: "exchange_rates";
|
|
66
|
+
dataType: "string";
|
|
67
|
+
columnType: "PgText";
|
|
68
|
+
data: string;
|
|
69
|
+
driverParam: string;
|
|
70
|
+
notNull: true;
|
|
71
|
+
hasDefault: false;
|
|
72
|
+
isPrimaryKey: false;
|
|
73
|
+
isAutoincrement: false;
|
|
74
|
+
hasRuntimeDefault: false;
|
|
75
|
+
enumValues: [string, ...string[]];
|
|
76
|
+
baseColumn: never;
|
|
77
|
+
identity: undefined;
|
|
78
|
+
generated: undefined;
|
|
79
|
+
}, {}, {}>;
|
|
80
|
+
rateDecimal: import("drizzle-orm/pg-core").PgColumn<{
|
|
81
|
+
name: "rate_decimal";
|
|
82
|
+
tableName: "exchange_rates";
|
|
83
|
+
dataType: "string";
|
|
84
|
+
columnType: "PgNumeric";
|
|
85
|
+
data: string;
|
|
86
|
+
driverParam: string;
|
|
87
|
+
notNull: true;
|
|
88
|
+
hasDefault: false;
|
|
89
|
+
isPrimaryKey: false;
|
|
90
|
+
isAutoincrement: false;
|
|
91
|
+
hasRuntimeDefault: false;
|
|
92
|
+
enumValues: undefined;
|
|
93
|
+
baseColumn: never;
|
|
94
|
+
identity: undefined;
|
|
95
|
+
generated: undefined;
|
|
96
|
+
}, {}, {}>;
|
|
97
|
+
inverseRateDecimal: import("drizzle-orm/pg-core").PgColumn<{
|
|
98
|
+
name: "inverse_rate_decimal";
|
|
99
|
+
tableName: "exchange_rates";
|
|
100
|
+
dataType: "string";
|
|
101
|
+
columnType: "PgNumeric";
|
|
102
|
+
data: string;
|
|
103
|
+
driverParam: string;
|
|
104
|
+
notNull: false;
|
|
105
|
+
hasDefault: false;
|
|
106
|
+
isPrimaryKey: false;
|
|
107
|
+
isAutoincrement: false;
|
|
108
|
+
hasRuntimeDefault: false;
|
|
109
|
+
enumValues: undefined;
|
|
110
|
+
baseColumn: never;
|
|
111
|
+
identity: undefined;
|
|
112
|
+
generated: undefined;
|
|
113
|
+
}, {}, {}>;
|
|
114
|
+
observedAt: import("drizzle-orm/pg-core").PgColumn<{
|
|
115
|
+
name: "observed_at";
|
|
116
|
+
tableName: "exchange_rates";
|
|
117
|
+
dataType: "date";
|
|
118
|
+
columnType: "PgTimestamp";
|
|
119
|
+
data: Date;
|
|
120
|
+
driverParam: string;
|
|
121
|
+
notNull: false;
|
|
122
|
+
hasDefault: false;
|
|
123
|
+
isPrimaryKey: false;
|
|
124
|
+
isAutoincrement: false;
|
|
125
|
+
hasRuntimeDefault: false;
|
|
126
|
+
enumValues: undefined;
|
|
127
|
+
baseColumn: never;
|
|
128
|
+
identity: undefined;
|
|
129
|
+
generated: undefined;
|
|
130
|
+
}, {}, {}>;
|
|
131
|
+
createdAt: import("drizzle-orm/pg-core").PgColumn<{
|
|
132
|
+
name: "created_at";
|
|
133
|
+
tableName: "exchange_rates";
|
|
134
|
+
dataType: "date";
|
|
135
|
+
columnType: "PgTimestamp";
|
|
136
|
+
data: Date;
|
|
137
|
+
driverParam: string;
|
|
138
|
+
notNull: true;
|
|
139
|
+
hasDefault: false;
|
|
140
|
+
isPrimaryKey: false;
|
|
141
|
+
isAutoincrement: false;
|
|
142
|
+
hasRuntimeDefault: false;
|
|
143
|
+
enumValues: undefined;
|
|
144
|
+
baseColumn: never;
|
|
145
|
+
identity: undefined;
|
|
146
|
+
generated: undefined;
|
|
147
|
+
}, {}, {}>;
|
|
148
|
+
};
|
|
149
|
+
dialect: "pg";
|
|
150
|
+
}>;
|
|
151
|
+
//# sourceMappingURL=markets-ref.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markets-ref.d.ts","sourceRoot":"","sources":["../src/markets-ref.ts"],"names":[],"mappings":"AAGA;;;;;;GAMG;AACH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAS3B,CAAA"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { typeId, typeIdRef } from "@voyantjs/db/lib/typeid-column";
|
|
2
|
+
import { numeric, pgTable, text, timestamp } from "drizzle-orm/pg-core";
|
|
3
|
+
/**
|
|
4
|
+
* Local reference to `markets.exchange_rates`. Bookings reads this
|
|
5
|
+
* table to convert per-item totals into the booking's base currency,
|
|
6
|
+
* but doesn't pull the markets package as a hard dep — the FK rule
|
|
7
|
+
* (intra-domain FKs OK, cross-domain MUST use plain text + links)
|
|
8
|
+
* means we mirror the columns we need with a `Ref`.
|
|
9
|
+
*/
|
|
10
|
+
export const exchangeRatesRef = pgTable("exchange_rates", {
|
|
11
|
+
id: typeId("exchange_rates").primaryKey(),
|
|
12
|
+
fxRateSetId: typeIdRef("fx_rate_set_id").notNull(),
|
|
13
|
+
baseCurrency: text("base_currency").notNull(),
|
|
14
|
+
quoteCurrency: text("quote_currency").notNull(),
|
|
15
|
+
rateDecimal: numeric("rate_decimal", { precision: 18, scale: 8 }).notNull(),
|
|
16
|
+
inverseRateDecimal: numeric("inverse_rate_decimal", { precision: 18, scale: 8 }),
|
|
17
|
+
observedAt: timestamp("observed_at", { withTimezone: true }),
|
|
18
|
+
createdAt: timestamp("created_at", { withTimezone: true }).notNull(),
|
|
19
|
+
});
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Booking PII redaction.
|
|
3
|
+
*
|
|
4
|
+
* Booking rows and traveler rows store contact identifiers (name, email,
|
|
5
|
+
* phone) as plaintext columns so the operator UI can search and sort. The
|
|
6
|
+
* `bookings-pii:*` scope (or `*` superuser scope) gates the right to see
|
|
7
|
+
* those identifiers verbatim. Callers without that scope receive a redacted
|
|
8
|
+
* shape that retains enough signal for operational triage but not enough to
|
|
9
|
+
* exfiltrate a full contact list.
|
|
10
|
+
*
|
|
11
|
+
* **Scope of this module:** route-layer redaction at the API boundary.
|
|
12
|
+
* Internal callers (cron jobs, workflows, in-process tasks) bypass redaction
|
|
13
|
+
* because they need the full record to do their job.
|
|
14
|
+
*
|
|
15
|
+
* **What this does NOT do:** encrypt the columns at rest. That is a
|
|
16
|
+
* follow-up requiring a schema migration + a search-tokenisation strategy
|
|
17
|
+
* (see issue #283 follow-up). For now plaintext-on-disk + redact-in-flight
|
|
18
|
+
* is the documented posture.
|
|
19
|
+
*/
|
|
20
|
+
export interface PiiAccessContext {
|
|
21
|
+
actor?: string | null;
|
|
22
|
+
scopes?: string[] | null;
|
|
23
|
+
callerType?: string | null;
|
|
24
|
+
isInternalRequest?: boolean;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Returns true when the caller has earned the right to see PII in the clear.
|
|
28
|
+
*
|
|
29
|
+
* Internal requests (server-to-server inside the trust boundary) and API
|
|
30
|
+
* keys with explicit `bookings-pii:read` scope (or superuser `*`) reveal.
|
|
31
|
+
* Plain staff sessions WITHOUT the scope do NOT reveal — staff are
|
|
32
|
+
* authorised to see *some* booking data but not necessarily the contact
|
|
33
|
+
* identifiers. This makes "give the new agent a read-only role" safe by
|
|
34
|
+
* default; granting `bookings-pii:read` is an explicit decision.
|
|
35
|
+
*/
|
|
36
|
+
export declare function shouldRevealBookingPii(ctx: PiiAccessContext): boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Mask the local-part of an email, preserving the domain so the operator
|
|
39
|
+
* can tell at a glance which provider is involved.
|
|
40
|
+
*
|
|
41
|
+
* `alice@example.com` → `a***e@example.com`
|
|
42
|
+
* `bo@example.com` → `**@example.com`
|
|
43
|
+
*/
|
|
44
|
+
export declare function redactEmail(email: string | null | undefined): string | null;
|
|
45
|
+
/**
|
|
46
|
+
* Mask all but the last four digits of a phone number, dropping
|
|
47
|
+
* non-digit characters from the masked region so the result is recognisable
|
|
48
|
+
* as a phone fragment.
|
|
49
|
+
*
|
|
50
|
+
* `+40 712 345 678` → `***5678`
|
|
51
|
+
*/
|
|
52
|
+
export declare function redactPhone(phone: string | null | undefined): string | null;
|
|
53
|
+
/**
|
|
54
|
+
* Masks an arbitrary identifier like a postal address or city to a single-
|
|
55
|
+
* char marker. We keep the field present so client schemas don't break,
|
|
56
|
+
* but the value is effectively absent.
|
|
57
|
+
*/
|
|
58
|
+
export declare function redactString(value: string | null | undefined): string | null;
|
|
59
|
+
/**
|
|
60
|
+
* Booking row contact-PII redaction. Returns a shallow copy with the
|
|
61
|
+
* `contact*` columns masked. Caller is responsible for not running this on
|
|
62
|
+
* already-redacted rows.
|
|
63
|
+
*/
|
|
64
|
+
export declare function redactBookingContact<T extends {
|
|
65
|
+
contactFirstName?: string | null;
|
|
66
|
+
contactLastName?: string | null;
|
|
67
|
+
contactEmail?: string | null;
|
|
68
|
+
contactPhone?: string | null;
|
|
69
|
+
contactAddressLine1?: string | null;
|
|
70
|
+
contactPostalCode?: string | null;
|
|
71
|
+
}>(row: T): T;
|
|
72
|
+
/**
|
|
73
|
+
* Traveler row redaction. Same shape as `redactBookingContact` but for
|
|
74
|
+
* traveler identity columns.
|
|
75
|
+
*
|
|
76
|
+
* `accessibilityNeeds` is intentionally NOT in the redacted set — it was
|
|
77
|
+
* moved to the encrypted `bookingTravelerTravelDetails` table (#283) and
|
|
78
|
+
* is only ever returned through `createBookingPiiService` after
|
|
79
|
+
* decryption + audit. It's never present on this row shape.
|
|
80
|
+
*/
|
|
81
|
+
export declare function redactTravelerIdentity<T extends {
|
|
82
|
+
firstName?: string | null;
|
|
83
|
+
lastName?: string | null;
|
|
84
|
+
email?: string | null;
|
|
85
|
+
phone?: string | null;
|
|
86
|
+
specialRequests?: string | null;
|
|
87
|
+
notes?: string | null;
|
|
88
|
+
}>(row: T): T;
|
|
89
|
+
//# sourceMappingURL=pii-redaction.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pii-redaction.d.ts","sourceRoot":"","sources":["../src/pii-redaction.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAMH,MAAM,WAAW,gBAAgB;IAC/B,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,MAAM,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAA;IACxB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,iBAAiB,CAAC,EAAE,OAAO,CAAA;CAC5B;AAED;;;;;;;;;GASG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,gBAAgB,GAAG,OAAO,CAQrE;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAQ3E;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAK3E;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAG5E;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,CAAC,SAAS;IACR,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAChC,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC/B,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5B,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5B,mBAAmB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACnC,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAClC,EACD,GAAG,EAAE,CAAC,GAAG,CAAC,CAUX;AAED;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CACpC,CAAC,SAAS;IACR,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC/B,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CACtB,EACD,GAAG,EAAE,CAAC,GAAG,CAAC,CAUX"}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Booking PII redaction.
|
|
3
|
+
*
|
|
4
|
+
* Booking rows and traveler rows store contact identifiers (name, email,
|
|
5
|
+
* phone) as plaintext columns so the operator UI can search and sort. The
|
|
6
|
+
* `bookings-pii:*` scope (or `*` superuser scope) gates the right to see
|
|
7
|
+
* those identifiers verbatim. Callers without that scope receive a redacted
|
|
8
|
+
* shape that retains enough signal for operational triage but not enough to
|
|
9
|
+
* exfiltrate a full contact list.
|
|
10
|
+
*
|
|
11
|
+
* **Scope of this module:** route-layer redaction at the API boundary.
|
|
12
|
+
* Internal callers (cron jobs, workflows, in-process tasks) bypass redaction
|
|
13
|
+
* because they need the full record to do their job.
|
|
14
|
+
*
|
|
15
|
+
* **What this does NOT do:** encrypt the columns at rest. That is a
|
|
16
|
+
* follow-up requiring a schema migration + a search-tokenisation strategy
|
|
17
|
+
* (see issue #283 follow-up). For now plaintext-on-disk + redact-in-flight
|
|
18
|
+
* is the documented posture.
|
|
19
|
+
*/
|
|
20
|
+
const PII_SCOPE_ANY = "bookings-pii:*";
|
|
21
|
+
const PII_SCOPE_READ = "bookings-pii:read";
|
|
22
|
+
const SUPERUSER_SCOPE = "*";
|
|
23
|
+
/**
|
|
24
|
+
* Returns true when the caller has earned the right to see PII in the clear.
|
|
25
|
+
*
|
|
26
|
+
* Internal requests (server-to-server inside the trust boundary) and API
|
|
27
|
+
* keys with explicit `bookings-pii:read` scope (or superuser `*`) reveal.
|
|
28
|
+
* Plain staff sessions WITHOUT the scope do NOT reveal — staff are
|
|
29
|
+
* authorised to see *some* booking data but not necessarily the contact
|
|
30
|
+
* identifiers. This makes "give the new agent a read-only role" safe by
|
|
31
|
+
* default; granting `bookings-pii:read` is an explicit decision.
|
|
32
|
+
*/
|
|
33
|
+
export function shouldRevealBookingPii(ctx) {
|
|
34
|
+
if (ctx.isInternalRequest)
|
|
35
|
+
return true;
|
|
36
|
+
const scopes = ctx.scopes ?? [];
|
|
37
|
+
return (scopes.includes(SUPERUSER_SCOPE) ||
|
|
38
|
+
scopes.includes(PII_SCOPE_ANY) ||
|
|
39
|
+
scopes.includes(PII_SCOPE_READ));
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Mask the local-part of an email, preserving the domain so the operator
|
|
43
|
+
* can tell at a glance which provider is involved.
|
|
44
|
+
*
|
|
45
|
+
* `alice@example.com` → `a***e@example.com`
|
|
46
|
+
* `bo@example.com` → `**@example.com`
|
|
47
|
+
*/
|
|
48
|
+
export function redactEmail(email) {
|
|
49
|
+
if (email == null)
|
|
50
|
+
return email ?? null;
|
|
51
|
+
const at = email.lastIndexOf("@");
|
|
52
|
+
if (at < 1)
|
|
53
|
+
return "***";
|
|
54
|
+
const local = email.slice(0, at);
|
|
55
|
+
const domain = email.slice(at);
|
|
56
|
+
if (local.length <= 2)
|
|
57
|
+
return `${"*".repeat(local.length)}${domain}`;
|
|
58
|
+
return `${local[0]}***${local[local.length - 1]}${domain}`;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Mask all but the last four digits of a phone number, dropping
|
|
62
|
+
* non-digit characters from the masked region so the result is recognisable
|
|
63
|
+
* as a phone fragment.
|
|
64
|
+
*
|
|
65
|
+
* `+40 712 345 678` → `***5678`
|
|
66
|
+
*/
|
|
67
|
+
export function redactPhone(phone) {
|
|
68
|
+
if (phone == null)
|
|
69
|
+
return phone ?? null;
|
|
70
|
+
const digits = phone.replace(/\D/g, "");
|
|
71
|
+
if (digits.length <= 4)
|
|
72
|
+
return "***";
|
|
73
|
+
return `***${digits.slice(-4)}`;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Masks an arbitrary identifier like a postal address or city to a single-
|
|
77
|
+
* char marker. We keep the field present so client schemas don't break,
|
|
78
|
+
* but the value is effectively absent.
|
|
79
|
+
*/
|
|
80
|
+
export function redactString(value) {
|
|
81
|
+
if (value == null)
|
|
82
|
+
return value ?? null;
|
|
83
|
+
return value.length === 0 ? value : "***";
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Booking row contact-PII redaction. Returns a shallow copy with the
|
|
87
|
+
* `contact*` columns masked. Caller is responsible for not running this on
|
|
88
|
+
* already-redacted rows.
|
|
89
|
+
*/
|
|
90
|
+
export function redactBookingContact(row) {
|
|
91
|
+
return {
|
|
92
|
+
...row,
|
|
93
|
+
contactFirstName: redactString(row.contactFirstName),
|
|
94
|
+
contactLastName: redactString(row.contactLastName),
|
|
95
|
+
contactEmail: redactEmail(row.contactEmail),
|
|
96
|
+
contactPhone: redactPhone(row.contactPhone),
|
|
97
|
+
contactAddressLine1: redactString(row.contactAddressLine1),
|
|
98
|
+
contactPostalCode: redactString(row.contactPostalCode),
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Traveler row redaction. Same shape as `redactBookingContact` but for
|
|
103
|
+
* traveler identity columns.
|
|
104
|
+
*
|
|
105
|
+
* `accessibilityNeeds` is intentionally NOT in the redacted set — it was
|
|
106
|
+
* moved to the encrypted `bookingTravelerTravelDetails` table (#283) and
|
|
107
|
+
* is only ever returned through `createBookingPiiService` after
|
|
108
|
+
* decryption + audit. It's never present on this row shape.
|
|
109
|
+
*/
|
|
110
|
+
export function redactTravelerIdentity(row) {
|
|
111
|
+
return {
|
|
112
|
+
...row,
|
|
113
|
+
firstName: redactString(row.firstName),
|
|
114
|
+
lastName: redactString(row.lastName),
|
|
115
|
+
email: redactEmail(row.email),
|
|
116
|
+
phone: redactPhone(row.phone),
|
|
117
|
+
specialRequests: redactString(row.specialRequests),
|
|
118
|
+
notes: redactString(row.notes),
|
|
119
|
+
};
|
|
120
|
+
}
|
package/dist/pii.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ export interface UpsertBookingTravelerTravelDetailInput {
|
|
|
7
7
|
passportExpiry?: string | null;
|
|
8
8
|
dateOfBirth?: string | null;
|
|
9
9
|
dietaryRequirements?: string | null;
|
|
10
|
+
accessibilityNeeds?: string | null;
|
|
10
11
|
isLeadTraveler?: boolean | null;
|
|
11
12
|
}
|
|
12
13
|
export interface BookingPiiAuditEvent {
|
package/dist/pii.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pii.d.ts","sourceRoot":"","sources":["../src/pii.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAG1D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AACjE,OAAO,
|
|
1
|
+
{"version":3,"file":"pii.d.ts","sourceRoot":"","sources":["../src/pii.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAG1D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AACjE,OAAO,EAKL,KAAK,oCAAoC,EAC1C,MAAM,4BAA4B,CAAA;AAGnC,MAAM,WAAW,sCAAsC;IACrD,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC9B,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC9B,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,mBAAmB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACnC,kBAAkB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAClC,cAAc,CAAC,EAAE,OAAO,GAAG,IAAI,CAAA;CAChC;AAED,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,QAAQ,CAAA;IACxC,UAAU,EAAE,MAAM,CAAA;IAClB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CACxB;AAED,MAAM,WAAW,wBAAwB;IACvC,GAAG,EAAE,WAAW,CAAA;IAChB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,oBAAoB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CAChE;AAED,MAAM,WAAW,iBAAiB;IAChC,wBAAwB,CACtB,EAAE,EAAE,kBAAkB,EACtB,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,GACtB,OAAO,CAAC,oCAAoC,GAAG,IAAI,CAAC,CAAA;IACvD,2BAA2B,CACzB,EAAE,EAAE,kBAAkB,EACtB,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,sCAAsC,EAC7C,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,GACtB,OAAO,CAAC,oCAAoC,GAAG,IAAI,CAAC,CAAA;IACvD,2BAA2B,CACzB,EAAE,EAAE,kBAAkB,EACtB,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,GACtB,OAAO,CAAC;QAAE,UAAU,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC,CAAA;CAC1C;AA4HD,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,wBAAwB,GAAG,iBAAiB,CAqI5F"}
|
package/dist/pii.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { decryptOptionalJsonEnvelope, encryptOptionalJsonEnvelope } from "@voyantjs/utils";
|
|
2
2
|
import { eq } from "drizzle-orm";
|
|
3
|
-
import { bookingTravelerDietarySchema, bookingTravelerIdentitySchema, bookingTravelerTravelDetails, } from "./schema/travel-details.js";
|
|
3
|
+
import { bookingTravelerAccessibilitySchema, bookingTravelerDietarySchema, bookingTravelerIdentitySchema, bookingTravelerTravelDetails, } from "./schema/travel-details.js";
|
|
4
4
|
import { bookingTravelers } from "./schema.js";
|
|
5
5
|
function buildIdentityPayload(input) {
|
|
6
6
|
const payload = bookingTravelerIdentitySchema.parse({
|
|
@@ -26,6 +26,15 @@ function buildDietaryPayload(input) {
|
|
|
26
26
|
}
|
|
27
27
|
return payload;
|
|
28
28
|
}
|
|
29
|
+
function buildAccessibilityPayload(input) {
|
|
30
|
+
const payload = bookingTravelerAccessibilitySchema.parse({
|
|
31
|
+
accessibilityNeeds: input.accessibilityNeeds ?? null,
|
|
32
|
+
});
|
|
33
|
+
if (!payload.accessibilityNeeds) {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
return payload;
|
|
37
|
+
}
|
|
29
38
|
async function loadExistingTravelDetails(db, travelerId, options, keyRef) {
|
|
30
39
|
const [row] = await db
|
|
31
40
|
.select()
|
|
@@ -37,12 +46,14 @@ async function loadExistingTravelDetails(db, travelerId, options, keyRef) {
|
|
|
37
46
|
}
|
|
38
47
|
const identity = await decryptOptionalJsonEnvelope(options.kms, keyRef, row.identityEncrypted, bookingTravelerIdentitySchema);
|
|
39
48
|
const dietary = await decryptOptionalJsonEnvelope(options.kms, keyRef, row.dietaryEncrypted, bookingTravelerDietarySchema);
|
|
49
|
+
const accessibility = await decryptOptionalJsonEnvelope(options.kms, keyRef, row.accessibilityEncrypted, bookingTravelerAccessibilitySchema);
|
|
40
50
|
return {
|
|
41
51
|
nationality: identity?.nationality ?? null,
|
|
42
52
|
passportNumber: identity?.passportNumber ?? null,
|
|
43
53
|
passportExpiry: identity?.passportExpiry ?? null,
|
|
44
54
|
dateOfBirth: identity?.dateOfBirth ?? null,
|
|
45
55
|
dietaryRequirements: dietary?.dietaryRequirements ?? null,
|
|
56
|
+
accessibilityNeeds: accessibility?.accessibilityNeeds ?? null,
|
|
46
57
|
isLeadTraveler: row.isLeadTraveler,
|
|
47
58
|
};
|
|
48
59
|
}
|
|
@@ -59,6 +70,9 @@ function mergeTravelDetailInput(existing, input) {
|
|
|
59
70
|
dietaryRequirements: input.dietaryRequirements === undefined
|
|
60
71
|
? (existing?.dietaryRequirements ?? null)
|
|
61
72
|
: input.dietaryRequirements,
|
|
73
|
+
accessibilityNeeds: input.accessibilityNeeds === undefined
|
|
74
|
+
? (existing?.accessibilityNeeds ?? null)
|
|
75
|
+
: input.accessibilityNeeds,
|
|
62
76
|
isLeadTraveler: input.isLeadTraveler === undefined
|
|
63
77
|
? (existing?.isLeadTraveler ?? false)
|
|
64
78
|
: input.isLeadTraveler,
|
|
@@ -78,6 +92,7 @@ export function createBookingPiiService(options) {
|
|
|
78
92
|
}
|
|
79
93
|
const identity = await decryptOptionalJsonEnvelope(options.kms, keyRef, row.identityEncrypted, bookingTravelerIdentitySchema);
|
|
80
94
|
const dietary = await decryptOptionalJsonEnvelope(options.kms, keyRef, row.dietaryEncrypted, bookingTravelerDietarySchema);
|
|
95
|
+
const accessibility = await decryptOptionalJsonEnvelope(options.kms, keyRef, row.accessibilityEncrypted, bookingTravelerAccessibilitySchema);
|
|
81
96
|
await options.onAudit?.({ action: "decrypt", travelerId, actorId });
|
|
82
97
|
return {
|
|
83
98
|
travelerId: row.travelerId,
|
|
@@ -86,6 +101,7 @@ export function createBookingPiiService(options) {
|
|
|
86
101
|
passportExpiry: identity?.passportExpiry ?? null,
|
|
87
102
|
dateOfBirth: identity?.dateOfBirth ?? null,
|
|
88
103
|
dietaryRequirements: dietary?.dietaryRequirements ?? null,
|
|
104
|
+
accessibilityNeeds: accessibility?.accessibilityNeeds ?? null,
|
|
89
105
|
isLeadTraveler: row.isLeadTraveler,
|
|
90
106
|
createdAt: row.createdAt,
|
|
91
107
|
updatedAt: row.updatedAt,
|
|
@@ -104,6 +120,7 @@ export function createBookingPiiService(options) {
|
|
|
104
120
|
const mergedInput = mergeTravelDetailInput(existing, input);
|
|
105
121
|
const identityEncrypted = await encryptOptionalJsonEnvelope(options.kms, keyRef, buildIdentityPayload(mergedInput));
|
|
106
122
|
const dietaryEncrypted = await encryptOptionalJsonEnvelope(options.kms, keyRef, buildDietaryPayload(mergedInput));
|
|
123
|
+
const accessibilityEncrypted = await encryptOptionalJsonEnvelope(options.kms, keyRef, buildAccessibilityPayload(mergedInput));
|
|
107
124
|
const now = new Date();
|
|
108
125
|
await db
|
|
109
126
|
.insert(bookingTravelerTravelDetails)
|
|
@@ -111,6 +128,7 @@ export function createBookingPiiService(options) {
|
|
|
111
128
|
travelerId,
|
|
112
129
|
identityEncrypted,
|
|
113
130
|
dietaryEncrypted,
|
|
131
|
+
accessibilityEncrypted,
|
|
114
132
|
isLeadTraveler: mergedInput.isLeadTraveler ?? false,
|
|
115
133
|
updatedAt: now,
|
|
116
134
|
})
|
|
@@ -119,6 +137,7 @@ export function createBookingPiiService(options) {
|
|
|
119
137
|
set: {
|
|
120
138
|
identityEncrypted,
|
|
121
139
|
dietaryEncrypted,
|
|
140
|
+
accessibilityEncrypted,
|
|
122
141
|
isLeadTraveler: mergedInput.isLeadTraveler ?? false,
|
|
123
142
|
updatedAt: now,
|
|
124
143
|
},
|
package/dist/routes-groups.d.ts
CHANGED
|
@@ -107,6 +107,7 @@ export declare const bookingGroupRoutes: import("hono/hono-base").HonoBase<Env,
|
|
|
107
107
|
contactPostalCode: string | null;
|
|
108
108
|
sellCurrency: string;
|
|
109
109
|
baseCurrency: string | null;
|
|
110
|
+
fxRateSetId: string | null;
|
|
110
111
|
sellAmountCents: number | null;
|
|
111
112
|
baseSellAmountCents: number | null;
|
|
112
113
|
costAmountCents: number | null;
|
|
@@ -243,6 +244,7 @@ export declare const bookingGroupRoutes: import("hono/hono-base").HonoBase<Env,
|
|
|
243
244
|
contactPostalCode: string | null;
|
|
244
245
|
sellCurrency: string;
|
|
245
246
|
baseCurrency: string | null;
|
|
247
|
+
fxRateSetId: string | null;
|
|
246
248
|
sellAmountCents: number | null;
|
|
247
249
|
baseSellAmountCents: number | null;
|
|
248
250
|
costAmountCents: number | null;
|
|
@@ -353,13 +355,12 @@ export declare const bookingGroupRoutes: import("hono/hono-base").HonoBase<Env,
|
|
|
353
355
|
email: string | null;
|
|
354
356
|
firstName: string;
|
|
355
357
|
lastName: string;
|
|
356
|
-
personId: string | null;
|
|
357
358
|
bookingId: string;
|
|
359
|
+
personId: string | null;
|
|
358
360
|
participantType: "other" | "traveler" | "occupant";
|
|
359
361
|
travelerCategory: "other" | "adult" | "child" | "infant" | "senior" | null;
|
|
360
362
|
phone: string | null;
|
|
361
363
|
preferredLanguage: string | null;
|
|
362
|
-
accessibilityNeeds: string | null;
|
|
363
364
|
specialRequests: string | null;
|
|
364
365
|
isPrimary: boolean;
|
|
365
366
|
}[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"routes-groups.d.ts","sourceRoot":"","sources":["../src/routes-groups.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAA;AAQ1D,KAAK,GAAG,GAAG;IACT,SAAS,EAAE;QACT,EAAE,EAAE,UAAU,CAAC,OAAO,oBAAoB,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAAA;QAChE,MAAM,CAAC,EAAE,MAAM,CAAA;KAChB,CAAA;CACF,CAAA;AAED,eAAO,MAAM,kBAAkB
|
|
1
|
+
{"version":3,"file":"routes-groups.d.ts","sourceRoot":"","sources":["../src/routes-groups.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAA;AAQ1D,KAAK,GAAG,GAAG;IACT,SAAS,EAAE;QACT,EAAE,EAAE,UAAU,CAAC,OAAO,oBAAoB,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAAA;QAChE,MAAM,CAAC,EAAE,MAAM,CAAA;KAChB,CAAA;CACF,CAAA;AAED,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yBA0E3B,CAAA;AAEJ,MAAM,MAAM,kBAAkB,GAAG,OAAO,kBAAkB,CAAA"}
|
package/dist/routes-public.d.ts
CHANGED
|
@@ -27,17 +27,6 @@ export declare const publicBookingRoutes: import("hono/hono-base").HonoBase<Env,
|
|
|
27
27
|
} & {
|
|
28
28
|
"/sessions/:sessionId": {
|
|
29
29
|
$get: {
|
|
30
|
-
input: {
|
|
31
|
-
param: {
|
|
32
|
-
sessionId: string;
|
|
33
|
-
};
|
|
34
|
-
};
|
|
35
|
-
output: {
|
|
36
|
-
error: string;
|
|
37
|
-
};
|
|
38
|
-
outputFormat: "json";
|
|
39
|
-
status: 404;
|
|
40
|
-
} | {
|
|
41
30
|
input: {
|
|
42
31
|
param: {
|
|
43
32
|
sessionId: string;
|
|
@@ -69,7 +58,6 @@ export declare const publicBookingRoutes: import("hono/hono-base").HonoBase<Env,
|
|
|
69
58
|
email: string | null;
|
|
70
59
|
phone: string | null;
|
|
71
60
|
preferredLanguage: string | null;
|
|
72
|
-
accessibilityNeeds: string | null;
|
|
73
61
|
specialRequests: string | null;
|
|
74
62
|
isPrimary: boolean;
|
|
75
63
|
notes: string | null;
|
|
@@ -140,6 +128,17 @@ export declare const publicBookingRoutes: import("hono/hono-base").HonoBase<Env,
|
|
|
140
128
|
};
|
|
141
129
|
outputFormat: "json";
|
|
142
130
|
status: import("hono/utils/http-status").ContentfulStatusCode;
|
|
131
|
+
} | {
|
|
132
|
+
input: {
|
|
133
|
+
param: {
|
|
134
|
+
sessionId: string;
|
|
135
|
+
};
|
|
136
|
+
};
|
|
137
|
+
output: {
|
|
138
|
+
error: string;
|
|
139
|
+
};
|
|
140
|
+
outputFormat: "json";
|
|
141
|
+
status: 404;
|
|
143
142
|
};
|
|
144
143
|
};
|
|
145
144
|
} & {
|
|
@@ -344,7 +343,6 @@ export declare const publicBookingRoutes: import("hono/hono-base").HonoBase<Env,
|
|
|
344
343
|
email: string | null;
|
|
345
344
|
phone: string | null;
|
|
346
345
|
preferredLanguage: string | null;
|
|
347
|
-
accessibilityNeeds: string | null;
|
|
348
346
|
specialRequests: string | null;
|
|
349
347
|
isPrimary: boolean;
|
|
350
348
|
notes: string | null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"routes-public.d.ts","sourceRoot":"","sources":["../src/routes-public.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,GAAG,EAAY,MAAM,oBAAoB,CAAA;AAsCvD,eAAO,MAAM,mBAAmB
|
|
1
|
+
{"version":3,"file":"routes-public.d.ts","sourceRoot":"","sources":["../src/routes-public.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,GAAG,EAAY,MAAM,oBAAoB,CAAA;AAsCvD,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;oBAuI5B,CAAA;AAEJ,MAAM,MAAM,mBAAmB,GAAG,OAAO,mBAAmB,CAAA"}
|