2. Set up a development environment¶
This tutorial takes you from a clean machine to a local C-PAT instance you can sign in to, with the API and client running from source and both test suites passing. It works on Windows and Linux. Expect it to take about an hour the first time, most of it waiting on downloads.
2.1. Prerequisites¶
Install the following before you begin:
Node.js 22.12 or later. The API declares
"node": ">=22.12.0"inapi/package.json, and both packages setengine-strict = truein their.npmrc, so an older Node refuses to install dependencies. CI runs on Node 22.Git.
Docker. You use it for the identity provider, the database, and the documentation build. Docker Desktop on Windows works with the commands below.
MySQL 8.0.24 or later, in a container or installed locally. The API checks the server version at startup (
minMySqlVersioninapi/Services/utils.js) and refuses anything older. The MySQL event scheduler must be on; it is on by default in MySQL 8.0, and a migration creates a scheduled event that updates POAM statuses.The demonstration identity provider,
nswccrane/c-pat-authon Docker Hub. It is a Keycloak image with theRMFToolsrealm, thec-patandstig-managerclients, and the roles C-PAT expects.
STIG Manager and Tenable.sc are optional. Without them the client hides the integration pages through the features block of its runtime configuration. The stig-manager OIDC client must still exist in the realm, because the web client authenticates against both clients before it shows any page; the demonstration realm includes it.
2.2. Start the supporting services¶
Start Keycloak and MySQL as containers. The API’s defaults expect Keycloak on port 8080 and MySQL on port 3306 of localhost.
docker run -d --name c-pat-auth -p 8080:8080 nswccrane/c-pat-auth
docker run -d --name c-pat-mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=change-me mysql:8.0
docker run -d --name c-pat-auth -p 8080:8080 nswccrane/c-pat-auth
docker run -d --name c-pat-mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=change-me mysql:8.0
The c-pat-auth README on Docker Hub lists the maintained run script and the test accounts the realm ships with (admin and user01 through user05). The Keycloak admin console is at http://localhost:8080.
Create the database and the account the API will use. Connect to MySQL as root and run:
CREATE DATABASE cpat;
CREATE USER 'cpat'@'%' IDENTIFIED BY 'change-me';
GRANT ALL ON cpat.* TO 'cpat';
You should see three Query OK responses. The API creates every table itself on first start. The Database page explains the account requirements and suggested server settings.
2.3. Configure the API¶
The API reads its configuration from environment variables, and in development from a .env file in the api/ directory. dotenv loads the file from the working directory, so always start the API from api/.
Clone the repository and copy the template:
git clone https://github.com/NSWC-Crane/C-PAT.git cd C-PAT\api Copy-Item example_env.txt .env
git clone https://github.com/NSWC-Crane/C-PAT.git cd C-PAT/api cp example_env.txt .env
Open
.envand set the database values to match the container you started:CPAT_DB_HOST=localhost,CPAT_DB_PORT=3306,CPAT_DB_SCHEMA=cpat,CPAT_DB_USER=cpat, andCPAT_DB_PASSWORD.Set
CPAT_OIDC_PROVIDER=http://localhost:8080/realms/RMFTools.Set
CPAT_SWAGGER_ENABLED=trueso the API serves Swagger UI at/api-docs.Optionally set
CPAT_LOG_LEVEL=4to log request and response bodies, andCPAT_DEV_RESPONSE_VALIDATION=logOnlyto have the OpenAPI validator log responses that do not match the contract. Both are development conveniences; leave them unset in any deployed environment.
The full variable reference is in Environment Variables.
Warning
The API refuses to start when the identity provider publishes a signing key that the API recognizes as a shared demonstration key. If the startup log reports an insecure signing key, you are using the demonstration realm. Set CPAT_DEV_ALLOW_INSECURE_TOKENS=true in .env on your development machine only. Never set it anywhere a real user can sign in.
2.4. Run the API¶
Install the dependencies from the lockfile and start the server:
npm ci
npm start
The API logs one JSON object per line. On the first start you should see, in this order:
A
bootstrapUtilsrecord with the version and the effective configuration (the database password is masked).A
serverrecord of typelisteningreporting port 8086 and the paths/api,/docs, and/api-docs. The port is open at this point, but requests are not served yet.oidcrecords as the API fetches the provider’s discovery document and signing keys.mysqlrecords: the empty schema is populated fromapi/Services/migrations/sql/current/, then every migration inapi/Services/migrations/runs and logsmigrationrecords withstatusvaluesstart,running, andfinish.A
serverrecord of typestartedwith the startup duration.
Until both the database and the identity provider are ready, every request receives 503 Service Unavailable with a JSON body describing the API state. That is the availability gate, not a failure; wait for the started record. Requests to /docs return 404 until you build the documentation in a later step.
2.5. Run the client¶
The client runs from source with the Angular dev server on port 4200 and calls the API on port 8086.
Install the dependencies. The
--forceflag is required; the reason is on the Dependencies and upgrades page.cd ../client npm install --force
Create the development index page from its template. The dev server uses
src/development.htmlas its index, and that file is git-ignored so that every developer can hold local values in it.Copy-Item src\development.example.html src\development.html
cp src/development.example.html src/development.html
Open
src/development.htmland edit theCPAT.Envobject near the top. In production the API injects this object; in development you maintain it by hand. ConfirmapiBaseishttp://localhost:8086/api,client.authorityandoauth.authorityarehttp://localhost:8080/realms/RMFTools,oauth.clientIdisc-pat, andstigman.clientIdisstig-manager. Setstigman.apiUrlto your STIG Manager API if you run one. Setprimeng.licenseto your own PrimeNG license key, or leave it empty and accept the license notice in the client.Start the dev server and open
http://localhost:4200:npm start
You should see the compilation finish with bundle generation complete and the browser redirect to the Keycloak sign-in page.
Warning
src/development.html is ignored by git on purpose. Never commit it, and never copy a license key from it into a tracked file.
2.6. Sign in and activate your user¶
Sign in with one of the realm’s test accounts. The client authenticates against the stig-manager client first and then the c-pat client, so you may see two redirects. On the first sign-in the API creates your user record with the account status PENDING, and the client shows the not-activated page.
An administrator activates accounts in the Admin Portal, under User Management, by setting the account status to ACTIVE. Administrators are users whose token carries the admin realm role; in the demonstration realm, sign in as admin to do this. See Administration Portal.
If no account in your realm carries the admin role, activate your first user directly in the database:
UPDATE cpat.user SET accountStatus = 'ACTIVE' WHERE userName = 'admin';
Reload the client. You should see the home page. Users also need a permission on at least one collection before they can see data; an administrator grants those in the Admin Portal as well.
2.7. Verify the setup¶
Open
http://localhost:8086/api-docs. Click Authorize, sign in, and callGET /user. You should get your own user record as JSON. Swagger UI uses the same PKCE flow as the client.Run the API tests from
api/:npm test
The Node.js test runner prints one line per test and ends with
# passand# fail 0counts.Lint the API contract from
api/:npm run lint:spec
Redocly prints
Woohoo! Your API description is validwhen the contract passes.Run the client tests from
client/:npm run test:run
Vitest ends with a summary of test files and tests passed.
2.8. Run the production shape locally¶
In production the API serves the built client and the built documentation itself. To see that shape:
Build the client and start the API in one command from
api/:npm run offline-rebuild
The API serves the bundle from
../client/dist/browser(theCPAT_CLIENT_DIRECTORYdefault). Openhttp://localhost:8086.Build the documentation so
/docsworks. The build runs in a container; on Windows, run it from PowerShell, because Git Bash rewrites the volume path and the build fails withconfig directory doesn't contain a conf.py file.cd ..\docs docker build -t sphinx-w-requirements . docker run --rm -v "${PWD}:/docs" sphinx-w-requirements make html
cd ../docs ./build.sh
Open
http://localhost:8086/docs. See Documentation for the build in detail.
Note
Two Windows details save time. Git Bash converts POSIX-style paths in Docker volume arguments; use PowerShell or set MSYS_NO_PATHCONV=1. And core.autocrlf is usually true on Windows checkouts; if a formatter run produces changes in every file, you ran one package’s formatter over the other package’s files. See Coding standards.
2.9. Next steps¶
Read Architecture overview to learn how a request travels from the browser to the database.
Read Coding standards before your first change.
Follow Add an API endpoint for a complete walk-through of a feature.