# Running on Windows

The code is portable — plain Python and Node. Three things differ: there is no
`make`, the venv sits elsewhere, and `demo_state.sh` is bash. Below is the path
without `make`, command by command.

Verified far enough to matter: the platform dependencies were removed (no
`os.fork`, no POSIX paths, every file opened with `encoding="utf-8"` — without
that, Windows' `cp1252` would break on the first accented character).

---

## 1. Prerequisites

| | version | check with |
|---|---|---|
| Python | 3.11 or newer | `python --version` |
| Node.js | 20 or newer | `node --version` |

If `python` is not recognised, use `py -3` in place of `python` everywhere below.

The Microsoft Store ships a Python "stub" that only opens the Store. If
`python --version` opens the Store, install from
[python.org](https://www.python.org/downloads/windows/) and tick
**Add python.exe to PATH** in the installer.

---

## 2. Unpack

```powershell
cd C:\your\path
Expand-Archive AS0572397_Distributed_Python_React.zip -DestinationPath .
cd as0572397-app
```

---

## 3. Install

```powershell
python -m venv .venv
.venv\Scripts\python -m pip install --upgrade pip
.venv\Scripts\pip install fastapi "uvicorn[standard]" httpx pytest

cd frontend
npm install
cd ..
```

The venv goes to `.venv\Scripts\`, not `.venv/bin/`. That is the only path
difference that matters.

---

## 4. Run the tests

```powershell
.venv\Scripts\python -m pytest
```

Expected: **152 passed**. A `StarletteDeprecationWarning` shows up and is
harmless — it comes from FastAPI, not from the generated code.

---

## 5. Start the application

You need **two terminals**.

**Terminal 1 — the gateway:**

```powershell
cd as0572397-app\services\gateway
..\..\.venv\Scripts\python -m uvicorn main:app --host 127.0.0.1 --port 8080 --reload
```

**Terminal 2 — the frontend:**

```powershell
cd as0572397-app\frontend
npx vite --host 127.0.0.1
```

Open **http://127.0.0.1:5173** — note the numeric address, not `localhost`.

> **Why `127.0.0.1` and not `localhost`.** On Windows `localhost` resolves to
> IPv6 (`::1`) first, and uvicorn listens on IPv4 only. The browser tries `::1`,
> finds nobody, and says *localhost cannot be found* — with the server running.
> The numeric address avoids the whole problem.
>
> To keep `localhost`, make the server listen on both: `--host ::` on uvicorn
> (and `npx vite --host` on the frontend).

---

## 6. Populate a period

**Terminal 3:**

```powershell
cd as0572397-app
powershell -ExecutionPolicy Bypass -File tools\demo_state.ps1
```

It should print `period 2025-12 in CALCULATED`.

In the application, click **open** on period 2025-12.

> Order matters: the script posts the adjustments **before** running F1, because
> the gateway guard blocks writes once the period turns `CALCULATED`. To watch the
> guard work, try posting an adjustment from the screen after the run.

---

## 7. The other targets

```powershell
# equivalence oracle against the workbook's COMPUTED cells
.venv\Scripts\python tools\equivalence_oracle.py

# regenerate TRACEABILITY.md from the live registries
.venv\Scripts\python tools\generate_traceability_matrix.py
.venv\Scripts\python tools\render_traceability_md.py

# typecheck and build the frontend
cd frontend
npx tsc --noEmit
npx vite build
cd ..
```

---

## 8. If you want `make`

With [Chocolatey](https://chocolatey.org/):

```powershell
choco install make
```

The `Makefile` then works as on macOS, **except** the `api` and `dev` targets,
which use `.venv/bin/python`. Run uvicorn as in step 5.

---

## 9. Docker Desktop

```powershell
docker compose up --build
```

Brings up 10 services + PostgreSQL + RabbitMQ + MinIO. **It has never been
executed** — the container the project was generated in has no Docker daemon. If
it fails, `docker-compose.yml` and the two Dockerfiles under `ops/` are a starting
point, not a validated configuration.

---

## 10. Known problems

**`unable to connect to the remote server` from `demo_state.ps1`.** Either the
gateway is not running, or the **corporate proxy** is intercepting.
`Invoke-RestMethod` inherits the system proxy, and a corporate PAC intercepts even
calls to `127.0.0.1` — the error is identical to a server that is down. The script
already disables the proxy for its own session; if you call the API by hand, do
the same:

```powershell
# Windows PowerShell 5.1
[System.Net.WebRequest]::DefaultWebProxy = $null
Invoke-RestMethod http://127.0.0.1:8080/api/v1/health

# PowerShell 7+
Invoke-RestMethod http://127.0.0.1:8080/api/v1/health -NoProxy
```

`curl.exe` (with the `.exe`, so you do not get the PowerShell alias) ignores the
proxy for a local address and serves as the counter-test:

```powershell
curl.exe -s http://127.0.0.1:8080/api/v1/health
```

If `curl.exe` answers and `Invoke-RestMethod` does not, it is the proxy — not the
server.

**`localhost cannot be found` / `ERR_CONNECTION_REFUSED`.** Almost always the
Windows IPv6 behaviour (see the note in step 5). Diagnose in this order:

```powershell
# 1. is the gateway up?
Invoke-RestMethod http://127.0.0.1:8080/api/v1/health
#    expected: status=ok, 9 services

# 2. who is listening on the port?
netstat -ano | findstr ":8080"
netstat -ano | findstr ":5173"

# 3. what does localhost resolve to?
ping -4 localhost
Resolve-DnsName localhost
```

If step 1 works and the browser does not, it is IPv6: use `http://127.0.0.1:5173`.
If step 1 fails, the gateway did not start — look at Terminal 1.

**Gateway on another port.** The script takes the address:

```powershell
.\tools\demo_state.ps1 -Api http://127.0.0.1:8081/api/v1
```

**Port 8080 or 5173 in use.** Change it with `--port 8081` on uvicorn (and adjust
the proxy in `frontend/vite.config.ts`) or `npx vite --port 5174`.

**Windows Firewall prompting.** The first time uvicorn or Vite starts, Defender
may ask for authorisation. Allow it on **private networks**. If you dismissed it
by accident, the server starts but nothing connects.

**Accents rendering wrong in the terminal.** `chcp 65001` before running. It does
not affect the files — all are written as UTF-8 explicitly.

**Line endings.** `.gitattributes` pins LF for everything but `.ps1`. This
repository has already suffered an unwanted LF-to-CRLF conversion; if Git rewrites
the files, check that `.gitattributes` survived.
