jring-client 0.5.0__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.
- jring_client-0.5.0/.github/workflows/distro-smoke.yml +98 -0
- jring_client-0.5.0/.github/workflows/publish-pypi.yml +120 -0
- jring_client-0.5.0/.github/workflows/release-artifacts.yml +104 -0
- jring_client-0.5.0/.github/workflows/test.yml +24 -0
- jring_client-0.5.0/.github/workflows/uv-tool-smoke.yml +42 -0
- jring_client-0.5.0/CONTRIBUTING.md +55 -0
- jring_client-0.5.0/LICENSE +21 -0
- jring_client-0.5.0/MANIFEST.in +10 -0
- jring_client-0.5.0/PKG-INFO +670 -0
- jring_client-0.5.0/README.md +640 -0
- jring_client-0.5.0/SECURITY.md +17 -0
- jring_client-0.5.0/docs/ADVERSARIAL_UX_REVIEW.md +209 -0
- jring_client-0.5.0/docs/APK_BINDER_SPEC.md +255 -0
- jring_client-0.5.0/docs/APK_CALLBACK_SPEC.md +274 -0
- jring_client-0.5.0/docs/APK_DATA_PLATFORM_SPEC.md +220 -0
- jring_client-0.5.0/docs/APK_FUNCTIONAL_SPEC.md +527 -0
- jring_client-0.5.0/docs/APK_OTA_SPEC.md +177 -0
- jring_client-0.5.0/docs/APK_PLATFORM_SPEC.md +153 -0
- jring_client-0.5.0/docs/APK_REQUEST_SPEC.md +203 -0
- jring_client-0.5.0/docs/APK_SESSION_SPEC.md +105 -0
- jring_client-0.5.0/docs/APK_TRANSPORT_SPEC.md +241 -0
- jring_client-0.5.0/docs/APK_UI_SPEC.md +344 -0
- jring_client-0.5.0/docs/COMPATIBILITY.md +97 -0
- jring_client-0.5.0/docs/DESIGN.md +702 -0
- jring_client-0.5.0/docs/EVENT_CONTRACTS.md +119 -0
- jring_client-0.5.0/docs/EXACT_SCOPE_ATTESTATION_SPEC.md +44 -0
- jring_client-0.5.0/docs/EXTERNAL_JRING_PRIOR_ART.md +35 -0
- jring_client-0.5.0/docs/INSTALL.md +352 -0
- jring_client-0.5.0/docs/JTBD.md +504 -0
- jring_client-0.5.0/docs/LICENSE_DECISION.md +83 -0
- jring_client-0.5.0/docs/OWNER_HARDWARE_EVIDENCE.md +224 -0
- jring_client-0.5.0/docs/PRIVATE_OBSERVATION_SPEC.md +68 -0
- jring_client-0.5.0/docs/PROTOCOL.md +1156 -0
- jring_client-0.5.0/docs/PUBLISHING.md +140 -0
- jring_client-0.5.0/docs/ROADMAP.md +125 -0
- jring_client-0.5.0/docs/UX_SPEC.md +1091 -0
- jring_client-0.5.0/docs/UX_TEST_MATRIX.md +74 -0
- jring_client-0.5.0/docs/VENDOR_AUTHORIZATION_GATES.md +140 -0
- jring_client-0.5.0/docs/VENDOR_GATT_TRANSACTION.md +110 -0
- jring_client-0.5.0/pyproject.toml +71 -0
- jring_client-0.5.0/requirements/release.txt +5 -0
- jring_client-0.5.0/scripts/__init__.py +1 -0
- jring_client-0.5.0/scripts/compatibility_matrix.py +280 -0
- jring_client-0.5.0/scripts/evidence_tool.py +1442 -0
- jring_client-0.5.0/scripts/generate_cli_artifacts.py +497 -0
- jring_client-0.5.0/scripts/release_artifacts.py +278 -0
- jring_client-0.5.0/setup.cfg +4 -0
- jring_client-0.5.0/src/jring/__init__.py +3 -0
- jring_client-0.5.0/src/jring/_vendor_binder_rows.py +646 -0
- jring_client-0.5.0/src/jring/_vendor_decode.py +14 -0
- jring_client-0.5.0/src/jring/bleak_transport.py +873 -0
- jring_client-0.5.0/src/jring/bluetooth_parity_manifest.py +133 -0
- jring_client-0.5.0/src/jring/clean_room_gap_registry.py +59 -0
- jring_client-0.5.0/src/jring/cli.py +3145 -0
- jring_client-0.5.0/src/jring/client.py +1074 -0
- jring_client-0.5.0/src/jring/diagnostics.py +11 -0
- jring_client-0.5.0/src/jring/discovery.py +92 -0
- jring_client-0.5.0/src/jring/errors.py +2 -0
- jring_client-0.5.0/src/jring/event_contracts.py +1008 -0
- jring_client-0.5.0/src/jring/input.py +315 -0
- jring_client-0.5.0/src/jring/non_health.py +474 -0
- jring_client-0.5.0/src/jring/owner_hardware_evidence.py +1760 -0
- jring_client-0.5.0/src/jring/private_observation.py +480 -0
- jring_client-0.5.0/src/jring/protocol.py +122 -0
- jring_client-0.5.0/src/jring/readiness.py +436 -0
- jring_client-0.5.0/src/jring/resources/completions/jring.bash +396 -0
- jring_client-0.5.0/src/jring/resources/man/jring.1 +435 -0
- jring_client-0.5.0/src/jring/transport.py +429 -0
- jring_client-0.5.0/src/jring/uuids.py +76 -0
- jring_client-0.5.0/src/jring/vendor_alarm_runtime_simulator.py +766 -0
- jring_client-0.5.0/src/jring/vendor_app_use_evidence.py +419 -0
- jring_client-0.5.0/src/jring/vendor_artifact_evidence.py +1023 -0
- jring_client-0.5.0/src/jring/vendor_authorization_gate.py +580 -0
- jring_client-0.5.0/src/jring/vendor_behavior_settings.py +457 -0
- jring_client-0.5.0/src/jring/vendor_binder_evidence.py +242 -0
- jring_client-0.5.0/src/jring/vendor_callback_event_registry.py +63 -0
- jring_client-0.5.0/src/jring/vendor_callback_surfaces.py +410 -0
- jring_client-0.5.0/src/jring/vendor_codec_registry.py +428 -0
- jring_client-0.5.0/src/jring/vendor_commands.py +509 -0
- jring_client-0.5.0/src/jring/vendor_coverage.py +698 -0
- jring_client-0.5.0/src/jring/vendor_decompilation_evidence.py +284 -0
- jring_client-0.5.0/src/jring/vendor_dispatcher_evidence.py +203 -0
- jring_client-0.5.0/src/jring/vendor_ecg_history_runtime_simulator.py +430 -0
- jring_client-0.5.0/src/jring/vendor_event_engine.py +31 -0
- jring_client-0.5.0/src/jring/vendor_gatt_preflight.py +403 -0
- jring_client-0.5.0/src/jring/vendor_gatt_transaction.py +1356 -0
- jring_client-0.5.0/src/jring/vendor_generic_history_runtime_simulator.py +492 -0
- jring_client-0.5.0/src/jring/vendor_history.py +630 -0
- jring_client-0.5.0/src/jring/vendor_history_runtime_simulator.py +477 -0
- jring_client-0.5.0/src/jring/vendor_input_preview.py +89 -0
- jring_client-0.5.0/src/jring/vendor_local_operations.py +412 -0
- jring_client-0.5.0/src/jring/vendor_main_commands.py +324 -0
- jring_client-0.5.0/src/jring/vendor_main_event_runtime_simulator.py +1096 -0
- jring_client-0.5.0/src/jring/vendor_notify.py +347 -0
- jring_client-0.5.0/src/jring/vendor_notify_runtime_simulator.py +930 -0
- jring_client-0.5.0/src/jring/vendor_operation_registry.py +484 -0
- jring_client-0.5.0/src/jring/vendor_ota_evidence.py +756 -0
- jring_client-0.5.0/src/jring/vendor_personal_settings.py +306 -0
- jring_client-0.5.0/src/jring/vendor_phone_integration.py +567 -0
- jring_client-0.5.0/src/jring/vendor_phone_volume_runtime_simulator.py +494 -0
- jring_client-0.5.0/src/jring/vendor_platform_surface.py +178 -0
- jring_client-0.5.0/src/jring/vendor_prior_art_candidate_codecs.py +71 -0
- jring_client-0.5.0/src/jring/vendor_prior_art_hypotheses.py +48 -0
- jring_client-0.5.0/src/jring/vendor_protocol.py +1377 -0
- jring_client-0.5.0/src/jring/vendor_raw_protocol.py +380 -0
- jring_client-0.5.0/src/jring/vendor_raw_runtime_simulator.py +399 -0
- jring_client-0.5.0/src/jring/vendor_request_builder_evidence.py +201 -0
- jring_client-0.5.0/src/jring/vendor_request_callback_correlation.py +698 -0
- jring_client-0.5.0/src/jring/vendor_request_integrity.py +74 -0
- jring_client-0.5.0/src/jring/vendor_request_routing.py +224 -0
- jring_client-0.5.0/src/jring/vendor_runtime_eligibility.py +201 -0
- jring_client-0.5.0/src/jring/vendor_runtime_fake.py +664 -0
- jring_client-0.5.0/src/jring/vendor_runtime_scope_eligibility.py +276 -0
- jring_client-0.5.0/src/jring/vendor_runtime_simulator.py +716 -0
- jring_client-0.5.0/src/jring/vendor_session_arbiter.py +106 -0
- jring_client-0.5.0/src/jring/vendor_session_evidence.py +480 -0
- jring_client-0.5.0/src/jring/vendor_settings.py +380 -0
- jring_client-0.5.0/src/jring/vendor_transport.py +1330 -0
- jring_client-0.5.0/src/jring/vendor_warning_evidence.py +471 -0
- jring_client-0.5.0/src/jring/vendor_wifi_runtime_simulator.py +606 -0
- jring_client-0.5.0/src/jring_client.egg-info/PKG-INFO +670 -0
- jring_client-0.5.0/src/jring_client.egg-info/SOURCES.txt +206 -0
- jring_client-0.5.0/src/jring_client.egg-info/dependency_links.txt +1 -0
- jring_client-0.5.0/src/jring_client.egg-info/entry_points.txt +3 -0
- jring_client-0.5.0/src/jring_client.egg-info/requires.txt +13 -0
- jring_client-0.5.0/src/jring_client.egg-info/top_level.txt +1 -0
- jring_client-0.5.0/tests/fixtures/compatibility/synthetic-python310.json +29 -0
- jring_client-0.5.0/tests/fixtures/compatibility/synthetic-python313.json +29 -0
- jring_client-0.5.0/tests/fixtures/evidence/synthetic-hid-fixture.json +20 -0
- jring_client-0.5.0/tests/fixtures/evidence/synthetic-hid-manifest.json +34 -0
- jring_client-0.5.0/tests/fixtures/evidence/synthetic-vendor-device-info-claim.json +91 -0
- jring_client-0.5.0/tests/fixtures/evidence/synthetic-vendor-device-info-fixture.json +75 -0
- jring_client-0.5.0/tests/test_bleak_transport.py +1221 -0
- jring_client-0.5.0/tests/test_bluetooth_parity_manifest.py +47 -0
- jring_client-0.5.0/tests/test_capabilities.py +891 -0
- jring_client-0.5.0/tests/test_clean_room_gap_registry.py +26 -0
- jring_client-0.5.0/tests/test_cli.py +2222 -0
- jring_client-0.5.0/tests/test_cli_artifacts.py +409 -0
- jring_client-0.5.0/tests/test_client.py +224 -0
- jring_client-0.5.0/tests/test_compatibility.py +111 -0
- jring_client-0.5.0/tests/test_event_contracts.py +736 -0
- jring_client-0.5.0/tests/test_evidence.py +1352 -0
- jring_client-0.5.0/tests/test_hardware.py +13 -0
- jring_client-0.5.0/tests/test_heart_rate_runtime.py +305 -0
- jring_client-0.5.0/tests/test_input.py +239 -0
- jring_client-0.5.0/tests/test_install_portability.py +135 -0
- jring_client-0.5.0/tests/test_license.py +33 -0
- jring_client-0.5.0/tests/test_non_health.py +369 -0
- jring_client-0.5.0/tests/test_owner_hardware_evidence_adversarial.py +1002 -0
- jring_client-0.5.0/tests/test_owner_hardware_evidence_runner.py +882 -0
- jring_client-0.5.0/tests/test_package_metadata.py +248 -0
- jring_client-0.5.0/tests/test_private_observation.py +312 -0
- jring_client-0.5.0/tests/test_protocol.py +95 -0
- jring_client-0.5.0/tests/test_publishing_workflow.py +151 -0
- jring_client-0.5.0/tests/test_readiness.py +238 -0
- jring_client-0.5.0/tests/test_release.py +243 -0
- jring_client-0.5.0/tests/test_safety.py +53 -0
- jring_client-0.5.0/tests/test_scope_keyed_runtime_eligibility.py +131 -0
- jring_client-0.5.0/tests/test_symphony_workflow.py +63 -0
- jring_client-0.5.0/tests/test_vendor_alarm_runtime_simulator.py +688 -0
- jring_client-0.5.0/tests/test_vendor_app_use_evidence.py +144 -0
- jring_client-0.5.0/tests/test_vendor_artifact_evidence.py +510 -0
- jring_client-0.5.0/tests/test_vendor_authorization_gate.py +439 -0
- jring_client-0.5.0/tests/test_vendor_behavior_settings.py +284 -0
- jring_client-0.5.0/tests/test_vendor_binder_evidence.py +171 -0
- jring_client-0.5.0/tests/test_vendor_callback_event_registry.py +29 -0
- jring_client-0.5.0/tests/test_vendor_callback_surfaces.py +194 -0
- jring_client-0.5.0/tests/test_vendor_codec_registry.py +136 -0
- jring_client-0.5.0/tests/test_vendor_commands.py +402 -0
- jring_client-0.5.0/tests/test_vendor_coverage.py +483 -0
- jring_client-0.5.0/tests/test_vendor_decompilation_evidence.py +186 -0
- jring_client-0.5.0/tests/test_vendor_dispatcher_evidence.py +85 -0
- jring_client-0.5.0/tests/test_vendor_ecg_history_runtime_simulator.py +427 -0
- jring_client-0.5.0/tests/test_vendor_event_engine.py +18 -0
- jring_client-0.5.0/tests/test_vendor_gatt_preflight.py +480 -0
- jring_client-0.5.0/tests/test_vendor_gatt_transaction.py +683 -0
- jring_client-0.5.0/tests/test_vendor_generic_history_runtime_simulator.py +450 -0
- jring_client-0.5.0/tests/test_vendor_history.py +460 -0
- jring_client-0.5.0/tests/test_vendor_history_runtime_simulator.py +388 -0
- jring_client-0.5.0/tests/test_vendor_input_preview.py +91 -0
- jring_client-0.5.0/tests/test_vendor_local_operations.py +249 -0
- jring_client-0.5.0/tests/test_vendor_main_commands.py +185 -0
- jring_client-0.5.0/tests/test_vendor_main_event_runtime_simulator.py +1352 -0
- jring_client-0.5.0/tests/test_vendor_notify.py +267 -0
- jring_client-0.5.0/tests/test_vendor_notify_runtime_simulator.py +757 -0
- jring_client-0.5.0/tests/test_vendor_operation_registry.py +188 -0
- jring_client-0.5.0/tests/test_vendor_ota_evidence.py +310 -0
- jring_client-0.5.0/tests/test_vendor_personal_settings.py +282 -0
- jring_client-0.5.0/tests/test_vendor_phone_integration.py +278 -0
- jring_client-0.5.0/tests/test_vendor_phone_volume_runtime_simulator.py +313 -0
- jring_client-0.5.0/tests/test_vendor_platform_surface.py +118 -0
- jring_client-0.5.0/tests/test_vendor_prior_art_candidate_codecs.py +29 -0
- jring_client-0.5.0/tests/test_vendor_prior_art_hypotheses.py +23 -0
- jring_client-0.5.0/tests/test_vendor_protocol.py +1166 -0
- jring_client-0.5.0/tests/test_vendor_raw_protocol.py +303 -0
- jring_client-0.5.0/tests/test_vendor_raw_runtime_simulator.py +298 -0
- jring_client-0.5.0/tests/test_vendor_request_builder_evidence.py +162 -0
- jring_client-0.5.0/tests/test_vendor_request_callback_correlation.py +710 -0
- jring_client-0.5.0/tests/test_vendor_request_routing.py +100 -0
- jring_client-0.5.0/tests/test_vendor_runtime_eligibility.py +135 -0
- jring_client-0.5.0/tests/test_vendor_runtime_fake.py +555 -0
- jring_client-0.5.0/tests/test_vendor_runtime_simulator.py +857 -0
- jring_client-0.5.0/tests/test_vendor_session_arbiter.py +35 -0
- jring_client-0.5.0/tests/test_vendor_session_evidence.py +222 -0
- jring_client-0.5.0/tests/test_vendor_settings.py +283 -0
- jring_client-0.5.0/tests/test_vendor_transport.py +1420 -0
- jring_client-0.5.0/tests/test_vendor_warning_evidence.py +210 -0
- jring_client-0.5.0/tests/test_vendor_wifi_runtime_simulator.py +645 -0
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
name: Native container smoke
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
pull_request:
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
contents: read
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
distro-smoke:
|
|
12
|
+
runs-on: ubuntu-24.04
|
|
13
|
+
timeout-minutes: 25
|
|
14
|
+
container:
|
|
15
|
+
image: ${{ matrix.image }}
|
|
16
|
+
strategy:
|
|
17
|
+
fail-fast: false
|
|
18
|
+
max-parallel: 2
|
|
19
|
+
matrix:
|
|
20
|
+
include:
|
|
21
|
+
- family: debian
|
|
22
|
+
image: debian:13-slim
|
|
23
|
+
python_command: python3
|
|
24
|
+
- family: fedora
|
|
25
|
+
image: fedora:44
|
|
26
|
+
python_command: python3
|
|
27
|
+
- family: enterprise-linux-9
|
|
28
|
+
# Follow Rocky's supported EL9 minor; retired minor repos are unsuitable CI inputs.
|
|
29
|
+
image: rockylinux/rockylinux:9
|
|
30
|
+
python_command: python3.11
|
|
31
|
+
# Arch is a rolling distribution and does not publish fixed release tags.
|
|
32
|
+
- family: arch
|
|
33
|
+
image: archlinux:base
|
|
34
|
+
python_command: python
|
|
35
|
+
- family: opensuse
|
|
36
|
+
image: opensuse/leap:15.6
|
|
37
|
+
python_command: python3.11
|
|
38
|
+
env:
|
|
39
|
+
JRING_HARDWARE_TEST: "0"
|
|
40
|
+
PIP_DISABLE_PIP_VERSION_CHECK: "1"
|
|
41
|
+
steps:
|
|
42
|
+
- name: Install ephemeral native prerequisites
|
|
43
|
+
shell: sh
|
|
44
|
+
run: |
|
|
45
|
+
case "${{ matrix.family }}" in
|
|
46
|
+
debian)
|
|
47
|
+
export DEBIAN_FRONTEND=noninteractive
|
|
48
|
+
apt-get update
|
|
49
|
+
apt-get install -y --no-install-recommends \
|
|
50
|
+
git ca-certificates python3 python3-venv python3-pip python3-dev \
|
|
51
|
+
build-essential linux-libc-dev bluez
|
|
52
|
+
;;
|
|
53
|
+
fedora)
|
|
54
|
+
dnf install -y \
|
|
55
|
+
git ca-certificates python3 python3-pip python3-devel gcc \
|
|
56
|
+
kernel-headers bluez
|
|
57
|
+
;;
|
|
58
|
+
enterprise-linux-9)
|
|
59
|
+
dnf install -y \
|
|
60
|
+
git ca-certificates python3.11 python3.11-pip python3.11-devel \
|
|
61
|
+
gcc kernel-headers bluez
|
|
62
|
+
;;
|
|
63
|
+
arch)
|
|
64
|
+
pacman -Syu --noconfirm --needed \
|
|
65
|
+
git ca-certificates python python-pip base-devel linux-api-headers \
|
|
66
|
+
bluez bluez-utils
|
|
67
|
+
;;
|
|
68
|
+
opensuse)
|
|
69
|
+
zypper --non-interactive install --no-recommends \
|
|
70
|
+
git ca-certificates python311 python311-pip python311-devel gcc make \
|
|
71
|
+
linux-glibc-devel bluez
|
|
72
|
+
;;
|
|
73
|
+
*)
|
|
74
|
+
echo "unsupported smoke family" >&2
|
|
75
|
+
exit 2
|
|
76
|
+
;;
|
|
77
|
+
esac
|
|
78
|
+
|
|
79
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
80
|
+
|
|
81
|
+
- name: Create isolated environment and install all extras
|
|
82
|
+
shell: sh
|
|
83
|
+
run: |
|
|
84
|
+
"${{ matrix.python_command }}" --version
|
|
85
|
+
"${{ matrix.python_command }}" -m venv /tmp/jring-smoke-venv
|
|
86
|
+
. /tmp/jring-smoke-venv/bin/activate
|
|
87
|
+
python -m pip install --upgrade pip
|
|
88
|
+
python -m pip install -e '.[ble,input,dev]'
|
|
89
|
+
|
|
90
|
+
- name: Run non-hardware tests and passive simulator smoke
|
|
91
|
+
shell: sh
|
|
92
|
+
run: |
|
|
93
|
+
. /tmp/jring-smoke-venv/bin/activate
|
|
94
|
+
python -m pytest -q
|
|
95
|
+
jring doctor --json
|
|
96
|
+
jring status --simulate --json
|
|
97
|
+
jring capabilities --simulate --json
|
|
98
|
+
jring input --simulate --map step=key:space
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
name: publish-pypi
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
inputs:
|
|
6
|
+
publish:
|
|
7
|
+
description: Publish the validated artifacts to PyPI after environment approval
|
|
8
|
+
required: true
|
|
9
|
+
type: boolean
|
|
10
|
+
default: false
|
|
11
|
+
push:
|
|
12
|
+
tags: ["v*"]
|
|
13
|
+
|
|
14
|
+
permissions: {}
|
|
15
|
+
|
|
16
|
+
concurrency:
|
|
17
|
+
group: publish-pypi-${{ github.ref }}
|
|
18
|
+
cancel-in-progress: false
|
|
19
|
+
|
|
20
|
+
jobs:
|
|
21
|
+
build-and-validate:
|
|
22
|
+
runs-on: ubuntu-latest
|
|
23
|
+
permissions:
|
|
24
|
+
contents: read
|
|
25
|
+
outputs:
|
|
26
|
+
artifact-id: ${{ steps.upload.outputs.artifact-id }}
|
|
27
|
+
steps:
|
|
28
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
29
|
+
with:
|
|
30
|
+
persist-credentials: false
|
|
31
|
+
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
32
|
+
with:
|
|
33
|
+
python-version: "3.13"
|
|
34
|
+
cache: pip
|
|
35
|
+
- name: Install pinned build tools
|
|
36
|
+
run: python -m pip install -r requirements/release.txt
|
|
37
|
+
- name: Validate source and publishing intent
|
|
38
|
+
shell: bash
|
|
39
|
+
env:
|
|
40
|
+
PUBLISH_REQUESTED: ${{ (github.event_name == 'push' && github.ref_type == 'tag') || inputs.publish }}
|
|
41
|
+
run: |
|
|
42
|
+
set -euo pipefail
|
|
43
|
+
git diff --exit-code
|
|
44
|
+
python scripts/evidence_tool.py scan .
|
|
45
|
+
if [[ "${GITHUB_REF_TYPE}" == "tag" ]]; then
|
|
46
|
+
python scripts/release_artifacts.py check-version "${GITHUB_REF_NAME}"
|
|
47
|
+
elif [[ "${PUBLISH_REQUESTED}" == "true" ]]; then
|
|
48
|
+
echo "Publishing requires selecting the matching protected version tag." >&2
|
|
49
|
+
exit 2
|
|
50
|
+
fi
|
|
51
|
+
python scripts/generate_cli_artifacts.py --check
|
|
52
|
+
if [[ "${PUBLISH_REQUESTED}" == "true" && "${GITHUB_REF_PROTECTED}" != "true" ]]; then
|
|
53
|
+
echo "Publishing requires a protected tag." >&2
|
|
54
|
+
exit 2
|
|
55
|
+
fi
|
|
56
|
+
- name: Build twice and validate reproducibility
|
|
57
|
+
shell: bash
|
|
58
|
+
run: |
|
|
59
|
+
set -euo pipefail
|
|
60
|
+
export SOURCE_DATE_EPOCH="$(git show -s --format=%ct HEAD)"
|
|
61
|
+
python -m build --no-isolation --outdir dist-a
|
|
62
|
+
python -m build --no-isolation --outdir dist-b
|
|
63
|
+
python scripts/release_artifacts.py normalize-sdist dist-a/*.tar.gz --epoch "${SOURCE_DATE_EPOCH}"
|
|
64
|
+
python scripts/release_artifacts.py normalize-sdist dist-b/*.tar.gz --epoch "${SOURCE_DATE_EPOCH}"
|
|
65
|
+
python scripts/release_artifacts.py compare dist-a dist-b
|
|
66
|
+
python scripts/release_artifacts.py inspect dist-a
|
|
67
|
+
mkdir dist
|
|
68
|
+
cp dist-a/*.whl dist-a/*.tar.gz dist/
|
|
69
|
+
- name: Install exact wheel and smoke offline paths
|
|
70
|
+
shell: bash
|
|
71
|
+
run: |
|
|
72
|
+
set -euo pipefail
|
|
73
|
+
python -m venv /tmp/jring-publish-smoke
|
|
74
|
+
/tmp/jring-publish-smoke/bin/python -m pip install --no-index --no-deps dist/*.whl
|
|
75
|
+
cd /tmp
|
|
76
|
+
/tmp/jring-publish-smoke/bin/jring doctor --json
|
|
77
|
+
/tmp/jring-publish-smoke/bin/jring status --simulate --json
|
|
78
|
+
/tmp/jring-publish-smoke/bin/jring capabilities --simulate --json
|
|
79
|
+
- name: Store the exact validated distributions
|
|
80
|
+
id: upload
|
|
81
|
+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
|
82
|
+
with:
|
|
83
|
+
name: pypi-distributions-${{ github.sha }}
|
|
84
|
+
path: |
|
|
85
|
+
dist/*.whl
|
|
86
|
+
dist/*.tar.gz
|
|
87
|
+
if-no-files-found: error
|
|
88
|
+
retention-days: 2
|
|
89
|
+
|
|
90
|
+
publish-pypi:
|
|
91
|
+
needs: build-and-validate
|
|
92
|
+
if: >-
|
|
93
|
+
(
|
|
94
|
+
github.event_name == 'push' &&
|
|
95
|
+
github.ref_type == 'tag' &&
|
|
96
|
+
github.ref_protected == true &&
|
|
97
|
+
startsWith(github.ref_name, 'v')
|
|
98
|
+
) || (
|
|
99
|
+
inputs.publish == true &&
|
|
100
|
+
github.ref_type == 'tag' &&
|
|
101
|
+
github.ref_protected == true &&
|
|
102
|
+
startsWith(github.ref_name, 'v')
|
|
103
|
+
)
|
|
104
|
+
runs-on: ubuntu-latest
|
|
105
|
+
environment:
|
|
106
|
+
name: pypi
|
|
107
|
+
url: https://pypi.org/project/jring-client/
|
|
108
|
+
permissions:
|
|
109
|
+
id-token: write
|
|
110
|
+
steps:
|
|
111
|
+
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
|
112
|
+
with:
|
|
113
|
+
artifact-ids: ${{ needs.build-and-validate.outputs.artifact-id }}
|
|
114
|
+
path: dist
|
|
115
|
+
- uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # v1.14.2
|
|
116
|
+
with:
|
|
117
|
+
packages-dir: dist
|
|
118
|
+
attestations: true
|
|
119
|
+
print-hash: true
|
|
120
|
+
verbose: false
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
name: release-artifacts
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
push:
|
|
6
|
+
tags: ["v*"]
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: read
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
build-and-verify:
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
permissions:
|
|
15
|
+
contents: read
|
|
16
|
+
id-token: write
|
|
17
|
+
attestations: write
|
|
18
|
+
steps:
|
|
19
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
20
|
+
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
21
|
+
with:
|
|
22
|
+
python-version: "3.13"
|
|
23
|
+
cache: pip
|
|
24
|
+
- name: Install pinned build tools
|
|
25
|
+
shell: bash
|
|
26
|
+
run: |
|
|
27
|
+
python -m pip download --only-binary=:all: \
|
|
28
|
+
--dest /tmp/jring-build-wheelhouse -r requirements/release.txt
|
|
29
|
+
python -m pip install -r requirements/release.txt
|
|
30
|
+
- name: Require a clean source and matching tag
|
|
31
|
+
shell: bash
|
|
32
|
+
run: |
|
|
33
|
+
git diff --exit-code
|
|
34
|
+
python scripts/evidence_tool.py scan .
|
|
35
|
+
if [[ "${GITHUB_REF_TYPE}" == "tag" ]]; then
|
|
36
|
+
python scripts/release_artifacts.py check-version "${GITHUB_REF_NAME}"
|
|
37
|
+
fi
|
|
38
|
+
python scripts/generate_cli_artifacts.py --check
|
|
39
|
+
- name: Prove isolated no-index build from pinned inputs
|
|
40
|
+
shell: bash
|
|
41
|
+
run: |
|
|
42
|
+
mkdir /tmp/jring-offline-source /tmp/jring-offline-dist
|
|
43
|
+
git archive HEAD -o /tmp/jring-offline-source.tar
|
|
44
|
+
tar -xf /tmp/jring-offline-source.tar -C /tmp/jring-offline-source
|
|
45
|
+
python -m venv /tmp/jring-offline-build
|
|
46
|
+
/tmp/jring-offline-build/bin/python -m pip install --no-index --find-links \
|
|
47
|
+
/tmp/jring-build-wheelhouse -r requirements/release.txt
|
|
48
|
+
cd /tmp/jring-offline-source
|
|
49
|
+
PIP_NO_INDEX=1 PIP_FIND_LINKS=/tmp/jring-build-wheelhouse \
|
|
50
|
+
/tmp/jring-offline-build/bin/python -m build \
|
|
51
|
+
--outdir /tmp/jring-offline-dist
|
|
52
|
+
/tmp/jring-offline-build/bin/python scripts/release_artifacts.py \
|
|
53
|
+
inspect /tmp/jring-offline-dist
|
|
54
|
+
- name: Build twice and compare bytes
|
|
55
|
+
shell: bash
|
|
56
|
+
run: |
|
|
57
|
+
export SOURCE_DATE_EPOCH="$(git show -s --format=%ct HEAD)"
|
|
58
|
+
python -m build --no-isolation --outdir dist-a
|
|
59
|
+
python -m build --no-isolation --outdir dist-b
|
|
60
|
+
python scripts/release_artifacts.py normalize-sdist dist-a/*.tar.gz --epoch "${SOURCE_DATE_EPOCH}"
|
|
61
|
+
python scripts/release_artifacts.py normalize-sdist dist-b/*.tar.gz --epoch "${SOURCE_DATE_EPOCH}"
|
|
62
|
+
python scripts/release_artifacts.py compare dist-a dist-b
|
|
63
|
+
python scripts/release_artifacts.py inspect dist-a
|
|
64
|
+
mkdir dist
|
|
65
|
+
cp dist-a/* dist/
|
|
66
|
+
python scripts/release_artifacts.py checksums dist
|
|
67
|
+
- name: Attest artifact provenance
|
|
68
|
+
uses: actions/attest-build-provenance@4d101475d8b20a2381f78447822ac1eab6504dd8 # v4.2.2
|
|
69
|
+
with:
|
|
70
|
+
subject-path: |
|
|
71
|
+
dist/*.whl
|
|
72
|
+
dist/*.tar.gz
|
|
73
|
+
dist/SHA256SUMS
|
|
74
|
+
- name: Upload reviewed artifacts without publishing a release
|
|
75
|
+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
|
76
|
+
with:
|
|
77
|
+
name: jring-client-${{ github.sha }}
|
|
78
|
+
path: dist/
|
|
79
|
+
if-no-files-found: error
|
|
80
|
+
retention-days: 14
|
|
81
|
+
|
|
82
|
+
clean-install-smoke:
|
|
83
|
+
needs: build-and-verify
|
|
84
|
+
runs-on: ubuntu-latest
|
|
85
|
+
strategy:
|
|
86
|
+
matrix:
|
|
87
|
+
python-version: ["3.10", "3.13"]
|
|
88
|
+
steps:
|
|
89
|
+
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
90
|
+
with:
|
|
91
|
+
python-version: ${{ matrix.python-version }}
|
|
92
|
+
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
|
93
|
+
with:
|
|
94
|
+
name: jring-client-${{ github.sha }}
|
|
95
|
+
path: dist
|
|
96
|
+
- name: Install outside the checkout and smoke safe paths
|
|
97
|
+
shell: bash
|
|
98
|
+
run: |
|
|
99
|
+
python -m venv /tmp/jring-release-smoke
|
|
100
|
+
/tmp/jring-release-smoke/bin/python -m pip install dist/*.whl
|
|
101
|
+
cd /tmp
|
|
102
|
+
/tmp/jring-release-smoke/bin/jring doctor --json
|
|
103
|
+
/tmp/jring-release-smoke/bin/jring status --simulate --json
|
|
104
|
+
/tmp/jring-release-smoke/bin/jring capabilities --simulate --json
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
name: test
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
pull_request:
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
contents: read
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
test:
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
strategy:
|
|
14
|
+
matrix:
|
|
15
|
+
python-version: ["3.10", "3.13"]
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
18
|
+
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
19
|
+
with:
|
|
20
|
+
python-version: ${{ matrix.python-version }}
|
|
21
|
+
cache: pip
|
|
22
|
+
- run: python -m pip install -e '.[ble,dev]'
|
|
23
|
+
- run: python scripts/generate_cli_artifacts.py --check
|
|
24
|
+
- run: python -m pytest -q
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
name: uv tool smoke
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
pull_request:
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: read
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
uv-tool-smoke:
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
timeout-minutes: 15
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
17
|
+
with:
|
|
18
|
+
persist-credentials: false
|
|
19
|
+
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
20
|
+
with:
|
|
21
|
+
python-version: "3.13"
|
|
22
|
+
cache: pip
|
|
23
|
+
- uses: astral-sh/setup-uv@d08d816a1ea176d61a318eff45abd3dffef415b1 # main, resolved 2026-08-26
|
|
24
|
+
with:
|
|
25
|
+
enable-cache: false
|
|
26
|
+
- name: Build the reviewed wheel
|
|
27
|
+
shell: bash
|
|
28
|
+
run: |
|
|
29
|
+
set -euo pipefail
|
|
30
|
+
python -m pip install -r requirements/release.txt
|
|
31
|
+
python scripts/evidence_tool.py scan .
|
|
32
|
+
python scripts/generate_cli_artifacts.py --check
|
|
33
|
+
python -m build --wheel --outdir dist
|
|
34
|
+
- name: Install the exact wheel as an isolated uv tool
|
|
35
|
+
shell: bash
|
|
36
|
+
run: |
|
|
37
|
+
set -euo pipefail
|
|
38
|
+
uv tool install dist/*.whl
|
|
39
|
+
jring --version
|
|
40
|
+
jring status --simulate --json
|
|
41
|
+
jring capabilities --simulate --json
|
|
42
|
+
jring-tui </dev/null
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Contributing to JRing client
|
|
2
|
+
|
|
3
|
+
Start with a public issue describing the user job, intended behavior, executable tests,
|
|
4
|
+
artifacts, and blockers. Keep each change independently reviewable. Update JTBD and UX
|
|
5
|
+
specification text before implementation, add a failing test, then make it pass.
|
|
6
|
+
|
|
7
|
+
## Evidence safety
|
|
8
|
+
|
|
9
|
+
Never attach or commit raw Bluetooth captures, Android application archives, addresses,
|
|
10
|
+
BlueZ object paths, device or account identifiers, precise personal timestamps, health
|
|
11
|
+
measurements, report maps, or vendor payload dumps. Do not paste them into an issue,
|
|
12
|
+
pull request, CI log, commit message, or chat transcript.
|
|
13
|
+
|
|
14
|
+
Work with synthetic evidence unless the owner separately authorizes a local hardware
|
|
15
|
+
observation. Keep originals outside the repository. Create a minimal manifest from the
|
|
16
|
+
synthetic example, then validate and derive locally:
|
|
17
|
+
|
|
18
|
+
```sh
|
|
19
|
+
python3 scripts/evidence_tool.py validate path/to/manifest.json
|
|
20
|
+
python3 scripts/evidence_tool.py derive path/to/manifest.json > /tmp/jring-fixture.json
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
The validator refuses unsafe content; it does not promise to anonymize it. Review the
|
|
24
|
+
derived fixture yourself before adding it. Run `python3 scripts/evidence_tool.py scan .`
|
|
25
|
+
and the full tests before committing. If a finding or reproduction needs sensitive
|
|
26
|
+
material, stop and follow [SECURITY.md](SECURITY.md) instead of opening a public issue.
|
|
27
|
+
|
|
28
|
+
Schema-2 `*-claim.json` files are public review candidates and must have an exact
|
|
29
|
+
`*-fixture.json` derivation. The current allowlist contains only the sealed vendor-main
|
|
30
|
+
device-info canary shape. Do not turn a private owner manifest into a tracked claim:
|
|
31
|
+
construct and review the minimal public candidate separately. Schema validation grants no
|
|
32
|
+
permission to connect, activate notifications, write, publish private evidence, or
|
|
33
|
+
claim hardware support.
|
|
34
|
+
|
|
35
|
+
A schema-2 private device-info observation is a self-declared record of one historical
|
|
36
|
+
attempt only. It withholds identifiers and model/firmware context. Keep it
|
|
37
|
+
outside the repository, owned by the current user, and mode 0600 (or read-only 0400),
|
|
38
|
+
then run only `python3 scripts/evidence_tool.py validate path/to/observation.json`.
|
|
39
|
+
Validation performs no Bluetooth operation and authenticates neither the owner nor the
|
|
40
|
+
observation. `derive` deliberately refuses this artifact; do not commit, attach, paste,
|
|
41
|
+
or publish it. A future pre-run plan, its one attempt, this post-run observation, and
|
|
42
|
+
any separately consented public candidate are four different artifacts and decisions.
|
|
43
|
+
|
|
44
|
+
The `-manifest.json`, `-claim.json`, and `-fixture.json` suffixes are reserved across
|
|
45
|
+
the repository; moving an unpaired artifact outside `tests/fixtures/evidence` does not
|
|
46
|
+
bypass validation.
|
|
47
|
+
|
|
48
|
+
Vendor writes remain disabled. Evidence contribution never authorizes scanning,
|
|
49
|
+
connecting, subscribing, input injection, or packet emission.
|
|
50
|
+
|
|
51
|
+
## License
|
|
52
|
+
|
|
53
|
+
Project source, including accepted contributions, is distributed under the
|
|
54
|
+
[MIT License](LICENSE). This repository does not add a separate contributor license
|
|
55
|
+
agreement.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 JRing Client contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
include CONTRIBUTING.md
|
|
2
|
+
include LICENSE
|
|
3
|
+
include SECURITY.md
|
|
4
|
+
recursive-include .github/workflows *.yml
|
|
5
|
+
recursive-include docs *.md
|
|
6
|
+
recursive-include requirements *.txt
|
|
7
|
+
recursive-include scripts *.py
|
|
8
|
+
include src/jring/resources/completions/jring.bash
|
|
9
|
+
include src/jring/resources/man/jring.1
|
|
10
|
+
recursive-include tests/fixtures *.json
|