Skip to content

CODETRIAL_DURATION_MIN does not preselect the interview length in the lobby #582

Open

Description

@RWong04

Problem

README.md and docs/interview-length.md say CODETRIAL_DURATION_MIN is the length preselected in the lobby for a candidate who does not choose. An operator who sets CODETRIAL_DURATION_MIN=30 and starts codetrial web still gets 45 preselected, and, from reading token_duration_min, a /api/token request with no durationMin would also be given 45.

Current behavior

Reproduced on a release build of upstream/main e87cc4d (the line numbers below were checked against it) with a placeholder LiveKit config and no provider keys:

make build
CODETRIAL_DURATION_MIN=30 ./target/release/codetrial web --config cfg.env --web-addr 127.0.0.1:3100
curl -s 127.0.0.1:3100/api/session

/api/session returns {"candidateVideo":null,"deviceLogin":false,"guestModeAvailable":false,"loginRequired":true,"maxDurationMin":90,"signedIn":false}, with no default length.

After the lobby page had loaded in a browser and its scripts had run, the duration buttons were:

data-duration=30  selected=false  disabled=false
data-duration=45  selected=true   disabled=false
data-duration=60  selected=false  disabled=false

With CODETRIAL_DURATION_MIN unset, /api/session and the served page are dentical. The browser check was made signed out, since the placeholder config cannot sign in. /api/token was not called for the same reason; its behavior below follows from token_duration_min taking no configured default.

  • src/config.rs:471 loads the value into default_duration_min.
  • The only readers of that field are src/main.rs:810 (check-gemini) and src/web/setup.rs:947 (setup probe bootstrap). Neither reaches a candidate.
  • src/web/auth.rs:543-587: /api/session reports maxDurationMin but no default length.
  • web/index.html:1766 hard-codes class="duration-button selected" on the 45 minute button.
  • src/web/token.rs:432: a missing durationMin becomes the constant DEFAULT_DURATION_MIN, not the configured value.
  • The value does take effect in one place: src/main.rs:1238 (interview_duration_min) feeds the recording cap check.

Desired outcome

Either of the following, whichever the maintainers prefer.

A. The setting reaches the lobby. The configured length is the one preselected in the lobby, and the one used when a token request names no length, limited by duration_ceiling. This matches what README.md and docs/interview-length.md already say.

B. The setting stays operator-only. CODETRIAL_DURATION_MIN keeps affecting only check-gemini, the setup probe and the recording cap check, and the README, docs/interview-length.md and config/codetrial.env.example say so instead of promising a preselected length.

Proposed scope

For A, one PR:

  • src/web/auth.rs: /api/session also reports the configured default length.
  • web/app.js: select that button when the page loads, before applyDurationCeiling, so a default above the recording cap still moves down. A length the candidate chose earlier is not overwritten.
  • src/web/token.rs: token_duration_min uses the configured value instead of DEFAULT_DURATION_MIN when no length is named.
  • Tests: /api/session reports 30 when configured and 45 when not; a token request without durationMin gets the configured value, still limited by the recording cap; a browser test shows which button is preselected and that a remembered choice wins.

For B, one PR that edits the three documents above and removes the claim.

Open question

The lobby offers 30, 45 and 60 minutes, while the endpoint accepts 10 to 90. For A, how should a configured value that is not one of the three buttons (for example 20 or 75) behave: snap to the nearest button, or leave the 45 default?

Acceptance criteria

For A:

  • With CODETRIAL_DURATION_MIN=30, /api/session reports 30 and the lobby shows 30 selected; with it unset, 45 as today.
  • A /api/token request without durationMin gets the configured value, still limited by the recording cap.
  • A configured value outside the three buttons follows the answer to the open question, and docs/interview-length.md states it.
  • ./scripts/test.sh passes.

For B:

  • No document says the setting preselects a lobby length.
  • ./scripts/test.sh passes.

Related

Not a duplicate of #16 or #17 (recording cap vs interview length), which are closed and do not touch the default.


I would like to implement this myself, whichever of A or B the maintainers choose. I will wait for the issue to be assigned to me before opening a pull request, and I will keep the change to one pull request with the tests listed above.

Activity

  1. RWong04 commented on Nov 4, 2026

    @RWong04
    ContributorAuthor

    Thanks for assigning this. I will go with option A: /api/session reports the configured length, the lobby preselects it, and /api/token uses it when none is given. A value that is not one of the three buttons snaps to the nearest one. Please tell me if you prefer B.

  2. jserv commented on Nov 4, 2026

    @jserv
    Contributor

    I will go with option A: /api/session reports the configured length, the lobby preselects it, and /api/token uses it when none is given. A value that is not one of the three buttons snaps to the nearest one. Please tell me if you prefer B.

    Go ahead with option A. Meanwhile, review the API endpoints and remove any that serve no useful purpose.

  3. RWong04 commented on Nov 4, 2026

    @RWong04
    ContributorAuthor

    Understood. I will keep this PR to option A and send the endpoint review as a separate PR, listing each endpoint I propose to remove and its callers. Please tell me if you want it in this PR instead.

  4. added 6 commits that reference this issue on Nov 4, 2026
    e64598e
    0609ef1
    ceaea79
    46a811e
    32f8528
    4d13dd5
  5. jserv commented on Nov 6, 2026

    @jserv
    Contributor

    @RWong04 Keep #584 to option A. Send the endpoint review as its own PR, listing each endpoint you propose to remove and its callers, as you describe.

  6. added 6 commits that reference this issue on Nov 7, 2026
    16dba04
    7728eb5
    2e11c3f
    e280bfd
    45a824f
    254616c
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions