Update README with feature overview, deploy instructions, and API reference
build-and-push / build-and-push (push) Successful in 1m40s

Expand the minimal README with sections for features, local run, tests,
Docker deploy via the Gitea registry, the Gitea Actions workflow, full
API table (now including interfaces and lookup-by-hardware-id), stack
choices, and project layout.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-04-19 17:09:02 -04:00
parent f500db971b
commit e74bc99e94
+70 -12
View File
@@ -1,15 +1,28 @@
# Infrastructure
A small internal tool for tracking servers. Search hosts by hardware ID, hostname, or asset ID; manage where they live (site / room / position) and what kind of server they are. Browser UI plus a JSON API.
A small internal tool for tracking servers. Look up a host by **hardware ID**, **hostname**, or **asset ID** and see where it lives (site / room / position), what kind of server it is, and how it's wired into the network.
## Run
Built as a single Node process that serves a vanilla-JS UI and a JSON API from one port. SQLite for storage. No auth — runs on a trusted internal network.
## Features
- One search box, three searchable fields. Single match jumps straight to the host page.
- Per-host **network interface** tracking — name, MAC, IPv4, CIDR, link/duplex — with format-validating regex.
- Lookup tables for **sites**, **rooms**, and **server types**, managed inline from the UI.
- Same JSON API for browsers and scripts; schemas validated in, serialized out.
## Run locally
Requires Node 22+ (uses the built-in `node:sqlite` and `node:test`).
```sh
npm install
npm start
```
UI on `http://localhost:3000`, API at `http://localhost:3000/api`.
UI: `http://localhost:3000` · API: `http://localhost:3000/api`
First boot seeds one site, one room, and a handful of server types so the dropdowns aren't empty.
## Test
@@ -17,25 +30,70 @@ UI on `http://localhost:3000`, API at `http://localhost:3000/api`.
npm test
```
## Docker
21 tests run against an in-process Fastify instance backed by an in-memory SQLite database.
## Deploy
Compose pulls the prebuilt image from the Gitea container registry:
```sh
docker compose up --build
docker compose up -d
```
Data persists in the `infrastructure-data` named volume.
This pulls `gitea.thewrightserver.net/josh/infrastructure:latest` and mounts a named volume at `/app/data` for the SQLite file. To grab a new build:
```sh
docker compose pull && docker compose up -d
```
### CI
[`.gitea/workflows/build.yml`](.gitea/workflows/build.yml) runs on every push to `main`:
1. Install deps and run the test suite.
2. If green, log in to `gitea.thewrightserver.net` using the `REGISTRY_TOKEN` repo secret.
3. Build the image and push two tags: `:latest` and `:<commit-sha>`.
Set `REGISTRY_TOKEN` under **Repo → Settings → Actions → Secrets** to a Personal Access Token with `write:package` scope.
## API
| Method | Path | Notes |
|---|---|---|
| GET | `/api/hosts?q=` | Substring search across `hardware_id`, `hostname`, `asset_id`. Capped at 200 results. |
| GET | `/api/hosts/:id` | Fetch one. |
| POST | `/api/hosts` | Create. |
| PUT | `/api/hosts/:id` | Replace. |
| DELETE | `/api/hosts/:id` | Hard delete. |
| `GET` | `/api/hosts?q=` | Substring search across `hardware_id`, `hostname`, `asset_id`. Capped at 200. |
| `GET` | `/api/hosts/:id` | Fetch one by numeric ID. |
| `GET` | `/api/hosts/by-hardware-id/:hwid` | Fetch by hardware ID — what the detail page uses. |
| `POST` | `/api/hosts` | Create. |
| `PUT` | `/api/hosts/:id` | Replace. |
| `DELETE` | `/api/hosts/:id` | Hard delete (cascades to the host's interfaces). |
| `GET` | `/api/interfaces?host_id=N` | List interfaces for a host. |
| `GET` | `/api/interfaces/:id` | Fetch one. |
| `POST` | `/api/interfaces` | Create. Required: `host_id`, `name`. Optional: `mac_address`, `ip_address`, `subnet`, `link_speed`. |
| `PUT` | `/api/interfaces/:id` | Replace. |
| `DELETE` | `/api/interfaces/:id` | Hard delete. |
| `*` | `/api/sites[/:id]` | Site CRUD. |
| `*` | `/api/rooms[/:id]` | Room CRUD (`?site_id=` filter on GET). |
| `*` | `/api/server-types[/:id]` | Server-type CRUD. |
Errors: `{ error, details? }` with status 400 / 404 / 409 / 500.
Errors are uniform: `{ error, details? }` with status `400` / `404` / `409` / `500`.
## Stack
- **Node 22** + `node:sqlite` + `node:test` — no `better-sqlite3`, no `vitest`
- **Fastify 5** with built-in JSON Schema validation
- **Vanilla HTML / CSS / JS** — no framework, no bundler
## Layout
```
src/
server.js Fastify bootstrap, /api mount, SPA fallback
db.js schema, prepared statements, query API
schemas.js JSON Schema definitions
sqlite-errors.js maps SQLite constraint violations to 400/409
routes/ hosts, interfaces, sites, rooms, server-types
public/
index.html app.css app.js
tests/
*.test.js one suite per resource
```