diff --git a/.github/settings.xml b/.github/settings.xml
new file mode 100644
index 0000000..bef4174
--- /dev/null
+++ b/.github/settings.xml
@@ -0,0 +1,17 @@
+
+
+
+ Personal
+ ${env.MAVEN_USERNAME}
+ ${env.MAVEN_PASSWORD}
+
+
+ Personal-snapshots
+ ${env.MAVEN_USERNAME}
+ ${env.MAVEN_PASSWORD}
+
+
+
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 0000000..d904df8
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,47 @@
+name: CI
+
+on:
+ push:
+ branches:
+ - master
+ - 'feature/**'
+ - 'fix/**'
+ - 'hotfix/**'
+ tags-ignore:
+ - 'v*'
+ pull_request:
+ branches:
+ - master
+
+jobs:
+ build:
+ name: Build & Test
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ - name: Set up Temurin 21
+ uses: actions/setup-java@v4
+ with:
+ distribution: temurin
+ java-version: 21
+ cache: maven
+ server-id: Personal
+ server-username: MAVEN_USERNAME
+ server-password: MAVEN_PASSWORD
+
+ - name: Build and test
+ run: mvn -B --settings .github/settings.xml clean verify
+ env:
+ MAVEN_USERNAME: ${{ secrets.MAVEN_USERNAME }}
+ MAVEN_PASSWORD: ${{ secrets.MAVEN_PASSWORD }}
+
+ - name: Publish test results
+ uses: actions/upload-artifact@v4
+ if: always()
+ with:
+ name: test-results
+ path: '**/target/surefire-reports/*.xml'
+ retention-days: 7
diff --git a/.github/workflows/prepare-release.yml b/.github/workflows/prepare-release.yml
new file mode 100644
index 0000000..4c6086c
--- /dev/null
+++ b/.github/workflows/prepare-release.yml
@@ -0,0 +1,69 @@
+name: Prepare Release
+
+on:
+ workflow_dispatch:
+ inputs:
+ version:
+ description: 'Release version (e.g. 2.0.0)'
+ required: true
+ type: string
+ next_version:
+ description: 'Next development version without -SNAPSHOT (e.g. 2.1.0)'
+ required: true
+ type: string
+
+jobs:
+ prepare:
+ name: Bump, Tag & Push
+ runs-on: ubuntu-latest
+ permissions:
+ contents: write
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+ with:
+ token: ${{ secrets.GITHUB_TOKEN }}
+ fetch-depth: 0
+
+ - name: Set up Temurin 21
+ uses: actions/setup-java@v4
+ with:
+ distribution: temurin
+ java-version: 21
+ cache: maven
+
+ - name: Configure Git
+ run: |
+ git config user.name "github-actions[bot]"
+ git config user.email "github-actions[bot]@users.noreply.github.com"
+
+ - name: Set release version
+ run: mvn -B --settings .github/settings.xml versions:set -DnewVersion=${{ inputs.version }}
+ env:
+ MAVEN_USERNAME: ${{ secrets.MAVEN_USERNAME }}
+ MAVEN_PASSWORD: ${{ secrets.MAVEN_PASSWORD }}
+
+ - name: Commit release version
+ run: |
+ git add -A
+ git commit -m "chore(release): ${{ inputs.version }}"
+
+ - name: Tag release
+ run: git tag v${{ inputs.version }}
+
+ - name: Set next snapshot version
+ run: mvn -B --settings .github/settings.xml versions:set -DnewVersion=${{ inputs.next_version }}-SNAPSHOT
+ env:
+ MAVEN_USERNAME: ${{ secrets.MAVEN_USERNAME }}
+ MAVEN_PASSWORD: ${{ secrets.MAVEN_PASSWORD }}
+
+ - name: Commit next snapshot version
+ run: |
+ git add -A
+ git commit -m "chore(release): prepare ${{ inputs.next_version }}-SNAPSHOT"
+
+ - name: Push commits and tag
+ run: |
+ git push origin master
+ git push origin v${{ inputs.version }}
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
new file mode 100644
index 0000000..cbc74bd
--- /dev/null
+++ b/.github/workflows/release.yml
@@ -0,0 +1,136 @@
+name: Release
+
+on:
+ push:
+ tags:
+ - 'v*'
+
+jobs:
+ release:
+ name: Build, Sign, Deploy & Publish
+ runs-on: ubuntu-latest
+ permissions:
+ contents: write
+ pages: write
+ id-token: write
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+
+ - name: Extract version from tag
+ id: version
+ run: echo "VERSION=${GITHUB_REF_NAME#v}" >> $GITHUB_OUTPUT
+
+ - name: Set up Temurin 21
+ uses: actions/setup-java@v4
+ with:
+ distribution: temurin
+ java-version: 21
+ cache: maven
+
+ - name: Import GPG key
+ run: |
+ echo "${{ secrets.GPG_PRIVATE_KEY }}" | gpg --batch --import
+ GPG_KEY_ID=$(gpg --list-secret-keys --with-colons | grep '^sec' | cut -d: -f5 | head -1)
+ echo "GPG_KEY_ID=$GPG_KEY_ID" >> $GITHUB_ENV
+
+ - name: Build, sign and deploy to releases
+ run: |
+ mvn -B --settings .github/settings.xml \
+ -DperformRelease=true \
+ -Dgpg.keyname=$GPG_KEY_ID \
+ clean deploy
+ env:
+ MAVEN_USERNAME: ${{ secrets.MAVEN_USERNAME }}
+ MAVEN_PASSWORD: ${{ secrets.MAVEN_PASSWORD }}
+
+ - name: Generate aggregated JavaDoc
+ run: |
+ mvn -B --settings .github/settings.xml \
+ -pl flash,flash-extensions -am \
+ javadoc:aggregate -DskipTests
+ env:
+ MAVEN_USERNAME: ${{ secrets.MAVEN_USERNAME }}
+ MAVEN_PASSWORD: ${{ secrets.MAVEN_PASSWORD }}
+
+ - name: Checkout gh-pages
+ uses: actions/checkout@v4
+ with:
+ ref: gh-pages
+ path: gh-pages-out
+ token: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Copy JavaDoc to versioned folder
+ run: |
+ VERSION=${{ steps.version.outputs.VERSION }}
+ mkdir -p gh-pages-out/javadoc/$VERSION
+ cp -r target/reports/apidocs/. gh-pages-out/javadoc/$VERSION/
+ rm -rf gh-pages-out/latest
+ mkdir -p gh-pages-out/latest
+ cp -r target/reports/apidocs/. gh-pages-out/latest/
+
+ - name: Regenerate index.html
+ run: |
+ cd gh-pages-out
+ python3 - <<'EOF'
+ import os, re
+
+ versions = sorted(
+ [d for d in os.listdir("javadoc") if os.path.isdir(f"javadoc/{d}")],
+ key=lambda v: [int(x) for x in re.sub(r'[^0-9.]', '', v).split('.') if x],
+ reverse=True
+ )
+
+ rows = "\n".join(
+ f'
{v}'
+ for v in versions
+ )
+
+ html = f"""
+
+
+
+ Flash JavaDoc
+
+
+
+ Flash — JavaDoc
+ → Latest
+ All versions
+
+
+ """
+
+ with open("index.html", "w") as f:
+ f.write(html)
+ print(f"index.html generated with {len(versions)} versions: {versions}")
+ EOF
+
+ - name: Push gh-pages
+ run: |
+ cd gh-pages-out
+ git config user.name "github-actions[bot]"
+ git config user.email "github-actions[bot]@users.noreply.github.com"
+ git add -A
+ git diff --cached --quiet || git commit -m "docs(javadoc): release ${{ steps.version.outputs.VERSION }}"
+ git push origin gh-pages
+
+ - name: Create GitHub Release
+ uses: softprops/action-gh-release@v2
+ with:
+ tag_name: v${{ steps.version.outputs.VERSION }}
+ name: v${{ steps.version.outputs.VERSION }}
+ generate_release_notes: true
+ draft: false
+ prerelease: false
diff --git a/.github/workflows/snapshot.yml b/.github/workflows/snapshot.yml
new file mode 100644
index 0000000..5d1d90c
--- /dev/null
+++ b/.github/workflows/snapshot.yml
@@ -0,0 +1,30 @@
+name: Publish Snapshot
+
+on:
+ push:
+ branches:
+ - master
+ tags-ignore:
+ - 'v*'
+
+jobs:
+ snapshot:
+ name: Deploy Snapshot
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ - name: Set up Temurin 21
+ uses: actions/setup-java@v4
+ with:
+ distribution: temurin
+ java-version: 21
+ cache: maven
+
+ - name: Deploy snapshot
+ run: mvn -B --settings .github/settings.xml clean deploy -DskipTests
+ env:
+ MAVEN_USERNAME: ${{ secrets.MAVEN_USERNAME }}
+ MAVEN_PASSWORD: ${{ secrets.MAVEN_PASSWORD }}
diff --git a/.gitignore b/.gitignore
index 6439a65..67d5b27 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,7 @@
target/
+*.versionsBackup
+.mvn/timing.properties
+*.class
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
diff --git a/AGENTS.md b/AGENTS.md
new file mode 100644
index 0000000..b37c568
--- /dev/null
+++ b/AGENTS.md
@@ -0,0 +1,118 @@
+# Flash — Agent Guidelines
+
+This document defines the conventions and rules that all agents (AI or human) must follow
+when working on this repository. Read it entirely before making any change.
+
+---
+
+## Git Workflow
+
+### Branch Naming
+
+| Type | Pattern | Example |
+|------|---------|---------|
+| New feature | `feature//` | `feature/ext-oidc/pkce-support` |
+| Bug fix | `fix//` | `fix/core/router-npe` |
+| Hotfix on released version | `hotfix//` | `hotfix/2.0.1/auth-bypass` |
+| CI/infra changes | `feature/ci/` | `feature/ci/add-snapshot-workflow` |
+
+Rules:
+- Always branch from `master`.
+- Branch names are lowercase, words separated by `-`.
+- Never push directly to `master`.
+- Never create `develop`, `release/*`, or any other long-lived branch.
+
+### Commit Messages — Conventional Commits
+
+Format: `(): `
+
+| Type | When to use |
+|------|-------------|
+| `feat` | New feature |
+| `fix` | Bug fix |
+| `refactor` | Code change without feature/fix |
+| `test` | Adding or updating tests |
+| `docs` | Documentation only |
+| `chore` | Build, deps, tooling — no production code |
+| `ci` | Changes to GitHub Actions workflows |
+
+Allowed scopes: `core`, `ext-jackson`, `ext-openapi`, `ext-oidc`, `ext-routeviewer`,
+`ext-view-core`, `ext-view-jte`, `ext-view-thymeleaf`, `ext-limiter`, `ext-web-bundler`,
+`ext-data-core`, `ext-data-jdbc`, `ext-data-hibernate`, `release`, `deps`, `ci`.
+
+Examples:
+```
+feat(ext-oidc): add PKCE support
+fix(core): fix NPE in RouteHandler when path is null
+chore(deps): upgrade jackson to 2.18.0
+ci: add timeout to snapshot workflow
+chore(release): 2.1.0
+```
+
+### Pull Requests
+
+- Every branch must be merged via PR, never with a direct push.
+- PR title must follow Conventional Commits format.
+- CI (`ci.yml`) must be green before merging.
+- Squash merge is preferred for `feature/*` and `fix/*` to keep history clean.
+- Merge commit is preferred for hotfixes (preserves the fix commit intact).
+
+---
+
+## Versioning
+
+- All modules share a single version defined in the root `pom.xml` (`flash-parent`).
+- Never change the version in child POMs — always and only in the parent.
+- Current scheme: `MAJOR.MINOR.PATCH`
+ - MAJOR: breaking API changes
+ - MINOR: new backward-compatible features
+ - PATCH: backward-compatible bug fixes on an already-released version
+- During development, master always carries a `-SNAPSHOT` version.
+- **Never manually edit the version** — versions are bumped exclusively by the
+ `prepare-release` GitHub Actions workflow.
+
+### Release Process (for maintainers only)
+
+1. Ensure `master` is green (CI passing).
+2. Go to GitHub Actions → `Prepare Release` → `Run workflow`.
+3. Input `version` (e.g. `2.1.0`) and `next_version` (e.g. `2.2.0`).
+4. The workflow handles everything: bump, commit, tag, push.
+5. The `release` workflow then triggers automatically on the tag.
+
+---
+
+## Maven & Module Structure
+
+- Root POM: `flash-parent` — defines all dependency versions and plugin config.
+- `flash` module: the core framework JAR.
+- `flash-extensions` POM: aggregator for all extension modules.
+- Extensions live under `flash-extensions/flash-ext-*/`.
+- When adding a new extension:
+ 1. Add the module to `flash-extensions/pom.xml` ``.
+ 2. Add the dependency to `flash-extensions/pom.xml` ``.
+ 3. Add the dependency to the root `pom.xml` ``.
+ 4. Do **not** declare a `` in the new module's POM — it inherits from the parent.
+
+---
+
+## CI/CD Pipelines
+
+| Workflow | Trigger | What it does |
+|----------|---------|--------------|
+| `ci.yml` | Push to any branch, PR to master | Compile + test — required gate |
+| `snapshot.yml` | Push to `master` | Deploy `-SNAPSHOT` to `maven.relism.dev/snapshots` |
+| `prepare-release.yml` | Manual `workflow_dispatch` | Bump version, commit, tag, push |
+| `release.yml` | Push of tag `v*` | GPG sign, deploy to `/releases`, JavaDoc to GitHub Pages, GitHub Release |
+
+**Agents must never manually trigger `prepare-release` or modify version strings.**
+
+---
+
+## What Agents Must NOT Do
+
+- Push directly to `master` or `gh-pages`.
+- Manually edit `` tags in any POM.
+- Add new `` or `` entries without explicit instruction.
+- Modify `.github/workflows/*.yml` files without explicit instruction.
+- Commit generated files (`target/`, `*.class`, `*.versionsBackup`).
+- Use `git push --force` on any branch.
diff --git a/flash-extensions/flash-ext-data-core/pom.xml b/flash-extensions/flash-ext-data-core/pom.xml
index 9ffd101..3fa5807 100644
--- a/flash-extensions/flash-ext-data-core/pom.xml
+++ b/flash-extensions/flash-ext-data-core/pom.xml
@@ -7,7 +7,7 @@
dev.relism
flash-extensions
- 1.1-indev6
+ 2.0.0-SNAPSHOT
flash-ext-data-core
diff --git a/flash-extensions/flash-ext-data-hibernate/pom.xml b/flash-extensions/flash-ext-data-hibernate/pom.xml
index 6153e4d..d0389fc 100644
--- a/flash-extensions/flash-ext-data-hibernate/pom.xml
+++ b/flash-extensions/flash-ext-data-hibernate/pom.xml
@@ -7,7 +7,7 @@
dev.relism
flash-extensions
- 1.1-indev6
+ 2.0.0-SNAPSHOT
flash-ext-data-hibernate
diff --git a/flash-extensions/flash-ext-data-jdbc/pom.xml b/flash-extensions/flash-ext-data-jdbc/pom.xml
index 1a32111..796bd5c 100644
--- a/flash-extensions/flash-ext-data-jdbc/pom.xml
+++ b/flash-extensions/flash-ext-data-jdbc/pom.xml
@@ -7,7 +7,7 @@
dev.relism
flash-extensions
- 1.1-indev6
+ 2.0.0-SNAPSHOT
flash-ext-data-jdbc
diff --git a/flash-extensions/flash-ext-jackson/pom.xml b/flash-extensions/flash-ext-jackson/pom.xml
index 0cddcdb..ab5e348 100644
--- a/flash-extensions/flash-ext-jackson/pom.xml
+++ b/flash-extensions/flash-ext-jackson/pom.xml
@@ -7,7 +7,7 @@
dev.relism
flash-extensions
- 1.1-indev6
+ 2.0.0-SNAPSHOT
flash-ext-jackson
diff --git a/flash-extensions/flash-ext-limiter/pom.xml b/flash-extensions/flash-ext-limiter/pom.xml
index 225e10f..23c48cf 100644
--- a/flash-extensions/flash-ext-limiter/pom.xml
+++ b/flash-extensions/flash-ext-limiter/pom.xml
@@ -7,7 +7,7 @@
dev.relism
flash-extensions
- 1.1-indev6
+ 2.0.0-SNAPSHOT
flash-ext-limiter
diff --git a/flash-extensions/flash-ext-oidc/pom.xml b/flash-extensions/flash-ext-oidc/pom.xml
index 97742ab..acbb00b 100644
--- a/flash-extensions/flash-ext-oidc/pom.xml
+++ b/flash-extensions/flash-ext-oidc/pom.xml
@@ -7,7 +7,7 @@
dev.relism
flash-extensions
- 1.1-indev6
+ 2.0.0-SNAPSHOT
flash-ext-oidc
diff --git a/flash-extensions/flash-ext-openapi/pom.xml b/flash-extensions/flash-ext-openapi/pom.xml
index 62c8c15..1c82efa 100644
--- a/flash-extensions/flash-ext-openapi/pom.xml
+++ b/flash-extensions/flash-ext-openapi/pom.xml
@@ -7,7 +7,7 @@
dev.relism
flash-extensions
- 1.1-indev6
+ 2.0.0-SNAPSHOT
flash-ext-openapi
diff --git a/flash-extensions/flash-ext-routeviewer/pom.xml b/flash-extensions/flash-ext-routeviewer/pom.xml
index b1b68d1..36698ad 100644
--- a/flash-extensions/flash-ext-routeviewer/pom.xml
+++ b/flash-extensions/flash-ext-routeviewer/pom.xml
@@ -7,7 +7,7 @@
dev.relism
flash-extensions
- 1.1-indev6
+ 2.0.0-SNAPSHOT
flash-ext-routeviewer
diff --git a/flash-extensions/flash-ext-view-core/pom.xml b/flash-extensions/flash-ext-view-core/pom.xml
index da55ba0..b7ba2ca 100644
--- a/flash-extensions/flash-ext-view-core/pom.xml
+++ b/flash-extensions/flash-ext-view-core/pom.xml
@@ -7,7 +7,7 @@
dev.relism
flash-extensions
- 1.1-indev6
+ 2.0.0-SNAPSHOT
flash-ext-view-core
diff --git a/flash-extensions/flash-ext-view-jte/pom.xml b/flash-extensions/flash-ext-view-jte/pom.xml
index b6c7a0e..1debbab 100644
--- a/flash-extensions/flash-ext-view-jte/pom.xml
+++ b/flash-extensions/flash-ext-view-jte/pom.xml
@@ -7,7 +7,7 @@
dev.relism
flash-extensions
- 1.1-indev6
+ 2.0.0-SNAPSHOT
flash-ext-view-jte
diff --git a/flash-extensions/flash-ext-view-thymeleaf/pom.xml b/flash-extensions/flash-ext-view-thymeleaf/pom.xml
index a12783f..84c2bcc 100644
--- a/flash-extensions/flash-ext-view-thymeleaf/pom.xml
+++ b/flash-extensions/flash-ext-view-thymeleaf/pom.xml
@@ -7,7 +7,7 @@
dev.relism
flash-extensions
- 1.1-indev6
+ 2.0.0-SNAPSHOT
flash-ext-view-thymeleaf
diff --git a/flash-extensions/flash-ext-web-bundler/pom.xml b/flash-extensions/flash-ext-web-bundler/pom.xml
index dcdec5b..113eb8b 100644
--- a/flash-extensions/flash-ext-web-bundler/pom.xml
+++ b/flash-extensions/flash-ext-web-bundler/pom.xml
@@ -7,7 +7,7 @@
dev.relism
flash-extensions
- 1.1-indev6
+ 2.0.0-SNAPSHOT
flash-ext-web-bundler
diff --git a/flash-extensions/pom.xml b/flash-extensions/pom.xml
index c3020fc..5e024ce 100644
--- a/flash-extensions/pom.xml
+++ b/flash-extensions/pom.xml
@@ -7,7 +7,7 @@
dev.relism
flash-parent
- 1.1-indev6
+ 2.0.0-SNAPSHOT
flash-extensions
diff --git a/flash/pom.xml b/flash/pom.xml
index f9e102a..e3cc907 100644
--- a/flash/pom.xml
+++ b/flash/pom.xml
@@ -7,7 +7,7 @@
dev.relism
flash-parent
- 1.1-indev6
+ 2.0.0-SNAPSHOT
flash
diff --git a/pom.xml b/pom.xml
index d88505a..2094dd3 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
dev.relism
flash-parent
- 1.1-indev6
+ 2.0.0-SNAPSHOT
pom
@@ -19,6 +19,10 @@
Personal
https://maven.relism.dev/releases
+
+ Personal-snapshots
+ https://maven.relism.dev/snapshots
+
@@ -27,6 +31,10 @@
UTF-8
1.18.44
2.0.16
+ 3.11.2
+ 3.3.1
+ 3.2.8
+ 2.18.0
@@ -141,8 +149,109 @@
+
+ org.apache.maven.plugins
+ maven-source-plugin
+ ${maven.source.plugin.version}
+
+
+ org.apache.maven.plugins
+ maven-javadoc-plugin
+ ${maven.javadoc.plugin.version}
+
+ ${maven.compiler.source}
+ ${project.build.sourceEncoding}
+ none
+ true
+
+
+
+ org.apache.maven.plugins
+ maven-gpg-plugin
+ ${maven.gpg.plugin.version}
+
+
+ org.codehaus.mojo
+ versions-maven-plugin
+ ${maven.versions.plugin.version}
+
+ false
+
+
+
+ org.apache.maven.plugins
+ maven-deploy-plugin
+ 3.1.2
+
+
+
+ attach-artifacts
+
+
+ src/main/java
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-source-plugin
+
+
+ attach-sources
+ verify
+
+ jar-no-fork
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-javadoc-plugin
+
+
+ attach-javadocs
+ verify
+
+ jar
+
+
+
+
+
+
+
+
+ sign-artifacts
+
+
+ performRelease
+ true
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-gpg-plugin
+
+
+ sign-artifacts
+ verify
+
+ sign
+
+
+
+
+
+
+
+
+