Skip to content

feat: a Room can ask one question at the door, and the answer becomes a group - #27

Merged
sunib merged 1 commit into
mainfrom
feat/room-question
Oct 6, 2026
Merged

sunib merged 1 commit into
mainfrom
feat/room-question

Conversation

@sunib

@sunib sunib commented Oct 6, 2026

Copy link
Copy Markdown
Owner

A Room can ask everyone who joins one question with a fixed set of answers. The group of the answer they pick joins audienceGroup in their token, so RBAC can let part of the room do what the rest cannot.

spec:
  question:
    prompt: Your favourite frontend framework?
    answers:                       # 2 to 8
      - {label: React,  group: demo:framework-react}
      - {label: Svelte, group: demo:framework-svelte}

Someone who picks Svelte signs in with demo:my-talk and demo:framework-svelte.

How

  • Room: spec.question is optional and mutable. Answer groups follow audienceGroup's pattern, and the CRD refuses duplicate groups and duplicate labels.
  • Join page: shows the answers as radio buttons, and the browser won't submit without one. The server accepts only an answer the Room offers, checked against the same Room it checked the code against.
  • Participant: a new optional field, spec.groups, keeps the answer. Operators may edit it, and the next sign-in carries the change.
  • Sign-in: X-Remote-Group becomes <audienceGroup>,<answer group>. Dex's authproxy connector splits on ,, its default groupHeaderSeparator, and no group the pattern admits contains one. The apiserver's demo:-only containment rule covers these groups unchanged.

Why this is a feat:

  • A Room without a question sends exactly the same X-Remote-Group as before, so the identity contract doesn't change. A tested forged answer field adds nothing.
  • The new fields on the Room and Participant are optional.
  • Groups that escaped the schema (an older CRD, hand edits) are dropped before they reach the header.
  • requirements.md said groups come "never from client input". It now says that every group comes from event configuration and a participant only chooses among the Room's answers.

Also in this PR

The demo client shows the token's groups. Its "Write a message to Kubernetes" button now works in a real browser: under Referrer-Policy: no-referrer a browser sends Origin: null, which its own check refused. Room Pass fixed the same bug earlier.

Rollout

Apply the new CRDs from config/crd before setting spec.question on a Room. With the old CRDs, Kubernetes silently drops the unknown field. Like any spec change, setting the question starts a new join-code epoch, and anyone who joined before it existed isn't asked.

Test plan

  • task lint, task test, task verify-generate, task integration
  • task e2e-up && task browser: 8/8. The new test picks Svelte, reads both groups from the real Dex token, and writes to Kubernetes with it (201).
  • task e2e, which still expects exactly [demo:room-pass-test] for a Room without a question
  • task test-network: not run locally; this change doesn't touch the network policy

🤖 Generated with Claude Code

… a group

spec.question is optional: a prompt and two to eight answers, each a label
and a demo: group. Everyone who joins picks one; the browser will not submit
without it, and the server accepts only an answer the Room offers. The
answer's group is kept on the Participant (spec.groups, new and optional) and
sent to Dex beside the audienceGroup at every sign-in, comma-separated, which
Dex's authproxy connector splits into the token's groups. The apiserver's
demo:-only containment rule covers it unchanged.

A Room without a question sends exactly the group it sent before, and a
forged answer adds nothing. Groups that escaped the schema are dropped
before they reach the header.

The demo client now shows the token's groups, and its write form works in a
real browser: under Referrer-Policy no-referrer a browser sends Origin "null",
which its own check refused.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@sunib
sunib added this pull request to stack #29 October 6, 2026 12:26
@sunib
sunib merged commit 61c77f4 into main Oct 6, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant