Clean up README and organize documentation
This commit is contained in:
@@ -0,0 +1,114 @@
|
||||
# Development
|
||||
|
||||
The controller uses SvelteKit, TypeScript and SQLite (`better-sqlite3`), with the
|
||||
Node adapter and server-sent events. The host agent uses Python 3's standard
|
||||
library and runs as a systemd service; hosts do not need Node.js.
|
||||
|
||||
Agents connect outbound to the controller over HTTPS and manage Docker/Plutainer
|
||||
and local RCON on each host. The controller owns fleet metadata and queues; it
|
||||
does not require a Docker socket or direct access to host filesystems.
|
||||
|
||||
## Run locally
|
||||
|
||||
Use Node.js 22 (the container's version), npm and Python 3.
|
||||
|
||||
```sh
|
||||
npm ci
|
||||
npm run agent:package
|
||||
export EC_SETUP_TOKEN="$(openssl rand -hex 32)"
|
||||
export BETA_ARCHIVE_DIR=./data/beta-archive
|
||||
EC_AUTH_ALLOW_HTTP=true npm run dev
|
||||
```
|
||||
|
||||
Use the exported token at `/setup` to create the first administrator, then remove
|
||||
it from the environment. Local metadata defaults to `./data/cherry.db`; use a
|
||||
separate database when testing enrollment. HTTP login is for local development;
|
||||
production agent transport requires HTTPS. See [authentication](../guides/authentication.md)
|
||||
for access and recovery details.
|
||||
|
||||
## Checks and builds
|
||||
|
||||
```sh
|
||||
npm run check
|
||||
npm test
|
||||
npm run test:agent
|
||||
npm run build
|
||||
```
|
||||
|
||||
Builds regenerate the downloadable agent, standalone updater and checksum
|
||||
manifest. They also bundle report workers under `build/reports` and launch
|
||||
preparation under `build/launch`. Development and test commands compile those
|
||||
workers automatically. Restart `npm run dev` after changing worker code.
|
||||
|
||||
Automated tests simulate Docker and game hosts. Real Debian installation and
|
||||
T5/T6 server validation use the [host acceptance checklist](../guides/native-hosts.md#development-and-validation).
|
||||
|
||||
## Code layout
|
||||
|
||||
Paths below are relative to the repository root.
|
||||
|
||||
| Path | Responsibility |
|
||||
| --- | --- |
|
||||
| `src/routes` | Pages and API endpoints |
|
||||
| `src/lib/ui` | Shared components, stores and [UI patterns](ui-patterns.md) |
|
||||
| `src/lib/server/hosts` | Enrollment, readiness and command transport |
|
||||
| `src/lib/server/backends` | Instance identity and remote file access |
|
||||
| `src/lib/server/provisioning/native.ts` | Lifecycle and campaign queues connected to agents |
|
||||
| `src/lib/server/game-files` | Immutable uploads and streaming distribution |
|
||||
| `src/lib/server/db` | SQLite schema, migrations and shared artifact storage |
|
||||
| `src/lib/server/reports` | Metrics, leaderboard and capacity workers |
|
||||
| `agent` | Python service, installer, packaging and tests |
|
||||
|
||||
## Performance diagnostics
|
||||
|
||||
Set `EC_PERF_LOG=true` to log slow requests, report computation/cache timings and
|
||||
event-loop delay. Responses expose `Server-Timing`; browser navigation records an
|
||||
`ec:navigation` performance measure. Report workers use separate read-only SQLite
|
||||
connections and bounded caches. Metrics snapshots can be reused for up to 30
|
||||
seconds when their inputs are unchanged.
|
||||
|
||||
Benchmark the leaderboard against an isolated synthetic database:
|
||||
|
||||
```sh
|
||||
npm run benchmark:leaderboard
|
||||
npm run benchmark:leaderboard -- --scenario all --baseline-ref <commit>
|
||||
```
|
||||
|
||||
The comparison checks response parity and warm query timings.
|
||||
|
||||
Set `EC_SLOW_SQL_MS=20` to log runtime statements taking at least 20 ms. Logging
|
||||
omits bound values and string literals and is disabled by default. Capture timings
|
||||
under the same fleet load before and after database changes. Inspect database
|
||||
size, large tables/indexes, WAL size and free pages inside the controller with:
|
||||
|
||||
```sh
|
||||
npm run diagnostics:database -- /data/cherry.db
|
||||
```
|
||||
|
||||
This opens an existing database read-only without running migrations. Substitute
|
||||
`./data/cherry.db` for a default local installation.
|
||||
|
||||
## Storage and upgrades
|
||||
|
||||
Game-file uploads live in dedicated filesystem storage. Script, plugin and
|
||||
configuration artifact bodies are stored once by SHA-256 in SQLite; versions,
|
||||
staging plans, rollback snapshots and launch commands reference those shared
|
||||
bytes. Startup transactionally backfills older rows. Current agents fetch
|
||||
assigned artifacts through an authenticated endpoint and verify their hashes;
|
||||
older agents receive inline content until they update.
|
||||
|
||||
Back up the persistent data directory before upgrading. Startup logs show
|
||||
migration phases, elapsed time and resident memory. Completed migrations are
|
||||
retained across restarts; interrupted transactions roll back and retry on startup.
|
||||
The one-time vacuum needs disk space for a temporary database copy. **Do not
|
||||
remove `cherry.db-wal` to recover from an interrupted upgrade.**
|
||||
|
||||
The controller uses a 128 MiB page cache; each reader worker uses 32 MiB.
|
||||
Main-database migrations use 16 MiB with memory mapping disabled. Temporary
|
||||
storage stays disk-backed. Containers use `/data/.sqlite-tmp` for scratch files;
|
||||
override `SQLITE_TMPDIR` only with another writable, disk-backed directory.
|
||||
|
||||
For a local data disk, `EC_SQLITE_MMAP_MB=256` enables memory-mapped reads; leave it
|
||||
at zero for network mounts. Query statistics are optimized at startup and hourly.
|
||||
WAL reuse is capped at 64 MiB after checkpoints, though active transactions can
|
||||
temporarily grow it larger.
|
||||
@@ -0,0 +1,40 @@
|
||||
# UI patterns
|
||||
|
||||
Use the shared components in `src/lib/ui/components` to keep pages consistent.
|
||||
Primitives live in its `primitives` directory.
|
||||
|
||||
## Page structure and controls
|
||||
|
||||
- Use `SectionHeader` for page titles and primary actions. The page owns spacing
|
||||
between sections.
|
||||
- Use `Field` with `Input`, `Select` or `Textarea` for labels, help and errors.
|
||||
Give controls distinct `ariaLabel` values when several share one field.
|
||||
- Pair `Tabs` with a labeled panel. Use `ListFooter` for long lists.
|
||||
- Use `StatusBadge` for workflow states and `ServerIdentity` for server names.
|
||||
Keep raw IDs available for copying and troubleshooting.
|
||||
|
||||
## Dialogs and feedback
|
||||
|
||||
Use `Dialog` for modal workflows and `confirmAction` from `src/lib/ui/confirm.ts`
|
||||
for ordinary confirmations. Browser unload protection remains native.
|
||||
|
||||
Keep loaded data visible when a refresh fails, show the error and provide a
|
||||
retry action. Distinguish loading, empty and failed states so operators know
|
||||
whether to wait or act.
|
||||
|
||||
## Live data
|
||||
|
||||
Use `pollVisible` from `src/lib/ui/poll.ts` for scheduled page refreshes. It avoids
|
||||
overlapping requests, pauses while the page is hidden and returns a cleanup
|
||||
function for use when the component unmounts.
|
||||
|
||||
Read live server data through `src/lib/ui/stores/fleet.ts` instead of adding
|
||||
another `/api/servers` polling loop. Server detail views use a scoped Fleet store
|
||||
so their snapshots do not replace the shared fleet.
|
||||
|
||||
## Accessibility and small screens
|
||||
|
||||
Preserve visible keyboard focus, associated field labels and separate navigation
|
||||
and action targets. Avoid nested buttons or placing a button inside a link.
|
||||
Allow long server identities to wrap and tab/filter rows to scroll on narrow
|
||||
screens.
|
||||
Reference in New Issue
Block a user