Back to Equalify Dashboard

Backend Api

Edit on GitHub

Backend API Reference

The Equalify backend is a single AWS Lambda function that acts as a router, directing requests to appropriate handlers based on the URL path and authentication status.

Entry Point

The main handler (apps/backend/index.ts) routes requests based on path prefixes:

Path PrefixRouterAuthentication
/publicpublicRouterNone
/authauthRouterJWT required
/internalinternalRouterInternal only
/scheduledscheduledRouterEventBridge
/hasurahasuraRouterWebhook secret
Cognito triggerscognitoRouterCognito events

Route Organization

Public Routes (/public)

Endpoints that don't require authentication:

  • POST /public/scanWebhook - Receives scan results from scanner Lambdas

Auth Routes (/auth)

Endpoints requiring a valid JWT token:

EndpointMethodDescription
getAccountGETRetrieve user account details
updateUserPOSTUpdate user profile
saveAuditPOSTCreate a new audit
updateAuditPOSTModify an existing audit
deleteAuditPOSTDelete an audit
rescanAuditPOSTTrigger a new scan for an audit
getAuditDetailsGETGet audit configuration
getAuditResultsGETGet scan results with blockers
getAuditChartGETGet chart data for blockers over time
getAuditTableGETGet paginated blocker table data
getAuditProgressGETGet current scan progress
getLogsGETGet activity logs
inviteUserPOSTInvite a new user to the team
trackUserPOSTTrack user analytics events
chatWithAuditPOSTAI-powered audit chat interface

Scheduled Routes (/scheduled)

Endpoints triggered by AWS EventBridge:

  • runEveryMinute - Processes scheduled audits and triggers scans

Hasura Routes (/hasura)

Webhook endpoints for Hasura event triggers (protected by webhook secret).

Authentication Flow

JWT Verification

// For Cognito tokens
const verifier = CognitoJwtVerifier.create({
  userPoolId: process.env.USER_POOL_ID,
  tokenUse: "id",
  clientId: process.env.WEB_CLIENT_ID
});
const claims = await verifier.verify(token);

// For SSO tokens
const rawClaims = await verifySsoToken(token);
const { normalizedClaims, hasuraClaims } = await ensureSsoUser(rawClaims);

Token Structure

Tokens include Hasura claims for GraphQL authorization:

{
  "sub": "user-uuid",
  "email": "user@example.com",
  "https://hasura.io/jwt/claims": {
    "x-hasura-allowed-roles": ["user", "admin"],
    "x-hasura-default-role": "user",
    "x-hasura-user-id": "user-uuid"
  }
}

Database Access

Direct PostgreSQL

Using serverless-postgres for connection pooling:

import { db } from '#src/utils';

await db.connect();
const result = await db.query({
  text: `SELECT * FROM "audits" WHERE "id" = $1`,
  values: [auditId],
});
await db.clean();

GraphQL via Hasura

For complex queries with relationships:

import { graphqlQuery } from '#src/utils';

const response = await graphqlQuery({
  query: `query ($audit_id: uuid!) {
    audits_by_pk(id: $audit_id) {
      scans(order_by: {created_at: desc}, limit: 1) {
        blockers { ... }
      }
    }
  }`,
  variables: { audit_id: auditId },
});

Creating an Audit

When a user creates an audit (saveAudit):

  • Insert audit record with configuration
  • Insert all URLs associated with the audit
  • If saveAndRun is true:
  • Create a new scan record
  • Invoke the scan router Lambda asynchronously
await lambda.send(new InvokeCommand({
  FunctionName: "aws-lambda-scan-sqs-router",
  InvocationType: "Event",
  Payload: JSON.stringify({
    urls: urls.map(url => ({
      auditId, scanId, urlId: url.id,
      url: url.url, type: url.type, isStaging
    }))
  })
}));

Webhook Processing

The scanWebhook endpoint processes results from scanners:

  • Validate required fields (auditId, urlId)
  • Handle failed scans (log error, update progress)
  • For successful scans:
  • Store blockers with content hashing for deduplication
  • Link blockers to messages (accessibility rules)
  • Update scan progress atomically
  • Mark scan complete when all URLs processed

Environment Variables

VariableDescription
DB_USERPostgreSQL username
DB_HOSTPostgreSQL host
DB_NAMEDatabase name
DB_PASSWORDDatabase password / Hasura admin secret
USER_POOL_IDCognito User Pool ID
WEB_CLIENT_IDCognito Web Client ID
SSO_ENABLEDEnable SSO authentication
WEBHOOKSECRETSecret for Hasura webhooks

For frontend integration details, see the Frontend Guide.