Skip to content

Release 9.4.0

Latest

Choose a tag to compare

@github-actions github-actions released this 15 Sep 07:38
0eb545d

AxonFlow Java SDK v9.4.0

Installation

Maven:

<dependency>
    <groupId>com.getaxonflow</groupId>
    <artifactId>axonflow-sdk</artifactId>
    <version>9.4.0</version>
</dependency>

Gradle:

implementation 'com.getaxonflow:axonflow-sdk:9.4.0'

The first Java SDK release carrying these entries sends the PEP capability handshake, which a
platform reads from v10.4.0, and reaches /api/v1/typed-policies, which needs a v11.0.0 platform;
against an older platform it works unchanged. Upgrade the SDK before the platform: from v11.0.0,
Decide under an organization's redact override refuses a caller that does not declare redaction,
and only a release that sends the handshake can declare it.

Added

  • v11.0.0 decision provenance on every governed response (axonflow-enterprise#3746).
    ClientResponse (proxyLLMCall), ConnectorResponse (queryConnector copies it from the
    /api/request response; mcpQuery reads it off the wire), MCPCheckOutputResponse,
    DecideResponse and the pre-check's PolicyApprovalResult carry getEngine(),
    getSubjectType(), getPolicyBundle() and getLegacyValidators(): which engine and policy set
    decided, the type of principal it decided for, and any checksum validator that acted before the
    engine. DecideResponse adds getPolicyIdentities() (naming each entry of
    getEvaluatedPolicies() in order), getPolicyPacks() and getDocumentVersion(), and
    PolicyApprovalResult adds getDecisionId() and getVerdict() (allow or deny). Every
    field is null or empty on an older platform. The pre-v11 constructors remain and leave the new
    fields unset.
  • LegacyPolicyWriteFrozenException. A v11.0.0 platform answers a write to its static- or
    dynamic-policy routes with 409 LEGACY_POLICY_WRITE_FROZEN. The SDK throws this typed
    exception, whose message names the typed policy route (/api/v1/typed-policies), instead of the
    generic VERSION_CONFLICT it used for every 409. Every other error keeps its existing form.
  • AxonFlowConfig.Builder.onRouteDeprecation(...). When the platform marks a route a call used
    as deprecated (X-AxonFlow-Removed-In or an RFC 9745 Deprecation header, with the successor
    from Link: <...>; rel="successor-version"), the SDK reports it once per route: to this
    listener when it is set, otherwise to the log at WARN. A route whose path carries an id is
    reported once, as its template (GET /api/v1/static-policies/{id}), not once per id. From
    v11.0.0 the legacy policy routes carry it: the static- and dynamic-policy routes and the policy
    simulation routes.
  • The PEP capability handshake, which a platform reads from v10.4.0
    (axonflow-enterprise#3746).
    An enforcement point
    declares the obligation types and schema versions it can discharge with PEPHandshake.of(...)
    and PEPCapability.of(...), presented as X-Axonflow-PEP-Handshake on every call to a plane
    that reads it: decide (and decideAndFulfill and fulfillRequest's engine round-trip),
    evaluate and evaluateAll, the MCP check methods, and the gateway pre-check, async forms
    included. Set AxonFlowConfig.Builder.pepHandshake(...) for the client, or derive a client
    presenting another with AxonFlow.withPEPHandshake(...). It is never sent to any other route,
    and a client with no declaration sends none. The encoding matches the platform's reference
    encoder byte for byte, and a declaration the platform would refuse throws
    PEPHandshakeException naming the member where it is built.
  • Typed policy authoring (axonflow-enterprise#3746). A v11.0.0 platform authors policy as a
    typed document: validated, published as a signed artifact pinned by its digest, and promoted
    to active. client.typedPolicies() reaches the six routes the agent proxies under
    /api/v1/typed-policies: edition(), validate(document, fixtures), publish(document, fixtures), activate(digest, reason), active() and system(). Every refusal except a 401 is
    a TypedPolicyRefusalException carrying the status, the platform's reason, any findings, the
    policy a tier refusal names (getPolicy()) and Retry-After. active() is empty only for the
    platform's 404 nothing_active; any other 404 is a TypedPolicyRefusalException with status
    404, and a v11.0.0 platform answers a document store it cannot read with 503
    storage_unavailable, which throws it too (getaxonflow/axonflow-enterprise#4255). The answers
    carry the edition's vocabulary (getCatalogDigest(), getRegistryVersion(),
    getCatalogFixture()), the organization template controls a publication or an activation omits
    (getTemplateOmissions(), a TemplateOmissionReport, or getTemplateOmissionsUnavailable()
    when the platform could not report them), and each system control's getName().
    TypedPolicySystemControl.getMandatory() is a plain boolean, false when the platform omits
    it. A client derived with asUser has its own namespace. Rolling back and withdrawing are customer portal operations the agent does
    not proxy, so the SDK has no method for either.
  • Two runnable examples for the v11 platform (axonflow-enterprise#3746). examples/pep-handshake declares an enforcement
    point's capabilities and decides with them, printing each verdict and its reasons;
    examples/typed-policies reads what the deployment may author, validates a document and, with
    AXONFLOW_TYPED_POLICY_PUBLISH=1, publishes and activates it, printing the publication's
    template-omission report before it activates: activating a document that omits the
    organization template's controls removes them for the organization. It finds its default
    document on its classpath, so it runs from any directory, and it exits non-zero when a
    publication or activation it asked for is refused. Run the handshake example first: after a
    document with an organization-scope constraint is activated, a decide that does not supply the
    attribute the constraint conditions on is denied fail-closed with reasons
    ["unknown_constraint"]. From v11.0.0 the deny's first reason is that code, followed by one
    naming each constraint it could not evaluate and the attribute it needed
    (getaxonflow/axonflow-enterprise#4247).

Deprecated

  • The v11.0.0 policy simulation routes (axonflow-enterprise#3746). simulatePolicies,
    getPolicyImpactReport and detectPolicyConflicts, and their Async forms, are deprecated: a
    v11.0.0 platform deprecates /api/v1/policies/simulate, /impact-report and /conflicts and
    removes them in v11.1, and stamps every response with X-AxonFlow-Removed-In: v11.1 and a
    successor Link naming /api/v1/typed-policies (plus an RFC 9745 Deprecation header once
    v11.0.0 is tagged), which AxonFlowConfig.Builder.onRouteDeprecation reports once per route.
    They keep answering until then, but on a v11.0.0 platform their results
    come from the legacy engine, which no longer decides, so they do not predict what the platform
    enforces. createPolicyOverride and deletePolicyOverride now document that
    a v11.0.0 platform retires per-policy overrides and refuses both with
    LegacyPolicyWriteFrozenException.

Fixed

  • A static-policy read no longer fails on a category the SDK does not know
    (axonflow-enterprise#4224).
    A v11 platform returns categories the PolicyCategory enum did not
    name (security-dangerous on getEffectiveStaticPolicies()), and the strict enum failed the
    whole read. StaticPolicy now keeps the platform's string: getCategory() returns the
    PolicyCategory, or null for a category this SDK does not know yet, and the new
    getCategoryValue() returns the string either way. PolicyCategory gains SECURITY_DANGEROUS,
    COMPLIANCE_EUAIACT, DANGEROUS_QUERIES, PII_DETECTION and SQL_INJECTION, the categories
    the platform's shipped posture uses that it lacked, and PolicyCategory.lookup(String). The list,
    create and update builders gain categoryValue(String), to filter by or write a category the
    enum does not name, and EffectivePoliciesOptions gains it too for symmetry; each of those types
    gains getCategoryValue(), and StaticPolicy gains setCategoryValue(String).
    EffectivePoliciesOptions and getEffectiveStaticPolicies now say what the platform does with
    them: the effective route declares no query parameter and applies none of their options, so
    filter the returned policies instead.
  • The published jar is now compiled AGAINST the Java 11 API, not merely to Java 11 bytecode
    (#231).
    pom.xml set maven.compiler.source and maven.compiler.target, which fix the
    language level and the class-file version but leave javac linking against the class library
    of whatever JDK runs the build. A Java 16+ API therefore compiled clean on a newer JDK and
    failed only at run time on Java 11, which is the declared minimum in both the pom and the
    README. The SDK pom and all five example poms now set maven.compiler.release to 11 instead.
    The floor is unchanged; only its enforcement is.