capauth 0.3.2__tar.gz → 0.3.4__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.4}/CHANGELOG.md +17 -0
- {capauth-0.3.2 → capauth-0.3.4}/PKG-INFO +3 -1
- {capauth-0.3.2 → capauth-0.3.4}/README.md +2 -0
- {capauth-0.3.2 → capauth-0.3.4}/SOP.md +25 -1
- capauth-0.3.4/docs/HUMAN_IDENTITY_SETUP_AND_ROTATION.md +149 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/agent_identity.py +4 -4
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/pairing/proof.py +36 -6
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth.egg-info/PKG-INFO +3 -1
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth.egg-info/SOURCES.txt +1 -0
- {capauth-0.3.2 → capauth-0.3.4}/tests/test_enrollment_proof_helper.py +86 -4
- {capauth-0.3.2 → capauth-0.3.4}/.cursorrules +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/.dockerignore +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/.github/workflows/ci.yml +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/.github/workflows/docs-check.yml +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/.github/workflows/nextcloud-appstore.yml +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/.github/workflows/publish.yml +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/.github/workflows/pytest.yml +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/.github/workflows/secret-scan.yml +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/.gitignore +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/.gitleaks-baseline.json +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/AGENTS.md +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/AI-ADVOCATE.md +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/ARCHITECTURE.md +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/CLAUDE.md +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/CODE_OF_CONDUCT.md +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/CONTRIBUTING.md +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/Dockerfile +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/Dockerfile.authentik-capauth +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/LICENSE +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/MANIFEST.in +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/MISSION.md +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/SECURITY.md +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/SKILL.md +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/authentik-custom/capauth_migrate.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/authentik-custom/imghdr.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/authentik-custom/user_settings.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/bin/cli.js +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/browser-extension/.gitignore +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/browser-extension/README.md +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/browser-extension/RELEASING.md +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/browser-extension/background.js +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/browser-extension/content_scripts/autofill.js +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/browser-extension/content_scripts/cross_origin_signing.js +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/browser-extension/content_scripts/detector.js +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/browser-extension/content_scripts/provider.js +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/browser-extension/content_scripts/provider_bridge.js +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/browser-extension/icons/icon.svg +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/browser-extension/icons/icon128.png +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/browser-extension/icons/icon16.png +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/browser-extension/icons/icon48.png +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/browser-extension/lib/bunker-e2e.js +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/browser-extension/lib/keyqr.js +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/browser-extension/lib/keyvault.js +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/browser-extension/lib/openpgp.js +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/browser-extension/lib/signer-backends.js +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/browser-extension/manifest.firefox.json +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/browser-extension/manifest.json +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/browser-extension/native-host/capauth_signer.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/browser-extension/native-host/com.capauth.signer.json +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/browser-extension/native-host/install.sh +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/browser-extension/options/options.html +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/browser-extension/options/options.js +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/browser-extension/package-lock.json +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/browser-extension/package.json +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/browser-extension/popup/popup.css +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/browser-extension/popup/popup.html +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/browser-extension/popup/popup.js +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/browser-extension/scripts/build.js +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/browser-extension/scripts/generate-icons.js +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/browser-extension/stages/AuthenticatorSelectionStage.js +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/browser-extension/stages/CapAuthStage.js +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/browser-extension/stages/QRDisplayStage.js +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/browser-extension/stages/SignatureVerificationStage.js +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/browser-extension/stages/StagePipeline.js +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/browser-extension/submission/STORE_LISTING.md +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/browser-extension/submission/privacy-policy.md +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/browser-extension/tests/fixtures/test_key.json +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/browser-extension/tests/unit/background.test.js +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/browser-extension/tests/unit/bunker_e2e.test.js +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/browser-extension/tests/unit/detector.test.js +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/browser-extension/tests/unit/keyqr.test.js +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/browser-extension/tests/unit/keyvault.test.js +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/browser-extension/tests/unit/openpgp.test.js +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/browser-extension/tests/unit/provider_api.test.js +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/browser-extension/tests/unit/provider_tierb.test.js +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/browser-extension/tests/unit/remote_bunker.test.js +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/browser-extension/tests/unit/signer_backends.test.js +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/browser-extension/vitest.config.js +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/deploy/capauth-service/.env.example +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/deploy/capauth-service/deploy.sh +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/deploy/capauth-service/docker-compose.yml +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/deploy/capauth-service/systemd/capauth-backup.service +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/deploy/capauth-service/systemd/capauth-backup.timer +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/deploy/forgejo-capauth/.env.example +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/deploy/forgejo-capauth/docker-compose.yml +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/deploy/forgejo-capauth/preflight.sh +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/docs/AIRGAPPED_SIGNING_WORKSTATION.md +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/docs/ARCHITECTURE.md +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/docs/AUTHENTIK_CUSTOM_STAGE.md +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/docs/AUTHENTIK_DEPLOYMENT_SKSSO.md +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/docs/AUTHENTIK_FORGEJO_DEPLOYMENT.md +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/docs/AUTHENTIK_STRATEGY_DECISION.md +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/docs/CAPAUTH_BUNKER_REMOTE_SIGNER.md +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/docs/CAPAUTH_OIDC_IDP.md +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/docs/CLAIMS.md +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/docs/COLD_MACHINE_BOOTSTRAP_AND_DR.md +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/docs/CRYPTO_SPEC.md +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/docs/ENTERPRISE_MANAGED_KEYS.md +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/docs/INTEGRATION_BLUEPRINT.md +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/docs/M0-capauth-api-v1.md +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/docs/M0-capauth-importer-inventory.md +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/docs/PQC_CAPAUTH_REVISIT.md +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/docs/PQC_ROOT_MIGRATION.md +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/docs/PROTOCOL.md +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/docs/ROOT_ROTATION_CEREMONY.md +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/docs/TRUST_GRAPH_COORD_PROJECTION.md +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/docs/ZERO_KNOWLEDGE_PROFILE.md +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/docs/authentik-capauth.md +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/docs/deploy-plan/capauth-bulletproof-deploy.md +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/index.d.ts +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/index.js +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/openclaw-plugin.archived-2026-04-23/package.json +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/openclaw-plugin.archived-2026-04-23/src/index.ts +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/openclaw-plugin.archived-2026-04-23/src/openclaw.plugin.json +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/package.json +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/phone-signer/app.js +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/phone-signer/icons/icon-192.png +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/phone-signer/icons/icon-512.png +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/phone-signer/index.html +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/phone-signer/lib/bunker-e2e.js +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/phone-signer/lib/bunker-signer.js +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/phone-signer/lib/canonical.js +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/phone-signer/lib/keyqr.js +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/phone-signer/lib/keyvault.js +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/phone-signer/manifest.webmanifest +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/phone-signer/sw.js +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/phone-signer/vendor/openpgp.min.js +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/phone-signer/vendor/qrcode-generator.js +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/pyproject.toml +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/ruff-0.15.4-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/scripts/build_authentik_capauth_image.sh +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/scripts/capauth-backup.sh +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/scripts/capauth-restore.sh +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/scripts/migrate_canonical_subjects.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/scripts/pqc_ceremony_dryrun.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/scripts/provision_agent_profiles.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/setup.cfg +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/skill.yaml +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/__init__.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/apps.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/authentik/__init__.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/authentik/api.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/authentik/blueprints/capauth-pgp-login.yaml +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/authentik/claims_mapper.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/authentik/nonce_store.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/authentik/stage.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/authentik/urls.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/authentik/verifier.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/authz.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/cli.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/crypto/__init__.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/crypto/base.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/crypto/gnupg_backend.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/crypto/pgpy_backend.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/crypto/sequoia_backend.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/crypto/skpgp_backend.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/custody.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/did.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/discovery/__init__.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/discovery/base.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/discovery/file_discovery.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/discovery/mdns.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/discovery/syncthing.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/exceptions.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/identity.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/identity_class.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/integration.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/integrations/__init__.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/integrations/forgejo/__init__.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/integrations/forgejo/auth_flow.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/integrations/forgejo/cli.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/integrations/forgejo/config.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/integrations/forgejo/forgejo_api.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/integrations/forgejo/oidc_provider.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/integrations/forgejo/tests/__init__.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/integrations/forgejo/tests/test_auth_flow.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/integrations/forgejo/tests/test_cli.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/integrations/forgejo/tests/test_config.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/integrations/forgejo/tests/test_forgejo_api.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/integrations/forgejo/tests/test_oidc_provider.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/integrations/nextcloud/.gitignore +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/integrations/nextcloud/.nextcloudignore +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/integrations/nextcloud/CSR-PR.md +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/integrations/nextcloud/INFO-XML-CHANGES.md +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/integrations/nextcloud/PUBLISHING.md +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/integrations/nextcloud/README.md +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/integrations/nextcloud/appinfo/info.xml +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/integrations/nextcloud/appinfo/routes.php +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/integrations/nextcloud/build-release.sh +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/integrations/nextcloud/certificates/.gitignore +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/integrations/nextcloud/certificates/capauth.crt +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/integrations/nextcloud/certificates/capauth.csr +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/integrations/nextcloud/composer.json +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/integrations/nextcloud/css/login.css +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/integrations/nextcloud/js/login.js +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/integrations/nextcloud/krankerl.toml +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/integrations/nextcloud/lib/AlternativeLogin/CapAuthLogin.php +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/integrations/nextcloud/lib/AppInfo/Application.php +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/integrations/nextcloud/lib/BackgroundJob/PruneExpiredNonces.php +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/integrations/nextcloud/lib/Controller/LoginController.php +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/integrations/nextcloud/lib/Controller/TokenController.php +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/integrations/nextcloud/lib/Db/KeyRegistry.php +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/integrations/nextcloud/lib/Exception/CapAuthUnauthorizedException.php +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/integrations/nextcloud/lib/Middleware/PgpVerificationMiddleware.php +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/integrations/nextcloud/lib/Migration/Version000300Date20260301000000.php +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/integrations/nextcloud/lib/Provider/CapAuthProvider.php +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/integrations/nextcloud/lib/Service/ChallengeService.php +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/integrations/nextcloud/lib/Service/GroupSyncService.php +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/integrations/nextcloud/lib/Service/UserProvisioningService.php +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/integrations/nextcloud/lib/Service/VerifierService.php +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/integrations/nextcloud/lib/User/Backend.php +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/integrations/nextcloud/phpunit.xml +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/integrations/nextcloud/screenshots/README.md +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/integrations/nextcloud/screenshots/login.png +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/integrations/nextcloud/templates/login.php +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/integrations/nextcloud/tests/bootstrap.php +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/integrations/nextcloud/tests/integration/FullAuthFlowTest.php +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/integrations/nextcloud/tests/oidc/oidc_e2e_login_test.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/integrations/nextcloud/tests/unit/Controller/LoginControllerTest.php +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/integrations/nextcloud/tests/unit/Db/KeyRegistryTest.php +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/integrations/nextcloud/tests/unit/Provider/CapAuthProviderTest.php +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/integrations/nextcloud/tests/unit/Service/ChallengeServiceTest.php +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/integrations/nextcloud/tests/unit/Service/VerifierServiceTest.php +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/integrations/nextcloud/tests/unit/User/BackendTest.php +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/key_transparency.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/login.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/manifest.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/mesh.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/migrations/0001_initial.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/migrations/0002_widen_fingerprint_to_64.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/migrations/__init__.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/models.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/pairing/__init__.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/pairing/canonicalize.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/pairing/kernel.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/pairing/operator_session.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/pairing/records.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/pairing/store.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/pairing/window.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/pma.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/pqc_confidentiality.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/pqc_identity.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/pqc_root_identity.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/pqc_tokens.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/profile.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/provisioning.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/registry.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/seal.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/service/__init__.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/service/app.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/service/bunker.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/service/bunker_e2e.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/service/keystore.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/service/oidc/__init__.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/service/oidc/clients.example.json +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/service/oidc/clients.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/service/oidc/passkey.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/service/oidc/provider.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/service/oidc/signing_key.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/service/oidc/store.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/service/push.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/service/server.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/subject.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/sync.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/testing.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/tokens.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/trust/__init__.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/trust/calibration.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth/trust/graph.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth.egg-info/dependency_links.txt +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth.egg-info/entry_points.txt +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth.egg-info/requires.txt +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/src/capauth.egg-info/top_level.txt +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/stages/ak-stage-capauth/.gitignore +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/stages/ak-stage-capauth/package-lock.json +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/stages/ak-stage-capauth/package.json +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/stages/ak-stage-capauth/src/CapAuthStage.test.js +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/stages/ak-stage-capauth/src/CapAuthStage.vue +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/stages/ak-stage-capauth/src/index.js +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/stages/ak-stage-capauth/vite.config.js +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/tests/__init__.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/tests/conftest.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/tests/fixtures/bunker_e2e_v1_vector.json +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/tests/fixtures/canonical_nonce_v2_vector.json +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/tests/test_agent_identity.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/tests/test_agentrun_capabilities.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/tests/test_audience_mint_helper.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/tests/test_audience_tokens.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/tests/test_authz.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/tests/test_authz_legacy_grace.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/tests/test_authz_signature_gate.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/tests/test_backup_restore.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/tests/test_bunker.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/tests/test_bunker_e2e.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/tests/test_canonicalize.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/tests/test_capauth_service_deploy.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/tests/test_change_capabilities.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/tests/test_claims_mapper.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/tests/test_crypto.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/tests/test_custody.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/tests/test_device_key_proof.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/tests/test_did_capability_relationships.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/tests/test_fingerprint_v6.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/tests/test_forgejo_preflight.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/tests/test_home_resolution.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/tests/test_identity.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/tests/test_identity_class.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/tests/test_identity_ttl.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/tests/test_integration.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/tests/test_key_revocation_expiry.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/tests/test_key_transparency.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/tests/test_login.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/tests/test_manifest.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/tests/test_mesh.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/tests/test_models_pqc_q0.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/tests/test_nextcloud_app.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/tests/test_no_subapp_dependency.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/tests/test_nonce_store.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/tests/test_oidc_idp.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/tests/test_oidc_idp_e2e.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/tests/test_operator_session.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/tests/test_pairing.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/tests/test_pairing_base_dir_env.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/tests/test_passkey.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/tests/test_pma.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/tests/test_pqc_confidentiality.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/tests/test_pqc_identity.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/tests/test_pqc_root_integration.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/tests/test_pqc_t3_gate.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/tests/test_pqc_tokens.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/tests/test_profile.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/tests/test_provisioning.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/tests/test_push.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/tests/test_py313_compat.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/tests/test_qr_login.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/tests/test_real_pgp_e2e.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/tests/test_register_cli.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/tests/test_registry.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/tests/test_seal.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/tests/test_sequoia_backend.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/tests/test_service.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/tests/test_service_authz_decide.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/tests/test_service_v6_fingerprint.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/tests/test_skpgp_backend.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/tests/test_subject.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/tests/test_syncthing_discovery.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/tests/test_testing_helper.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/tests/test_token_gc.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/tests/test_token_store_flag.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/tests/test_tokens.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/tests/test_trust_calibration.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/tests/test_trust_graph.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/tests/test_trust_graph_coord_audit.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/tests/test_verifier.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/tests/test_version_honesty.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/tests/test_zk_profile.py +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/tools/build-sq.sh +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/urllib.error +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/web/README.md +0 -0
- {capauth-0.3.2 → capauth-0.3.4}/web/stages/capauth/CapAuthStage.ts +0 -0
|
@@ -6,6 +6,23 @@ All notable changes to `capauth` are documented here. The format is based on
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
### Documentation
|
|
10
|
+
|
|
11
|
+
- Added the SK-standards-aligned human identity setup and rotation runbook,
|
|
12
|
+
covering human-only key handling, revocation certificates, protected backup
|
|
13
|
+
transfer, additive trust migration, signed CAB approval, verification,
|
|
14
|
+
rollback, evidence, and recurring custody management.
|
|
15
|
+
|
|
16
|
+
### Fixed
|
|
17
|
+
|
|
18
|
+
- **Identity docstrings taught the wrong fqid shape.** `agent_identity.py`
|
|
19
|
+
showed `lumina@chef.skworld` in its prose, its worked example and its
|
|
20
|
+
doctest: the missing-TLD form that the N5 store migration exists to correct.
|
|
21
|
+
Verified against the live resolver, which returns `lumina@chef.skworld.io`.
|
|
22
|
+
A wrong example in the module that defines identity is what the next reader
|
|
23
|
+
or agent copies. `subject.py` deliberately keeps its legacy examples, since
|
|
24
|
+
they document the shapes the alias table normalizes.
|
|
25
|
+
|
|
9
26
|
### Added
|
|
10
27
|
|
|
11
28
|
- **`capauth.pairing.proof`: a supported way to BUILD the enrollment proof card
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: capauth
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.4
|
|
4
4
|
Summary: Capability-based Authentication — decentralized, PGP-based identity and authorization
|
|
5
5
|
Author-email: smilinTux <admin@smilintux.org>
|
|
6
6
|
License: GPL-3.0-or-later
|
|
@@ -317,6 +317,8 @@ capauth is the identity root of SKWorld — most of the stack links back here.
|
|
|
317
317
|
— produces the runtime crypto self-report that makes capauth's claims evidence-backed.
|
|
318
318
|
- 📐 **Standards:** [sk-standards](https://github.com/smilinTux/sk-standards) — the
|
|
319
319
|
crypto, data-flow, version, and doc/SOP standards (incl. `CRYPTOGRAPHY_STANDARD`).
|
|
320
|
+
- 🔐 **Human key operations:**
|
|
321
|
+
[setup, recovery, rotation, approval, and rollback](docs/HUMAN_IDENTITY_SETUP_AND_ROTATION.md).
|
|
320
322
|
|
|
321
323
|
## License
|
|
322
324
|
|
|
@@ -255,6 +255,8 @@ capauth is the identity root of SKWorld — most of the stack links back here.
|
|
|
255
255
|
— produces the runtime crypto self-report that makes capauth's claims evidence-backed.
|
|
256
256
|
- 📐 **Standards:** [sk-standards](https://github.com/smilinTux/sk-standards) — the
|
|
257
257
|
crypto, data-flow, version, and doc/SOP standards (incl. `CRYPTOGRAPHY_STANDARD`).
|
|
258
|
+
- 🔐 **Human key operations:**
|
|
259
|
+
[setup, recovery, rotation, approval, and rollback](docs/HUMAN_IDENTITY_SETUP_AND_ROTATION.md).
|
|
258
260
|
|
|
259
261
|
## License
|
|
260
262
|
|
|
@@ -346,6 +346,25 @@ capauth manifest sign | verify | list # signed module manifests
|
|
|
346
346
|
capauth token mint-audience ... # mint an audience-scoped token
|
|
347
347
|
```
|
|
348
348
|
|
|
349
|
+
### Authorization token incident check
|
|
350
|
+
|
|
351
|
+
`capauth.authz.decide()` is fail-closed on token authenticity: a granting token
|
|
352
|
+
must have a non-empty signature, `signature_verifies()` must succeed, it must be
|
|
353
|
+
active, and its token ID must not appear in
|
|
354
|
+
`$SKCAPSTONE_HOME/security/revoked-tokens.json`. Never infer trust from the
|
|
355
|
+
persisted `verified` field alone. `issue_token()` must also abort before storage
|
|
356
|
+
when signing fails; an unsigned compatibility token may only pass through the
|
|
357
|
+
explicit, bounded legacy-grace configuration documented in `authz.py`.
|
|
358
|
+
|
|
359
|
+
For an incident sweep, inventory the token payloads in
|
|
360
|
+
`$SKCAPSTONE_HOME/security/tokens/`, confirm every live grant has a detached
|
|
361
|
+
signature, search the revocation list for the reported token ID, and exercise
|
|
362
|
+
both controls: an unsigned/tampered token is denied while a valid signed token
|
|
363
|
+
is allowed. Revoke a discovered token through `capauth.tokens.revoke_token()`;
|
|
364
|
+
do not delete the evidence file by hand. Preserve the test evidence from
|
|
365
|
+
`tests/test_authz_signature_gate.py` and `tests/test_authz_legacy_grace.py` on
|
|
366
|
+
the coordination card.
|
|
367
|
+
|
|
349
368
|
> **There is NO `capauth did` command group.** Earlier revisions of this SOP and of
|
|
350
369
|
> the README documented `capauth did generate` and `capauth did identity-card`; both
|
|
351
370
|
> are fabrications, and running them exits non-zero with "No such command". The DID
|
|
@@ -402,6 +421,12 @@ Full protocol + claim/token format: [docs/PROTOCOL.md](docs/PROTOCOL.md),
|
|
|
402
421
|
|
|
403
422
|
## 8. Troubleshooting
|
|
404
423
|
|
|
424
|
+
Human identity setup, custody recovery, rotation, signed approval, and rollback
|
|
425
|
+
are governed by
|
|
426
|
+
[docs/HUMAN_IDENTITY_SETUP_AND_ROTATION.md](docs/HUMAN_IDENTITY_SETUP_AND_ROTATION.md).
|
|
427
|
+
The human performs all passphrase/private-key operations; automation may only
|
|
428
|
+
prepare paths and verify public evidence.
|
|
429
|
+
|
|
405
430
|
| Symptom | Likely cause | Fix |
|
|
406
431
|
|---|---|---|
|
|
407
432
|
| `capauth verify` fails on a valid peer | wrong public key / stale profile | re-`export-pubkey`; confirm fingerprint matches the DID/identity card |
|
|
@@ -486,4 +511,3 @@ checks:
|
|
|
486
511
|
- name: ci.yml lint gate is ruff (section 4 says black is NOT a gate)
|
|
487
512
|
run: grep -qF 'ruff format --check src/ tests/' .github/workflows/ci.yml
|
|
488
513
|
-->
|
|
489
|
-
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
# Human identity setup, recovery, and key rotation
|
|
2
|
+
|
|
3
|
+
Status: operational runbook. Owner: the human identity holder. Applies to
|
|
4
|
+
classical CapAuth human identities used for signed approvals and operator
|
|
5
|
+
governance. This runbook follows the SK standards for provenance, reversible
|
|
6
|
+
mutation, backup/retention, testing evidence, and ITIL change control.
|
|
7
|
+
|
|
8
|
+
## 1. Purpose and invariants
|
|
9
|
+
|
|
10
|
+
- A human private key is generated and unlocked only by that human.
|
|
11
|
+
- Agents may prepare paths and verify public evidence, but never type, copy,
|
|
12
|
+
print, or forge the human passphrase or private key.
|
|
13
|
+
- Rotation is additive first: retain the old public key and profile as audit
|
|
14
|
+
history, enroll the new fingerprint, verify it, then retire old trust.
|
|
15
|
+
- Private keys and revocation certificates are `0600`; containing directories
|
|
16
|
+
are `0700`. Public keys may be `0644`.
|
|
17
|
+
- Never paste key material or passphrases into chat, tickets, shell history,
|
|
18
|
+
source control, logs, or command output.
|
|
19
|
+
- A backup is not accepted until its fingerprint and restore path are tested.
|
|
20
|
+
|
|
21
|
+
## 2. State and ownership
|
|
22
|
+
|
|
23
|
+
```mermaid
|
|
24
|
+
flowchart LR
|
|
25
|
+
H[Human at terminal] -->|generates and unlocks| S[staging identity]
|
|
26
|
+
S -->|public fingerprint verification| V[verification gate]
|
|
27
|
+
S -->|0600 copy by human| B[two offline custody copies]
|
|
28
|
+
V -->|approved change| L[live CapAuth identity]
|
|
29
|
+
L --> R[registries and trust consumers]
|
|
30
|
+
L --> A[signed authorization envelope]
|
|
31
|
+
O[old public identity] --> X[retired audit history]
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Canonical live home on the operator workstation is
|
|
35
|
+
`~/.skcapstone/capauth`. Temporary ceremony homes and home-directory backups
|
|
36
|
+
are transitional custody only and must be moved to two independent offline
|
|
37
|
+
media after acceptance.
|
|
38
|
+
|
|
39
|
+
## 3. Initial setup
|
|
40
|
+
|
|
41
|
+
The human runs key generation personally:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
install -d -m 700 "$HOME/.chef-cauth-setup"
|
|
45
|
+
capauth --home "$HOME/.chef-cauth-setup" init \
|
|
46
|
+
--name Chef --email chef@skworld.io --type human \
|
|
47
|
+
--algorithm ed25519 --no-sync
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Use a unique passphrase and retain it outside the workstation. Verify without
|
|
51
|
+
printing key contents:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
capauth --home "$HOME/.chef-cauth-setup" profile verify
|
|
55
|
+
capauth --home "$HOME/.chef-cauth-setup" doctor custody --json
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
`doctor` will remain red until a matching revocation certificate and backup
|
|
59
|
+
exist. A red custody gate is not waived.
|
|
60
|
+
|
|
61
|
+
## 4. Revocation certificate and custody copies
|
|
62
|
+
|
|
63
|
+
The human imports the staged key into an isolated temporary GnuPG home and
|
|
64
|
+
runs `gpg --gen-revoke <fingerprint>`. Creating the certificate does not revoke
|
|
65
|
+
the key. Store the resulting `root-revocation.asc` beside each protected
|
|
66
|
+
private-key custody copy. Confirm:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
stat -c '%a %U %G %n' \
|
|
70
|
+
"$HOME/.chef-cauth-setup/identity/private.asc" \
|
|
71
|
+
"$HOME/.chef-cauth-setup/identity/root-revocation.asc"
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Expected mode is `600`. Maintain two independent offline copies. An on-host
|
|
75
|
+
backup is only a transfer/staging copy, not the required 3-2-1 end state.
|
|
76
|
+
|
|
77
|
+
## 5. Rotation workflow
|
|
78
|
+
|
|
79
|
+
1. Open an ITIL change with old fingerprint, reason, affected trust surfaces,
|
|
80
|
+
maintenance window, verification plan, and rollback target.
|
|
81
|
+
2. Snapshot the old public key, signed profile, custody declaration, and
|
|
82
|
+
revocation certificate into an owner-only `retired-keys/` directory.
|
|
83
|
+
3. Generate the replacement in an isolated `0700` ceremony home.
|
|
84
|
+
4. Verify public/private/backup fingerprints are identical and the profile
|
|
85
|
+
signature is valid.
|
|
86
|
+
5. Generate and duplicate the replacement revocation certificate.
|
|
87
|
+
6. Install the replacement keypair and profile with the modes in section 1.
|
|
88
|
+
7. Update explicit fingerprint bindings in registries. Do not use global text
|
|
89
|
+
replacement; validate every target record before mutation.
|
|
90
|
+
8. Run a fresh public-state backup and its restore verification.
|
|
91
|
+
9. Run `capauth doctor custody`; all mandatory checks must be `OK`.
|
|
92
|
+
10. Produce a signed, short-lived authorization and verify it through the real
|
|
93
|
+
consuming workflow.
|
|
94
|
+
11. Keep both public fingerprints during the declared grace period. Revoke the
|
|
95
|
+
old key only for compromise; an unavailable secret is retired, not falsely
|
|
96
|
+
claimed revoked.
|
|
97
|
+
|
|
98
|
+
## 6. Signed approval ceremony
|
|
99
|
+
|
|
100
|
+
For an ATLAS/CMDB change, the authorization binds decision, target, change,
|
|
101
|
+
scope, expiry, nonce, signer fingerprint, and role:
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
skcapstone itil cab authorize CHANGE_ID \
|
|
105
|
+
--decision approved --target TARGET --scope SCOPE \
|
|
106
|
+
--output "$HOME/.skcapstone/authorizations/CHANGE_ID.json"
|
|
107
|
+
skcapstone itil cab vote CHANGE_ID \
|
|
108
|
+
--decision approved \
|
|
109
|
+
--authorization "$HOME/.skcapstone/authorizations/CHANGE_ID.json" \
|
|
110
|
+
--target TARGET --scope SCOPE
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Read the folded change back. The named human, authenticated role,
|
|
114
|
+
fingerprint, authorization ID, target, and scope must all match. Authorization
|
|
115
|
+
does not bypass freeze, maintenance-window, evidence, or rollback gates.
|
|
116
|
+
|
|
117
|
+
## 7. Verification and rollback
|
|
118
|
+
|
|
119
|
+
Acceptance evidence:
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
capauth --home "$HOME/.skcapstone/capauth" profile verify
|
|
123
|
+
capauth --home "$HOME/.skcapstone/capauth" doctor custody --json
|
|
124
|
+
capauth manifest verify-all
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
If any check fails, stop consumers, restore the prior public/profile state from
|
|
128
|
+
the named rollback directory, restore the previous registry fingerprint, and
|
|
129
|
+
rerun the same checks. Never delete the failed replacement; quarantine it with
|
|
130
|
+
its evidence and record the reversing event on the ITIL change.
|
|
131
|
+
|
|
132
|
+
## 8. Ongoing management
|
|
133
|
+
|
|
134
|
+
- Daily: custody doctor and backup freshness through the wrapped scheduler.
|
|
135
|
+
- Monthly: verify permissions, registry fingerprint parity, and restore the
|
|
136
|
+
newest public-state backup into a temporary directory.
|
|
137
|
+
- Quarterly: verify both offline custody media and revocation-certificate
|
|
138
|
+
readability; do not import the private key during routine inspection.
|
|
139
|
+
- Before each approval: verify profile signature and exact action/change/scope.
|
|
140
|
+
- On suspected compromise: freeze ATLAS, publish the held revocation
|
|
141
|
+
certificate, invalidate affected grants, rotate, and open an incident/problem.
|
|
142
|
+
|
|
143
|
+
## 9. Evidence, records, and prohibited shortcuts
|
|
144
|
+
|
|
145
|
+
Record fingerprints, timestamps, modes, doctor results, backup artifact ID,
|
|
146
|
+
change ID, and verification outcome. Never record passphrases or private-key
|
|
147
|
+
content. Prohibited shortcuts include agent-generated human keys, reusing an
|
|
148
|
+
agent key as a person, unsigned votes, copying secrets through chat, accepting
|
|
149
|
+
a mismatched backup, or deleting old identity history to make checks green.
|
|
@@ -19,7 +19,7 @@ A resolved identity carries **two complementary URIs**:
|
|
|
19
19
|
|
|
20
20
|
``fqid``
|
|
21
21
|
``<agent>@<operator>.<realm>`` — the skcomms three-tier FQID
|
|
22
|
-
(agent @ operator . realm, e.g. ``lumina@chef.skworld``). Derived from
|
|
22
|
+
(agent @ operator . realm, e.g. ``lumina@chef.skworld.io``). Derived from
|
|
23
23
|
``~/.skcapstone/cluster.json`` for operator/realm; ``None`` when
|
|
24
24
|
cluster.json is absent or malformed.
|
|
25
25
|
|
|
@@ -38,7 +38,7 @@ Public API
|
|
|
38
38
|
# AgentIdentity(
|
|
39
39
|
# agent = "lumina",
|
|
40
40
|
# capauth_uri = "capauth:lumina@skworld.io",
|
|
41
|
-
# fqid = "lumina@chef.skworld",
|
|
41
|
+
# fqid = "lumina@chef.skworld.io",
|
|
42
42
|
# fingerprint = "02BC0EB3CAD31DB691A753C70C5629AB893F9746",
|
|
43
43
|
# )
|
|
44
44
|
|
|
@@ -84,7 +84,7 @@ class AgentIdentity:
|
|
|
84
84
|
agent: Short agent name (e.g. ``"lumina"``).
|
|
85
85
|
capauth_uri: Wire identity — ``capauth:<agent>@skworld.io``.
|
|
86
86
|
fqid: Three-tier label — ``<agent>@<operator>.<realm>``
|
|
87
|
-
(e.g. ``"lumina@chef.skworld"``). ``None`` when
|
|
87
|
+
(e.g. ``"lumina@chef.skworld.io"``). ``None`` when
|
|
88
88
|
cluster.json is not available.
|
|
89
89
|
fingerprint: 40 (v4) or 64 (v6) hex PGP fingerprint from the agent's
|
|
90
90
|
CapAuth profile. ``None`` when no real profile exists.
|
|
@@ -274,7 +274,7 @@ def resolve_agent_identity(
|
|
|
274
274
|
>>> ident.capauth_uri
|
|
275
275
|
'capauth:lumina@skworld.io'
|
|
276
276
|
>>> ident.fqid # only if cluster.json present
|
|
277
|
-
'lumina@chef.skworld'
|
|
277
|
+
'lumina@chef.skworld.io'
|
|
278
278
|
"""
|
|
279
279
|
if agent is None:
|
|
280
280
|
agent = _resolve_active_agent_name()
|
|
@@ -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")
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: capauth
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.4
|
|
4
4
|
Summary: Capability-based Authentication — decentralized, PGP-based identity and authorization
|
|
5
5
|
Author-email: smilinTux <admin@smilintux.org>
|
|
6
6
|
License: GPL-3.0-or-later
|
|
@@ -317,6 +317,8 @@ capauth is the identity root of SKWorld — most of the stack links back here.
|
|
|
317
317
|
— produces the runtime crypto self-report that makes capauth's claims evidence-backed.
|
|
318
318
|
- 📐 **Standards:** [sk-standards](https://github.com/smilinTux/sk-standards) — the
|
|
319
319
|
crypto, data-flow, version, and doc/SOP standards (incl. `CRYPTOGRAPHY_STANDARD`).
|
|
320
|
+
- 🔐 **Human key operations:**
|
|
321
|
+
[setup, recovery, rotation, approval, and rollback](docs/HUMAN_IDENTITY_SETUP_AND_ROTATION.md).
|
|
320
322
|
|
|
321
323
|
## License
|
|
322
324
|
|
|
@@ -107,6 +107,7 @@ docs/CLAIMS.md
|
|
|
107
107
|
docs/COLD_MACHINE_BOOTSTRAP_AND_DR.md
|
|
108
108
|
docs/CRYPTO_SPEC.md
|
|
109
109
|
docs/ENTERPRISE_MANAGED_KEYS.md
|
|
110
|
+
docs/HUMAN_IDENTITY_SETUP_AND_ROTATION.md
|
|
110
111
|
docs/INTEGRATION_BLUEPRINT.md
|
|
111
112
|
docs/M0-capauth-api-v1.md
|
|
112
113
|
docs/M0-capauth-importer-inventory.md
|
|
@@ -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
|