Skip to content

Commit 952420b

Browse files
authored
Merge pull request #300 from DeutscheModelUnitedNations/claude/enhance-country-code-input-rQX7L
2 parents 09ea847 + 59e9ffb commit 952420b

File tree

24 files changed

+2038
-7574
lines changed

24 files changed

+2038
-7574
lines changed

.github/workflows/build_image.yml

Lines changed: 80 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
1-
name: Build and publish container images
1+
name: Build and publish container image
22

33
on:
4-
release:
5-
types: [published]
64
push:
75
branches:
8-
- main
6+
- 'main'
7+
tags:
8+
- '*'
9+
pull_request:
10+
branches:
11+
- 'main'
912

1013
jobs:
1114
build:
@@ -18,8 +21,29 @@ jobs:
1821
- name: Checkout code
1922
uses: actions/checkout@v4
2023

21-
- name: Set up QEMU
22-
uses: docker/setup-qemu-action@v3
24+
- name: Set up bun
25+
uses: oven-sh/setup-bun@v2
26+
27+
- name: Install dependencies
28+
run: bun i --frozen-lockfile
29+
30+
- name: Run Trivy scanner on fs
31+
uses: aquasecurity/trivy-action@0.32.0
32+
with:
33+
scan-type: 'fs'
34+
scan-ref: '.'
35+
exit-code: 1
36+
format: 'table'
37+
ignore-unfixed: true
38+
vuln-type: 'os,library'
39+
severity: 'CRITICAL,HIGH'
40+
trivyignores: .trivyignore
41+
# don't scan for secrets in PRs
42+
scanners: ${{ github.event_name == 'pull_request' && 'vuln,license' || 'vuln,secret,misconfig,license'}}
43+
44+
# TODO: enable if we also plan on building for ARM natively
45+
# - name: Set up QEMU
46+
# uses: docker/setup-qemu-action@v3
2347

2448
- name: Set up Docker Buildx
2549
uses: docker/setup-buildx-action@v3
@@ -44,29 +68,69 @@ jobs:
4468
flavor: |
4569
latest=false
4670
images: |
71+
ghcr.io/${{ github.repository }}
4772
deutschemodelunitednations/chase
48-
ghcr.io/${{ github.repository_owner }}/${{ github.repository }}
4973
tags: |
50-
type=raw,value=${{ github.sha }},suffix=${{ matrix.runtime != 'bun' && format('-{0}', matrix.runtime) || '' }}
74+
type=ref,event=branch,suffix=${{ matrix.runtime != 'bun' && format('-{0}', matrix.runtime) || '' }}
75+
type=ref,event=pr,suffix=${{ matrix.runtime != 'bun' && format('-{0}', matrix.runtime) || '' }}
76+
type=semver,pattern={{version}},suffix=${{ matrix.runtime != 'bun' && format('-{0}', matrix.runtime) || '' }}
77+
type=semver,pattern={{major}}.{{minor}},suffix=${{ matrix.runtime != 'bun' && format('-{0}', matrix.runtime) || '' }}
78+
type=semver,pattern={{major}},suffix=${{ matrix.runtime != 'bun' && format('-{0}', matrix.runtime) || '' }}
79+
type=raw,value=latest,enable=${{ github.ref_type == 'tag' && matrix.runtime == 'bun' }}
5180
52-
type=semver,pattern={{version}},value=${{ github.event.release.tag_name }},enable=${{ github.event_name == 'release' }},suffix=${{ matrix.runtime != 'bun' && format('-{0}', matrix.runtime) || '' }}
81+
- name: Build Docker image
82+
uses: docker/build-push-action@v5
83+
id: build
84+
with:
85+
context: .
86+
load: true
87+
push: false
88+
tags: ${{ steps.meta.outputs.tags }}
89+
labels: ${{ steps.meta.outputs.labels }}
90+
file: ./Dockerfile.${{ matrix.runtime }}
91+
cache-from: type=gha
92+
cache-to: type=gha,mode=max
93+
build-args: |
94+
VERSION=${{ github.ref_name }}
95+
SHA=${{ github.sha }}
5396
54-
type=raw,value=latest,enable=${{ github.event_name == 'release' && !github.event.release.prerelease }}
55-
type=semver,pattern={{major}},value=${{ github.event.release.tag_name }},enable=${{ github.event_name == 'release' && !github.event.release.prerelease }},suffix=${{ matrix.runtime != 'bun' && format('-{0}', matrix.runtime) || '' }}
56-
type=semver,pattern={{major}}.{{minor}},value=${{ github.event.release.tag_name }},enable=${{ github.event_name == 'release' && !github.event.release.prerelease }},suffix=${{ matrix.runtime != 'bun' && format('-{0}', matrix.runtime) || '' }}
97+
- name: Get first built image ref
98+
id: split-tags
99+
run: echo "fragment=$(echo "${DOCKER_METADATA_OUTPUT_TAGS}" | head -n 1)" >> $GITHUB_OUTPUT
57100

58-
type=raw,value=prerelease,enable=${{ github.event_name == 'release' && github.event.release.prerelease }},suffix=${{ matrix.runtime != 'bun' && format('-{0}', matrix.runtime) || '' }}
59-
type=raw,value=nightly,enable=${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }},suffix=${{ matrix.runtime != 'bun' && format('-{0}', matrix.runtime) || '' }}
101+
- name: Run Trivy vulnerability scanner on the built image
102+
uses: aquasecurity/trivy-action@0.32.0
103+
with:
104+
image-ref: ${{ steps.split-tags.outputs.fragment }}
105+
format: 'table'
106+
exit-code: '1'
107+
ignore-unfixed: true
108+
vuln-type: 'os,library'
109+
severity: 'CRITICAL,HIGH'
110+
skip-setup-trivy: true
111+
trivyignores: .trivyignore
112+
scanners: ${{ github.event_name == 'pull_request' && 'vuln' || 'vuln,secret,misconfig'}}
60113

61-
- name: Build and push Docker image
114+
- name: Publish docker image
115+
if: github.event_name != 'pull_request'
62116
uses: docker/build-push-action@v5
63117
with:
64118
context: .
65119
push: true
120+
# TODO: enable if we also plan on building for ARM natively
66121
# platforms: linux/amd64,linux/arm64
67122
tags: ${{ steps.meta.outputs.tags }}
68123
labels: ${{ steps.meta.outputs.labels }}
69124
file: ./Dockerfile.${{ matrix.runtime }}
125+
cache-from: type=gha
70126
build-args: |
71-
VERSION=${{ github.event.release.tag_name }}
127+
VERSION=${{ github.ref_name }}
72128
SHA=${{ github.sha }}
129+
130+
- name: Create GitHub Release
131+
uses: softprops/action-gh-release@v2
132+
if: github.ref_type == 'tag' && matrix.runtime == 'bun'
133+
with:
134+
generate_release_notes: true
135+
env:
136+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

.github/workflows/build_run.yml

Lines changed: 0 additions & 20 deletions
This file was deleted.

.github/workflows/i18n.yml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
name: i18n Check
2+
on:
3+
pull_request:
4+
branches:
5+
- main
6+
push:
7+
branches:
8+
- main
9+
10+
jobs:
11+
i18n-check:
12+
runs-on: ubuntu-latest
13+
14+
steps:
15+
- name: Checkout code
16+
uses: actions/checkout@v4
17+
18+
- name: Set up bun
19+
uses: oven-sh/setup-bun@v2
20+
21+
- name: Install dependencies
22+
run: bun i --frozen-lockfile
23+
24+
- name: i18n Check
25+
run: bun run i18n:check
26+
27+
- name: i18n Validate Configuration
28+
run: bun run i18n:validate
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: Lint
1+
name: Test
22

33
on:
44
pull_request:
@@ -11,4 +11,5 @@ jobs:
1111
uses: actions/checkout@v4
1212
- uses: oven-sh/setup-bun@v2
1313
- run: bun install
14+
- run: bunx svelte-kit sync
1415
- run: bun run lint

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,6 @@ vite.config.ts.timestamp-*
2424

2525

2626
.houdini
27+
.claude
28+
29+
.lazyi18n

.prettierignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,6 @@
22
package-lock.json
33
pnpm-lock.yaml
44
yarn.lock
5-
schema.graphql
5+
schema.graphql
6+
.claude/**
7+
drizzle/meta/**

.prettierrc

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
11
{
2-
"useTabs": true,
3-
"singleQuote": true,
4-
"trailingComma": "none",
5-
"printWidth": 100,
6-
"plugins": ["prettier-plugin-svelte", "prettier-plugin-tailwindcss"],
2+
"jsonRecursiveSort": true,
73
"overrides": [
84
{
95
"files": "*.svelte",
106
"options": {
117
"parser": "svelte"
128
}
139
}
14-
]
10+
],
11+
"plugins": ["prettier-plugin-tailwindcss", "prettier-plugin-svelte", "prettier-plugin-sort-json"],
12+
"printWidth": 100,
13+
"singleQuote": true,
14+
"trailingComma": "none",
15+
"useTabs": true
1516
}

.trivyignore

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# Trivy ignore file
2+
# Add CVE IDs to ignore specific vulnerabilities
3+
4+
# esbuild Go stdlib vulnerabilities (build-time tool only)
5+
# esbuild is a JS/TS bundler that doesn't use these Go stdlib features
6+
7+
# net/netip: IPv4-mapped IPv6 address parsing - esbuild doesn't do network ops
8+
CVE-2024-24790
9+
10+
# net/http, x/net/http2: HTTP/2 DoS vulnerabilities - esbuild doesn't serve HTTP
11+
CVE-2023-39325
12+
CVE-2023-45288
13+
14+
# filepath: Windows \??\ path prefix - Linux containers only
15+
CVE-2023-45283
16+
17+
# encoding/gob: nested struct decoding - esbuild doesn't use gob
18+
CVE-2024-34156
19+
20+
# database/sql: Postgres race condition - esbuild doesn't use databases
21+
CVE-2025-47907
22+
23+
# archive/tar: GNU sparse map allocation - esbuild doesn't parse tar files
24+
CVE-2025-58183
25+
26+
# crypto/x509: certificate error string DoS - esbuild doesn't validate certs
27+
CVE-2025-61729
28+
29+
# Debian system packages - not used by Node.js runtime
30+
31+
# libgnutls30: GnuTLS SAN export - Node.js uses OpenSSL, not GnuTLS
32+
CVE-2025-32988
33+
34+
# libgnutls30: GnuTLS certtool parsing - certtool not used at runtime
35+
CVE-2025-32990
36+
37+
# perl-base: CPAN TLS verification - CPAN module installer not used at runtime
38+
CVE-2023-31484
39+
40+
# TODO: Remove these ignores once fixed
41+
42+
# TODO: glob command injection - Already fixed in bun.lock (10.5.0+)
43+
# Check: Rebuild Docker image and re-run Trivy scan to confirm fix
44+
# Remove this ignore once scan passes without it
45+
CVE-2025-64756
46+
47+
# TODO: glibc setuid/dlopen vulnerability
48+
# Check: Update base image when Debian 12.12 is released (fixes libc 2.36-9+deb12u11)
49+
# Remove this ignore once base image is updated
50+
CVE-2025-4802

CLAUDE.md

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4+
5+
## Project Overview
6+
7+
MUNify CHASE (CHAiring SoftwarE) is a conference management application for Model United Nations debates. Built by Deutsche Model United Nations (DMUN) e.V., it provides speakers lists, digital voting, resolution editing, committee status tracking, and roll-call management.
8+
9+
**Tech Stack**: SvelteKit + TypeScript, PostgreSQL + Drizzle ORM, GraphQL (Yoga + Houdini), Tailwind CSS + DaisyUI, Paraglide i18n
10+
11+
**GraphQL Generation**: Uses [Rumble](https://github.com/m1212e/rumble) (`@m1212e/rumble`), a custom glue package that generates GraphQL schemas and resolvers directly from Drizzle ORM definitions with built-in ability-based access control.
12+
13+
## Common Commands
14+
15+
```bash
16+
# Development
17+
bun run dev # Start dev server + Docker containers (database, mock OIDC)
18+
bun run dev:server # Dev server only (requires running containers)
19+
bun run dev:docker # Docker containers only (add -d for detached)
20+
21+
# Code Quality
22+
bun run lint # Prettier check + ESLint
23+
bun run format # Auto-format with Prettier
24+
bun run check # Svelte type checking
25+
bun run typecheck # TypeScript type checking
26+
27+
# Database
28+
bun run db:push # Push schema changes to database
29+
bun run db:migrate # Run migrations
30+
bun run db:seed:dev # Seed test data
31+
bun run db:studio # Open Drizzle Studio GUI
32+
bun run db:reset # Reset database
33+
34+
# Build
35+
bun run build # Production build
36+
bun run preview # Preview production build
37+
```
38+
39+
## Architecture
40+
41+
### API Layer (`src/api/`)
42+
43+
- **`db/schema.ts`**: Drizzle table definitions (source of truth for database)
44+
- **`db/relations.ts`**: Table relationships for Drizzle queries
45+
- **`handlers/*.ts`**: GraphQL resolvers using Rumble DSL with ability-based access control
46+
- **`context.ts`**: Request context with auth and permissions
47+
- **`services/`**: Business logic (OIDC integration, email validation)
48+
49+
**Handler pattern**: Each handler file defines GraphQL types, access control rules, queries, mutations, and subscriptions for an entity using the Rumble DSL.
50+
51+
### Frontend (`src/lib/`)
52+
53+
- **`components/`**: Svelte 5 components using runes (not stores)
54+
- **`state/`**: Client-side state (theme, server time sync)
55+
- **`data/`**: Static data (country names, flags)
56+
- **`paraglide/`**: Auto-generated i18n code (do not edit)
57+
58+
### Routes (`src/routes/`)
59+
60+
- **`(pages)/`**: Public landing pages
61+
- **`app/[conferenceId]/`**: Protected conference routes (require auth)
62+
- **`api/graphql/`**: GraphQL endpoint
63+
64+
### Key Generated Files (do not edit manually)
65+
66+
- `schema.graphql` - Generated GraphQL schema
67+
- `src/lib/paraglide/` - Generated i18n code
68+
- `.houdini/` - Generated GraphQL client code
69+
- `drizzle/` - Generated database migrations
70+
71+
## Conventions
72+
73+
- **IDs**: nanoid with 30 characters, no lookalike chars (see `src/lib/helpers/nanoid.ts`)
74+
- **Database columns**: snake_case (configured in Drizzle)
75+
- **i18n**: Messages in `messages/de.json` and `messages/en.json`, auto-translated via `bun run machine-translate`
76+
- **Styling**: Tailwind CSS with DaisyUI components, DMUN corporate identity package
77+
78+
## Authentication
79+
80+
OIDC-only authentication (no built-in auth). Local development uses mock OIDC server. Configure via:
81+
82+
- `PUBLIC_OIDC_AUTHORITY`: OIDC provider URL
83+
- `PUBLIC_OIDC_CLIENT_ID`: Application client ID
84+
- `ADMIN_EMAIL_WHITELIST` / `ADMIN_DOMAIN_WHITELIST`: Admin access control
85+
86+
## Development Setup
87+
88+
Requirements: Docker, Bun, Node.js
89+
90+
```bash
91+
bun i # Install dependencies
92+
cp .env.example .env # Configure environment
93+
bun run dev # Start everything
94+
```
95+
96+
Database: `localhost:5432` (postgres/postgres)
97+
Mock OIDC: `localhost:8080`

0 commit comments

Comments
 (0)