╭ changed ────╮ │src/event.zig│ ╰─────────────╯ ╭─────────────────────────────────────────────────────────────────────────╮ │2309 if (user.removed) return error.NotFound; │ │2310 │ │2311 var keys: std.ArrayList(u8) = .empty; │ │2312 + var count: usize = 0; │ │2313 var held = false; │ │2314 var lines = std.mem.splitScalar(u8, user.event.ssh_keys, '\n');│ │2315 while (lines.next()) |line| { │ ╰─────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────╮ │2320 } │ │2321 if (keys.items.len > 0) try keys.append(arena.allocator(), '\n');│ │2322 try keys.appendSlice(arena.allocator(), line); │ │2323 + count += 1; │ │2324 } │ │2325 if (added) |key| { │ │2326 if (held) return error.KeyAdded; │ ╰───────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────╮ │2327 + if (count >= User.ssh_key_max_count) return error.TooManyKeys; │ │2328 if (keys.items.len > 0) try keys.append(arena.allocator(), '\n');│ │2329 try keys.appendSlice(arena.allocator(), key); │ │2330 } else if (!held) return; │ ╰───────────────────────────────────────────────────────────────────────────────╯ ╭ changed ─────────╮ │src/event/User.zig│ ╰──────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────╮ │28 │ │29 pub const name_min_len = 4; │ │30 pub const name_max_len = 32; │ │31 +// how many ssh keys a user may hold, so the keys tab stays one short page│ │32 +pub const ssh_key_max_count = 50; │ │33 │ │34 // the moment keys `evt.merge` reads and writes for this kind │ │35 pub const merge_policy: evt.MergePolicy = .target_wins; │ ╰──────────────────────────────────────────────────────────────────────────────╯ ╭ changed ─╮ │src/ui.zig│ ╰──────────╯ ╭───────────────────────────────────────────────────────────────╮ │2374 invalid, │ │2375 unsupported, │ │2376 already_added, │ │2377 + too_many, │ │2378 │ │2379 pub fn fromError(err: anyerror) ?KeyFailure {│ │2380 return switch (err) { │ ╰───────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────╮ │2381 error.InvalidKey => .invalid, │ │2382 error.UnsupportedKey => .unsupported,│ │2383 error.KeyAdded => .already_added, │ │2384 + error.TooManyKeys => .too_many, │ │2385 else => null, │ │2386 }; │ │2387 } │ ╰───────────────────────────────────────────────────────────────╯ ╭ changed ──────────╮ │src/ui/UserKeys.zig│ ╰───────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │173 .invalid => " add ssh key (invalid) ", │ │174 .unsupported => " add ssh key (unsupported type) ", │ │175 .already_added => " add ssh key (already added) ", │ │176 + .too_many => " add ssh key (too many keys) ", │ │177 } else add_label; │ │178 add.options.bottom_label.text = if (root_focus.grandchild_id == add.getFocus().id) " press enter " else "";│ │179 // the web form handling finds the inputs by focus id │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯