| ← Back to s.plings.io | Core Systems |
Routing Logic
Created: Tue 29 Jul 2025 06:49:39 CEST
Document Version: 1.0 - Initial documentation
Security Classification: Public Technical Documentation
Target Audience: Frontend Developers, Product Managers
Author: Paul Wisén
Overview
The Director’s routing logic determines where to send users based on multiple factors including object status, user authentication, scan context, and business rules. This document details all routing scenarios and decision trees.
Routing Decision Flow
Routing Rules by Object Status
FOR_SALE Objects
if (object.status === 'FOR_SALE') {
return {
service: 'market.plings.io',
path: `/item`,
params: {
oid: object.id,
price: object.salePrice,
seller: object.owner.username
}
};
}
User Experience: Direct to marketplace listing with buy button
FOR_RENT Objects
if (object.status === 'FOR_RENT') {
return {
service: 'rent.plings.io',
path: `/listing`,
params: {
oid: object.id,
daily: object.rentPrice.daily,
weekly: object.rentPrice.weekly
}
};
}
User Experience: Rental page with availability calendar
LENDABLE Objects
if (object.status === 'LENDABLE') {
return {
service: 'lend.plings.io',
path: `/borrow`,
params: {
oid: object.id,
terms: object.lendingTerms
}
};
}
User Experience: Peer-to-peer lending interface
LOST Objects
if (object.status === 'LOST') {
return {
service: 'plings.io',
path: `/found`,
params: {
oid: object.id,
location: scanLocation,
timestamp: Date.now()
}
};
}
User Experience: “I found this item” flow with owner notification
Unknown Identifier Routing
Generic Plings Tags
Identification: Path starts with 1. (Plings manufacturer ID)
if (path.startsWith('1.') && !objectExists) {
return {
service: 'plings.io',
path: '/create',
params: {
ikey: instanceKey,
path: path,
type: 'generic'
}
};
}
Manufacturer Pre-printed Tags
Identification: Non-Plings manufacturer ID with class pointer
if (!path.startsWith('1.') && classPointer && !objectExists) {
return {
service: 'plings.io',
path: '/claim',
params: {
ikey: instanceKey,
path: path,
class: resolvedClassId,
cptr: classPointer,
manufacturer: manufacturerName
}
};
}
Authentication-Based Routing
Owner Scanning Own Object
if (isAuthenticated && object.owner === user.id) {
return {
service: 'plings.io',
path: `/edit/${object.id}`,
params: {
context: 'owner_scan',
quickActions: true
}
};
}
Public Scanning Private Object
if (!isAuthenticated && object.visibility === 'private') {
return {
service: 'plings.io',
path: '/login',
params: {
return: `/o/${object.id}`,
reason: 'private_object'
}
};
}
Context-Aware Routing
A/B Testing
const testGroup = hashUserId(userId) % 100;
if (testGroup < 10) { // 10% of users
return experimentalRoute;
} else {
return standardRoute;
}
Geographic Routing
const userRegion = geoIP.getRegion(request.ip);
const regionalServices = {
'EU': 'eu.plings.io',
'US': 'us.plings.io',
'ASIA': 'asia.plings.io'
};
return {
service: regionalServices[userRegion] || 'plings.io',
// ... rest of routing
};
Time-Based Routing
if (isMaintenanceWindow()) {
return {
service: 'status.plings.io',
path: '/maintenance',
params: {
estimatedTime: getMaintenanceEnd()
}
};
}
Special Routing Scenarios
Business Hours Routing
if (object.type === 'BUSINESS_ASSET' && !isBusinessHours()) {
return {
service: 'plings.io',
path: '/business-hours',
params: {
openTime: getNextOpenTime(),
contact: object.businessContact
}
};
}
Emergency Services
if (object.tags.includes('MEDICAL') || object.tags.includes('EMERGENCY')) {
return {
service: 'plings.io',
path: '/emergency',
params: {
type: object.emergencyType,
contact: object.emergencyContact,
priority: 'HIGH'
}
};
}
Compliance Routing
if (userRegion === 'EU' && !hasGDPRConsent(user)) {
return {
service: 'plings.io',
path: '/privacy-consent',
params: {
return: originalRoute,
region: 'EU'
}
};
}
Parameter Enrichment
All routes include enriched parameters:
function enrichParameters(baseParams: Params, context: Context): EnrichedParams {
return {
...baseParams,
// Always included
src: 'scan',
ikey: context.instanceKey,
path: context.path,
// Conditional
...(context.objectId && { oid: context.objectId }),
...(context.classPointer && { cptr: context.classPointer }),
...(context.hasLocation && { loc: context.location }),
...(context.isAuthenticated && { session: context.sessionId }),
// Analytics
ts: Date.now(),
v: '1.0' // API version
};
}
Error Routing
Invalid Identifier
if (!isValidIdentifier(instanceKey)) {
return {
service: 'plings.io',
path: '/scan-error',
params: {
reason: 'invalid_identifier',
help: 'Check if this is a valid Plings QR code'
}
};
}
Rate Limited
if (isRateLimited(request.ip)) {
return {
service: 'plings.io',
path: '/scan-error',
params: {
reason: 'rate_limit',
retryAfter: getRateLimitExpiry(request.ip)
}
};
}
System Error
catch (error) {
logError(error);
return {
service: 'plings.io',
path: '/scan-error',
params: {
reason: 'system_error',
code: error.code || 500,
support: 'support@plings.io'
}
};
}
Routing Priority
When multiple routing rules apply, this priority order is followed:
- Security & Compliance (GDPR, rate limits)
- System Status (maintenance, outages)
- Object Status (FOR_SALE, LOST, etc.)
- User Context (authenticated, owner)
- Business Rules (hours, geography)
- Default Routes
Configuration
Routing rules can be configured via environment variables:
# Service URLs
MAIN_SERVICE_URL=https://plings.io
MARKET_SERVICE_URL=https://market.plings.io
RENT_SERVICE_URL=https://rent.plings.io
# Feature Flags
ENABLE_AB_TESTING=true
ENABLE_GEO_ROUTING=true
ENABLE_BUSINESS_HOURS=false
# Routing Rules
DEFAULT_UNKNOWN_ROUTE=/create
MAINTENANCE_ROUTE=/status
Monitoring
Key metrics tracked for routing decisions:
- Route distribution by service
- Authentication success rate
- Geographic distribution
- Error rate by route type
- A/B test performance
- Average routing latency
Related Documentation
- URL Structure - Parameter specifications
- Implementation Guide - Code examples
- Security Model - Security considerations