Skip to main content

gnap-caep-risc

A server-side GNAP client. The key is registered by value and proved with mutual TLS, an HTTP message signature, or a detached JWS. Access tokens are key-bound; a bearer token is refused. One Shared Signals poll stream carries CAEP and RISC events.

The private key stays in this process. The same gnap.json shape as the Node library loads: the JSON keys are identical.

Build and tests

docker build --target test .

The test stage runs pip install --no-cache-dir ".[dev]" && pytest in python:3.11-slim. GitHub Actions on a push uses that command. Do not run pytest on the host. The demo image does not run the suite.

Those tests use an in-process stub. They do not start iya-sts.

python3 scripts/live_iya_sts.py is the live half. It copies this checkout to a scratch build context, generates the client key and runs the install script there (which writes the tlsCa chain), then builds this demo image from it, checks the image carries the chain and no key, starts the demo with no CA mount and TLS_CA_REFRESH=0, signs in, and requires a credential-change event and a session-revoked event on GET /live-status. The second event ends the local session. When IYA_STS_URL is unset it starts the latest main branch of iya-sts in memory mode, with persistence and clustering off. It uses the host's Python and Docker and does not import this library. It binds two high ports and never binds 3000 or 8081. The nightly workflow runs the unit suite and this script once every 24 hours.

A pull request merged into main publishes the package to PyPI after the test workflow succeeds on that commit. A direct push does not. There is no API token: PyPI Trusted Publishing trades the workflow's GitHub OIDC token for a short-lived upload token, from the pypi environment, and PyPI holds the publisher for this repository and publish.yml. A version already on PyPI stays there; the next release is a new version in pyproject.toml (and VERSION).

The iya-sts trust chain (tlsCa)

tlsCa in demo/gnap.json names the iya-sts TLS listener CA trust chain the library trusts. The default is generated/idp-ca.pem, relative to demo/. The value may also be file:<path>, env:<NAME>, or the PEM itself. The library adds every certificate in it to the default trust store.

scripts/configure_iya_sts.py, the install script, writes that file. It saves the whole chain iya-sts publishes at GET /tls/server-certificate (leaf, TLS Issuing CA, Intermediate, Root), or the chain from the TLS handshake when that path does not answer. It prints the path, the trust anchor's subject and its SHA-256 fingerprint. Compare the anchor with the Root CA on iya-sts's PKI page.

The demo image build copies that file into the image at /app/demo/generated/idp-ca.pem, so the image trusts that iya-sts with no bind mount and no fetch. Run the install script before you build the image. Rebuild the image after running the install script against a different iya-sts. .dockerignore admits only that file from demo/generated. The client key and certificate stay out of the image; compose mounts demo/generated for them. A build with no chain file yet (a fresh clone, CI) still succeeds; the image then has no tlsCa file.

The mechanism is COPY demo demo plus .dockerignore's demo/generated/* and !demo/generated/idp-ca.pem. Do not replace it with a COPY that names the file or globs for it: when the file is absent, BuildKit fails on the missing demo/generated and the classic builder fails with "no source files were specified". A directory COPY of demo/ (which always exists) succeeds in both.

The container entrypoint also refreshes the file from the authorization server at start, because a development iya-sts makes a new CA when it restarts. A failed refresh keeps the file from the build. TLS_CA_REFRESH=0 turns the refresh off. python scripts/trust_chain.py --config demo/gnap.json refreshes it by hand.

Three calls

from gnap_caep_risc import GnapClient

gnap = GnapClient.from_file("gnap.json")
started = gnap.request_grant()
done = gnap.finish_redirect(query, [started.pending.id])

request_grant returns a redirect and a pending grant. finish_redirect checks the interaction hash against grants this process started, then continues the grant with the key proof. Pass the pending ids this browser was given as allowed_ids.

resolve_config and read_config_file load the same document without starting a grant.

Signals

signals omitted or true keeps CAEP and RISC on. The resolved configuration omits the key, fills ssf from ssf.transmitter or transmitterIssuer, and asks for ssf.read and ssf.manage when access does not say otherwise.

signals: false does not start the Shared Signals receiver, does not require transmitter metadata, and drops ssf.read and ssf.manage from the GNAP access. The resolved configuration includes signals: false. If those two rights were the only ones, configuration fails and asks for another right the authorization server grants. Any other value fails with signals must be true or false.

ssf.pollIntervalMs is the poll interval in milliseconds.

Demo

docker compose up --build

PORT defaults to 3000 and is the bind port. Loopback finish and display URLs follow PORT. Any other host is left as written. PUBLIC_URL or --public-url replaces the origin and keeps the path. GET /healthz returns ok. The home page has a sign-in control; /login starts a grant, /callback finishes it, and POST /logout signs out. GET /live-status is JSON: signedIn, subject, the receiver state, and the Shared Signals events this process has accepted (type and jti only). It does not include tokens. Do not bind port 3000 or 8081 while something else is already using them.

The shipped demo/gnap.json leaves signals on by omitting the key. Key material is file: or env: and is not in the tree. Generate a key inside the demo image, then register the application:

docker compose build
docker run --rm --user "$(id -u):$(id -g)" \
  -v "$PWD/demo:/app/demo" \
  gnap-caep-risc-python-demo \
  gnap-caep-risc generate-key --config demo/gnap.json
ADMIN_API_CLIENT_SECRET=… python scripts/configure_iya_sts.py --config demo/gnap.json
docker compose build

The second build bakes in the trust chain the install script saved.

The install script creates the test user gnap-demo-user. Its password is $GNAP_DEMO_USER_PASSWORD, or iya-sts generates one; the script writes a generated password to demo/generated/gnap-demo-user.password (mode 0600) and prints only that path, never the password.

--dry-run prints the admin API calls and sends nothing. When the gnap-demo container is running, its PORT wins over the shell PORT.

License

MIT. Copyright (c) 2026 Iya CyberSecurity Solutions, LLC.

Metadata

Release files for gnap-caep-risc 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for gnap-caep-risc 0.1.0
File Size Uploaded Provenance Actions
gnap_caep_risc-0.1.0.tar.gz 44.9 kB With provenance Details for gnap_caep_risc-0.1.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for gnap-caep-risc 0.1.0
File Interpreter ABI Platform Actions
gnap_caep_risc-0.1.0-py3-none-any.whl Python 3 none any Details for gnap_caep_risc-0.1.0-py3-none-any.whl

Total release size: 83.4 kB

Release files / gnap_caep_risc-0.1.0.tar.gz

Download URL gnap_caep_risc-0.1.0.tar.gz
Size 44.9 kB
Tags Source
SHA-256 checksum
How to use checksums
e6cdc2366eb73a905f5c225b6811328ffcb03f2c7bb44d6dc99098705e083667
BLAKE2b-256 checksum
How to use checksums
bebb2b62e6be57f570dede6b59f287bf9f005e28f786ef35a8d99677f9906a80
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

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 Nov 2, 2026.

Transparency log

Release files / gnap_caep_risc-0.1.0-py3-none-any.whl

Download URL gnap_caep_risc-0.1.0-py3-none-any.whl
Size 38.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
152ff5288dfb0b182aff3cf3112774eef4f789c410f40114aec6fa24da9bd853
BLAKE2b-256 checksum
How to use checksums
710d8624d54af2c2a6da0b8a03edf46da0acefad66beff7a6869e58b2bb1e388
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

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 Nov 2, 2026.

Transparency log

Security for gnap-caep-risc 0.1.0

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.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for gnap_caep_risc-0.1.0.tar.gz

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 Nov 2, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page