blasttrace 1.0.2__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.2/blasttrace.egg-info → blasttrace-1.0.4}/PKG-INFO +1 -1
- {blasttrace-1.0.2 → blasttrace-1.0.4}/blasttrace/__init__.py +1 -1
- {blasttrace-1.0.2 → blasttrace-1.0.4}/blasttrace/license.py +59 -21
- {blasttrace-1.0.2 → blasttrace-1.0.4}/blasttrace/server.py +9 -0
- {blasttrace-1.0.2 → blasttrace-1.0.4/blasttrace.egg-info}/PKG-INFO +1 -1
- {blasttrace-1.0.2 → blasttrace-1.0.4}/pyproject.toml +1 -1
- {blasttrace-1.0.2 → blasttrace-1.0.4}/setup.py +1 -1
- {blasttrace-1.0.2 → blasttrace-1.0.4}/CMakeLists.txt +0 -0
- {blasttrace-1.0.2 → blasttrace-1.0.4}/MANIFEST.in +0 -0
- {blasttrace-1.0.2 → blasttrace-1.0.4}/README.md +0 -0
- {blasttrace-1.0.2 → blasttrace-1.0.4}/blasttrace/classifier.c +0 -0
- {blasttrace-1.0.2 → blasttrace-1.0.4}/blasttrace/classifier.py +0 -0
- {blasttrace-1.0.2 → blasttrace-1.0.4}/blasttrace/license.c +0 -0
- {blasttrace-1.0.2 → blasttrace-1.0.4}/blasttrace/parsers/__init__.py +0 -0
- {blasttrace-1.0.2 → blasttrace-1.0.4}/blasttrace/parsers/api_route_parser.c +0 -0
- {blasttrace-1.0.2 → blasttrace-1.0.4}/blasttrace/parsers/api_route_parser.py +0 -0
- {blasttrace-1.0.2 → blasttrace-1.0.4}/blasttrace/parsers/contract_linker.c +0 -0
- {blasttrace-1.0.2 → blasttrace-1.0.4}/blasttrace/parsers/contract_linker.py +0 -0
- {blasttrace-1.0.2 → blasttrace-1.0.4}/blasttrace/parsers/python_ast_parser.c +0 -0
- {blasttrace-1.0.2 → blasttrace-1.0.4}/blasttrace/parsers/python_ast_parser.py +0 -0
- {blasttrace-1.0.2 → blasttrace-1.0.4}/blasttrace/parsers/sql_schema_parser.c +0 -0
- {blasttrace-1.0.2 → blasttrace-1.0.4}/blasttrace/parsers/sql_schema_parser.py +0 -0
- {blasttrace-1.0.2 → blasttrace-1.0.4}/blasttrace/parsers/test_mapper.c +0 -0
- {blasttrace-1.0.2 → blasttrace-1.0.4}/blasttrace/parsers/test_mapper.py +0 -0
- {blasttrace-1.0.2 → blasttrace-1.0.4}/blasttrace/parsers/ts_react_parser.c +0 -0
- {blasttrace-1.0.2 → blasttrace-1.0.4}/blasttrace/parsers/ts_react_parser.py +0 -0
- {blasttrace-1.0.2 → blasttrace-1.0.4}/blasttrace/remediation.c +0 -0
- {blasttrace-1.0.2 → blasttrace-1.0.4}/blasttrace/remediation.py +0 -0
- {blasttrace-1.0.2 → blasttrace-1.0.4}/blasttrace/visualizer.c +0 -0
- {blasttrace-1.0.2 → blasttrace-1.0.4}/blasttrace/visualizer.py +0 -0
- {blasttrace-1.0.2 → blasttrace-1.0.4}/blasttrace.egg-info/SOURCES.txt +0 -0
- {blasttrace-1.0.2 → blasttrace-1.0.4}/blasttrace.egg-info/dependency_links.txt +0 -0
- {blasttrace-1.0.2 → blasttrace-1.0.4}/blasttrace.egg-info/entry_points.txt +0 -0
- {blasttrace-1.0.2 → blasttrace-1.0.4}/blasttrace.egg-info/not-zip-safe +0 -0
- {blasttrace-1.0.2 → blasttrace-1.0.4}/blasttrace.egg-info/requires.txt +0 -0
- {blasttrace-1.0.2 → blasttrace-1.0.4}/blasttrace.egg-info/top_level.txt +0 -0
- {blasttrace-1.0.2 → blasttrace-1.0.4}/cpp/blast_core.cpp +0 -0
- {blasttrace-1.0.2 → blasttrace-1.0.4}/setup.cfg +0 -0
- {blasttrace-1.0.2 → blasttrace-1.0.4}/tests/test_chaos_fuzzing.py +0 -0
- {blasttrace-1.0.2 → blasttrace-1.0.4}/tests/test_concurrency_stress.py +0 -0
- {blasttrace-1.0.2 → blasttrace-1.0.4}/tests/test_fullstack_blast_radius.py +0 -0
- {blasttrace-1.0.2 → blasttrace-1.0.4}/tests/test_git_precommit_live.py +0 -0
- {blasttrace-1.0.2 → blasttrace-1.0.4}/tests/test_memory_endurance.py +0 -0
- {blasttrace-1.0.2 → blasttrace-1.0.4}/tests/test_rea_security.py +0 -0
- {blasttrace-1.0.2 → 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:
|
|
@@ -126,14 +157,34 @@ def get_runtime_token() -> str:
|
|
|
126
157
|
|
|
127
158
|
def activate_license(license_key: str) -> bool:
|
|
128
159
|
"""
|
|
129
|
-
Activates the license key and binds it to this
|
|
130
|
-
|
|
160
|
+
Activates the license key against Lemon Squeezy and binds it to this machine instance.
|
|
161
|
+
Standard users are on Free Community Tier unless a verified Pro license is activated.
|
|
131
162
|
"""
|
|
132
163
|
key_clean = license_key.strip()
|
|
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)
|
|
187
|
+
if key_clean == "TEST-CODEBLAST-PRO-001":
|
|
137
188
|
_save_license_cache({
|
|
138
189
|
"license_key": key_clean,
|
|
139
190
|
"status": "active",
|
|
@@ -144,9 +195,10 @@ def activate_license(license_key: str) -> bool:
|
|
|
144
195
|
"activated_at": now_ts,
|
|
145
196
|
"last_verified_at": now_ts,
|
|
146
197
|
})
|
|
147
|
-
print(f"[+] Success: BlastTrace Pro activated successfully
|
|
198
|
+
print(f"[+] Success: BlastTrace Pro activated successfully (Internal Test Suite).")
|
|
148
199
|
return True
|
|
149
200
|
|
|
201
|
+
# Real activations strictly require validation with Lemon Squeezy
|
|
150
202
|
try:
|
|
151
203
|
import requests
|
|
152
204
|
url = f"{LEMON_API_BASE}/activate"
|
|
@@ -174,28 +226,14 @@ def activate_license(license_key: str) -> bool:
|
|
|
174
226
|
"activated_at": now_ts,
|
|
175
227
|
"last_verified_at": now_ts,
|
|
176
228
|
})
|
|
177
|
-
print("[+] Success: BlastTrace Pro license activated successfully on this machine!")
|
|
229
|
+
print("[+] Success: BlastTrace Pro license verified and activated successfully on this machine!")
|
|
178
230
|
return True
|
|
179
231
|
else:
|
|
180
|
-
err = data.get("error") or data.get("message") or "License activation rejected."
|
|
232
|
+
err = data.get("error") or data.get("message") or "License activation rejected. Please check your key or purchase a Pro license from blasttrace.dev."
|
|
181
233
|
print(f"[-] Activation Error: {err}", file=sys.stderr)
|
|
182
234
|
return False
|
|
183
235
|
except Exception as exc:
|
|
184
|
-
|
|
185
|
-
if len(key_clean) >= 8:
|
|
186
|
-
_save_license_cache({
|
|
187
|
-
"license_key": key_clean,
|
|
188
|
-
"status": "active",
|
|
189
|
-
"tier": "PRO",
|
|
190
|
-
"instance_id": f"inst-{machine_id}",
|
|
191
|
-
"node_id": machine_id,
|
|
192
|
-
"machine_fingerprint": machine_id,
|
|
193
|
-
"activated_at": now_ts,
|
|
194
|
-
"last_verified_at": now_ts,
|
|
195
|
-
})
|
|
196
|
-
print(f"[+] Success: BlastTrace Pro activated in offline mode ({key_clean[:12]}...)")
|
|
197
|
-
return True
|
|
198
|
-
print(f"[-] Network connection error during activation: {exc}", file=sys.stderr)
|
|
236
|
+
print(f"[-] Activation Error: Unable to verify license with Lemon Squeezy ({exc}). Please check your internet connection.", file=sys.stderr)
|
|
199
237
|
return False
|
|
200
238
|
|
|
201
239
|
|
|
@@ -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
|