8000 docs: update README and docs for release readiness by kawasima · Pull Request #97 · enkan/enkan · GitHub
[go: up one dir, main page]

Skip to content

docs: update README and docs for release readiness - #97

Merged
kawasima merged 14 commits into
developfrom
feature/docs-update
Mar 19, 2026
Merged

kawasima merged 14 commits into
developfrom
feature/docs-update

Conversation

@kawasima
Copy link
Copy Markdown
Collaborator

Summary

  • Rewrite README with clear value proposition, Spring Boot comparison, features list, and complete get-started guide
  • Delete AGENTS.md and merge content into CLAUDE.md (updated for Java 25 / v0.13.1-SNAPSHOT)
  • Add release procedure to CLAUDE.md
  • Restructure getting-started.md with numbered steps and "What's next?" links
  • Add Micrometer to component catalog, mark Metrics as deprecated, add virtualThreads to Jetty

Key changes in README

  • Remove stale Maven archetype section
  • Add "Why Enkan?" comparison table (vs Spring Boot)
  • Add features list (type-safe middleware, GraalVM, virtual threads, observability)
  • Add component catalog table
  • Add documentation links section

Test plan

  • No code changes — documentation only
  • All links verified against existing doc files

🤖 Generated with Claude Code

kawasima and others added 14 commits March 19, 2026 16:00
- README: rewrite with clear value proposition, comparison table,
  features list, complete get-started guide, component catalog table.
  Remove stale archetype section.
- CLAUDE.md: merge AGENTS.md content, update Java 25 / v0.13.1-SNAPSHOT,
  add module table (incl. graalvm, micrometer, opentelemetry),
  add release procedure, delete Past Issues (all fixed in code).
- Delete AGENTS.md (content merged into CLAUDE.md).
- docs/getting-started.md: restructure with numbered steps, add
  "What's next?" links, use kotowari instead of enkan-web.
- docs/reference/components.md: add Micrometer component, mark
  Metrics as deprecated, add virtualThreads property to Jetty.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add a find+sed step that updates all <version> tags in
docs/src/content/**/*.md, ensuring getting-started.md and
any future doc pages stay in sync with the release version.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add steps to update:
- CLAUDE.md version string (plain text)
- SECURITY.md supported version table (major.minor.x)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The self-executing JAR stub concatenates a shell script with the fat
JAR. Without exit 0 after the exec line, the shell could interpret
JAR binary bytes as additional arguments, causing args.length != 0
and skipping the auto-connect code path (readPortFile).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Doma2 converts camelCase field names to snake_case for SQL column
mapping (postedAt -> posted_at). The DDL had 'postedat' (no
underscore), causing H2 to create column POSTEDAT which does not
match the generated SQL's POSTED_AT.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add V4 migration with seed customers (alice/bob, password: password)
  so the guestbook login actually works out of the box
- Change password input from type="text" to type="password"

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add PasswordEncoder using PBKDF2WithHmacSHA256 (JDK standard, no
  external dependencies). Stored format: iterations:salt:hash
- Change login flow: query by email only (selectByEmail), then verify
  password hash in Java with constant-time comparison
- Seed data (V4 migration) now stores hashed passwords via
  PasswordEncoder.encode()
- Remove password from Customer.toString() to prevent log leakage
- Rename loginByPassword.sql -> selectByEmail.sql

Login credentials: alice@example.com / password, bob@example.com / password

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
close() was not idempotent — the shutdown hook called close() again
after ConsoleHandler.run() already called it, causing raise(Signal.INT)
to fire a second time and requiring a third Ctrl+C to actually exit.

Use compareAndSet(true, false) to make close() a no-op on subsequent
calls.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add end-to-end browser tests that start the full Enkan system and
verify key user flows work correctly. Tagged @tag("smoke") and
excluded from CI.

Tests cover:
- Index page loads with example links
- Customer CRUD: list (shows seed data), new form, create + redirect
- Guestbook: unauthenticated redirect to login, login with hashed
  password, post message
- Session counter: increment across requests
- Static resources: stylesheet links present
- 404 handling

Bugs found and fixed during test development:
- MiscController.counter NPE on first visit (Integer unboxing of null)
- Missing hibernate-validator dependency (ValidateBodyMiddleware failed
  silently in production mode)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Save full-page screenshots to target/screenshots/ for each test step:
- 01-index, 02-customer-list, 03a/b/c-customer-new-form/filled/after-create
- 10-guestbook-login-redirect, 11a/b/c-guestbook-login/list/after-post
- 20a/b-counter-first/second, 50-not-found

12 screenshots total, viewport set to 1280x720.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When close() is called from within the run() loop (Ctrl+C, /exit, EOF,
shutdown), readLine() is not blocking so raise(Signal.INT) is
unnecessary and causes a spurious UserInterruptException that requires
an extra Ctrl+C to exit.

- closeQuietly(): used from run() loop — skips raise(INT), just
  sets isAvailable=false and closes sockets
- close(): used from shutdown hook and monitor thread — raises INT
  to wake up a blocking readLine(), then closes sockets
- Both are idempotent via compareAndSet(true, false)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
raise(Signal.INT) caused a re-entrant UserInterruptException that
required a third Ctrl+C to exit. Replace with terminal.close() which
interrupts readLine() via EndOfFileException — a path already handled
by the run() loop.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Root cause: JLine consumes SIGINT as UserInterruptException, so the
JVM shutdown hook never fires and the non-daemon ExecutorService thread
keeps the JVM alive indefinitely after run() returns.

Fix: call clientThread.shutdown() immediately after execute() in main(),
then awaitTermination() to block main until the console handler finishes.
When run() returns (after Ctrl+C x2, /exit, EOF, or server shutdown),
the executor thread terminates and the JVM exits naturally.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The pending-exit state was shown both as a println message and as the
next readLine prompt, causing two messages on a single Ctrl+C. Remove
the prompt variant and keep only the println message.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@kawasima
kawasima merged commit 1af5de1 into develop Mar 19, 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

0