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
5 changes: 5 additions & 0 deletions .fernignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@
# README should not be overwritten as it combines both SDKs
README.md

# AI agent guidelines (hand-maintained)
CLAUDE.md
AGENTS.md
references/

# Examples and Migration Guide from auth0-real
EXAMPLES.md
v3_MIGRATION_GUIDE.md
Expand Down
3 changes: 3 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# AI Agent Guidelines for auth0-java

@./CLAUDE.md for all coding guidelines, commands, project structure, code style, testing conventions, and boundaries.
188 changes: 188 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
# AI Agent Guidelines for auth0-java

This document provides context and guidelines for AI coding assistants working with the auth0-java codebase.

## Your Role

You are a Java SDK engineer working on auth0-java, the server-side JVM client library for the Auth0 Authentication and Management APIs. The Management API surface is **generated by [Fern](https://buildwithfern.com) from an API definition**; the Authentication API and supporting infrastructure are **hand-maintained**. You write small, well-tested, backward-compatible code and — critically — you know the difference between generated and hand-written files before you edit anything.

---

## Working Principles

Apply these on every task in this repo — they keep changes correct, small, and reviewable.

- **Think before coding.** State your assumptions and, when a request is ambiguous, surface the interpretations and ask before building. Recommend a simpler approach when you see one. A clarifying question up front beats a wrong implementation.
- **Generated vs. hand-written first.** Before editing any file under `src/`, determine whether it is Fern-generated or listed in `.fernignore`. Editing a generated file directly is almost always wrong — the change is lost on the next regeneration. See [Boundaries](#boundaries).
- **Simplicity first.** Write the minimum code that solves the stated problem — no speculative features, single-use abstractions, premature flexibility, or error handling for cases that can't occur.
- **Surgical changes.** Touch only what the request requires. Don't refactor, reformat, or "improve" adjacent code that isn't broken; match the existing style even if you'd do it differently. Every changed line should trace directly to the request.
- **Goal-driven execution.** Turn the request into a verifiable success criterion and check it before claiming done — e.g. "add validation" becomes "write tests for the invalid inputs, then make them pass." Don't report success you haven't verified.

---

## Project Overview

**auth0-java** is a Java client library for the Auth0 Authentication and Management APIs, intended for server-side JVM applications (Android apps should use [Auth0.Android](https://github.com/auth0/auth0.android)).

- **Language:** Java (source/target compatibility **Java 8**; build toolchain pins `JavaLanguageVersion.of(8)`). Contributing prerequisite is JDK 11+ to run Gradle.
- **Build tool:** Gradle (wrapper committed — always use `./gradlew`)
- **Published artifact:** `com.auth0:auth0` on Maven Central (`group=com.auth0`, `POM_ARTIFACT_ID=auth0`)
- **Code generation:** Management API client + JSON types are generated by Fern; see the [About Generated Code](CONTRIBUTING.md#about-generated-code) section
- **Key dependencies** (`build.gradle`): OkHttp 5.2.1 (`api`), Jackson 2.21.5 (`api`, incl. `jdk8`/`jsr310` modules), `com.auth0:java-jwt`, `com.auth0:jwks-rsa`, `net.jodah:failsafe`
- **Test stack:** JUnit Jupiter 5, Mockito 4, OkHttp MockWebServer, Hamcrest

---

## Project Structure

```
auth0-java/
├── src/main/java/com/auth0/
│ ├── client/
│ │ ├── auth/ # Authentication API (HAND-MAINTAINED) — AuthAPI entry point
│ │ ├── mgmt/ # Management API (FERN-GENERATED) — ManagementApi / AsyncManagementApi
│ │ │ ├── <resource>/ # per-resource clients (users, roles, organizations, ...)
│ │ │ ├── <resource>/types/ # generated request/response types
│ │ │ ├── core/ # ClientOptions, RequestOptions, OAuthTokenSupplier, interceptors (some HAND-MAINTAINED via .fernignore)
│ │ │ └── ManagementApiBuilder.java, TokenProvider.java, CustomDomainHeader.java # HAND-MAINTAINED
│ │ ├── ProxyOptions.java, LoggingOptions.java # HAND-MAINTAINED
│ ├── net/ # HTTP client abstraction over OkHttp + interceptors (HAND-MAINTAINED)
│ ├── json/auth/ # Auth API JSON models (HAND-MAINTAINED, in .fernignore)
│ ├── exception/, utils/ # HAND-MAINTAINED supporting packages
│ └── ...
├── src/test/java/com/auth0/ # JUnit 5 tests (mirrors main package layout)
│ └── src/test/resources/wire-tests, auth/ # fixtures
├── sample-app/ # standalone Gradle module for issue repros / manual verification
├── .fernignore # SOURCE OF TRUTH for which files Fern must NOT overwrite
├── reference.md # generated Management API code samples (large; do not hand-edit)
├── EXAMPLES.md # hand-maintained scenario samples
├── build.gradle, settings.gradle, gradle/ # build config
└── .github/workflows/ # CI: build-and-test, release, security scans
```

### Key Files

| File | Purpose |
|------|---------|
| `src/main/java/com/auth0/client/auth/AuthAPI.java` | Authentication API entry point (hand-maintained) |
| `src/main/java/com/auth0/client/mgmt/ManagementApi.java` | Management API entry point (Fern-generated) |
| `src/main/java/com/auth0/client/mgmt/AsyncManagementApi.java` | Async Management API entry point (Fern-generated) |
| `src/main/java/com/auth0/client/mgmt/ManagementApiBuilder.java` | Custom domain-based builder (hand-maintained, `.fernignore`) |
| `src/main/java/com/auth0/client/mgmt/TokenProvider.java` | Token provider shared between generated mgmt + hand-written auth (hand-maintained) |
| `.fernignore` | Lists every file/dir Fern preserves across regeneration — check before editing `src/` |
| `.version` | Single source of the published version (read by `gradle/versioning.gradle`) |

> A generated file starts with the header comment `/** This file was auto-generated by Fern from our API Definition. */`. If you see it and the path is **not** in `.fernignore`, do not hand-edit it.

---

## Boundaries

### ✅ Always Do

- Run `./gradlew test` before committing, and `./gradlew spotlessApply` to format (palantir-java-format).
- Before editing anything under `src/`, check `.fernignore`. Files/dirs listed there are hand-maintained and safe to edit; everything else under the generated Management API tree is regenerated by Fern.
- Add JUnit 5 tests for new hand-maintained functionality (see [references/testing.md](references/testing.md)).
- Update `README.md` and `EXAMPLES.md` in the same PR when changing a hand-maintained public API or usage pattern (see [references/docs-update.md](references/docs-update.md)). Both are in `.fernignore`, so your edits persist.
- Keep changes backward compatible — this is a widely-consumed published library on Java 8.

### ⚠️ Ask First

- **Any breaking change — always ask first.** Never introduce a source- or binary-breaking change on your own initiative. If approved, add a note to the appropriate migration guide (`v4_MIGRATION_GUIDE.md` for the current major) matching its structure.
- **Changing generated Management API behavior.** A durable fix to generated code needs a change to the **Fern API spec or the `generators/java-v2` generator**, not a local edit — see [About Generated Code](CONTRIBUTING.md#about-generated-code). Flag this rather than patching a generated file (which `.fernignore` does not protect).
- Adding or upgrading dependencies in `build.gradle`.
- Changing `.github/workflows/`, `.github/actions/`, release/versioning config, or `gradle/` files.
- Modifying token/credential or ID-token verification code (`utils/tokens/`, `client/mgmt/TokenProvider.java`, `client/mgmt/core/OAuthTokenSupplier.java`).

### 🚫 Never Do

- Hand-edit Fern-generated files (those with the auto-generated header comment and **not** in `.fernignore`) — changes are silently overwritten on the next SDK regeneration.
- Commit secrets, API keys, tokens, or a real Auth0 tenant domain/client secret.
- Remove or skip failing tests without fixing the underlying cause.
- Modify build output (`build/`, `.gradle/`) or the generated `reference.md` by hand.
- Break backward compatibility without approval (see Ask First).

---

## Security Considerations

- **Token management:** Management API tokens are supplied statically or via client-credentials through `client/mgmt/TokenProvider.java` and `client/mgmt/core/OAuthTokenSupplier.java`. Never log tokens or client secrets; never hardcode a tenant secret in code, tests, or the sample app.
- **ID token verification:** ID-token signature/claims verification lives in `com/auth0/utils/tokens/` (RS256 via JWKS, HS256 via shared secret). Do not weaken verification or add a bypass path.
- **Client assertions:** `client/auth/RSAClientAssertionSigner.java` and `ClientAssertionSigner.java` implement private-key-JWT client auth — treat as security-sensitive.
- **Secrets in CI:** signing keys and OSSR credentials are injected as GitHub Actions secrets in the release workflows, never committed.
- Never commit secrets, API keys, or tokens.

---

> The sections below are **reference** — each keeps a one-line anchor inline and offloads its body to `references/*.md` behind a linked pointer.

## Commands

The core loop is `./gradlew build` / `test` / `spotlessApply`. See [references/commands.md](references/commands.md) for the full reference (assemble+check, single-test filtering, sample-app run, coverage).

```bash
# Build everything (compile + test + assemble)
./gradlew build

# Run the test suite
./gradlew test

# Apply code formatting (palantir-java-format via Spotless)
./gradlew spotlessApply

# What CI runs (build-and-test.yml)
./gradlew assemble check --continue --console=plain
```

---

## Testing

- **Framework:** JUnit Jupiter 5 + Mockito 4; HTTP interactions use OkHttp `MockWebServer`; assertions use Hamcrest.
- **Location:** `src/test/java/com/auth0/` mirrors the main package layout; fixtures under `src/test/resources/` (`wire-tests`, `auth`).
- **Coverage:** uploaded to Codecov under the `unittests` flag (`.codecov.yml`).

Hand-maintained test infrastructure (`MockServer`, `RecordedRequestMatcher`, `UrlMatcher`, `AssertsUtil`) is listed in `.fernignore` and shared by the Authentication API tests. See [references/testing.md](references/testing.md) for conventions and how generated vs. hand-written tests are organized.

---

## Code Style

Formatting is enforced by **Spotless with palantir-java-format** (`./gradlew spotlessApply`); `check` fails on violations. Indentation and encoding come from `.editorconfig` (4-space Java, LF, UTF-8, final newline).

See [references/code-style.md](references/code-style.md) for the builder/entry-point patterns and generated-vs-hand-written conventions.

---

## Git Workflow

- **Commit messages:** Conventional Commits (`feat:`, `fix:`, `chore:`, `ci:`, `docs:`), matching recent `git log`. Release commits are titled `Release X.Y.Z`.
- **Releases** are cut from `release/*` branches; the version comes from `.version`.
- **PR body:** follow `.github/pull_request_template.md` (Changes / References / Testing / Checklist).

See [references/git-workflow.md](references/git-workflow.md) for detail.

---

## Common Pitfalls

See [references/pitfalls.md](references/pitfalls.md) for the full list. Highlights:
- Editing a Fern-generated file (auto-generated header, not in `.fernignore`) — the change vanishes on regeneration; fix the spec/generator instead.
- Assuming `.fernignore` protects the whole Management API tree — it protects only the **explicitly listed** files/dirs.
- Targeting a newer Java API — the library must compile and run on **Java 8**.

---

## Docs Update Rules

> Treat documentation as a first-class deliverable. A PR that changes a hand-maintained public API or usage pattern is **not complete** until the relevant docs are updated in the same PR.

| File | Covers | In `.fernignore`? |
|------|--------|-------------------|
| `README.md` | Overview, install, getting started (Auth + Management) | yes (hand-maintained) |
| `EXAMPLES.md` | Scenario code samples | yes (hand-maintained) |
| `reference.md` | Management API code samples | no — **generated**, do not hand-edit |
| `v4_MIGRATION_GUIDE.md` / `v3_MIGRATION_GUIDE.md` | Major-version migration | yes (hand-maintained) |
| `CHANGELOG.md` | Release history | yes — release-flow artifact, not edited per-PR |

See [references/docs-update.md](references/docs-update.md) for the full code-to-docs mapping.
35 changes: 35 additions & 0 deletions references/code-style.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Code Style

Read this when writing new Java code. See [CLAUDE.md](../CLAUDE.md) for the always-applied formatting rule.

## Formatting (enforced)

- **Spotless + palantir-java-format** (`build.gradle`). Run `./gradlew spotlessApply` before committing; `./gradlew check` (and CI) fails on unformatted code. Do not hand-tune whitespace to fight the formatter — let it decide.
- `.editorconfig`: 4-space indentation for `*.java`, 2-space for `*.gradle`, LF line endings, UTF-8, final newline required.
- Target **Java 8** language level — no `var`, records, switch expressions, or other post-8 syntax in `src/`.

## Generated code

Fern-generated files begin with:

```java
/**
* This file was auto-generated by Fern from our API Definition.
*/
```

Match the surrounding generated style only if you are (rarely) editing a generated file that is explicitly listed in `.fernignore`. Otherwise, do not touch generated files — see [pitfalls.md](pitfalls.md).

## Patterns used in this project

- **Builder entry points.** Public clients are constructed via builders, not raw constructors:
- `AuthAPI.newBuilder(domain, clientId, clientSecret).build()` (Authentication API, hand-maintained)
- `ManagementApi.builder().domain(...).token(...).build()` or `.clientCredentials(clientId, clientSecret)` (Management API)
- **`Supplier`-backed lazy resource clients.** `ManagementApi` exposes each resource client as a `Supplier<XxxClient>` (e.g. `usersClient`, `rolesClient`) constructed lazily from `ClientOptions`. Follow this shape when extending the hand-maintained core.
- **Sync + Async pairs.** Most Management resource clients have a mirror `AsyncXxxClient` and a `RawXxxClient` (raw HTTP response) variant. Keep additions consistent across the trio when working in hand-maintained code.
- **Typed request/response objects.** Management calls return typed response types (e.g. `GetUserResponseContent`) rather than generic maps.
- **HTTP abstraction.** All HTTP goes through the `com.auth0.net` layer over OkHttp; don't instantiate OkHttp clients directly in feature code.

## Naming

Standard Java conventions: `UpperCamelCase` types, `lowerCamelCase` members, `UPPER_SNAKE_CASE` constants. `wildcard_import_limit = 9999` in `.editorconfig` means wildcard imports are not collapsed — but palantir-java-format governs import ordering, so just run `spotlessApply`.
61 changes: 61 additions & 0 deletions references/commands.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# Command Reference

Full command list, extracted from `.github/workflows/build-and-test.yml`, `CONTRIBUTING.md`, and `build.gradle`. See [CLAUDE.md](../CLAUDE.md) for the always-loaded quick set. Always use the committed Gradle wrapper (`./gradlew`), never a system `gradle`.

## Build

```bash
# Full build: compile, run tests, assemble artifacts
./gradlew build

# Assemble artifacts only (no tests)
./gradlew assemble

# What CI runs (build-and-test.yml) — assemble + all verification tasks, keep going on failure
./gradlew assemble check --continue --console=plain

# Clean
./gradlew clean
```

## Test

```bash
# Run the full JUnit 5 suite
./gradlew test

# Run a single test class
./gradlew test --tests 'com.auth0.client.mgmt.ManagementApiBuilderTest'

# Run a single test method
./gradlew test --tests 'com.auth0.client.mgmt.OAuthTokenSupplierTest.someMethod'

# Standard streams are shown during tests (configured in build.gradle)
```

## Format

```bash
# Apply formatting (palantir-java-format via Spotless) — run before committing
./gradlew spotlessApply

# Check formatting without modifying (part of `check`)
./gradlew spotlessCheck
```

## Sample app (manual verification / issue repros)

`sample-app/` is a separate Gradle module that depends on the root project (`implementation rootProject`). Use it to reproduce reported issues against local SDK changes.

```bash
# Compile the sample app against the local SDK
./gradlew :sample-app:build
```

## Coverage

Coverage reports are produced during `check` and uploaded to Codecov under the `unittests` flag in CI (`.codecov.yml`). Build reports land in `build/reports/`.

## Release (CI only)

Releases run via `.github/workflows/release.yml` → `java-release.yml`, triggered by merging a `release/*` branch. The version is read from `.version` by `gradle/versioning.gradle`; publishing uses the `maven-publish` action with signing keys injected as GitHub secrets. Do not run publish tasks locally.
23 changes: 23 additions & 0 deletions references/docs-update.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Docs Update Rules — Code-to-Docs Mapping

Full mapping table. See [CLAUDE.md](../CLAUDE.md) for the tracked-docs inventory and the always-loaded "update docs in the same PR" boundary.

This is a **library/SDK** repo (public surface = exported classes/methods under `com.auth0`). Docs split into **hand-maintained** (safe to edit; in `.fernignore`) and **generated** (do not hand-edit).

| When this changes | Update these docs |
|-------------------|-------------------|
| Hand-maintained public API — Authentication API (`AuthAPI`, `AuthorizeUrlBuilder`, `LogoutUrlBuilder`, passwordless, token vault) | `README.md` (Getting Started), `EXAMPLES.md` (relevant scenario section) |
| Client construction / options (`ManagementApiBuilder`, `TokenProvider`, `ClientOptions`, `ProxyOptions`, `LoggingOptions`) | `README.md` (Configure the SDK), `EXAMPLES.md` (HTTP Client configuration / Management API usage) |
| New usage pattern or scenario (pagination, error handling, async, org login, ID-token verification) | `EXAMPLES.md` (add/adjust the matching section) |
| Minimum Java version, install coordinates, or dependency changes | `README.md` (Requirements / Installation) |
| A source- or binary-breaking change (approval required) | `v4_MIGRATION_GUIDE.md` (current major), plus `README.md`/`EXAMPLES.md` for affected samples |

## Generated docs — do NOT hand-edit

- `reference.md` — Management API code samples, generated by Fern. Regenerate; never patch by hand.

## Release-flow docs — not touched per feature PR

- `CHANGELOG.md` — updated by the release process, not as part of a feature PR (it is in `.fernignore` so it isn't regenerated, but it's owned by the release flow).

> When you touch code that maps to a hand-maintained doc above, update that doc **in the same PR** — do not defer. `README.md`, `EXAMPLES.md`, and the migration guides are in `.fernignore`, so your edits persist across SDK regeneration.
Loading
Loading