Juntai IAM Python
juntai-iam is the side-effect-free Python integration library for Juntai
identity and domain authorization. It validates Casdoor API access tokens and
agent Application proofs, resolves current human, agent, and service principals,
validates Kubernetes projected workload tokens, evaluates the reviewed Casbin
policy and peer-principal intersections, constructs trusted Meridian operation
context, and enforces field-read and field-write decisions.
This repository does not contain an IAM service, HTTP listener, browser session, tenant administration API, secret backend, policy store, audit chain, database migration owner, provider runtime, deployment image, OpenAPI artifact, or generated TypeScript client. Casdoor remains authoritative for organizations, Users, Applications, OIDC tokens, Permissions, models, and Casbin records. Domain services remain authoritative for their resources, actions, fields, business policy, logical schemas, and protected operations.
Install
python -m pip install "juntai-iam>=2,<3"
The stable import root is juntai.iam. Importing it performs no discovery,
network request, token validation, database connection, migration, policy
synchronization, listener startup, or global middleware installation.
Compose a service boundary
from juntai.iam import (
CasdoorAccessTokenVerifier,
PeerAuthorizationRequest,
build_operation_context,
enforce_operation_context,
project_allowed_fields,
)
verifier = CasdoorAccessTokenVerifier.from_discovery(
issuer=settings.oidc_issuer,
audiences={settings.api_audience},
required_scopes={"juntai.api"},
)
authorizer = application_authorizer
meridian_runtime = application_meridian_runtime
Construct these objects once in the service composition root and inject them. The policy source reads a revisioned snapshot from the configured Casdoor policy integration; this package does not persist or mutate policy.
For a protected operation:
identity = verifier.verify(access_token, correlation_id=request_id)
authorization_request = PeerAuthorizationRequest(
tenant_id=identity.tenant_id,
resource=f"axiom/workflows/{workflow_id}",
resource_indicator="urn:juntai:axiom",
audience="axiom-api",
action="read",
purpose="workflow-view",
requested_fields=("id", "name", "created_at", "secret_notes"),
)
decision = authorizer.authorize(identity, authorization_request)
operation_context = build_operation_context(
identity,
decision,
deadline=request_deadline,
)
expression = structured.get(resource=workflow_resource, key=workflow_id)
with enforce_operation_context(meridian_runtime, operation_context):
row = meridian_runtime.execute(expression).data
return project_allowed_fields(row, decision)
authorizer implements AuthorizationDecisionHook; the domain composition root
owns its current policy inputs. meridian_runtime implements
OperationContextRuntimeHook; the released Meridian runtime owns physical
installation and enforcement. authorize_operation() combines both decision
and context construction when the caller does not also need the decision for
field projection.
Build tenant, resource, action, purpose, and requested fields from verified identity and the domain route. Never deserialize an authorization decision or operation context from an untrusted request.
Peer principals, bindings, and token rules
IdentityContext/v2 is immutable and uses exactly human, agent, or
service. Authentication mechanism, session, workload, delegated authority,
and MCP/OpenAPI channel remain separate. The durable issuer-qualified subject is
always the actor; in delegated agent execution it remains the agent, while the
human grantor and exact live grant are separate references. PrincipalPresentation/v1
is safe user-facing identity data and never authorizes an operation.
Human API validation checks signature, issuer, audience, authorized party,
expiry, not-before, scopes, organization, key identity, and the exact
tokenType=access-token profile. Callers forward Casdoor's OAuth access_token
response field. Casdoor 3.125 aliases id_token to the same JWT bytes, so
downstream code cannot infer response-field provenance; any future distinct
ID-token profile is rejected as an API credential.
Each agent is a distinct non-interactive Casdoor User owned by juntai-system.
An Agent-category Application is only an AuthenticatorBinding/v1. For
client credentials, verify_agent() verifies standard sub as the Application,
azp and standard aud as its exact client ID, plus six signed JWT-Custom
claims for binding ID, principal ID, binding revision, authority epoch, logical
audience, and logical resource. resolve_agent_identity() then requires the
current Application and User to reference the same principal, binding, epoch,
and revisions, and verifies the running application-version reference and every
selected profile against the principal's current eligibility lists. A custom
claim never substitutes for standard JWT validation or current-state resolution.
Raw credentials are never returned or logged.
Discovery and JWKS are fetched lazily and cached. Unknown keys trigger at most
one bounded refresh and fail closed. Previously validated keys may survive a
configured short issuer outage; invalidate_keys() supplies the rotation and
emergency invalidation path.
Services use audience-bound projected ServiceAccount tokens validated through the live Kubernetes TokenReview API. Namespace and ServiceAccount are mapped by trusted service configuration. The TokenReview client may authenticate with a projected reviewer token or an explicit Kubernetes client-certificate/key pair supplied by the composition root; credential files are never read at import time.
PeerPrincipalEvaluator is the shared fail-closed path. Self mode evaluates
direct grants; delegated mode replaces direct grants with the current grantor
authority intersected with the exact DelegationGrant/v1. It never unions self
grants. Both modes then intersect the principal/agent ceiling, application
installation, profile, invocation/session/task, and final domain policy. The
exact equations are:
A_self = G_self ∩ C_principal ∩ C_install ∩ C_profile ∩ C_invocation_session_task ∩ P_domain
A_delegated = A_grantor(current) ∩ G_delegation ∩ C_principal ∩ C_install ∩ C_profile ∩ C_invocation_session_task ∩ P_domain
G_self is deliberately absent from A_delegated. The
default current-state staleness is at most 30 seconds; high-risk operations can
require a live check. Revocation, expiry, lost grantor authority, stale epochs,
or any tenant/application/audience/resource/purpose/profile/task/session mismatch
denies without fallback. MCP and OpenAPI select audit channel only.
Casbin conventions
The reviewed logical policy tuple is:
p = subject_or_role, tenant, resource_pattern, action_pattern, field_pattern, effect
g = subject, role, tenant
Evaluation is default deny and any matching deny overrides allows. Tenant is an
exact verified organization identifier and cannot be wildcarded. Resource,
action, and field patterns use literal slash segments, * for one segment, and
terminal ** for descendants. Regular expressions and executable matcher text
are rejected. Operation policies use field pattern *; requested fields are
evaluated separately through field.read or field.write policies.
AuthorizationDecision binds the result to the exact tenant, resource, action,
allowed fields, matched policy identifiers, revision, correlation-derived
decision identifier, and audit reason. Call invalidate() on the evaluator for
policy revocation, emergency deny, or revision notifications; cache TTL is the
bounded fallback.
Meridian operation context
OperationContext/v1 carries only bounded logical facts established by the
verified identity and exact peer-principal decision: tenant, actor, principal
kind, groups, roles, workload reference, audience/resource boundary, purpose,
requested and allowed fields, policy revisions, decision and request
fingerprints, authority epoch, correlation, and the shortest trusted deadline.
It contains no storage Binding, Adapter, Engine, broker, credential, physical
locator, secret, or deployment setting.
build_operation_context() rejects denied, expired, malformed, or mismatched
decisions. The deterministic request fingerprint includes every authorization
dimension, including requested fields, purpose, application/profile/task/
invocation/session bounds, and live-authority mode.
enforce_operation_context() and its async variant require the injected
Meridian runtime to prove that no prior context exists, the exact context is
active before protected work, and no context remains afterward. Missing runtime
support, failed installation, nested reuse, and leakage fail closed. IAM never
inspects or selects the physical enforcement mechanism.
Contracts
This package pins juntai-iam-contracts==1.2.0. That separate, language-neutral
package owns the wire schemas, deterministic fixtures, canonicalization, and
cross-language conformance matrix. juntai-iam owns Python validation and
enforcement only. It does not copy the schemas, issue credentials, persist a
principal or grant, or expose a network service. A schema-valid request still
grants no authority until current proof and every evaluation layer allow it.
Verification
python -m pip install -e '.[test]'
ruff check .
pytest -m 'not kubernetes and not casdoor'
python -m build
Real-dependency suites are opt-in and never substitute SQLite, in-memory authority, or fixture platform APIs:
tests/casdoorvalidates a native Casdoor-issued access token through live discovery and JWKS. Platform's official-image acceptance additionally proves two distinct agent Applications, signed JWT-Custom binding claims, supported User/Application/Permission convergence, and absence of the historical patch.tests/kubernetesvalidates a projected ServiceAccount token with live TokenReview.tests/unit/test_meridian_context.pyproves deterministic allow/deny context, exact boundary binding, deadline narrowing, installation, cleanup, and leakage denial without a storage implementation.
The deterministic HTTP/JWT and TokenReview test doubles under tests/unit are
unit evidence only.
Native authority observations
Version 2.1.0 adds juntai.iam.native_records and
juntai.iam.native_observation, using the exact IAM contracts 1.2.0 release.
The host supplies authenticated selected reads and enforces their deadlines.
The library projects native records, verifies unchanged Casdoor proofs and
intersects current authority with destination bounds; it creates no credentials,
listener, grant or durable state. See the consumer contract
for the observation lifecycle, masked-field behavior and separately required live
qualification. Existing authority APIs retain their regression coverage.
Version 2.1.1 accepts the exact single native JWT audience as either a string or Casdoor’s singleton array. Extra, duplicate and malformed audiences remain denied; the signed token bytes and authority checks are unchanged.
Release files for juntai-iam 2.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| juntai_iam-2.1.1.tar.gz | 44.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| juntai_iam-2.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 93.5 kB
Release files / juntai_iam-2.1.1.tar.gz
| Download URL | juntai_iam-2.1.1.tar.gz |
|---|---|
| Size | 44.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
9cd18c0bfcea8bbc0ea34643b2c24b940ae2e2d4600f035a8a3c378ccea00211
|
|
BLAKE2b-256 checksum How to use checksums |
3fb5ff2a782a9631fab4251a4992b8f8bd265f3e98098bb09541503f3450ee6c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 25, 2026.
Transparency logRelease files / juntai_iam-2.1.1-py3-none-any.whl
| Download URL | juntai_iam-2.1.1-py3-none-any.whl |
|---|---|
| Size | 49.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e6aa6517d0618b749e91d5ee887302a193e5e57bdc558cb3f8ac7c0460b16af2
|
|
BLAKE2b-256 checksum How to use checksums |
461d567c38c9191010aebaa39019eed312c60e852401e1f5fe7de8036d362daf
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 25, 2026.
Transparency log