# Technical documentation — DoctorX_Josh

Evidence date: 2026-10-16.

Source: `git@bitbucket.org:overdrive/doctorx_josh.git`, `master` at `01973b1` (2021-05-04, Joshua Gatley-Dewing).

Ids below are the values committed in `src/aws-config.js`. They are browser configuration, not a database password. No `.env` is tracked. No database password is in git.

## What this repository is

A private Create React App (`package.json` name `doctorx_josh`, version `0.1.0`) titled Doctor X. It is a single-page client. It does not contain Lambda handlers on the tip.

`77de4c8` (2021-03-17) added four calendar Lambda files under `lambda/`. `b0527bc` the same day deleted that directory. The tip has no `serverless.yml`, no Dockerfile, and no CI config.

`README.md` still heads the project "Unity - Lite Demo" and says to use Amplify and Lambda. `LoaderButton.js` cites `https://github.com/AnomalyInnovations/serverless-stack-demo-user-mgmt-client` under the MIT licence.

`jsconfig.json` sets `compilerOptions.baseUrl` to `./src`, so imports such as `routes`, `utils`, and `components` resolve from `src/`.

## Repository layout

```text
package.json
yarn.lock
jsconfig.json
README.md
.gitignore
public/index.html          title "Doctor X", Bootstrap 4.3.1 CDN, W3.CSS CDN, Raleway
public/manifest.json       name "Doctor X by Josh", display standalone
public/favicon.ico
src/index.js               Amplify.configure, render, serviceWorker.unregister
src/aws-config.js          region, bucket, API URL, Cognito ids
src/App.js                 particles background and Routes
src/App.test.js            one render test
src/serviceWorker.js       CRA worker, not registered
src/index.css
src/routes/                public, private, auth gate, allowed-route map
src/config/Roles.js
src/config/PrivateRoutesConfig.js
src/components/            screens and unityRequests.js
src/components/common/     TopNav, JumbotronWrapper, LoaderButton, NotFound
src/components/makeData.js unused namor fixture
src/utils/index.js         localStorage session helpers
src/utils/history.js       createBrowserHistory
src/assets/                fonts and images
```

Not in `git ls-files` at `01973b1`: `node_modules/`, `build/`, `.env`, `.storybook/`, `sonar-project.properties`, `sonarqube_scan.bat`. The onboarding issue listed the two Sonar files in the scan-host working tree on 2026-09-28. They were not in this clone.

## Stack

| Layer | Choice in the tip |
|---|---|
| UI | React 16.8.6, React DOM 16.8.6 |
| Build | `react-scripts` 3.0.1 (`start`, `build`, `test`, `eject`) |
| Routing | `react-router-dom` 5.2.0 and the `history` package via `createBrowserHistory` |
| Components | `react-bootstrap` 1.0.0-beta.10, Bootstrap 4.3.1 (CDN in `index.html` and the npm package) |
| CSS extras | W3.CSS and Google Fonts Raleway from public CDNs in `index.html` |
| AWS | `aws-amplify` 3.3.21 |
| Tables | `react-table` 7.6.3 |
| Roles UI | `react-multiselect-dropdown-bootstrap` 1.1.0 |
| Other imported libs | `lodash` 4.17.15, `particles-bg` 2.5.0, `react-newline-to-break`, `@strongdm/glyphicon` |
| Declared, no `src/` import | `@fullcalendar/*` 5.5, `chartist` / `react-chartist`, `react-trello` |
| Tests | `react-scripts test` (Jest). One test: render `App` and unmount |
| Format | `yarn pretty` → Prettier 1.18 with tabs, single quotes, always arrow parens. No config file |
| Stories | `@storybook/react` 5.2 scripts `storybook` (port 6006) and `build-storybook`. Stories exist for `JumbotronWrapper` and `NotFound`. No `.storybook` directory is tracked |
| Lockfile | `yarn.lock` only |
| Node on the build machine | **Unknown.** `package.json` has no `engines` field. Create React App 3 expects a Node 8–12 era toolchain |

`browserslist` production: `>0.2%`, `not dead`, `not op_mini all`. Development: last one version of Chrome, Firefox, and Safari.

## Application structure

`src/index.js` configures Amplify, then `ReactDOM.render(<App />)`.

`App` wraps `Routes` in a fluid Bootstrap container and a `particles-bg` cobweb (`color` `#9EFF76`, `num` 150).

`Routes` (`src/routes/index.js`) uses a `Router` with the browser history from `src/utils/history.js`:

| Path | Handler |
|---|---|
| `/app` | `PrivateRoutes` |
| everything else | `Auth` → `PublicRoutes` if logged out, else redirect `/app/home` |

Public `Switch` order:

| Path | Component |
|---|---|
| `/forgot-password` | `ForgotPassword` |
| `/register` | `Register` |
| `/login` | `Login` |
| empty (fallback) | `LandingPage` |

Private routes (`src/config/PrivateRoutesConfig.js`), prefixed with `/app` by `MapAllowedRoutes`:

| Path | Title | permission |
|---|---|---|
| `/home` | Home | none |
| `/diagnosis` | Diagnosis | none |
| `/users` | Users | `[SUPER_ADMIN]` |
| `/profile` | My Profile | none |

`TopNav` links to `` `${prefix}${path}` ``. For the private shell, `prefix` is the `/app` match. Landing links have an empty prefix.

`JumbotronWrapper` is wrapped in the `CenterToScreen` HOC and turns `\n` in `description` into breaks. If `description` is omitted, the default prop is a Lorem Ipsum paragraph. Home, login, and the other screens pass a string, including `""`.

## Auth

Amplify Auth config in `src/index.js`:

| Key | Value |
|---|---|
| `mandatorySignIn` | `true` |
| `region` | `eu-west-1` |
| `userPoolId` | `eu-west-1_qAilrD6X0` |
| `userPoolWebClientId` | `66ajgtvc57ig3rh5hivfmat2a` |
| `identityPoolId` | `eu-west-1:f4892151-eb6c-4e57-8b44-971cf1b1ad65` |

Calls:

| Screen | Amplify API |
|---|---|
| Login | `Auth.signIn` |
| Register | `Auth.signUp`, `Auth.confirmSignUp`, `Auth.signIn`, `Auth.resendSignUp` |
| Forgot password | `Auth.forgotPassword`, `Auth.forgotPasswordSubmit` |
| Users dialog | `Auth.adminCreateUser`, `Auth.resendSignUp` |
| Logout | `Auth.signOut` |

Router authorisation does not call Amplify. It uses `localStorage`:

| Key | Written by login | Cleared on logout |
|---|---|---|
| `roles` | `body.strRole` from `/josh/getuuid/` | yes |
| `userDetails` | JSON `{ doctorID, name, surname, userGroup }` where `userGroup` is the pool id | yes |

`debugger` statements remain in `Login.js`, `Register.js` (two), and `Profile.js`.

There is no refresh-token handling, no route guard around API 401, and no CSRF token in this tree.

## API

Amplify API endpoint name `unity`:

```text
https://nhyfbveswk.execute-api.eu-west-1.amazonaws.com/prod
```

Region `eu-west-1`. Until `01973b1` the host was `2dg2tax5pg`.

`unityRequests(path, vars, action)` (`src/components/unityRequests.js`):

- `action === "get"` → `API.get(apiName, path, vars)`.
- Any other action, including the default → `API.post(apiName, path, { body: vars })`.

No call site passes `"get"`. `Auth.currentSession()` is commented out. Amplify 3 will attach credentials when a user is signed in. What authorizer the deployed API requires is **Unknown** from this repo alone. `DoctorX_lambda_api_Josh` documents `authorizer: aws_iam` on the same path strings.

| Caller | Method | Path string as written | Body |
|---|---|---|---|
| `Login.js` | `API.post` | `/josh/getuuid/` | `{ strEmail }` |
| `Login.js` | post via helper | `/josh/update/` | `{ DoctorID, strEmail, dtLastLoggedIn }` |
| `Register.js` | `API.post` | `/josh/getuuid/` | `{ strEmail }` |
| `Register.js` | post via helper | `/josh/create/` | new doctor fields, `strRole` string `['GUEST']` |
| `Register.js` | post via helper | `/josh/update` | `{ DoctorID, strEmail, refUserID }` |
| `Profile.js` | post via helper | `/josh/get/` | `{ id }` |
| `Profile.js` | post via helper | `/josh/update/` | `{ DoctorID, strName, strSurname, strEmail, strCity }` |
| `Users.js` | post via helper | `/josh/getusers/` | `{}` |
| `Users.js` | post via helper | `/josh/create/` | doctor fields, `strRole` array, `userPoolID`, `strUserCreatedName` |
| `Users.js` | post via helper | `/josh/update/` | doctor fields without `strUserCreatedName` |
| `Diagnosis.js` | post via helper | `/josh/diagnose` | `{ type, model, xray, diagnosis }` |

Login and profile and users and diagnosis do `JSON.parse(body)` and, except `getusers`, take `[0]`. The helper returns the Amplify result unchanged. Double-encoding would be a property of the API. `DoctorX_lambda_api_Josh` technical documentation says its handlers stringify twice. Whether this client is talking to that deployment is **Unknown / Requires Confirmation**.

Trailing slashes are not consistent. Register's update and the diagnose path omit the trailing slash. The other paths include it.

## Storage

| Key | Value |
|---|---|
| `s3.REGION` | `eu-west-1` |
| `s3.BUCKET` | `unity-lite-files` |
| `MAX_ATTACHMENT_SIZE` | `5000000` |

`Amplify.configure` sets `Storage.region`, `Storage.bucket`, and `Storage.identityPoolId`. No file under `src/` imports `Storage` from Amplify or reads `MAX_ATTACHMENT_SIZE`.

The bucket name string is the same one recorded for Silicon Ark projects `unity-lite` and `unity-soft-ui`. Whether it is one bucket is **Unknown / Requires Confirmation**.

## Data

This repository has no database client, migration, or schema. Doctor fields are JSON keys on API bodies (see `business-rules.md`). `localStorage` is the only durable store in the browser, and logout deletes the two keys.

## Background work, queues, monitoring

None in this repository. No worker, cron, SQS, SNS, or log client. Errors use `console.log` and `alert`.

`src/serviceWorker.js` can register a CRA worker in production. `src/index.js` calls `unregister()`, so that path does not run.

## Security notes visible in the tree

These are observations, not a pentest.

- Cognito app client id, user pool id, identity pool id, API URL, and bucket name are in source and therefore in the built bundle.
- Route protection is a `localStorage` item. Anyone who can set `roles` to a JSON array containing `SUPER_ADMIN` can render the Users screen. The API may still reject the calls. That split is **Implemented** on the client and **Unknown** on the server.
- `Auth.adminCreateUser` is invoked from the users dialog in the browser bundle.
- Registration terms are not stored on the doctor payload.
- `debugger` statements will pause DevTools on login, registration confirmation, and profile save.
- Third-party scripts and CSS are loaded from `maxcdn.bootstrapcdn.com`, `www.w3schools.com`, and `fonts.googleapis.com` (`public/index.html`).
- `.gitignore` ignores `node_modules/`, `dist/`, logs, IDE files, and common media extensions. It does not name `.env`. No `.env` is tracked anyway, because configuration is hard-coded.

## Build, test, and run

**Documented** in `README.md`:

```text
yarn install
yarn start
```

Other scripts in `package.json`: `yarn build`, `yarn test`, `yarn eject`, `yarn pretty`, `yarn storybook`, `yarn build-storybook`.

`src/App.test.js` renders `<App />` into a detached div. It does not mock Amplify. Whether that test passes was not executed during this documentation pass.

No pipeline file (Bitbucket Pipelines, GitHub Actions, Jenkins), no Dockerfile, and no hosting config (`amplify.yml`, S3 website, CloudFront) is in git. Where a production build is deployed is **Unknown / Requires Confirmation**.

## Related repositories

| Repo / Silicon Ark directory | Relationship evidenced from this tree |
|---|---|
| `DoctorX_lambda_api_Josh` | This client calls `/josh/create`, `/josh/getusers`, `/josh/update`, `/josh/get`, `/josh/getuuid`, `/josh/diagnose`. That Silicon Ark set documents those POST paths on service `josh-lambda-api`. The API id `nhyfbveswk` is not in the lambda repo. Pairing is **Inferred** |
| `unity-lite`, `unity-soft-ui` | Shared bucket name string `unity-lite-files`. This README says "Unity - Lite Demo". The first app commit included calendar Lambdas that were removed the same day. Pool and API host equality is **Unknown** |

## Human confirmation

- Node version this app was built with, and where the production bundle is hosted.
- That gateway `nhyfbveswk` is the `josh-lambda-api` stage `prod`.
- Cognito password policy, MFA, and app-client secret (none is in `aws-config.js`).
- Whether `adminCreateUser` from this bundle is intentional.
- Whether Sonar files on the scan host should be treated as part of the project.
