skcomms 0.2.2__tar.gz → 0.2.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.
- skcomms-0.2.4/.github/workflows/ci.yml +99 -0
- skcomms-0.2.4/.github/workflows/publish.yml +134 -0
- skcomms-0.2.4/.github/workflows/pytest.yml +127 -0
- skcomms-0.2.4/.github/workflows/qa.yml +55 -0
- skcomms-0.2.4/.github/workflows/secret-scan.yml +48 -0
- skcomms-0.2.4/.gitignore +16 -0
- skcomms-0.2.4/.gitleaks.toml +35 -0
- skcomms-0.2.4/CHANGELOG.md +243 -0
- skcomms-0.2.4/CODE_OF_CONDUCT.md +129 -0
- skcomms-0.2.4/CONTRIBUTING.md +162 -0
- skcomms-0.2.4/DEPLOY-NOTES.md +105 -0
- skcomms-0.2.4/Dockerfile +47 -0
- skcomms-0.2.4/MISSION.md +19 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/PKG-INFO +1 -1
- skcomms-0.2.4/SECURITY.md +152 -0
- skcomms-0.2.4/SOP.md +625 -0
- skcomms-0.2.4/constraints.txt +89 -0
- skcomms-0.2.4/contrib/systemd/skcomms-api.service +50 -0
- skcomms-0.2.4/contrib/systemd/skcomms-housekeep.service +24 -0
- skcomms-0.2.4/contrib/systemd/skcomms-housekeep.timer +19 -0
- skcomms-0.2.4/docs/ARCHITECTURE.md +370 -0
- skcomms-0.2.4/docs/DISCORD_SETUP.md +185 -0
- skcomms-0.2.4/docs/HANDOFF-skfed-s2s-opus-delivery.md +80 -0
- skcomms-0.2.4/docs/PAIRING.md +187 -0
- skcomms-0.2.4/docs/REVOCATION_LATENCY.md +175 -0
- skcomms-0.2.4/docs/SYNCTHING_TOPOLOGY.md +470 -0
- skcomms-0.2.4/docs/access-plane-p7.md +201 -0
- skcomms-0.2.4/docs/access-plane-p8.md +119 -0
- skcomms-0.2.4/docs/cot-bridge.md +130 -0
- skcomms-0.2.4/docs/crypto-architecture.md +227 -0
- skcomms-0.2.4/docs/deploy-plan/skcomms-bulletproof-deploy.md +196 -0
- skcomms-0.2.4/docs/federation-data-comms-architecture.md +325 -0
- skcomms-0.2.4/docs/funnel-privacy.md +195 -0
- skcomms-0.2.4/docs/mode-b-tailnet-deploy.md +56 -0
- skcomms-0.2.4/docs/node_registry.example.yml +36 -0
- skcomms-0.2.4/docs/rfcs/RFC-0001-pq-ratchet-metadata-dual-identity.md +339 -0
- skcomms-0.2.4/docs/skfed-consent-design.md +329 -0
- skcomms-0.2.4/docs/skfed-federation-guide.md +257 -0
- skcomms-0.2.4/docs/state-sync-rearch-plan.md +398 -0
- skcomms-0.2.4/docs/superpowers/plans/2026-06-10-qr-pairing.md +375 -0
- skcomms-0.2.4/docs/superpowers/plans/2026-06-13-ble-mesh-p1-core.md +1568 -0
- skcomms-0.2.4/docs/superpowers/plans/2026-06-13-lora-l1-core.md +783 -0
- skcomms-0.2.4/docs/superpowers/plans/2026-06-13-skglossa-g1-core.md +674 -0
- skcomms-0.2.4/docs/superpowers/plans/2026-06-13-skglossa-g2-macro-lexicon.md +381 -0
- skcomms-0.2.4/docs/superpowers/plans/2026-06-13-skglossa-g4-emergent.md +272 -0
- skcomms-0.2.4/docs/superpowers/plans/2026-06-13-tier3-adapter-runtime.md +187 -0
- skcomms-0.2.4/docs/superpowers/specs/2026-06-13-ble-mesh-proximity-transport-design.md +193 -0
- skcomms-0.2.4/docs/superpowers/specs/2026-06-13-lora-meshtastic-transport-design.md +158 -0
- skcomms-0.2.4/docs/superpowers/specs/2026-06-13-skglossa-design.md +335 -0
- skcomms-0.2.4/docs/tak-vs-skfed-analysis.md +52 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/pyproject.toml +16 -2
- skcomms-0.2.4/scripts/backfill_file_locations.py +249 -0
- skcomms-0.2.4/scripts/bootstrap.sh +169 -0
- skcomms-0.2.4/scripts/discord_smoke.py +198 -0
- skcomms-0.2.4/scripts/drain_orphan_outbox.py +268 -0
- skcomms-0.2.4/scripts/mode-b-setup.sh +383 -0
- skcomms-0.2.4/scripts/refresh-constraints.sh +75 -0
- skcomms-0.2.4/scripts/skfed-dns.sh +117 -0
- skcomms-0.2.4/scripts/skfed-neutral-addresses.sh +73 -0
- skcomms-0.2.4/scripts/skfed-sync-rearch.sh +353 -0
- skcomms-0.2.4/scripts/telegram_smoke.py +245 -0
- skcomms-0.2.4/scripts/templates/consent-mode.conf.tmpl +7 -0
- skcomms-0.2.4/scripts/templates/realms.yml.tmpl +4 -0
- skcomms-0.2.4/scripts/templates/tailscale-serve.sh.tmpl +8 -0
- skcomms-0.2.4/scripts/test_skfed_sync_rearch.sh +84 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/__init__.py +10 -10
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/access/__init__.py +4 -2
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/access/config.py +3 -1
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/access/exec.py +6 -7
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/access/files.py +11 -7
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/access/grants.py +3 -1
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/access/knowledge.py +14 -14
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/access/routing.py +51 -22
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/access/server.py +55 -32
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/access/wiring.py +14 -6
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/ack.py +1 -3
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/adapters/discord.py +14 -26
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/adapters/matrix.py +22 -28
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/adapters/registry.py +2 -6
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/adapters/slack.py +19 -25
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/adapters/telegram.py +14 -28
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/anon_queue.py +3 -7
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/anon_transport.py +14 -19
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/api.py +74 -11
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/capabilities.py +3 -4
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/capauth_validator.py +7 -7
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/cli.py +74 -41
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/cluster.py +3 -9
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/config.py +1 -3
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/consent.py +7 -7
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/consent_banfeeds.py +1 -2
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/consent_captcha.py +6 -9
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/consent_greylist.py +1 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/consent_group_gate.py +6 -4
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/consent_groups.py +21 -16
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/consent_moderation.py +3 -7
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/consent_pipeline.py +2 -3
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/consent_policy.py +5 -5
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/consent_requests.py +2 -3
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/consent_runtime.py +3 -6
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/consent_tiering.py +8 -15
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/consent_tokens.py +2 -3
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/core.py +14 -22
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/crypto.py +8 -5
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/crypto_suites.py +4 -4
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/did_router.py +3 -1
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/envelope.py +4 -6
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/federation.py +1 -3
- skcomms-0.2.4/src/skcomms/geo_seed.py +168 -0
- skcomms-0.2.4/src/skcomms/geo_store.py +232 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/glossa/codebook.py +16 -4
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/glossa/codec.py +7 -6
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/glossa/emergent.py +4 -3
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/glossa/gloss.py +3 -2
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/glossa/handshake.py +15 -10
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/glossa/macros.py +5 -5
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/glossa/message.py +9 -5
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/glossa/session.py +7 -2
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/grants.py +6 -14
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/housekeeping.py +1 -3
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/integration.py +1 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/key_exchange.py +4 -1
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/mailbox.py +3 -1
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/mcp_server.py +15 -5
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/nostr_discovery.py +7 -15
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/observability.py +2 -8
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/operator_probe.py +26 -5
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/outbox.py +12 -5
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/outbox_migrate.py +2 -6
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/padding.py +2 -5
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/pairing.py +49 -18
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/peers.py +3 -9
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/pqdm.py +233 -11
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/pqkem.py +4 -9
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/pqroute.py +2 -10
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/pqroute_transport.py +6 -6
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/pqsig.py +15 -32
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/public_pairing.py +1 -3
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/registry.py +1 -1
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/router.py +6 -11
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/signing.py +4 -12
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/skfed_announce.py +3 -1
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/skfed_directory.py +1 -2
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/skfed_readdr.py +8 -8
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/skfed_resolve.py +3 -1
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/ssrf.py +4 -12
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/store_forward.py +3 -9
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/syncthing_rail.py +4 -4
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/tofu.py +2 -6
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/transports/ble/gatt.py +1 -1
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/transports/ble/identity.py +4 -4
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/transports/ble/node.py +11 -5
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/transports/ble/noise.py +7 -4
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/transports/ble/protocol.py +40 -17
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/transports/ble/relay.py +5 -7
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/transports/file.py +3 -10
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/transports/http_s2s.py +4 -9
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/transports/lora/addressing.py +1 -2
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/transports/lora/framing.py +2 -2
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/transports/lora/interface.py +2 -3
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/transports/lora/meshtastic_iface.py +15 -8
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/transports/lora/store.py +2 -1
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/transports/lora/transport.py +24 -12
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/transports/p2p_manager.py +1 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/transports/p2p_session.py +1 -3
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/transports/signaling_broker.py +17 -11
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/transports/signaling_mailbox.py +13 -8
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/transports/webrtc.py +1 -3
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/trustbackup.py +1 -7
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms.egg-info/PKG-INFO +1 -1
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms.egg-info/SOURCES.txt +80 -1
- skcomms-0.2.4/src/skcomms.egg-info/scm_file_list.json +407 -0
- skcomms-0.2.4/src/skcomms.egg-info/scm_version.json +8 -0
- skcomms-0.2.4/tests/__init__.py +0 -0
- skcomms-0.2.4/tests/conftest.py +69 -0
- skcomms-0.2.4/tests/fixtures/pqdm2_from_dart.json +18 -0
- skcomms-0.2.4/tests/gen_pqdm2_fixture.py +75 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_access_exec.py +2 -7
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_access_files.py +1 -7
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_access_nonce_durable.py +7 -6
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_access_rbac.py +10 -5
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_access_routing.py +30 -16
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_access_server.py +10 -7
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_access_wiring.py +12 -3
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_ack_bind.py +1 -3
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_adapter_factory.py +2 -2
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_anon_queue.py +7 -7
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_anon_transport.py +1 -1
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_api_consent.py +0 -1
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_api_consent_token_gate.py +0 -1
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_api_cors.py +1 -4
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_api_federation_inbox.py +12 -7
- skcomms-0.2.4/tests/test_api_geo_seed.py +119 -0
- skcomms-0.2.4/tests/test_api_geo_skcot_bridge.py +223 -0
- skcomms-0.2.4/tests/test_api_geo_units.py +144 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_api_send_signed_wire.py +35 -15
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_api_skfed_directory.py +26 -12
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_backfill_file_locations.py +0 -1
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_ble_fragment.py +15 -5
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_ble_identity.py +4 -2
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_ble_noise.py +3 -3
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_ble_protocol.py +1 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_ble_relay.py +7 -2
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_broker_server.py +5 -2
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_capabilities.py +4 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_capauth_failclosed.py +1 -3
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_capauth_key_reconcile.py +1 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_capauth_resolution.py +2 -3
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_channel_adapter.py +3 -9
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_config.py +1 -2
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_consent.py +2 -2
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_consent_banfeeds.py +0 -1
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_consent_captcha.py +1 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_consent_cli.py +1 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_consent_cli_mgmt.py +1 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_consent_greylist.py +3 -2
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_consent_group_gate.py +10 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_consent_groups.py +8 -2
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_consent_moderation.py +3 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_consent_pipeline.py +5 -5
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_consent_policy.py +20 -18
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_consent_requests.py +14 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_consent_runtime.py +1 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_consent_tiering.py +6 -7
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_consent_tokens.py +1 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_core_inbound_beacon_skip.py +4 -9
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_core_send_federated.py +50 -23
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_core_send_signed.py +68 -39
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_core_stop.py +1 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_crypto_suites_q0.py +13 -7
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_delivery_semantics.py +1 -3
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_discord_adapter.py +16 -18
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_envelope_v1.py +0 -1
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_federation.py +33 -19
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_federation_integration.py +76 -28
- skcomms-0.2.4/tests/test_geo_roundtrip_skcot.py +139 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_glossa_codebook.py +3 -3
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_glossa_codec_l0.py +4 -3
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_glossa_codec_l1.py +7 -3
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_glossa_codec_l2.py +11 -12
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_glossa_emergent.py +4 -4
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_glossa_emergent_negotiator.py +5 -4
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_glossa_emergent_protocol.py +1 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_glossa_gloss.py +3 -2
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_glossa_handshake.py +5 -4
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_glossa_handshake_lexicon.py +8 -4
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_glossa_macros.py +6 -2
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_glossa_macros_render.py +6 -7
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_glossa_message.py +1 -2
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_glossa_session.py +9 -5
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_glossa_session_macros.py +10 -6
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_glossa_to_human.py +2 -4
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_grants.py +8 -17
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_home_scaffold.py +0 -1
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_housekeeping.py +3 -9
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_http_s2s_transport.py +6 -12
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_identity_env_override.py +2 -4
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_identity_key_binding.py +1 -1
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_identity_realm.py +1 -4
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_identity_trust_backup.py +5 -17
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_integration.py +7 -2
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_key_exchange_transport_scoping.py +2 -6
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_knowledge.py +13 -13
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_lora_addressing.py +1 -1
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_lora_framing.py +9 -4
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_lora_interface.py +2 -2
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_lora_store.py +10 -10
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_lora_transport.py +19 -6
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_mailbox.py +8 -8
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_mailbox_encrypt_at_rest.py +17 -24
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_mailbox_recipient_key.py +1 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_matrix_adapter.py +19 -27
- skcomms-0.2.4/tests/test_mode_b_setup.sh +157 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_no_subapp_dependency.py +2 -4
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_node_registry.py +1 -4
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_nonce_durable.py +2 -5
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_nostr_discovery.py +8 -4
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_observability.py +2 -7
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_operator_cli.py +20 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_outbox_home_alignment.py +2 -4
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_outbox_migrate.py +2 -8
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_p2p_connector.py +10 -2
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_p2p_manager.py +15 -7
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_p2p_media.py +12 -3
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_p2p_session.py +9 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_padding.py +1 -1
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_pairing.py +88 -31
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_pairing_cli.py +7 -2
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_pairing_mirror.py +45 -20
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_peers.py +5 -13
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_pqc_cutover.py +1 -1
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_pqdm.py +9 -3
- skcomms-0.2.4/tests/test_pqdm2.py +132 -0
- skcomms-0.2.4/tests/test_pqdm2_interop.py +80 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_pqkem.py +3 -9
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_pqroute_padding.py +25 -11
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_pqroute_transport.py +17 -9
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_pqsig.py +1 -3
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_public_pairing.py +0 -1
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_queue_bounds.py +1 -3
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_receiver_wire_ttl_expiry.py +11 -5
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_registry.py +2 -6
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_registry_cli.py +2 -6
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_router_failure_log_dedup.py +21 -14
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_router_perm_backoff_fixes.py +7 -3
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_router_quarantine.py +10 -3
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_router_rail_ordering.py +1 -2
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_router_route_anon.py +12 -10
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_router_route_signed.py +30 -14
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_router_star_broadcast_routing.py +10 -2
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_router_unsigned_excludes_https_s2s.py +17 -3
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_signaling_broker.py +4 -1
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_signaling_mailbox.py +34 -13
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_signaling_select.py +1 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_skfed_announce.py +17 -7
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_skfed_cli.py +12 -1
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_skfed_directory.py +4 -5
- skcomms-0.2.4/tests/test_skfed_dns.sh +75 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_skfed_operator_pin.py +18 -5
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_skfed_readdr.py +7 -6
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_skfed_resolve.py +14 -12
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_skworld_manifest.py +3 -11
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_slack_adapter.py +16 -18
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_ssrf_guard.py +4 -14
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_store_forward.py +10 -14
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_syncthing_rail.py +6 -4
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_telegram_adapter.py +28 -19
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_typed_message_content.py +3 -10
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_webrtc_ice_logging.py +1 -1
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_webrtc_signaling_log_dedup.py +3 -3
- {skcomms-0.2.2 → skcomms-0.2.4}/LICENSE +0 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/README.md +0 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/setup.cfg +0 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/access/audit.py +0 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/access/registry.py +0 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/adapters/__init__.py +0 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/adapters/base.py +0 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/adapters/factory.py +0 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/adapters/fake.py +0 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/adapters/models.py +0 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/compression.py +0 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/discovery.py +0 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/glossa/__init__.py +0 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/heartbeat.py +0 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/home.py +0 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/household_router.py +0 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/identity.py +0 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/marketplace.py +0 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/metrics.py +0 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/models.py +0 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/node_registry.py +0 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/pairing_mirror.py +0 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/paths.py +0 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/pq_provider.py +0 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/pqkem_backend.py +0 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/profile_router.py +0 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/pubsub.py +0 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/pubsub_transport.py +0 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/queue.py +0 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/ratelimit.py +0 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/realm.py +0 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/signaling.py +0 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/skworld_manifest.py +0 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/souls_router.py +0 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/transport.py +0 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/transports/__init__.py +0 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/transports/audio_track.py +0 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/transports/ble/__init__.py +0 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/transports/ble/radio.py +0 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/transports/broker_server.py +0 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/transports/lora/__init__.py +0 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/transports/nostr.py +0 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/transports/p2p_connector.py +0 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/transports/signaling_base.py +0 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/transports/syncthing.py +0 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/transports/tailscale.py +0 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/transports/video_track.py +0 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/transports/webrtc_media.py +0 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms/transports/websocket.py +0 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms.egg-info/dependency_links.txt +0 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms.egg-info/entry_points.txt +0 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms.egg-info/requires.txt +0 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/src/skcomms.egg-info/top_level.txt +0 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_adapter_fake.py +0 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_api_access_token.py +0 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_api_health.py +0 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_ble_gatt.py +0 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_ble_mesh.py +0 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_ble_pairing_bundle.py +0 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_ble_radio.py +0 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_capauth_revoked_expired.py +0 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_cluster_schema.py +0 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_consent_ban_gate_fail_closed.py +0 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_crypto_failclosed.py +0 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_daemon_adapter_lifecycle.py +0 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_deadletter_ops.py +0 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_encrypt_fail_closed.py +0 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_envelope_consent_token.py +0 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_http_s2s_star_recipient.py +0 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_hybrid_envelope_sig.py +0 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_lora_meshtastic_iface.py +0 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_paths_scoping.py +0 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_peer_inbox_traversal.py +0 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_pqc_shim.py +0 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_pqroute.py +0 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_prune_inbox.py +0 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_router_perm_backoff.py +0 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_sign_fail_closed.py +0 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_skfed_ssrf.py +0 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_smoke.py +0 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_syncthing_recipient_guard.py +0 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_tofu.py +0 -0
- {skcomms-0.2.2 → skcomms-0.2.4}/tests/test_webrtc_bridge_lifecycle.py +0 -0
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
test:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
strategy:
|
|
13
|
+
matrix:
|
|
14
|
+
python-version: ["3.10", "3.11", "3.12"]
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v4
|
|
17
|
+
with:
|
|
18
|
+
# setuptools-scm derives the version from the git tag, so a
|
|
19
|
+
# shallow checkout would yield a placeholder like 0.1.dev1 and
|
|
20
|
+
# break dependency resolution against pinned siblings.
|
|
21
|
+
fetch-depth: 0
|
|
22
|
+
fetch-tags: true
|
|
23
|
+
- uses: actions/setup-python@v5
|
|
24
|
+
with:
|
|
25
|
+
python-version: ${{ matrix.python-version }}
|
|
26
|
+
- name: Install dependencies
|
|
27
|
+
# -c constraints.txt pins every dependency to the versions this repo
|
|
28
|
+
# validated, so CI does not silently drift onto newer releases.
|
|
29
|
+
run: pip install -c constraints.txt -e ".[crypto,dev,pqc]"
|
|
30
|
+
# skcomms does NOT depend on skcapstone (that would invert the direction),
|
|
31
|
+
# but tests/test_integration.py exercises "integrated" mode and assumed a
|
|
32
|
+
# dev venv where skcapstone happens to be installed. In CI it is not, so
|
|
33
|
+
# those tests errored with ModuleNotFoundError instead of testing anything.
|
|
34
|
+
# skcoord is named too (skcapstone.coordination is a re-export shim over it),
|
|
35
|
+
# and skcot, which backs geo_store.SkcotGeoStore and is git-only (not on PyPI,
|
|
36
|
+
# not declared), so CI could never have exercised the skcot bridge. --no-deps
|
|
37
|
+
# also stops this dragging a published skcomms over the checkout under test.
|
|
38
|
+
- name: Install skcapstone (optional integration backbone) from source
|
|
39
|
+
run: |
|
|
40
|
+
pip install --no-deps --no-cache-dir \
|
|
41
|
+
"skcapstone @ git+https://github.com/smilinTux/skcapstone" \
|
|
42
|
+
"skcoord @ git+https://github.com/smilinTux/skcoord" \
|
|
43
|
+
"skcot @ git+https://github.com/smilinTux/skcot" \
|
|
44
|
+
"capauth @ git+https://github.com/smilinTux/capauth"
|
|
45
|
+
- name: Run tests with coverage
|
|
46
|
+
run: python -m pytest tests/ -v --tb=short --cov=skcomms --cov-report=xml --cov-report=term-missing
|
|
47
|
+
- name: Upload coverage
|
|
48
|
+
if: matrix.python-version == '3.12'
|
|
49
|
+
uses: codecov/codecov-action@v4
|
|
50
|
+
with:
|
|
51
|
+
files: coverage.xml
|
|
52
|
+
fail_ci_if_error: false
|
|
53
|
+
|
|
54
|
+
lint:
|
|
55
|
+
runs-on: ubuntu-latest
|
|
56
|
+
steps:
|
|
57
|
+
- uses: actions/checkout@v4
|
|
58
|
+
with:
|
|
59
|
+
# setuptools-scm derives the version from the git tag, so a
|
|
60
|
+
# shallow checkout would yield a placeholder like 0.1.dev1 and
|
|
61
|
+
# break dependency resolution against pinned siblings.
|
|
62
|
+
fetch-depth: 0
|
|
63
|
+
fetch-tags: true
|
|
64
|
+
- uses: actions/setup-python@v5
|
|
65
|
+
with:
|
|
66
|
+
python-version: "3.12"
|
|
67
|
+
# Versions come from constraints.txt (black==26.5.1, ruff==0.15.21),
|
|
68
|
+
# which already does the pinning correctly. Do NOT re-pin them inline:
|
|
69
|
+
# naming a different version here makes pip unsolvable against the
|
|
70
|
+
# constraint file, which fails the job on install before it lints
|
|
71
|
+
# anything at all.
|
|
72
|
+
- name: Install lint tools
|
|
73
|
+
run: pip install -c constraints.txt black ruff
|
|
74
|
+
- name: Check formatting
|
|
75
|
+
run: black --check src/ tests/
|
|
76
|
+
- name: Lint
|
|
77
|
+
run: ruff check src/
|
|
78
|
+
|
|
79
|
+
build:
|
|
80
|
+
runs-on: ubuntu-latest
|
|
81
|
+
steps:
|
|
82
|
+
- uses: actions/checkout@v4
|
|
83
|
+
with:
|
|
84
|
+
# setuptools-scm derives the version from the git tag, so a
|
|
85
|
+
# shallow checkout would yield a placeholder like 0.1.dev1 and
|
|
86
|
+
# break dependency resolution against pinned siblings.
|
|
87
|
+
fetch-depth: 0
|
|
88
|
+
fetch-tags: true
|
|
89
|
+
- uses: actions/setup-python@v5
|
|
90
|
+
with:
|
|
91
|
+
python-version: "3.12"
|
|
92
|
+
- name: Build wheel and sdist
|
|
93
|
+
run: |
|
|
94
|
+
pip install build
|
|
95
|
+
python -m build
|
|
96
|
+
- name: Check dist
|
|
97
|
+
run: |
|
|
98
|
+
pip install twine
|
|
99
|
+
twine check dist/*
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: ["main"]
|
|
6
|
+
tags: ["v*"]
|
|
7
|
+
workflow_dispatch:
|
|
8
|
+
|
|
9
|
+
permissions:
|
|
10
|
+
contents: read
|
|
11
|
+
|
|
12
|
+
# Trusted Publishing (OIDC) is configured on PyPI for this project:
|
|
13
|
+
# owner=smilinTux workflow=publish.yml environment=pypi
|
|
14
|
+
# No PyPI token is used in the publish path. The full test suite is intentionally
|
|
15
|
+
# NOT a gate here (that lives in ci.yml on PRs); a tagged release only needs to
|
|
16
|
+
# build cleanly and pass `twine check`, so a red/flaky unrelated test never blocks
|
|
17
|
+
# a release again.
|
|
18
|
+
concurrency:
|
|
19
|
+
# Never let two releases race: a second push to main waits rather than
|
|
20
|
+
# computing the same "next" tag from a stale view of the tag list.
|
|
21
|
+
group: publish-${{ github.ref }}
|
|
22
|
+
cancel-in-progress: false
|
|
23
|
+
|
|
24
|
+
jobs:
|
|
25
|
+
# ---------------------------------------------------------------------- #
|
|
26
|
+
# Cut the release tag. Only on a push to main; skipped on a tag push.
|
|
27
|
+
# ---------------------------------------------------------------------- #
|
|
28
|
+
tag:
|
|
29
|
+
if: github.ref == 'refs/heads/main'
|
|
30
|
+
runs-on: ubuntu-latest
|
|
31
|
+
permissions:
|
|
32
|
+
contents: write
|
|
33
|
+
outputs:
|
|
34
|
+
tagged: ${{ steps.bump.outputs.tagged }}
|
|
35
|
+
steps:
|
|
36
|
+
- uses: actions/checkout@v4
|
|
37
|
+
with:
|
|
38
|
+
# Full history + tags, or `git describe` cannot see the latest tag and
|
|
39
|
+
# every run would compute v0.0.1.
|
|
40
|
+
fetch-depth: 0
|
|
41
|
+
fetch-tags: true
|
|
42
|
+
- id: bump
|
|
43
|
+
name: Cut the next patch tag if HEAD is not already tagged
|
|
44
|
+
run: |
|
|
45
|
+
set -euo pipefail
|
|
46
|
+
git config user.name "github-actions[bot]"
|
|
47
|
+
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
|
48
|
+
|
|
49
|
+
latest="$(git describe --tags --abbrev=0 --match 'v[0-9]*' 2>/dev/null || echo '')"
|
|
50
|
+
head_sha="$(git rev-parse HEAD)"
|
|
51
|
+
|
|
52
|
+
if [ -n "$latest" ] && [ "$(git rev-list -n1 "$latest")" = "$head_sha" ]; then
|
|
53
|
+
echo "HEAD is already $latest; nothing to release."
|
|
54
|
+
echo "tagged=false" >> "$GITHUB_OUTPUT"
|
|
55
|
+
exit 0
|
|
56
|
+
fi
|
|
57
|
+
|
|
58
|
+
base="${latest:-v0.0.0}"
|
|
59
|
+
ver="${base#v}"
|
|
60
|
+
IFS='.' read -r major minor patch <<< "$ver"
|
|
61
|
+
major="${major:-0}"; minor="${minor:-0}"; patch="${patch:-0}"
|
|
62
|
+
next="v${major}.${minor}.$((patch + 1))"
|
|
63
|
+
while git rev-parse -q --verify "refs/tags/$next" >/dev/null 2>&1; do
|
|
64
|
+
patch=$((patch + 1))
|
|
65
|
+
next="v${major}.${minor}.$((patch + 1))"
|
|
66
|
+
done
|
|
67
|
+
|
|
68
|
+
echo "Cutting $next at ${head_sha:0:8} (previous: ${latest:-none})"
|
|
69
|
+
git tag -a "$next" -m "release: $next from main"
|
|
70
|
+
git push origin "$next"
|
|
71
|
+
echo "tagged=true" >> "$GITHUB_OUTPUT"
|
|
72
|
+
|
|
73
|
+
build:
|
|
74
|
+
needs: [tag]
|
|
75
|
+
# `always()` is required because `needs` on a SKIPPED job would otherwise
|
|
76
|
+
# skip this one on the tag-push path.
|
|
77
|
+
if: >-
|
|
78
|
+
always() && !cancelled() &&
|
|
79
|
+
(needs.tag.result == 'skipped' || needs.tag.outputs.tagged == 'true')
|
|
80
|
+
runs-on: ubuntu-latest
|
|
81
|
+
steps:
|
|
82
|
+
- uses: actions/checkout@v4
|
|
83
|
+
with:
|
|
84
|
+
# setuptools-scm derives the version from the tag, so the tag the job
|
|
85
|
+
# above just pushed must be visible here or the build would produce a
|
|
86
|
+
# dev version with a local segment (+g<sha>), which PyPI rejects.
|
|
87
|
+
fetch-depth: 0
|
|
88
|
+
fetch-tags: true
|
|
89
|
+
- name: Refuse to publish a tag that is not on main
|
|
90
|
+
# The local pre-push hook is a symlink into each clone's working tree, so
|
|
91
|
+
# a clone that has not pulled the main-only fix keeps cutting tags at
|
|
92
|
+
# feature-branch tips and pushing them. This is the server-side backstop:
|
|
93
|
+
# it holds no matter what any developer's clone does.
|
|
94
|
+
#
|
|
95
|
+
# Override with the ALLOW_OFF_MAIN_RELEASE repository variable if a
|
|
96
|
+
# release ever legitimately needs to come off a maintenance branch.
|
|
97
|
+
if: startsWith(github.ref, 'refs/tags/')
|
|
98
|
+
run: |
|
|
99
|
+
set -euo pipefail
|
|
100
|
+
if [ "${{ vars.ALLOW_OFF_MAIN_RELEASE }}" = "1" ]; then
|
|
101
|
+
echo "ALLOW_OFF_MAIN_RELEASE=1 is set; skipping the on-main check."
|
|
102
|
+
exit 0
|
|
103
|
+
fi
|
|
104
|
+
git fetch --no-tags origin main:refs/remotes/origin/main
|
|
105
|
+
if git merge-base --is-ancestor "$GITHUB_SHA" refs/remotes/origin/main; then
|
|
106
|
+
echo "OK: ${GITHUB_REF_NAME} (${GITHUB_SHA:0:8}) is on main."
|
|
107
|
+
exit 0
|
|
108
|
+
fi
|
|
109
|
+
echo "::error::${GITHUB_REF_NAME} points at ${GITHUB_SHA:0:8}, which is NOT on main. Refusing to publish."
|
|
110
|
+
echo "::error::A tag cut off a feature branch must not become a release. Delete the tag, merge to main, and let the main push cut the release."
|
|
111
|
+
exit 1
|
|
112
|
+
- uses: actions/setup-python@v5
|
|
113
|
+
with:
|
|
114
|
+
python-version: "3.12"
|
|
115
|
+
- run: python -m pip install --upgrade build twine
|
|
116
|
+
- run: python -m build
|
|
117
|
+
- run: python -m twine check dist/*
|
|
118
|
+
- uses: actions/upload-artifact@v4
|
|
119
|
+
with:
|
|
120
|
+
name: dist
|
|
121
|
+
path: dist/
|
|
122
|
+
|
|
123
|
+
pypi-publish:
|
|
124
|
+
needs: build
|
|
125
|
+
runs-on: ubuntu-latest
|
|
126
|
+
environment: pypi
|
|
127
|
+
permissions:
|
|
128
|
+
id-token: write
|
|
129
|
+
steps:
|
|
130
|
+
- uses: actions/download-artifact@v4
|
|
131
|
+
with:
|
|
132
|
+
name: dist
|
|
133
|
+
path: dist/
|
|
134
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
name: pytest
|
|
2
|
+
|
|
3
|
+
# Runs the skcomms pytest suite on GitHub-hosted runners.
|
|
4
|
+
#
|
|
5
|
+
# GREEN-by-construction: this mirrors the repo's own known-passing invocation
|
|
6
|
+
# (see qa.yml) — install the package with its `dev` extras, then run the WHOLE
|
|
7
|
+
# suite. The suite is CI-clean: it requires no live external services and no
|
|
8
|
+
# sibling sk* packages.
|
|
9
|
+
#
|
|
10
|
+
# Honest notes on scope (verified 2026-06-28):
|
|
11
|
+
# * There are NO custom pytest markers in this repo (no `integration`,
|
|
12
|
+
# `e2e_live`, `bunker`, etc. registered or applied). So there is nothing to
|
|
13
|
+
# exclude with `-m "not ..."` — adding such a filter would be fabricated.
|
|
14
|
+
# * Optional-transport tests (telegram/discord/webrtc/zeroconf/liboqs) and the
|
|
15
|
+
# capauth/skcapstone-dependent paths self-skip via pytest.importorskip /
|
|
16
|
+
# @pytest.mark.skipif when those packages are absent. The `dev` extras
|
|
17
|
+
# (pytest, pytest-asyncio, fastapi, httpx, pgpy, websockets, cryptography)
|
|
18
|
+
# are the deliberate known-green dependency set; sibling sk* packages
|
|
19
|
+
# (capauth, skcapstone, sk-pqc) are NOT installed and the suite stays green
|
|
20
|
+
# without them.
|
|
21
|
+
|
|
22
|
+
on:
|
|
23
|
+
push:
|
|
24
|
+
branches: ["main"]
|
|
25
|
+
pull_request:
|
|
26
|
+
branches: ["main"]
|
|
27
|
+
|
|
28
|
+
permissions:
|
|
29
|
+
contents: read
|
|
30
|
+
|
|
31
|
+
jobs:
|
|
32
|
+
pytest:
|
|
33
|
+
runs-on: ubuntu-latest
|
|
34
|
+
strategy:
|
|
35
|
+
fail-fast: false
|
|
36
|
+
matrix:
|
|
37
|
+
python-version: ["3.11", "3.12"]
|
|
38
|
+
steps:
|
|
39
|
+
- uses: actions/checkout@v4
|
|
40
|
+
with:
|
|
41
|
+
# setuptools-scm derives the version from the git tag, so a
|
|
42
|
+
# shallow checkout would yield a placeholder like 0.1.dev1 and
|
|
43
|
+
# break dependency resolution against pinned siblings.
|
|
44
|
+
fetch-depth: 0
|
|
45
|
+
fetch-tags: true
|
|
46
|
+
- uses: actions/setup-python@v5
|
|
47
|
+
with:
|
|
48
|
+
python-version: ${{ matrix.python-version }}
|
|
49
|
+
cache: pip
|
|
50
|
+
- name: Install skcomms + dev extras
|
|
51
|
+
# -c constraints.txt pins the dev/runtime set to the versions this repo
|
|
52
|
+
# validated, so a fresh runner installs exactly what CI last tested.
|
|
53
|
+
run: |
|
|
54
|
+
python -m pip install --upgrade pip
|
|
55
|
+
pip install -c constraints.txt -e ".[crypto,dev,pqc]"
|
|
56
|
+
# skcomms does NOT depend on skcapstone (that would invert the direction),
|
|
57
|
+
# but tests/test_integration.py exercises "integrated" mode and assumed a
|
|
58
|
+
# dev venv where skcapstone happens to be installed. In CI it is not, so
|
|
59
|
+
# those tests errored with ModuleNotFoundError instead of testing anything.
|
|
60
|
+
# skcoord is named too (skcapstone.coordination is a re-export shim over it),
|
|
61
|
+
# and skcot, which backs geo_store.SkcotGeoStore and is git-only (not on PyPI,
|
|
62
|
+
# not declared), so CI could never have exercised the skcot bridge. --no-deps
|
|
63
|
+
# also stops this dragging a published skcomms over the checkout under test.
|
|
64
|
+
- name: Install skcapstone (optional integration backbone) from source
|
|
65
|
+
run: |
|
|
66
|
+
pip install --no-deps --no-cache-dir \
|
|
67
|
+
"skcapstone @ git+https://github.com/smilinTux/skcapstone" \
|
|
68
|
+
"skcoord @ git+https://github.com/smilinTux/skcoord" \
|
|
69
|
+
"skcot @ git+https://github.com/smilinTux/skcot" \
|
|
70
|
+
"capauth @ git+https://github.com/smilinTux/capauth"
|
|
71
|
+
- name: Run pytest (full suite)
|
|
72
|
+
run: python -m pytest tests/ -q
|
|
73
|
+
|
|
74
|
+
# The pqdm/pqdm2 crypto gates are the ONE place a wire-format drift between
|
|
75
|
+
# this repo and the Dart client (sk-pqc-dart / skworld-app) gets caught, and
|
|
76
|
+
# they are exactly the tests the `dev`-extras job above cannot run: every
|
|
77
|
+
# hybrid KEM op needs liboqs, and pqdm.open_multi() swallows a missing backend
|
|
78
|
+
# into a plain `None` return, so without liboqs the gate cannot fail-loud — it
|
|
79
|
+
# self-skips. This job installs the `pqc` extra so the gate genuinely runs.
|
|
80
|
+
#
|
|
81
|
+
# liboqs-python builds liboqs from source into ~/_oqs on first import when it
|
|
82
|
+
# cannot find a system copy, so that directory is cached across runs.
|
|
83
|
+
pqc-interop:
|
|
84
|
+
runs-on: ubuntu-latest
|
|
85
|
+
steps:
|
|
86
|
+
- uses: actions/checkout@v4
|
|
87
|
+
with:
|
|
88
|
+
# setuptools-scm derives the version from the git tag, so a
|
|
89
|
+
# shallow checkout would yield a placeholder like 0.1.dev1 and
|
|
90
|
+
# break dependency resolution against pinned siblings.
|
|
91
|
+
fetch-depth: 0
|
|
92
|
+
fetch-tags: true
|
|
93
|
+
- uses: actions/setup-python@v5
|
|
94
|
+
with:
|
|
95
|
+
python-version: "3.12"
|
|
96
|
+
cache: pip
|
|
97
|
+
- name: Cache the liboqs build
|
|
98
|
+
uses: actions/cache@v4
|
|
99
|
+
with:
|
|
100
|
+
path: ~/_oqs
|
|
101
|
+
key: liboqs-${{ runner.os }}-${{ hashFiles('constraints.txt') }}
|
|
102
|
+
- name: Install skcomms + dev + pqc extras
|
|
103
|
+
run: |
|
|
104
|
+
python -m pip install --upgrade pip
|
|
105
|
+
pip install -c constraints.txt -e ".[crypto,dev,pqc]"
|
|
106
|
+
# skcomms does NOT depend on skcapstone (that would invert the direction),
|
|
107
|
+
# but tests/test_integration.py exercises "integrated" mode and assumed a
|
|
108
|
+
# dev venv where skcapstone happens to be installed. In CI it is not, so
|
|
109
|
+
# those tests errored with ModuleNotFoundError instead of testing anything.
|
|
110
|
+
# skcoord is named too (skcapstone.coordination is a re-export shim over it),
|
|
111
|
+
# and skcot, which backs geo_store.SkcotGeoStore and is git-only (not on PyPI,
|
|
112
|
+
# not declared), so CI could never have exercised the skcot bridge. --no-deps
|
|
113
|
+
# also stops this dragging a published skcomms over the checkout under test.
|
|
114
|
+
- name: Install skcapstone (optional integration backbone) from source
|
|
115
|
+
run: |
|
|
116
|
+
pip install --no-deps --no-cache-dir \
|
|
117
|
+
"skcapstone @ git+https://github.com/smilinTux/skcapstone" \
|
|
118
|
+
"skcoord @ git+https://github.com/smilinTux/skcoord" \
|
|
119
|
+
"skcot @ git+https://github.com/smilinTux/skcot" \
|
|
120
|
+
"capauth @ git+https://github.com/smilinTux/capauth"
|
|
121
|
+
- name: Assert the PQ backend is really present
|
|
122
|
+
# Without this the crypto gates would silently self-skip and the job
|
|
123
|
+
# would report green while proving nothing.
|
|
124
|
+
run: |
|
|
125
|
+
python -c "from skcomms import pqkem; assert pqkem.is_available(), 'liboqs missing: the pqdm gates would self-skip'"
|
|
126
|
+
- name: Run the pqdm / pqdm2 interop gates
|
|
127
|
+
run: python -m pytest tests/test_pqdm.py tests/test_pqdm2.py tests/test_pqdm2_interop.py -q
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
name: QA
|
|
2
|
+
|
|
3
|
+
# Runs the full skcomms QA pytest suite on every push to main, every PR, and
|
|
4
|
+
# every version tag. The suite is CI-clean (no live external services required),
|
|
5
|
+
# so we run it whole.
|
|
6
|
+
|
|
7
|
+
on:
|
|
8
|
+
push:
|
|
9
|
+
branches: ["main"]
|
|
10
|
+
tags: ["v*"]
|
|
11
|
+
pull_request:
|
|
12
|
+
|
|
13
|
+
permissions:
|
|
14
|
+
contents: read
|
|
15
|
+
|
|
16
|
+
jobs:
|
|
17
|
+
qa:
|
|
18
|
+
runs-on: ubuntu-latest
|
|
19
|
+
strategy:
|
|
20
|
+
fail-fast: false
|
|
21
|
+
matrix:
|
|
22
|
+
python-version: ["3.10", "3.11", "3.12"]
|
|
23
|
+
steps:
|
|
24
|
+
- uses: actions/checkout@v4
|
|
25
|
+
with:
|
|
26
|
+
# setuptools-scm derives the version from the git tag, so a
|
|
27
|
+
# shallow checkout would yield a placeholder like 0.1.dev1 and
|
|
28
|
+
# break dependency resolution against pinned siblings.
|
|
29
|
+
fetch-depth: 0
|
|
30
|
+
fetch-tags: true
|
|
31
|
+
- uses: actions/setup-python@v5
|
|
32
|
+
with:
|
|
33
|
+
python-version: ${{ matrix.python-version }}
|
|
34
|
+
- name: Install package + dev deps
|
|
35
|
+
# -c constraints.txt pins to the versions this repo validated (inert on
|
|
36
|
+
# the fallback branch, which installs a smaller set).
|
|
37
|
+
run: |
|
|
38
|
+
pip install -c constraints.txt -e ".[crypto,dev,pqc]" || { pip install -c constraints.txt -e . && pip install -c constraints.txt pytest pytest-asyncio; }
|
|
39
|
+
# skcomms does NOT depend on skcapstone (that would invert the direction),
|
|
40
|
+
# but tests/test_integration.py exercises "integrated" mode and assumed a
|
|
41
|
+
# dev venv where skcapstone happens to be installed. In CI it is not, so
|
|
42
|
+
# those tests errored with ModuleNotFoundError instead of testing anything.
|
|
43
|
+
# skcoord is named too (skcapstone.coordination is a re-export shim over it),
|
|
44
|
+
# and skcot, which backs geo_store.SkcotGeoStore and is git-only (not on PyPI,
|
|
45
|
+
# not declared), so CI could never have exercised the skcot bridge. --no-deps
|
|
46
|
+
# also stops this dragging a published skcomms over the checkout under test.
|
|
47
|
+
- name: Install skcapstone (optional integration backbone) from source
|
|
48
|
+
run: |
|
|
49
|
+
pip install --no-deps --no-cache-dir \
|
|
50
|
+
"skcapstone @ git+https://github.com/smilinTux/skcapstone" \
|
|
51
|
+
"skcoord @ git+https://github.com/smilinTux/skcoord" \
|
|
52
|
+
"skcot @ git+https://github.com/smilinTux/skcot" \
|
|
53
|
+
"capauth @ git+https://github.com/smilinTux/capauth"
|
|
54
|
+
- name: Run QA pytest suite
|
|
55
|
+
run: python -m pytest tests/ -q
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
name: secret-scan
|
|
2
|
+
|
|
3
|
+
# Secret-scan gate: keeps the repo's clean secrets hygiene true over time.
|
|
4
|
+
#
|
|
5
|
+
# Runs gitleaks (the fleet default, via its official GitHub Action) on every
|
|
6
|
+
# push and every pull request. The build FAILS if gitleaks finds anything not
|
|
7
|
+
# covered by the baseline allowlist in .gitleaks.toml at the repo root.
|
|
8
|
+
#
|
|
9
|
+
# The allowlist documents known non-secret placeholder tokens; see that file
|
|
10
|
+
# for how to add an entry when a real placeholder trips the scanner. If the
|
|
11
|
+
# scanner flags a REAL secret, rotate it and purge it from history, do NOT
|
|
12
|
+
# add it to the allowlist.
|
|
13
|
+
|
|
14
|
+
on:
|
|
15
|
+
push:
|
|
16
|
+
branches: ["main"]
|
|
17
|
+
pull_request:
|
|
18
|
+
branches: ["main"]
|
|
19
|
+
|
|
20
|
+
permissions:
|
|
21
|
+
contents: read
|
|
22
|
+
|
|
23
|
+
jobs:
|
|
24
|
+
gitleaks:
|
|
25
|
+
runs-on: ubuntu-latest
|
|
26
|
+
steps:
|
|
27
|
+
- uses: actions/checkout@v4
|
|
28
|
+
with:
|
|
29
|
+
# Full history so a push scans every new commit, not just the tip.
|
|
30
|
+
fetch-depth: 0
|
|
31
|
+
- name: Run gitleaks
|
|
32
|
+
uses: gitleaks/gitleaks-action@v2
|
|
33
|
+
env:
|
|
34
|
+
# Use the baseline/allowlist committed at the repo root.
|
|
35
|
+
GITLEAKS_CONFIG: ${{ github.workspace }}/.gitleaks.toml
|
|
36
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
37
|
+
# gitleaks-action requires a license for ORGANIZATION-owned repos.
|
|
38
|
+
# The note here used to say this repo ran on an individual account;
|
|
39
|
+
# it does not, it is owned by the smilinTux org, which is why every
|
|
40
|
+
# run fails with "missing gitleaks license" before scanning anything.
|
|
41
|
+
# Licensing keys on org-vs-personal, not public-vs-private, so being
|
|
42
|
+
# a public repo does not exempt it.
|
|
43
|
+
#
|
|
44
|
+
# Free key for open source at https://gitleaks.io; add it as an
|
|
45
|
+
# organization secret named GITLEAKS_LICENSE so every smilinTux repo
|
|
46
|
+
# can use the same one. Until it exists this reference is harmless:
|
|
47
|
+
# an unset secret expands to empty, exactly as today.
|
|
48
|
+
GITLEAKS_LICENSE: ${{ secrets.GITLEAKS_LICENSE }}
|
skcomms-0.2.4/.gitignore
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# gitleaks configuration for skcomms
|
|
2
|
+
#
|
|
3
|
+
# This is the baseline/allowlist that pairs with the secret-scan CI gate
|
|
4
|
+
# (.github/workflows/secret-scan.yml). It keeps the full set of gitleaks
|
|
5
|
+
# default rules and layers on an allowlist for known, non-secret placeholder
|
|
6
|
+
# tokens so the build only fails on genuine findings.
|
|
7
|
+
#
|
|
8
|
+
# How to use it:
|
|
9
|
+
# * The CI gate (gitleaks GitHub Action) reads this file automatically because
|
|
10
|
+
# it lives at the repo root and is named .gitleaks.toml.
|
|
11
|
+
# * To scan locally the same way CI does:
|
|
12
|
+
# docker run --rm -v "$(pwd):/repo" zricethezav/gitleaks:latest \
|
|
13
|
+
# detect --source /repo -c /repo/.gitleaks.toml -v
|
|
14
|
+
# * If gitleaks flags a value that is a documented placeholder or fixture
|
|
15
|
+
# (not a real secret), add it below with a justification comment. If it
|
|
16
|
+
# flags a REAL secret, rotate it and purge it from history; do NOT allowlist.
|
|
17
|
+
|
|
18
|
+
title = "skcomms gitleaks config"
|
|
19
|
+
|
|
20
|
+
# Start from the full gitleaks default ruleset, then extend with the allowlist
|
|
21
|
+
# below. Without this, only our custom rules would run.
|
|
22
|
+
[extend]
|
|
23
|
+
useDefault = true
|
|
24
|
+
|
|
25
|
+
# Global allowlists apply to every rule.
|
|
26
|
+
[[allowlists]]
|
|
27
|
+
description = """
|
|
28
|
+
Prose token "Ed25519-signed" in the BLE mesh proximity transport design spec.
|
|
29
|
+
The generic-api-key rule flags the hyphenated cryptography term (high entropy)
|
|
30
|
+
even though it is plain documentation text describing that packets are signed
|
|
31
|
+
with Ed25519, not a credential. Confirmed non-secret on 2026-07-10 by reading
|
|
32
|
+
docs/superpowers/specs/2026-06-13-ble-mesh-proximity-transport-design.md:178.
|
|
33
|
+
"""
|
|
34
|
+
paths = ['''docs/superpowers/specs/2026-06-13-ble-mesh-proximity-transport-design\.md''']
|
|
35
|
+
regexes = ['''Ed25519-signed''']
|