Skip to content
This repository was archived by the owner on Sep 14, 2026. It is now read-only.

Commit ac4bc62

Browse files
committed
Release Java Network Chat 1.6.0
1 parent a50f1d0 commit ac4bc62

47 files changed

Lines changed: 3907 additions & 198 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/release.yml

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ permissions:
1111
jobs:
1212
release-check:
1313
runs-on: ubuntu-latest
14+
permissions:
15+
contents: write
1416
steps:
1517
- name: Checkout
1618
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
@@ -22,4 +24,10 @@ jobs:
2224
- name: Verify release build
2325
run: |
2426
chmod +x ./gradlew
25-
./gradlew check
27+
./gradlew check releaseBundle
28+
- name: Upload release assets
29+
if: github.event_name == 'release'
30+
env:
31+
GH_TOKEN: ${{ github.token }}
32+
run: |
33+
gh release upload "${GITHUB_REF_NAME}" build/release/*.zip build/release/checksums.txt build/release/provenance.json --clobber

CHANGELOG.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,47 @@
22

33
## Unreleased
44

5+
## 1.6.0 - 2026-06-12
6+
7+
- Reworked Swing connection flow into a single settings dialog with defaults, cancel, and retry.
8+
- Added GUI status bar, send button, outgoing message validation, and graceful disconnect on close.
9+
- Preserved exact connection failure reasons for GUI retry flows.
10+
- Broadcast text messages back to the sender and include the current user in the initial user list.
11+
- Resolved console client settings in host/port/user order and fixed EOF handling for piped input.
12+
- Changed connection close order so closing a client unblocks pending socket reads.
13+
- Fixed UI smoke coverage to exercise the controller-owned chat window.
14+
- Wired Gradle `runClient` to standard input for interactive console runs.
15+
- Added embedded Swing connection panel, last-settings preferences, participant count in the status
16+
bar, read-only disconnect state, and reconnect button with a short backoff.
17+
- Replaced the GUI latest-message slot with a bounded local timeline, service events, copy/select
18+
all/clear controls, own-message rendering, and `messageId`-based deduplication.
19+
- Preserved client `messageId` and timestamp when the server echoes normalized text messages.
20+
- Added protocol versioning metadata plus room/private message frame types.
21+
- Added server-managed rooms with default `general`, room creation on join, room-scoped broadcasts,
22+
leave events, and private sender/recipient delivery.
23+
- Added Swing room selection, join/leave controls, optional private recipient input, and room/private
24+
timeline rendering.
25+
- Added integration coverage for room-only delivery, private-only delivery, room join/leave, and
26+
explicit protocol errors for unversioned clients.
27+
- Added optional file-backed JSONL server history with bounded rotation, corrupt-line tolerance, and
28+
room replay after restart.
29+
- Added local GUI timeline search by text, sender, date/timestamp, room, and recipient plus JSON/CSV
30+
timeline export.
31+
- Added tests for history persistence, rotation, corrupt startup data, restart replay, search, and
32+
export.
33+
- Added legacy JSONL history migration for unversioned `TEXT` records.
34+
- Added optional TLS server/client socket mode through JSSE keystore/truststore configuration.
35+
- Added optional file-backed token accounts, salted SHA-256 token hashes, `USER`/`ADMIN` roles, and a
36+
`createAccount` helper.
37+
- Added admin `/health` command with private server status responses and structured lifecycle/auth
38+
logs.
39+
- Added Windows release zip packaging plus SHA-256 checksums and local provenance metadata.
40+
- Updated release workflow to build and upload release artifacts with checksums/provenance.
41+
- Expanded security documentation with chat threat model, trust boundaries, and deployment
42+
recommendations.
43+
- Fixed a client shutdown race where fast console `exit` could close the socket while the reader
44+
thread still used the shared connection reference.
45+
546
## 1.1.0
647

748
- Added `ChatServerConfig` with server limits and socket timeout settings.

README.en.md

Lines changed: 72 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,12 @@ Network Chat is a Java 21 chat application over TCP sockets with:
1414
- a resilient server with user handshake and broadcast.
1515
- a console client.
1616
- a bot client with date/time commands.
17-
- a Swing GUI client using MVC style structure.
17+
- a Swing GUI client with an embedded connection panel, retry/cancel flow, saved last settings,
18+
local message timeline, rooms, private messages, and MVC style structure.
19+
- optional file-backed message history with room replay after server restart.
20+
- optional TLS mode, token-based accounts with `USER`/`ADMIN` roles, and the admin `/health`
21+
command.
22+
- a Windows release zip with launch scripts, checksums, and provenance metadata.
1823
- reproducible Gradle build, tests, CI, and quality gates.
1924

2025
![Swing GUI client](docs/images/gui-client.svg)
@@ -39,14 +44,70 @@ Server and clients can also be run directly with Java by building jars from Grad
3944
The default server port is `1500`. Programmatic server startup can use `ChatServerConfig` to set the
4045
port, maximum client count, handshake timeout, and post-handshake read timeout.
4146

47+
To enable file-backed history:
48+
49+
```bash
50+
./gradlew runServer --args="--port 1500 --history build/chat-history.jsonl"
51+
```
52+
53+
To enable accounts, first generate rows for `accounts.csv`:
54+
55+
```bash
56+
./gradlew createAccount --args="alice USER secret" >> build/accounts.csv
57+
./gradlew createAccount --args="admin ADMIN admin-secret" >> build/accounts.csv
58+
./gradlew runServer --args="--port 1500 --accounts build/accounts.csv"
59+
```
60+
61+
Clients send the token through the GUI `Token` field or the `NETWORK_CHAT_TOKEN` environment
62+
variable. Admin users can send `/health` and receive a private server status response.
63+
64+
To enable TLS, create a Java keystore for the server:
65+
66+
```bash
67+
keytool -genkeypair -alias network-chat -keyalg RSA -keysize 3072 -validity 365 \
68+
-keystore build/network-chat.p12 -storetype PKCS12 -storepass changeit
69+
./gradlew runServer --args="--port 1500 --tls-keystore build/network-chat.p12 --tls-password changeit"
70+
```
71+
72+
Clients enable TLS through environment variables:
73+
74+
```powershell
75+
$env:NETWORK_CHAT_TLS="true"
76+
$env:NETWORK_CHAT_TRUSTSTORE="build/network-chat.p12"
77+
$env:NETWORK_CHAT_TRUSTSTORE_PASSWORD="changeit"
78+
./gradlew runGuiClient
79+
```
80+
81+
To build a no-Gradle release package for end users:
82+
83+
```bash
84+
./gradlew releaseBundle
85+
```
86+
87+
Artifacts are written to `build/release`: the Windows zip, `checksums.txt`, and `provenance.json`.
88+
4289
## Architecture and protocol
4390

4491
The compact architecture contract is documented in [docs/architecture.md](docs/architecture.md).
4592

4693
- `ChatServer` accepts TCP connections and handles clients in a bounded executor.
4794
- `ChatConnection` reads and writes one-line UTF-8 JSON frames.
4895
- `ChatProtocol` serializes `ChatMessage`.
96+
- `ChatMessage` carries `protocolVersion`; unversioned clients receive an explicit `ERROR`.
4997
- For `TEXT` messages, `data` contains only raw text and `sender` contains the author.
98+
- `TEXT` messages are broadcast to every client, including the sender, so users see their own sent
99+
messages in the timeline.
100+
- `ROOM_TEXT` is delivered only to room members; `PRIVATE_TEXT` is delivered only to the sender and
101+
recipient.
102+
- The GUI keeps a bounded local timeline for the current session, renders `USER_ADDED`/`USER_REMOVED`
103+
as service events, uses `messageId` for deduplication, and supports search by text, sender,
104+
date/timestamp, room, recipient plus JSON/CSV export.
105+
- When history is enabled, the server stores `ROOM_TEXT`/`PRIVATE_TEXT` frames as JSONL, bounds the
106+
history size, migrates legacy unversioned `TEXT` records, and replays recent room messages on
107+
join.
108+
- When accounts are enabled, the server accepts only `USER_NAME` frames with a valid token; roles are
109+
used for admin-only commands.
110+
- TLS is enabled through server configuration and client environment variables.
50111
- Console and Swing clients format display text such as `alice: hello`.
51112
- The bot client reads date/time commands from `data` and uses the author from `sender`.
52113

@@ -124,8 +185,16 @@ This repository is organized for maintainability:
124185
- GUI does not render in CI: UI smoke tests skip automatically in headless environments.
125186
- Client disconnects immediately: check username uniqueness and nickname length (`3..64`, letters, digits, `_`, `-`).
126187
- Client receives `Server is busy`: the configured `ChatServerConfig.maxClients` limit has been reached.
188+
- GUI shows `No connection`: check host/port and use the reconnect button; the last entered settings
189+
are stored locally.
190+
- A corrupt line in the history file is skipped during startup; valid history still loads.
191+
- `Authentication failed`: check the user row in `accounts.csv` and the GUI token field or
192+
`NETWORK_CHAT_TOKEN`.
193+
- TLS trust errors: set `NETWORK_CHAT_TRUSTSTORE` on the client or use a certificate trusted by the
194+
JVM.
127195

128196
## Roadmap
129197

130-
- v1.1.x: stabilize protocol/server lifecycle, expand negative tests, and improve documentation.
131-
- Later: rooms, message history, TLS, and persistent accounts as separate product-focused phases.
198+
- v1.6.x: TLS, token accounts, release packaging, and security hardening are implemented in the
199+
current line.
200+
- Later: persistent user profiles and richer administration as separate product-focused phases.

README.md

Lines changed: 73 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,12 @@ Network Chat — это Java 21 приложение для сетевого ч
1919
- сервер с handshake и рассылкой сообщений;
2020
- консольный клиент;
2121
- бот-клиент с командами времени/даты;
22-
- GUI клиент на Swing с разделением на MVC;
22+
- GUI клиент на Swing со встроенной панелью подключения, retry/cancel, сохранением последних
23+
настроек, локальной лентой сообщений, комнатами, приватными сообщениями и разделением на MVC;
24+
- опциональная файловая история сообщений с replay последних сообщений комнаты после рестарта;
25+
- опциональный TLS-режим, token-based accounts с ролями `USER`/`ADMIN` и admin-команда
26+
`/health`;
27+
- Windows release zip с launch scripts, checksums и provenance metadata;
2328
- воспроизводимая Gradle-сборка, тесты, CI и проверки качества.
2429

2530
![Swing GUI client](docs/images/gui-client.svg)
@@ -37,14 +42,70 @@ Network Chat — это Java 21 приложение для сетевого ч
3742
`ChatServerConfig`: он задаёт порт, максимальное число клиентов, timeout handshake и timeout чтения
3843
после handshake.
3944

45+
Чтобы включить файловую историю:
46+
47+
```bash
48+
./gradlew runServer --args="--port 1500 --history build/chat-history.jsonl"
49+
```
50+
51+
Чтобы включить accounts, сначала создайте строку для `accounts.csv`:
52+
53+
```bash
54+
./gradlew createAccount --args="alice USER secret" >> build/accounts.csv
55+
./gradlew createAccount --args="admin ADMIN admin-secret" >> build/accounts.csv
56+
./gradlew runServer --args="--port 1500 --accounts build/accounts.csv"
57+
```
58+
59+
Клиенты передают token через GUI-поле `Токен` или переменную окружения `NETWORK_CHAT_TOKEN`.
60+
Admin-пользователь может отправить `/health` и получить приватный ответ со статусом сервера.
61+
62+
Чтобы включить TLS, серверу нужен Java keystore:
63+
64+
```bash
65+
keytool -genkeypair -alias network-chat -keyalg RSA -keysize 3072 -validity 365 \
66+
-keystore build/network-chat.p12 -storetype PKCS12 -storepass changeit
67+
./gradlew runServer --args="--port 1500 --tls-keystore build/network-chat.p12 --tls-password changeit"
68+
```
69+
70+
Клиент включает TLS через окружение:
71+
72+
```powershell
73+
$env:NETWORK_CHAT_TLS="true"
74+
$env:NETWORK_CHAT_TRUSTSTORE="build/network-chat.p12"
75+
$env:NETWORK_CHAT_TRUSTSTORE_PASSWORD="changeit"
76+
./gradlew runGuiClient
77+
```
78+
79+
Релизный набор без Gradle на машине пользователя собирается командой:
80+
81+
```bash
82+
./gradlew releaseBundle
83+
```
84+
85+
Артефакты появятся в `build/release`: Windows zip, `checksums.txt` и `provenance.json`.
86+
4087
## Архитектура и протокол
4188

4289
Краткий архитектурный контракт описан в [docs/architecture.md](docs/architecture.md).
4390

4491
- `ChatServer` принимает TCP-соединения и обрабатывает клиентов в bounded executor.
4592
- `ChatConnection` читает и пишет однострочные UTF-8 JSON frames.
4693
- `ChatProtocol` сериализует `ChatMessage`.
94+
- `ChatMessage` содержит `protocolVersion`; unversioned клиенты получают явный `ERROR`.
4795
- Для `TEXT` сообщений `data` содержит только исходный текст, а `sender` содержит автора.
96+
- `TEXT` сообщения рассылаются всем клиентам, включая отправителя, чтобы пользователь видел своё
97+
сообщение в ленте.
98+
- `ROOM_TEXT` доставляется только участникам комнаты; `PRIVATE_TEXT` доставляется отправителю и
99+
адресату.
100+
- GUI хранит локальную ленту текущей сессии, оформляет `USER_ADDED`/`USER_REMOVED` как service
101+
events, использует `messageId` для дедупликации, поддерживает поиск по тексту, автору,
102+
дате/timestamp, комнате, адресату и экспорт JSON/CSV.
103+
- При включённой истории сервер сохраняет `ROOM_TEXT`/`PRIVATE_TEXT` в JSONL, ограничивает размер
104+
истории, мигрирует старые unversioned `TEXT` записи и отправляет последние сообщения комнаты при
105+
входе.
106+
- При включённых accounts сервер принимает только `USER_NAME` с корректным token; роли используются
107+
для admin-команд.
108+
- TLS включается конфигурацией сервера и переменными окружения клиента.
48109
- Console и Swing клиенты сами форматируют отображение вида `alice: hello`.
49110
- Bot client отвечает на команды времени/даты по `data`, используя автора из `sender`.
50111

@@ -75,6 +136,14 @@ Actions Summary для Linux job.
75136
- GUI не показывает окно в CI: UI smoke тесты автоматически пропускаются в headless окружении.
76137
- Клиент сразу отключился: проверьте уникальность имени и длину ника (`3..64`, буквы, цифры, `_`, `-`).
77138
- Клиент получил `Server is busy`: достигнут `maxClients` из `ChatServerConfig`.
139+
- GUI показывает `Нет соединения`: проверьте адрес/порт и используйте кнопку `Повторить`; последние
140+
введённые настройки сохраняются локально.
141+
- Повреждённая строка в history-файле пропускается при старте; валидная история продолжает
142+
загружаться.
143+
- `Authentication failed`: проверьте строку пользователя в `accounts.csv` и token в GUI или
144+
`NETWORK_CHAT_TOKEN`.
145+
- Ошибка TLS trust: укажите truststore клиента через `NETWORK_CHAT_TRUSTSTORE` или используйте
146+
сертификат, которому доверяет JVM.
78147

79148
## Структура репозитория
80149

@@ -95,5 +164,6 @@ Actions Summary для Linux job.
95164

96165
## Roadmap
97166

98-
- v1.1.x: стабилизация protocol/server lifecycle, расширение негативных тестов, улучшение документации.
99-
- Позже: комнаты, история сообщений, TLS и персистентные аккаунты отдельными функциональными этапами.
167+
- v1.6.x: TLS, token accounts, release packaging и security hardening реализованы в текущей линии.
168+
- Позже: персистентные профили пользователей и расширенное администрирование отдельными
169+
функциональными этапами.

SECURITY.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,39 @@ The maintainer aims to acknowledge valid reports within 48 hours and provide a r
2424
## Scope
2525

2626
This policy applies to application code, protocol handling, server lifecycle code, and CI configuration.
27+
28+
## Threat model
29+
30+
Network Chat is a small self-hosted Java chat, not an end-to-end encrypted messenger.
31+
32+
Protected assets:
33+
34+
- chat message contents in transit when TLS is enabled,
35+
- account tokens stored only as salted SHA-256 hashes in the optional accounts file,
36+
- server availability under configured client limits,
37+
- release artifacts and their checksums/provenance metadata.
38+
39+
Trust boundaries:
40+
41+
- Plain TCP mode is intended only for local development or trusted networks.
42+
- TLS mode protects the socket transport between client and server, but the server can still read
43+
message contents.
44+
- The accounts file is trusted server configuration; filesystem access to it is administrative
45+
access.
46+
- GUI preferences store host, port, and username only; account tokens are not persisted by the GUI.
47+
48+
Known limitations:
49+
50+
- No end-to-end encryption, federation, device verification, or forward secrecy beyond the selected
51+
JSSE TLS configuration.
52+
- No account lockout, password reset, audit log retention, or persistent profile management.
53+
- Private messages are server-mediated and are persisted when history is enabled.
54+
- `NETWORK_CHAT_TLS_TRUST_ALL=true` is a development escape hatch and must not be used for production
55+
deployments.
56+
57+
Operational recommendations:
58+
59+
- Enable TLS outside localhost/trusted lab networks.
60+
- Keep `accounts.csv` readable only by the server operator.
61+
- Rotate tokens by replacing account-file rows and restarting the server.
62+
- Publish release zip files together with `checksums.txt` and `provenance.json`.

0 commit comments

Comments
 (0)