capauth 0.3.2__tar.gz → 0.3.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {capauth-0.3.2 → capauth-0.3.3}/PKG-INFO +1 -1
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/pairing/proof.py +36 -6
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth.egg-info/PKG-INFO +1 -1
- {capauth-0.3.2 → capauth-0.3.3}/tests/test_enrollment_proof_helper.py +86 -4
- {capauth-0.3.2 → capauth-0.3.3}/.cursorrules +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/.dockerignore +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/.github/workflows/ci.yml +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/.github/workflows/docs-check.yml +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/.github/workflows/nextcloud-appstore.yml +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/.github/workflows/publish.yml +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/.github/workflows/pytest.yml +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/.github/workflows/secret-scan.yml +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/.gitignore +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/.gitleaks-baseline.json +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/AGENTS.md +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/AI-ADVOCATE.md +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/ARCHITECTURE.md +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/CHANGELOG.md +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/CLAUDE.md +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/CODE_OF_CONDUCT.md +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/CONTRIBUTING.md +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/Dockerfile +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/Dockerfile.authentik-capauth +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/LICENSE +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/MANIFEST.in +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/MISSION.md +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/README.md +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/SECURITY.md +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/SKILL.md +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/SOP.md +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/authentik-custom/capauth_migrate.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/authentik-custom/imghdr.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/authentik-custom/user_settings.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/bin/cli.js +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/browser-extension/.gitignore +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/browser-extension/README.md +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/browser-extension/RELEASING.md +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/browser-extension/background.js +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/browser-extension/content_scripts/autofill.js +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/browser-extension/content_scripts/cross_origin_signing.js +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/browser-extension/content_scripts/detector.js +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/browser-extension/content_scripts/provider.js +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/browser-extension/content_scripts/provider_bridge.js +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/browser-extension/icons/icon.svg +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/browser-extension/icons/icon128.png +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/browser-extension/icons/icon16.png +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/browser-extension/icons/icon48.png +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/browser-extension/lib/bunker-e2e.js +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/browser-extension/lib/keyqr.js +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/browser-extension/lib/keyvault.js +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/browser-extension/lib/openpgp.js +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/browser-extension/lib/signer-backends.js +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/browser-extension/manifest.firefox.json +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/browser-extension/manifest.json +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/browser-extension/native-host/capauth_signer.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/browser-extension/native-host/com.capauth.signer.json +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/browser-extension/native-host/install.sh +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/browser-extension/options/options.html +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/browser-extension/options/options.js +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/browser-extension/package-lock.json +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/browser-extension/package.json +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/browser-extension/popup/popup.css +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/browser-extension/popup/popup.html +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/browser-extension/popup/popup.js +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/browser-extension/scripts/build.js +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/browser-extension/scripts/generate-icons.js +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/browser-extension/stages/AuthenticatorSelectionStage.js +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/browser-extension/stages/CapAuthStage.js +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/browser-extension/stages/QRDisplayStage.js +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/browser-extension/stages/SignatureVerificationStage.js +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/browser-extension/stages/StagePipeline.js +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/browser-extension/submission/STORE_LISTING.md +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/browser-extension/submission/privacy-policy.md +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/browser-extension/tests/fixtures/test_key.json +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/browser-extension/tests/unit/background.test.js +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/browser-extension/tests/unit/bunker_e2e.test.js +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/browser-extension/tests/unit/detector.test.js +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/browser-extension/tests/unit/keyqr.test.js +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/browser-extension/tests/unit/keyvault.test.js +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/browser-extension/tests/unit/openpgp.test.js +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/browser-extension/tests/unit/provider_api.test.js +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/browser-extension/tests/unit/provider_tierb.test.js +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/browser-extension/tests/unit/remote_bunker.test.js +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/browser-extension/tests/unit/signer_backends.test.js +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/browser-extension/vitest.config.js +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/deploy/capauth-service/.env.example +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/deploy/capauth-service/deploy.sh +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/deploy/capauth-service/docker-compose.yml +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/deploy/capauth-service/systemd/capauth-backup.service +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/deploy/capauth-service/systemd/capauth-backup.timer +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/deploy/forgejo-capauth/.env.example +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/deploy/forgejo-capauth/docker-compose.yml +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/deploy/forgejo-capauth/preflight.sh +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/docs/AIRGAPPED_SIGNING_WORKSTATION.md +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/docs/ARCHITECTURE.md +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/docs/AUTHENTIK_CUSTOM_STAGE.md +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/docs/AUTHENTIK_DEPLOYMENT_SKSSO.md +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/docs/AUTHENTIK_FORGEJO_DEPLOYMENT.md +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/docs/AUTHENTIK_STRATEGY_DECISION.md +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/docs/CAPAUTH_BUNKER_REMOTE_SIGNER.md +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/docs/CAPAUTH_OIDC_IDP.md +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/docs/CLAIMS.md +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/docs/COLD_MACHINE_BOOTSTRAP_AND_DR.md +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/docs/CRYPTO_SPEC.md +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/docs/ENTERPRISE_MANAGED_KEYS.md +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/docs/INTEGRATION_BLUEPRINT.md +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/docs/M0-capauth-api-v1.md +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/docs/M0-capauth-importer-inventory.md +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/docs/PQC_CAPAUTH_REVISIT.md +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/docs/PQC_ROOT_MIGRATION.md +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/docs/PROTOCOL.md +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/docs/ROOT_ROTATION_CEREMONY.md +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/docs/TRUST_GRAPH_COORD_PROJECTION.md +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/docs/ZERO_KNOWLEDGE_PROFILE.md +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/docs/authentik-capauth.md +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/docs/deploy-plan/capauth-bulletproof-deploy.md +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/index.d.ts +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/index.js +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/openclaw-plugin.archived-2026-04-23/package.json +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/openclaw-plugin.archived-2026-04-23/src/index.ts +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/openclaw-plugin.archived-2026-04-23/src/openclaw.plugin.json +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/package.json +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/phone-signer/app.js +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/phone-signer/icons/icon-192.png +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/phone-signer/icons/icon-512.png +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/phone-signer/index.html +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/phone-signer/lib/bunker-e2e.js +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/phone-signer/lib/bunker-signer.js +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/phone-signer/lib/canonical.js +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/phone-signer/lib/keyqr.js +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/phone-signer/lib/keyvault.js +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/phone-signer/manifest.webmanifest +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/phone-signer/sw.js +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/phone-signer/vendor/openpgp.min.js +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/phone-signer/vendor/qrcode-generator.js +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/pyproject.toml +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/ruff-0.15.4-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/scripts/build_authentik_capauth_image.sh +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/scripts/capauth-backup.sh +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/scripts/capauth-restore.sh +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/scripts/migrate_canonical_subjects.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/scripts/pqc_ceremony_dryrun.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/scripts/provision_agent_profiles.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/setup.cfg +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/skill.yaml +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/__init__.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/agent_identity.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/apps.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/authentik/__init__.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/authentik/api.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/authentik/blueprints/capauth-pgp-login.yaml +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/authentik/claims_mapper.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/authentik/nonce_store.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/authentik/stage.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/authentik/urls.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/authentik/verifier.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/authz.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/cli.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/crypto/__init__.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/crypto/base.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/crypto/gnupg_backend.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/crypto/pgpy_backend.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/crypto/sequoia_backend.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/crypto/skpgp_backend.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/custody.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/did.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/discovery/__init__.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/discovery/base.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/discovery/file_discovery.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/discovery/mdns.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/discovery/syncthing.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/exceptions.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/identity.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/identity_class.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/integration.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/integrations/__init__.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/integrations/forgejo/__init__.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/integrations/forgejo/auth_flow.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/integrations/forgejo/cli.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/integrations/forgejo/config.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/integrations/forgejo/forgejo_api.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/integrations/forgejo/oidc_provider.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/integrations/forgejo/tests/__init__.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/integrations/forgejo/tests/test_auth_flow.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/integrations/forgejo/tests/test_cli.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/integrations/forgejo/tests/test_config.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/integrations/forgejo/tests/test_forgejo_api.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/integrations/forgejo/tests/test_oidc_provider.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/integrations/nextcloud/.gitignore +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/integrations/nextcloud/.nextcloudignore +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/integrations/nextcloud/CSR-PR.md +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/integrations/nextcloud/INFO-XML-CHANGES.md +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/integrations/nextcloud/PUBLISHING.md +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/integrations/nextcloud/README.md +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/integrations/nextcloud/appinfo/info.xml +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/integrations/nextcloud/appinfo/routes.php +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/integrations/nextcloud/build-release.sh +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/integrations/nextcloud/certificates/.gitignore +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/integrations/nextcloud/certificates/capauth.crt +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/integrations/nextcloud/certificates/capauth.csr +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/integrations/nextcloud/composer.json +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/integrations/nextcloud/css/login.css +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/integrations/nextcloud/js/login.js +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/integrations/nextcloud/krankerl.toml +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/integrations/nextcloud/lib/AlternativeLogin/CapAuthLogin.php +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/integrations/nextcloud/lib/AppInfo/Application.php +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/integrations/nextcloud/lib/BackgroundJob/PruneExpiredNonces.php +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/integrations/nextcloud/lib/Controller/LoginController.php +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/integrations/nextcloud/lib/Controller/TokenController.php +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/integrations/nextcloud/lib/Db/KeyRegistry.php +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/integrations/nextcloud/lib/Exception/CapAuthUnauthorizedException.php +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/integrations/nextcloud/lib/Middleware/PgpVerificationMiddleware.php +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/integrations/nextcloud/lib/Migration/Version000300Date20260301000000.php +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/integrations/nextcloud/lib/Provider/CapAuthProvider.php +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/integrations/nextcloud/lib/Service/ChallengeService.php +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/integrations/nextcloud/lib/Service/GroupSyncService.php +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/integrations/nextcloud/lib/Service/UserProvisioningService.php +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/integrations/nextcloud/lib/Service/VerifierService.php +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/integrations/nextcloud/lib/User/Backend.php +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/integrations/nextcloud/phpunit.xml +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/integrations/nextcloud/screenshots/README.md +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/integrations/nextcloud/screenshots/login.png +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/integrations/nextcloud/templates/login.php +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/integrations/nextcloud/tests/bootstrap.php +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/integrations/nextcloud/tests/integration/FullAuthFlowTest.php +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/integrations/nextcloud/tests/oidc/oidc_e2e_login_test.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/integrations/nextcloud/tests/unit/Controller/LoginControllerTest.php +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/integrations/nextcloud/tests/unit/Db/KeyRegistryTest.php +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/integrations/nextcloud/tests/unit/Provider/CapAuthProviderTest.php +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/integrations/nextcloud/tests/unit/Service/ChallengeServiceTest.php +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/integrations/nextcloud/tests/unit/Service/VerifierServiceTest.php +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/integrations/nextcloud/tests/unit/User/BackendTest.php +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/key_transparency.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/login.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/manifest.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/mesh.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/migrations/0001_initial.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/migrations/0002_widen_fingerprint_to_64.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/migrations/__init__.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/models.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/pairing/__init__.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/pairing/canonicalize.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/pairing/kernel.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/pairing/operator_session.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/pairing/records.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/pairing/store.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/pairing/window.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/pma.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/pqc_confidentiality.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/pqc_identity.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/pqc_root_identity.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/pqc_tokens.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/profile.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/provisioning.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/registry.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/seal.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/service/__init__.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/service/app.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/service/bunker.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/service/bunker_e2e.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/service/keystore.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/service/oidc/__init__.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/service/oidc/clients.example.json +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/service/oidc/clients.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/service/oidc/passkey.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/service/oidc/provider.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/service/oidc/signing_key.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/service/oidc/store.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/service/push.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/service/server.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/subject.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/sync.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/testing.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/tokens.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/trust/__init__.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/trust/calibration.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth/trust/graph.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth.egg-info/SOURCES.txt +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth.egg-info/dependency_links.txt +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth.egg-info/entry_points.txt +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth.egg-info/requires.txt +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/src/capauth.egg-info/top_level.txt +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/stages/ak-stage-capauth/.gitignore +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/stages/ak-stage-capauth/package-lock.json +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/stages/ak-stage-capauth/package.json +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/stages/ak-stage-capauth/src/CapAuthStage.test.js +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/stages/ak-stage-capauth/src/CapAuthStage.vue +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/stages/ak-stage-capauth/src/index.js +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/stages/ak-stage-capauth/vite.config.js +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/tests/__init__.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/tests/conftest.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/tests/fixtures/bunker_e2e_v1_vector.json +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/tests/fixtures/canonical_nonce_v2_vector.json +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/tests/test_agent_identity.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/tests/test_agentrun_capabilities.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/tests/test_audience_mint_helper.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/tests/test_audience_tokens.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/tests/test_authz.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/tests/test_authz_legacy_grace.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/tests/test_authz_signature_gate.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/tests/test_backup_restore.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/tests/test_bunker.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/tests/test_bunker_e2e.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/tests/test_canonicalize.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/tests/test_capauth_service_deploy.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/tests/test_change_capabilities.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/tests/test_claims_mapper.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/tests/test_crypto.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/tests/test_custody.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/tests/test_device_key_proof.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/tests/test_did_capability_relationships.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/tests/test_fingerprint_v6.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/tests/test_forgejo_preflight.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/tests/test_home_resolution.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/tests/test_identity.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/tests/test_identity_class.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/tests/test_identity_ttl.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/tests/test_integration.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/tests/test_key_revocation_expiry.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/tests/test_key_transparency.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/tests/test_login.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/tests/test_manifest.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/tests/test_mesh.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/tests/test_models_pqc_q0.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/tests/test_nextcloud_app.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/tests/test_no_subapp_dependency.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/tests/test_nonce_store.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/tests/test_oidc_idp.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/tests/test_oidc_idp_e2e.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/tests/test_operator_session.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/tests/test_pairing.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/tests/test_pairing_base_dir_env.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/tests/test_passkey.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/tests/test_pma.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/tests/test_pqc_confidentiality.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/tests/test_pqc_identity.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/tests/test_pqc_root_integration.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/tests/test_pqc_t3_gate.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/tests/test_pqc_tokens.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/tests/test_profile.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/tests/test_provisioning.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/tests/test_push.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/tests/test_py313_compat.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/tests/test_qr_login.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/tests/test_real_pgp_e2e.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/tests/test_register_cli.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/tests/test_registry.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/tests/test_seal.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/tests/test_sequoia_backend.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/tests/test_service.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/tests/test_service_authz_decide.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/tests/test_service_v6_fingerprint.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/tests/test_skpgp_backend.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/tests/test_subject.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/tests/test_syncthing_discovery.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/tests/test_testing_helper.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/tests/test_token_gc.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/tests/test_token_store_flag.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/tests/test_tokens.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/tests/test_trust_calibration.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/tests/test_trust_graph.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/tests/test_trust_graph_coord_audit.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/tests/test_verifier.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/tests/test_version_honesty.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/tests/test_zk_profile.py +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/tools/build-sq.sh +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/urllib.error +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/web/README.md +0 -0
- {capauth-0.3.2 → capauth-0.3.3}/web/stages/capauth/CapAuthStage.ts +0 -0
|
@@ -173,6 +173,36 @@ def _is_pgp(key: Optional[str]) -> bool:
|
|
|
173
173
|
return "BEGIN PGP" in (key or "")
|
|
174
174
|
|
|
175
175
|
|
|
176
|
+
def _require_subject(subject: Optional[str]) -> str:
|
|
177
|
+
"""Reject an absent or blank subject, loudly, at the call.
|
|
178
|
+
|
|
179
|
+
``subject`` is a REQUIRED keyword on every public builder here, but a caller
|
|
180
|
+
can still hand us ``None`` at runtime (an Optional threaded down from its own
|
|
181
|
+
config, a dict lookup that missed). Falling back to a derived default there
|
|
182
|
+
is the one thing this module must never do.
|
|
183
|
+
|
|
184
|
+
Why: the challenge binds the subject, so a proof built for subject A does not
|
|
185
|
+
verify for subject B. If the builder quietly substituted its own default
|
|
186
|
+
while ``enroll_device`` was called with the caller's real subject, the device
|
|
187
|
+
would sign honestly, capauth would reject the proof, and the enrollment would
|
|
188
|
+
land on the TOFU floor behind a success response with nothing raised. That is
|
|
189
|
+
exactly the silent downgrade card N10 exists to remove.
|
|
190
|
+
|
|
191
|
+
This bit for real: capauth's derived default is the full 40-char
|
|
192
|
+
``fingerprint_for`` value, while skchat's own derivation is a 16-char device
|
|
193
|
+
id. Two individually reasonable defaults, different signed bytes, and the
|
|
194
|
+
mismatch is invisible until the security boundary rejects it. Caught in
|
|
195
|
+
review by clawd-43 on 2026-08-17 before it shipped to a caller.
|
|
196
|
+
"""
|
|
197
|
+
if subject is None or not str(subject).strip():
|
|
198
|
+
raise ProofSigningError(
|
|
199
|
+
"subject is required: the enrollment challenge binds it, so it must be "
|
|
200
|
+
"the SAME subject you pass to enroll_device(). Deriving one here would "
|
|
201
|
+
"silently change the signed bytes and downgrade the enrollment to tofu."
|
|
202
|
+
)
|
|
203
|
+
return str(subject)
|
|
204
|
+
|
|
205
|
+
|
|
176
206
|
def _resolve_subject(pubkey: str, subject: Optional[str]) -> tuple[str, str]:
|
|
177
207
|
"""Derive ``(fingerprint, canonical_subject)`` exactly as ``enroll_device`` will.
|
|
178
208
|
|
|
@@ -208,7 +238,7 @@ def _coerce_mode(mode: EnrollmentMode | str) -> EnrollmentMode:
|
|
|
208
238
|
def enrollment_challenge(
|
|
209
239
|
pubkey: str,
|
|
210
240
|
*,
|
|
211
|
-
subject:
|
|
241
|
+
subject: str,
|
|
212
242
|
mode: EnrollmentMode | str = EnrollmentMode.VERIFIED,
|
|
213
243
|
) -> bytes:
|
|
214
244
|
"""The exact bytes an enrollment's proof must sign, from the PUBLIC key alone.
|
|
@@ -245,7 +275,7 @@ def enrollment_challenge(
|
|
|
245
275
|
PairingError: If ``mode`` is not a known enrollment mode.
|
|
246
276
|
"""
|
|
247
277
|
resolved = _coerce_mode(mode)
|
|
248
|
-
fingerprint, canonical = _resolve_subject(pubkey, subject)
|
|
278
|
+
fingerprint, canonical = _resolve_subject(pubkey, _require_subject(subject))
|
|
249
279
|
if resolved is EnrollmentMode.ATTESTED:
|
|
250
280
|
return attested_challenge(fingerprint, canonical)
|
|
251
281
|
if resolved is EnrollmentMode.VERIFIED:
|
|
@@ -340,8 +370,8 @@ def build_verified_proof(
|
|
|
340
370
|
pubkey: str,
|
|
341
371
|
*,
|
|
342
372
|
private_key: Any,
|
|
373
|
+
subject: str,
|
|
343
374
|
passphrase: str = "",
|
|
344
|
-
subject: Optional[str] = None,
|
|
345
375
|
) -> EnrollmentProof:
|
|
346
376
|
"""Sign the ``verified`` enrollment challenge with the device's OWN key.
|
|
347
377
|
|
|
@@ -379,7 +409,7 @@ def build_verified_proof(
|
|
|
379
409
|
capauth.exceptions.SubjectNamingError: If ``subject`` does not conform
|
|
380
410
|
to the canonical fqid grammar even after alias translation.
|
|
381
411
|
"""
|
|
382
|
-
fingerprint, canonical = _resolve_subject(pubkey, subject)
|
|
412
|
+
fingerprint, canonical = _resolve_subject(pubkey, _require_subject(subject))
|
|
383
413
|
challenge = verified_challenge(fingerprint, canonical)
|
|
384
414
|
signature = _sign(challenge, private_key, passphrase, pgp=_is_pgp(pubkey))
|
|
385
415
|
_self_check(pubkey, signature, challenge, what="verified proof")
|
|
@@ -398,8 +428,8 @@ def build_attested_proof(
|
|
|
398
428
|
*,
|
|
399
429
|
operator_pubkey: str,
|
|
400
430
|
operator_private_key: Any,
|
|
431
|
+
subject: str,
|
|
401
432
|
passphrase: str = "",
|
|
402
|
-
subject: Optional[str] = None,
|
|
403
433
|
) -> EnrollmentProof:
|
|
404
434
|
"""Sign the ``attested`` challenge with a VOUCHING OPERATOR's key.
|
|
405
435
|
|
|
@@ -440,7 +470,7 @@ def build_attested_proof(
|
|
|
440
470
|
capauth.exceptions.SubjectNamingError: If ``subject`` does not conform
|
|
441
471
|
to the canonical fqid grammar even after alias translation.
|
|
442
472
|
"""
|
|
443
|
-
fingerprint, canonical = _resolve_subject(pubkey, subject)
|
|
473
|
+
fingerprint, canonical = _resolve_subject(pubkey, _require_subject(subject))
|
|
444
474
|
challenge = attested_challenge(fingerprint, canonical)
|
|
445
475
|
signature = _sign(challenge, operator_private_key, passphrase, pgp=_is_pgp(operator_pubkey))
|
|
446
476
|
_self_check(operator_pubkey, signature, challenge, what="attestation")
|
|
@@ -155,10 +155,22 @@ def test_attested_proof_round_trips_through_enroll_device(tmp_path):
|
|
|
155
155
|
|
|
156
156
|
|
|
157
157
|
def test_helper_defaults_subject_to_the_device_fingerprint_like_enroll_device(tmp_path):
|
|
158
|
-
"""
|
|
158
|
+
"""An EXPLICIT subject on both sides agrees end to end.
|
|
159
|
+
|
|
160
|
+
This test used to omit ``subject`` and rely on the builder and
|
|
161
|
+
``enroll_device`` deriving the same default. That default was removed: two
|
|
162
|
+
individually reasonable defaults (capauth's 40-char fingerprint, skchat's
|
|
163
|
+
16-char device id) produce different signed bytes, and the mismatch is
|
|
164
|
+
invisible until the security boundary rejects it. The subject is now
|
|
165
|
+
required, so the agreement is asserted rather than assumed.
|
|
166
|
+
"""
|
|
159
167
|
bundle = _pgp_keypair()
|
|
168
|
+
subject = fingerprint_for(bundle.public_armor)
|
|
160
169
|
proof = build_verified_proof(
|
|
161
|
-
bundle.public_armor,
|
|
170
|
+
bundle.public_armor,
|
|
171
|
+
private_key=bundle.private_armor,
|
|
172
|
+
subject=subject,
|
|
173
|
+
passphrase=TEST_PASSPHRASE,
|
|
162
174
|
)
|
|
163
175
|
|
|
164
176
|
enrollment = enroll_device(
|
|
@@ -412,11 +424,19 @@ def test_building_with_a_WRONG_PASSPHRASE_raises():
|
|
|
412
424
|
def test_building_with_a_NON_KEY_raises_rather_than_returning_an_empty_proof():
|
|
413
425
|
bundle = _pgp_keypair()
|
|
414
426
|
with pytest.raises(ProofSigningError):
|
|
415
|
-
build_verified_proof(
|
|
427
|
+
build_verified_proof(
|
|
428
|
+
bundle.public_armor,
|
|
429
|
+
private_key="not a key at all",
|
|
430
|
+
subject=fingerprint_for(bundle.public_armor),
|
|
431
|
+
)
|
|
416
432
|
|
|
417
433
|
pubkey_b64, _ = _device_keypair()
|
|
418
434
|
with pytest.raises(ProofSigningError):
|
|
419
|
-
build_verified_proof(
|
|
435
|
+
build_verified_proof(
|
|
436
|
+
pubkey_b64,
|
|
437
|
+
private_key=b"-----BEGIN PRIVATE KEY-----\nnope\n",
|
|
438
|
+
subject=fingerprint_for(pubkey_b64),
|
|
439
|
+
)
|
|
420
440
|
|
|
421
441
|
|
|
422
442
|
def test_a_built_proof_is_never_empty():
|
|
@@ -430,3 +450,65 @@ def test_a_built_proof_is_never_empty():
|
|
|
430
450
|
assert proof.proof
|
|
431
451
|
assert dict(proof) == {"proof": proof.proof}
|
|
432
452
|
assert "operator_pubkey" not in dict(proof)
|
|
453
|
+
|
|
454
|
+
|
|
455
|
+
# --- subject is REQUIRED (regression: two reasonable defaults, different bytes) ---
|
|
456
|
+
|
|
457
|
+
|
|
458
|
+
def test_subject_is_required_on_every_public_builder():
|
|
459
|
+
"""A derived default here silently changes the SIGNED BYTES.
|
|
460
|
+
|
|
461
|
+
capauth's own default was the full 40-char `fingerprint_for` value. skchat,
|
|
462
|
+
the helper's first caller, derives a 16-char device id. Both defensible in
|
|
463
|
+
isolation. But a proof built with capauth's default, then handed to
|
|
464
|
+
`enroll_device` with skchat's real subject, does not verify: the device signs
|
|
465
|
+
honestly, capauth rejects, and the enrollment lands on the TOFU floor behind
|
|
466
|
+
a success response with nothing raised. That is the exact silent downgrade
|
|
467
|
+
card N10 exists to remove, reintroduced by the convenience meant to close it.
|
|
468
|
+
|
|
469
|
+
Caught in review by clawd-43 on 2026-08-17, before any caller shipped it.
|
|
470
|
+
"""
|
|
471
|
+
bundle = _pgp_keypair()
|
|
472
|
+
|
|
473
|
+
for call in (
|
|
474
|
+
lambda: enrollment_challenge(bundle.public_armor),
|
|
475
|
+
lambda: build_verified_proof(
|
|
476
|
+
bundle.public_armor,
|
|
477
|
+
private_key=bundle.private_armor,
|
|
478
|
+
passphrase=TEST_PASSPHRASE,
|
|
479
|
+
),
|
|
480
|
+
):
|
|
481
|
+
with pytest.raises(TypeError, match="subject"):
|
|
482
|
+
call()
|
|
483
|
+
|
|
484
|
+
|
|
485
|
+
@pytest.mark.parametrize("blank", [None, "", " "])
|
|
486
|
+
def test_an_explicitly_blank_subject_raises_rather_than_deriving_one(blank):
|
|
487
|
+
"""The signature makes it required; this makes a runtime None fail too.
|
|
488
|
+
|
|
489
|
+
A caller can still thread an Optional down from its own config and hand us
|
|
490
|
+
None. Falling back to a derived default there is the failure this module
|
|
491
|
+
must never have.
|
|
492
|
+
"""
|
|
493
|
+
bundle = _pgp_keypair()
|
|
494
|
+
|
|
495
|
+
with pytest.raises(ProofSigningError, match="subject is required"):
|
|
496
|
+
enrollment_challenge(bundle.public_armor, subject=blank)
|
|
497
|
+
|
|
498
|
+
with pytest.raises(ProofSigningError, match="subject is required"):
|
|
499
|
+
build_verified_proof(
|
|
500
|
+
bundle.public_armor,
|
|
501
|
+
private_key=bundle.private_armor,
|
|
502
|
+
subject=blank,
|
|
503
|
+
passphrase=TEST_PASSPHRASE,
|
|
504
|
+
)
|
|
505
|
+
|
|
506
|
+
|
|
507
|
+
def test_two_different_subjects_produce_different_challenges():
|
|
508
|
+
"""The property the whole guard exists to protect, asserted directly."""
|
|
509
|
+
bundle = _pgp_keypair()
|
|
510
|
+
full = fingerprint_for(bundle.public_armor)
|
|
511
|
+
|
|
512
|
+
assert enrollment_challenge(bundle.public_armor, subject=full) != enrollment_challenge(
|
|
513
|
+
bundle.public_armor, subject=full[:16]
|
|
514
|
+
), "challenge must bind the subject, or a subject mismatch would go unnoticed"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{capauth-0.3.2 → capauth-0.3.3}/openclaw-plugin.archived-2026-04-23/src/openclaw.plugin.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{capauth-0.3.2 → capauth-0.3.3}/ruff-0.15.4-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|