# Technical documentation — blindside (BlindSide)

Evidence date: 2026-10-19. Source: `git@bitbucket.org:overdrive/blindside.git`, `master` at `25a8c70` (2019-06-17, "new styling", Jaco Brits).

Secrets are named by location. The literal API key in `core/routes/routes.js` is not copied here.

## Repository

| Item | Value |
|---|---|
| Origin | `git@bitbucket.org:overdrive/blindside.git` |
| Default branch | `master` (`origin/HEAD`) |
| Tip | `25a8c70` — 2019-06-17 — Jaco Brits |
| First commit | `fa31734` — 2019-05-31 — "Pipeline Setup" |
| Other remote branches | None |
| Tags | None |
| Tracked files at tip | 2548 |
| README, product licence, changelog | None. Vendor readmes exist only under CKEditor |
| Tests | None found |
| Application manifest | No `package.json`, `composer.json`, or `requirements.txt` for the site. The pipeline installs `boto3==1.3.0` at run time |

Authors on the 13 commits: Jaco Brits and siliconoverdrive.

A scan that created the onboarding task listed `sonar-project.properties` and `sonarqube_scan.bat` at the repository root. Neither path appears in `git log --all`. **Unknown / Requires Confirmation**.

The task-creation local path `~/projects/sonar_scan/repos/blindside` was not on the machine used for this pass. The clone used for these notes is `master` at the same commit the task named.

## Architecture

BlindSide is a static site. Apache is expected to serve the files. The browser loads `index.html`, and jQuery injects HTML fragments into named divs. There is no server-side renderer, no API process in this repository, and no database.

```text
index.html
  ├── assets/css, assets/js          Limitless / Bootstrap / jQuery
  ├── core/controller/common.js      cookie helpers (unused by the live path)
  ├── core/routes/routes.js          ready handler and .button switch
  └── fragments loaded on demand
        ├── core/view/login/login.html
        ├── core/view/headerTopNav.html
        ├── core/view/headerContent.html
        ├── core/view/headerDesctiption.html
        ├── core/view/footer.html
        ├── core/view/dashboard/mainDashboard.html
        │     └── core/controller/dashboard.js
        │           ECharts + FullCalendar
        ├── core/view/member/*.html
        └── core/view/organisastion/*.html

template/                              Limitless demo pages (not the entry point)
appspec.yml + scripts/                 CodeDeploy hooks for httpd
bitbucket-pipelines.yml
codedeploy_deploy.py                   S3 upload and CodeDeploy API
```

`template/index_4.html` is an older shell (title BlindSide) that also loads `routes.js`. It additionally requests `core/controller/main.js`, which is not in the tree, and it loads `dashboard.js` from the head rather than from the fragment. `index.html` does not link to it.

## Application structure

### Entry

`index.html` sets the title BlindSide, pulls Roboto from Google Fonts, and loads local styles:

- `assets/css/icons/icomoon/styles.min.css`
- `assets/css/bootstrap.min.css`
- `assets/css/bootstrap_limitless.min.css`
- `assets/css/layout.min.css`
- `assets/css/components.min.css`
- `assets/css/colors.min.css`

Scripts in the shell: jQuery, Bootstrap bundle, BlockUI, Slinky, FAB, D3, Switchery, bootstrap-multiselect, Moment, daterangepicker, then `core/controller/common.js` and `core/routes/routes.js`. Comments around those two files say "silicon Overdrive".

Body regions: `#headerTopNav`, `#headerContent`, `#headerDesctiption` (spelling as in the id), `#pageContent`, `#pageFooter`.

### Routing

`loadPage(container, page)` empties the container, calls jQuery `.load(page)`, and scrolls to the top. jQuery executes `<script>` tags in the loaded fragment, which is how `dashboard.js` and the empty controllers start.

The click delegate is `$('body').on('click', '.button', ...)`. The switch key is the `action` attribute. The container id is `eltarget`.

| `action` | Fragment |
|---|---|
| `login` | `loadIndex()` then `core/view/dashboard/mainDashboard.html`, then `return false` |
| `dashboard` | `core/view/dashboard/mainDashboard.html` |
| `listMember` | `core/view/member/listMember.html` |
| `addMember` | `core/view/member/addMember.html` |
| `listOrganisastion` | `core/view/organisastion/listOrganisastion.html` |
| `addOrganisastion` | `core/view/organisastion/addOrganisastion.html` |
| `logout` | `logOut()` |
| default | `loadPage(eltarget, loadUrl)` with `loadUrl` undeclared |

`loadIndex()` strips `bg-slate-800` from `body` and loads the three header fragments and the footer.

On ready, `userSession` is forced from false to true and the login fragment is loaded. The session flag is a page-lifetime variable, not a cookie.

### Controllers

| File | Behaviour |
|---|---|
| `core/controller/login.js` | Empty |
| `core/controller/common.js` | `fetchHtmlAsText`, `getAbsoluteUrl`, `setCookie`, `getCookie`, `checkLoggedinCookie`, `logOut` |
| `core/controller/dashboard.js` | Builds the ECharts option and the FullCalendar sample. Runs on fragment ready |
| `core/controller/listMember.js` | Empty ready |
| `core/controller/addMember.js` | Empty ready |
| `core/controller/listOrganisastion.js` | Empty ready |
| `core/controller/addOrganisastion.js` | Empty ready |

`fetchHtmlAsText` and `getAbsoluteUrl` have no callers in `core/`.

### Views

Product views live under `core/view/`. `floatingMenu.html` repeats the floating action menu that is already inlined at the bottom of `headerDesctiption.html`. `routes.js` never loads `floatingMenu.html`.

Member and organisation fragments start with `<script src="assets/js/plugins/s"></script>`. That path is not a file.

## Frameworks and libraries

All application libraries are vendored under `assets/` except the Google Fonts CSS.

| Piece | Where it is used |
|---|---|
| jQuery | Shell and routing. `$.load`, `$.ajax`, `$.ajaxSetup` |
| Bootstrap and Bootstrap Limitless | Layout and components. Class names such as `navbar-nav-highlight`, `bg-slate-800` |
| Icomoon | Icon font |
| ECharts | `#line_zoom` in the dashboard |
| FullCalendar (core, daygrid, timegrid, list, interaction) | `.fullcalendar-basic`. Plugins named in the constructor: `dayGrid`, `interaction` |
| D3 and `d3_tooltip.js` | Loaded by `index.html`. No BlindSide chart calls D3 directly |
| Moment, daterangepicker, Switchery, bootstrap-multiselect, Slinky, FAB, BlockUI | Loaded by the shell. The BlindSide controllers do not call them |
| Limitless `assets/js/app.js` and `assets/js/demo_pages/*` | Used by `template/` pages. The root `index.html` does not load `app.js` |

The theme identifies itself in `template/*.html` as "Limitless - Responsive Web Application Kit by Eugene Kopyov", with footer links to ThemeForest user Kopyov and the years 2015–2018. The BlindSide footer replaced that credit with Evolv / EVOLVaV in `2ef3f33`.

`assets/scss` is present and is not compiled by any script in the repo. `assets/swf` and `assets/demo_data` are theme files.

## Data

There is no database, ORM, or local storage schema.

The only client persistence helpers are `document.cookie` writers in `common.js`. Cookie attributes set by `setCookie` are `expires` and `path=/`. `Secure`, `HttpOnly`, and `SameSite` are not set. `HttpOnly` cannot be set from this script in any case: the helper runs in the page.

Live pages do not call `setCookie`. The unreachable login path would write `bs*` cookies. `logOut` expires `ff*` cookies.

Dashboard series, calendar events, member cards, and the provincial table are HTML or JavaScript literals.

## APIs

### In this repository

None are served. There is no PHP, Python, or Node application besides `codedeploy_deploy.py`, which is a pipeline tool.

### Called by the browser

`POST api/login.php` is present only after `return false` in the login case. It is not reachable. The file `api/login.php` is not in git.

Request body the unreachable call would send:

- `username`
- `password`
- `apikey` (hardcoded literal; value omitted)

`dataType` is `json`. Success handling looks for `data.error` or `data.name`, `data.surname`, `data.id`, `data.role`. The `failure` callback is empty. There is no `error` callback (jQuery's hook is `error`, not `failure`).

`$.ajaxSetup` would add header `CsrfToken` from a meta tag that `index.html` does not contain.

## External integrations

| Integration | Role |
|---|---|
| Google Fonts | Roboto CSS on each full document |
| AWS S3 | Pipeline uploads `/tmp/artifact.zip` |
| AWS CodeDeploy | Pipeline creates a deployment from that S3 object |
| `http://evolvav.com` | Footer link only |
| `http://google.com/` | One sample calendar event |

AWS settings are environment variables read by `codedeploy_deploy.py`:

- `APPLICATION_NAME` — also the first segment of the S3 key
- `S3_BUCKET`
- `DEPLOYMENT_GROUP_NAME`
- `DEPLOYMENT_CONFIG`

Region and credentials are whatever the boto3 default chain finds in the pipeline environment. They are not in the repository. Values are **Unknown**.

The deployment description string is `New deployment from BitBucket`. The revision bundle type is `zip`. `ignoreApplicationStopFailures` is true.

The status poll is a `while 1` loop with no `sleep`, even though `sleep` is imported. In-progress deployments are busy-polled.

## Infrastructure and deployment

Pipeline file: `bitbucket-pipelines.yml`.

- Image: `python:3.5.7`
- Branch filter: `master` only
- Steps: `apt-get update`, `apt-get install -y zip`, `pip install boto3==1.3.0`, `zip -r /tmp/artifact.zip *`, `python codedeploy_deploy.py`
- The zip glob `*` does not include dotfiles. `.git` is a dot directory, so it is not included by that glob.

`appspec.yml` (version 0.0, os linux):

| Hook | Script | timeout | runas |
|---|---|---|---|
| BeforeInstall | `scripts/install_dependencies` | 300 | root |
| ApplicationStop | `scripts/stop_server` | 300 | root |
| ApplicationStart | `scripts/start_server` | 300 | root |

Files section copies `/` to `/var/www/html/`.

`install_dependencies` runs `sudo yum install -y httpd` (Amazon Linux style). The hook is already `runas: root`, and the script also uses `sudo`.

`start_server` runs `sudo chmod 755 -R /var/www/html` and `service httpd start`.

`stop_server` contains `isExistApp = `pgrep httpd``. The spaces around `=` make this a command name, not an assignment. It then runs `sudo chmod 777 -R /var/www/html`.

No Docker file, no Terraform, no web-server vhost, and no HTTPS configuration are in the repository. TLS, host names, and DNS are **Unknown**.

## Authentication

There is no working authentication.

The login card is a view. The active click handler does not send credentials. The code that would have sent them is unreachable and points at a missing PHP file. See the PRD, FR-003 and FR-004.

No password hash, session store, OAuth client, or user table exists.

## Background work

No workers, cron, queues, or scheduled jobs are defined. The pipeline poll loop is the only wait, and it runs inside the Bitbucket step.

## Storage

The site stores nothing of its own. CodeDeploy is instructed to replace `/var/www/html/`. User uploads are not implemented. `assets/images` is theme imagery, including `logo_light.png`, which the top nav displays.

## Monitoring and quality

No application logging, health check, metrics, or error reporter is configured.

Sonar project files are not in git (see Repository). Bitbucket Pipelines is the only CI definition, and it deploys; it does not run tests.

## Security notes visible in the tree

These are observations from the files, not a penetration test.

- A literal API key sits in the unreachable login request in `core/routes/routes.js`. Confirm whether it was ever a live credential. The value is intentionally omitted from Silicon Ark.
- `stop_server` applies mode `777` to the web root.
- Cookie helpers do not set `Secure` or `SameSite`.
- The CSRF header is wired to a missing meta tag.
- `codedeploy_deploy.py` uses the AWS credential chain. No key file is stored in the repository.
- The login success path, if it were connected, would put user id and role in a non-HttpOnly cookie for 365 days.

## Development and testing

No test runner, lint config, or local run script is in the repository. The site can be opened by serving the repository root over HTTP so that jQuery `.load` can fetch the fragments. Opening `index.html` as a `file://` document will fail those loads. That serving note is **Inferred** from how `.load` works; the repository does not document a dev server.

`template/` can be opened as the Limitless kit's own demo pages. Those pages are not the BlindSide workflows.

## File map for the product code

```text
index.html
appspec.yml
bitbucket-pipelines.yml
codedeploy_deploy.py
scripts/install_dependencies
scripts/start_server
scripts/stop_server
core/routes/routes.js
core/controller/common.js
core/controller/dashboard.js
core/controller/login.js
core/controller/listMember.js
core/controller/addMember.js
core/controller/listOrganisastion.js
core/controller/addOrganisastion.js
core/view/headerTopNav.html
core/view/headerContent.html
core/view/headerDesctiption.html
core/view/footer.html
core/view/floatingMenu.html
core/view/login/login.html
core/view/dashboard/mainDashboard.html
core/view/member/listMember.html
core/view/member/addMember.html
core/view/organisastion/listOrganisastion.html
core/view/organisastion/addOrganisastion.html
```

Everything else at the tip is the Limitless kit under `template/` and `assets/`.
