# 02 — Architecture

## Runtime stack

| Layer | Implementation |
|-------|----------------|
| Language | Go 1.22+ |
| HTTP | `net/http` + `http.ServeMux` |
| UI | Embedded templates and static assets via `go:embed` |
| State | In-memory only |
| Build | `CGO_ENABLED=0`, single binary |

Default port: `8082`

Audit result rendering is delegated to embedded `reanimator/chart`, vendored as git submodule `internal/chart`.
LOGPile remains responsible for upload, collection, parsing, normalization, and Reanimator export generation.

## Code map

```text
cmd/logpile/main.go          entrypoint and CLI flags
internal/server/             HTTP handlers, jobs, upload/export flows
internal/collector/          live collection and Redfish replay
internal/analyzer/           shared analysis helpers
internal/parser/             archive extraction and parser dispatch
internal/exporter/           CSV and Reanimator conversion
internal/chart/              vendored `reanimator/chart` viewer submodule
internal/models/             stable data contracts
web/                         embedded UI assets
```

## Server state

`internal/server.Server` stores:

| Field | Purpose |
|------|---------|
| `result` | Current `AnalysisResult` shown in UI and used by exports |
| `detectedVendor` | Parser/collector identity for the current dataset |
| `rawExport` | Reopenable raw-export package associated with current result |
| `jobManager` | Shared async job state for collect and convert flows |
| `collectors` | Registered live collectors (`redfish`, `ipmi`) |
| `convertOutput` | Temporary ZIP artifacts for batch convert downloads |

State is replaced only on successful upload or successful live collection.
Failed or canceled jobs do not overwrite the previous dataset.

## Main flows

### Upload

1. `POST /api/upload` receives multipart field `archive`
2. JSON inputs are checked for raw-export package or `AnalysisResult` snapshot
3. Non-JSON inputs go through `parser.BMCParser`
4. Archive metadata is normalized onto `AnalysisResult`
5. Result becomes the current in-memory dataset

### Live collect

1. `POST /api/collect` validates request fields
2. Server creates an async job and returns `202 Accepted`
3. Selected collector gathers raw data
4. For Redfish, collector saves `raw_payloads.redfish_tree`
5. Result is normalized, source metadata applied, and state replaced on success

### Batch convert

1. `POST /api/convert` accepts multiple files
2. Each supported file is analyzed independently
3. Successful results are converted to Reanimator JSON
4. Outputs are packaged into a temporary ZIP artifact
5. Client polls job status and downloads the artifact when ready

## Redfish design rule

Live Redfish collection and offline Redfish re-analysis must use the same replay path.
The collector first captures `raw_payloads.redfish_tree`, then the replay logic builds the normalized result.

## PCI IDs lookup

Lookup order:

1. Embedded `internal/parser/vendors/pciids/pci.ids`
2. `./pci.ids`
3. `/usr/share/hwdata/pci.ids`
4. `/usr/share/misc/pci.ids`
5. `/opt/homebrew/share/pciids/pci.ids`
6. Extra paths from `LOGPILE_PCI_IDS_PATH`

Later sources override earlier ones for the same IDs.
