feat(isac): link skill chips to abilities

This commit is contained in:
JB
2026-07-26 17:04:47 -04:00
parent 6722665f5c
commit b1656c430f
19 changed files with 681 additions and 424 deletions
+40 -44
View File
@@ -1,9 +1,9 @@
# Container, staging, and production deployment
SHD.build is packaged as a Node 24 container using the official SvelteKit Node
adapter. The image contains application code, migration and notification
scripts, and native runtime dependencies. It does not contain an environment
file, database, backups, or user uploads.
SHD.build runs in a Node 24 container through the official SvelteKit Node
adapter. The image includes application code, migration and notification
scripts, and native runtime dependencies. Environment files, databases,
backups, and user uploads remain outside the image.
## Persistent data
@@ -15,10 +15,9 @@ mounted at `/app/data`. It contains:
- normalized user avatars under `avatars/`;
- uploaded game-data icons under `game-icons/`.
Never remove this volume during routine deployments. `docker compose down`
without `--volumes` preserves it. Before any manual backup or restore, stop
both the `app` and `scheduler` services because both access the embedded
database.
Keep this volume during routine deployments. `docker compose down` without
`--volumes` preserves it. Before a manual backup or restore, stop the `app`
and `scheduler` services because both access the embedded database.
## Staging environment
@@ -46,9 +45,9 @@ port on the host interfaces so a containerized reverse proxy or tunnel can
reach it; firewall the port to trusted LAN/tunnel sources when the host is
reachable from other networks.
The deployment decrypts `.env.staging` on the trusted staging runner into a
mode-`0600` runtime file. The decryption key is held by Gitea Actions, not
committed or included in the container image.
The trusted staging runner decrypts `.env.staging` into a mode-`0600` runtime
file. Gitea Actions holds the decryption key; Git and the container image do
not.
The staging container disables default-user seeding. On a brand-new staging
database, the existing bootstrap policy grants Admin to the first real account
@@ -93,9 +92,9 @@ In `https://git.jb.codes/jb/shd.build/settings/actions`:
3. Optionally add repository variable `STAGE_PORT`. It defaults to `5569`.
4. Ensure Actions are enabled and the `stage-deploy` runner is online.
The workflow at `.gitea/workflows/deploy-staging.yml` runs on every push to
`main` and can also be started manually. It does not need registry credentials
because the trusted staging runner builds a commit-tagged image locally.
`.gitea/workflows/deploy-staging.yml` runs for pushes to `main` and manual
dispatches. The trusted staging runner builds each commit-tagged image locally,
so the workflow needs no registry credentials.
## Deployment lifecycle
@@ -110,8 +109,7 @@ The workflow:
7. waits for `/api/health/database` to report healthy;
8. retains the logs and exits unsuccessfully if health verification fails.
The short outage is limited to backup, migration, and container startup. This
follows the database-preservation policy while minimizing data-entry downtime.
The outage covers backup, migration, and container startup.
The scheduler calls a bearer-authenticated endpoint on the application service
once per minute. Scheduled message delivery therefore uses the web process's
existing embedded-database connection instead of opening the locked database
@@ -120,11 +118,10 @@ consolidation, and email digest checks and is not published through a host port.
## Initial development-data bootstrap
The first staging release can be initialized from the current development
database, including users, roles, builds, guides, proposals, audit history,
avatars, and uploaded game-data icons. This is deliberately a one-time flow:
the staging importer refuses to run after users, builds, audits, or proposals
exist in its target database.
Initialize the first staging release from the development database, including
users, roles, builds, guides, proposals, audit history, avatars, and uploaded
game-data icons. The staging importer refuses a target database that contains
users, builds, audits, or proposals.
First stop this project's development server. The embedded database must not be
open while its complete transfer bundle is created:
@@ -134,8 +131,8 @@ npm run stage:bootstrap:export
```
The command writes a timestamped, ignored JSON bundle under `data/backups/`.
It contains user records and password hashes, so transfer it over an encrypted
channel and never add it to Git. Copy it to the staging host, then run:
The bundle includes user records and password hashes. Transfer it over an
encrypted channel, keep it out of Git, then copy it to the staging host and run:
```sh
/opt/shd-build-stage/bootstrap-staging.sh \
@@ -160,8 +157,8 @@ Actions. It briefly stops staging database writers, exports only canonical
builder-source tables plus uploaded game-data icons, restarts staging, and
publishes a `shd-stage-isac-data` artifact for 14 days.
Download `isac-stage.json` from that workflow run. Then stop this project's
development server and run:
Download `isac-stage.json` from that workflow run, stop this project's
development server, and run:
```sh
npm run isac:import -- /path/to/isac-stage.json --confirm-replace-isac-data
@@ -206,10 +203,10 @@ environment, port, and deployment workflow:
- Database: `/app/data/shd-build-production.db`
- Persistent volume: `shd-build-production-data`
Routine pushes never import or replace production data. The production deploy
stops only its application and scheduler, creates a timestamped JSON backup,
applies repeatable migrations, restarts, and verifies database health. Never
run `docker compose down --volumes` against production.
Routine pushes leave production data unchanged. The production deploy stops its
application and scheduler, creates a timestamped JSON backup, applies repeatable
migrations, restarts, and verifies database health. Keep
`docker compose down --volumes` away from production.
Add these repository Action secrets:
@@ -234,8 +231,8 @@ reuse the staging scheduler token.
### Initial production bootstrap
The one-time production bootstrap clones current development data and uploads.
Stop this project's development server before creating the bundle:
The production bootstrap clones current development data and uploads. Stop this
project's development server before creating the bundle:
```sh
npm run production:bootstrap:export
@@ -269,9 +266,8 @@ notifications, settings, and audit history untouched.
Manually run **Replace staging ISAC data from production** in Gitea Actions.
The workflow exports a consistent production snapshot, restarts production,
then stops staging and imports it. The staging importer creates both full and
ISAC-only safety backups before replacement. This is intentionally manual and
never runs as part of either deployment.
then stops staging and imports it. The staging importer creates full and
ISAC-only safety backups before replacement. Deployments do not run this flow.
### Promote managed images without replacing other data
@@ -280,9 +276,9 @@ development. Export a bundle after finishing local uploads and metadata edits:
Set the server-only `REMOVE_BG_API_KEY` in each encrypted environment that
accepts ISAC uploads. It is sent only from the server in the `X-Api-Key` header.
Icon uploads that already contain transparency do not call remove.bg; opaque
icon sources use its preview output and then continue through local trimming,
white normalization, WebP conversion, and storage.
Transparent icon uploads skip remove.bg. Opaque sources use its preview output,
then pass through local trimming, white normalization, WebP conversion, and
storage.
```sh
npm run images:export
@@ -311,13 +307,13 @@ docker compose -f compose.production.yml run --rm \
docker compose -f compose.production.yml up -d app scheduler
```
Each import creates a full target database backup before changing anything.
New stable IDs are inserted, identical existing assets are skipped, and a
different existing record blocks the import. After reviewing an intentional
metadata or file replacement, add `--update-existing`. Imported changes append
`image.imported` or `image.import_updated` audit events. Remove the transferred
bundle after both environments have been verified because it may contain
unpublished visual assets and creator identifiers.
Each import creates a full target database backup before changes. The importer
adds new stable IDs, skips identical assets, and blocks conflicting records.
After reviewing an intentional metadata or file replacement, add
`--update-existing`. Imported changes append `image.imported` or
`image.import_updated` audit events. Remove the transferred bundle after
verifying both environments because it may contain unpublished visual assets
and creator identifiers.
The `.env.staging` and `.env.production` npm import commands are intended for
maintenance performed directly in an environment where those database and