syntaxmatrix 2.6.4.3__py3-none-any.whl → 3.0.0__py3-none-any.whl

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.
Files changed (45) hide show
  1. syntaxmatrix/__init__.py +6 -4
  2. syntaxmatrix/agentic/agents.py +195 -15
  3. syntaxmatrix/agentic/agents_orchestrer.py +16 -10
  4. syntaxmatrix/client_docs.py +237 -0
  5. syntaxmatrix/commentary.py +96 -25
  6. syntaxmatrix/core.py +156 -54
  7. syntaxmatrix/dataset_preprocessing.py +2 -2
  8. syntaxmatrix/db.py +60 -0
  9. syntaxmatrix/db_backends/__init__.py +1 -0
  10. syntaxmatrix/db_backends/postgres_backend.py +14 -0
  11. syntaxmatrix/db_backends/sqlite_backend.py +258 -0
  12. syntaxmatrix/db_contract.py +71 -0
  13. syntaxmatrix/kernel_manager.py +174 -150
  14. syntaxmatrix/page_builder_generation.py +654 -50
  15. syntaxmatrix/page_layout_contract.py +25 -3
  16. syntaxmatrix/page_patch_publish.py +368 -15
  17. syntaxmatrix/plugins/__init__.py +0 -0
  18. syntaxmatrix/plugins/plugin_manager.py +114 -0
  19. syntaxmatrix/premium/__init__.py +18 -0
  20. syntaxmatrix/premium/catalogue/__init__.py +121 -0
  21. syntaxmatrix/premium/gate.py +119 -0
  22. syntaxmatrix/premium/state.py +507 -0
  23. syntaxmatrix/premium/verify.py +222 -0
  24. syntaxmatrix/profiles.py +1 -1
  25. syntaxmatrix/routes.py +9782 -8004
  26. syntaxmatrix/settings/model_map.py +50 -65
  27. syntaxmatrix/settings/prompts.py +1435 -380
  28. syntaxmatrix/settings/string_navbar.py +4 -4
  29. syntaxmatrix/static/icons/bot_icon.png +0 -0
  30. syntaxmatrix/static/icons/bot_icon2.png +0 -0
  31. syntaxmatrix/templates/admin_billing.html +408 -0
  32. syntaxmatrix/templates/admin_branding.html +65 -2
  33. syntaxmatrix/templates/admin_features.html +54 -0
  34. syntaxmatrix/templates/dashboard.html +285 -8
  35. syntaxmatrix/templates/edit_page.html +199 -18
  36. syntaxmatrix/themes.py +17 -17
  37. syntaxmatrix/workspace_db.py +0 -23
  38. syntaxmatrix-3.0.0.dist-info/METADATA +219 -0
  39. {syntaxmatrix-2.6.4.3.dist-info → syntaxmatrix-3.0.0.dist-info}/RECORD +42 -30
  40. {syntaxmatrix-2.6.4.3.dist-info → syntaxmatrix-3.0.0.dist-info}/WHEEL +1 -1
  41. syntaxmatrix/settings/default.yaml +0 -13
  42. syntaxmatrix-2.6.4.3.dist-info/METADATA +0 -539
  43. syntaxmatrix-2.6.4.3.dist-info/licenses/LICENSE.txt +0 -21
  44. /syntaxmatrix/static/icons/{logo3.png → logo2.png} +0 -0
  45. {syntaxmatrix-2.6.4.3.dist-info → syntaxmatrix-3.0.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,222 @@
1
+ from __future__ import annotations
2
+
3
+ import base64
4
+ import hashlib
5
+ import json
6
+ import os
7
+ from dataclasses import dataclass
8
+ from datetime import datetime
9
+ from typing import Any, Dict, Optional
10
+
11
+ from syntaxmatrix.project_root import detect_project_root
12
+
13
+ try:
14
+ from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PublicKey
15
+ except Exception:
16
+ Ed25519PublicKey = None
17
+
18
+ DEFAULT_PUBLIC_KEY_B64 = (
19
+ (os.environ.get("SMX_PREMIUM_PUBLIC_KEY_B64") or "").strip()
20
+ or "Pne3EX_NoOo6pZ4UB87kpXaTf78A6tEfuwoTBZvVRbg"
21
+ )
22
+
23
+ _CACHED_PUBLIC_KEY_B64: Optional[str] = None
24
+ SECRET_KEY_FILENAME = ".smx_secret_key"
25
+
26
+ def _utcnow() -> datetime:
27
+ return datetime.utcnow()
28
+
29
+
30
+ def _resolved_client_dir() -> str:
31
+ return str(detect_project_root())
32
+
33
+
34
+ def _parse_iso_utc(s: str) -> Optional[datetime]:
35
+ if not s:
36
+ return None
37
+ s = str(s).strip()
38
+ if not s:
39
+ return None
40
+ s2 = s.replace(" ", "T")
41
+ if s2.endswith("Z"):
42
+ s2 = s2[:-1]
43
+ try:
44
+ return datetime.fromisoformat(s2)
45
+ except Exception:
46
+ return None
47
+
48
+
49
+ def _b64url_decode(s: str) -> bytes:
50
+ s = (s or "").strip()
51
+ if not s:
52
+ return b""
53
+ pad = "=" * (-len(s) % 4)
54
+ return base64.urlsafe_b64decode((s + pad).encode("utf-8"))
55
+
56
+
57
+ def _b64url_encode(b: bytes) -> str:
58
+ return base64.urlsafe_b64encode(b).decode("utf-8").rstrip("=")
59
+
60
+
61
+ def _safe_json(obj: Any) -> bytes:
62
+ return json.dumps(obj, sort_keys=True, separators=(",", ":"), ensure_ascii=False).encode("utf-8")
63
+
64
+
65
+ def _truthy(v: Any) -> bool:
66
+ return str(v).strip().lower() in ("1", "true", "yes", "on", "y")
67
+
68
+
69
+ def instance_fingerprint() -> str:
70
+ client_dir = _resolved_client_dir()
71
+ p = os.path.join(client_dir, SECRET_KEY_FILENAME)
72
+ try:
73
+ secret = open(p, "r", encoding="utf-8").read().strip()
74
+ except Exception:
75
+ return ""
76
+ if not secret:
77
+ return ""
78
+ digest = hashlib.sha256(secret.encode("utf-8")).digest()
79
+ return _b64url_encode(digest)
80
+
81
+
82
+ @dataclass
83
+ class VerifiedLicence:
84
+ ok: bool
85
+ entitlements: Dict[str, Any]
86
+ plan: str
87
+ error: str
88
+
89
+
90
+ def _normalise_payload(payload: Dict[str, Any]) -> Dict[str, Any]:
91
+ if not isinstance(payload, dict):
92
+ return {}
93
+ if isinstance(payload.get("entitlements"), dict):
94
+ ent = dict(payload.get("entitlements") or {})
95
+ for k in ("plan_id", "plan", "entitlement_version", "addons"):
96
+ if payload.get(k) is not None and ent.get(k) is None:
97
+ ent[k] = payload.get(k)
98
+ return ent
99
+ return dict(payload)
100
+
101
+
102
+ def _get_public_key_b64() -> str:
103
+ """
104
+ Resolve Ed25519 public key used for licence verification.
105
+
106
+ Order:
107
+ 1) SMX_PREMIUM_PUBLIC_KEY_B64 env var
108
+ 2) in-process cache
109
+ 3) <client_dir>/premium/public_key.b64 (cached file)
110
+ 4) GET <SMX_LICENCE_SERVER_URL>/v1/public-key (then cache to file)
111
+ 5) DEFAULT_PUBLIC_KEY_B64 fallback
112
+ """
113
+ global _CACHED_PUBLIC_KEY_B64
114
+
115
+ env = os.environ.get("SMX_PREMIUM_PUBLIC_KEY_B64")
116
+ if env and env.strip():
117
+ _CACHED_PUBLIC_KEY_B64 = env.strip()
118
+ return _CACHED_PUBLIC_KEY_B64
119
+ if _CACHED_PUBLIC_KEY_B64 and _CACHED_PUBLIC_KEY_B64.strip():
120
+ return _CACHED_PUBLIC_KEY_B64.strip()
121
+ client_dir = _resolved_client_dir()
122
+ try:
123
+ p = os.path.join(client_dir, "premium", "public_key.b64")
124
+ if os.path.exists(p):
125
+ key = open(p, "r", encoding="utf-8").read().strip()
126
+ if key:
127
+ _CACHED_PUBLIC_KEY_B64 = key
128
+ return key
129
+ except Exception:
130
+ pass
131
+ licence_server = (os.environ.get("SMX_LICENCE_SERVER_URL") or "").strip()
132
+ if licence_server:
133
+ url = licence_server.rstrip("/") + "/v1/public-key"
134
+ try:
135
+ import urllib.request
136
+
137
+ req = urllib.request.Request(url, method="GET")
138
+ with urllib.request.urlopen(req, timeout=10) as resp:
139
+ raw = resp.read().decode("utf-8", errors="replace").strip()
140
+
141
+ data = json.loads(raw) if raw else {}
142
+ key = str(data.get("public_key_b64") or "").strip()
143
+ if key:
144
+ _CACHED_PUBLIC_KEY_B64 = key
145
+ try:
146
+ os.makedirs(os.path.join(client_dir, "premium"), exist_ok=True)
147
+ with open(os.path.join(client_dir, "premium", "public_key.b64"), "w", encoding="utf-8") as f:
148
+ f.write(key)
149
+ except Exception:
150
+ pass
151
+ return key
152
+ except Exception:
153
+ pass
154
+ return (DEFAULT_PUBLIC_KEY_B64 or "").strip()
155
+
156
+
157
+ def _licence_message(payload: Dict[str, Any]) -> bytes:
158
+ body = {k: v for k, v in payload.items() if k != "sig"}
159
+ return _safe_json(body)
160
+
161
+
162
+ def verify_licence_payload(
163
+ payload: Dict[str, Any],
164
+ *,
165
+ now: Optional[datetime] = None,
166
+ allow_unsigned: Optional[bool] = None,
167
+ ) -> VerifiedLicence:
168
+ if not isinstance(payload, dict) or not payload:
169
+ return VerifiedLicence(False, {}, "free", "Licence payload is empty or not a JSON object")
170
+
171
+ allow_unsigned_eff = _truthy(os.environ.get("SMX_PREMIUM_ALLOW_UNSIGNED", "0"))
172
+ if allow_unsigned is not None:
173
+ allow_unsigned_eff = bool(allow_unsigned)
174
+
175
+ fp = instance_fingerprint()
176
+ if not fp:
177
+ return VerifiedLicence(False, {}, "free", "Cannot compute instance fingerprint (missing .smx_secret_key)")
178
+
179
+ lic_inst = str(payload.get("instance_id") or payload.get("instanceId") or "").strip()
180
+ if not lic_inst:
181
+ if not allow_unsigned_eff:
182
+ return VerifiedLicence(False, {}, "free", "Licence missing instance_id")
183
+ elif lic_inst != fp:
184
+ return VerifiedLicence(False, {}, "free", "Instance mismatch (licence is for a different install)")
185
+
186
+ now_dt = now or _utcnow()
187
+ exp_raw = payload.get("expires_at") or payload.get("expiresAt")
188
+ exp_dt = _parse_iso_utc(str(exp_raw)) if exp_raw else None
189
+ if exp_dt and now_dt > exp_dt:
190
+ return VerifiedLicence(False, {}, "free", "Licence has expired")
191
+
192
+ sig_b64 = str(payload.get("sig") or "").strip()
193
+ if not sig_b64:
194
+ if not allow_unsigned_eff:
195
+ return VerifiedLicence(False, {}, "free", "Licence is unsigned (sig missing)")
196
+ ent = _normalise_payload(payload)
197
+ plan = str(ent.get("plan_id") or ent.get("plan") or payload.get("plan_id") or payload.get("plan") or "free").strip().lower() or "free"
198
+ return VerifiedLicence(True, ent, plan, "")
199
+
200
+ if Ed25519PublicKey is None:
201
+ return VerifiedLicence(False, {}, "free", "cryptography package is required for licence verification")
202
+
203
+ pub_b64 = _get_public_key_b64()
204
+ if not pub_b64:
205
+ return VerifiedLicence(False, {}, "free", "Public key not configured (SMX_PREMIUM_PUBLIC_KEY_B64)")
206
+
207
+ try:
208
+ pub_bytes = _b64url_decode(pub_b64)
209
+ pub = Ed25519PublicKey.from_public_bytes(pub_bytes)
210
+ except Exception:
211
+ return VerifiedLicence(False, {}, "free", "Public key is invalid")
212
+
213
+ try:
214
+ sig = _b64url_decode(sig_b64)
215
+ msg = _licence_message(payload)
216
+ pub.verify(sig, msg)
217
+ except Exception:
218
+ return VerifiedLicence(False, {}, "free", "Signature verification failed")
219
+
220
+ ent = _normalise_payload(payload)
221
+ plan = str(ent.get("plan_id") or ent.get("plan") or payload.get("plan_id") or payload.get("plan") or "free").strip().lower() or "free"
222
+ return VerifiedLicence(True, ent, plan, "")
syntaxmatrix/profiles.py CHANGED
@@ -36,7 +36,7 @@ def get_client(profile):
36
36
 
37
37
  #1 - Google - gemini series
38
38
  if provider == "google":
39
- return genai.Client(api_key=api_key)
39
+ return genai.Client(api_key=api_key)
40
40
 
41
41
  #2 OpenAI gpt-5 series
42
42
  if provider == "openai":