Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
294 commits
Select commit Hold shift + click to select a range
e35f4e4
feat(devcontainer): optional Cloudflare quick-tunnel service
caviri Aug 4, 2026
8e14e76
fix(frontend): partner strip - real logos, no phone overflow
caviri Aug 4, 2026
2ba0f13
fix(frontend): dashboard stacks on phones; manage/users table scrolls
caviri Aug 4, 2026
f49de25
fix(frontend): poll for file changes in the devcontainer
caviri Aug 4, 2026
47ebb68
fix(frontend): phone layout polish on the public home and footer
caviri Aug 4, 2026
2722a2a
feat(devcontainer): OIDC login through the quick tunnel via caddy pat…
caviri Aug 4, 2026
e34636d
feat(keycloak): Hackagon-branded login theme
caviri Aug 4, 2026
321cafb
fix(backend): audit bugs B1, B5, B6, B8, B10-B12, B14
caviri Aug 4, 2026
ca52f76
fix(frontend): real Join button, audit bugs F3-F5, F7, F8
caviri Aug 4, 2026
cbde094
fix(devcontainer): keep node_modules off the host bind mount
caviri Aug 4, 2026
25f19bc
feat(frontend): sanitizing markdown pipeline (fixes F6)
caviri Aug 4, 2026
a149287
feat: platform pages (About, Privacy, Terms) with admin editing
caviri Aug 4, 2026
d73e2ee
fix(frontend): make the public home page actually clickable
caviri Aug 4, 2026
1a5fbd1
feat(devcontainer): healthchecks, readiness gating, service containers
caviri Aug 4, 2026
27fb71e
fix(devcontainer): do not gate sidecars on the dev container's health
caviri Aug 4, 2026
f15d837
fix(frontend): real data on the public event page, reachable CMS slugs
caviri Aug 4, 2026
35fc82a
feat: invitation links for private hackathons (closes B9, F1)
caviri Aug 4, 2026
510eb2c
feat(backend): email templates, branding, submission validation, acco…
caviri Aug 4, 2026
d8f489f
feat(frontend): organizer cockpit and hackathon creation
caviri Aug 4, 2026
fee8f50
feat(backend): expose per-hackathon branding on the read path
caviri Aug 4, 2026
d07dfbd
feat(frontend): complete the organizer cockpit, render branding, drop…
caviri Aug 4, 2026
e674cec
feat(backend): expose form schemas on Get, make ListVotes callable
caviri Aug 4, 2026
4179514
feat(frontend): participant lifecycle, voting phase, organizer config
caviri Aug 4, 2026
1509a70
feat: registration form, account deletion, and GDPR erasure scope
caviri Aug 5, 2026
354c179
feat: sendable email templates, final preferences, editable submissions
caviri Aug 5, 2026
23d1891
fix(keycloak): two-column login, and unblock the phone keyboard
caviri Aug 5, 2026
2bcf81e
fix(keycloak): drop the wordmark from the login brand block
caviri Aug 5, 2026
71fe6ae
feat(frontend): account menu on the avatar, with admin entries
caviri Aug 5, 2026
bf07dfe
fix(frontend): stop hackathon rows clipping their title on phones
caviri Aug 5, 2026
103c96b
fix(frontend): break the redirect loop on /hackathon/create
caviri Aug 5, 2026
ff76f02
chore(frontend): update the partner list on the landing page
caviri Aug 5, 2026
e299940
docs(todo): add Content Security Policy to the security checklist
caviri Aug 5, 2026
050ab7a
docs(todo): record the OpenReplay session-replay evaluation
caviri Aug 5, 2026
8e5f010
fix(frontend): derive reserved route segments so /account stops looping
caviri Aug 5, 2026
cf71f6b
fix(frontend): make the account menu open on the first click
caviri Aug 5, 2026
ab90840
feat: let people edit their display name
caviri Aug 5, 2026
742fc01
feat: let registrants correct their form answers
caviri Aug 5, 2026
ffab06f
docs: record the profile/registration-answer decisions and regen API.md
caviri Aug 5, 2026
8879b15
docs: user flows with desktop and phone screenshots
caviri Aug 5, 2026
f8e4b88
feat(frontend): branded favicon and OpenGraph link previews
caviri Aug 5, 2026
a1c7ec4
fix(frontend): a malformed invitation token is 404, not 500
caviri Aug 5, 2026
d34a84e
fix(frontend): build preview URLs from the visitor's origin, not the …
caviri Aug 5, 2026
7c37ea7
feat(frontend): shared list toolbar, table view and row-action menu
caviri Aug 5, 2026
26790bb
feat(frontend): search, filters and a table view on the management lists
caviri Aug 5, 2026
e1bb9f6
fix(backend): UserService.List returns global roles
caviri Aug 5, 2026
dd29f15
chore(frontend): type the landing page partner list
caviri Aug 5, 2026
a8b87ae
fix(backend): the anonymous subject cannot be a person
caviri Aug 5, 2026
46b6e20
docs: refresh the flow screenshots for the new list toolbar
caviri Aug 5, 2026
fa3740d
feat(frontend): add the Durham University logo to the partner row
caviri Aug 5, 2026
705fcda
feat(frontend): size partner logos by area so the row is balanced
caviri Aug 5, 2026
42856b9
fix: tunnel login broke because the frontend was told it was on https
caviri Aug 5, 2026
c7319b5
docs: add the C4 architecture model, generated from the code
caviri Aug 5, 2026
591bc99
feat(frontend): Home / Hackathons / About as the platform's top nav
caviri Aug 5, 2026
ffaabc7
feat(frontend): a real Hackathons page, browsable as panels
caviri Aug 5, 2026
96022bd
feat(frontend): joining an event opens its registration form
caviri Aug 5, 2026
d0aa609
fix(keycloak): label the way back out of the password step
caviri Aug 5, 2026
3fa4aaa
docs: how to adopt main's design on this branch
caviri Aug 5, 2026
ab9d346
docs: plan to bring main's design and screens onto this branch
caviri Aug 5, 2026
8b7d7bd
feat(backend): port SetCapabilities and GetPreference from main
caviri Aug 5, 2026
bd16ddc
docs: main removed Skeleton — Phase 2 is a class translation, and swa…
caviri Aug 5, 2026
17f6d7e
feat(frontend): take main's src wholesale, adapt its model to ours
caviri Aug 5, 2026
4c5cd8a
feat(frontend): re-add the account page and adapt the timeline to our…
caviri Aug 5, 2026
64b641f
feat(frontend): re-add the CMS, registration form, invitations and SEO
caviri Aug 5, 2026
3b61402
feat(frontend): browse page, real top nav, and invitation links as a …
caviri Aug 5, 2026
aa7f839
feat(frontend): form builders as their own route
caviri Aug 5, 2026
f34379c
feat: deadlines screen, and the GetWindows RPC it needed
caviri Aug 5, 2026
e290616
feat: prizes screen, and the PrizeService.Get it needed
caviri Aug 5, 2026
cff8a57
test: fix the login helper for the new identity markup, triage the rest
caviri Aug 5, 2026
c81b81f
fix(frontend): make /account reachable, and rewrite its spec for this…
caviri Aug 5, 2026
f1d586f
fix(nav): one meaning per entry — Dashboard, Hackathons, logo home
caviri Aug 5, 2026
1d33448
feat(frontend): voting, notifications, branding and the media views
caviri Aug 5, 2026
5a718df
fix(public): the event page shows the event
caviri Aug 5, 2026
147ef5d
fix(frontend): joining asks the questions, and the CMS has a way in
caviri Aug 5, 2026
15d5c9a
docs: migration queue and TODO reflect the port's actual state
caviri Aug 5, 2026
77a398e
feat(frontend): the preferences export has a link, and lives with its…
caviri Aug 6, 2026
02955d2
feat(frontend): teams can turn work in again
caviri Aug 6, 2026
f3c9c31
fix(nav): signing in from the landing page lands on your dashboard
caviri Aug 6, 2026
637195a
fix(landing): the front page's primary action was a 404
caviri Aug 6, 2026
d81ce0b
fix(backend): the voting policy is read, not just stored
caviri Aug 6, 2026
3c7303b
feat: an event can state its voting rules, and the dashboard says why…
caviri Aug 6, 2026
3a7c87b
feat(voting): organisers can open the ballot
caviri Aug 6, 2026
ae0eb56
docs(testing): the two reachability audits, and what they found
caviri Aug 6, 2026
94cc6f0
docs(todo): B3 decided (capability governs), B7 fixed
caviri Aug 6, 2026
5557202
fix(landing): real winners, not invented ones
caviri Aug 6, 2026
ce8f65e
feat(public): the event page carries the event's own pages
caviri Aug 6, 2026
28d1025
fix(teams): the team's name is its own text
caviri Aug 6, 2026
92075e5
fix(timeline): phases sit one level under the heading that lists them
caviri Aug 6, 2026
ef550b5
fix(submissions): the whole room sees what the room built
caviri Aug 6, 2026
d39f8c7
feat(lists): users and participants get the shared toolbar back
caviri Aug 6, 2026
3ea831c
fix(responsive): two horizontal scrolls at phone width
caviri Aug 6, 2026
9377b03
docs: the port is done and every suite is green
caviri Aug 6, 2026
369dccf
fix: the nav keeps its shape, Keycloak gets the favicon, the landing …
caviri Aug 6, 2026
29cce19
fix: public pages worked for strangers and broke for members
caviri Aug 6, 2026
ed152f1
fix(build): the app could not be built for production at all
caviri Aug 6, 2026
eb9bd16
perf(assets): the landing page shipped 2.6 MB of photographs
caviri Aug 6, 2026
f27afbe
docs(tunnel): say why the public route has two upstreams
caviri Aug 6, 2026
f422c31
fix(public): a backend outage costs the list, not the page
caviri Aug 6, 2026
65a6558
feat(account): a profile you fill in once, not at every event
caviri Aug 6, 2026
6ccf4fe
docs(storage): the file-storage design, and the two decisions in it
caviri Aug 6, 2026
58866b7
feat(storage): an S3-compatible object store for development
caviri Aug 6, 2026
f7ec3e2
feat(storage): public-read imagery, private everything else
caviri Aug 6, 2026
8d8f305
feat(storage): the seeded events have pictures, served from the app's…
caviri Aug 6, 2026
6e6ed92
fix(devcontainer): the one-command path starts storage and prepares it
caviri Aug 6, 2026
cb82578
fix: three controls that could not work, and copy that lied
caviri Aug 6, 2026
947c25d
docs: review of origin/main against our branch
caviri Aug 6, 2026
815c084
feat(roles): granting a global role works instead of 500ing
caviri Aug 6, 2026
3e72cbc
fix(timeline): "Clear current phase" clears the current phase
caviri Aug 6, 2026
5470e34
fix(voting): the VOTE and VIEW_RESULTS switches now do something
caviri Aug 6, 2026
f24df97
feat(voting): compute the tally instead of typing it in
caviri Aug 6, 2026
5b5f0a8
feat(overview): tell a participant what they can do right now
caviri Aug 6, 2026
52258c5
feat(organiser): a place to manage the event, and a warning when it lies
caviri Aug 6, 2026
f9ed01b
fix(a11y): the revoke-role button announces what it does
caviri Aug 6, 2026
59986aa
feat(hackathon): an organizer can recruit a co-organizer
caviri Aug 6, 2026
6913d7d
feat: ranked/points ballots, HackathonState facade, object uploads
caviri Aug 7, 2026
8399bf0
fix(ui): covers, glyphs, a centred nav, and prizes that keep their pi…
caviri Aug 7, 2026
af90431
feat(teams): a people panel beside the assignment board
caviri Aug 7, 2026
bb79b4c
feat(forms): read the whole cohort's registration answers at once
caviri Aug 7, 2026
810b7b9
fix(hackathon): the logo rule rejected inline data:image logos
caviri Aug 7, 2026
88ca54b
feat(media): upload images from the page editor
caviri Aug 7, 2026
b34aecd
feat(media): re-encode uploads to WebP, and honour a field's declared…
caviri Aug 7, 2026
e66131f
fix(deploy): `down` frees every port the stack binds, not two of four
caviri Aug 8, 2026
3149985
feat(audit): journal RPC traffic in recipe.jsonl shape
caviri Aug 8, 2026
f9960ee
feat(observability): session replay, masked by default and proven so
caviri Aug 8, 2026
e774ba9
feat(privacy): replay asks first, forgets eventually, and leaks no in…
caviri Aug 8, 2026
be4ccd2
docs(testing): correct every count, and the branch it describes
caviri Aug 8, 2026
1333124
fix: unbreak CI, regenerate the DBML, and correct the stale docs
caviri Aug 8, 2026
ece4a3d
fix(docs): the model's own header disagreed with its own table
caviri Aug 9, 2026
48fe783
style: land the repo-wide formatter, and stop it owning two things it…
caviri Aug 9, 2026
ce6ece1
docs(model): the object store is built, not planned
caviri Aug 9, 2026
1e764a2
fix(layout): chrome that reflows instead of colliding
caviri Aug 9, 2026
3a13b74
fix(layout): reflow four surfaces that overflowed at 360; seed settings
caviri Aug 9, 2026
0baf612
fix(concurrency): two real races, found by testing simultaneity at last
caviri Aug 10, 2026
60435b1
feat(hackathon): capacity is a real limit, with the queue it implies
caviri Aug 10, 2026
773baca
chore: drop a stray empty log that was never an error
caviri Aug 10, 2026
8665a18
fix(config): a local overlay, so wiring a tunnel stops editing tracke…
caviri Aug 10, 2026
b57c924
chore: track the e2e tooling on this branch
caviri Aug 10, 2026
21a2f85
Merge: the e2e tooling now lives on this branch
caviri Aug 10, 2026
654b065
docs: what a contributor actually needs, proven from a clean clone
caviri Aug 10, 2026
4701732
feat(skills): one command for a dev deploy, optionally with session r…
caviri Aug 10, 2026
347cf1a
fix(ui): the consent banner no longer covers what it sits on top of
caviri Aug 10, 2026
4987270
feat(media): upload where the platform only ever asked for a URL
caviri Aug 10, 2026
833a738
fix(replay): recordings were unplayable because the rig was broken, n…
caviri Aug 10, 2026
d4c1cb7
feat(storage): list stored objects, and pick one instead of re-upload…
caviri Aug 12, 2026
f0dad00
feat(frontend): make the markdown editor usable — toolbar, tables, re…
caviri Aug 12, 2026
e0e4dc7
feat(frontend): import team composition from CSV or JSON
caviri Aug 12, 2026
c606275
fix(frontend): put the footer back on the dashboard and the manage sc…
caviri Aug 12, 2026
4f52896
feat(frontend): adopt main's manage panel, keeping what main does not…
caviri Aug 12, 2026
987ec8e
fix(skills): make --restore verify the processes, not just the config…
caviri Aug 12, 2026
2ebc1f7
fix(frontend): stop offering Join on events that cannot be joined
caviri Aug 12, 2026
1e3ce8a
fix(skills): bounce the :8081 server on BOTH --restore paths
caviri Aug 12, 2026
416d203
feat(frontend): explain the bounce to login, and come back where you …
caviri Aug 12, 2026
244dc19
fix(frontend): light the whole dashboard row, badge included, on hover
hanaCasey Aug 12, 2026
c70bc10
feat: declare the product version in VERSION and stamp it into builds
hanaCasey Aug 12, 2026
0265838
feat(frontend): rebuild the footer after datascience.ch, with the ver…
hanaCasey Aug 12, 2026
eb92894
test(e2e): drive the organiser's own screens — recipe 344 → 463 actions
caviri Aug 12, 2026
4a1ebf1
chore(e2e): re-splice the recipe player
caviri Aug 13, 2026
d51a0d7
fix(e2e): the player's coverage legend was wrong about all three colours
caviri Aug 13, 2026
c596683
feat(frontend): port main's overview redesign, wave two
hanaCasey Aug 13, 2026
b171fe3
Merge remote-tracking branch 'origin/sketch/06-08-26' into develop
hanaCasey Aug 13, 2026
1821544
chore: gitignore .claude/settings.local.json
hanaCasey Aug 13, 2026
b2208f5
chore: add the Claude Code devcontainer feature
hanaCasey Aug 13, 2026
83b24ee
chore(backend): tidy go.sum
hanaCasey Aug 13, 2026
143a961
feat(frontend): separate Dashboard from All Hackathons, and drop About
hanaCasey Aug 13, 2026
dbbc8c8
feat(frontend): static social preview cards from the platform default…
hanaCasey Aug 13, 2026
9f62f78
feat(e2e): let the player's colours mean what you need them to mean
caviri Aug 13, 2026
f82c45a
feat(e2e): drag the diagram, name its regions, and bake in a real run…
caviri Aug 13, 2026
7603784
fix(frontend): make the participants "View" link reach a real page
hanaCasey Aug 13, 2026
942b60a
fix(frontend): make the hackathon manage sidebar flat, not collapsible
hanaCasey Aug 13, 2026
5a7b253
chore: run treefmt across the repo
hanaCasey Aug 13, 2026
e06f1f3
fix(dev): stop the stack killing itself, and stop the browse page lyi…
caviri Aug 13, 2026
feb88bf
fix(hackathon): make the offered action work, create the missing row,…
caviri Aug 13, 2026
1be8424
chore: unblock CI by formatting the tree and exempting .claude
hanaCasey Aug 13, 2026
cdc9a5c
chore: unblock CI by formatting the tree and exempting .claude
hanaCasey Aug 13, 2026
6263540
fix(frontend): footer no longer pins to viewport on short pages; fres…
hanaCasey Aug 13, 2026
d750974
test(e2e): make mutation testing routine — 38 mutations, 12 gaps found
caviri Aug 13, 2026
e77e6f9
build(devcontainer): install git-lfs, and bake in the packages a recr…
caviri Aug 13, 2026
9ea99b8
docs(e2e): a quality report that re-derives every number it prints
caviri Aug 13, 2026
3ba79be
chore: exempt .claude from treefmt and fix the one shellcheck false p…
hanaCasey Aug 14, 2026
6e5c883
chore(backend): regenerate proto docs
hanaCasey Aug 14, 2026
cfa8a92
feat(analytics): self-hosted Plausible for development, behind its ow…
caviri Aug 14, 2026
fbff2fd
feat(tunnel): teach serve-public.sh about the analytics rig
caviri Aug 14, 2026
01724cf
Merge remote-tracking branch 'origin/develop' into fix/participant-vi…
hanaCasey Aug 14, 2026
6427798
Merge remote-tracking branch 'origin/develop' into fix/manage-sidebar…
hanaCasey Aug 14, 2026
2086075
Merge remote-tracking branch 'origin/develop' into feat/static-social…
hanaCasey Aug 14, 2026
be02598
Merge remote-tracking branch 'origin/develop' into feat/navbar-dashbo…
hanaCasey Aug 14, 2026
b1a3349
feat(helm): bring in PR #161's chart and teach it about object storage
caviri Aug 14, 2026
4dc8370
fix(frontend): undo manageNav's accidental phase-create/participants …
hanaCasey Aug 14, 2026
cfab9b7
fix(frontend): resolve navigation lint debt across app links
hanaCasey Aug 14, 2026
ceb560c
fix(frontend): apply the organiser's input-type map on submission fields
hanaCasey Aug 14, 2026
788f472
chore(frontend): drop unused resolvePath import in hooks.server.ts
hanaCasey Aug 14, 2026
a500359
feat(tunnel): named tunnels on a domain you own, alongside quick tunnels
caviri Aug 14, 2026
74da915
chore(backend): rewrap two overlong ent schema comments (lll)
hanaCasey Aug 14, 2026
05dcb27
chore(backend): clean up storage-layer lint findings
hanaCasey Aug 14, 2026
b6e75dd
chore(backend): clean up voting-service lint findings
hanaCasey Aug 14, 2026
24f4097
chore(backend): reduce hackathon/config/prize service complexity, fix…
hanaCasey Aug 14, 2026
98aed37
Merge commit '788f4727f7' into HEAD
hanaCasey Aug 14, 2026
a06f80b
Merge commit '4dc837052f' into HEAD
hanaCasey Aug 14, 2026
063a2ac
Merge remote-tracking branch 'origin/develop' into fix/participant-vi…
hanaCasey Aug 14, 2026
8c779ba
Merge remote-tracking branch 'origin/develop' into feat/static-social…
hanaCasey Aug 14, 2026
85ac234
Merge remote-tracking branch 'origin/develop' into fix/manage-sidebar…
hanaCasey Aug 14, 2026
9e1f04e
Merge remote-tracking branch 'origin/develop' into feat/navbar-dashbo…
hanaCasey Aug 14, 2026
9495dba
docs(devcontainer): correct what was false, then document what is new
caviri Aug 14, 2026
7f33be1
Merge pull request #170 from SwissDataScienceCenter/feat/navbar-dashb…
hanaCasey Aug 14, 2026
21a6f29
Merge pull request #171 from SwissDataScienceCenter/feat/static-socia…
hanaCasey Aug 14, 2026
88227fc
Merge pull request #172 from SwissDataScienceCenter/fix/participant-v…
hanaCasey Aug 14, 2026
ffb350b
Merge pull request #173 from SwissDataScienceCenter/fix/manage-sideba…
hanaCasey Aug 14, 2026
b98fbdd
test(helm): install the chart on a real cluster — and find five bugs …
caviri Aug 14, 2026
e0d2f6d
feat(k3d): a real HTTPS hostname for the cluster, and what it proved
caviri Aug 14, 2026
0b83f84
docs: how to deploy this on Kubernetes, and what will bite you
caviri Aug 14, 2026
52c545a
fix(helm): make a config-only upgrade actually reach the running pods
caviri Aug 14, 2026
f2b699d
test(backend): close 11 of the 12 gaps mutation testing found
caviri Aug 14, 2026
d373769
Merge remote-tracking branch 'origin/develop' into sketch/06-08-26
caviri Aug 14, 2026
a9caa83
test(e2e): re-specify the sidebar action for develop's flat Manage nav
caviri Aug 14, 2026
807ce87
test(e2e): re-specify the nav and footer checks for develop's chrome
caviri Aug 14, 2026
ecc580d
test(e2e): re-specify the 403 way-out, and re-establish both baselines
caviri Aug 14, 2026
fbc81ad
fix(frontend): make both "About" links say which About they mean
caviri Aug 14, 2026
34043b1
chore: format .claude with treefmt, as develop does
caviri Aug 14, 2026
e48137b
fix(frontend): say when a footer link leaves the site
caviri Aug 14, 2026
ea66ff9
fix(ci): stop prettier choking on the Helm templates, and clear the d…
caviri Aug 15, 2026
226d201
fix(e2e): validate the quality report BEFORE writing it, and regenera…
caviri Aug 15, 2026
59ae35a
Merge pull request #174 from SwissDataScienceCenter/sketch/06-08-26
caviri Aug 15, 2026
74a8f85
docs: record the five handovers that were confidently wrong
caviri Aug 15, 2026
abb7f92
feat(frontend): a welcoming social card, and a script that can rebuil…
caviri Aug 15, 2026
0fc67a8
fix(e2e): validate the player before writing it, and refresh the muta…
caviri Aug 16, 2026
d69f515
Merge pull request #175 from SwissDataScienceCenter/chore/loose-ends
caviri Aug 16, 2026
5205801
test(backend): a deterministic witness for the capacity boundary
caviri Aug 16, 2026
a497ca3
chore(e2e): judge capacity.oversell-by-one by a witness that cannot f…
caviri Aug 16, 2026
e93f1c1
docs(e2e): two traps found rebuilding the social card
caviri Aug 16, 2026
f98838e
chore: reflow CLAUDE.md after the trap notes
caviri Aug 16, 2026
935e2eb
Merge pull request #176 from SwissDataScienceCenter/fix/capacity-witness
caviri Aug 17, 2026
66cd651
fix(frontend): serve a properly sized apple-touch-icon
hanaCasey Aug 17, 2026
37f3401
fix(frontend): add favicon.ico for crawlers that fetch it by convention
hanaCasey Aug 17, 2026
fb22107
Merge pull request #177 from SwissDataScienceCenter/fix/apple-touch-i…
hanaCasey Aug 18, 2026
1a457d5
fix(frontend): drop id_token from session JWT to stop 502 cookie chun…
caviri Aug 18, 2026
b205f30
fix(frontend): survive a backend outage on first login instead of 500
caviri Aug 18, 2026
911d986
fix(frontend): define the .checkbox theme style three forms already use
caviri Aug 18, 2026
2f31b10
fix(backend): gate vote-category and ballot reads against anonymous c…
caviri Aug 18, 2026
ed9b25f
Merge pull request #191 from SwissDataScienceCenter/fix/feedback-2026…
caviri Aug 18, 2026
3ad1504
fix(frontend): stop saving voting rules from silently unchecking own-…
caviri Aug 18, 2026
a1d2600
fix(frontend): tell a voter why a ballot was refused
caviri Aug 18, 2026
217556d
fix(frontend): stop the teams "More Information" link from erroring
caviri Aug 18, 2026
455feff
Merge pull request #192 from SwissDataScienceCenter/fix/feedback-voti…
caviri Aug 18, 2026
409e597
fix(frontend): count only confirmed participants in the hero total
caviri Aug 19, 2026
adfb69b
Merge pull request #193 from SwissDataScienceCenter/fix/feedback-batc…
caviri Aug 19, 2026
5d41544
fix(backend): gate the registration-form self-path on participation (D3)
caviri Aug 19, 2026
f23f428
fix(backend): bind submission-attachment uploads to the submissions w…
caviri Aug 19, 2026
8352db1
Merge pull request #194 from SwissDataScienceCenter/fix/feedback-secu…
caviri Aug 19, 2026
de4253b
fix(backend): require a signed-in user to read vote results (D4)
caviri Aug 19, 2026
abdfbcc
fix(backend): exclude waitlisted registrants from hackathon-wide subm…
caviri Aug 19, 2026
86b8b71
Merge pull request #195 from SwissDataScienceCenter/fix/feedback-secu…
caviri Aug 19, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
1,482 changes: 1,482 additions & 0 deletions .claude/CLAUDE.md

Large diffs are not rendered by default.

7 changes: 7 additions & 0 deletions .claude/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"attribution": {
"commit": "",
"pr": ""
},
"includeCoAuthoredBy": false
}
64 changes: 64 additions & 0 deletions .claude/skills/cloudflare-tunnel/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# Cloudflare credentials for NAMED tunnels — persistent hostnames on a zone you
# own, instead of a quick tunnel's throwaway *.trycloudflare.com.
#
# Copy to `.env` BESIDE THIS FILE and fill it in. That path is gitignored by the
# repo-wide `.env` rule, and every script that touches it asks
# `git check-ignore` first and REFUSES to read or write a token that git could
# take. Verify yourself before you paste anything:
#
# git check-ignore -v .claude/skills/cloudflare-tunnel/.env
#
# Nothing here is required. With no `.env`, every rig falls back to a quick
# tunnel exactly as before — named mode is an addition, not a replacement.
#
# ⚠ THE TOKEN SCOPES TO A ZONE, NOT TO A HOSTNAME. There is no "only these three
# subdomains" grant in Cloudflare. A token that can edit DNS in your zone can
# edit ANY record in it. Use a zone you are willing to hand to a dev script.
# SKILL.md → "Named tunnels" has the exact minting steps and what each
# permission is for.

# API token. Minted at
# Cloudflare dashboard → My Profile → API Tokens → Create Token → Custom token
# with exactly two permissions:
# Zone → DNS → Edit (Zone Resources: Include → your zone)
# Account → Cloudflare Tunnel → Edit (Account Resources: your account)
CLOUDFLARE_API_TOKEN=

# The zone the hostnames below live in. The account id is read OUT of the zone
# record, which is why no account-read permission is needed.
CLOUDFLARE_ZONE=example.org

# Optional: only if the token can see more than one account and the zone lookup
# picks the wrong one.
#CLOUDFLARE_ACCOUNT_ID=

# One hostname per rig; each gets its own tunnel. Leave a line blank or absent
# and that rig stays on quick tunnels.
#
# The app hostname serves the frontend AND Keycloak through caddy's path mux
# (/realms/*, /resources/* → Keycloak, /objects/* → the object store, everything
# else → SvelteKit), which is what makes the OIDC redirect work from outside.
HACKAGON_HOSTNAME=hackagon.example.org
PLAUSIBLE_HOSTNAME=plausible-hackagon.example.org
OPENREPLAY_HOSTNAME=openreplay-hackagon.example.org

# The k3d chart rig (.claude/skills/k3d-chart-rig/scripts/tunnel.sh) takes TWO
# names on ONE tunnel: the helm chart routes the app and Keycloak by HOST, on
# two separate Ingresses, so there is no single name that reaches both.
#
# ⚠ BOTH ARE ONE LABEL DEEP, DELIBERATELY. Cloudflare's free Universal SSL
# covers the apex and one label — `example.org` and `a.example.org` — and
# NOTHING below that. `auth.k3d-hackagon.example.org` gets no certificate at the
# edge and answers a TLS handshake with alert 40, which reads to a browser as a
# broken site rather than as a missing certificate. Keep them siblings unless
# the zone has Advanced Certificate Manager.
K3D_HOSTNAME=k3d-hackagon.example.org
K3D_AUTH_HOSTNAME=k3d-auth-hackagon.example.org

# Optional: tunnel names as they appear in the Cloudflare dashboard. Defaults
# below. Change them if two checkouts share one Cloudflare account, or the
# second one will reuse the first's tunnel and repoint its DNS.
#HACKAGON_TUNNEL_NAME=hackagon
#PLAUSIBLE_TUNNEL_NAME=hackagon-plausible
#OPENREPLAY_TUNNEL_NAME=hackagon-openreplay
#RIG_TUNNEL_NAME=hackagon-k3d
364 changes: 364 additions & 0 deletions .claude/skills/cloudflare-tunnel/SKILL.md

Large diffs are not rendered by default.

433 changes: 433 additions & 0 deletions .claude/skills/cloudflare-tunnel/scripts/auth-wire.sh

Large diffs are not rendered by default.

55 changes: 55 additions & 0 deletions .claude/skills/cloudflare-tunnel/scripts/down.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#!/usr/bin/env bash
# Stop all tunnels to this stack — the compose quick tunnel, the named tunnel's
# container, and any generic port tunnels — and undo the OIDC rewiring.
#
# THE NAMED TUNNEL'S HOSTNAME AND DNS RECORD SURVIVE THIS, on purpose. Stopping
# the container is "take the link down for now"; the whole value of a named
# tunnel is that the same hostname comes back on the next up.sh, with the issuer
# wiring still correct. To give the hostname up for good — delete the tunnel and
# its DNS record from Cloudflare — that is a separate, explicit act:
#
# bash .claude/skills/lib/cf-named-tunnel.sh destroy hackagon <hostname>
set -euo pipefail
HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
ROOT_DIR="$(cd "$HERE/../../../.." && pwd)"
COMPOSE_FILE="$ROOT_DIR/.devcontainer/docker-compose.yml"
case "$(uname -s)" in
MINGW* | MSYS*)
export MSYS_NO_PATHCONV=1
export MSYS2_ARG_CONV_EXCL="*"
COMPOSE_FILE="$(cygpath -m "$COMPOSE_FILE")"
;;
esac
# Stop the built server on :8082 first. `auth-wire.sh --restore` deliberately
# leaves a running one alone (it would be a hole in the public link mid-suite),
# so if this did not kill it the box would keep a server pinned to a tunnel
# issuer for a tunnel that no longer exists. No-op when nothing is running.
# (It never owned :8081, so `vite dev` needs no handover — that used to be this
# step's real job, and the reason a suite run blacked out the public link.)
docker compose -f "$COMPOSE_FILE" exec -T -u vscode -e USER=vscode dev \
bash -lc 'cd /workspaces/hackagon && bash .claude/skills/cloudflare-tunnel/scripts/prod-serve.sh stop' ||
echo "warn: prod-serve stop skipped (dev container not running?)" >&2

# If a --with-auth run rewired the OIDC issuers, put them back too (no-op
# when there is no config.local.yaml to delete; skipped if the dev container is
# down, in which case the next `just up` still needs a manual --restore).
docker compose -f "$COMPOSE_FILE" exec -T -u vscode -e USER=vscode dev \
bash -lc 'cd /workspaces/hackagon && bash .claude/skills/cloudflare-tunnel/scripts/auth-wire.sh --restore' ||
echo "warn: auth restore skipped (dev container not running?)" >&2

docker compose -f "$COMPOSE_FILE" --profile tunnel rm -sf tunnel caddy 2>/dev/null || true

# THIS STACK's named tunnel only. `cf-named-*` also covers the plausible and
# openreplay rigs, which have their own hostnames and their own down.sh — taking
# an analytics dashboard offline as a side effect of stopping the app's link is
# exactly the kind of over-broad cleanup that gets discovered days later.
docker rm -f "cf-named-${HACKAGON_TUNNEL_NAME:-hackagon}" >/dev/null 2>&1 &&
echo "stopped cf-named-${HACKAGON_TUNNEL_NAME:-hackagon}" || true

for name in $(docker ps --format '{{.Names}}' | grep -E '^cf-quicktunnel-' || true); do
docker rm -f "$name" >/dev/null
echo "stopped $name"
done
echo "tunnels down"
echo "(a named tunnel's hostname and DNS record are kept — the next up.sh reuses"
echo " them. Give them up with: lib/cf-named-tunnel.sh destroy <name> <hostname>)"
Loading