Users: display name of 129 characters accepted #1584

Open
opened 2026-10-12 02:01:15 +00:00 by kayg · 3 comments
Owner

A 129-character display name is accepted although the documented limit is 128 characters (#1553 changed the limit to characters). Align validation and the field error.

Found by the merge round 41 adversarial run (branch job/merge41 adf8205c9; log artifacts/merge41-gates/adversarial-final.log in worktree /home/kayg/Developer/calternal-wt/merge41, report on #1573). Not a merge blocker under the CLAUDE.md rule. Owner of the fix: confirm whether it also happens on production c0f8da461, fix with a regression test in tests/adversarial.

A 129-character display name is accepted although the documented limit is 128 characters (#1553 changed the limit to characters). Align validation and the field error. Found by the merge round 41 adversarial run (branch job/merge41 adf8205c9; log artifacts/merge41-gates/adversarial-final.log in worktree /home/kayg/Developer/calternal-wt/merge41, report on #1573). Not a merge blocker under the CLAUDE.md rule. Owner of the fix: confirm whether it also happens on production c0f8da461, fix with a regression test in tests/adversarial.
Author
Owner

Starting #1584 on job/dname-1584, based on 8e840962979acd2bdf58141888618ab5560f728e. I am tracing the display-name limit through server validation, the web form and the existing adversarial profile probe before applying a focused regression fix.

Starting #1584 on `job/dname-1584`, based on `8e840962979acd2bdf58141888618ab5560f728e`. I am tracing the display-name limit through server validation, the web form and the existing adversarial profile probe before applying a focused regression fix.
Author
Owner

Found the mismatch in the current branch: crates/calternal-auth/src/store.rs sets the display-name cap to 160 and its unit test accepts 129 ASCII characters; UsersGroup.svelte and userCreate.ts also cap at 160. The existing tests/adversarial/attack2.py profile probe expects 129 to return 400, but profile validation used the same 160-character helper and returned a generic error without a field. I am aligning all account name inputs and the profile response with 128 Unicode scalar values, then extending the probe to verify the 400 field and Unicode boundaries.

Found the mismatch in the current branch: `crates/calternal-auth/src/store.rs` sets the display-name cap to 160 and its unit test accepts 129 ASCII characters; `UsersGroup.svelte` and `userCreate.ts` also cap at 160. The existing `tests/adversarial/attack2.py` profile probe expects 129 to return 400, but profile validation used the same 160-character helper and returned a generic error without a field. I am aligning all account name inputs and the profile response with 128 Unicode scalar values, then extending the probe to verify the 400 field and Unicode boundaries.
Author
Owner

#1584 complete

Aligned display-name validation to 128 Unicode scalar values in the server and all account forms: Admin add-User, profile editing, and signup. The server accepts 128 and rejects 129, including multibyte and combining-mark cases. Invalid profile edits return HTTP 400 with field: "display_name". Setup and invite creation keep their generic error shape from #1553.

Files

  • crates/calternal-auth/src/store.rs
  • apps/web/src/lib/auth/displayName.ts and displayName.test.ts
  • apps/web/src/lib/auth/components/CreateAccountFlow.svelte
  • apps/web/src/routes/settings/account/ProfileGroup.svelte
  • apps/web/src/routes/settings/admin/UsersGroup.svelte and UsersGroup.svelte.test.ts
  • apps/web/src/routes/settings/admin/userCreate.ts and userCreate.test.ts
  • tests/adversarial/attack2.py
  • contracts/perf/exceptions.json and contracts/perf/adoption-1058.json (refreshed exact live hashes; ledger counts and limits are unchanged)

Head SHA

e26bb4c7dc1a38ba1dee9666ac58a07fe6194ac6

Gates (verbatim summary output)

  • cargo fmt --check: no output; exit 0.
  • cargo clippy -p calternal-auth --all-targets -- -D warnings:
    Finished dev profile [unoptimized + debuginfo] target(s) in 2.06s
  • cargo test -p calternal-auth:
    test result: ok. 142 passed; 0 failed; 3 ignored; 0 measured; 0 filtered out; finished in 39.63s
    test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
  • bun run check:
    perf-lint: PASS; 0 violations; 20373 scoped exceptions
    svelte-check found 0 errors and 0 warnings
  • Focused Vitest (displayName.test.ts, userCreate.test.ts, UsersGroup.svelte.test.ts):
    Test Files 3 passed (3)
    Tests 17 passed (17)
  • Real-server ROUND2_SECTIONS=display-names adversarial probe:
    server alive at end: True
    ==== ROUND 2 FINDINGS 0
    ==== ROUND 2 SLOW 0
  • cargo clean: Removed 12474 files, 9.4GiB total. Removed apps/web/build, apps/web/.svelte-kit, and task temp files.

UX gaps closed

All three account-name forms now use the same Unicode-scalar limit. The real-server probe checks the 400 field name and boundary cases.

UX gaps left

None introduced. The change does not alter visible layout.

Decisions

docs/DESIGN.md does not set a display-name length. I followed #1553's existing Unicode-scalar choice (str::chars() / JavaScript Array.from()) and #1584's 128-character cap. Combining marks count as separate scalars. The profile route names the invalid field; setup and invite routes retain their existing generic error contract.

The check cost is bounded by the input size: server validation scans at most 512 UTF-8 bytes, and browser inputs are capped at 256 UTF-16 code units. This change adds no new operation.

For the merge round

  • cd apps/web && bun run test -- --maxWorkers=2 — verify the complete web suite on the merged branch.
  • tests/adversarial/run.sh — run the full cross-plugin adversarial matrix against the merged branch; this job ran only the focused display-names section.
# #1584 complete Aligned display-name validation to 128 Unicode scalar values in the server and all account forms: Admin add-User, profile editing, and signup. The server accepts 128 and rejects 129, including multibyte and combining-mark cases. Invalid profile edits return HTTP 400 with `field: "display_name"`. Setup and invite creation keep their generic error shape from #1553. ## Files - `crates/calternal-auth/src/store.rs` - `apps/web/src/lib/auth/displayName.ts` and `displayName.test.ts` - `apps/web/src/lib/auth/components/CreateAccountFlow.svelte` - `apps/web/src/routes/settings/account/ProfileGroup.svelte` - `apps/web/src/routes/settings/admin/UsersGroup.svelte` and `UsersGroup.svelte.test.ts` - `apps/web/src/routes/settings/admin/userCreate.ts` and `userCreate.test.ts` - `tests/adversarial/attack2.py` - `contracts/perf/exceptions.json` and `contracts/perf/adoption-1058.json` (refreshed exact live hashes; ledger counts and limits are unchanged) ## Head SHA `e26bb4c7dc1a38ba1dee9666ac58a07fe6194ac6` ## Gates (verbatim summary output) - `cargo fmt --check`: no output; exit 0. - `cargo clippy -p calternal-auth --all-targets -- -D warnings`: `Finished `dev` profile [unoptimized + debuginfo] target(s) in 2.06s` - `cargo test -p calternal-auth`: `test result: ok. 142 passed; 0 failed; 3 ignored; 0 measured; 0 filtered out; finished in 39.63s` `test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s` - `bun run check`: `perf-lint: PASS; 0 violations; 20373 scoped exceptions` `svelte-check found 0 errors and 0 warnings` - Focused Vitest (`displayName.test.ts`, `userCreate.test.ts`, `UsersGroup.svelte.test.ts`): `Test Files 3 passed (3)` `Tests 17 passed (17)` - Real-server `ROUND2_SECTIONS=display-names` adversarial probe: `server alive at end: True` `==== ROUND 2 FINDINGS 0` `==== ROUND 2 SLOW 0` - `cargo clean`: `Removed 12474 files, 9.4GiB total`. Removed `apps/web/build`, `apps/web/.svelte-kit`, and task temp files. ## UX gaps closed All three account-name forms now use the same Unicode-scalar limit. The real-server probe checks the 400 field name and boundary cases. ## UX gaps left None introduced. The change does not alter visible layout. ## Decisions `docs/DESIGN.md` does not set a display-name length. I followed #1553's existing Unicode-scalar choice (`str::chars()` / JavaScript `Array.from()`) and #1584's 128-character cap. Combining marks count as separate scalars. The profile route names the invalid field; setup and invite routes retain their existing generic error contract. The check cost is bounded by the input size: server validation scans at most 512 UTF-8 bytes, and browser inputs are capped at 256 UTF-16 code units. This change adds no new operation. ## For the merge round - `cd apps/web && bun run test -- --maxWorkers=2` — verify the complete web suite on the merged branch. - `tests/adversarial/run.sh` — run the full cross-plugin adversarial matrix against the merged branch; this job ran only the focused `display-names` section.
Commenting is not possible because the repository is archived.
No labels
No milestone
No project
No assignees
1 participant
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
kayg/calternal-v0#1584
No description provided.