# PRD — codescanner

Evidence date: 2026-10-18. Source: `git@bitbucket.org:overdrive/codescanner.git`, `master` at `dc201f67859ee649a7f033194f116479c99aad00` (2021-07-14 14:08:34 +0200, "Update snippets").

There is no prior PRD in Silicon Ark. `readme.md` is empty. Requirements below come from `snippets.txt` and from the batch files. Provenance is marked on each item.

The scan-host checkout named on the onboarding issue was not on this machine. Statements are from a clone of `origin/master`. Passwords, scanner tokens, and the PEM body are not reproduced here.

## Product purpose

An operator uses this repository to point SonarScanner at a SonarQube server, and to start or stop the EC2 instance that hosts that server.

Provenance: **Documented** (`snippets.txt` setup, server details, and saved scan commands) and **Implemented** (`sonar-scanner.bat`, `start.cmd`, `stop.cmd`).

The repository does not contain the code being scanned, and it does not contain the SonarQube server.

## Users and interactions

No role table, login screen, or permission check exists in this repository.

| Actor | What the tree says they do | Provenance |
|---|---|---|
| Operator | Clone the repo, copy `sonar-scanner` to `C:\sonar-scanner`, copy `sonar-scanner.bat` into a code root, create a SonarQube project, run the CLI there | **Documented** (`snippets.txt` steps 1–5) |
| Jaco | The person to ask when the server is not alive, so the instance can be started | **Documented** (`snippets.txt` Server Details) |
| SonarQube admin | Username `admin` is written next to the liveness URL. A password is in the same file and is omitted here | **Documented** username. Secret value not copied |
| Scanner identity | Each saved command passes `-Dsonar.login` with a token. Token values are omitted here | **Documented** that a token is supplied. Values not copied |

Whether anyone other than Jaco may start the instance is **Unknown / Requires Confirmation**.

## Main workflows

### W1 — Install the scanner on a PC

Trigger: an operator follows setup in `snippets.txt`.

1. Clone `https://bitbucket.org/overdrive/codescanner.git` and open `snippets.txt`.
2. Copy the `sonar-scanner` directory to the PC root. The example path is `c:/sonar-scanner`.
3. Copy `sonar-scanner.bat` into the code root of the project that will be scanned. The runbook text is "code route database". That phrase is quoted as written. Reading it as "code root directory" is **Inferred**.

The root `sonar-scanner.bat` sets `SONAR_SCANNER_HOME=C:\sonar-scanner\bin\..`, which matches step 2. Provenance: **Implemented**.

`sonar-scanner/bin/sonar-scanner.bat` sets home from its own directory instead. The runbook does not tell the operator to invoke that file. Provenance: **Implemented**, unused by the written steps.

A checkout of `master` does not contain `lib\sonar-scanner-cli-4.6.2.2472.jar` or `jre\bin\java.exe`. Both launchers set `use_embedded_jre=true` and require those files. Provenance: **Implemented** expectation, **absent** binaries (`.gitignore` excludes `*.jar` and `*.exe`). Whether operators add those binaries locally is **Unknown / Requires Confirmation**.

### W2 — Check that SonarQube is up

Trigger: before a scan, as written under Server Details.

- Open `http://79.125.106.230/sessions/new`.
- If it is not alive, ask Jaco to start the instance.

Provenance: **Documented**. No script performs this HTTP check.

The path `/sessions/new` is the URL the runbook gives. Calling that path the SonarQube login page is **Inferred** from the product named in the same file (SonarQube) and from that path. The file itself only says to check whether the server is alive.

### W3 — Start or stop the instance

Trigger: an operator runs `start.cmd` or `stop.cmd`.

- `start.cmd` runs `aws ec2 start-instances --instance-ids i-009462d8c9b182d5a`.
- `stop.cmd` runs `aws ec2 stop-instances --instance-ids i-009462d8c9b182d5a`.

Neither file sets a region, a profile, an output check, or a prompt. Provenance: **Implemented**.

The notes section shows a different command, `aws ec2 run-instances`, with `--image-id ami-005ec3d100c64ab37`, `--instance-type t3a.medium`, `--region eu-west-1`, and `--profile unity`. That line is not what `start.cmd` runs. Provenance: **Documented** as notes. It does not launch anything by itself.

### W4 — Create a project and scan a code root

Trigger: setup steps 4 and 5, and the block "Commands Already scanned".

1. In SonarQube, create a project with a name and a key. The runbook says "random key", then "copy the cli command".
2. Run that command in the code root, which is the directory that contains the copied `sonar-scanner.bat`.

Every saved command has the same shape:

```text
.\sonar-scanner.bat -D"sonar.projectKey=<key>" -D"sonar.sources=." -D"sonar.host.url=http://79.125.106.230" -D"sonar.login=<token>"
```

`sonar.sources=.` scans the working directory. The host has no port, so the client uses port 80. The scheme is `http`. Provenance: **Documented**.

Recorded projects:

| Label in `snippets.txt` | `sonar.projectKey` | Branch note in the label |
|---|---|---|
| TMT - Pay My Fines | `TMTFrontend` | none |
| TMT - Backend | `TMTBackend` | none |
| My Pass - Regstartion Form | `MyPassRegistration` | Master Branch |
| My Pass - PWA | `MyPassPWA` | Prod branch |
| 1 for the road PWA | `1fortheroadPWA` | Master BranchConn |

The spellings "Regstartion" and "Master BranchConn" are the file's text. Provenance: **Documented**.

The setup sentence says the key is random. The five saved keys are readable names. Provenance of both: **Documented**. Which rule applies to a new project is **Unknown / Requires Confirmation**.

These commands are a record that those scans were written down. They are not proof that those projects still exist on the server. Provenance of "still current": **Unknown / Requires Confirmation**.

The launcher forwards every argument to `org.sonarsource.scanner.cli.Main`. It does not check that `projectKey`, `sources`, `host.url`, or `login` were supplied. Provenance: **Implemented**.

### W5 — Debug the scanner

Trigger: run `sonar-scanner/bin/sonar-scanner-debug.bat`. The runbook does not mention this file.

The script sets `SONAR_SCANNER_DEBUG_OPTS` to JDWP (`transport=dt_socket`, `server=y`, `suspend=y`, `address=8000`), prints that it is in debug mode, and calls `sonar-scanner.bat` in the same directory.

Provenance: **Implemented**. It is the upstream SonarScanner debug script shipped in `sonar-scanner/bin`. No Overdrive-specific debug procedure was found.

## Functional requirements

### FR-001 — Place the scanner at `C:\sonar-scanner`

Requirement: the operator copies `sonar-scanner` to `C:\sonar-scanner` before using the root launcher.

Who: operator. Trigger: setup step 2.

Expected behaviour: the root `sonar-scanner.bat` resolves `SONAR_SCANNER_HOME` to `C:\sonar-scanner` regardless of the directory it was copied into.

Output: a Java process whose classpath is `C:\sonar-scanner\lib\sonar-scanner-cli-4.6.2.2472.jar`.

Validation: the path is hardcoded. There is no check that the directory exists before Java starts.

Error: if `C:\sonar-scanner\jre\bin\java.exe` is missing, the script prints `ERROR: JAVA_HOME exists but does not point to a valid Java home folder` and exits with code 1. `use_embedded_jre` is set to `true` before that check, so `JAVA_HOME` is forced to the embedded `jre` folder.

Provenance: **Documented** step, **Implemented** path and error text.

Evidence: `snippets.txt`, `sonar-scanner.bat`.

Implementation: **Implemented** as a script. The jar and `java.exe` are **not** in the git tree.

Confidence: High for the script. Low for whether a full scanner directory exists on operator PCs.

### FR-002 — Copy the launcher into the project being scanned

Requirement: `sonar-scanner.bat` is copied into the root of the code to scan, and the scan is started with `.\sonar-scanner.bat` from that directory.

Who: operator. Trigger: setup steps 3 and 5.

Inputs: the working directory at launch time. The script sets `PROJECT_HOME` to `%CD%` and strips one trailing backslash.

Expected behaviour: `project.home` passed to the scanner is that code root. `sonar.sources=.` in the saved commands therefore means that same directory.

Error: no check that the copy and `C:\sonar-scanner` are different files. Copying the bat into the scanner's own folder is not described.

Provenance: **Documented** and **Implemented**.

Evidence: `snippets.txt`, `sonar-scanner.bat` (`PROJECT_HOME`).

Implementation: **Implemented**.

Confidence: High.

### FR-003 — Create a SonarQube project, then run the copied CLI command

Requirement: a project is created in SonarQube with a name and a key, and the CLI command from that screen is run in the code root.

Who: operator. Trigger: setup steps 4 and 5.

Inputs: project name, project key, and the token the SonarQube screen puts on the command. The saved commands also send `sonar.sources=.` and `sonar.host.url=http://79.125.106.230`.

Expected behaviour: the scanner process starts and the arguments are forwarded unchanged to `org.sonarsource.scanner.cli.Main`.

Validation in this repo: none. Empty keys, a dead host, and a rejected token are the scanner's and the server's responses. This repo does not catch them except as a non-zero exit from Java (`ERRORLEVEL` 1 sets `ERROR_CODE=1`).

Outputs: process exit code 0 or 1. Scan results live on the SonarQube server. This repo does not store a report.

Provenance: steps **Documented**. Exit code **Implemented**.

Evidence: `snippets.txt`, `sonar-scanner.bat`.

Implementation: the launcher is **Implemented**. Project creation is a manual server step, not code in this repo.

Confidence: High for the launcher. The "random key" wording disagrees with the saved keys. See W4.

### FR-004 — Record the host and the project key on the command line

Requirement: scans in the runbook identify the server and the project only through `-D` properties. They do not use `sonar-scanner/conf/sonar-scanner.properties`.

Who: operator. Trigger: a saved command or a new command of the same shape.

Expected behaviour: `sonar.host.url` is `http://79.125.106.230`. `sonar.projectKey` is one project per command. The properties file leaves `sonar.host.url` and `sonar.sourceEncoding` commented out, with the upstream examples `http://localhost:9000` and `UTF-8`.

Provenance: **Documented** commands, **Implemented** properties file (comments only).

Evidence: `snippets.txt`, `sonar-scanner/conf/sonar-scanner.properties`.

Implementation: **Implemented**.

Confidence: High.

### FR-005 — Start the EC2 instance

Requirement: `start.cmd` asks AWS to start instance `i-009462d8c9b182d5a`.

Who: the person starting the server. The runbook names Jaco when the UI is down. The cmd file itself has no access check.

Trigger: running `start.cmd`.

Inputs: the AWS CLI's existing credentials, region, and output settings. The file adds only the instance id.

Expected behaviour: one `aws ec2 start-instances` call. No wait for the instance to reach running. No poll of `http://79.125.106.230/sessions/new`.

Error: if the AWS CLI is missing, unauthenticated, or pointed at the wrong region, the failure is whatever the AWS CLI prints. The cmd file does not branch on that.

Provenance: **Implemented**. The link from "server not alive" to this script is **Inferred** (the runbook says ask Jaco to start the instance; `start.cmd` is the only start script).

Evidence: `start.cmd`, `snippets.txt`.

Implementation: **Implemented**.

Confidence: High for the command. Medium for the inference that this file is how Jaco starts it.

### FR-006 — Stop the EC2 instance

Requirement: `stop.cmd` asks AWS to stop the same instance id.

Who: whoever runs the file. No rule says when a stop is allowed.

Trigger: running `stop.cmd`.

Expected behaviour: one `aws ec2 stop-instances` call. No drain of running scans. No confirmation prompt.

Error: same as FR-005. The file does not handle a failed call.

Provenance: **Implemented**. A business rule for when to stop was **not found**.

Evidence: `stop.cmd`.

Implementation: **Implemented**.

Confidence: High.

### FR-007 — Treat a down server as a request to Jaco

Requirement: if `http://79.125.106.230/sessions/new` does not show the server as alive, the operator asks Jaco to start the instance.

Who: operator, then Jaco. Trigger: the server check in `snippets.txt`.

Inputs: the HTTP response the operator sees. The repo does not define what "alive" looks like.

Expected behaviour: human handoff. There is no ticket, email, or health endpoint in this repo.

Error: not specified.

Provenance: **Documented**.

Evidence: `snippets.txt`.

Implementation: procedure only. No code.

Confidence: High that the sentence exists. Low that it is still the operating rule in 2026.

## Integrations

### SonarQube

| | |
|---|---|
| Purpose | Store projects and receive scans |
| Trigger | Operator runs `sonar-scanner.bat` after creating a project |
| Direction | PC to server |
| Data sent | `sonar.projectKey`, `sonar.sources=.`, `sonar.host.url`, `sonar.login` token, and the files under the working directory |
| Data received | Not stored in this repo. Scanner stdout is the process output |
| Authentication | Token on the command line (`sonar.login`). A separate admin username is written in `snippets.txt` for the UI |
| Transport | `http` on port 80, host `79.125.106.230` |
| Failure | Non-zero Java exit becomes exit code 1. No retry |

Provenance: **Documented** and **Implemented**. Whether the host still answers is **Unknown / Requires Confirmation**.

### AWS EC2

| | |
|---|---|
| Purpose | Start or stop one instance. Notes also show how to run a new instance |
| Trigger | `start.cmd`, `stop.cmd`, or the example `run-instances` line typed by hand |
| Direction | PC to AWS API, via the AWS CLI |
| Data sent | Instance id `i-009462d8c9b182d5a` on start and stop. The example launch also sends AMI, type, region, and profile |
| Authentication | Whatever the AWS CLI is already configured to use. Profile `unity` appears only on the example launch |
| Failure | Not handled in the cmd files |

Provenance: **Implemented** for start and stop. **Documented** for the example launch.

### References that are not integrations

`snippets.txt` links to a Baeldung AWS CLI article and a Bitnami SonarQube AMI page. Nothing in the repo calls those URLs. Provenance: **Documented** links.

## Constraints

- Launchers are Windows batch files. No shell script for Linux or macOS is in the tree. The Baeldung link is a Linux article. Provenance: **Implemented** scripts, **Documented** link.
- Embedded JRE is forced on (`use_embedded_jre=true`). Provenance: **Implemented**.
- Scanner install path for the copied bat is `C:\sonar-scanner`. Provenance: **Implemented**.
- One instance id. Provenance: **Implemented**.
- Scanner and UI URLs are HTTP, not HTTPS. Provenance: **Documented**.
- `.gitignore` drops `*.jar` and `*.exe`, so the published tree cannot run a scan. Provenance: **Implemented**.
- `sonarqubekey.pem` is an RSA private key committed in `2f01cda`. No batch file, cmd file, or runbook line references it. Provenance: **Implemented** file. Use **Unknown**.

## Behaviour the issue listing suggested, which is not in git

The 2026-09-28 file list included `sonar-project.properties` and `sonarqube_scan.bat`. They are not in `dc201f6`. No requirement for a per-repo `sonar-project.properties` or a `sonarqube_scan.bat` wrapper can be taken from this commit. Provenance: **Unknown**.

## Assumptions not made

- That the EC2 instance is still running, stopped, or terminated.
- That the admin password or any `sonar.login` token still works.
- That `sonarqubekey.pem` is the SSH key for that instance. The filename suggests it. That is **Inferred** and unconfirmed.
- That the five project keys are the full set of SonarQube projects.
- That AMI `ami-005ec3d100c64ab37` is the Bitnami image named by the neighbouring URL.
