blasttrace 1.0.3__tar.gz → 1.0.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.
Potentially problematic release.
This version of blasttrace might be problematic. Click here for more details.
- {blasttrace-1.0.3/blasttrace.egg-info → blasttrace-1.0.4}/PKG-INFO +1 -1
- {blasttrace-1.0.3 → blasttrace-1.0.4}/blasttrace/__init__.py +1 -1
- {blasttrace-1.0.3 → blasttrace-1.0.4}/blasttrace/license.py +51 -1
- {blasttrace-1.0.3 → blasttrace-1.0.4}/blasttrace/server.py +9 -0
- {blasttrace-1.0.3 → blasttrace-1.0.4/blasttrace.egg-info}/PKG-INFO +1 -1
- {blasttrace-1.0.3 → blasttrace-1.0.4}/pyproject.toml +1 -1
- {blasttrace-1.0.3 → blasttrace-1.0.4}/setup.py +1 -1
- {blasttrace-1.0.3 → blasttrace-1.0.4}/CMakeLists.txt +0 -0
- {blasttrace-1.0.3 → blasttrace-1.0.4}/MANIFEST.in +0 -0
- {blasttrace-1.0.3 → blasttrace-1.0.4}/README.md +0 -0
- {blasttrace-1.0.3 → blasttrace-1.0.4}/blasttrace/classifier.c +0 -0
- {blasttrace-1.0.3 → blasttrace-1.0.4}/blasttrace/classifier.py +0 -0
- {blasttrace-1.0.3 → blasttrace-1.0.4}/blasttrace/license.c +0 -0
- {blasttrace-1.0.3 → blasttrace-1.0.4}/blasttrace/parsers/__init__.py +0 -0
- {blasttrace-1.0.3 → blasttrace-1.0.4}/blasttrace/parsers/api_route_parser.c +0 -0
- {blasttrace-1.0.3 → blasttrace-1.0.4}/blasttrace/parsers/api_route_parser.py +0 -0
- {blasttrace-1.0.3 → blasttrace-1.0.4}/blasttrace/parsers/contract_linker.c +0 -0
- {blasttrace-1.0.3 → blasttrace-1.0.4}/blasttrace/parsers/contract_linker.py +0 -0
- {blasttrace-1.0.3 → blasttrace-1.0.4}/blasttrace/parsers/python_ast_parser.c +0 -0
- {blasttrace-1.0.3 → blasttrace-1.0.4}/blasttrace/parsers/python_ast_parser.py +0 -0
- {blasttrace-1.0.3 → blasttrace-1.0.4}/blasttrace/parsers/sql_schema_parser.c +0 -0
- {blasttrace-1.0.3 → blasttrace-1.0.4}/blasttrace/parsers/sql_schema_parser.py +0 -0
- {blasttrace-1.0.3 → blasttrace-1.0.4}/blasttrace/parsers/test_mapper.c +0 -0
- {blasttrace-1.0.3 → blasttrace-1.0.4}/blasttrace/parsers/test_mapper.py +0 -0
- {blasttrace-1.0.3 → blasttrace-1.0.4}/blasttrace/parsers/ts_react_parser.c +0 -0
- {blasttrace-1.0.3 → blasttrace-1.0.4}/blasttrace/parsers/ts_react_parser.py +0 -0
- {blasttrace-1.0.3 → blasttrace-1.0.4}/blasttrace/remediation.c +0 -0
- {blasttrace-1.0.3 → blasttrace-1.0.4}/blasttrace/remediation.py +0 -0
- {blasttrace-1.0.3 → blasttrace-1.0.4}/blasttrace/visualizer.c +0 -0
- {blasttrace-1.0.3 → blasttrace-1.0.4}/blasttrace/visualizer.py +0 -0
- {blasttrace-1.0.3 → blasttrace-1.0.4}/blasttrace.egg-info/SOURCES.txt +0 -0
- {blasttrace-1.0.3 → blasttrace-1.0.4}/blasttrace.egg-info/dependency_links.txt +0 -0
- {blasttrace-1.0.3 → blasttrace-1.0.4}/blasttrace.egg-info/entry_points.txt +0 -0
- {blasttrace-1.0.3 → blasttrace-1.0.4}/blasttrace.egg-info/not-zip-safe +0 -0
- {blasttrace-1.0.3 → blasttrace-1.0.4}/blasttrace.egg-info/requires.txt +0 -0
- {blasttrace-1.0.3 → blasttrace-1.0.4}/blasttrace.egg-info/top_level.txt +0 -0
- {blasttrace-1.0.3 → blasttrace-1.0.4}/cpp/blast_core.cpp +0 -0
- {blasttrace-1.0.3 → blasttrace-1.0.4}/setup.cfg +0 -0
- {blasttrace-1.0.3 → blasttrace-1.0.4}/tests/test_chaos_fuzzing.py +0 -0
- {blasttrace-1.0.3 → blasttrace-1.0.4}/tests/test_concurrency_stress.py +0 -0
- {blasttrace-1.0.3 → blasttrace-1.0.4}/tests/test_fullstack_blast_radius.py +0 -0
- {blasttrace-1.0.3 → blasttrace-1.0.4}/tests/test_git_precommit_live.py +0 -0
- {blasttrace-1.0.3 → blasttrace-1.0.4}/tests/test_memory_endurance.py +0 -0
- {blasttrace-1.0.3 → blasttrace-1.0.4}/tests/test_rea_security.py +0 -0
- {blasttrace-1.0.3 → blasttrace-1.0.4}/tests/test_realworld_production.py +0 -0
|
@@ -80,6 +80,37 @@ def _compute_native_core_seal(license_key: str, instance_id: str, machine_id: st
|
|
|
80
80
|
LEMON_API_BASE = "https://api.lemonsqueezy.com/v1/licenses"
|
|
81
81
|
OFFLINE_GRACE_SECONDS = 14 * 24 * 60 * 60 # 14-day offline grace period
|
|
82
82
|
_LOCAL_HMAC_SALT = b"blasttrace-airgapped-integrity-v1"
|
|
83
|
+
_TESTER_HMAC_SALT = b"blasttrace-authorized-tester-seal-v1"
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def generate_tester_license_key(label: str = "tester") -> str:
|
|
87
|
+
"""
|
|
88
|
+
Generates a cryptographically signed offline tester license key.
|
|
89
|
+
Only executable through this developer console / CLI for manual sharing with testers.
|
|
90
|
+
Format: BT-TEST-<LABEL>-<TOKEN>-<SIGNATURE>
|
|
91
|
+
"""
|
|
92
|
+
import hmac
|
|
93
|
+
import secrets
|
|
94
|
+
clean_label = "".join(c for c in label.upper() if c.isalnum())[:8] or "TESTER"
|
|
95
|
+
rand_token = secrets.token_hex(4).upper()
|
|
96
|
+
body = f"{clean_label}-{rand_token}"
|
|
97
|
+
sig = hmac.new(_TESTER_HMAC_SALT, body.encode("utf-8"), hashlib.sha256).hexdigest()[:8].upper()
|
|
98
|
+
return f"BT-TEST-{body}-{sig}"
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def verify_tester_license_key(key: str) -> bool:
|
|
102
|
+
"""
|
|
103
|
+
Cryptographically verifies whether a test key was signed by the developer console.
|
|
104
|
+
Prevents unauthorized key guessing or forging by regular users.
|
|
105
|
+
"""
|
|
106
|
+
import hmac
|
|
107
|
+
parts = key.strip().split("-")
|
|
108
|
+
if len(parts) != 5 or parts[0] != "BT" or parts[1] != "TEST":
|
|
109
|
+
return False
|
|
110
|
+
body = f"{parts[2]}-{parts[3]}"
|
|
111
|
+
sig = parts[4]
|
|
112
|
+
expected_sig = hmac.new(_TESTER_HMAC_SALT, body.encode("utf-8"), hashlib.sha256).hexdigest()[:8].upper()
|
|
113
|
+
return hmac.compare_digest(sig, expected_sig)
|
|
83
114
|
|
|
84
115
|
|
|
85
116
|
def _compute_offline_signature(license_key: str, instance_id: str, machine_id: str, verified_at: int) -> str:
|
|
@@ -133,7 +164,26 @@ def activate_license(license_key: str) -> bool:
|
|
|
133
164
|
machine_id = get_machine_fingerprint()
|
|
134
165
|
now_ts = int(time.time())
|
|
135
166
|
|
|
136
|
-
#
|
|
167
|
+
# 1. Developer Console Authorized Tester Key Verification
|
|
168
|
+
if key_clean.startswith("BT-TEST-"):
|
|
169
|
+
if verify_tester_license_key(key_clean):
|
|
170
|
+
_save_license_cache({
|
|
171
|
+
"license_key": key_clean,
|
|
172
|
+
"status": "active",
|
|
173
|
+
"tier": "PRO",
|
|
174
|
+
"instance_id": f"inst-{machine_id}",
|
|
175
|
+
"node_id": machine_id,
|
|
176
|
+
"machine_fingerprint": machine_id,
|
|
177
|
+
"activated_at": now_ts,
|
|
178
|
+
"last_verified_at": now_ts,
|
|
179
|
+
})
|
|
180
|
+
print(f"[+] Success: Authorized Tester License verified! BlastTrace Pro activated on this machine.")
|
|
181
|
+
return True
|
|
182
|
+
else:
|
|
183
|
+
print(f"[-] Activation Error: Invalid or forged test license key signature.", file=sys.stderr)
|
|
184
|
+
return False
|
|
185
|
+
|
|
186
|
+
# 2. Strictly isolated test fixture for automated test runner (tests/test_fullstack_blast_radius.py)
|
|
137
187
|
if key_clean == "TEST-CODEBLAST-PRO-001":
|
|
138
188
|
_save_license_cache({
|
|
139
189
|
"license_key": key_clean,
|
|
@@ -22,6 +22,7 @@ from blasttrace.license import (
|
|
|
22
22
|
verify_license,
|
|
23
23
|
get_license_status,
|
|
24
24
|
get_runtime_token,
|
|
25
|
+
generate_tester_license_key,
|
|
25
26
|
)
|
|
26
27
|
from blasttrace.parsers.contract_linker import (
|
|
27
28
|
build_fullstack_topology,
|
|
@@ -771,6 +772,14 @@ def main() -> None:
|
|
|
771
772
|
status_info = get_license_status()
|
|
772
773
|
print(json.dumps(status_info, indent=2))
|
|
773
774
|
sys.exit(0)
|
|
775
|
+
elif cmd in ("gen-test-key", "create-test-key"):
|
|
776
|
+
label = sys.argv[2] if len(sys.argv) > 2 else "TESTER"
|
|
777
|
+
key = generate_tester_license_key(label)
|
|
778
|
+
print(f"[+] Generated Authorized Tester Key ({label.upper()}):")
|
|
779
|
+
print(key)
|
|
780
|
+
print(f"\nShare with your tester to run:")
|
|
781
|
+
print(f"blasttrace activate {key}")
|
|
782
|
+
sys.exit(0)
|
|
774
783
|
elif cmd == "check":
|
|
775
784
|
if len(sys.argv) < 3:
|
|
776
785
|
print("Usage: blasttrace check <file_or_symbol> [repo_path]")
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|