This backend is retired. All of its functionality (auth, provider credentials, integrations, commit monitor) was migrated to
ima-agent-backend-python, which is now the only backend. This repo is kept for reference only — do not run it alongside the Python backend.
This service owns authentication, provider credentials, repository imports, project mappings, provider health, and the continuous monitoring scheduler for RecallOps.
It sits between the browser and external providers. GitHub, Vercel, and Render tokens are encrypted per user before being stored. The service sends a short-lived RecallOps JWT to the Python backend when a deployment inspection is required.
- Register and authenticate local users
- Verify Firebase/GitHub sign-in
- Issue RecallOps JWTs
- Encrypt Vercel, Render, and GitHub credentials with AES-256-GCM
- Persist encrypted credential copies in Firestore
- Discover GitHub repositories available to the current user
- Import monitored repositories
- Discover and map Vercel projects and Render services
- Expose provider and deployment health
- Poll GitHub for new commits
- Trigger Python remediation syncs for tracked providers
- Store repository, connection, and workflow state in SQLite
- Node.js 20-24
- npm
- Firebase project with Authentication and Firestore
- Python backend available locally or over HTTPS
- GitHub access token supplied by Firebase sign-in
- Optional Vercel and Render credentials for deployment monitoring
npm install
Copy-Item .env.example .env
npm run devThe API starts on http://localhost:4000 by default.
Run tests with:
npm test| Variable | Purpose |
|---|---|
NODE_ENV |
development, test, or production |
NODE_PORT |
Local listening port; Azure may provide PORT |
NODE_DATABASE_PATH |
SQLite file used for users and integration state |
NODE_CORS_ORIGINS |
Comma-separated allowed frontend origins |
AUTH_JWT_SECRET |
Signs RecallOps JWTs; must match the Python backend |
CREDENTIAL_ENCRYPTION_KEY |
Independent secret used to encrypt provider tokens |
FRONTEND_URL |
Browser URL used after provider callbacks |
PYTHON_BACKEND_URL |
Python agent API base URL |
MONITOR_INTERVAL_MS |
Enables the monitor when greater than zero |
VERCEL_CLIENT_ID |
Sign in with Vercel application client ID |
VERCEL_CLIENT_SECRET |
Sign in with Vercel application secret |
VERCEL_CALLBACK_URL |
Exact registered Vercel callback URL |
VERCEL_SCOPES |
OAuth identity scopes |
FIREBASE_PROJECT_ID |
Firebase Admin project ID |
FIREBASE_CLIENT_EMAIL |
Firebase Admin service account email |
FIREBASE_PRIVATE_KEY |
Firebase Admin private key with escaped newlines |
FIREBASE_SERVICE_ACCOUNT_BASE64 |
Preferred hosted service-account format |
FIREBASE_SERVICE_ACCOUNT_PATH |
Optional local JSON credential path |
Production requires AUTH_JWT_SECRET and CREDENTIAL_ENCRYPTION_KEY to be at
least 32 characters.
Generate independent random values in PowerShell:
[Convert]::ToBase64String([Security.Cryptography.RandomNumberGenerator]::GetBytes(48))Do not use the JWT secret as the credential encryption key. Keep the encryption key unchanged across deployments; changing it makes existing encrypted provider credentials unreadable.
Use one of these methods, in priority order:
FIREBASE_SERVICE_ACCOUNT_BASE64- A local
service-account.json FIREBASE_PROJECT_ID,FIREBASE_CLIENT_EMAIL, andFIREBASE_PRIVATE_KEY
For Azure, convert the service-account file to one Base64 value:
[Convert]::ToBase64String(
[IO.File]::ReadAllBytes(".\service-account.json")
)Store the output in FIREBASE_SERVICE_ACCOUNT_BASE64. Never commit
service-account.json.
Firestore stores only encrypted provider values under:
users/{hashed-owner-id}/providerCredentials/{provider}
The owner ID is a one-way SHA-256-derived identifier. Encryption provides confidentiality and AES-GCM authentication detects tampering. Hashing alone is not used for tokens because the application must decrypt them to call provider APIs.
GitHub is connected during Firebase GitHub sign-in. The resulting access token is scoped to the signed-in user, so repository visibility follows that user's GitHub permissions.
There are two separate connection modes:
- Sign in with Vercel OAuth identifies an account.
- A Vercel personal access token enables project, deployment, and log APIs.
For monitoring, use a token created by a user who belongs to the team that owns
the project. A 403 from Vercel usually means the token can identify the user
but cannot access the requested project/team.
Create a token at https://vercel.com/account/settings/tokens.
Create an API key in Render Dashboard > Account Settings > API Keys. The key owner must have access to the workspace and services being monitored.
- A user imports a GitHub repository.
- RecallOps stores its latest commit as the initial baseline.
- The scheduler checks each repository at its configured polling interval.
- A new commit creates a commit workflow record.
- Mapped Vercel and Render resources are inspected through the Python API.
- Failed deployments are diagnosed and retained as incidents.
- Generated fixes and draft PR results are linked back to the commit workflow.
The scheduler wakes every two seconds, while each repository's
poll_interval_seconds determines whether it is due. MONITOR_INTERVAL_MS=0
disables the scheduler.
Very short intervals are useful for demonstrations but may consume provider API quotas. Use a longer interval in production unless rapid polling is required.
POST /api/auth/registerPOST /api/auth/loginPOST /api/auth/firebaseGET /api/auth/me
GET /api/integrations/statusGET /api/integrations/github/repositoriesPOST /api/integrations/repositories/importGET /api/integrations/repositories/:owner/:repo/activityPATCH /api/integrations/repositories/:owner/:repo/settingsPOST /api/integrations/vercel/tokenGET /api/integrations/vercel/projectsPOST /api/integrations/render/connectGET /api/integrations/provider-healthPOST /api/integrations/provider-health/trackPOST /api/integrations/tracked-projectsDELETE /api/integrations/connections/:providerGET /api/integrations/runtime
All integration routes except the OAuth callback require a RecallOps bearer token.
Deploy this folder as the application root.
- Runtime: Node 22 LTS
- Startup command:
npm start - Persistent SQLite path:
/home/data/auth.db - Enable App Service storage
Import azure-app-settings.json through Configuration > Advanced edit, but
replace placeholders and secrets before applying it. Restart the App Service
after any environment change.
The production callback registered with Vercel must exactly equal:
https://ima-node-ckgjatf7btgeczgd.canadacentral-01.azurewebsites.net/api/integrations/vercel/callback
Enable GitHub in Firebase Authentication.
Check Firebase Admin credentials and ensure the production frontend domain is listed in Firebase Authorized domains.
The application callback, VERCEL_CALLBACK_URL, and the URL registered with
Vercel must match exactly, including HTTPS and path.
Use supported identity scopes for OAuth. Use a personal access token for deployment/project APIs rather than adding unsupported deployment scopes.
Confirm Firestore is reachable, App Service storage is enabled, and the same
CREDENTIAL_ENCRYPTION_KEY is present in every deployment slot.
SQLite is suitable for one App Service instance. Move state to a managed database before scaling to multiple instances.
- Never commit
.env, Firebase private keys, access tokens, or populated Azure settings. - Rotate any credential that has entered Git history.
- Keep
AUTH_JWT_SECRETidentical only between the two trusted backend services. - Keep
CREDENTIAL_ENCRYPTION_KEYprivate to the Node service. - Provider credentials are isolated by authenticated user ID.