Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
162 commits
Select commit Hold shift + click to select a range
5853ffd
Flyway-style migrations: one engine for the app database and the backend
shai-almog Oct 6, 2026
f64bdc3
Compile migration scripts into the build
shai-almog Oct 6, 2026
948cf02
Migration goals, an on-device migration test, and the guide chapters
shai-almog Oct 6, 2026
9f66e47
Backend migrations: for-each loops and a preserved cause
shai-almog Oct 6, 2026
128d323
Backend: a slot for a security layer in the request path, and @Order
shai-almog Oct 6, 2026
6af16e0
Backend: a security layer in the shape of Spring Security
shai-almog Oct 6, 2026
f786c91
Build: link the security layer for a chain bean, and bind who is sign…
shai-almog Oct 6, 2026
a8358b4
Backend tests: run as a user, and send a CSRF token or credentials
shai-almog Oct 6, 2026
013c59d
Migrations: the same history on the translated runtime and the JVM
shai-almog Oct 6, 2026
f23f731
Backend crypto: signatures, HMAC and PBKDF2 over any digest, AES-GCM
shai-almog Oct 6, 2026
3d0797c
Backend: keys in PEM and JWK, signed tokens, and JWTs under public ke…
shai-almog Oct 6, 2026
e79fffa
Backend security: a JWT resource server
shai-almog Oct 6, 2026
df41aff
Backend security: API keys
shai-almog Oct 6, 2026
7746acc
Backend API reference: a server's own description of a package it sha…
shai-almog Oct 6, 2026
f6e501a
Backend: where a request came from, rate limits, and a bound on passw…
shai-almog Oct 6, 2026
d599ebb
JWT claim validator: hand the test an Object, and compare the limiter…
shai-almog Oct 6, 2026
1c1478b
Backend security: method security, compiled at build time
shai-almog Oct 6, 2026
513baee
Backend security: a server links the security it declares, and no other
shai-almog Oct 6, 2026
0acc604
Backend: a refused WebSocket handshake is answered with its headers
shai-almog Oct 6, 2026
7e65e14
Backend security: remember-me, and one way of signing in to a session
shai-almog Oct 6, 2026
2f6827d
Backend security: a second factor at sign-in
shai-almog Oct 6, 2026
580ff1c
Backend security: a schema of its own, and stores in the database
shai-almog Oct 6, 2026
26d6f09
Backend tests: a request with an accepted token or API key
shai-almog Oct 6, 2026
a592d1d
Backend security: keep the session sign-in out of a server that has none
shai-almog Oct 6, 2026
f02a235
Backend build: leave out of the binary the natives nothing calls
shai-almog Oct 6, 2026
cc39ad3
Backend security: sign-in through another provider, with OAuth2 and O…
shai-almog Oct 6, 2026
6a338ef
Backend security: an authorization server, with refresh tokens and th…
shai-almog Oct 6, 2026
ea0e40b
Backend linking: a server that signs in elsewhere, and one that issue…
shai-almog Oct 6, 2026
7fd36bb
Authorization server: a device is approved only from the question put…
shai-almog Oct 6, 2026
1652c88
Authorization server docs: what a method throws, before its parameters
shai-almog Oct 6, 2026
af7086d
Backend Checkstyle: verify fails on an error, and the seven that were…
shai-almog Oct 6, 2026
a18f64c
Backend docs: a reference in AsyncTask that resolved nowhere, and pac…
shai-almog Oct 6, 2026
7cacc7d
OAuth2 login: hold an answer to its issuer, and an ID token to its ac…
shai-almog Oct 6, 2026
108fa54
Account linking: GitHub's verified address comes from its list of them
shai-almog Oct 6, 2026
45fc61f
Backend security: the session keeps the kind of sign-in, through code…
shai-almog Oct 6, 2026
ca3cb45
Backend passkeys: a CBOR reader for what an authenticator sends, and …
shai-almog Oct 6, 2026
4947889
Backend passkeys: the registration and sign-in ceremonies
shai-almog Oct 6, 2026
38757d0
Backend passkeys: handles and credentials in the database
shai-almog Oct 6, 2026
10b5a59
Backend security: http.webAuthn(), with the endpoints of the two cere…
shai-almog Oct 6, 2026
9035828
Backend PMD: thirteen findings of rules PR CI forbids, left by the se…
shai-almog Oct 6, 2026
0e2ea3e
Backend passkeys: what the Checkstyle and PMD gates said of them
shai-almog Oct 6, 2026
14a7d2e
Backend linking: a server that signs in with passkeys, and nobody els…
shai-almog Oct 6, 2026
6459951
CLAUDE.md: which of the backend's three gates a local build enforces
shai-almog Oct 6, 2026
ae3e753
CLAUDE.md: the PMD report held fifteen findings, not thirteen
shai-almog Oct 6, 2026
8e03ae0
OIDC client: a token store in secure storage, and two ways the plain …
shai-almog Oct 6, 2026
3951f35
Requests that carry a token and renew it on a 401, and the device gra…
shai-almog Oct 6, 2026
dbd9a13
Developer guide: a chapter on backend security
shai-almog Oct 6, 2026
6014a73
Developer guide: signing an app in against a Codename One backend
shai-almog Oct 6, 2026
3026d01
Migrations: a server with scripts could not be translated
shai-almog Oct 6, 2026
b963e2b
Device grant: an answer with no session was a 500, and three comments…
shai-almog Oct 6, 2026
934d0ee
The CI test server signs users in, issues tokens and guards an API
shai-almog Oct 6, 2026
84b8bdf
Device tests: sign in to the backend, call what it guards, and have a…
shai-almog Oct 6, 2026
7e94191
Backend security: the path check belongs to the chain that claims the…
shai-almog Oct 6, 2026
d62b279
Backend security: a second factor holds for every way of presenting a…
shai-almog Oct 6, 2026
2c0dfb1
Authorization server: an access token's audience is the resource server
shai-almog Oct 6, 2026
8ecaab7
Authorization server: a secret nothing can check stops the start
shai-almog Oct 6, 2026
0b64bce
OAuth2 login: Sign in with Apple in the configuration stops the start
shai-almog Oct 6, 2026
6f16015
Backend: cn1.security.schema.enabled at run time no longer does nothing
shai-almog Oct 6, 2026
734e0dc
Backend security: the two built-in limiters are configured, and can b…
shai-almog Oct 6, 2026
7b25564
Device grant: the verification endpoint answers in JSON too
shai-almog Oct 6, 2026
732657b
Backend: reason phrases, the scope a bearer challenge can name, and a…
shai-almog Oct 6, 2026
dc52dbc
Migrations: a module that drops its last script loses the compiled ones
shai-almog Oct 6, 2026
d8652f2
Migrate goals: a module that asked for the security tables gets them
shai-almog Oct 6, 2026
0d93f66
The CI test server: an audience and an issuer on its tokens, and the …
shai-almog Oct 6, 2026
fd9398f
NetworkManager.setAuthorizer: base URLs are compared as origins
shai-almog Oct 6, 2026
852702f
OIDC authorizer: renew a token before it expires, not after it is ref…
shai-almog Oct 6, 2026
7459a0a
OIDC client: the issuer of a response and the signature of an ID token
shai-almog Oct 6, 2026
5584dfe
Backend gates: a clock set outside its lock, and three names spelled …
shai-almog Oct 6, 2026
7aa6d35
Developer guide: the built-in counters are per process only until a l…
shai-almog Oct 6, 2026
02262d1
Request authorizers: their state belongs to the EDT, and nothing is l…
shai-almog Oct 6, 2026
92978b1
Backend: every key the build links by is refused at run time the same…
shai-almog Oct 6, 2026
148422b
Migrate goals: a module with only a library's set gets them, and nine…
shai-almog Oct 6, 2026
3851e3e
Backend security: two RateLimiter beans are chosen between or refused…
shai-almog Oct 6, 2026
cd1c64f
Second factor: one address that has the password cannot keep the user…
shai-almog Oct 6, 2026
8a5054c
NetworkManager.addToQueue: no path that hands a known null on
shai-almog Oct 6, 2026
d7c3bbd
Build-time settings: a key that names an unset variable asks for nothing
shai-almog Oct 6, 2026
095f2fe
Port status: the new device tests have features; the compiled sample …
shai-almog Oct 7, 2026
99ddf9e
Gradle migration tasks launch the class that has the main
shai-almog Oct 7, 2026
6863b55
Migrations: repeatables are rechecked under the lock and held to by v…
shai-almog Oct 7, 2026
1b4e4b2
OIDC client: what a response is checked for before it is believed or …
shai-almog Oct 7, 2026
e720952
Backend security: user info is for tokens made for this server; confi…
shai-almog Oct 7, 2026
3285ef0
OidcCoreTest carries the standard header
shai-almog Oct 7, 2026
319394f
JavaScript port: a rethrow out of a JSR finally is not caught by its …
shai-almog Oct 7, 2026
00b763b
ConnectionRequest: a POST's arguments are flushed into the request
shai-almog Oct 7, 2026
fc8920a
OIDC client: an ID token names its subject; a biometric store is sign…
shai-almog Oct 7, 2026
5b28163
Backend: long rate-limit keys keep apart; SQLite scripts outside a tr…
shai-almog Oct 7, 2026
28b286b
Website search index: written in parts, because one file of every pag…
shai-almog Oct 7, 2026
4855b1b
Merge remote-tracking branch 'origin/master' into backend-security-an…
shai-almog Oct 7, 2026
5700f85
Wait for beacon request startup in timeout test
shai-almog Oct 7, 2026
4bccf5f
Reject OIDC discovery metadata from a different issuer
shai-almog Oct 7, 2026
c8cc6c9
Restore background queuing when requests need no authorizer
shai-almog Oct 7, 2026
d2b9198
Close token lifecycle and server security review gaps
shai-almog Oct 7, 2026
18b4b7c
Satisfy PMD checks for authorization fixes
shai-almog Oct 7, 2026
4bd535d
Report token revocation failures and correct API documentation
shai-almog Oct 7, 2026
564f425
Use clearer client wording in reauthentication guide
shai-almog Oct 7, 2026
d1bbe91
Validate applied migration description drift
shai-almog Oct 7, 2026
636886f
Normalize URL paths before applying authorization scope
shai-almog Oct 7, 2026
66e2d25
Bind OIDC tokens to the expected issuer client and subject
shai-almog Oct 7, 2026
7ec8e28
Extend reused refresh tokens and their grants from last use
shai-almog Oct 7, 2026
53c65d1
Retain active rate-limit windows during database cleanup
shai-almog Oct 7, 2026
91bbd2f
Reject ambiguous authentication beans and honor primary selection
shai-almog Oct 7, 2026
fd0c190
Serialize token persistence so sign-out cannot be undone by a delayed…
shai-almog Oct 7, 2026
d720c4d
Publish authorizer registration to background network callers
shai-almog Oct 7, 2026
ed3b7e9
Reject migration descriptions that exceed history storage
shai-almog Oct 7, 2026
8869e4a
Carry path variables through combined request matchers
shai-almog Oct 7, 2026
b416fc9
Delete durable credentials transactionally with their user
shai-almog Oct 7, 2026
aa6544f
Document stock Java 8 PS256 support and its regression coverage
shai-almog Oct 7, 2026
33bd7a8
Avoid pipefail false negatives in the screenshot server startup probe
shai-almog Oct 7, 2026
dfb66ad
Preserve identity when corrupting the device test access token
shai-almog Oct 7, 2026
8122f8c
Preserve OIDC sessions on transient and protocol refresh failures
shai-almog Oct 7, 2026
8aaf5a6
Normalize mapped IPv4 peers before trusted proxy checks
shai-almog Oct 7, 2026
2560020
Reject unsafe browser targets in saved request redirects
shai-almog Oct 7, 2026
829d869
Count device user code lookups without charging ticket approvals
shai-almog Oct 7, 2026
a068eaa
Allow bounded concurrent remember-me rotation across shared stores
shai-almog Oct 7, 2026
3c8255f
Reject mixed public and secret client authentication
shai-almog Oct 7, 2026
78de7e2
Revoke remember-me series withdrawn by later authentication checks
shai-almog Oct 7, 2026
b89b1fe
Separate access-token algorithm defaults from OIDC ID-token metadata
shai-almog Oct 7, 2026
285579e
Bound migration versions to the history schema
shai-almog Oct 7, 2026
35280d4
Require a finite representable device authorization expiry
shai-almog Oct 7, 2026
c07a801
Observe playground animation within a bounded rendering window
shai-almog Oct 7, 2026
e5c330b
Preserve customized OAuth login scopes when the provider omits scope
shai-almog Oct 7, 2026
20222fb
Reject missing and unsupported OIDC token types before persistence
shai-almog Oct 7, 2026
20dd3ae
Reject scope delimiters that change registered clients after storage
shai-almog Oct 7, 2026
71b264a
Return security and session cookies with WebSocket upgrade responses
shai-almog Oct 7, 2026
29e9dae
Resume GPU animation when a detached preview is attached
shai-almog Oct 7, 2026
f67b0a0
Preserve VM crash traces and Windows suite debug symbols
shai-almog Oct 7, 2026
26a648b
Merge remote-tracking branch 'origin/master' into backend-security-an…
shai-almog Oct 7, 2026
212ca55
Require session authentication when managing passkeys
shai-almog Oct 7, 2026
bcd2091
Validate device polling intervals before scheduling timers
shai-almog Oct 7, 2026
0c391f2
Reject mismatched private and public signing keys
shai-almog Oct 7, 2026
41a2902
Record Java migrations with the Flyway JDBC history type
shai-almog Oct 7, 2026
bb10b8a
Store recovery codes as salted password hashes
shai-almog Oct 7, 2026
ecb8015
Wait for delayed GPU attachment before measuring animation
shai-almog Oct 7, 2026
20dc127
Align recovery-code documentation with the prose checks
shai-almog Oct 7, 2026
76939d2
Require session authentication for user authorization grants
shai-almog Oct 7, 2026
2001cb7
Use Object vtable slots for inherited interface dispatch
shai-almog Oct 7, 2026
5b3eda0
Give presented browser scenes a bounded animation window
shai-almog Oct 7, 2026
87abf97
Expect Flyway JDBC type in generated migration tests
shai-almog Oct 7, 2026
460cc6e
Include native method names in image benchmark failures
shai-almog Oct 7, 2026
fefae93
Use signed-in sessions in sample authorization flows
shai-almog Oct 7, 2026
6460fab
Add required copyright header to native image benchmark
shai-almog Oct 7, 2026
12687a3
Require ID token issuance time and exact non-Google issuers
shai-almog Oct 7, 2026
2560dde
Supersede pending token loads when client credentials change
shai-almog Oct 7, 2026
f33dc01
Make token issuance atomic with revocation and omit incomplete scopes
shai-almog Oct 7, 2026
8dec19b
Compile identity bridges for watchOS without iOS presentation APIs
shai-almog Oct 7, 2026
48b77df
Validate OAuth token types, redirect URIs, and credential transport
shai-almog Oct 7, 2026
21ef0a7
Exercise OAuth form transport on the compiled backend
shai-almog Oct 7, 2026
b9ab144
Make Playground harness host setup synchronous on the EDT
shai-almog Oct 7, 2026
7821269
Complete cancelled requests while proactive authorization is pending
shai-almog Oct 7, 2026
fbfd81c
Bind CSRF cookies to sessions and make device authorization updates safe
shai-almog Oct 7, 2026
c37ab61
Reject invalid client policy and terminate unusable OAuth sessions
shai-almog Oct 7, 2026
1a2abc8
Retain compiler diagnostics for failing ablation configurations
shai-almog Oct 7, 2026
f0a0b72
Preserve animation frames arriving during suspended Java callbacks
shai-almog Oct 7, 2026
e0830a6
Calibrate Xeon 8370C allocation timing from matching hosted runs
shai-almog Oct 7, 2026
fd57908
Lock browser CI dependencies to the validated Playwright release
shai-almog Oct 7, 2026
ac3403e
Calibrate macOS allocation memory from unchanged runtime controls
shai-almog Oct 7, 2026
352d27f
Bind TOTP and JWKS verification and harden migration cleanup
shai-almog Oct 8, 2026
af9c21e
Allow full VM tests and bounded benchmarks to finish in CI
shai-almog Oct 8, 2026
8422562
Harden migration startup and security token validation
shai-almog Oct 8, 2026
553569f
Bind OAuth state cookies to the host and honor default header casing
shai-almog Oct 8, 2026
56b4ce6
Exercise explicit proxy trust in backend security parity tests
shai-almog Oct 8, 2026
06de6f1
Allow iOS notification CI time for setup and bounded tests
shai-almog Oct 8, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
17 changes: 15 additions & 2 deletions .github/scripts/build_javadocs.sh
Original file line number Diff line number Diff line change
Expand Up @@ -145,8 +145,9 @@ fi
# declare nothing outside java.*, so the JDK resolves them here as it does the
# rest.
#
# The shared classes keep their package-info.java, so a shared package has the
# same description in both references. SharedWithBackend itself and the rest of
# The shared classes keep their package-info.java, so a package shared whole has
# the same description in both references; one shared in part is described for
# the server in vm/backend/package-docs (see where it is staged, below). SharedWithBackend itself and the rest of
# com.codename1.impl are staged for symbol resolution and filtered out of the
# documented set, exactly as for the client API above.
BACKEND_DIR="$ROOT_DIR/vm/backend"
Expand All @@ -162,6 +163,18 @@ cp -r "$BACKEND_DIR/impl/parparvm/." "$BACKEND_STAGE/"
# document.
cp -r "$BACKEND_DIR/test/src/." "$BACKEND_STAGE/"
cp -r "$BACKEND_DIR/test/parparvm/." "$BACKEND_STAGE/"
# A package the backend shares only PART of cannot take the core's description:
# that one names every class of the package, and the ones a server does not have
# are references this run cannot resolve -- which doclint fails, and which the
# website's doclet would otherwise print as plain text where a link was meant.
# vm/backend/package-docs holds the server's own description of such a package
# (com.codename1.security: the digests and one-time passwords, without the
# client's ciphers and key storage). Staged before the loop below, whose
# "unless one is already there" then leaves it in place. It cannot live in
# vm/backend/src: shared-sources.sh refuses any file there that has a core twin.
if [ -d "$BACKEND_DIR/package-docs" ]; then
cp -r "$BACKEND_DIR/package-docs/." "$BACKEND_STAGE/"
fi
while IFS= read -r shared; do
rel="${shared#"$CN1_DIR/src/"}"
mkdir -p "$BACKEND_STAGE/$(dirname "$rel")"
Expand Down
3 changes: 1 addition & 2 deletions .github/workflows/blog-prose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -135,8 +135,7 @@ jobs:
run: |
set -euo pipefail
cd scripts
npm init -y 2>/dev/null || true
npm install playwright
npm ci
# Playwright shells out to apt for the OS-level deps, so the runner
# image's third-party sources have to be pruned FIRST -- a broken
# vendor mirror makes its apt-get fail as a whole and it reports
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/cn1playground-language.yml
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ jobs:
run: |
set -euo pipefail
cd scripts
npm install playwright
npm ci
bash "$GITHUB_WORKSPACE/scripts/ci/apt-get-update.sh"
npx playwright install-deps chromium firefox
npx playwright install chromium firefox
Expand Down
83 changes: 44 additions & 39 deletions .github/workflows/identity-stack.yml
Original file line number Diff line number Diff line change
Expand Up @@ -294,11 +294,6 @@ jobs:
run: |
set -euo pipefail
cd Ports/iOSPort/nativeSources
SDK="$(xcrun --show-sdk-path --sdk iphoneos)"
if [ ! -d "$SDK" ]; then
echo "::error::No iPhoneOS SDK available on this runner"
exit 1
fi
# The .m files include "xmlvm.h" and use ParparVM's CN1_THREAD_*
# macros. Those live in the ParparVM build pipeline, not in this
# checkout, so we stage a minimal shim header that defines the
Expand Down Expand Up @@ -328,38 +323,48 @@ jobs:
#define CN1_THREAD_GET_STATE_PASS_ARG threadStateData,
#define CN1_THREAD_GET_STATE_PASS_SINGLE_ARG threadStateData
EOF
# Exercise BOTH configurations -- the "stubs" path (apps that
# don't reference com.codename1.io.oidc / AppleSignIn) and the
# "full" path (apps that do). IPhoneBuilder flips the macros on
# via the classpath scanner; we want either to keep building.
for label in stubs full; do
extra=""
if [ "$label" = full ]; then
extra="-DCN1_INCLUDE_OIDC -DCN1_INCLUDE_APPLESIGNIN -DCN1_INCLUDE_WEBAUTHN"
fi
echo "::group::clang $label"
# -fmodules because the port's Metal sources use @import, and the
# real build compiles with CLANG_ENABLE_MODULES=YES. The renderer
# header used to be unreachable here -- CN1_USE_METAL was a
# commented-out define the builder uncommented -- so a lint with
# modules off never saw the @import. Metal is the only renderer
# now and the define is unconditional, so this lint has to compile
# the way the product does or it fails on syntax the product
# accepts.
xcrun --sdk iphoneos clang \
-fsyntax-only \
-fmodules \
-fmodules-cache-path="$STUB/modulecache" \
-arch arm64 \
-fobjc-arc \
-Werror=incompatible-pointer-types \
-Werror=objc-method-access \
-Wno-unused-parameter \
-I"$STUB" \
-DNEW_CODENAME_ONE_VM=1 \
$extra \
CN1OidcBrowser.m \
CN1AppleSignIn.m \
CN1WebAuthn.m
echo "::endgroup::"
# Identity sources are copied into the watch companion too. Compile
# the actual SDK variants so unavailable presentation APIs fail here.
for sdk in iphoneos watchos; do
SDK="$(xcrun --show-sdk-path --sdk "$sdk")"
case "$sdk" in
iphoneos) target=arm64-apple-ios12.0 ;;
watchos) target=arm64_32-apple-watchos6.2 ;;
esac
# Exercise BOTH configurations -- the "stubs" path (apps that
# don't reference com.codename1.io.oidc / AppleSignIn) and the
# "full" path (apps that do). IPhoneBuilder flips the macros on
# via the classpath scanner; we want either to keep building.
for label in stubs full; do
extra=""
if [ "$label" = full ]; then
extra="-DCN1_INCLUDE_OIDC -DCN1_INCLUDE_APPLESIGNIN -DCN1_INCLUDE_WEBAUTHN"
fi
echo "::group::clang $sdk $label"
# -fmodules because the port's Metal sources use @import, and the
# real build compiles with CLANG_ENABLE_MODULES=YES. The renderer
# header used to be unreachable here -- CN1_USE_METAL was a
# commented-out define the builder uncommented -- so a lint with
# modules off never saw the @import. Metal is the only renderer
# now and the define is unconditional, so this lint has to compile
# the way the product does or it fails on syntax the product
# accepts.
xcrun --sdk "$sdk" clang \
-fsyntax-only \
-fmodules \
-fmodules-cache-path="$STUB/modulecache" \
-target "$target" \
-isysroot "$SDK" \
-fobjc-arc \
-Werror=incompatible-pointer-types \
-Werror=objc-method-access \
-Wno-unused-parameter \
-I"$STUB" \
-DNEW_CODENAME_ONE_VM=1 \
$extra \
CN1OidcBrowser.m \
CN1AppleSignIn.m \
CN1WebAuthn.m
echo "::endgroup::"
done
done
1 change: 1 addition & 0 deletions .github/workflows/javadocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ on:
- 'vm/backend/src/**/*.java'
- 'vm/backend/impl/**/*.java'
- 'vm/backend/shared-sources.sh'
- 'vm/backend/package-docs/**'
- 'maven/**/src/main/java/**/*.java'
- '.github/scripts/build_javadocs.sh'
- 'scripts/check-package-info.sh'
Expand Down
29 changes: 28 additions & 1 deletion .github/workflows/parparvm-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,14 @@ on:
- 'CodenameOne/src/com/codename1/annotations/JsonIgnore.java'
- 'CodenameOne/src/com/codename1/annotations/JsonProperty.java'
- 'CodenameOne/src/com/codename1/io/gzip/**'
- 'CodenameOne/src/com/codename1/migration/**'
- 'CodenameOne/src/com/codename1/impl/migration/**'
- 'CodenameOne/src/com/codename1/security/Hash.java'
- 'CodenameOne/src/com/codename1/security/Hmac.java'
- 'CodenameOne/src/com/codename1/security/MessageDigestImpl.java'
- 'CodenameOne/src/com/codename1/security/Otp.java'
- 'CodenameOne/src/com/codename1/security/Base32.java'
- 'CodenameOne/src/com/codename1/security/CryptoException.java'
- '!vm/**/README.md'
- '!vm/**/readme.md'
- '!vm/**/docs/**'
Expand Down Expand Up @@ -85,6 +93,14 @@ on:
- 'CodenameOne/src/com/codename1/annotations/JsonIgnore.java'
- 'CodenameOne/src/com/codename1/annotations/JsonProperty.java'
- 'CodenameOne/src/com/codename1/io/gzip/**'
- 'CodenameOne/src/com/codename1/migration/**'
- 'CodenameOne/src/com/codename1/impl/migration/**'
- 'CodenameOne/src/com/codename1/security/Hash.java'
- 'CodenameOne/src/com/codename1/security/Hmac.java'
- 'CodenameOne/src/com/codename1/security/MessageDigestImpl.java'
- 'CodenameOne/src/com/codename1/security/Otp.java'
- 'CodenameOne/src/com/codename1/security/Base32.java'
- 'CodenameOne/src/com/codename1/security/CryptoException.java'
- '!vm/**/README.md'
- '!vm/**/readme.md'
- '!vm/**/docs/**'
Expand Down Expand Up @@ -148,10 +164,21 @@ jobs:
run: vm/benchmarks/check-ablation-arms.sh
env:
CN1_ABLATION_CFLAGS: -O1
- name: Preserve ablation failure logs
if: failure()
uses: actions/upload-artifact@v7
with:
name: ablation-failure-logs
path: |
vm/benchmarks/target/ablation/*.log
vm/benchmarks/target/ablation/*.run
if-no-files-found: warn

vm-tests:
runs-on: ubuntu-24.04
timeout-minutes: 90
# The full suite takes about an hour before the bounded GC benchmark arms.
# Leave time for both; each benchmark workload retains its own timeout.
timeout-minutes: 120
# The two database engines the backend speaks a wire protocol to.
#
# BackendDatabaseTest and BackendOrmTest run one body of assertions against
Expand Down
3 changes: 1 addition & 2 deletions .github/workflows/port-status-nightly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,7 @@ jobs:
- name: Install Playwright browser
working-directory: scripts
run: |
npm init -y 2>/dev/null || true
npm install playwright
npm ci
# Playwright shells out to apt for the OS-level deps, so the runner
# image's third-party sources have to be pruned FIRST -- a broken
# vendor mirror makes its apt-get fail as a whole and it reports
Expand Down
4 changes: 4 additions & 0 deletions .github/workflows/scripts-android.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ name: Test Android build scripts
# transport.
- 'scripts/hellocodenameone/backend/**'
- 'scripts/lib/cn1ss.sh'
- 'scripts/ci/tests/cn1ss-selfcheck-test.sh'
push:
branches:
- master
Expand Down Expand Up @@ -98,6 +99,7 @@ name: Test Android build scripts
# transport.
- 'scripts/hellocodenameone/backend/**'
- 'scripts/lib/cn1ss.sh'
- 'scripts/ci/tests/cn1ss-selfcheck-test.sh'

# The token in secrets.CN1SS_GH_TOKEN was generated on
# Oct 16th 2025. If in Oct 2026 builds start failing, it
Expand Down Expand Up @@ -155,6 +157,8 @@ jobs:
CN1SS_FAIL_ON_TEST_PROBLEMS: '1'
steps:
- uses: actions/checkout@v6
- name: Test screenshot server startup probe
run: bash scripts/ci/tests/cn1ss-selfcheck-test.sh
- name: Set TMPDIR
run: echo "TMPDIR=${{ runner.temp }}" >> $GITHUB_ENV
- name: Free Disk Space
Expand Down
5 changes: 4 additions & 1 deletion .github/workflows/scripts-ios-native.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,10 @@ jobs:
permissions:
contents: read
runs-on: macos-15
timeout-minutes: 45
# Allow setup plus the separately bounded 30-minute generation and 45-minute
# XCTest build/run steps. A 45-minute job cap canceled a progressing native
# build after only 34 minutes of the XCTest step in run 37728629000.
timeout-minutes: 90
steps:
- uses: actions/checkout@v6

Expand Down
16 changes: 5 additions & 11 deletions .github/workflows/scripts-javascript.yml
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ jobs:
uses: actions/cache@v5
with:
path: scripts/node_modules
key: ${{ runner.os }}-scripts-npm-playwright-v1
key: ${{ runner.os }}-scripts-npm-${{ hashFiles('scripts/package-lock.json') }}
restore-keys: |
${{ runner.os }}-scripts-npm-

Expand All @@ -233,29 +233,23 @@ jobs:
uses: actions/cache@v5
with:
path: ~/.cache/ms-playwright
key: ${{ runner.os }}-playwright-chromium-firefox-v1
key: ${{ runner.os }}-playwright-chromium-firefox-${{ hashFiles('scripts/package-lock.json') }}
restore-keys: |
${{ runner.os }}-playwright-

- name: Install Playwright Chromium
run: |
cd scripts
npm init -y 2>/dev/null || true
npm install playwright
npm ci
# OS-level deps (apt packages) aren't cached so always install them.
# Playwright shells out to apt for the OS-level deps, so the runner
# image's third-party sources have to be pruned FIRST -- a broken
# vendor mirror makes its apt-get fail as a whole and it reports
# only "Failed to install browser dependencies".
bash "$GITHUB_WORKSPACE/scripts/ci/apt-get-update.sh"
npx playwright install-deps chromium firefox
# `npm install playwright` resolves the floating version, so the
# cached browser binary can drift away from what the freshly
# installed Playwright expects (the cache only stores the binary).
# `install chromium` is a no-op when the versions match and
# re-downloads the right build when they don't, so it makes the
# job resilient to Playwright revving its bundled chromium build
# in between cache writes.
# Install the browser revisions selected by the committed lockfile;
# a restored fallback cache may contain a different revision.
npx playwright install chromium
# Firefox for the composited rendering check below: issue #5910 was reported
# from Firefox, and the two engines composite the canvas and the text layer
Expand Down
4 changes: 3 additions & 1 deletion .github/workflows/website-docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ on:
- 'vm/backend/src/**'
- 'vm/backend/impl/**'
- 'vm/backend/shared-sources.sh'
- 'vm/backend/package-docs/**'
# build.sh renders the Port Status JDK 25 table with this script's `summary`, so a
# change to its output shape must go through the Hugo build and validate_port_status.
# The baseline DATA (vm/selfhost/perf-baseline/**) is left out on purpose: a row
Expand Down Expand Up @@ -83,6 +84,7 @@ on:
- 'vm/backend/src/**'
- 'vm/backend/impl/**'
- 'vm/backend/shared-sources.sh'
- 'vm/backend/package-docs/**'
# As above: the JDK 25 table's renderer.
- 'vm/selfhost/perf_baseline.py'
- '.github/workflows/website-docs.yml'
Expand Down Expand Up @@ -363,7 +365,7 @@ jobs:
run: |
set -euo pipefail
cd scripts
npm install playwright
npm ci
bash "$GITHUB_WORKSPACE/scripts/ci/apt-get-update.sh"
npx playwright install-deps chromium firefox
npx playwright install chromium firefox
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,8 @@ dependency-reduced-pom.xml
/.playwright-cli
package-lock.json
package.json
!/scripts/package.json
!/scripts/package-lock.json
.claude/

# Local screenshot/perf bench output
Expand Down
41 changes: 40 additions & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -375,7 +375,13 @@ The backend is held to the client's gates:
`package-info.java` per package; no since markers.
- SpotBugs (zero findings, `maven/backend/spotbugs-exclude.xml`), PMD (the core's
forbidden list) and Checkstyle (zero errors) run in `maven/backend`'s `verify`,
using the core's own `pmd.xml` and `checkstyle.xml`.
using the core's own `pmd.xml` and `checkstyle.xml`. Only two of the three
fail a local build: SpotBugs, and Checkstyle through its `check` execution
(`checkstyle-zero-errors`). **PMD writes `maven/backend/target/pmd.xml` and
judges nothing** -- its forbidden list lives in
`.github/scripts/generate-quality-report.py`, which PR CI runs afterwards. A
green `mvn verify` therefore says nothing about PMD: read the report. Both
reports once sat at seven and fifteen findings behind green local builds.
- Error Prone's `BanClassForName`, because ParparVM translates the backend too.
- `maven/backend` compiles only the `impl/javase` twins, so the production
`impl/parparvm` tree gets its own analysis-only module, `maven/backend-parparvm`
Expand All @@ -391,6 +397,39 @@ The backend is held to the client's gates:
`DM_CONVERT_CASE` is deliberately not excluded for the backend, as it is for the
core: a server folds protocol tokens, and the next section is why that matters.

#### A package shared only in part: `vm/backend/package-docs`

A core package of which the backend takes only SOME classes cannot be described
by the core's `package-info.java`. That file links every class of the package,
and the ones a server does not have are references the backend run cannot
resolve: doclint fails on them, and the website's doclet would print each as
plain text where a link was meant. `com.codename1.security` is the case that
exists -- the server shares the digests and the one-time passwords, not the
client's ciphers and key storage.

`vm/backend/package-docs/<package path>/package-info.java` is the server's own
description of such a package. `build_javadocs.sh` copies that tree into the
backend staging directory *before* it copies the shared classes, and the loop
that follows takes a core `package-info.java` only for a package that has none
yet, so the server's one stays. The website build renders the same staging
directory, so it needs nothing of its own.

- It cannot live in `vm/backend/src`: `shared-sources.sh` and
`maven/backend/pom.xml` fail the build on any file there with the same package
and name as a core source, and a `package-info.java` cannot be marked
`@SharedWithBackend` either.
- It is documentation only. No build compiles it, so nothing but the javadoc
run tells you it is wrong: after touching one, run the backend half of
`build_javadocs.sh` under a JDK 25 `javadoc`.
- A package the backend shares WHOLE needs no entry -- the core's description is
true of it and is taken as it is.
- The directory is in the `paths` of `javadocs.yml` and `website-docs.yml`; a
new tree beside it would need adding there.

`com.codename1.impl.*` is on the source path of that run but not among the
documented sources, so doclint never reads its comments: a broken reference in
an internal class passes the gate. Write those references fully qualified.

### No `@author`, `@version` or `@since` in documentation

All three are banned, each by its own gate. `@since` (and "#### Since" sections)
Expand Down
Loading