Updated CLAUDE.md and deployment script
This commit is contained in:
@@ -30,7 +30,7 @@ npm run lint # eslint
|
|||||||
|
|
||||||
### Docker
|
### Docker
|
||||||
```powershell
|
```powershell
|
||||||
.\build-budget-image.ps1 # builds multi-stage image and pushes to docker.stwaddle.com/budget:latest
|
.\deploy.ps1 # builds image, pushes to docker.stwaddle.com/budget:latest, and deploys to prod via SSH
|
||||||
```
|
```
|
||||||
|
|
||||||
## Architecture
|
## Architecture
|
||||||
@@ -71,11 +71,18 @@ src/
|
|||||||
- **Inline table editing**: rows show read-only data; clicking a cell enters edit mode in-place using a `useState(editing)` toggle. New rows use a separate input row appended to `<tbody>` (not a modal).
|
- **Inline table editing**: rows show read-only data; clicking a cell enters edit mode in-place using a `useState(editing)` toggle. New rows use a separate input row appended to `<tbody>` (not a modal).
|
||||||
- **Sorting**: `SortableHeader` component and `SortState` type in `src/components/SortableHeader.tsx`. Sorting is client-side only and derives a view from the drag-ordered `displayItems` array — clearing sort restores drag order. Drag handles are disabled while a sort is active.
|
- **Sorting**: `SortableHeader` component and `SortState` type in `src/components/SortableHeader.tsx`. Sorting is client-side only and derives a view from the drag-ordered `displayItems` array — clearing sort restores drag order. Drag handles are disabled while a sort is active.
|
||||||
- **Frequency calculations** for real-time previews are in `src/utils/frequency.ts`, mirroring the C# `FrequencyCalculator` exactly.
|
- **Frequency calculations** for real-time previews are in `src/utils/frequency.ts`, mirroring the C# `FrequencyCalculator` exactly.
|
||||||
|
- **Drag-and-drop ordering**: `@dnd-kit` is used on income/outgo rows. Row order is persisted to the server. Sort handles are hidden while a column sort is active.
|
||||||
- **Auth**: `react-oidc-context` wraps the whole app; `AuthGuard` protects all budget routes; `TokenSync` wires the OIDC access token into the API client on every auth state change. After OIDC callback, navigation uses `window.location.replace('/')` (not `history.replaceState`) so React Router picks up the URL change.
|
- **Auth**: `react-oidc-context` wraps the whole app; `AuthGuard` protects all budget routes; `TokenSync` wires the OIDC access token into the API client on every auth state change. After OIDC callback, navigation uses `window.location.replace('/')` (not `history.replaceState`) so React Router picks up the URL change.
|
||||||
|
|
||||||
|
### Local development environment
|
||||||
|
Required env vars when running the API locally (set in `appsettings.Development.json` or shell):
|
||||||
|
- `ConnectionStrings__DefaultConnection` — Postgres connection string
|
||||||
|
- `Oidc__Audience` — `budget_api`
|
||||||
|
- `OTEL_EXPORTER_OTLP_ENDPOINT` — optional; omit or set to skip telemetry export
|
||||||
|
|
||||||
### Auth / OIDC
|
### Auth / OIDC
|
||||||
- Authority: `https://auth.stwaddle.com/` (OpenIddict-based, at `src.Auth.Server` in a sibling repo)
|
- Authority: `https://auth.stwaddle.com/` (OpenIddict-based, at `src.Auth.Server` in a sibling repo)
|
||||||
- API audience claim: `budget-api` (must match `AUTH__AUDIENCE` env var)
|
- API audience claim: `budget_api` (underscore — must match `Oidc__Audience` env var)
|
||||||
- Scope: `budget_api` (underscore, not hyphen)
|
- Scope: `budget_api` (underscore, not hyphen)
|
||||||
- Roles `admin` and `user` are granted per-user on the client registration in the auth server admin panel. A user with no role gets `access_denied` at the authorize endpoint.
|
- Roles `admin` and `user` are granted per-user on the client registration in the auth server admin panel. A user with no role gets `access_denied` at the authorize endpoint.
|
||||||
- Frontend OIDC config is baked into the build via `VITE_*` env vars; override locally in `src/Budget.Client/.env.local`
|
- Frontend OIDC config is baked into the build via `VITE_*` env vars; override locally in `src/Budget.Client/.env.local`
|
||||||
|
|||||||
@@ -1,4 +0,0 @@
|
|||||||
$image = "docker.stwaddle.com/budget:latest"
|
|
||||||
docker build -t $image .
|
|
||||||
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
|
|
||||||
docker push $image
|
|
||||||
+6
-2
@@ -1,2 +1,6 @@
|
|||||||
.\build-image.ps1
|
$image = "docker.stwaddle.com/budget:latest"
|
||||||
.\update-container.ps1
|
docker build -t $image .
|
||||||
|
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
|
||||||
|
docker push $image
|
||||||
|
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
|
||||||
|
ssh stwaddle_com "cd stwaddlecom; docker compose pull budget; docker compose down budget; docker compose up -d budget"
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
services:
|
|
||||||
budget:
|
|
||||||
image: ${IMAGE_REGISTRY:-}budget:latest
|
|
||||||
environment:
|
|
||||||
- VIRTUAL_HOST=${BUDGET_VIRTUAL_HOST:-budget.stwaddle.com}
|
|
||||||
- LETSENCRYPT_HOST=${BUDGET_LETSENCRYPT_HOST:-budget.stwaddle.com}
|
|
||||||
- VIRTUAL_PORT=8080
|
|
||||||
- ASPNETCORE_ENVIRONMENT=${ASPNETCORE_ENVIRONMENT:-Production}
|
|
||||||
- ConnectionStrings__DefaultConnection=Host=apps-db;Port=5432;Database=${POSTGRES_DB:-budget};Username=${POSTGRES_USER:-budget};Password=${POSTGRES_PASSWORD}
|
|
||||||
- OTEL_EXPORTER_OTLP_ENDPOINT=${OTEL_EXPORTER_OTLP_ENDPOINT}
|
|
||||||
- OTEL_EXPORTER_OTLP_PROTOCOL=${OTEL_EXPORTER_OTLP_PROTOCOL}
|
|
||||||
- OTEL_SERVICE_NAME=budget
|
|
||||||
depends_on:
|
|
||||||
- apps-db
|
|
||||||
- auth
|
|
||||||
networks:
|
|
||||||
- web
|
|
||||||
- apps-internal
|
|
||||||
- auth-public
|
|
||||||
- telemetry
|
|
||||||
restart: unless-stopped
|
|
||||||
|
|
||||||
apps-db:
|
|
||||||
image: postgres:16-alpine
|
|
||||||
environment:
|
|
||||||
- POSTGRES_DB=${POSTGRES_DB:-budget}
|
|
||||||
- POSTGRES_USER=${POSTGRES_USER:-budget}
|
|
||||||
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
|
|
||||||
volumes:
|
|
||||||
- apps-db-data:/var/lib/postgresql/data
|
|
||||||
networks:
|
|
||||||
- apps-internal
|
|
||||||
restart: unless-stopped
|
|
||||||
|
|
||||||
networks:
|
|
||||||
web:
|
|
||||||
external: true
|
|
||||||
apps-internal:
|
|
||||||
external: true
|
|
||||||
auth-public:
|
|
||||||
external: true
|
|
||||||
telemetry:
|
|
||||||
external: true
|
|
||||||
|
|
||||||
volumes:
|
|
||||||
apps-db-data:
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
ssh stwaddle_com "cd stwaddlecom; docker compose pull budget; docker compose down budget; docker compose up -d budget"
|
|
||||||
Reference in New Issue
Block a user