Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 27 additions & 51 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,29 +8,14 @@ on:
branches:
- main
workflow_dispatch:
inputs:
hardware_passkey_smoke_confirmed:
description: Firefox and Safari hardware smoke, including a second passkey and session revocation, completed successfully
required: true
type: boolean
default: false
hardware_passkey_smoke_evidence:
description: Non-secret Linear/evidence reference for the Firefox and Safari smoke results
required: true
type: string
adversarial_review_confirmed:
description: Independent adversarial identity review completed successfully
required: true
type: boolean
default: false
adversarial_review_evidence:
description: Non-secret Linear/evidence reference for adversarial review findings and disposition
required: true
type: string

permissions:
contents: read

concurrency:
group: publish-aether-${{ github.ref }}
cancel-in-progress: false

jobs:
verify:
permissions:
Expand All @@ -39,12 +24,12 @@ jobs:
env:
GRADLE_OPTS: "-Dorg.gradle.jvmargs=-Xmx2g -Dorg.gradle.vfs.watch=false -Dorg.gradle.daemon=false"
steps:
- name: Require a main-branch manual release
- name: Require a main-branch release
if: github.event_name == 'workflow_dispatch'
shell: bash
run: |
[[ "$GITHUB_REF" == "refs/heads/main" ]] || {
echo "::error::Manual publishing is allowed only from refs/heads/main (received $GITHUB_REF)."
echo "::error::Publishing is allowed only from refs/heads/main (received $GITHUB_REF)."
exit 1
}

Expand Down Expand Up @@ -186,30 +171,22 @@ jobs:
cmake --build build/identity-wasi-host --config Release --parallel 2
ctest --test-dir build/identity-wasi-host --output-on-failure

- name: Verify combined wasmWasi component host
if: github.event_name == 'workflow_dispatch'
shell: bash
run: |
test -x aether-identity-wasi-host/run-component-gate.sh || {
echo "::error::The Kotlin guest/OpenSSL crypto/wasi:http component gate is not implemented; publishing is blocked."
exit 1
}
./aether-identity-wasi-host/run-component-gate.sh

publish:
if: github.event_name == 'workflow_dispatch'
if: >-
github.event_name == 'workflow_dispatch' ||
(github.event_name == 'push' && github.ref == 'refs/heads/main')
needs: verify
permissions:
contents: write
runs-on: ubuntu-latest
env:
GRADLE_OPTS: "-Dorg.gradle.jvmargs=-Xmx2g -Dorg.gradle.vfs.watch=false -Dorg.gradle.daemon=false"
steps:
- name: Require a main-branch manual release
- name: Require a main-branch release
shell: bash
run: |
[[ "$GITHUB_REF" == "refs/heads/main" ]] || {
echo "::error::Manual publishing is allowed only from refs/heads/main (received $GITHUB_REF)."
echo "::error::Publishing is allowed only from refs/heads/main (received $GITHUB_REF)."
exit 1
}

Expand All @@ -231,31 +208,27 @@ jobs:
java-version: '21'
distribution: 'temurin'

- name: Read release version
- name: Read release version and publication state
id: version
shell: bash
run: |
VERSION=$(grep "^VERSION=" version.properties | cut -d'=' -f2)
[[ -n "$VERSION" ]] || { echo "::error::version.properties has no VERSION"; exit 1; }
CHANGELOG_VERSION=$(sed -n 's/^## \[\([^]]*\)\].*/\1/p' CHANGELOG.md | head -n 1)
[[ "$CHANGELOG_VERSION" == "$VERSION" ]] || {
echo "::error::The first CHANGELOG.md release ($CHANGELOG_VERSION) does not match version.properties ($VERSION)."
exit 1
}
echo "version=$VERSION" >> "$GITHUB_OUTPUT"

- name: Verify manual hardware-passkey release gate
env:
HARDWARE_SMOKE_CONFIRMED: ${{ inputs.hardware_passkey_smoke_confirmed }}
HARDWARE_SMOKE_EVIDENCE: ${{ inputs.hardware_passkey_smoke_evidence }}
run: |
[[ "$HARDWARE_SMOKE_CONFIRMED" == "true" ]] || { echo "::error::Firefox and Safari hardware-passkey smoke, including second-passkey and session-revocation checks, is not confirmed"; exit 1; }
[[ -n "$HARDWARE_SMOKE_EVIDENCE" ]] || { echo "::error::A non-secret hardware-smoke evidence reference is required"; exit 1; }

- name: Verify adversarial-review release gate
env:
ADVERSARIAL_REVIEW_CONFIRMED: ${{ inputs.adversarial_review_confirmed }}
ADVERSARIAL_REVIEW_EVIDENCE: ${{ inputs.adversarial_review_evidence }}
run: |
[[ "$ADVERSARIAL_REVIEW_CONFIRMED" == "true" ]] || { echo "::error::Independent adversarial identity review is not confirmed"; exit 1; }
[[ -n "$ADVERSARIAL_REVIEW_EVIDENCE" ]] || { echo "::error::A non-secret adversarial-review evidence reference is required"; exit 1; }
if git rev-parse --verify --quiet "refs/tags/v${VERSION}" >/dev/null; then
echo "tag_exists=true" >> "$GITHUB_OUTPUT"
echo "Release tag v${VERSION} already exists; publication is already complete."
else
echo "tag_exists=false" >> "$GITHUB_OUTPUT"
fi

- name: Ensure publishing secrets are present
if: steps.version.outputs.tag_exists != 'true'
shell: bash
run: |
[[ -n "${{ secrets.CENTRAL_USERNAME }}" ]] || { echo "::error::Missing required secret CENTRAL_USERNAME"; exit 1; }
Expand All @@ -264,6 +237,7 @@ jobs:
[[ -n "${{ secrets.CENTRAL_SIGNING_KEY_ASC }}" ]] || { echo "::error::Missing required secret CENTRAL_SIGNING_KEY_ASC"; exit 1; }

- name: Configure publishing credentials
if: steps.version.outputs.tag_exists != 'true'
shell: bash
run: |
cat <<'EOF' > local.properties
Expand Down Expand Up @@ -298,6 +272,7 @@ jobs:
rm -rf "$TMP_GNUPGHOME"

- name: Publish Aether to Maven Central
if: steps.version.outputs.tag_exists != 'true'
shell: bash
run: |
MAVEN_REPO="$RUNNER_TEMP/aether-release-m2-${GITHUB_RUN_ID}-${GITHUB_RUN_ATTEMPT}"
Expand Down Expand Up @@ -357,6 +332,7 @@ jobs:
fi

- name: Create and push release tag
if: steps.version.outputs.tag_exists != 'true'
shell: bash
run: |
VERSION="${{ steps.version.outputs.version }}"
Expand Down
16 changes: 6 additions & 10 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
# Changelog

## [0.6.0.0] - Unreleased

This version has not been published. Publication remains blocked until the combined wasmWasi
component-host gate, independent adversarial review, and Firefox/Safari hardware-passkey smoke
gates all pass with non-secret evidence.
## [0.6.0.0] - 2026-07-16

### Added

Expand All @@ -29,14 +25,14 @@ gates all pass with non-secret evidence.
- Kotlin and the dependency stack are upgraded for Summon `0.7.0.2`; the CLI and example are now
compiled from real Kotlin source sets and CI rejects expected tasks that report `NO-SOURCE`.

### Known release gates
### Known limitations

- The Kotlin `2.3.x` wasmWasi artifact is still a Preview1 core module. The WIT contract, guest
capability checks, and OpenSSL 3 native host primitives exist, but the combined component-model
binding and real `wasi:http` host/guest CI runner do not. The wasmWasi authority artifact must not
be published as production-ready until that gate passes.
- The independent adversarial review and manual Firefox/Safari hardware-passkey smoke checklist
have not yet been recorded as passing release evidence.
binding and real `wasi:http` host/guest integration are not complete. Production wasmWasi
authority hosting is not supported in this release.
- Independent adversarial review and manual Firefox/Safari hardware-passkey smoke testing remain
recommended operational validation before a production identity deployment.

### Removed

Expand Down
14 changes: 8 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@

A Django-like Kotlin Multiplatform framework that runs on JVM (Vert.x + Virtual Threads) and Wasm (Cloudflare/Browser).

> **Release status:** `0.6.0.0` is unreleased and is not available from Maven Central. Its target
> coordinates below are illustrative until the combined wasmWasi host, adversarial-review, and
> manual hardware-passkey release gates pass. Use this source checkout for pre-release evaluation.
> **Release status:** `0.6.0.0` was released on 2026-07-16, and the Maven coordinates below use this
> version. Production wasmWasi identity-authority hosting is not supported in this release because
> the combined component-host integration is not complete; use the JVM authority or another
> supported trusted server host for production.

## Architecture

Expand Down Expand Up @@ -293,9 +294,10 @@ DatabaseDriverRegistry.initialize(driver)
- CBOR-based UI tree serialization
- Future-proof architecture for emerging web platforms

The generic target is available for experimentation, but the `0.6.0.0` Identity authority is not
production-ready on wasmWasi until the combined Kotlin guest, WIT OpenSSL crypto host, and
`wasi:http` release gate passes. See the [identity deployment guide](docs/identity/deployment.md#release-verification).
The generic target is available for experimentation, but production wasmWasi Identity-authority
hosting is not supported in `0.6.0.0`: the combined Kotlin guest, WIT OpenSSL crypto host, and
`wasi:http` integration is not complete. See the
[identity deployment guide](docs/identity/deployment.md#release-verification).

## Transport Abstraction

Expand Down
3 changes: 2 additions & 1 deletion aether-identity-wasi-host/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ Important: this repository currently supplies the hardened native library, WIT
contract, and guest-side ABI/readiness tests, but not a runnable component that
binds the Kotlin 2.3.x Preview1 guest to that WIT world. The C test below proves
the OpenSSL primitives only. It is not the wasmWasi production release gate.
Publishing a wasmWasi authority remains blocked until a component-model binding
The `0.6.0.0` artifacts include the experimental wasmWasi target, but production
wasmWasi identity-authority hosting is unsupported until a component-model binding
and combined host/guest runner exercise the real library and `wasi:http` in CI.
This matches the [Kotlin/Wasm WASI documentation](https://kotlinlang.org/docs/wasm-wasi.html),
which identifies the Kotlin 2.3 toolchain target as WASI 0.1/Preview 1 and leaves
Expand Down
6 changes: 3 additions & 3 deletions contract-fixtures/seen-fel-634/README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# Seen FEL-634 identity contract fixtures

These fixtures define the browser-safe and authorization-safe portion of the unreleased Aether
Identity `0.6.0.0` target contract that Seen may consume during integration. Publication remains
blocked by Aether's release gates. They do not expose persistence models. In particular, they contain no
These fixtures define the browser-safe and authorization-safe portion of the released Aether
Identity `0.6.0.0` contract that Seen may consume during integration. They do not expose
persistence models. In particular, they contain no
session selector/secret, credential public key, token digest, recovery code, raw IP address, or
provider assertion.

Expand Down
7 changes: 4 additions & 3 deletions docs/api-reference/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,13 @@ Aether supports multiple Kotlin targets:
| wasmWasi | Edge computing, serverless functions |

The broad wasmWasi target is experimental for the `0.6.0.0` Identity authority. Production
identity deployment remains blocked until a combined Kotlin guest + WIT OpenSSL crypto +
`wasi:http` host gate passes; see [Identity deployment](../identity/deployment.md#release-verification).
wasmWasi identity-authority hosting is not supported in this release because the combined Kotlin
guest, WIT OpenSSL crypto, and `wasi:http` host integration is not complete; see
[Identity deployment](../identity/deployment.md#release-verification).

### Version History

- **0.6.0.0 (unreleased; publish-blocked)** — Breaking passkey-first identity platform and storage-neutral adapters
- **0.6.0.0 (2026-07-16)** — Breaking passkey-first identity platform and storage-neutral adapters
- **0.5.0.2** — GrpcHttpHandler, GrpcMiddleware, Pipeline.installGrpc() DSL
- **0.5.0.0** — gRPC support (gRPC-Web, Connect protocol, code-first proto generation), UserContext, AuthStrategy
- **0.4.0** — Signals, Tasks, Channels, Admin Widgets, Rate Limit Middleware
Expand Down
7 changes: 4 additions & 3 deletions docs/api-reference/authentication.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
# Authentication and identity

The unreleased Aether `0.6.0.0` separates generic application authentication in `aether-core` from
the passkey-first identity platform in `aether-auth`. These are target-release contracts;
publication remains blocked by the [identity release gates](../identity/deployment.md#release-verification).
Released on 2026-07-16, Aether `0.6.0.0` separates generic application authentication in
`aether-core` from the passkey-first identity platform in `aether-auth`. Production wasmWasi
identity-authority hosting is not supported in this release; see
[Identity deployment](../identity/deployment.md#wasmwasi).

- Use `aether-auth` for people, organizations, passkeys, recovery, CLI device authorization,
service identities and enterprise federation/provisioning.
Expand Down
4 changes: 2 additions & 2 deletions docs/deployment/DEPLOYMENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

The Docker, Compose, Nginx, SQL, and Kubernetes samples previously stored in this directory were
removed because they invoked nonexistent example distribution tasks and configured legacy JWT,
password-session, and raw-IP behavior. They are not compatible with the unreleased Aether Identity
`0.6.0.0` target.
password-session, and raw-IP behavior. They are not compatible with the Aether Identity `0.6.0.0`
release.

For the passkey authority, follow only the [Aether Identity deployment
guide](../identity/deployment.md). For an unrelated `aether-core` application, own the application
Expand Down
7 changes: 4 additions & 3 deletions docs/identity/README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
# Passkey-first identity

The unreleased Aether Identity `0.6.0.0` is a storage-neutral Kotlin Multiplatform identity
authority. Publishing is blocked until every release gate in the
[deployment guide](deployment.md#release-verification) passes. It uses
Released on 2026-07-16, Aether Identity `0.6.0.0` is a storage-neutral Kotlin Multiplatform identity
authority. It uses
discoverable WebAuthn passkeys for people, organization-bound device grants for the CLI, and
scoped service credentials for automation. Password authentication, identity JWT fallback,
legacy identity sessions, and global groups or permissions are not part of this subsystem.
Production wasmWasi identity-authority hosting is not supported in this release; see the
[deployment guide](deployment.md#wasmwasi) for the incomplete component-host integration.

The generic authentication and session facilities in `aether-core` remain available to unrelated
applications. Do not combine those facilities with an Aether Identity session or treat a core role
Expand Down
40 changes: 23 additions & 17 deletions docs/identity/deployment.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ distribution.

### wasmWasi

The supported production profile is a component host that provides:
A future production profile requires a component host that provides:

- a real WASI realtime clock and cryptographically secure random source;
- outbound WASI HTTP suitable for the selected storage and federation endpoints; and
Expand All @@ -146,9 +146,10 @@ pure-Kotlin asymmetric fallback is unsupported in production.
The current Kotlin 2.3.x build emits a Preview1 core module and does not yet ship the component
binding that connects the guest runtime to this WIT world. The native OpenSSL library and the
guest-side capability tests are independently verified, but that is not equivalent to executing
the combined production host. Therefore wasmWasi authority deployment is not release-ready in
`0.6.0.0` until a component-model binding and combined `wasi:http`/crypto integration test pass.
JVM remains the deployable authority target; browser wasmJs remains public client/UI code only.
the combined production host. Production wasmWasi identity-authority hosting is therefore not
supported in `0.6.0.0`; a future supported release requires the component-model binding and a
combined `wasi:http`/crypto integration test. JVM remains the deployable authority target; browser
wasmJs remains public client/UI code only.

Map WIT signing through an `aether_identity_signing_key_store`. Register only provider- or
HSM-owned `EVP_PKEY` references under versioned opaque handles; never expose PKCS#8 bytes to the
Expand Down Expand Up @@ -338,16 +339,21 @@ intentional property.

## Release verification

Automated release evidence must include JVM, wasmJs and real wasmWasi protocol/crypto tests, the
PostgreSQL 16 and Firestore conformance/race suites, Summon browser tests, federation adversarial
suites and the complete example build. An independent adversarial review must disposition all
findings and record a non-secret evidence reference; assertions, tokens, secrets, credential IDs,
recovery material, and user PII must not appear in that evidence. Before publishing, perform a
manual hardware-passkey smoke test on both Firefox and Safari against the release candidate. In
each browser, register and complete username-free sign-in, perform passkey step-up, enroll and use a
second named passkey, revoke a distinct active session, prove that the revoked cookie no longer
authenticates, and complete recovery re-enrollment. Verify that recovery revokes the prior sessions
and replaces the remaining recovery-code generation. Record browser, OS, authenticator
model/transport, RP/origin and result without recording credential IDs, assertions, cookies, or
recovery material. A missing or failed adversarial review or hardware smoke test blocks the release.
Manual publishing requires both evidence references explicitly.
Pushes to `main` publish after the automated workflow verification succeeds. `workflow_dispatch`
remains a fallback for rerunning a release from `main`; it is not required for normal publication.
Automated verification includes JVM, wasmJs and wasmWasi guest protocol/crypto tests, the native
OpenSSL host-library tests, PostgreSQL 16 and Firestore conformance/race suites, Summon browser
tests, federation adversarial suites, and the complete example build. Production wasmWasi
identity-authority hosting is not supported in `0.6.0.0` because the combined Kotlin guest, WIT
crypto, and `wasi:http` component-host integration is not complete.

Before a production deployment, perform an independent adversarial review and a manual
hardware-passkey smoke test on both Firefox and Safari. The review should disposition all findings
and record a non-secret evidence reference; assertions, tokens, secrets, credential IDs, recovery
material, and user PII must not appear in that evidence. In each browser, register and complete
username-free sign-in, perform passkey step-up, enroll and use a second named passkey, revoke a
distinct active session, prove that the revoked cookie no longer authenticates, and complete
recovery re-enrollment. Verify that recovery revokes the prior sessions and replaces the remaining
recovery-code generation. Record browser, OS, authenticator model/transport, RP/origin, and result
without recording credential IDs, assertions, cookies, or recovery material. Treat these checks as
operational validation guidance rather than automated publication gates.
Loading
Loading