Skip to content

deps(python): bump the python-all group in /python-oauth-dpop with 3 updates#1

Closed
dependabot[bot] wants to merge 344 commits into
mainfrom
dependabot/pip/python-oauth-dpop/python-all-03d55aadeb
Closed

deps(python): bump the python-all group in /python-oauth-dpop with 3 updates#1
dependabot[bot] wants to merge 344 commits into
mainfrom
dependabot/pip/python-oauth-dpop/python-all-03d55aadeb

Conversation

@dependabot
Copy link
Copy Markdown
Contributor

@dependabot dependabot Bot commented on behalf of github Apr 13, 2026

Updates the requirements on cryptography, pytest and pytest-cov to permit the latest version.
Updates cryptography to 46.0.7

Changelog

Sourced from cryptography's changelog.

46.0.7 - 2026-04-07


* **SECURITY ISSUE**: Fixed an issue where non-contiguous buffers could be
  passed to APIs that accept Python buffers, which could lead to buffer
  overflow. **CVE-2026-39892**
* Updated Windows, macOS, and Linux wheels to be compiled with OpenSSL 3.5.6.

.. _v46-0-6:

46.0.6 - 2026-03-25

  • SECURITY ISSUE: Fixed a bug where name constraints were not applied to peer names during verification when the leaf certificate contains a wildcard DNS SAN. Ordinary X.509 topologies are not affected by this bug, including those used by the Web PKI. Credit to Oleh Konko (1seal) for reporting the issue. CVE-2026-34073

.. _v46-0-5:

46.0.5 - 2026-02-10


* An attacker could create a malicious public key that reveals portions of your
  private key when using certain uncommon elliptic curves (binary curves).
  This version now includes additional security checks to prevent this attack.
  This issue only affects binary elliptic curves, which are rarely used in
  real-world applications. Credit to **XlabAI Team of Tencent Xuanwu Lab and
  Atuin Automated Vulnerability Discovery Engine** for reporting the issue.
  **CVE-2026-26007**
* Support for ``SECT*`` binary elliptic curves is deprecated and will be
  removed in the next release.

.. v46-0-4:

46.0.4 - 2026-01-27

  • Dropped support for win_arm64 wheels_.
  • Updated Windows, macOS, and Linux wheels to be compiled with OpenSSL 3.5.5.

.. _v46-0-3:

46.0.3 - 2025-10-15


* Fixed compilation when using LibreSSL 4.2.0.

.. _v46-0-2:
</tr></table>

... (truncated)

Commits

Updates pytest to 8.4.2

Release notes

Sourced from pytest's releases.

8.4.2

pytest 8.4.2 (2025-09-03)

Bug fixes

  • #13478: Fixed a crash when using console_output_style{.interpreted-text role="confval"} with times and a module is skipped.

  • #13530: Fixed a crash when using pytest.approx{.interpreted-text role="func"} and decimal.Decimal{.interpreted-text role="class"} instances with the decimal.FloatOperation{.interpreted-text role="class"} trap set.

  • #13549: No longer evaluate type annotations in Python 3.14 when inspecting function signatures.

    This prevents crashes during module collection when modules do not explicitly use from __future__ import annotations and import types for annotations within a if TYPE_CHECKING: block.

  • #13559: Added missing [int]{.title-ref} and [float]{.title-ref} variants to the [Literal]{.title-ref} type annotation of the [type]{.title-ref} parameter in pytest.Parser.addini{.interpreted-text role="meth"}.

  • #13563: pytest.approx{.interpreted-text role="func"} now only imports numpy if NumPy is already in sys.modules. This fixes unconditional import behavior introduced in [8.4.0]{.title-ref}.

Improved documentation

  • #13577: Clarify that pytest_generate_tests is discovered in test modules/classes; other hooks must be in conftest.py or plugins.

Contributor-facing changes

  • #13480: Self-testing: fixed a few test failures when run with -Wdefault or a similar override.
  • #13547: Self-testing: corrected expected message for test_doctest_unexpected_exception in Python 3.14.
  • #13684: Make pytest's own testsuite insensitive to the presence of the CI environment variable -- by ogrisel{.interpreted-text role="user"}.
Commits
  • bfae422 Prepare release version 8.4.2
  • 8990538 Fix passenv CI in tox ini and make tests insensitive to the presence of the C...
  • ca676bf Merge pull request #13687 from pytest-dev/patchback/backports/8.4.x/e63f6e51c...
  • 975a60a Merge pull request #13686 from pytest-dev/patchback/backports/8.4.x/12bde8af6...
  • 7723ce8 Merge pull request #13683 from even-even/fix_Exeption_to_Exception_in_errorMe...
  • b7f0568 Merge pull request #13685 from CoretexShadow/fix/docs-pytest-generate-tests
  • 2c94c4a add missing colon (#13640) (#13641)
  • c3d7684 Merge pull request #13606 from pytest-dev/patchback/backports/8.4.x/5f9938563...
  • dc6e3be Merge pull request #13605 from The-Compiler/training-update-2025-07
  • f87289c Fix crash with times output style and skipped module (#13573) (#13579)
  • Additional commits viewable in compare view

Updates pytest-cov to 7.1.0

Changelog

Sourced from pytest-cov's changelog.

7.1.0 (2026-03-21)

  • Fixed total coverage computation to always be consistent, regardless of reporting settings. Previously some reports could produce different total counts, and consequently can make --cov-fail-under behave different depending on reporting options. See [#641](https://github.com/pytest-dev/pytest-cov/issues/641) <https://github.com/pytest-dev/pytest-cov/issues/641>_.

  • Improve handling of ResourceWarning from sqlite3.

    The plugin adds warning filter for sqlite3 ResourceWarning unclosed database (since 6.2.0). It checks if there is already existing plugin for this message by comparing filter regular expression. When filter is specified on command line the message is escaped and does not match an expected message. A check for an escaped regular expression is added to handle this case.

    With this fix one can suppress ResourceWarning from sqlite3 from command line::

    pytest -W "ignore:unclosed database in <sqlite3.Connection object at:ResourceWarning" ...

  • Various improvements to documentation. Contributed by Art Pelling in [#718](https://github.com/pytest-dev/pytest-cov/issues/718) <https://github.com/pytest-dev/pytest-cov/pull/718>_ and "vivodi" in [#738](https://github.com/pytest-dev/pytest-cov/issues/738) <https://github.com/pytest-dev/pytest-cov/pull/738>. Also closed [#736](https://github.com/pytest-dev/pytest-cov/issues/736) <https://github.com/pytest-dev/pytest-cov/issues/736>.

  • Fixed some assertions in tests. Contributed by in Markéta Machová in [#722](https://github.com/pytest-dev/pytest-cov/issues/722) <https://github.com/pytest-dev/pytest-cov/pull/722>_.

  • Removed unnecessary coverage configuration copying (meant as a backup because reporting commands had configuration side-effects before coverage 5.0).

7.0.0 (2025-09-09)

  • Dropped support for subprocesses measurement.

    It was a feature added long time ago when coverage lacked a nice way to measure subprocesses created in tests. It relied on a .pth file, there was no way to opt-out and it created bad interations with coverage's new patch system <https://coverage.readthedocs.io/en/latest/config.html#run-patch>_ added in 7.10 <https://coverage.readthedocs.io/en/7.10.6/changes.html#version-7-10-0-2025-07-24>_.

    To migrate to this release you might need to enable the suprocess patch, example for .coveragerc:

    .. code-block:: ini

    [run] patch = subprocess

    This release also requires at least coverage 7.10.6.

  • Switched packaging to have metadata completely in pyproject.toml and use hatchling <https://pypi.org/project/hatchling/>_ for building. Contributed by Ofek Lev in [#551](https://github.com/pytest-dev/pytest-cov/issues/551) <https://github.com/pytest-dev/pytest-cov/pull/551>_ with some extras in [#716](https://github.com/pytest-dev/pytest-cov/issues/716) <https://github.com/pytest-dev/pytest-cov/pull/716>_.

  • Removed some not really necessary testing deps like six.

... (truncated)

Commits
  • 66c8a52 Bump version: 7.0.0 → 7.1.0
  • f707662 Make the examples use pypy 3.11.
  • 6049a78 Make context test use the old ctracer (seems the new sysmon tracer behaves di...
  • 8ebf20b Update changelog.
  • 861d30e Remove the backup context manager - shouldn't be needed since coverage 5.0, ...
  • fd4c956 Pass the precision on the nulled total (seems that there's some caching goion...
  • 78c9c4e Only run the 3.9 on older deps.
  • 4849a92 Punctuation.
  • 197c35e Update changelog and hopefully I don't forget to publish release again :))
  • 14dc1c9 Update examples to use 3.11 and make the adhoc layout example look a bit more...
  • Additional commits viewable in compare view

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


Dependabot commands and options

You can trigger Dependabot actions by commenting on this PR:

  • @dependabot rebase will rebase this PR
  • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
  • @dependabot show <dependency name> ignore conditions will show all of the ignore conditions of the specified dependency
  • @dependabot ignore <dependency name> major version will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself)
  • @dependabot ignore <dependency name> minor version will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself)
  • @dependabot ignore <dependency name> will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself)
  • @dependabot unignore <dependency name> will remove all of the ignore conditions of the specified dependency
  • @dependabot unignore <dependency name> <ignore condition> will remove the ignore condition of the specified dependency and ignore conditions

prodnull and others added 30 commits March 11, 2026 08:37
…roof INFO logging

- Add #[instrument(skip(signing_key, nonce), fields(method, target))] to generate_dpop_proof()
- Add #[instrument(skip(public_key_jwk, nonce), fields(method, target))] to build_dpop_message()
- Add #[instrument(skip_all)] to assemble_dpop_proof() (entry/exit timing only)
- Add AgentRequest::command_name() for stable span command field recording
- Add #[instrument(name='ipc_request')] to handle_connection with request_id UUID, command, peer_pid span fields
- Record command name in span after JSON parse; peer_pid forwarded from serve loop (no second syscall)
- Emit INFO log 'DPoP proof requested' in GetProof arm with username, target, signer_type fields (OPS-13)
- Add test_get_proof_emits_info_log using tracing_test::traced_test to verify INFO log emission
- Fix clippy unneeded-late-initialization warning in serve loop
- Add unix-oidc-agent/src/askpass.rs: SSH_ASKPASS handler for PAM keyboard-interactive DPoP conversation
- DPOP_NONCE: stores server nonce in PPID-keyed tmpfile (0600 perms)
- DPOP_PROOF: reads stored nonce, calls GetProof IPC, caches token, prints dpop_proof
- OIDC Token: reads cached token tmpfile or falls back to GetProof IPC
- Unrecognized prompts: safe default (empty line), no-fail
- Add SshAskpass subcommand to Commands enum in main.rs (positional <PROMPT> arg)
- 13 unit tests covering: permissions, PPID keying, prompt parsing, read_and_delete, path helpers
…wiring

- fix: append \\n after SessionClosed JSON in notify_agent_session_closed() so
  agent BufReader::read_line() returns immediately (was blocking 2s timeout)
- feat: add PamTimeoutsConfig struct with clock_skew_future_secs=5 and
  clock_skew_staleness_secs=60 defaults; wire as PolicyConfig.timeouts field
- feat: add DPoPAuthConfig::from_policy() to read clock skew from PolicyConfig.timeouts
- fix: authenticate_with_dpop() now sets ValidationConfig.clock_skew_tolerance_secs
  from policy.timeouts.clock_skew_staleness_secs (not hardcoded 60)
- fix: lib.rs pam_sm_authenticate() reads clock skew from PolicyConfig instead of
  hardcoded max_proof_age=60 and clock_skew_future_secs=5
- chore: remove DPoPAuthConfig::from_env() dead code; replace with from_policy()
- chore: remove dead CLOCK_SKEW_TOLERANCE constant from validation.rs
- test: add TDD tests for all behaviors (newline framing, PamTimeoutsConfig
  YAML/default/env-override, from_policy() clock skew)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- fix: TOCTOU unwrap() on HashMap::get() at second read lock in
  handle_step_up_result() replaced with let-else returning
  AgentResponse::error("Step-up result already consumed", "STEP_UP_CONSUMED")
- test: add test_handle_step_up_result_no_panic_on_missing_entry verifying
  error response for unknown correlation IDs (not panic)
- test: add test_handle_step_up_result_finished_task_returns_complete verifying
  the happy path (finished task → StepUpComplete) still works after the fix
- resolves clippy::unwrap_used lint violation in socket.rs

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Three bugs affecting both test_token_exchange.sh and test_dpop_binding.sh on
macOS (and any platform where bash $(cat) captures binary via command substitution):

1. DER signature parser off-by-one (OFFSET=4 → OFFSET=6): the old code read the
   INTEGER tag byte (0x02) as the R length, producing a garbage 2-byte R and a
   misaligned S. Fixed by starting at offset 6 to skip SEQUENCE header (30 XX)
   and the INTEGER tag (02) before reading the length.

2. macOS base64 trailing newline not stripped: macOS base64(1) appends a newline
   after each output line. The tr -d '=' did not remove it, embedding a '\n' inside
   JWK x/y coordinates and causing "Point not on curve" in Keycloak's BouncyCastle
   EC key parser. Fixed by inserting tr -d '\n' before tr '+/' '-_'.

3. Bash variable binary corruption (0x5c 0x30 → 0x00): when binary data is captured
   via $(cat) in a shell variable, bash interprets backslash sequences such as
   0x5c 0x30 (\0) as a null byte, silently truncating or corrupting EC coordinate
   bytes. Fixed by piping binary directly to base64 in all locations where raw binary
   (EC coordinates, SHA-256 digest, ECDSA signature) was previously routed through
   the base64url_encode() function's $(cat) capture pattern.

4. Token exchange without audience: test_token_exchange.sh step 7 was sending
   audience=target-host-b which triggers "Client not allowed to exchange" in
   Keycloak 26 standard token exchange V2. Fixed to try without audience first
   (matching test_token_exchange.py behavior) and fall back to explicit audience.

Verified: all three scripts exit 0 against a live Keycloak 26.2 instance with
docker-compose.token-exchange.yaml (clean volume, fresh realm import).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Running cargo fmt --all finds formatting drift accumulated across previous
phase implementations. No logic changes — purely formatting normalization
required for CI check to pass.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
tss-esapi-sys v0.5.0 requires the tss2-sys system library. Add
libtss2-dev to the check job apt-get install so clippy can compile
all features, unblocking the token-exchange job (needs: [check]).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add missing clock_skew_tolerance_secs field to test ValidationConfig
  initializer in validation.rs (field added in Phase 14 but test helper
  not updated)
- Fix mlock errno access: use __errno_location() on Linux, __error() on
  macOS — libc::__error() is macOS-only but was used unconditionally
- Fix tss-esapi v7.6 API breaks in tpm_signer.rs:
  - EccScheme moved from interface_types::algorithm to structures
  - PersistentTpmHandle moved from structures to handles
  - Provision moved from crate root to interface_types::resource_handles
  - StructureTag path: use constants::StructureTag (not interface_types)
  - Hierarchy::Null replaces tss_esapi::constants::tpm::Handles::Null
  - Public::Ecc { unique, .. } pattern replaces PublicIdUnion::Ecc(unique)
    (PublicIdUnion was removed; Public is now a plain enum with named fields)

These are pre-existing bugs that prevented the CI check job from passing,
which in turn blocked the token-exchange job via needs: [check].

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add #[allow(clippy::unwrap_used, clippy::expect_used)] to 16 test
  modules in pam-unix-oidc and unix-oidc-agent test files
- Fix TPM signer compilation on Linux: EccCurveIdentifier type,
  Persistent handle conversion, TPM2_RH_NULL constant, deprecated
  as_slice -> as_ref
- Inline format args (uninlined_format_args lint, ~80 instances)
- Fix misc clippy: assert_eq!(x,true)->assert!(x), writeln!,
  struct initializer syntax, filter_map, redundant import
- Guard macOS-only launchd constants with #[cfg(target_os = "macos")]
- Fix askpass test race condition with unique temp paths per test
- Add SecureStorage trait import for headless_storage Linux compilation

Verified clean on both platforms:
  macOS: cargo clippy --workspace --all-targets -- -D warnings
  Linux: docker rust:1.88 with --all-features (includes TPM/PKCS#11)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ak-glass

Phase 16 implements INT-01 through INT-04 integration test infrastructure:

- INT-01: CIBA-enabled Keycloak test realm (ciba-test-realm.json) with
  poll-mode backchannel auth, DPoP binding, and ACR LoA mapper. New
  docker-compose.ciba-integration.yaml with --features=ciba.

- INT-02: Step-up IPC full-flow integration test (step_up_ipc.rs) using
  wiremock-rs to mock OIDC discovery + CIBA endpoints. Tests StepUp →
  StepUpPending → poll → StepUpComplete, NOT_LOGGED_IN guard, and
  unknown correlation_id rejection.

- INT-03: Break-glass fallback tests — shell script validates IdP-down
  graceful failure and recovery; Rust integration test validates policy
  parsing, account matching, and unreachable-issuer independence.

- INT-04: ACR validation via CIBA integration test against live Keycloak
  with acr-loa-mapper configured. Direct-grant fallback validates ACR
  claim presence.

CI: New ciba-integration job in ci.yml.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- REQUIREMENTS.md: INT-01..INT-04 marked Complete
- ROADMAP.md: Phase 16 status updated, Phase 12 marked superseded
- docs/threat-model.md: STRIDE-based threat model covering all trust
  boundaries (IdP↔Agent, Agent↔PAM IPC, PAM↔sshd, storage backends)

50/50 v2.0 requirements now satisfied.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- docs/adversarial-review.md: Three-persona adversarial review (red team,
  enterprise architect, ops engineer) with cross-examination and prioritized
  findings. 10 findings catalogued, 1 P0 recommendation (test-mode release
  guard).
- Phase 16 VERIFICATION.md: INT-01..INT-04 all verified with test evidence.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
P0: Add compile_error! guard preventing test-mode in release builds
P0: Document dpop_required: strict as mandatory production default
P1: Pin ID token algorithm to JWKS-advertised algorithm (closes R-8)
P1: Enable nbf (not-before) validation for ID tokens
P1: Document JTI cache externalization deferral to v2.1 (SCALE-01)
P2: Add IPC connection semaphore (max 64) to prevent resource exhaustion

References: docs/threat-model.md §7, STRIDE analysis from Phase 16

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Critical fixes:
- SECURITY.md: config.toml → policy.yaml (file doesn't exist)
- CONTRIBUTING.md: license corrected to CC BY-NC-SA 4.0 (was Apache-2.0/MIT)
- CONTRIBUTING.md: Rust version 1.70 → 1.88 (matches Cargo.toml)
- CONTRIBUTING.md: remove docker-compose.dev.yaml refs (file doesn't exist)
- THREAT_MODEL.md: mark as superseded, point to threat-model.md v3.0
- README.md: link threat model to current version
- security-guide.md: remove nonexistent env vars (OIDC_VERIFY_TLS et al.)
- security-guide.md: fix break-glass config (users→accounts, method→requires)
- security-guide.md: PQC/ML-DSA-65 marked as planned, not implemented
- README.md: PQC marked as planned, not implemented

Medium fixes:
- installation.md: ChallengeResponseAuthentication → KbdInteractiveAuthentication
- installation.md: add mandatory break-glass setup section
- sudo-step-up.md: UNIX_OIDC_POLICY_PATH → UNIX_OIDC_POLICY_FILE
- deployment-patterns.md: fix username config schema (identity.transforms)
- examples/policy.yaml: add identity, break_glass, full security_modes
- docs/adr/README.md: add ADR-005, 005-alignment, 006 to index

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Break-glass auth events now log at CRITICAL, authentication/validation
failures at WARNING, and successful operations at INFO — replacing the
previous blanket INFO for all events. Adds AuditSeverity enum,
syslog_severity() method on AuditEvent, and comprehensive test coverage.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fixes deserialization failures with Google and Azure configs that
omit preferred_username. Falls back to empty string for username
mapping when absent. Closes BUG-3.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace fragile Debug-format string comparison with serde JSON
serialization, which produces stable canonical JOSE names (e.g.
'RS256'). Closes HARDEN-1.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Block HS256/HS384/HS512 when JWKS key has no alg field to prevent
algorithm confusion attacks. Closes HARDEN-2.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace DoD 5220.22-M naming with NIST SP 800-88 Rev 1 §2.4 (Clear),
which is the current authoritative standard. Closes HARDEN-5.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds experimental post-quantum hybrid DPoP signing and verification
behind the `pqc` feature gate, per draft-ietf-jose-pq-composite-sigs-01.

Agent side:
- HybridPqcSigner with composite signature (2-byte len + ML-DSA-65 + ES256)
- Composite JWK thumbprint (RFC 7638 extended for COMPOSITE kty)
- Key persistence via export_ec_key/export_pq_seed + storage router
- Config wiring: CryptoConfig.enable_pqc selects signer at daemon startup
- build_dpop_message_with_alg/assemble_dpop_proof_composite helpers

PAM side:
- validate_composite_proof verifies both ML-DSA-65 and ES256 components
- Composite thumbprint computation matches agent-side
- Feature-gated: non-PQC builds reject ML-DSA-65-ES256 as UnsupportedAlgorithm

Cross-crate:
- Forward pqc feature from unix-oidc-agent to pam-unix-oidc dependency
- 5 integration tests: roundtrip, nonce, signature structure, binding, persistence

Also fixes:
- ADR-002: correct CIBA citation (was RFC 9126/PAR, now OpenID CIBA Core)
- ADR-007/protected_key.rs: correct zeroize docs (ecdsa-0.16 ZeroizeOnDrop
  is unconditional, no feature flag on p256 0.13)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add sweep_interval_secs (default 300s, min 60s) to TimeoutsConfig
- Add validation: sweep_interval_secs >= 60 prevents I/O thrashing
- Create daemon/sweep.rs with session_expiry_sweep_loop (async) and
  sweep_expired_sessions (sync): removes expired + corrupt .json files
- ENOENT on remove_file treated as success (concurrent PAM delete race)
- Non-.json files skipped; missing directory logs WARN and returns
- Register sweep module in daemon/mod.rs
- All 9 behavior tests (TDD) pass: defaults, expired/valid/corrupt/missing
  directory/non-json/ENOENT/env-override scenarios covered

Reference: SES-09
- Add sweep_interval and session_dir builder fields to AgentServer
- Add with_sweep_interval() and with_session_dir() builder methods
- serve_with_listener() spawns sweep::session_expiry_sweep_loop when both
  sweep_interval and session_dir are Some (defaults to None — opt-in)
- main.rs Gate 2 now captures full TimeoutsConfig; wires sweep_interval_secs
  and /run/unix-oidc/sessions/ into AgentServer builder chain
- cargo clippy --workspace -- -D warnings: clean
- cargo test -p unix-oidc-agent --lib: 159 passed, 0 failed

Reference: SES-09
- Add _mlock_guard: Option<MlockGuard> field to HybridPqcSigner
- Add new_inner() private constructor matching ProtectedSigningKey pattern:
  Box::new() for stable heap address, then mlock over full allocation
- Change generate() -> Self to generate() -> Box<Self> (MEM-05)
- Change from_key_bytes() -> Result<Self,...> to Result<Box<Self>,...> (MEM-05)
- Make MlockGuard and try_mlock pub(crate) in protected_key.rs for reuse
- Update load_or_create_pqc_signer in main.rs to return Box<HybridPqcSigner>
- Dereference Box at Arc::new() call sites (*pqc) for DPoPSigner coercion
- Add test_generate_returns_box, test_from_key_bytes_returns_box,
  test_ml_dsa_zeroize_on_drop, test_hybrid_signer_boxed_and_signs
- All 13 pqc_signer unit tests pass; workspace --features pqc green

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add parent_session_id to AgentRequest::StepUp with skip_serializing_if for backward compat
- Add parent_session_id to AgentResponseData::StepUpComplete with same compat semantics
- Update step_up_complete() constructor to accept parent_session_id parameter
- Add parent_session_id to PendingStepUp struct (threaded from request)
- Add parent_session_id to StepUpOutcome::Complete (threaded through poll_ciba)
- Thread parent_session_id through handle_step_up -> PendingStepUp -> StepUpOutcome -> StepUpComplete
- Read UNIX_OIDC_SESSION_ID in pam sudo.rs and include in StepUp IPC JSON
- Add AGENT_STEP_UP and AGENT_STEP_UP_COMPLETE/TIMED_OUT audit events (OBS-3)
- 5 new serde round-trip tests cover backward compat and full field serialization
- All existing tests updated for new struct fields
- Event 1 AGENT_AUTH: 3 failure paths (not_logged_in, no_access_token, sign_error)
  and 1 success path in GetProof handler; session_id='n/a' (pre-session context)
- Event 2 AGENT_REFRESH: success path in spawn_refresh_task backoff loop;
  session_id='n/a' (background task not tied to a PAM session IPC)
- Event 3 AGENT_SESSION_CLOSED: after cleanup_session completes; session_id from IPC
- Event 4 AGENT_STEP_UP: after PendingStepUp inserted; includes parent_session_id
- Event 5 AGENT_STEP_UP_COMPLETE / AGENT_STEP_UP_TIMED_OUT: in handle_step_up_result
  with both sudo_session_id and parent_session_id for end-to-end SIEM correlation
- All events include event_type, session_id, username, and outcome (OBS-1 requirement)
- timestamp provided automatically by tracing-subscriber JSON layer (not duplicated)
- Workspace builds clean with -D warnings; all 518 tests pass
- Create docs/standards-compliance-matrix.md (329 lines, 61 standards)
  covering RFCs, NIST SPs, FIPS, OpenID specs, IETF drafts,
  SOC2/PCI/HIPAA/FedRAMP controls, MITRE ATT&CK, and CIS Controls
- Cross-reference index mapping source files to standards
- Known gaps section with priority classification
- Close F-07 (ML-DSA mlock), OBS-1 (audit events), OBS-3 (session linking)
  as resolved by Phase 17
- Update STATE.md to mark standards matrix todo as complete

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…SSH tests)

Phase 18 — Blocker Fixes + E2E Infrastructure:
- BFIX-03: Device flow token polling now sends DPoP proof header per
  RFC 9449 §4.2 (fresh proof per poll iteration + refresh requests)
- INFR-01: docker-compose.e2e.yaml with Keycloak 26.4, aligned issuer
  URLs (KC_HOSTNAME=keycloak), NO TEST_MODE
- INFR-02: Keycloak health check uses /health/ready endpoint
- INFR-03: Sentinel script verifies TEST_MODE absence before E2E tests
- INFR-04: E2E realm JSON for Keycloak 26.4 (DPoP GA, device flow)
- BFIX-02: Agent binary installed on PATH in test-host-e2e container
- E2E policy.yaml with dpop_required: strict, real validation

Phase 19 — Playwright Device Flow Automation:
- PLAY-01: Playwright spec automates Keycloak device flow consent
- PLAY-02: Tmpfile coordination between shell poll loop and Playwright
- PLAY-03: CI-compatible headless config (no --no-sandbox)
- Shell orchestrator (run-device-flow-e2e.sh) coordinates both sides

Phase 20 — SSH E2E Test:
- E2E-01: test_keycloak_real_sig.sh validates full auth chain
- E2E-02: Token claims validation (issuer, username, audience)
- E2E-03: Negative tests (wrong realm, expired tokens, DPoP replay)

Formatting changes: cargo fmt applied to touched files.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Dockerfile.build: rust 1.85→1.88 (MSRV), add libdbus-1-dev
- test-host: Ubuntu 22.04→24.04, add socat for localhost proxy
- Keycloak: 26.4→26.5.5 (realm file rename required by 26.5)
- Playwright: 1.52→1.58.2
- KC_HOSTNAME=localhost so browser+tokens use same origin
- socat proxies localhost:8080→keycloak:8080 inside test-host
- Rewrote E2E script to use unix-oidc-agent binary (real DPoP)
- Separated Linux binaries (target/release-linux) from native
- Verified selectors: #username, #password, #kc-login all present
- Full E2E pass: macOS agent→Keycloak 26.5.5→Playwright→DPoP token

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Document D-Bus session bus snooping risks, Secret Service encrypted
session mitigation, residual risks (plain session fallback), and
operator hardening recommendations.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
prodnull and others added 21 commits April 11, 2026 02:29
Two release build failures:

1. libtss2-dev missing: tss-esapi-sys (TPM2 bindings) requires tss2-sys.pc
   Added libtss2-dev to x86_64 apt-get and libtss2-dev:arm64 to Cross.toml.
   Same pattern as libdbus-1-dev fix in previous commit.

2. Security gate false positive: PRMANA_TEST_MODE grep matched the env var
   name in the runtime check code, which is present in ALL builds. The true
   sentinel for test-mode compilation is new_insecure_for_testing (a function
   that only exists when --features test-mode is active). Grep updated to
   check only for that symbol.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
prmana-agent/src/crypto/pqc_signer.rs:
- ml-dsa 0.1.0-rc.8 moved from_seed to the KeyGen trait; import it
- Use MlDsa65::from_seed(&seed) via KeyGen trait (was SigningKey::from_seed)
- Use pq_key.signing_key().verifying_key() — verifying_key() is on
  ExpandedSigningKey in rc.8, not directly on the SigningKey wrapper

prmana-agent/src/storage/migration.rs:
- migration_pairs() declared pairs as let but pushes to it under #[cfg(pqc)]
  — needs mut; only surfaces when --all-features is active

.github/workflows/release.yml:
- Package artifacts step copied LICENSE-APACHE and LICENSE-MIT which do not
  exist; repo uses a single CC BY-NC-SA 4.0 LICENSE file

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Cold builds with --all-features take 40+ min on GH runners due to
TPM2/PQC/SPIRE compilation. Cache ~/.cargo and target/ keyed on
Cargo.lock to reduce subsequent runs to ~5 min.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
CWE-377 / CWE-379: write_with_restricted_perms() used .create(true) without
O_EXCL, allowing a local attacker to pre-create the tmpfile with 0666
permissions. The agent would write the OIDC access token into the attacker-
controlled file, preserving the world-readable permissions.

Fix: remove_file() clears any pre-existing file/symlink, then create_new(true)
(O_CREAT|O_EXCL) guarantees atomic exclusive creation with mode 0o600 set at
creation time. If an attacker wins the narrow race between remove and create,
create_new returns AlreadyExists — a localized DoS rather than token exfiltration.

Tmpfiles are keyed by PPID so two concurrent SSH sessions do not collide.
The token tmpfile is deleted immediately after reading (see run_ssh_askpass).

Discovered by Gemini security review, independently verified.
References: VULN-001, CWE-377, CWE-379

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Go stdlib (GO-2025-3750 — O_CREATE|O_EXCL inconsistency on Unix/Windows):
- go-oauth-dpop/go.mod: go 1.21 → 1.23
- dpop-cross-language-tests/go-test/go.mod: go 1.21 → 1.23

deny.toml — document accepted/deferred advisories with rationale:
- RUSTSEC-2026-0097 (rand 0.8.5 unsound with custom logger): accepted —
  prmana uses OsRng from rand_core directly, never rand::rng(); zero exposure
- RUSTSEC-2024-0436 (paste unmaintained): accepted — proc-macro only,
  no runtime risk
- RUSTSEC-2025-0134 (rustls-pemfile unmaintained): deferred — requires
  reqwest 0.11 → 0.12 upgrade (43 call sites + blocking feature refactor);
  tracked for a dedicated dependency update pass

reqwest 0.11 → 0.12 upgrade is intentionally deferred: the fix requires
refactoring 43 call sites and removing the blocking feature — a breaking
change that needs its own phase to do properly without introducing regressions.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
…compile check

cargo test --all-features on a cold 2-core GH runner takes 45+ min because
it builds every optional crate (TPM2, PQC, SPIRE, YubiKey) from scratch.
Hardware-gated tests (TPM, YubiKey, SPIRE) are all #[ignore] anyway, so
--all-features adds only compilation cost, not test coverage.

Split into two steps:
1. cargo test --workspace (default features) — runs real tests in ~5 min
2. cargo check --workspace --all-features — verifies optional features compile

This keeps CI honest (all features still checked) while completing in a
reasonable time. The cargo cache will warm on first pass for future runs.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Previously 13 tests were #[ignore] and never ran in CI:
- 3x step_up_ipc: needed --test-threads=1 (now run sequentially)
- 2x headless_storage: needed Linux keyutils (now run with libkeyutils-dev)
- 1x storage router migration: needed ProjectDirs (works on Linux runner)
- 5x TPM swtpm tests: now run against swtpm Docker container
- 2x SPIRE workload API: now run against SPIRE Docker container

Still genuinely cannot run in CI (physical hardware required):
- 2x yubikey_signer: physical YubiKey needed (test locally with --ignored)
- 3x keyring_store/router: D-Bus session keychain (requires interactive session)

Workflow triggers on push/PR to main when agent/PAM source changes.
Uses shared Cargo cache key for efficient compilation across all 4 jobs.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
…lume

TPM: ghcr.io/tpm2-software/swtpm requires authentication on GH Actions
  — add docker/login-action@v3 with GITHUB_TOKEN before compose up

SPIRE: bind-mount volume device /tmp/spire-agent/public must exist before
  docker compose can populate it — add mkdir -p before compose up
  — also add GHCR login since SPIRE images are on ghcr.io/spiffe/

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
cargo test --workspace was taking 40+ min cold because compilation and
test execution were merged in one step with no timeout guard.

Split into:
1. 'Build test binaries' — cargo test --workspace --no-run (compile only)
   No timeout — compilation time is unpredictable on cold cache
2. 'Run tests' — cargo test --workspace -- --test-threads=4 (15 min limit)
   If a test hangs, this step fails clearly after 15 min
3. 'Verify all-features compile' — 20 min limit

--test-threads=4 uses all 4 vCPUs (GH Actions runners have 4 cores,
not 2) for parallel test execution, cutting test run time significantly.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
send_ipc_message() wrote JSON and '\n' in two separate write_all calls.
When cargo test runs with --test-threads=4, the mock server can read the
JSON in the first syscall, respond, and close the stream before the
second write_all('\n') completes, causing EPIPE / Broken pipe.

Fix: concatenate JSON + newline into a single string and send in one
write_all call. The server receives a complete newline-delimited frame
atomically, eliminating the race window.

Affects: test_step_up_ipc_denied (pam-prmana sudo unit tests)

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
…DR-019

ADR-021 is now Accepted after a second-pass adversarial review. The ADR
splits SCIM hardening into Decision A (v1.0-blocking single-process
hardening — startup transport policy, request-shaping middleware, audit
chain integration, dry_run removal, systemd unit fix) and Decision B
(post-v1.0 helper-based privilege separation via AF_UNIX + SO_PEERCRED +
versioned RPC). Decision A is specified but not yet implemented; the ADR
now includes an Implementation Status section forbidding any "privilege
separation" marketing claim until Decision B ships.

Redlines applied from the second-pass review:

- Implementation Status section naming the gap between spec and code
- §A1: TLS fail-closed on missing/unreadable key material, rustls-via-
  axum-server named, TLS 1.3 default cipher policy, no silent fallback
- §A2: untrusted-peer behavior (strip X-Forwarded-*, audit
  forwarded_headers_stripped=true, never reject)
- §A3: new middleware layers (header size limit, TCP read-idle timeout,
  keep-alive idle timeout); discovery endpoint carveout for
  /ServiceProviderConfig and /Schemas; rate-limiter library choice
  (tower-governor + composite key extractor) flagged as multi-day work;
  defaults relabeled "illustrative"; Retry-After required on 429 and 503
- §A4: peer_addr/client_addr authoritativeness; rejection event types
  (rate_limited, payload_too_large, header_too_large, concurrency_exceeded,
  request_timeout, read_idle_timeout); audit stream locked to the ADR-010
  HMAC chain via a shared prmana-audit crate
- §A5: hard decision to delete dry_run field entirely; test migration to
  FakeAccountBackend via with_account_backend
- §A6: explicit 500-for-ops-failures vs 503-reserved-for-concurrency-and-
  helper contract
- §B1: reconciliation expansion (orphan mapping, orphan account, timeout)
  with x-prmana-* discovery fields
- §B2: prmana-scim is Linux-only; no launchd/rc.d units
- §B5: PrivateUsers=no is the default; IPAddressDeny= fail-closed via
  AssertKernelVersion= / ConditionSecurity=ip_filter
- §Effect on ADR-019: ADR-019 must carry inline supersession notes

ADR-019 is edited in three places to carry "Superseded by ADR-021"
inline notes on the capability-dropping (§4), rate-limiting (§5), and
TLS (§6) claims that describe behavior not present in the current code.

ADR index updated to reflect the Accepted status.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
…-021

The README's "Production-ready security" bullet previously listed "Rate
limiting, JTI replay protection, structured audit logging" as a blanket
claim. Rate limiting exists in pam-prmana/src/security/rate_limit.rs
(PAM auth-attempt limits) but does NOT exist in prmana-scim — SCIM has
none of the request-shaping controls specified in ADR-021 §A3. The old
phrasing was ambiguous in a way that would lead a reader to assume
SCIM has protections it does not.

Changes:

- README "Production-ready security" → "PAM-path defenses" with an
  explicit pointer to the new SCIM Service Hardening Status subsection.
- README Security Design section → a scope-note callout at the top
  directing SCIM deployers to the new subsection before deploying.
- README new "SCIM Service Hardening Status" subsection enumerating
  what works today, what ADR-021 Decision A specifies but does not yet
  ship, what Decision B defers to post-v1.0, the explicit prohibition
  on "privilege separation" marketing until Decision B ships, and the
  Linux-only platform scope.
- SECURITY Defense-in-Depth bullet 4 "Minimal Privileges" → now scopes
  the claim to the PAM module and agent daemon and explains why
  prmana-scim runs as root.
- SECURITY new "SCIM Service Hardening Status" section including an
  Implication-for-deployment compensating-control checklist (loopback
  bind, reverse-proxy-terminated TLS, proxy-layer rate limits, network
  policy restriction) for operators running SCIM before DT-SCIM ships.
- SECURITY Supported Versions table: 0.1.x → 1.0.x (current release
  under ADR-021 Decision A), < 1.0 (pre-rename unix-oidc) unsupported.
- SECURITY pre-deployment checklist SCIM item expanded from a one-liner
  into an 8-point sub-checklist covering loopback bind, reverse-proxy
  TLS, network policy, reading ADR-021, and the anti-marketing-claim
  reminder.

The top-of-README "educational use only" disclaimer is retained
deliberately — v1.0 is still in the rc series and is not yet declared
ship-ready. Disclaimer will be revisited before cutting v1.0.0 GA.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
…dlock

test_c1_get_token_prints_exec_credential was hanging indefinitely in CI,
causing Pre-release Tests on v1.0.0-rc1 (run 24286961692) to hit the
15-minute job timeout after all build and packaging jobs had succeeded.

Root cause: the test is #[tokio::test] and spawns a mock agent via
tokio::spawn, which runs on the current tokio runtime. The test then
called std::process::Command::new(binary).output() — a blocking call
that pins the current runtime thread. The mock-agent task never got
scheduled to accept the child process's connection, so the child
prmana-kubectl hung waiting for the socket, and .output() blocked
forever waiting for the child. Classic async/blocking deadlock.

Fix:
1. Use tokio::process::Command instead of std::process::Command so the
   async command does not block the runtime thread and the mock-agent
   task can make progress.
2. Wrap the .output() await in a tokio::time::timeout of 30 seconds so
   any future regression in the agent handshake fails fast with a
   clear message instead of eating the 15-minute job budget.

Verified locally: test passes in 0.28s (vs. forever before the fix).

This unblocks cutting v1.0.0-rc2 after v1.0.0-rc1's Pre-release Tests
failure.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
The Check job in ci.yml (cargo fmt --all --check) was failing on main
because ~17 files across pam-prmana, prmana-agent, and prmana-kubectl
had accumulated formatting drift that was not caught by per-commit
pre-push checks. This commit runs cargo fmt --all on a clean tree and
commits only the formatting deltas, no functional changes.

Files touched (all formatting-only):
- pam-prmana: device_flow/client.rs, lib.rs, oidc/validation.rs,
  tests/adversarial_pentest.rs
- prmana-agent: askpass.rs, auth_code.rs, main.rs, metrics.rs,
  storage/migration.rs, storage/router.rs, tests/spire_integration.rs
- prmana-kubectl: commands.rs, exec_credential.rs, ipc_client.rs,
  kubeconfig.rs, socket_path.rs, tests/integration.rs

Verified clean with cargo fmt --all --check.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
… deadline

Two unrelated main-CI unblocks bundled together:

1. .github/workflows/kubectl-e2e.yml — "Unit tests (prmana-kubectl +
   audience isolation)" was failing at "Build workspace" because the
   runner did not have libdbus-1-dev installed, so libdbus-sys v0.2.7's
   pkg_config build script failed. Same issue and same fix as the one
   applied to release.yml in commit 8ad1523. Adds the same apt install
   step to both jobs in kubectl-e2e.yml: unit-tests and kubectl-e2e.

2. prmana-agent/tests/daemon_lifecycle.rs — test_daemon_lifecycle was
   flaking on GHA macos-aarch64 with "Daemon did not exit within 5
   seconds after Shutdown". The 5-second deadline measured only the
   gap between sending the shutdown command and the parent process's
   try_wait() observing the exit. On slow GHA macos-aarch64 runners
   this budget is too tight even though the daemon does exit correctly
   (verified locally — 5.64s end-to-end on a fast Apple Silicon
   machine, right at the old deadline).

   Bumps the deadline to 30 seconds with a comment explaining the
   runner-speed sensitivity and why 5s was the wrong threshold. The
   new deadline is still strict enough to catch a genuine hang (the
   expected exit latency is sub-second on any realistic machine) but
   absorbs GHA runner variance.

Both fixes are independent of rc2 tag — this is main-branch CI hygiene
to make future PRs land cleanly.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
…nd trait

Substantial hardening pass on prmana-scim covering authorization, state
durability, and testability. This is the "recent hardening work" ADR-021
§Context refers to as already complete — committing it explicitly.

Authorization (prmana-scim/src/auth.rs):

- Adds a required_entitlement check to AuthMode::Validated alongside the
  existing iss/aud/exp/signature validation. Accepts the configured
  entitlement value from any of the five common claim shapes IdPs
  actually ship: top-level scope/scp/roles, realm_access.roles,
  resource_access[oidc_audience].roles. A StringOrList enum handles
  both space-separated and array-shaped scope/scp.
- Returns 401 + "Insufficient privileges" when the claim is missing,
  with a WARN log line carrying issuer/audience/required_entitlement.
- Tests (positive + negative):
  test_validated_mode_rejects_token_missing_required_entitlement,
  test_validated_mode_accepts_required_scope,
  test_validated_mode_accepts_required_role.

Persistent state (prmana-scim/src/provisioner.rs):

- Introduces AccountBackend trait with SystemAccountBackend (production:
  subprocess useradd/usermod/userdel + NSS lookup via `uzers`) and
  FakeAccountBackend (tests). Provisioner::new() returns the production
  path; tests use with_account_backend to inject the fake.
- {SCIM id <-> ScimUser} mapping persists to a JSON state file:
  atomic temp+rename, mode 0600 on file, mode 0700 on parent dir,
  UUID-suffixed temp name. Load enforces persisted SCIM id matches the
  map key and rejects drift.
- create_user now rejects if a system account with that name already
  exists in NSS (not just the in-memory store).
- replace_user rejects userName changes via UsernameImmutable error
  (Unix usernames are load-bearing; SCIM rename is unsafe).
- replace_user preserves original `created` timestamp in meta.
- list_users filters out SCIM entries whose backing system account has
  disappeared (drift detection).
- Tests (positive + negative): persists-across-restart, duplicate-for-
  existing-system-user, replace-updates-backend-and-state, replace-
  nonexistent, delete-after-restart, list-filters-missing-accounts,
  dry_run-keeps-persisted-state, plus existing username validation.

Config (prmana-scim/src/config.rs):

- Adds required_entitlement: String (default "scim:provision").
- Adds state_file: String (default "/var/lib/prmana/scim-users.json").

Startup (prmana-scim/src/main.rs):

- Refuses to start if required_entitlement is empty.
- Logs issuer + required_entitlement at startup.
- Propagates Provisioner::new() state-file errors as fatal.

Note: dry_run remains a runtime config field here. ADR-021 §A5 (Accepted
2026-04-11) now specifies deleting it entirely; that removal is tracked
as phase DT-SCIM-05 and is deliberately not part of this commit.

Verified locally on macOS: cargo fmt clean, cargo clippy
--all-targets --all-features -- -D warnings clean, 44/44 prmana-scim
tests passing.

Co-Authored-By: Codex
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Unblock and green-light the full CI matrix:
- Pin all GitHub Actions to commit SHAs with least-privilege tokens
- Fix Keycloak E2E: pam_env token delivery, auth-phase chain
- Fix TPM: swtpm native install, TCTI mssim, KDF scheme, idempotent provision
- Fix SPIFFE: camelCase flags, distroless sidecar, test filter
- Fix CIBA: binding_message encoding, defensive script rewrite, channel skip
- Fix Auth0: preferred_username multi-key lookup
- Serialize Check unit tests to eliminate env-var race

Namespace audit (unix-oidc → prmana):
- Rename Chef cookbook and Puppet module to prmana
- Remove legacy Ansible unix_oidc role
- Rename logrotate config, update CODEOWNERS team name
- Fix prmana.dev → prmana.com in docs and tests
- Update presentation product name

Also includes:
- HTTPS endpoint policy + canonical runtime socket paths
- Fail-closed installer signature verification
- Claude/Gemini file-based dialogue sync script

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Remove || true masks from 3 E2E tests in CI (dpop-nonce, session
  lifecycle, systemd) — tests must fail visibly now that CI is green
- Enforce rustdoc -D warnings (was -W) and fix all 12 doc warnings:
  bare URLs, unresolved intra-doc links, unclosed HTML tags
- Verified: cargo fmt, clippy -D warnings, and rustdoc -D warnings
  all pass cleanly

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Product boundary (locked):
- OSS (Apache-2.0): prmana-core, pam-prmana, prmana-agent
  SSH login, device flow, auth code, DPoP, software/YubiKey/TPM signing,
  local policy, break-glass, local audit
- Enterprise (proprietary): enterprise/
  SCIM, kubectl, sudo step-up, approval workflows, CIBA, multi-IdP
  failover, token exchange, SPIFFE/SPIRE, fleet/posture/compliance

Structural changes:
- New crate: prmana-core (OIDC discovery + JWKS types)
- prmana-agent runtime dependency on pam-prmana fully severed
  (now depends on prmana-core; pam-prmana retained as dev-dep only)
- Enterprise modules excised from pam-prmana:
  approval/, ciba/, evidence.rs, sudo.rs, bin/evidence_export.rs
- Enterprise modules excised from prmana-agent:
  failover.rs, exchange.rs, spire/, attestation_pop.rs, spire_signer.rs
- Enterprise crates relocated: prmana-scim, prmana-kubectl → enterprise/crates/
- Enterprise docs, deploy templates, test fixtures, packaging → enterprise/
- License: Apache-2.0 (OSS), proprietary (enterprise/)
- README rewritten for OSS product
- CLAUDE.md updated with OSS/enterprise boundary section

All tests pass (866 passed, 0 failed). Clippy clean. Fmt clean.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Updates the requirements on [cryptography](https://github.com/pyca/cryptography), [pytest](https://github.com/pytest-dev/pytest) and [pytest-cov](https://github.com/pytest-dev/pytest-cov) to permit the latest version.

Updates `cryptography` to 46.0.7
- [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst)
- [Commits](pyca/cryptography@41.0.0...46.0.7)

Updates `pytest` to 8.4.2
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](pytest-dev/pytest@7.0.0...8.4.2)

Updates `pytest-cov` to 7.1.0
- [Changelog](https://github.com/pytest-dev/pytest-cov/blob/master/CHANGELOG.rst)
- [Commits](pytest-dev/pytest-cov@v4.0.0...v7.1.0)

---
updated-dependencies:
- dependency-name: cryptography
  dependency-version: 46.0.7
  dependency-type: direct:production
  dependency-group: python-all
- dependency-name: pytest
  dependency-version: 8.4.2
  dependency-type: direct:development
  dependency-group: python-all
- dependency-name: pytest-cov
  dependency-version: 7.1.0
  dependency-type: direct:development
  dependency-group: python-all
...

Signed-off-by: dependabot[bot] <support@github.com>
@dependabot @github
Copy link
Copy Markdown
Contributor Author

dependabot Bot commented on behalf of github Apr 13, 2026

Labels

The following labels could not be found: dependencies, python. Please create them before Dependabot can add them to a pull request.

Please fix the above issues or remove invalid values from dependabot.yml.

@dependabot @github
Copy link
Copy Markdown
Contributor Author

dependabot Bot commented on behalf of github Apr 13, 2026

This pull request was built based on a group rule. Closing it will not ignore any of these versions in future pull requests.

To ignore these dependencies, configure ignore rules in dependabot.yml

@dependabot dependabot Bot deleted the dependabot/pip/python-oauth-dpop/python-all-03d55aadeb branch April 13, 2026 17:56
prodnull added a commit to Strykar/prmana that referenced this pull request Apr 19, 2026
Three maintainer fixes on top of @Strykar's review-response commit:

1. format_claims: skip oversized pairs whole rather than truncate mid-
   escape. The previous out.truncate(MAX_PAYLOAD) could land between
   '%' and '3D', handing a corrupt percent-escape to decoders. Now the
   function pre-computes each encoded pair length and skips ones that
   won't fit whole. Later pairs still get a chance to fit, so payloads
   with one oversized claim still include shorter subsequent claims.

2. Add negative test for the @us refusal path. publish() is refactored
   to delegate to publish_with_detector() which takes a pluggable
   is_shared detector. The public API is unchanged; the test injects
   || true and asserts KeyringError::SharedSessionKeyring is returned
   before any kernel state is created. Corresponds to invariant prodnull#1 in
   ADR-026.

3. Drop CString::new("user").unwrap() in favour of the c-string literal
   c"user". No runtime allocation, no unwrap path. Fixes a clippy
   unwrap_used violation the crate's #![deny(clippy::unwrap_used)]
   would otherwise catch.

New tests added:
 - format_claims_skips_oversized_pair_whole
 - format_claims_never_truncates_mid_escape
 - format_claims_fits_typical_payload
 - publish_refuses_shared_session_keyring
 - publish_proceeds_when_session_is_isolated

Verified locally: cargo fmt --check, cargo clippy --all-targets
--all-features -- -D warnings (macOS + Linux), and the full pam-prmana
keyring test suite (9/9 pass on Linux).

Refs: prodnull#14, ADR-026.

Co-Authored-By: Avinash H. Duduskar <Strykar@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
prodnull added a commit that referenced this pull request Apr 19, 2026
…rk policy from OIDC claims (#14)

* feat(pam): publish session claims to a kernel-keyring entry

Signed-off-by: Strykar <2946372+Strykar@users.noreply.github.com>

* feat(pam): add pam_authnft interop — enrich keyring payload and correlation token

Signed-off-by: Strykar <2946372+Strykar@users.noreply.github.com>
Co-Authored-By: Claude Opus

* fix(keyring): address review blockers (#14)

1. Remove AUTHNFT_CORRELATION export — consumer-agnostic
2. Detect shared @us keyring, refuse to publish
3. Close TOCTOU: publish to @p, lock down, then KEYCTL_LINK
4. Versioned payload (v=1;) with percent-encoded delimiters
5. #[cfg(target_os = "linux")] on keyring module and call site

Co-Authored-By: Claude Opus

* fix(keyring): polish format_claims truncation and add negative test

Three maintainer fixes on top of @Strykar's review-response commit:

1. format_claims: skip oversized pairs whole rather than truncate mid-
   escape. The previous out.truncate(MAX_PAYLOAD) could land between
   '%' and '3D', handing a corrupt percent-escape to decoders. Now the
   function pre-computes each encoded pair length and skips ones that
   won't fit whole. Later pairs still get a chance to fit, so payloads
   with one oversized claim still include shorter subsequent claims.

2. Add negative test for the @us refusal path. publish() is refactored
   to delegate to publish_with_detector() which takes a pluggable
   is_shared detector. The public API is unchanged; the test injects
   || true and asserts KeyringError::SharedSessionKeyring is returned
   before any kernel state is created. Corresponds to invariant #1 in
   ADR-026.

3. Drop CString::new("user").unwrap() in favour of the c-string literal
   c"user". No runtime allocation, no unwrap path. Fixes a clippy
   unwrap_used violation the crate's #![deny(clippy::unwrap_used)]
   would otherwise catch.

New tests added:
 - format_claims_skips_oversized_pair_whole
 - format_claims_never_truncates_mid_escape
 - format_claims_fits_typical_payload
 - publish_refuses_shared_session_keyring
 - publish_proceeds_when_session_is_isolated

Verified locally: cargo fmt --check, cargo clippy --all-targets
--all-features -- -D warnings (macOS + Linux), and the full pam-prmana
keyring test suite (9/9 pass on Linux).

Refs: #14, ADR-026.

Co-Authored-By: Avinash H. Duduskar <Strykar@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Signed-off-by: Strykar <2946372+Strykar@users.noreply.github.com>
Co-authored-by: prmana Developers <prodnull@users.noreply.github.com>
Co-authored-by: Avinash H. Duduskar <Strykar@users.noreply.github.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant