Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 0 additions & 9 deletions apps/delivery-api/src/config/env.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
import type { TokenEncryptionKey } from '../modules/security/token-encryption.js';
import { loadTokenEncryptionKey } from '../modules/security/token-encryption.js';

export type AppEnv = {
nodeEnv: string;
port: number;
Expand All @@ -17,12 +14,6 @@ export function loadEnv(input: NodeJS.ProcessEnv = process.env): AppEnv {
};
}

export function loadShopifyTokenEncryptionKey(
input: NodeJS.ProcessEnv = process.env
): TokenEncryptionKey {
return loadTokenEncryptionKey(input.SHOPIFY_TOKEN_ENCRYPTION_KEY);
}

function parsePort(value: string | undefined): number {
if (value === undefined || value.trim() === '') {
return DEFAULT_PORT;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1527,14 +1527,6 @@ function automaticSettingsVersion(settings: CustomerEmailSettings): string {
return `v3:g${settings.globalVersion}:t${templateVersions}`;
}

export function readCustomerEmailSettingsPayload(value: unknown): CustomerEmailSettings | null {
try {
return validateCustomerEmailSettingsPayload(value);
} catch {
return null;
}
}

export function readCustomerEmailGlobalSettingsPayload(value: unknown): {
branding: Partial<CustomerEmailBranding>;
expectedVersion: number;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -421,7 +421,3 @@ export function parseDriverDiagnosticEnvelopeDetailed(value: unknown): ParsedDri
rejectedRecords
};
}

export function parseDriverDiagnosticEnvelope(value: unknown): DriverDiagnosticEnvelope | null {
return parseDriverDiagnosticEnvelopeDetailed(value)?.envelope ?? null;
}
60 changes: 0 additions & 60 deletions apps/delivery-api/src/modules/driver/driver-token-verifier.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import { createHmac, timingSafeEqual } from 'node:crypto';
import { normalizeDriverCommerceDomain } from './driver-commerce-domain.js';

const DRIVER_AUDIENCE = 'clever-delivery-driver';
const DRIVER_ACCOUNT_AUDIENCE = 'clever-driver-account';
const DRIVER_ROUTE_AUDIENCE = 'clever-delivery-driver-route';
const MIN_DRIVER_JWT_SECRET_CHARACTERS = 32;
Expand All @@ -22,14 +20,6 @@ export type VerifiedDriverAccountToken = {
tokenVersion: number;
};

export type VerifiedDriverToken = {
driverId: string;
issuedAt: Date;
shopDomain: string;
subject: string;
tokenVersion: number;
};

export type VerifiedDriverRouteToken = {
accountId: string;
issuedAt: Date;
Expand All @@ -43,14 +33,6 @@ export type VerifyDriverTokenOptions = {
secret: string;
};

export type SignDriverTokenInput = {
driverId: string;
expiresInSeconds: number;
shopDomain: string;
subject: string;
tokenVersion?: number;
};

export type SignDriverAccountTokenInput = {
accountId: string;
expiresInSeconds: number;
Expand Down Expand Up @@ -116,35 +98,6 @@ export function verifyDriverAccountToken(
};
}

export function verifyDriverToken(
token: string,
options: VerifyDriverTokenOptions
): VerifiedDriverToken {
const claims = verifyTokenEnvelope(token, options.secret);
const nowSeconds = Math.floor((options.now ?? new Date()).getTime() / 1000);
const audience = requireStringClaim(claims.aud, 'aud');
const driverId = requireStringClaim(claims.driverId, 'driverId');
const expiresAt = requireNumberClaim(claims.exp, 'exp');
const issuedAtSeconds = requireNumberClaim(claims.iat, 'iat');
const shopDomain = normalizeDriverCommerceDomain(requireStringClaim(claims.shopDomain, 'shopDomain'));
const subject = requireStringClaim(claims.sub, 'sub');
const tokenVersion = readTokenVersionClaim(claims.tokenVersion);

if (audience !== DRIVER_AUDIENCE) {
throw new Error('Driver token audience mismatch');
}

verifyTokenTimes(claims, expiresAt, nowSeconds);

return {
driverId,
issuedAt: new Date(issuedAtSeconds * 1000),
shopDomain,
subject,
tokenVersion
};
}

export function verifyDriverRouteToken(
token: string,
options: VerifyDriverTokenOptions
Expand Down Expand Up @@ -185,19 +138,6 @@ export function signDriverAccountToken(
}, input.expiresInSeconds, options);
}

export function signDriverToken(
input: SignDriverTokenInput,
options: VerifyDriverTokenOptions
): SignDriverTokenResult {
return signToken({
aud: DRIVER_AUDIENCE,
driverId: requireStringClaim(input.driverId, 'driverId'),
shopDomain: normalizeDriverCommerceDomain(input.shopDomain),
sub: requireStringClaim(input.subject, 'sub'),
tokenVersion: readTokenVersionClaim(input.tokenVersion)
}, input.expiresInSeconds, options);
}

export function signDriverRouteToken(
input: SignDriverRouteTokenInput,
options: VerifyDriverTokenOptions
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { appScopedShopWhere } from '../shopify/shopify-app-scope.js';
import type { AdminStoreSettings } from '../commerce/admin-store-settings.service.js';
import { normalizeDsvOperationalSettings } from './dsv-operational-settings.js';
import type { DsvManualEmailService } from './dsv-manual-email.service.js';
import { loadDsvWebPublicOrigin } from './dsv-web-public-origin.js';

export type DsvCustomerAccountInvitePurpose = 'SIGNUP' | 'PASSWORD_RESET';
export type DsvCustomerAccountApiStatus = 'INVITED' | 'ACTIVE' | 'DISABLED' | 'EXPIRED';
Expand Down Expand Up @@ -528,10 +527,6 @@ export class DsvCustomerAccountServiceError extends Error {
}
}

export function loadDsvCustomerAccountWebPublicOrigin(value: string | undefined): string | undefined {
return loadDsvWebPublicOrigin(value);
}

export function createCustomerSessionSubject(input: { accountId: string; activeSessionId: string }): string {
if (!uuidPattern.test(input.accountId) || !uuidPattern.test(input.activeSessionId)) {
throw new Error('Invalid DSV customer session subject');
Expand Down
21 changes: 0 additions & 21 deletions apps/delivery-api/src/modules/dsv/dsv-driver-identity.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,7 @@
import { createHmac } from 'node:crypto';

const RESIDENT_NUMBER_FRONT_PATTERN = /^\d{7}$/u;

export function normalizeDsvDriverLoginId(value: string): string {
return value.trim().toLowerCase();
}

export function normalizeDsvDriverPhone(value: string): string {
return value.replace(/\D/gu, '');
}

export function fingerprintResidentNumberFront(
residentNumberFront: string,
secret: string,
): string {
if (!RESIDENT_NUMBER_FRONT_PATTERN.test(residentNumberFront)) {
throw new Error('residentNumberFront must contain exactly seven digits');
}
if (secret.length < 32) {
throw new Error('DSV driver identity secret must contain at least 32 characters');
}

return createHmac('sha256', secret)
.update('clever-dsv-driver-resident-front-v1\0', 'utf8')
.update(residentNumberFront, 'utf8')
.digest('hex');
}
21 changes: 0 additions & 21 deletions apps/delivery-api/src/modules/dsv/dsv-principal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -171,24 +171,3 @@ export function requireDsvScopes(principal: DsvPrincipal, requiredScopes: readon
if (requiredScopes.every((scope) => granted.has(scope))) return;
throw new DsvForbiddenError({ principal, requiredScopes });
}

export function requireCustomerDeliveryPrincipal(input: {
customerId?: string;
destinationId?: string;
principal: DsvPrincipal;
}): DsvCustomerUserPrincipal {
requireDsvScopes(input.principal, ['dsv:customer-deliveries:read']);
if (input.principal.principalType !== 'CUSTOMER_USER' || input.principal.customerId === '') {
throw new DsvForbiddenError({
principal: input.principal,
requiredScopes: ['dsv:customer-deliveries:read'],
});
}
if (input.customerId !== undefined && input.customerId !== input.principal.customerId) {
throw new DsvForbiddenError({
principal: input.principal,
requiredScopes: ['dsv:customer-deliveries:read'],
});
}
return input.principal;
}
25 changes: 0 additions & 25 deletions apps/delivery-api/src/modules/dsv/dsv-v1-read.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,31 +24,6 @@ export const dsvV1ErrorCodes = [
] as const;
export type DsvV1ErrorCode = typeof dsvV1ErrorCodes[number];

export const dsvV1CustomerDeliveryRequiredFields = [
'sellerOrderId',
'sellerOrderKey',
'destinationId',
'destinationDisplayName',
'shippedBoxes',
'deliveryStatus',
'etaStatus',
'eventSummary',
'proofStatus',
] as const;

export const dsvV1SellerOrderSummaryRequiredFields = [
'sellerOrderId',
'sellerOrderKey',
'deliveryStopId',
'customerId',
'destinationId',
'assignmentStatus',
'etaStatus',
'eventSummary',
] as const;

export const dsvV1SessionRequiredFields = ['csrfToken', 'principalType', 'shopId', 'scopes'] as const;

export type DsvV1PrincipalType = 'DSV_ADMIN' | 'CUSTOMER_USER' | 'DRIVER' | 'IMPORT_WORKER' | 'DEVICE';

export type DsvV1SuccessEnvelope<TData> = {
Expand Down
6 changes: 0 additions & 6 deletions apps/delivery-api/src/modules/geocoding/geocoding.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -368,12 +368,6 @@ export function normalizeAddress(address: GeocodingAddress): string | null {
return normalizeAddressParts(addressParts(address));
}

export function normalizeAddressQueries(address: GeocodingAddress): string[] {
return buildGeocodingQueries(address).flatMap((query) =>
query.kind === 'freeform' ? [query.q] : [],
);
}

export function buildGeocodingQueries(address: GeocodingAddress): GeocodingQuery[] {
const full = normalizeAddress(address);
if (full === null) return [];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,3 @@ export function createAdminNotificationRuntime(input: {
start: () => bridge?.start() ?? Promise.resolve(),
};
}

export function createAdminNotificationService(input: {
prisma: PrismaClient;
}): AdminNotificationService {
return createAdminNotificationRuntime(input).service;
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,19 +23,6 @@ export type DriverPushProvider = {
sendRouteNotification(message: DriverRoutePushMessage): Promise<DriverRoutePushResult>;
};

export class FakeDriverPushProvider implements DriverPushProvider {
readonly providerName = 'fake';
readonly sentMessages: DriverRoutePushMessage[] = [];

sendRouteNotification(message: DriverRoutePushMessage): Promise<DriverRoutePushResult> {
this.sentMessages.push(message);
return Promise.resolve({
providerMessageId: `fake:${message.routeGroupingId ?? 'standalone'}:${message.childVersion ?? message.publicationVersion ?? 'current'}:${message.routePlanId}`,
status: 'SENT'
});
}
}

export class DisabledDriverPushProvider implements DriverPushProvider {
readonly providerName = 'disabled';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,19 +70,3 @@ export function coordinatesFromGeoJsonPolygon(value: unknown): PolygonRing {
})
.filter((entry): entry is Coordinate => entry !== null);
}

export function geoJsonPolygonFromCoordinates(vertices: PolygonRing): { type: 'Polygon'; coordinates: number[][][] } {
const ring = vertices.map((vertex) => [vertex.longitude, vertex.latitude]);
const first = ring[0];
const last = ring[ring.length - 1];
const closed =
first !== undefined &&
last !== undefined &&
first[0] === last[0] &&
first[1] === last[1]
? ring
: first === undefined
? ring
: [...ring, first];
return { type: 'Polygon', coordinates: [closed] };
}
Original file line number Diff line number Diff line change
Expand Up @@ -169,31 +169,6 @@ type ChildRouteGeometrySnapshot = {
routeStopPoints: RoutePlanRouteStopPoint[];
};

export function currentRouteBindingAuthorityState(
childVersionId: string,
snapshotOrderIds: string[],
assignments: Array<{ orderId: string; order: { currentRouteVersionId: string | null } }>
): 'EXACT' | 'LEGACY_UNBOUND' | 'MISMATCH' {
const snapshotOrderIdSet = new Set(snapshotOrderIds);
if (snapshotOrderIdSet.size !== snapshotOrderIds.length) return 'MISMATCH';

const snapshotAssignments = assignments.filter(({ orderId }) => snapshotOrderIdSet.has(orderId));
if (snapshotAssignments.length !== snapshotOrderIds.length) return 'MISMATCH';

const boundOrderIds = assignments
.filter(({ order }) => order.currentRouteVersionId === childVersionId)
.map(({ orderId }) => orderId)
.sort();
const sortedSnapshotOrderIds = [...snapshotOrderIds].sort();
const exactBinding = sortedSnapshotOrderIds.length === boundOrderIds.length
&& sortedSnapshotOrderIds.every((orderId, index) => orderId === boundOrderIds[index]);
if (exactBinding) return 'EXACT';

const entirelyUnbound = boundOrderIds.length === 0
&& snapshotAssignments.every(({ order }) => order.currentRouteVersionId === null);
return entirelyUnbound ? 'LEGACY_UNBOUND' : 'MISMATCH';
}

type OptimizedDraftRoute = {
assignments: LoadedAssignment[];
routeResult: RoutePlanRouteResult;
Expand Down
8 changes: 0 additions & 8 deletions apps/delivery-api/src/modules/route-ops/route-scope-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -165,14 +165,6 @@ export function isActiveDeliverySession(config: RouteScopeConfigDto, value: unkn
return isActiveRouteScopeValue(config.deliverySessions, value);
}

export function buildActiveServiceTypes(config: RouteScopeConfigDto): RouteScopeValueDto[] {
return config.serviceTypes.filter((item) => item.enabled);
}

export function buildActiveDeliverySessions(config: RouteScopeConfigDto): RouteScopeValueDto[] {
return config.deliverySessions.filter((item) => item.enabled);
}

function normalizeRouteScopeValues(input: {
builtIns: readonly RouteScopeValueDto[];
raw: unknown;
Expand Down
Loading
Loading