-
Notifications
You must be signed in to change notification settings - Fork 0
Contributing and Conventions
The authoritative process document is CONTRIBUTING.md. This page summarises it and adds the code conventions that follow from the architecture.
Participation is governed by the Code of Conduct.
| Branch | Purpose |
|---|---|
main |
Stable, protected. Direct pushes blocked |
feat/<short-description> |
New features |
fix/<short-description> |
Bug fixes |
chore/<short-description> |
Tooling, dependencies, refactors |
docs/<short-description> |
Documentation only |
Branch from main; rebase on main before opening a PR.
<type>(<scope>): <short summary in present tense>
<body — explain WHY, not what. Include context, trade-offs, constraints.>
Types: feat, fix, chore, docs, test, refactor, perf
Scopes (the module name): transport-api, transport-netty, server, bundle, common,
consumer-state-store, lab, build, ci
feat(server): add TokenValidator SPI for per-handshake auth
fix(bundle): DEGRADED channel drops in-flight responses
chore(build): bump Spring Boot to 3.5.5
The body carries the weight.
git show <hash>should be self-contained enough that someone can understand the motivation without external context. This is not ceremony — several of the subtlest behaviours in this codebase (the supersede skip,canSend()onDEGRADED, growth-first queueing) are only comprehensible from the commit that explains why.
- All tests pass locally
- PR template filled in completely — summary plus test plan
- Related issues linked
- One maintainer approval required
- Merged with squash-and-merge (linear
mainhistory) -
CHANGELOG.mdupdated under[Unreleased]
The PR title follows the same Conventional Commits format as a commit message.
Call out security-sensitive changes explicitly in the description so maintainers can prioritise review: authentication, TLS, token validation, wire protocol, serialization, event-store persistence, and dependency updates with known CVEs.
- Java 25 — records, sealed interfaces, pattern matching, virtual threads where appropriate. No preview features in production code.
-
No
System.exit, anywhere. Failures surface through futures, exceptions or callbacks. -
Constructors do no work. Thread starts and I/O belong in an explicit
start(). -
OCP via dispatcher maps —
Map<Class<? extends Message>, Handler>, not switch chains. Adding a handler type must not touch existing dispatch code. -
Records for all value types —
Messagesubtypes,BundleRegistrationInfo,ConsumerCheckpointsubtypes,ConsumerErrorState,VersionedCheckpoint, and so on. - Tests at the boundary. Real TCP, not mocks.
- No comments that restate the code. Comment non-obvious invariants, constraints and workarounds only.
- No extra abstractions. Solve the problem at hand; do not design for hypothetical futures.
- Virtual threads for business executors. Never block a Netty EventLoop — CBOR decode and handler dispatch both hand off.
Style is enforced by .editorconfig: 4-space indent for Java, LF line endings, 120-character soft
limit.
Three rules are load-bearing rather than stylistic. Breaking them causes real, subtle bugs.
Two steps, and the compiler enforces the rest:
- Extend the
permitsclause of the sealedMessageinterface - Register a byte tag in
MessageTypeRegistry
Every non-exhaustive switch in the codebase then fails to compile until it handles the new type.
Do not work around this with a default branch.
Wire DTOs evolve by addition, and every codec tolerates unknown properties. When adding a field:
- keep
FAIL_ON_UNKNOWN_PROPERTIESdisabled in all four mappers (JacksonCborCodec,JacksonCborPayloadCodec,AdminPayloadCodec,ObjectMapperUtils), and - give the new record component a
null-normalising@JsonCreator.
CodecVersionToleranceTest pins both skew directions. See
Wire Protocol § 8 for the near-invisible outage that strictness caused — and note
that a derived getter on a wire DTO is enough to trigger it.
Every Netty-to-Netty forward must take the raw path (Transport.sendRaw). The counters
forwardedRawCount / forwardedReencodedCount are exported as
evento.server.forwarded{path=raw|reencoded} and tests assert the contract.
Changing any of these signatures requires a major version bump:
-
Annotations —
@Aggregate,@CommandHandler,@AggregateCommandHandler,@EventHandler,@EventSourcingHandler,@QueryHandler,@SagaEventHandler,@InvocationHandler,@Service,@Projector,@Projection,@Saga,@Observer,@Invoker -
Bundle bootstrap —
EventoBundle.Builder -
Modeling types —
AggregateState,Event,Command,Query,DomainCommandMessage,DomainEventMessage,ServiceCommandMessage,ServiceEventMessage,DecoratedDomainCommandMessage -
Gateways —
CommandGateway,QueryGateway -
Consumer SPIs —
ConsumerStateStore,ConsumerLock,SagaStateStore,DeadEventQueue,DedupeStore,ConsumerEngineConfig,ConsumerExecutor+ConsumerExecutors -
Server Spring starter — the
evento.server.bus.*properties andBusFacadeautowiring
By submitting a pull request you agree that your contribution is licensed under the project's dual licence — AGPL-3.0 for open source, commercial licence for proprietary use.
Roles, decision-making, release responsibilities and ownership are documented in GOVERNANCE.md and MAINTAINERS.md.
Evento Framework — Copyright 2020–2026 © Gabor Galazzo. Dual-licensed under AGPL-3.0 and a commercial licence.
This wiki documents the implementation; the repository is authoritative where the two disagree. Found something out of date? Open an issue.
Getting oriented
Internals
Operations
- Server Configuration
- Throughput and Capacity
- Observability
- Security Model
- Server REST API
- Troubleshooting
Project