This document provides essential information for autonomous AI agents working on the Gram codebase.
Gram is Klarna's threat model diagramming tool—a web application for collaboratively creating threat models with dataflow diagrams. It consists of a React frontend, Express backend API, and shared core library using TypeScript and PostgreSQL.
Repository: git@github.com:klarna-incubator/gram.git
npm install
docker compose up -d
npm run build
npm run devThis sequence:
- Installs all dependencies for the monorepo workspace
- Starts PostgreSQL containers for development and testing
- Builds the API and frontend applications
- Starts both backend API (http://localhost:8080) and frontend (http://localhost:4726)
Use email user@localhost or admin@localhost (hardcoded test users by default). The login link will appear in application logs.
Monorepo Structure (Lerna + npm workspaces):
app/- React frontend for threat modeling UI (Port 4726)api/- Express.js backend API (Port 8080)core/- Shared library with business logic, data access, validationconfig/- Configuration management and plugin loadingplugins/- Optional plugins (GitHub, Jira, OIDC, LDAP, AWS, Azure, Kubernetes, etc.)
Key Technologies:
- TypeScript 5.2 with strict mode
- ESLint + Prettier for code quality
- Jest for testing
- PostgreSQL for data persistence
- Express + WebSocket for real-time collaboration
- React 17 + Redux for frontend state
npm run build # Build API + App (main packages)
npm run build-backend # Build only backend (API + core)
npm run build-all # Build all packages including plugins
npm run clean # Remove all build artifactsnpm run dev # Start backend API + frontend (parallel) - restart for backend changes
npm run start-backend # Start API only (http://localhost:8080)
npm run start-frontend # Start React app only (http://localhost:4726)
npm run debug # Start backend with Node debugger (--inspect)npm run lint # Check formatting and linting (all packages)
npm run lint-fix # Auto-fix formatting issues
npm test # Run all tests (jest)
npm run snyk # Security vulnerability scanningStart services: docker compose up -d
Connect to development database:
scripts/local-psql.sh # Development database
scripts/test-psql.sh # Test databaseRun all tests (monorepo):
npm testRun tests for specific package:
npm -w @gram/api test
npm -w @gram/app test
npm -w @gram/core testTests are configured with:
- Jest as test runner
- TypeScript support (ts-jest)
- Database isolation for integration tests (--runInBand, in-memory/test containers)
- 50+ test files across API and core packages
- Frontend tests with jsdom environment
Test locations:
- API:
api/src/**/*.spec.ts(50+ files) - App:
app/src/**(jest config) - Core:
core/src/**/*.spec.ts(25+ files)
- camelCase for functions, variables, properties
- PascalCase for classes, interfaces, React components
- CONSTANT_CASE for constants
- Configured via ESLint @typescript-eslint/naming-convention
- Enforced by Prettier (2-space indentation)
- Follow Conventional Commits
- Format:
type(scope): description - Example:
feat(api): add threat validation endpoint - Types:
feat,fix,chore,docs,refactor,test,perf
- Keep changes focused (one feature/fix per PR)
- Include test cases for new features and bug fixes
- All tests must pass
- Code must follow existing style (run
npm run lint-fixbefore pushing)
Install/update dependencies:
npm install # Install all workspace deps
npm -w @gram/api install # Install in specific workspace
npm install <package> # Add to root (shared)
npm install -w api <package> # Add to specific workspacePublishing packages (release):
npm run version # Lerna version bump with conventional commitsEnvironment Variables:
Copy .env.example to .env and fill in required values:
cp .env.example .envSee .env.example for complete list of environment variables including:
- REQUIRED:
NODE_ENV,ORIGIN,AUTH_SECRET, Database credentials (POSTGRES_*) - OPTIONAL: Email config (EMAIL_*), Sentry (SENTRY_DSN), Frontend (PORT, REACT_APP_VERSION)
The config/ package loads environment-specific configurations:
config/default.ts- Base configurationconfig/development.ts- Development overridesconfig/staging.ts- Staging overridesconfig/production.ts- Production overrides
Set NODE_ENV to load appropriate config:
NODE_ENV=development npm run dev
NODE_ENV=production npm run buildImportant Security Notes:
- Never commit
.envto version control (.envis in.gitignore) - Generate a strong
AUTH_SECRETfor production:openssl rand -base64 32 - Use strong passwords for
POSTGRES_PASSWORD - Ensure
.envcontains no committed secrets
Add plugin to config:
npm -w config install @gram/<pluginname>Then update config/default.ts to load the plugin.
Available plugins: GitHub, Jira, OIDC, LDAP, AWS, Azure, Kubernetes, Threat Library, STRIDE, CNCF, SVG Porn (logo library)
Docker Build (single container):
docker build -t gram:latest .
docker run -e POSTGRES_HOST=db -p 4726:4726 gram:latestDocker Compose (demo):
docker-compose -f docker-compose.demo.yml up --buildSet environment variables before deployment. Application runs as single Express server with WebSocket support (not horizontally scalable yet).
Backend debugging:
npm run debug # Starts with --inspect=127.0.0.1:9229Use Chrome DevTools (chrome://inspect) or VS Code debugger.
Logs:
- Application logs appear in console during
npm run dev - Magic login link shown in debug logs:
[DEBUG] MagicLinkIdentityProvider - Sending magic link...
Database:
docker compose up -d # Start services
scripts/local-psql.sh # Connect to dev DB
scripts/test-psql.sh # Connect to test DB| Path | Purpose |
|---|---|
package.json |
Root monorepo config (Lerna, workspaces) |
tsconfig.json |
TypeScript config with path aliases |
api/src/ |
Backend API routes and logic |
app/src/ |
React frontend components |
core/src/ |
Shared business logic, data access |
config/ |
App configuration and plugins |
plugins/*/ |
Optional plugin implementations |
.github/workflows/ |
CI/CD pipelines (test, lint, build) |
docker-compose.yml |
Local development services |
Tests fail with "lerna: command not found":
npm install # Re-install node_modulesBackend doesn't rebuild on changes:
npm run devrequires restart after backend changes- Run
npm run buildmanually then restart
Cannot login (no magic link):
- Check console logs for the login URL
- Default test users:
user@localhost,reviewer@localhost,admin@localhost
Database connection issues:
docker compose logs database # View Docker logs
docker compose restart # Restart services
docker compose down -v # Remove containers and volumes
docker compose up -d # Recreate freshPort conflicts:
- Frontend: http://localhost:4726 (set with PORT env var)
- Backend API: http://localhost:8080 (hardcoded in app proxy)
- Postgres dev: localhost:5432
- Postgres test: localhost:5433
Workflows (.github/workflows/):
ci.yml- Runs on all branches: install → build → test → lintdocker-publish.yml- Publishes Docker image on tag (v*..) to GHCR
Pre-merge checks:
- All tests pass
- Lint check passes
- Build succeeds
- Threat Modeling: See README.md for feature overview
- Contributing: See CONTRIBUTING.md for guidelines
- Deployment: See QuickStart.md for deployment setup
- Development Details: See Development.md for technical details