saprfclib 0.1.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.
- saprfclib-0.1.0/.github/ISSUE_TEMPLATE/bug_report.yml +68 -0
- saprfclib-0.1.0/.github/ISSUE_TEMPLATE/config.yml +8 -0
- saprfclib-0.1.0/.github/ISSUE_TEMPLATE/feature_request.yml +24 -0
- saprfclib-0.1.0/.github/ISSUE_TEMPLATE/protocol_gap.yml +50 -0
- saprfclib-0.1.0/.github/PULL_REQUEST_TEMPLATE.md +26 -0
- saprfclib-0.1.0/.github/dependabot.yml +17 -0
- saprfclib-0.1.0/.github/workflows/ci.yml +72 -0
- saprfclib-0.1.0/.github/workflows/docs.yml +52 -0
- saprfclib-0.1.0/.github/workflows/publish.yml +109 -0
- saprfclib-0.1.0/.github/workflows/security.yml +102 -0
- saprfclib-0.1.0/.gitignore +189 -0
- saprfclib-0.1.0/CHANGELOG.md +59 -0
- saprfclib-0.1.0/CLAUDE.md +206 -0
- saprfclib-0.1.0/CONTRIBUTING.md +196 -0
- saprfclib-0.1.0/LICENSE +373 -0
- saprfclib-0.1.0/NOTICE +48 -0
- saprfclib-0.1.0/PKG-INFO +181 -0
- saprfclib-0.1.0/README.md +144 -0
- saprfclib-0.1.0/SECURITY.md +52 -0
- saprfclib-0.1.0/conftest.py +15 -0
- saprfclib-0.1.0/docs/api/codec.md +5 -0
- saprfclib-0.1.0/docs/api/connect.md +5 -0
- saprfclib-0.1.0/docs/api/connection-pool.md +3 -0
- saprfclib-0.1.0/docs/api/connection.md +16 -0
- saprfclib-0.1.0/docs/api/exceptions.md +17 -0
- saprfclib-0.1.0/docs/api/rfc-server.md +3 -0
- saprfclib-0.1.0/docs/api/stores.md +11 -0
- saprfclib-0.1.0/docs/cookbook/connection-pool.md +58 -0
- saprfclib-0.1.0/docs/cookbook/index.md +13 -0
- saprfclib-0.1.0/docs/cookbook/rfc-server.md +96 -0
- saprfclib-0.1.0/docs/cookbook/snc-connection.md +53 -0
- saprfclib-0.1.0/docs/cookbook/table-parameters.md +79 -0
- saprfclib-0.1.0/docs/cookbook/trfc-submit.md +93 -0
- saprfclib-0.1.0/docs/cookbook/websocket-rfc.md +72 -0
- saprfclib-0.1.0/docs/getting-started/connection-options.md +114 -0
- saprfclib-0.1.0/docs/getting-started/error-handling.md +156 -0
- saprfclib-0.1.0/docs/getting-started/installation.md +46 -0
- saprfclib-0.1.0/docs/getting-started/quick-start.md +77 -0
- saprfclib-0.1.0/docs/index.md +36 -0
- saprfclib-0.1.0/docs/protocol/.gitkeep +0 -0
- saprfclib-0.1.0/docs/protocol/framing.md +792 -0
- saprfclib-0.1.0/docs/protocol/handshake.md +328 -0
- saprfclib-0.1.0/docs/protocol/methodology.md +213 -0
- saprfclib-0.1.0/docs/protocol/serialization.md +658 -0
- saprfclib-0.1.0/docs/protocol/snc.md +252 -0
- saprfclib-0.1.0/docs/protocol/trfc.md +327 -0
- saprfclib-0.1.0/examples/01_connect_and_call.py +42 -0
- saprfclib-0.1.0/examples/02_table_params.py +47 -0
- saprfclib-0.1.0/examples/03_connection_pool.py +53 -0
- saprfclib-0.1.0/examples/04_trfc_submit.py +66 -0
- saprfclib-0.1.0/examples/05_rfc_server.py +96 -0
- saprfclib-0.1.0/examples/06_snc_connection.py +59 -0
- saprfclib-0.1.0/examples/07_websocket_rfc.py +65 -0
- saprfclib-0.1.0/mkdocs.yml +101 -0
- saprfclib-0.1.0/pyproject.toml +116 -0
- saprfclib-0.1.0/src/saprfclib/__init__.py +116 -0
- saprfclib-0.1.0/src/saprfclib/_version.py +24 -0
- saprfclib-0.1.0/src/saprfclib/codec.py +562 -0
- saprfclib-0.1.0/src/saprfclib/compress.py +854 -0
- saprfclib-0.1.0/src/saprfclib/connection.py +4620 -0
- saprfclib-0.1.0/src/saprfclib/exceptions.py +282 -0
- saprfclib-0.1.0/src/saprfclib/invoke.py +874 -0
- saprfclib-0.1.0/src/saprfclib/metadata.py +329 -0
- saprfclib-0.1.0/src/saprfclib/pool.py +476 -0
- saprfclib-0.1.0/src/saprfclib/py.typed +0 -0
- saprfclib-0.1.0/src/saprfclib/router.py +548 -0
- saprfclib-0.1.0/src/saprfclib/server.py +1723 -0
- saprfclib-0.1.0/src/saprfclib/server_session.py +333 -0
- saprfclib-0.1.0/src/saprfclib/session.py +423 -0
- saprfclib-0.1.0/src/saprfclib/snc.py +1025 -0
- saprfclib-0.1.0/src/saprfclib/stores.py +888 -0
- saprfclib-0.1.0/src/saprfclib/transport.py +231 -0
- saprfclib-0.1.0/src/saprfclib/types.py +84 -0
- saprfclib-0.1.0/src/saprfclib/ws.py +632 -0
- saprfclib-0.1.0/tests/__init__.py +0 -0
- saprfclib-0.1.0/tests/_mocks.py +77 -0
- saprfclib-0.1.0/tests/conftest.py +117 -0
- saprfclib-0.1.0/tests/golden/__init__.py +0 -0
- saprfclib-0.1.0/tests/golden/framing/.gitkeep +0 -0
- saprfclib-0.1.0/tests/golden/framing/__init__.py +0 -0
- saprfclib-0.1.0/tests/golden/framing/logon_request.bin +0 -0
- saprfclib-0.1.0/tests/golden/framing/logon_request.json +62 -0
- saprfclib-0.1.0/tests/golden/framing/rfc_read_table_request.bin +0 -0
- saprfclib-0.1.0/tests/golden/framing/rfc_read_table_response.bin +0 -0
- saprfclib-0.1.0/tests/golden/framing/server_inbound_call_request.bin +0 -0
- saprfclib-0.1.0/tests/golden/framing/server_inbound_call_request.json +43 -0
- saprfclib-0.1.0/tests/golden/framing/server_ni_init_client.bin +0 -0
- saprfclib-0.1.0/tests/golden/framing/server_ni_init_gateway.bin +0 -0
- saprfclib-0.1.0/tests/golden/framing/server_registration_ack.bin +0 -0
- saprfclib-0.1.0/tests/golden/framing/server_registration_request.bin +0 -0
- saprfclib-0.1.0/tests/golden/framing/server_registration_request.json +181 -0
- saprfclib-0.1.0/tests/golden/framing/server_response.bin +0 -0
- saprfclib-0.1.0/tests/golden/framing/server_response.json +45 -0
- saprfclib-0.1.0/tests/golden/framing/stfc_changing_request.bin +0 -0
- saprfclib-0.1.0/tests/golden/framing/stfc_changing_response.bin +0 -0
- saprfclib-0.1.0/tests/golden/framing/stfc_connection_request.bin +0 -0
- saprfclib-0.1.0/tests/golden/framing/stfc_connection_request.json +153 -0
- saprfclib-0.1.0/tests/golden/framing/stfc_connection_response.bin +0 -0
- saprfclib-0.1.0/tests/golden/framing/stfc_connection_response.json +194 -0
- saprfclib-0.1.0/tests/golden/framing/stfc_deep_table_request.bin +0 -0
- saprfclib-0.1.0/tests/golden/framing/stfc_deep_table_response.bin +0 -0
- saprfclib-0.1.0/tests/golden/framing/stfc_exception_response.bin +0 -0
- saprfclib-0.1.0/tests/golden/framing/stfc_structure_request.bin +0 -0
- saprfclib-0.1.0/tests/golden/framing/stfc_structure_response.bin +0 -0
- saprfclib-0.1.0/tests/golden/framing/trfc_call_request.bin +0 -0
- saprfclib-0.1.0/tests/golden/framing/trfc_call_request.json +84 -0
- saprfclib-0.1.0/tests/golden/handshake/.gitkeep +0 -0
- saprfclib-0.1.0/tests/golden/handshake/__init__.py +0 -0
- saprfclib-0.1.0/tests/golden/handshake/gw_connect_response.bin +0 -0
- saprfclib-0.1.0/tests/golden/handshake/gw_connect_response.json +76 -0
- saprfclib-0.1.0/tests/golden/handshake/gw_done_client.bin +0 -0
- saprfclib-0.1.0/tests/golden/handshake/gw_done_client.json +75 -0
- saprfclib-0.1.0/tests/golden/handshake/gw_done_server.bin +0 -0
- saprfclib-0.1.0/tests/golden/handshake/gw_done_server.json +77 -0
- saprfclib-0.1.0/tests/golden/handshake/ni_version_request.bin +0 -0
- saprfclib-0.1.0/tests/golden/handshake/ni_version_request.json +135 -0
- saprfclib-0.1.0/tests/golden/handshake/ni_version_response.bin +0 -0
- saprfclib-0.1.0/tests/golden/handshake/ni_version_response.json +135 -0
- saprfclib-0.1.0/tests/golden/handshake/stfc_connection_handshake.bin +0 -0
- saprfclib-0.1.0/tests/golden/handshake/stfc_connection_handshake.json +226 -0
- saprfclib-0.1.0/tests/golden/handshake/test_handshake.py +38 -0
- saprfclib-0.1.0/tests/golden/router/ni_route_payload.bin +0 -0
- saprfclib-0.1.0/tests/golden/router/sapms_server_list.bin +0 -0
- saprfclib-0.1.0/tests/golden/router/sapms_server_list.json +219 -0
- saprfclib-0.1.0/tests/golden/serialization/.gitkeep +0 -0
- saprfclib-0.1.0/tests/golden/serialization/__init__.py +0 -0
- saprfclib-0.1.0/tests/golden/serialization/_replay.py +104 -0
- saprfclib-0.1.0/tests/golden/serialization/test_codec_roundtrip.py +306 -0
- saprfclib-0.1.0/tests/golden/serialization/test_serialization.py +56 -0
- saprfclib-0.1.0/tests/golden/serialization/type_bcd.bin +1 -0
- saprfclib-0.1.0/tests/golden/serialization/type_bcd.json +43 -0
- saprfclib-0.1.0/tests/golden/serialization/type_bcd_p15_2.bin +0 -0
- saprfclib-0.1.0/tests/golden/serialization/type_bcd_p15_2.json +84 -0
- saprfclib-0.1.0/tests/golden/serialization/type_byte.bin +1 -0
- saprfclib-0.1.0/tests/golden/serialization/type_byte.json +25 -0
- saprfclib-0.1.0/tests/golden/serialization/type_cday.bin +0 -0
- saprfclib-0.1.0/tests/golden/serialization/type_cday.json +24 -0
- saprfclib-0.1.0/tests/golden/serialization/type_char.bin +0 -0
- saprfclib-0.1.0/tests/golden/serialization/type_char.json +33 -0
- saprfclib-0.1.0/tests/golden/serialization/type_date.bin +0 -0
- saprfclib-0.1.0/tests/golden/serialization/type_date.json +81 -0
- saprfclib-0.1.0/tests/golden/serialization/type_decf16_GAP.json +19 -0
- saprfclib-0.1.0/tests/golden/serialization/type_dtday.bin +0 -0
- saprfclib-0.1.0/tests/golden/serialization/type_dtday.json +24 -0
- saprfclib-0.1.0/tests/golden/serialization/type_dtmonth.bin +0 -0
- saprfclib-0.1.0/tests/golden/serialization/type_dtmonth.json +24 -0
- saprfclib-0.1.0/tests/golden/serialization/type_dtweek.bin +0 -0
- saprfclib-0.1.0/tests/golden/serialization/type_dtweek.json +24 -0
- saprfclib-0.1.0/tests/golden/serialization/type_float.bin +1 -0
- saprfclib-0.1.0/tests/golden/serialization/type_float.json +25 -0
- saprfclib-0.1.0/tests/golden/serialization/type_int1.bin +1 -0
- saprfclib-0.1.0/tests/golden/serialization/type_int1.json +24 -0
- saprfclib-0.1.0/tests/golden/serialization/type_int2.bin +0 -0
- saprfclib-0.1.0/tests/golden/serialization/type_int2.json +24 -0
- saprfclib-0.1.0/tests/golden/serialization/type_int4.bin +0 -0
- saprfclib-0.1.0/tests/golden/serialization/type_int4.json +23 -0
- saprfclib-0.1.0/tests/golden/serialization/type_int8.bin +0 -0
- saprfclib-0.1.0/tests/golden/serialization/type_int8.json +24 -0
- saprfclib-0.1.0/tests/golden/serialization/type_num.bin +0 -0
- saprfclib-0.1.0/tests/golden/serialization/type_num.json +50 -0
- saprfclib-0.1.0/tests/golden/serialization/type_string.bin +0 -0
- saprfclib-0.1.0/tests/golden/serialization/type_string.json +66 -0
- saprfclib-0.1.0/tests/golden/serialization/type_structure.bin +0 -0
- saprfclib-0.1.0/tests/golden/serialization/type_structure.json +61 -0
- saprfclib-0.1.0/tests/golden/serialization/type_table.bin +0 -0
- saprfclib-0.1.0/tests/golden/serialization/type_table.json +78 -0
- saprfclib-0.1.0/tests/golden/serialization/type_time.bin +0 -0
- saprfclib-0.1.0/tests/golden/serialization/type_time.json +65 -0
- saprfclib-0.1.0/tests/golden/serialization/type_tminute.bin +0 -0
- saprfclib-0.1.0/tests/golden/serialization/type_tminute.json +24 -0
- saprfclib-0.1.0/tests/golden/serialization/type_tsecond.bin +0 -0
- saprfclib-0.1.0/tests/golden/serialization/type_tsecond.json +24 -0
- saprfclib-0.1.0/tests/golden/serialization/type_utclong.bin +0 -0
- saprfclib-0.1.0/tests/golden/serialization/type_utclong.json +24 -0
- saprfclib-0.1.0/tests/golden/serialization/type_utcminute.bin +0 -0
- saprfclib-0.1.0/tests/golden/serialization/type_utcminute.json +24 -0
- saprfclib-0.1.0/tests/golden/serialization/type_utcsecond.bin +0 -0
- saprfclib-0.1.0/tests/golden/serialization/type_utcsecond.json +24 -0
- saprfclib-0.1.0/tests/golden/serialization/type_xstring.bin +0 -0
- saprfclib-0.1.0/tests/golden/serialization/type_xstring.json +34 -0
- saprfclib-0.1.0/tests/golden/synthetic/__init__.py +0 -0
- saprfclib-0.1.0/tests/golden/synthetic/ni_header_synthetic.bin +0 -0
- saprfclib-0.1.0/tests/golden/synthetic/ni_header_synthetic.json +28 -0
- saprfclib-0.1.0/tests/golden/synthetic/test_synthetic.py +21 -0
- saprfclib-0.1.0/tests/golden/test_fixtures.py +56 -0
- saprfclib-0.1.0/tests/test_codec.py +536 -0
- saprfclib-0.1.0/tests/test_compress.py +338 -0
- saprfclib-0.1.0/tests/test_connection.py +1166 -0
- saprfclib-0.1.0/tests/test_exceptions.py +162 -0
- saprfclib-0.1.0/tests/test_invoke.py +661 -0
- saprfclib-0.1.0/tests/test_metadata.py +319 -0
- saprfclib-0.1.0/tests/test_packaging.py +65 -0
- saprfclib-0.1.0/tests/test_phase03_integration.py +264 -0
- saprfclib-0.1.0/tests/test_phase04_integration.py +479 -0
- saprfclib-0.1.0/tests/test_phase05_integration.py +296 -0
- saprfclib-0.1.0/tests/test_phase05_pool.py +261 -0
- saprfclib-0.1.0/tests/test_phase05_server.py +360 -0
- saprfclib-0.1.0/tests/test_phase06_bgrfc.py +224 -0
- saprfclib-0.1.0/tests/test_phase06_integration.py +408 -0
- saprfclib-0.1.0/tests/test_phase06_server.py +240 -0
- saprfclib-0.1.0/tests/test_phase06_stores.py +373 -0
- saprfclib-0.1.0/tests/test_phase06_trfc.py +239 -0
- saprfclib-0.1.0/tests/test_phase07_snc_integration.py +99 -0
- saprfclib-0.1.0/tests/test_phase07_wrfc_integration.py +206 -0
- saprfclib-0.1.0/tests/test_phase09_async_client.py +246 -0
- saprfclib-0.1.0/tests/test_phase09_async_pool.py +152 -0
- saprfclib-0.1.0/tests/test_phase09_async_server.py +232 -0
- saprfclib-0.1.0/tests/test_phase09_integration.py +339 -0
- saprfclib-0.1.0/tests/test_phase09_retry.py +414 -0
- saprfclib-0.1.0/tests/test_phase09_sqlite_store.py +348 -0
- saprfclib-0.1.0/tests/test_router.py +373 -0
- saprfclib-0.1.0/tests/test_session.py +158 -0
- saprfclib-0.1.0/tests/test_snc_frame.py +133 -0
- saprfclib-0.1.0/tests/test_snc_gss_binding.py +176 -0
- saprfclib-0.1.0/tests/test_snc_transport.py +428 -0
- saprfclib-0.1.0/tests/test_transport.py +169 -0
- saprfclib-0.1.0/tests/test_types.py +133 -0
- saprfclib-0.1.0/tests/test_wrfc_invoke.py +142 -0
- saprfclib-0.1.0/tests/test_ws_frames.py +206 -0
- saprfclib-0.1.0/tests/test_ws_proxy.py +84 -0
- saprfclib-0.1.0/tests/test_ws_upgrade.py +147 -0
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
name: Bug report
|
|
2
|
+
description: Something behaves incorrectly against an SAP system
|
|
3
|
+
labels: ["bug"]
|
|
4
|
+
body:
|
|
5
|
+
- type: markdown
|
|
6
|
+
attributes:
|
|
7
|
+
value: |
|
|
8
|
+
**Never paste real credentials, real hostnames, customer data, or an unsanitised
|
|
9
|
+
pcap.** Redact before posting. If this is a security issue, do not open an issue —
|
|
10
|
+
see SECURITY.md.
|
|
11
|
+
|
|
12
|
+
- type: input
|
|
13
|
+
id: version
|
|
14
|
+
attributes:
|
|
15
|
+
label: saprfclib version
|
|
16
|
+
placeholder: "0.1.0 (python -c 'import saprfclib; print(saprfclib.__version__)')"
|
|
17
|
+
validations:
|
|
18
|
+
required: true
|
|
19
|
+
|
|
20
|
+
- type: input
|
|
21
|
+
id: python
|
|
22
|
+
attributes:
|
|
23
|
+
label: Python version and OS
|
|
24
|
+
placeholder: "3.13.1 on Ubuntu 24.04"
|
|
25
|
+
validations:
|
|
26
|
+
required: true
|
|
27
|
+
|
|
28
|
+
- type: input
|
|
29
|
+
id: sap
|
|
30
|
+
attributes:
|
|
31
|
+
label: SAP system release
|
|
32
|
+
placeholder: "SAP NW 7.58 / S/4HANA 2023 / BTP ABAP environment"
|
|
33
|
+
|
|
34
|
+
- type: dropdown
|
|
35
|
+
id: transport
|
|
36
|
+
attributes:
|
|
37
|
+
label: Connection mode
|
|
38
|
+
options:
|
|
39
|
+
- Direct TCP (ashost/sysnr)
|
|
40
|
+
- SAProuter
|
|
41
|
+
- Message server (group logon)
|
|
42
|
+
- SNC
|
|
43
|
+
- WebSocket RFC (BTP)
|
|
44
|
+
- RFC server (inbound)
|
|
45
|
+
validations:
|
|
46
|
+
required: true
|
|
47
|
+
|
|
48
|
+
- type: textarea
|
|
49
|
+
id: what
|
|
50
|
+
attributes:
|
|
51
|
+
label: What happened
|
|
52
|
+
description: Include the full traceback if there is one, with credentials redacted.
|
|
53
|
+
validations:
|
|
54
|
+
required: true
|
|
55
|
+
|
|
56
|
+
- type: textarea
|
|
57
|
+
id: expected
|
|
58
|
+
attributes:
|
|
59
|
+
label: What you expected
|
|
60
|
+
validations:
|
|
61
|
+
required: true
|
|
62
|
+
|
|
63
|
+
- type: textarea
|
|
64
|
+
id: repro
|
|
65
|
+
attributes:
|
|
66
|
+
label: Reproduction
|
|
67
|
+
description: Smallest snippet that shows the problem, with placeholders for connection parameters.
|
|
68
|
+
render: python
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
blank_issues_enabled: false
|
|
2
|
+
contact_links:
|
|
3
|
+
- name: Security vulnerability
|
|
4
|
+
url: https://github.com/randomstr1ng/saprfclib/security/advisories/new
|
|
5
|
+
about: Report privately. Never open a public issue for a security problem.
|
|
6
|
+
- name: Documentation
|
|
7
|
+
url: https://randomstr1ng.github.io/saprfclib/
|
|
8
|
+
about: Getting started, cookbook, API reference, and wire-protocol docs.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
name: Feature request
|
|
2
|
+
description: Propose new functionality
|
|
3
|
+
labels: ["enhancement"]
|
|
4
|
+
body:
|
|
5
|
+
- type: textarea
|
|
6
|
+
id: problem
|
|
7
|
+
attributes:
|
|
8
|
+
label: What problem does this solve
|
|
9
|
+
validations:
|
|
10
|
+
required: true
|
|
11
|
+
|
|
12
|
+
- type: textarea
|
|
13
|
+
id: proposal
|
|
14
|
+
attributes:
|
|
15
|
+
label: Proposed API or behaviour
|
|
16
|
+
render: python
|
|
17
|
+
|
|
18
|
+
- type: checkboxes
|
|
19
|
+
id: constraints
|
|
20
|
+
attributes:
|
|
21
|
+
label: Constraints
|
|
22
|
+
options:
|
|
23
|
+
- label: This can be implemented in pure Python with no new native dependency
|
|
24
|
+
required: true
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
name: Protocol gap or wrong wire behaviour
|
|
2
|
+
description: A field, type, or frame is unsupported, mis-parsed, or mis-serialized
|
|
3
|
+
labels: ["protocol"]
|
|
4
|
+
body:
|
|
5
|
+
- type: markdown
|
|
6
|
+
attributes:
|
|
7
|
+
value: |
|
|
8
|
+
This project does not accept guessed wire values. A report that includes observed
|
|
9
|
+
bytes can be acted on; one that does not usually cannot. See CLAUDE.md for the
|
|
10
|
+
evidence tiers.
|
|
11
|
+
|
|
12
|
+
**Sanitise captures before attaching them** — no credentials, no real hostnames,
|
|
13
|
+
no customer data.
|
|
14
|
+
|
|
15
|
+
- type: textarea
|
|
16
|
+
id: area
|
|
17
|
+
attributes:
|
|
18
|
+
label: Which part of the protocol
|
|
19
|
+
placeholder: "e.g. DecFloat34 decode, tRFC TID format, 0x0514 session token"
|
|
20
|
+
validations:
|
|
21
|
+
required: true
|
|
22
|
+
|
|
23
|
+
- type: textarea
|
|
24
|
+
id: observed
|
|
25
|
+
attributes:
|
|
26
|
+
label: Observed bytes
|
|
27
|
+
description: Hex dump of the frame or field as seen on the wire, with offsets if known.
|
|
28
|
+
render: text
|
|
29
|
+
|
|
30
|
+
- type: textarea
|
|
31
|
+
id: expected
|
|
32
|
+
attributes:
|
|
33
|
+
label: What saprfclib produced or expected instead
|
|
34
|
+
|
|
35
|
+
- type: dropdown
|
|
36
|
+
id: evidence
|
|
37
|
+
attributes:
|
|
38
|
+
label: Evidence tier
|
|
39
|
+
options:
|
|
40
|
+
- Live capture (pcap from my own system)
|
|
41
|
+
- Behavioural probe (server accepted/rejected)
|
|
42
|
+
- Inference from a neighbouring confirmed field
|
|
43
|
+
validations:
|
|
44
|
+
required: true
|
|
45
|
+
|
|
46
|
+
- type: input
|
|
47
|
+
id: sap
|
|
48
|
+
attributes:
|
|
49
|
+
label: SAP system release
|
|
50
|
+
placeholder: "SAP NW 7.58 / S/4HANA 2023"
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
## What this changes
|
|
2
|
+
|
|
3
|
+
<!-- One or two sentences. -->
|
|
4
|
+
|
|
5
|
+
## Evidence (required for any wire-behaviour change)
|
|
6
|
+
|
|
7
|
+
<!--
|
|
8
|
+
State the source for every wire value you added or changed. See CLAUDE.md.
|
|
9
|
+
Delete this section only if the PR touches no protocol behaviour.
|
|
10
|
+
-->
|
|
11
|
+
|
|
12
|
+
- [ ] Live capture / golden fixture — fixture path:
|
|
13
|
+
- [ ] Behavioural probe against a live system — describe:
|
|
14
|
+
- [ ] Inference from a confirmed field — labelled `[ASSUMED]` in code and docs
|
|
15
|
+
|
|
16
|
+
## Checklist
|
|
17
|
+
|
|
18
|
+
- [ ] `hatch run test -m "not integration"` passes
|
|
19
|
+
- [ ] `hatch run lint:check` passes
|
|
20
|
+
- [ ] `hatch run lint:type` passes
|
|
21
|
+
- [ ] No golden fixture was edited to make a test pass
|
|
22
|
+
- [ ] No new non-Python runtime dependency
|
|
23
|
+
- [ ] No SAP source, headers, binaries, or decompiler output added
|
|
24
|
+
- [ ] `docs/protocol/` updated if wire behaviour changed
|
|
25
|
+
- [ ] `CHANGELOG.md` updated under "Unreleased"
|
|
26
|
+
- [ ] New source files carry the MPL-2.0 header
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
version: 2
|
|
2
|
+
updates:
|
|
3
|
+
- package-ecosystem: "pip"
|
|
4
|
+
directory: "/"
|
|
5
|
+
schedule:
|
|
6
|
+
interval: "weekly"
|
|
7
|
+
day: "monday"
|
|
8
|
+
open-pull-requests-limit: 5
|
|
9
|
+
labels: ["dependencies"]
|
|
10
|
+
|
|
11
|
+
- package-ecosystem: "github-actions"
|
|
12
|
+
directory: "/"
|
|
13
|
+
schedule:
|
|
14
|
+
interval: "weekly"
|
|
15
|
+
day: "monday"
|
|
16
|
+
open-pull-requests-limit: 5
|
|
17
|
+
labels: ["dependencies", "ci"]
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: ["main"]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: ["main"]
|
|
8
|
+
|
|
9
|
+
permissions:
|
|
10
|
+
contents: read
|
|
11
|
+
|
|
12
|
+
concurrency:
|
|
13
|
+
group: ci-${{ github.ref }}
|
|
14
|
+
cancel-in-progress: true
|
|
15
|
+
|
|
16
|
+
jobs:
|
|
17
|
+
test:
|
|
18
|
+
runs-on: ubuntu-latest
|
|
19
|
+
strategy:
|
|
20
|
+
fail-fast: false
|
|
21
|
+
matrix:
|
|
22
|
+
python-version: ["3.12", "3.13"]
|
|
23
|
+
|
|
24
|
+
steps:
|
|
25
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
26
|
+
with:
|
|
27
|
+
fetch-depth: 0 # required for hatch-vcs git-tag version derivation
|
|
28
|
+
persist-credentials: false
|
|
29
|
+
|
|
30
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
31
|
+
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
32
|
+
with:
|
|
33
|
+
python-version: ${{ matrix.python-version }}
|
|
34
|
+
|
|
35
|
+
- name: Install Hatch
|
|
36
|
+
run: pip install hatch "hatchling>=1.21,<1.32"
|
|
37
|
+
|
|
38
|
+
- name: Lint (Ruff)
|
|
39
|
+
run: hatch run lint:check
|
|
40
|
+
|
|
41
|
+
- name: Type-check (mypy)
|
|
42
|
+
run: hatch run lint:type
|
|
43
|
+
|
|
44
|
+
- name: Test (pytest — offline only, no live SAP)
|
|
45
|
+
run: hatch run test -m "not integration"
|
|
46
|
+
|
|
47
|
+
- name: Build distribution
|
|
48
|
+
run: hatch build
|
|
49
|
+
|
|
50
|
+
- name: Verify importable wheel
|
|
51
|
+
run: |
|
|
52
|
+
pip install dist/*.whl --force-reinstall
|
|
53
|
+
python -c "import saprfclib; print(saprfclib.__version__)"
|
|
54
|
+
|
|
55
|
+
docs-build:
|
|
56
|
+
runs-on: ubuntu-latest
|
|
57
|
+
steps:
|
|
58
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
59
|
+
with:
|
|
60
|
+
fetch-depth: 0
|
|
61
|
+
persist-credentials: false
|
|
62
|
+
|
|
63
|
+
- name: Set up Python
|
|
64
|
+
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
65
|
+
with:
|
|
66
|
+
python-version: "3.12"
|
|
67
|
+
|
|
68
|
+
- name: Install Hatch
|
|
69
|
+
run: pip install hatch "hatchling>=1.21,<1.32"
|
|
70
|
+
|
|
71
|
+
- name: Build docs (strict)
|
|
72
|
+
run: hatch run docs:build
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
name: Docs
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: ["main"]
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: read
|
|
10
|
+
|
|
11
|
+
concurrency:
|
|
12
|
+
group: pages
|
|
13
|
+
cancel-in-progress: false
|
|
14
|
+
|
|
15
|
+
jobs:
|
|
16
|
+
build:
|
|
17
|
+
runs-on: ubuntu-latest
|
|
18
|
+
steps:
|
|
19
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
20
|
+
with:
|
|
21
|
+
fetch-depth: 0
|
|
22
|
+
persist-credentials: false
|
|
23
|
+
|
|
24
|
+
- name: Set up Python
|
|
25
|
+
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
26
|
+
with:
|
|
27
|
+
python-version: "3.12"
|
|
28
|
+
|
|
29
|
+
- name: Install Hatch
|
|
30
|
+
run: pip install hatch "hatchling>=1.21,<1.32"
|
|
31
|
+
|
|
32
|
+
- name: Build docs
|
|
33
|
+
run: hatch run docs:build
|
|
34
|
+
|
|
35
|
+
- uses: actions/configure-pages@45bfe0192ca1faeb007ade9deae92b16b8254a0d # v6.0.0
|
|
36
|
+
|
|
37
|
+
- uses: actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9 # v5.0.0
|
|
38
|
+
with:
|
|
39
|
+
path: ./site
|
|
40
|
+
|
|
41
|
+
deploy:
|
|
42
|
+
needs: build
|
|
43
|
+
runs-on: ubuntu-latest
|
|
44
|
+
environment:
|
|
45
|
+
name: github-pages
|
|
46
|
+
url: ${{ steps.deployment.outputs.page_url }}
|
|
47
|
+
permissions:
|
|
48
|
+
pages: write
|
|
49
|
+
id-token: write
|
|
50
|
+
steps:
|
|
51
|
+
- id: deployment
|
|
52
|
+
uses: actions/deploy-pages@cd2ce8fcbc39b97be8ca5fce6e763baed58fa128 # v5.0.0
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
name: Publish
|
|
2
|
+
|
|
3
|
+
# Tag-driven release. hatch-vcs derives the version from the tag, so the tag is the
|
|
4
|
+
# single source of truth — never hand-edit a version string.
|
|
5
|
+
#
|
|
6
|
+
# git tag v0.2.0 && git push origin v0.2.0
|
|
7
|
+
#
|
|
8
|
+
# Uploads use PyPI Trusted Publishing (OIDC). No API token is stored in this repo.
|
|
9
|
+
|
|
10
|
+
on:
|
|
11
|
+
push:
|
|
12
|
+
tags: ["v*"]
|
|
13
|
+
workflow_dispatch:
|
|
14
|
+
|
|
15
|
+
permissions:
|
|
16
|
+
contents: read
|
|
17
|
+
|
|
18
|
+
jobs:
|
|
19
|
+
build:
|
|
20
|
+
runs-on: ubuntu-latest
|
|
21
|
+
steps:
|
|
22
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
23
|
+
with:
|
|
24
|
+
fetch-depth: 0
|
|
25
|
+
persist-credentials: false
|
|
26
|
+
|
|
27
|
+
- name: Set up Python
|
|
28
|
+
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
29
|
+
with:
|
|
30
|
+
python-version: "3.12"
|
|
31
|
+
|
|
32
|
+
- name: Install Hatch
|
|
33
|
+
run: pip install hatch "hatchling>=1.21,<1.32"
|
|
34
|
+
|
|
35
|
+
- name: Test before release (offline suite)
|
|
36
|
+
run: hatch run test -m "not integration"
|
|
37
|
+
|
|
38
|
+
- name: Build wheel + sdist
|
|
39
|
+
run: hatch build
|
|
40
|
+
|
|
41
|
+
- name: Show built version
|
|
42
|
+
run: ls -l dist/
|
|
43
|
+
|
|
44
|
+
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
|
45
|
+
with:
|
|
46
|
+
name: dist
|
|
47
|
+
path: dist/
|
|
48
|
+
if-no-files-found: error
|
|
49
|
+
|
|
50
|
+
testpypi:
|
|
51
|
+
needs: build
|
|
52
|
+
runs-on: ubuntu-latest
|
|
53
|
+
environment:
|
|
54
|
+
name: testpypi
|
|
55
|
+
url: https://test.pypi.org/p/saprfclib
|
|
56
|
+
permissions:
|
|
57
|
+
id-token: write # required for Trusted Publishing
|
|
58
|
+
steps:
|
|
59
|
+
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
|
60
|
+
with:
|
|
61
|
+
name: dist
|
|
62
|
+
path: dist/
|
|
63
|
+
|
|
64
|
+
- name: Publish to TestPyPI
|
|
65
|
+
uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # v1.14.2
|
|
66
|
+
with:
|
|
67
|
+
repository-url: https://test.pypi.org/legacy/
|
|
68
|
+
|
|
69
|
+
pypi:
|
|
70
|
+
needs: testpypi
|
|
71
|
+
runs-on: ubuntu-latest
|
|
72
|
+
environment:
|
|
73
|
+
name: pypi # protect with a required reviewer in repo settings
|
|
74
|
+
url: https://pypi.org/p/saprfclib
|
|
75
|
+
permissions:
|
|
76
|
+
id-token: write
|
|
77
|
+
steps:
|
|
78
|
+
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
|
79
|
+
with:
|
|
80
|
+
name: dist
|
|
81
|
+
path: dist/
|
|
82
|
+
|
|
83
|
+
- name: Publish to PyPI
|
|
84
|
+
uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # v1.14.2
|
|
85
|
+
|
|
86
|
+
github-release:
|
|
87
|
+
needs: pypi
|
|
88
|
+
if: github.ref_type == 'tag'
|
|
89
|
+
runs-on: ubuntu-latest
|
|
90
|
+
permissions:
|
|
91
|
+
contents: write
|
|
92
|
+
steps:
|
|
93
|
+
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
|
94
|
+
with:
|
|
95
|
+
name: dist
|
|
96
|
+
path: dist/
|
|
97
|
+
|
|
98
|
+
# `gh` ships on the runner, so no third-party action is needed in the
|
|
99
|
+
# release path. One less dependency to trust on a job that has write
|
|
100
|
+
# access to the repository.
|
|
101
|
+
- name: Create GitHub release
|
|
102
|
+
env:
|
|
103
|
+
GH_TOKEN: ${{ github.token }}
|
|
104
|
+
TAG: ${{ github.ref_name }}
|
|
105
|
+
run: |
|
|
106
|
+
gh release create "$TAG" dist/* \
|
|
107
|
+
--repo "$GITHUB_REPOSITORY" \
|
|
108
|
+
--title "$TAG" \
|
|
109
|
+
--generate-notes
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
name: Security
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: ["main"]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: ["main"]
|
|
8
|
+
schedule:
|
|
9
|
+
- cron: "0 6 * * 1" # Weekly Monday 06:00 UTC — catch new CVEs without code change
|
|
10
|
+
|
|
11
|
+
permissions:
|
|
12
|
+
contents: read
|
|
13
|
+
|
|
14
|
+
jobs:
|
|
15
|
+
trivy:
|
|
16
|
+
name: Trivy (dependency CVEs + secrets)
|
|
17
|
+
runs-on: ubuntu-latest
|
|
18
|
+
steps:
|
|
19
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
20
|
+
with:
|
|
21
|
+
persist-credentials: false
|
|
22
|
+
|
|
23
|
+
- name: Install Trivy
|
|
24
|
+
run: |
|
|
25
|
+
curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh \
|
|
26
|
+
| sh -s -- -b /usr/local/bin latest
|
|
27
|
+
|
|
28
|
+
- name: Dependency vulnerability scan (HIGH/CRITICAL)
|
|
29
|
+
# Scans pyproject.toml / requirements / installed packages for known CVEs.
|
|
30
|
+
# OSV + NVD + GitHub Advisory DB. Exit 1 on any HIGH or CRITICAL finding.
|
|
31
|
+
run: |
|
|
32
|
+
trivy fs \
|
|
33
|
+
--scanners vuln \
|
|
34
|
+
--pkg-types library \
|
|
35
|
+
--severity HIGH,CRITICAL \
|
|
36
|
+
--exit-code 1 \
|
|
37
|
+
--format table \
|
|
38
|
+
.
|
|
39
|
+
|
|
40
|
+
- name: Secret scan
|
|
41
|
+
# Detects hardcoded credentials, API keys, private keys in source tree.
|
|
42
|
+
# Any finding fails the build — credentials must never be committed.
|
|
43
|
+
run: |
|
|
44
|
+
trivy fs \
|
|
45
|
+
--scanners secret \
|
|
46
|
+
--exit-code 1 \
|
|
47
|
+
--format table \
|
|
48
|
+
.
|
|
49
|
+
|
|
50
|
+
semgrep:
|
|
51
|
+
name: Semgrep (SAST)
|
|
52
|
+
runs-on: ubuntu-latest
|
|
53
|
+
steps:
|
|
54
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
55
|
+
with:
|
|
56
|
+
persist-credentials: false
|
|
57
|
+
|
|
58
|
+
- name: Set up Python
|
|
59
|
+
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
60
|
+
with:
|
|
61
|
+
python-version: "3.12"
|
|
62
|
+
|
|
63
|
+
- name: Install Semgrep
|
|
64
|
+
run: pip install semgrep
|
|
65
|
+
|
|
66
|
+
- name: SAST scan
|
|
67
|
+
# p/python — Python security rules (dangerous builtins, injection, etc.)
|
|
68
|
+
# p/secrets — hardcoded credential patterns (belt-and-suspenders vs Trivy)
|
|
69
|
+
# p/trailofbits — Trail of Bits crypto/protocol rules (relevant for RFC wire code)
|
|
70
|
+
# --error: any finding → exit 1. Suppress false positives inline with # nosemgrep.
|
|
71
|
+
run: |
|
|
72
|
+
semgrep \
|
|
73
|
+
--config p/python \
|
|
74
|
+
--config p/secrets \
|
|
75
|
+
--config p/trailofbits \
|
|
76
|
+
--error \
|
|
77
|
+
--no-rewrite-rule-ids \
|
|
78
|
+
src/ tests/
|
|
79
|
+
|
|
80
|
+
zizmor:
|
|
81
|
+
name: Zizmor (GitHub Actions workflow audit)
|
|
82
|
+
runs-on: ubuntu-latest
|
|
83
|
+
steps:
|
|
84
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
85
|
+
with:
|
|
86
|
+
persist-credentials: false
|
|
87
|
+
|
|
88
|
+
- name: Set up Python
|
|
89
|
+
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
90
|
+
with:
|
|
91
|
+
python-version: "3.12"
|
|
92
|
+
|
|
93
|
+
- name: Audit workflows
|
|
94
|
+
# GH_TOKEN enables zizmor's online audits — notably impostor-commit
|
|
95
|
+
# detection, which verifies that a pinned SHA actually belongs to the
|
|
96
|
+
# action's repository. Without it those audits are skipped, which is
|
|
97
|
+
# precisely the risk that pinning by SHA introduces.
|
|
98
|
+
env:
|
|
99
|
+
GH_TOKEN: ${{ github.token }}
|
|
100
|
+
run: |
|
|
101
|
+
pip install zizmor
|
|
102
|
+
zizmor --persona=regular .github/workflows/
|