Skip to main content

ADP — Architecture

Developer reference for functions/modules/adp/. Companion docs: flows, operations.

Surface​

One Cloud Function, adp, serving a Hono router. Production host is us-central1-pivot-inc.cloudfunctions.net/adp.

RouteAuthPurpose
/subscription/orderMarketplace BasicLink a company on subscribe
/subscription/changeMarketplace BasicEdition change
/subscription/cancelMarketplace BasicUnlink and delete ADP state
/subscription/noticeMarketplace BasicSuspend / reactivate
/subscription/assignMarketplace BasicRecord a user assignment
/subscription/unassignMarketplace BasicRecord a user unassignment
/subscription/verifypublicCheckout custom-field validation
/subscription/statususerIntegration status
/authenticate-ssopublicOIDC code exchange, mints a Firebase custom token
/exportuserSend a payroll period to ADP
/search-employeesuserSearch ADP workers by name
/get-payroll-group-codesuserList payroll groups
/get-earning-codesuserList earning codes
/get-credentials-after-consentuserRe-fetch client credentials after consent

Background: onInitAdpIntegration (RTDB trigger) and syncAdpEmployeesCronJob (scheduled).

Subscription event URLs must be registered with the ?eventUrl={eventUrl} template. Without it the handler receives no event URL, treats the call as ADP's validation probe, and returns 200 without acting.

Module layout​

Standard modules/<name>/ clean architecture — types/, logic/, contracts/, handlers/, repositories/, services/, endpoints/, wired in container.ts. Handlers take dependencies as a factory argument and return {status, body}; only container.ts imports concrete implementations.

Credentials​

Five sets, and two of the secret names do not match ADP's terminology:

SecretHoldsUsed by
ADP_CLIENT_ID_SSO / ADP_CLIENT_SECRET_SSOADP's End-User / SSO credentials/authenticate-sso code exchange
ADP_CLIENT_ID_CONNECTOR / ADP_CLIENT_SECRET_CONNECTORADP's Data Connector credentialscredentials.read
ADP_SUBSCRIPTION_CLIENT_ID / _SECRETInbound Marketplace credentials, issued by ADPFetching subscription payloads
ADP_SUBSCRIPTION_USERNAME / _PASSWORDOutbound Basic auth, chosen by us and typed into the listingVerifying inbound marketplace calls
ADP_PUBLIC_CERT / ADP_PRIVATE_CERTmTLS client certificate and key, base64 of the PEMEvery ADP API call

Per-client credentials are fetched once via credentials.read and stored per company. A 200 response with an empty body means the client has not consented.

Data model​

AdpSettings/{companyId}
organizationOID ADP organization, the join key for SSO and events
clientId / clientSecret per-client API credentials
payrollGroupCode export target; writing this fires the initial sync
assignedUsers/{associateOID} { status, updatedAt, email, name }

CompanySettings/{companyId}
hasAdpIntegration subscription linked
hasAcceptedADPConsent credentials retrieved
adpSuspended set by SUBSCRIPTION_NOTICE

EmployeeIntegrationIds/{companyId}/adp/{employeeId}
{ id, payrollFileNumber } id is the ADP associateOID

associateOID is the canonical person identifier and the key everything joins on. ADP's assignment payload carries it at payload.configuration.associateOID — payload.user.uuid is an OpenID subject and is not the same value.