From 3cf76bee76289fe764f4b4974de89756825ad38c Mon Sep 17 00:00:00 2001 From: Jaixii Date: Sun, 26 Jul 2026 01:26:17 +0000 Subject: [PATCH 01/82] Fix licensing gating, cloud failure modes and update hangs for launch Closes defects that denied paying customers what they bought, hung or crashed the client when the cloud was unreachable, and leaked a credential into logs. Each fix carries a regression test. Paying customers were denied what they bought - /api/license always returned an empty feature list, so Analytics, Automation and Team rendered with PRO/TEAM lock badges for customers who had paid for them. It now reports the entitled feature set. - The plan is read from the registration and refresh handshake, which now discloses it, with an explicit precedence: ENGRAPHIS_CLOUD_PLAN override, then the persisted session plan, then the cached entitlement, then inference. A Team customer previously had to set an undocumented environment variable or be shown PRO. - Team upgrade links pointed at the Pro page. - A 409 consent_required is no longer treated as a billing answer. It was folded into the entitlement check, so a paying customer who had not set ENGRAPHIS_MANAGED_COMPUTE_CONSENT=1 was shown a panel telling them to buy the plan they already owned. Consent is now routed ahead of entitlement at every hosted call site. - loadSyncStatus rendered the purchase panel for every failure, including a transient network error or a 5xx, so a dropped connection told a paying customer to buy Pro. - /memory/license reported plan "local" for a connected paying customer, so the two license surfaces contradicted each other. Cloud failure modes - Draining an HTTP error body inside the except block let a timeout escape as an unhandled TimeoutError, surfacing as an opaque 500 with a traceback exactly when the cloud was flaky. - A DNS or resolution failure raised the same error as a genuinely malformed URL and was reported to the customer as a non-transient configuration problem with no retry. - Lapsed billing was indistinguishable from an outage: 402, 429 and 404 all collapsed into one 503, so a past_due customer retried forever instead of being sent to billing. - Connection attempts shared one deadline instead of giving each vetted address the full timeout, which turned a 10s refresh budget into N x 10s while holding the exclusive cross-process refresh lock. - PinnedHTTPSConnection pins a default connect timeout rather than inheriting urllib's block-forever default. Credential handling - The access token is excluded from the client's repr. The dataclass default printed a live bearer token into any traceback frame or debug log. - update_check.py uses the pinned HTTPS opener, so the one credential-adjacent request with a user-controllable endpoint is no longer exempt from the repo's SSRF and DNS-rebinding vetting. Updater - scripts/update.py had nineteen untimed network subprocess calls, all with captured output, so engraphis-update hung silently and indefinitely against a stalled index or unreachable remote. A stall mid-upgrade left the tree checked out to the new tag with the rollback unreached. Every call is now bounded and the rollback runs on timeout. Test suite: ~1209 -> 1363 passing, plus 11 end-to-end tests. The end-to-end suite previously only ever exercised a free customer, which is why a paying user seeing a lock badge survived this long; it now covers Pro, Team and lapsed Team. --- .env.example | 25 +- engraphis/cloud_features.py | 57 +- engraphis/cloud_session.py | 162 +++- engraphis/hosted_client.py | 55 +- engraphis/routes/memory.py | 22 +- engraphis/routes/v2_api.py | 570 ++++++++++++- engraphis/static/dashboard.css | 1 + engraphis/static/dashboard.js | 36 +- engraphis/update_check.py | 11 +- scripts/update.py | 158 +++- tests/e2e/commercial.spec.js | 173 +++- tests/test_client_launch.py | 373 +++++++++ tests/test_dashboard_auth_placement.py | 214 ++++- tests/test_hosted_plan_resolution.py | 1032 ++++++++++++++++++++++++ tests/test_licensing_launch.py | 473 +++++++++++ 15 files changed, 3255 insertions(+), 107 deletions(-) create mode 100644 tests/test_client_launch.py create mode 100644 tests/test_hosted_plan_resolution.py create mode 100644 tests/test_licensing_launch.py diff --git a/.env.example b/.env.example index 9a3a72b..5d9e504 100644 --- a/.env.example +++ b/.env.example @@ -161,7 +161,30 @@ ENGRAPHIS_LLM_API_KEY=sk-your-key-here # ENGRAPHIS_CLOUD_TOKEN_SUBJECT=member # ENGRAPHIS_CLOUD_ACCESS_TOKEN= -# Persistent customer state (cloud session and optional saved scoped relay bearer). +# Which plan the dashboard shows, and which capabilities it draws as unlocked. You should +# not need either of these. +# +# The plan is resolved automatically: once this installation has reached the control plane +# it reads the authoritative entitlement (plan and feature list) and caches it beside the +# cloud session, so a Pro or Team badge is correct on every later boot including offline +# ones. The refresh is opportunistic and runs on a background thread — it never blocks or +# delays startup, and it never fails the dashboard when the cloud is unreachable. Before +# the very first successful contact a connected installation is presented as Pro, the +# smallest paid plan, so a paying customer is never shown the free local core. +# +# ENGRAPHIS_CLOUD_PLAN is an override for the cases automatic resolution cannot cover: an +# air-gapped deployment, or one pinned to a short-lived ENGRAPHIS_CLOUD_ACCESS_TOKEN that +# cannot refresh. It takes precedence over the cached entitlement. Accepts pro, team, or +# free. It is presentation only — setting it grants nothing, because Engraphis Cloud +# authorizes every paid call regardless of what this client displays. +# ENGRAPHIS_CLOUD_PLAN=team +# +# Set to 0 to stop the client contacting the control plane for the entitlement at all. The +# badge then falls back to ENGRAPHIS_CLOUD_PLAN, or to the last cached answer. +# ENGRAPHIS_CLOUD_ENTITLEMENT_REFRESH=0 + +# Persistent customer state (cloud session, the cached hosted entitlement, and an optional +# saved scoped relay bearer). # Locally defaults to ~/.engraphis; in a container use a private persistent volume. # ENGRAPHIS_STATE_DIR=/data/.engraphis diff --git a/engraphis/cloud_features.py b/engraphis/cloud_features.py index 2235517..64c7984 100644 --- a/engraphis/cloud_features.py +++ b/engraphis/cloud_features.py @@ -14,12 +14,12 @@ import urllib.error import urllib.request import uuid -from dataclasses import dataclass +from dataclasses import dataclass, field from typing import Any, Optional from urllib.parse import quote from engraphis.cloud_session import CloudSessionError, access_for_workspace -from engraphis.hosted_client import build_pinned_https_opener +from engraphis.hosted_client import build_pinned_https_opener, upgrade_url SNAPSHOT_SCHEMA = "engraphis-managed-snapshot/v1" MAX_RESPONSE_BYTES = 16 * 1024 * 1024 @@ -67,7 +67,14 @@ def _public_http_error(status: int) -> tuple[str, bool]: if status in {401, 403}: return "Engraphis Cloud authorization was rejected.", False if status == 402: - return "This hosted feature is not available for the current plan.", False + # 402 is the control plane's "no active paid entitlement", which a lapsed or + # past_due subscription reaches just as often as a genuine free plan. Name the + # billing page so a paying customer can fix it instead of reading a dead end. + return ( + "This hosted feature needs an active Engraphis Cloud subscription. Check " + "billing or upgrade at %s." % upgrade_url(), + False, + ) if status == 404: return "The hosted workspace or feature was not found.", False if status == 409: @@ -81,6 +88,43 @@ def _public_http_error(status: int) -> tuple[str, bool]: return "Engraphis Cloud rejected the request.", False +def _public_session_error(status: int) -> tuple[str, bool]: + """Map a session-acquisition failure to fixed, actionable public copy. + + ``CloudSessionError`` text is never forwarded across this boundary (it can quote local + state paths), but the bare status alone reads as an outage for every cause. A customer + whose subscription lapsed, whose session was revoked, or who is simply offline each + need a different next step, and only the transient ones are worth retrying. + """ + + if status == 401: + return ( + "Connect this installation to Engraphis Cloud to use hosted features.", + False, + ) + if status == 402: + return ( + "This hosted feature needs an active Engraphis Cloud subscription. Check " + "billing or upgrade at %s." % upgrade_url(), + False, + ) + if status == 403: + return ("Engraphis Cloud authorization was rejected.", False) + if status == 409: + return ( + "The saved cloud session is unusable; connect this installation again.", + False, + ) + if status == 429: + return ("Engraphis Cloud is temporarily busy. Try again shortly.", True) + if status >= 500: + return ( + "Engraphis Cloud is unreachable; hosted features resume once it responds.", + True, + ) + return ("The cloud session is unavailable.", False) + + def _metadata(value: Any) -> dict: if isinstance(value, dict): return value @@ -297,7 +341,9 @@ def _build_managed_snapshot_locked(service: Any, workspace: str, *, class CloudFeatureClient: base_url: str organization_id: str - access_token: str + # A dataclass ``__repr__`` prints every field, so the default would put a live bearer + # token into any traceback, log line, or debugger frame that renders this client. + access_token: str = field(repr=False) timeout_seconds: float = 15.0 @classmethod @@ -306,8 +352,9 @@ def from_environment(cls, workspace_id: str) -> "CloudFeatureClient": access_token, organization_id, base_url = access_for_workspace(workspace_id) except CloudSessionError as exc: status = exc.status if 400 <= exc.status <= 599 else 503 + message, transient = _public_session_error(status) raise CloudFeatureError( - "The cloud session is unavailable.", status=status + message, status=status, transient=transient ) from exc except ValueError as exc: raise CloudFeatureError( diff --git a/engraphis/cloud_session.py b/engraphis/cloud_session.py index f3f97dd..63fb21b 100644 --- a/engraphis/cloud_session.py +++ b/engraphis/cloud_session.py @@ -10,13 +10,19 @@ import os import stat import threading +import time import urllib.error import urllib.request from contextlib import contextmanager from pathlib import Path from typing import Optional, Tuple -from engraphis.hosted_client import build_pinned_https_opener, validate_cloud_base_url +from engraphis.hosted_client import ( + CloudUrlUnresolved, + build_pinned_https_opener, + upgrade_url, + validate_cloud_base_url, +) from engraphis.private_state import ( UnsafeStateFile, atomic_private_text, @@ -53,6 +59,21 @@ def _token_subject(saved: dict) -> str: return _validated_token_subject(configured or saved.get("token_subject") or "member") +def _reachable_cloud_base_url(value: str) -> str: + """Validate a cloud endpoint, keeping "offline" separate from "misconfigured". + + ``validate_cloud_base_url`` resolves the host, so a paying customer on a plane or + behind a broken resolver raises the same ``ValueError`` as a genuinely bad URL. The + caller turns that into a permanent "your configuration is invalid", which is both + wrong and unactionable. Report a resolution failure as the retryable outage it is. + """ + + try: + return validate_cloud_base_url(value) + except CloudUrlUnresolved as exc: + raise CloudSessionError("Engraphis Cloud is temporarily unreachable.") from exc + + def _session_path() -> Path: root = os.environ.get("ENGRAPHIS_STATE_DIR", "").strip() base = Path(root).expanduser() if root else Path.home() / ".engraphis" @@ -191,6 +212,81 @@ def _save(value: dict) -> None: atomic_private_text(path, json.dumps(value, sort_keys=True, separators=(",", ":"))) +#: Plans that carry no paid cloud access, used only to default an absent activity flag. +_UNPAID_PLANS = ("free", "local") +#: Bounds on the entitlement fields before they are written into the session record. The +#: record is read back under a 64 KiB private-state cap, so an unbounded provider value +#: could grow the file past that cap and make the whole session permanently unreadable. +#: These are presentation strings; anything longer is not a plan name or a feature key. +_MAX_PLAN_CHARS = 64 +_MAX_FEATURES = 32 +_MAX_FEATURE_CHARS = 64 + + +def _declared_entitlement(response: object) -> dict: + """Return the entitlement fields a control-plane response carried, or ``{}``. + + ``DeviceRegistrationResponse`` — the body both ``/internal/devices/register`` and + ``POST /v1/tokens/refresh`` answer with — carries ``plan``, ``cloud_features`` and + ``cloud_access_active``. They are read as *optional* on purpose: a control plane that + has not deployed them yet returns exactly what it always did, and this client must keep + working against it rather than requiring a newer server. An absent or unusable ``plan`` + therefore yields ``{}``, which leaves whatever the caller already knew in place. + + Nothing here is authority. The cloud authorizes every paid call regardless of what + this record says; persisting it only saves the dashboard from guessing. + """ + + if not isinstance(response, dict): + return {} + plan = response.get("plan") + if not isinstance(plan, str) or not plan.strip(): + return {} + plan = plan.strip().lower()[:_MAX_PLAN_CHARS] + active = response.get("cloud_access_active") + declared = { + "plan": plan, + # Absent is not "inactive". Defaulting a paid plan to ``False`` would re-lock a + # paying customer against a server that reports the plan but not the flag. + "cloud_access_active": ( + bool(active) if isinstance(active, bool) else plan not in _UNPAID_PLANS + ), + "entitlement_checked_at": time.time(), + } + features = response.get("cloud_features") + if isinstance(features, (list, tuple)): + declared["cloud_features"] = sorted({ + item.strip().lower()[:_MAX_FEATURE_CHARS] + for item in features if isinstance(item, str) and item.strip() + })[:_MAX_FEATURES] + return declared + + +def saved_entitlement() -> dict: + """Return the entitlement persisted from the last registration or refresh, or ``{}``. + + This is the client's primary plan answer: it rides the two calls the client already + makes, so it needs no extra request and is refreshed whenever any cloud feature is used. + Reads state only — no network, no lock, and never raises, because the dashboard's plan + badge is on the boot path. + """ + + try: + saved = _load() + declared = _declared_entitlement(saved) + if not declared: + return {} + try: + checked_at = float(saved.get("entitlement_checked_at") or 0.0) + except (TypeError, ValueError, OverflowError): + checked_at = 0.0 + declared["entitlement_checked_at"] = checked_at + declared["organization_id"] = str(saved.get("organization_id") or "") + return declared + except Exception: # noqa: BLE001 — an unreadable session is simply "nothing known yet" + return {} + + def save_bootstrap(response: dict, *, control_url: str, compute_url: Optional[str] = None) -> None: """Persist the one-time bootstrap/refresh material returned by the control plane.""" @@ -213,10 +309,45 @@ def save_bootstrap(response: dict, *, control_url: str, response.get("token_subject") or "member" ), } + # Whatever entitlement the control plane volunteered, so the dashboard knows the plan + # from the first boot instead of inferring it. Absent on an older cloud; harmless. + value.update(_declared_entitlement(response)) with _refresh_lock(): _save(value) +def _refresh_http_error(status: int) -> CloudSessionError: + """Map a control-plane status to fixed, actionable public copy. + + Only the status is used: provider bodies are untrusted and may carry credentials or + internal URLs. Billing and authorization failures must stay distinguishable from an + outage -- a lapsed subscription reported as "temporarily unavailable" makes a paying + customer retry forever instead of being sent to the one page that fixes it. + """ + + if status in {401, 403}: + return CloudSessionError( + "The cloud session expired or was revoked; connect again.", status=status + ) + if status == 402: + return CloudSessionError( + "This Engraphis Cloud subscription is not active. Update billing at %s to " + "restore Pro and Team features." % upgrade_url(), + status=402, + ) + if status == 404: + return CloudSessionError( + "This installation is no longer registered with Engraphis Cloud; " + "connect again.", + status=409, + ) + if status == 429: + return CloudSessionError( + "Engraphis Cloud is temporarily busy. Try again shortly.", status=429 + ) + return CloudSessionError("Engraphis Cloud could not refresh this session.") + + def _post_refresh(control_url: str, refresh: str, workspace_id: str, token_subject: str) -> dict: payload = json.dumps({ @@ -240,16 +371,21 @@ def _post_refresh(control_url: str, refresh: str, workspace_id: str, ) as response: raw = response.read(_MAX_RESPONSE_BYTES + 1) except urllib.error.HTTPError as exc: + code = exc.code + # Draining and closing the error body can itself time out or reset. A sibling + # ``except`` clause of this ``try`` does NOT cover an exception raised inside this + # handler, so an unguarded read escapes as an unhandled traceback whenever the + # cloud is flaky -- exactly the launch-day condition this path exists for. try: exc.read(_MAX_RESPONSE_BYTES + 1) - if exc.code in {401, 403}: - raise CloudSessionError( - "The cloud session expired or was revoked; connect again.", - status=exc.code, - ) - raise CloudSessionError("Engraphis Cloud could not refresh this session.") + except (OSError, ValueError): + pass finally: - exc.close() + try: + exc.close() + except (OSError, ValueError): + pass + raise _refresh_http_error(code) except (urllib.error.URLError, TimeoutError, OSError) as exc: raise CloudSessionError("Engraphis Cloud is temporarily unreachable.") from exc if len(raw) > _MAX_RESPONSE_BYTES: @@ -294,7 +430,7 @@ def access_for_workspace( direct_org = os.environ.get("ENGRAPHIS_CLOUD_ORGANIZATION_ID", "").strip() direct_compute = os.environ.get("ENGRAPHIS_CLOUD_COMPUTE_URL", "").strip() if direct_token and direct_org and (direct_compute or not require_compute): - compute_url = validate_cloud_base_url(direct_compute) if direct_compute else "" + compute_url = _reachable_cloud_base_url(direct_compute) if direct_compute else "" return direct_token, direct_org, compute_url # Do not create the owner-only state directory merely to report an unconnected @@ -323,8 +459,8 @@ def access_for_workspace( raise CloudSessionError( "Connect this installation to Engraphis Cloud first.", status=401 ) - control = validate_cloud_base_url(control) - compute = validate_cloud_base_url(compute) if compute else "" + control = _reachable_cloud_base_url(control) + compute = _reachable_cloud_base_url(compute) if compute else "" token_subject = _token_subject(saved) body = _post_refresh(control, refresh, workspace_id, token_subject) access = str(body.get("access_token") or "").strip() @@ -347,5 +483,9 @@ def access_for_workspace( "refresh_expires_at": str(body.get("refresh_expires_at") or ""), "token_subject": response_subject, }) + # The refresh response carries the same entitlement fields as registration, so the + # plan re-confirms itself on every token rotation. An older cloud omits them and + # the previously persisted answer (if any) is left untouched. + updated.update(_declared_entitlement(body)) _save(updated) return access, organization_id, compute diff --git a/engraphis/hosted_client.py b/engraphis/hosted_client.py index d633a0c..560ff47 100644 --- a/engraphis/hosted_client.py +++ b/engraphis/hosted_client.py @@ -11,6 +11,7 @@ import os import socket import sys +import time import urllib.request from typing import Optional from urllib.parse import urlsplit, urlunsplit @@ -20,6 +21,14 @@ TRIAL_SECONDS = 3 * 24 * 60 * 60 MAX_LOCAL_WRITE_GRACE_SECONDS = 24 * 60 * 60 +# A credential-bearing cloud connection must never inherit "block forever". urllib hands +# ``socket._GLOBAL_DEFAULT_TIMEOUT`` to the connection whenever a caller omits ``timeout=``, +# so substitute a bounded default rather than letting a customer's agent hang on launch day. +DEFAULT_CONNECT_TIMEOUT_SECONDS = 15.0 +# One vetted address must not be able to spend the whole budget and leave nothing for the +# rest, but every attempt still gets a usable floor so a slow first hop is not aborted. +MIN_ATTEMPT_TIMEOUT_SECONDS = 0.5 + # The hosted dashboard and the commercial account portal are separate surfaces. # Upgrade/connect actions must land on the authenticated control-plane portal; the # dashboard host does not serve its own ``/account`` route. @@ -36,6 +45,16 @@ } +class CloudUrlUnresolved(ValueError): + """The cloud endpoint could not be resolved right now. + + This is a *reachability* failure, not a misconfiguration: an offline laptop and a + broken resolver both land here. It stays a ``ValueError`` so existing callers keep + working, but lets a caller degrade an offline paying customer to a retryable + "temporarily unreachable" instead of a permanent "your configuration is invalid". + """ + + class HostedFeatureError(RuntimeError): """A hosted feature is unavailable to this local client. @@ -99,7 +118,7 @@ def _validated_addresses(host: str) -> list[str]: host, None, socket.AF_UNSPEC, socket.SOCK_STREAM ) except (socket.gaierror, OSError): - raise ValueError("cloud service URL could not be resolved") from None + raise CloudUrlUnresolved("cloud service URL could not be resolved") from None addresses = [] loopback_name = _is_loopback_host(host) @@ -115,7 +134,7 @@ def _validated_addresses(host: str) -> list[str]: raise ValueError("cloud service URL must not target private/reserved IP ranges") addresses.append(str(address)) if not addresses: - raise ValueError("cloud service URL could not be resolved") + raise CloudUrlUnresolved("cloud service URL could not be resolved") return list(dict.fromkeys(addresses)) @@ -124,9 +143,29 @@ class PinnedHTTPSConnection(http.client.HTTPSConnection): def __init__(self, host, *args, **kwargs): super().__init__(host, *args, **kwargs) + # ``http.client`` stores ``socket._GLOBAL_DEFAULT_TIMEOUT`` (or ``None``) when no + # timeout was supplied, and both mean "block forever" at the socket layer. Neither + # is acceptable for a credential-bearing hosted call, so pin a bounded default. + if not isinstance(self.timeout, (int, float)) or isinstance(self.timeout, bool): + self.timeout = DEFAULT_CONNECT_TIMEOUT_SECONDS self._tls_server_hostname = self.host self._tunnel_targets = [] + def _connect_deadline(self): + """Return the monotonic instant by which every dial attempt must be finished.""" + + return time.monotonic() + max(float(self.timeout), 0.0) + + def _attempt_timeout(self, deadline): + """Share one caller-supplied budget across every vetted address. + + Handing each address the full timeout turns a 10s budget into N x 10s for a + multi-homed endpoint that blackholes traffic -- and ``cloud_session`` dials while + holding an exclusive cross-process refresh lock, so every other worker waits too. + """ + + return max(deadline - time.monotonic(), MIN_ATTEMPT_TIMEOUT_SECONDS) + def set_tunnel(self, host, port=None, headers=None): # Make a configured proxy CONNECT to the vetted numeric target. TLS still # authenticates the original hostname after the tunnel is established. @@ -149,6 +188,7 @@ def connect(self): def _connect_directly(self): last_error = None + deadline = self._connect_deadline() for target in _validated_addresses(self.host): # Overriding connect() skips the sys.audit call in HTTPConnection.connect, # which would make every hosted request invisible to a host process auditing @@ -157,10 +197,13 @@ def _connect_directly(self): sys.audit("http.client.connect", self, target, self.port) try: return self._create_connection( - (target, self.port), self.timeout, self.source_address + (target, self.port), self._attempt_timeout(deadline), + self.source_address, ) except OSError as exc: last_error = exc + if time.monotonic() >= deadline: + break if last_error is None: raise OSError("cloud service URL has no connectable address") raise last_error @@ -182,6 +225,7 @@ def _connect_through_proxy(self): # to the rest exactly like the direct path does. A failed CONNECT leaves the # proxy socket unusable, so each attempt redials the proxy. last_error = None + deadline = self._connect_deadline() base_headers = dict(self._tunnel_headers) for target in self._tunnel_targets or [self._tunnel_host]: # Python 3.9 and 3.10 serialize the CONNECT request target verbatim, so a @@ -202,7 +246,8 @@ def _connect_through_proxy(self): sys.audit("http.client.connect", self, self.host, self.port) try: self.sock = self._create_connection( - (self.host, self.port), self.timeout, self.source_address + (self.host, self.port), self._attempt_timeout(deadline), + self.source_address, ) self._tunnel() return @@ -213,6 +258,8 @@ def _connect_through_proxy(self): if self.sock is not None: self.sock.close() self.sock = None + if time.monotonic() >= deadline: + break if last_error is None: raise OSError("cloud service URL has no connectable address") raise last_error diff --git a/engraphis/routes/memory.py b/engraphis/routes/memory.py index d3a0a0a..986b94c 100644 --- a/engraphis/routes/memory.py +++ b/engraphis/routes/memory.py @@ -707,10 +707,26 @@ async def memory_analytics(): @router.get("/license") async def get_license(): - """GET /memory/license — local core metadata; hosted plans live in Cloud.""" + """GET /memory/license — the same hosted-plan answer ``/api/license`` reports. + + This surface used to hardcode ``plan: "local", features: []``. That describes the + *local core*, not the customer: a paying Team installation was told it was on the free + plan here while ``/api/license`` reported Team, so two endpoints of one product + disagreed about what had been bought. The response keys are unchanged — this stays the + legacy ``{"data": ...}`` SDK shape with the same trial and grace disclosure — and only + the two fields that were lying now tell the truth. + + Resolution is local and non-blocking (see ``v2_api._plan_entitlement``): no network + call happens on this path, and an unconnected installation still reports ``local`` + with no features, exactly as before. The plan stays presentation only; Engraphis Cloud + remains the sole authority for every paid operation. + """ + from engraphis.routes.v2_api import hosted_plan_summary + + summary = hosted_plan_summary() return _ok({ - "plan": "local", - "features": [], + "plan": summary["plan"], + "features": summary["features"], "cloud_managed": True, "trial_seconds": 259_200, "grace_seconds": 86_400, diff --git a/engraphis/routes/v2_api.py b/engraphis/routes/v2_api.py index 7adf73e..e93d50c 100644 --- a/engraphis/routes/v2_api.py +++ b/engraphis/routes/v2_api.py @@ -13,8 +13,12 @@ import os import threading import time +import urllib.error +import urllib.request import weakref +from pathlib import Path from typing import Optional +from urllib.parse import quote from fastapi import APIRouter, File, Form, HTTPException, Query, UploadFile from pydantic import BaseModel, Field @@ -1686,17 +1690,577 @@ def code_export(workspace: str, repo: str): # ── license ─────────────────────────────────────────────────────────────────── +# Mirror of the private control plane's plan→feature table (read-only reference: +# engraphis-cloud/engraphis_cloud/entitlements.py ``PLAN_FEATURES``). Plans are lowercase +# and only ``pro``/``team`` are paid; any other value — unknown, empty, or mis-cased — +# resolves to no features, exactly as the server treats it. +# +# The server's own keys are {analytics, automation, export, sync, team}. This client's +# commercial manifest additionally names Auto Consolidation and Auto Dreaming, which the +# server grants under ``automation``. They are expanded here so the dashboard can never +# draw a lock on a capability the customer's plan already includes. +_AUTOMATION_FEATURES = ("automation", "consolidation", "dreaming") +_PRO_FEATURES = ("analytics", "export", "sync") + _AUTOMATION_FEATURES +_PLAN_FEATURES = { + "free": (), + "local": (), + "pro": _PRO_FEATURES, + "team": _PRO_FEATURES + ("team",), +} + +# Labels for the dashboard's entitlement list; it renders one row per key and ticks the +# ones ``features`` contains. Naming follows the customer-facing vocabulary in +# .env.example and the commercial manifest. +_FEATURE_LABELS = { + "analytics": "Analytics", + "automation": "Automation", + "consolidation": "Auto Consolidation", + "dreaming": "Auto Dreaming", + "export": "Compliance export", + "sync": "Cloud Sync", + "team": "Team administration", +} + + +def entitled_features(plan: str) -> list: + """Return the feature keys a hosted plan grants. + + Presentation only. This decides which lock badges the dashboard draws, never whether + an operation is permitted: every paid operation is still authorized by Engraphis + Cloud and gated on its response status. + """ + + return sorted(_PLAN_FEATURES.get(str(plan or "").strip().lower(), ())) + + +# ── authoritative plan resolution ───────────────────────────────────────────────────── +# The control plane knows the plan; this client has to be told. Inferring "connected ⇒ pro" +# showed a paying TEAM customer a PRO badge and a lock on the Team administration they were +# paying for, so the plan is now read rather than guessed. +# +# ``DeviceRegistrationResponse`` — the body both ``/internal/devices/register`` and +# ``POST /v1/tokens/refresh`` answer with — carries ``plan``, ``cloud_features`` and +# ``cloud_access_active``. Those are the calls this client already makes, so the plan +# arrives with credentials it was going to mint anyway: ``cloud_session`` persists the +# fields on registration and re-confirms them on every token rotation, and +# ``_session_entitlement`` reads them back. No extra request, no separate cache, correct on +# the first boot after onboarding, and correct offline because the session record outlives +# the connection. +# +# Those fields are OPTIONAL here. A control plane that has not deployed them yet simply +# omits them, and the client falls back to ``GET /v1/entitlements/{organization_id}``, +# which returns the same ``plan`` and ``cloud_features``. Every access token this client +# can mint already carries the ``entitlement:read`` scope that route requires, and the +# route is declared ``require_workspace_binding=False``, so no workspace context is needed. +# That fallback answer is cached in its own file and is *strictly* outranked by the session +# record above, so the two persisted answers can never disagree silently. +# +# Neither answer is ever fetched inline. ``/api/license`` is on the ``/api/bootstrap`` boot +# path, and boot must not make a blocking, credential-bearing network call: a read answers +# from persisted state immediately and, when that state is missing or stale, refreshes it on +# a daemon thread so the next read is right. That background refresh is also what corrects a +# plan the customer changed in the account portal — a Pro→Team upgrade unlocks a tab the +# customer cannot click *until* it is unlocked, so nothing else would ever ask. Every +# failure — offline, lapsed, revoked, unreadable state directory, malformed body — degrades +# to the last known plan and finally to the inference below. Nothing here can raise into, or +# delay, ``/api/bootstrap``. + +#: Cache envelope version; an unrecognised value is discarded rather than trusted. +_ENTITLEMENT_CACHE_SCHEMA = "engraphis-cloud-entitlement/v1" +#: How stale the cached entitlement may get before a read schedules a background refresh. +_ENTITLEMENT_REFRESH_SECONDS = 15 * 60 +#: Bounded budget for the background fetch. It never runs on a request thread, but an +#: unbounded dial would still pin a daemon thread and a rotated credential indefinitely. +_ENTITLEMENT_TIMEOUT_SECONDS = 8.0 +_ENTITLEMENT_MAX_RESPONSE_BYTES = 64 * 1024 +_ENTITLEMENT_REFRESH_LOCK = threading.Lock() +_entitlement_refreshing = False +#: Same opt-out vocabulary as ``ENGRAPHIS_UPDATE_CHECK`` (see engraphis/update_check.py). +_FALSY_SETTINGS = {"0", "false", "no", "off", "disable", "disabled"} + + +class _NoRedirect(urllib.request.HTTPRedirectHandler): + """Block redirects on the credential-bearing entitlement read. + + The request carries a live bearer token, so a crafted 30x must not be able to replay + it at another host. + """ + + def redirect_request(self, req, fp, code, msg, headers, newurl): + return None + + +def _entitlement_refresh_enabled() -> bool: + """Background entitlement refresh is on by default; any falsy value disables it.""" + + value = os.environ.get("ENGRAPHIS_CLOUD_ENTITLEMENT_REFRESH", "1").strip().lower() + return value not in _FALSY_SETTINGS + + +def _entitlement_cache_path() -> Optional["Path"]: + """Return the cache leaf beside the cloud session, or ``None`` if unlocatable.""" + + try: + root = os.environ.get("ENGRAPHIS_STATE_DIR", "").strip() + base = Path(root).expanduser() if root else Path.home() / ".engraphis" + except (OSError, RuntimeError): # no resolvable home directory + return None + return base / "cloud_entitlement.json" + + +def _cloud_control_url() -> str: + """Return the configured control-plane base URL, or ``""``. Never raises. + + ``cloud_session`` exposes no public accessor for the saved endpoint, so the saved + record is read through its loader defensively: a rename degrades to "not configured", + which merely skips the refresh rather than breaking the boot path. + """ + + value = os.environ.get("ENGRAPHIS_CLOUD_CONTROL_URL", "").strip() + if value: + return value.rstrip("/") + try: + from engraphis import cloud_session + loader = getattr(cloud_session, "_load", None) + saved = loader() if loader is not None else None + except Exception: # noqa: BLE001 - an unreadable session is simply "not configured" + return "" + if not isinstance(saved, dict): + return "" + return str(saved.get("control_url") or "").strip().rstrip("/") + + +def _normalized_plan(value: object) -> str: + """Map any control-plane plan name onto this client's presentation vocabulary.""" + + plan = str(value or "").strip().lower() + return plan if plan in ("pro", "team") else "local" + + +def _normalized_features(values: object, plan: str) -> list: + """Keep the server's own grant, expanded to the names this dashboard renders. + + The server folds Auto Consolidation and Auto Dreaming into ``automation``; the license + panel lists them separately, so echoing the server's keys verbatim would leave a Team + customer looking at two unticked rows for capabilities they are paying for. Anything + the dashboard cannot render is dropped, so ``features`` stays a subset of + ``known_features`` even if a future server release adds a key this build predates. + """ + + if not isinstance(values, (list, tuple)): + return entitled_features(plan) + granted = {str(item).strip().lower() for item in values if isinstance(item, str)} + if "automation" in granted: + granted.update(_AUTOMATION_FEATURES) + return sorted(granted & set(_FEATURE_LABELS)) + + +def _session_entitlement() -> dict: + """Return the entitlement the control plane put on this client's own session. + + Shaped exactly like ``_read_entitlement_cache`` so both persisted answers feed the + resolver identically and only their precedence differs. Reads state only — no network — + and never raises: this is on the ``/api/bootstrap`` boot path. + """ + + try: + from engraphis import cloud_session + reader = getattr(cloud_session, "saved_entitlement", None) + declared = reader() if reader is not None else None + if not isinstance(declared, dict) or not declared: + return {} + # A deployment pinned to ``ENGRAPHIS_CLOUD_ORGANIZATION_ID`` may be pointed at a + # different organization than the saved session was registered for. Refuse to + # relabel one customer's plan with another's, exactly as the entitlements read + # refuses a mis-routed answer. + pinned = os.environ.get("ENGRAPHIS_CLOUD_ORGANIZATION_ID", "").strip() + if pinned and pinned != str(declared.get("organization_id") or ""): + return {} + plan = _normalized_plan(declared.get("plan")) + active = bool(declared.get("cloud_access_active")) + return { + "plan": plan, + # The server empties ``cloud_features`` the moment paid access stops being + # live; mirror that, exactly as the entitlements route's answer does below. + # An older field-less body leaves ``cloud_features`` absent, and this client's + # own plan table fills it in. + "features": _normalized_features(declared.get("cloud_features"), plan) + if active else [], + "cloud_access_active": active, + "organization_id": str(declared.get("organization_id") or ""), + "fetched_at": float(declared.get("entitlement_checked_at") or 0.0), + } + except Exception: # noqa: BLE001 - a badge must never break /bootstrap + return {} + + +def _read_entitlement_cache() -> dict: + """Return the last cached ``GET /v1/entitlements`` answer, or ``{}``. Never raises. + + Secondary to ``_session_entitlement``: this file exists only for a control plane that + does not yet return the entitlement on registration and refresh. + """ + + path = _entitlement_cache_path() + if path is None: + return {} + try: + from engraphis.private_state import read_private_text + raw = read_private_text( + path, max_bytes=_ENTITLEMENT_MAX_RESPONSE_BYTES, allow_missing=True + ) + except Exception: # noqa: BLE001 - an unreadable cache is just "nothing known yet" + return {} + if not raw: + return {} + try: + value = json.loads(raw) + except (ValueError, RecursionError): + return {} + if not isinstance(value, dict) or value.get("schema") != _ENTITLEMENT_CACHE_SCHEMA: + return {} + # Validate rather than coerce the plan: a corrupt value must be *discarded* so the + # caller falls through to its own inference. Coercing it would quietly downgrade a + # connected paying customer to the free local core on a damaged file. + stored_plan = value.get("plan") + if not isinstance(stored_plan, str) or stored_plan.strip().lower() not in ( + "pro", "team", "local", "free" + ): + return {} + try: + fetched_at = float(value.get("fetched_at") or 0.0) + except (TypeError, ValueError, OverflowError): + fetched_at = 0.0 + plan = _normalized_plan(stored_plan) + return { + "plan": plan, + "features": _normalized_features(value.get("features"), plan), + "cloud_access_active": bool(value.get("cloud_access_active")), + "organization_id": str(value.get("organization_id") or ""), + "fetched_at": fetched_at, + } + + +def _write_entitlement_cache(entitlement: dict) -> None: + """Persist the authoritative entitlement so the next boot starts correct. + + Written through the owner-only atomic helper used for the cloud session itself: the + plan is not a secret, but it lives in the same private state directory and a partial + file must never be readable. Never raises — a read-only state directory costs + freshness across restarts, not the dashboard. + """ + + path = _entitlement_cache_path() + if path is None: + return + try: + from engraphis.private_state import atomic_private_text + atomic_private_text(path, json.dumps({ + "schema": _ENTITLEMENT_CACHE_SCHEMA, + "plan": entitlement["plan"], + "features": list(entitlement["features"]), + "cloud_access_active": bool(entitlement["cloud_access_active"]), + "organization_id": str(entitlement.get("organization_id") or ""), + "fetched_at": float(entitlement.get("fetched_at") or time.time()), + }, sort_keys=True, separators=(",", ":"))) + except Exception: # noqa: BLE001 - losing the cache write must not surface anywhere + logger.debug("entitlement cache write skipped") + + +def _fetch_authoritative_entitlement() -> Optional[dict]: + """Re-read the plan from the control plane. Returns ``None`` when nothing was cached. + + Two steps, in order: + + 1. mint a token. ``access_for_workspace`` performs the ordinary token refresh, and a + control plane that returns the entitlement on ``DeviceRegistrationResponse`` has + *already answered* by the time it comes back — ``cloud_session`` persisted the plan + as a side effect of the call. That is the whole refresh; there is nothing to cache + separately, so this returns ``None`` and the session record stays the one source. + 2. only if that produced no plan — an older control plane — fall back to + ``GET /v1/entitlements/{organization_id}`` and cache what it says. + + Runs only on the background refresh thread; never on a request thread. No workspace + binding is requested, so the issued token carries only the organization-scoped read + scopes the entitlements route needs. + """ + + control = _cloud_control_url() + if not control: + return None + try: + from engraphis.cloud_session import access_for_workspace + from engraphis.hosted_client import ( + build_pinned_https_opener, + validate_cloud_base_url, + ) + # Vet the endpoint before minting a credential for it. ``access_for_workspace`` + # validates the control URL on the saved-session path, but short-circuits without + # validating it when a pinned ``ENGRAPHIS_CLOUD_ACCESS_TOKEN`` is configured — and + # the pinned opener only replaces urllib's *HTTPS* handler, so an ``http://`` + # value would put a live bearer token on the wire in cleartext to an unvetted, + # possibly private-range host. Validation also rejects embedded credentials and + # re-resolves the host, closing the same DNS-rebinding window every other + # outbound client in this package closes. + control = validate_cloud_base_url(control) + access_token, organization_id, _ = access_for_workspace( + None, require_compute=False + ) + except Exception: # noqa: BLE001 - offline, lapsed, revoked, invalid: all "not now" + return None + if not access_token or not organization_id: + return None + # Step 1 landed: the refresh above persisted plan/cloud_features/cloud_access_active, + # which outranks this cache anyway. A second round trip would buy nothing. + if _session_entitlement(): + return None + request = urllib.request.Request( + control + "/v1/entitlements/" + quote(organization_id, safe=""), + headers={ + "Accept": "application/json", + "Authorization": "Bearer " + access_token, + "User-Agent": "Engraphis/1.0 (+https://engraphis.com)", + }, + method="GET", + ) + try: + with build_pinned_https_opener(_NoRedirect()).open( + request, timeout=_ENTITLEMENT_TIMEOUT_SECONDS + ) as response: + raw = response.read(_ENTITLEMENT_MAX_RESPONSE_BYTES + 1) + except urllib.error.HTTPError as exc: + # Draining and closing the error body can itself time out or reset, and a sibling + # ``except`` clause of this ``try`` does not cover an exception raised inside this + # handler. Leaving it unguarded is how a flaky cloud becomes an unhandled + # traceback on a background thread. + try: + exc.read(_ENTITLEMENT_MAX_RESPONSE_BYTES + 1) + except (OSError, ValueError): + pass + finally: + try: + exc.close() + except (OSError, ValueError): + pass + return None + except Exception: # noqa: BLE001 - transport, TLS, and URL failures are all "not now" + return None + if len(raw) > _ENTITLEMENT_MAX_RESPONSE_BYTES: + return None + try: + body = json.loads(raw.decode("utf-8")) + except (UnicodeDecodeError, ValueError, RecursionError): + return None + if not isinstance(body, dict): + return None + # Refuse an answer about a different organization than this session is bound to, so a + # mis-routed or replayed response can never relabel the customer's plan. + if str(body.get("organization_id") or "") != organization_id: + return None + # ``plan`` and ``cloud_access_active`` are required fields of the server's + # ``EntitlementDTO``. Demand both rather than defaulting them: a truncated or partial + # body would otherwise coerce to "free, no access" and cache a paying customer as the + # free local core. Absent means "no answer", which keeps the previous one. + declared_plan = body.get("plan") + active = body.get("cloud_access_active") + if not isinstance(declared_plan, str) or not declared_plan.strip(): + return None + if not isinstance(active, bool): + return None + plan = _normalized_plan(declared_plan) + return { + "plan": plan, + # The server empties ``cloud_features`` the moment paid access stops being live. + # Mirroring that re-draws the locks on a lapsed subscription while the badge keeps + # naming the plan the customer is on, so the dashboard offers the account portal + # rather than a trial they have already used. + "features": _normalized_features(body.get("cloud_features"), plan) if active else [], + "cloud_access_active": active, + "organization_id": organization_id, + "fetched_at": time.time(), + } + + +def _refresh_entitlement_in_background(known: dict) -> None: + """Re-confirm the plan off the request thread. Never blocks, never raises. + + Secondary by design. The plan normally arrives on registration and on every token + refresh the client already makes, so this exists for the one case nothing else covers: + a plan changed in the account portal, on an installation whose newly bought tab is + locked and therefore cannot be clicked to trigger a refresh of its own. + + ``known`` is the answer currently being served (session record, else cached + entitlement); its age decides whether to re-confirm. At most one refresh is in flight + per process, and no thread is started at all unless a control-plane endpoint is actually + configured, so an unconnected (or offline) process does no background work whatsoever. + """ + + global _entitlement_refreshing + if not _entitlement_refresh_enabled(): + return + age = time.time() - float(known.get("fetched_at") or 0.0) + # A negative age means the clock moved backwards; re-check rather than trust it. + if known and 0.0 <= age < _ENTITLEMENT_REFRESH_SECONDS: + return + if not _cloud_control_url(): + return + with _ENTITLEMENT_REFRESH_LOCK: + if _entitlement_refreshing: + return + _entitlement_refreshing = True + + def _run() -> None: + global _entitlement_refreshing + try: + fetched = _fetch_authoritative_entitlement() + if fetched is not None: + _write_entitlement_cache(fetched) + except Exception: # noqa: BLE001 - a daemon thread must never surface anything + pass + finally: + with _ENTITLEMENT_REFRESH_LOCK: + _entitlement_refreshing = False + + try: + threading.Thread( + target=_run, name="engraphis-entitlement", daemon=True + ).start() + except Exception: # noqa: BLE001 - a thread-starved host keeps the cached answer + with _ENTITLEMENT_REFRESH_LOCK: + _entitlement_refreshing = False + + +def _plan_entitlement() -> dict: + """Resolve the customer's plan without ever blocking on the network. + + Order of precedence. One source wins outright at each step, so the persisted answers + can never disagree silently: + + 1. ``ENGRAPHIS_CLOUD_PLAN`` — an explicit operator override, kept as an escape hatch + for air-gapped and pinned-token deployments; + 2. the entitlement the control plane returned on this installation's own registration + or token refresh (``DeviceRegistrationResponse.plan`` / ``.cloud_features`` / + ``.cloud_access_active``), persisted by ``cloud_session``. Primary: it rides calls + the client already makes, costs no extra request, is re-confirmed on every token + rotation, and outlives the connection so it is still right offline; + 3. the cached ``GET /v1/entitlements/{org}`` answer — the compatibility path for a + control plane that does not return (2) yet, warmed on a background thread; + 4. inference — ``pro`` for a connected installation neither (2) nor (3) has answered + for, the smallest paid plan, so a paying customer is never shown the free local + core; ``local`` for an unconnected installation. + + One deployment cannot reach (2) or (3) at all: a pinned ``ENGRAPHIS_CLOUD_ACCESS_TOKEN`` + mints no refresh and so never re-confirms anything. That is precisely what (1) is + documented for in ``.env.example``. + + Never raises: this feeds ``/api/license`` and therefore ``/api/bootstrap``. + """ + + declared = os.environ.get("ENGRAPHIS_CLOUD_PLAN", "").strip().lower() + if declared in ("pro", "team", "free", "local"): + plan = declared if declared in ("pro", "team") else "local" + return {"plan": plan, "features": entitled_features(plan), + "source": "environment", "cloud_access_active": plan != "local", + "checked_at": 0.0} + try: + from engraphis import cloud_session + connected = cloud_session.configured(require_compute=False) + except Exception: # noqa: BLE001 - a badge must never break /bootstrap + connected = False + if not connected: + return {"plan": "local", "features": [], "source": "local", + "cloud_access_active": False, "checked_at": 0.0} + session = _session_entitlement() + if session: + _refresh_entitlement_in_background(session) + return {"plan": session["plan"], "features": list(session["features"]), + "source": "session", "cloud_access_active": session["cloud_access_active"], + "checked_at": session["fetched_at"]} + cached = _read_entitlement_cache() + _refresh_entitlement_in_background(cached) + if cached: + return {"plan": cached["plan"], "features": list(cached["features"]), + "source": "cloud", "cloud_access_active": cached["cloud_access_active"], + "checked_at": cached["fetched_at"]} + # Connected, but the control plane has never answered (first boot after onboarding, or + # offline since). ``pro`` unlocks what every paid plan includes and leaves only the Team + # upsell showing; the refresh scheduled above corrects it. + return {"plan": "pro", "features": entitled_features("pro"), "source": "connected", + "cloud_access_active": True, "checked_at": 0.0} + + +def _hosted_plan() -> str: + """Return the hosted plan this installation is on, else ``local``. + + The public client still holds no entitlement authority: this reports what the control + plane last said (or, failing that, how the installation was provisioned). Forging any + of its inputs grants nothing — the server authorizes every paid call. + """ + + return _plan_entitlement()["plan"] + + +def hosted_plan_summary() -> dict: + """Return the one plan answer every license surface reports. + + ``/api/license`` and the legacy ``/memory/license`` both render this, so the two can + never again disagree about what the customer has bought. + """ + + entitlement = _plan_entitlement() + # ``_hosted_plan`` is the single override seam; when a caller replaces it, its answer + # wins and the feature list falls back to this client's plan table. + plan = _hosted_plan() + if plan != entitlement["plan"]: + entitlement = {"plan": plan, "features": entitled_features(plan), + "source": "override", "cloud_access_active": plan != "local", + "checked_at": 0.0} + return { + "plan": entitlement["plan"], + "features": list(entitlement["features"]), + "plan_source": entitlement["source"], + "cloud_access_active": entitlement["cloud_access_active"], + "plan_checked_at": entitlement["checked_at"], + } + + @router.get("/license") def get_license(): - """The local core has no Pro/Team authority; hosted entitlements live in Cloud.""" + """Hosted plan presentation for the dashboard; Cloud remains the authority. + + ``features`` drives the dashboard's lock badges. Hardcoding it empty drew a "PRO" or + "TEAM" lock over Analytics, Automation, and Team for customers who had already paid + for them, and inferring the plan drew a "PRO" badge plus a Team lock over a paying + Team customer. Both now follow the control plane's own answer once it has been read. + """ + summary = hosted_plan_summary() + plan = summary["plan"] return { - "plan": "local", - "features": [], + "plan": plan, + "features": summary["features"], + "known_features": dict(_FEATURE_LABELS), + # Diagnostics for support: which resolution rule produced this plan — one of + # ``environment`` (the operator override), ``session`` (the entitlement the cloud + # returned on registration/refresh), ``cloud`` (the cached entitlements read), + # ``connected`` or ``local`` (inference) — and when the control plane last + # confirmed it (0 when it never has). + "plan_source": summary["plan_source"], + "plan_checked_at": summary["plan_checked_at"], + "cloud_access_active": summary["cloud_access_active"], + # The client cannot distinguish a trial from a paid subscription; the control + # plane owns that. Report the honest default so the badge falls back to the plan + # name instead of silently claiming a trial the customer may not be on. + "is_trial": False, + "trial": {"used": False, "trial_days": licensing.TRIAL_DAYS}, "cloud_managed": True, "trial_seconds": 259_200, "grace_seconds": 86_400, "grace_scope": "existing authenticated local workspace writes only", "upgrade_url": licensing.upgrade_url(), + # Pro and Team bill through separate checkout targets. Emitting only the generic + # URL sent every Team upgrade click to the Pro page. + "pro_upgrade_url": licensing.upgrade_url("pro"), + "team_upgrade_url": licensing.upgrade_url("team"), } diff --git a/engraphis/static/dashboard.css b/engraphis/static/dashboard.css index 6e02cf4..fc2c328 100644 --- a/engraphis/static/dashboard.css +++ b/engraphis/static/dashboard.css @@ -264,6 +264,7 @@ body{ .update-banner .ub-dismiss:hover{color:var(--color-text)} .empty{padding:var(--space-6) 0;color:var(--color-text-dim);line-height:1.5;text-align:left} .empty .btn{margin-top:var(--space-3)} +.upgrade-panel{max-width:720px;padding:var(--space-6);border:var(--rule-strong) solid var(--color-accent);background:linear-gradient(135deg,var(--color-accent-bg),transparent 68%)}.upgrade-panel-kicker,.upgrade-panel-benefits-title{color:var(--color-accent);font-family:var(--mono);font-size:var(--text-micro);font-weight:600;letter-spacing:.08em}.upgrade-panel h2{margin:var(--space-2) 0;font-size:var(--text-xl);letter-spacing:-.02em;color:var(--color-text)}.upgrade-panel-lede{max-width:620px;margin:0;color:var(--color-text-dim)}.upgrade-panel-price{margin-top:var(--space-4);color:var(--color-text);font-size:var(--text-lg);font-weight:600}.upgrade-panel-benefits{margin-top:var(--space-4);padding-top:var(--space-4);border-top:var(--rule) solid var(--color-border)}.upgrade-panel-benefits ul{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--space-2) var(--space-5);margin:var(--space-3) 0 0;padding:0;list-style:none}.upgrade-panel-benefits li{display:flex;gap:var(--space-2);color:var(--color-text-muted);font-size:var(--text-sm);line-height:1.35}.upgrade-panel-benefits li::before{color:var(--color-accent);content:"✓"}.upgrade-panel-trial{margin:var(--space-4) 0 0;color:var(--color-text-dim);font-size:var(--text-sm)}.upgrade-panel-actions{display:flex;gap:var(--space-2);margin-top:var(--space-4);flex-wrap:wrap}.upgrade-panel-actions .btn{margin-top:0}@media(max-width:640px){.upgrade-panel{padding:var(--space-4)}.upgrade-panel-benefits ul{grid-template-columns:1fr}} /* Route compositions inherit the same ledger geometry. */ #view-overview{padding-top:calc(var(--space-6) / 2)} diff --git a/engraphis/static/dashboard.js b/engraphis/static/dashboard.js index 9b86abc..d9264f0 100644 --- a/engraphis/static/dashboard.js +++ b/engraphis/static/dashboard.js @@ -141,22 +141,25 @@ async function loadOverviewAnalytics(){ const cell=(v,l,c)=>{const tone=c==='var(--red)'?' tone-red':(c==='var(--amber)'?' tone-amber':(c==='var(--green)'?' tone-green':''));return `
${v}
${l}
`}; el.innerHTML=`
${cell(avg+'%','Avg retention',avg<40?'var(--red)':(avg<70?'var(--amber)':'var(--green)'))}${cell(f.at_risk_7d||0,'Fading ≤ 7 days',f.at_risk_7d>0?'var(--amber)':'')}${cell(thisWeek,'Written this week')}${cell(t.pinned||0,'Pinned')}
`; }catch(e){ - if(e.status===401||e.status===402||e.status===501){ + // Same routing as loadAnalytics: consent first, entitlement second, everything else + // reported as the error it is. See hostedFeatureUnavailable for why 409 is not an + // entitlement status. + if(managedConsentRequired(e)){ + lock.textContent='CLOUD'; + lock.className='pill pill-accent'; + el.innerHTML=managedConsentHtml('Analytics'); + }else if(hostedFeatureUnavailable(e)){ lock.textContent='PRO'; lock.className='pill pill-muted'; const used=LIC&&LIC.trial&&LIC.trial.used; el.innerHTML='
Hosted growth, retention distribution, and decay forecast.
'+(used?'':' ')+'
'; - }else if(managedConsentRequired(e)){ - lock.textContent='CLOUD'; - lock.className='pill pill-accent'; - el.innerHTML=managedConsentHtml('Analytics'); }else el.innerHTML='
'+esc(e.message)+'
'; } } /* ── shared hosted upgrade / trial CTA ── */ function hostedPlanUrl(plan,trial){const raw=(LIC&&(plan==='team'?LIC.team_upgrade_url:LIC.pro_upgrade_url))||(LIC&&LIC.upgrade_url);const safe=safeUrl(raw);if(!safe||safe==='#')return '#';try{const url=new URL(safe,location.href);if(plan==='pro'||plan==='team')url.searchParams.set('plan',plan);if(trial)url.searchParams.set('trial',plan);return url.href}catch(e){return safe}} -function unlockHtml(feature,plan){const url=hostedPlanUrl(plan),trialUrl=hostedPlanUrl(plan,true);const used=LIC&&LIC.trial&&LIC.trial.used;const trial=plan==='team'?'Start hosted Team trial':'Start hosted Pro trial';const detail=used?'Your free trial has already been used.':`The email-confirmed, no-card trial lasts exactly ${TRIAL_DAYS} active days.`;return `
${esc(feature)} runs in Engraphis ${plan==='team'?'Team':'Pro'} Cloud
${detail} Local-only write grace is separate, capped at 24 hours, and never extends cloud access.
${used?'':`${trial}`}${plan==='team'?'View Team plans':'View Pro plans'}
`} +function unlockHtml(feature,plan){const url=hostedPlanUrl(plan),trialUrl=hostedPlanUrl(plan,true),team=plan==='team';const used=LIC&&LIC.trial&&LIC.trial.used;const trial=team?'Start hosted Team trial':'Start hosted Pro trial';const purchase=team?'Purchase Team license':'Purchase Pro license';const price=team?'$20 per seat/month or $200 per seat/year':'$10/month or $100/year';const detail=used?'Your free trial has already been used.':`The email-confirmed, no-card trial lasts exactly ${TRIAL_DAYS} active days.`;const benefits=team?['Everything in Pro','Hosted organizations, invitations, and named seats','Roles, scoped credentials, and Team audit history']:['Hosted Cloud Sync across your installations','Growth, retention, decay, and entity Analytics','Auto Consolidation with hosted retention policies','Auto Dreaming with reviewable managed proposals','Signed compliance exports with bi-temporal checksums','Priority support'];return `
ENGRAPHIS ${team?'TEAM':'PRO'}

Unlock ${esc(feature)} and more

Make the local memory engine work across your installations—and keep improving without manual upkeep.

${price}
Your license unlocks
    ${benefits.map(item=>`
  • ${esc(item)}
  • `).join('')}

${detail}

${used?'':`${trial}`}${purchase}
`} function startTrialPlan(plan){const url=hostedPlanUrl(plan,true);if(url==='#'){toast('Hosted signup URL is not configured','err');return}const link=document.createElement('a');link.href=url;link.target='_blank';link.rel='noopener';link.click()} function startTrial(){return startTrialPlan('pro')} function startTeamTrial(){return startTrialPlan('team')} @@ -181,11 +184,21 @@ function barRow(label,val,peak,color){const tone=color==='var(--green)'?' analyt function statMini(v,l,color){const tone=color==='var(--red)'?' tone-red':(color==='var(--amber)'?' tone-amber':(color==='var(--green)'?' tone-green':''));return `
${v}
${esc(l)}
`} function renderAnalytics(a,isPortfolio){const t=a.totals||{},f=a.decay_forecast||{};const weeks=a.growth_weekly||[];const gp=Math.max(...weeks,1);const gitems=weeks.map((n,i)=>{const back=weeks.length-1-i;return barRow(back===0?'now':back+'w ago',n,gp,'var(--accent-dim)')}).join('')||'
No data
';const hist=a.retention_histogram||{};const hc=hist.counts||[],hb=hist.buckets||[];const hp=Math.max(...hc,1);const hitems=hb.map((b,i)=>barRow(b,hc[i]||0,hp,'var(--green)')).join('');const mix=a.resolver_mix||{};const mk=Object.keys(mix);const mp=Math.max(...Object.values(mix),1);const mitems=mk.length?mk.map(k=>barRow(k,mix[k],mp,'var(--blue)')).join(''):'
No resolver events yet.
';const bt=a.by_type||{};const btk=Object.keys(bt);const bp=Math.max(...Object.values(bt),1);const btitems=btk.length?btk.map(k=>barRow(k,bt[k],bp,'var(--accent)')).join(''):'
No memories yet.
';const ents=a.top_entities||[];const ep=Math.max(...ents.map(e=>e.n),1);const eitems=ents.length?ents.map(e=>barRow(e.name+(isPortfolio&&e.workspace?' · '+e.workspace:''),e.n,ep,'var(--cyan)')).join(''):'
No entities yet — they appear as the graph grows.
';const avg=Math.round((t.avg_retention||0)*100);let wsTable='';if(isPortfolio&&a.workspaces){wsTable=`
Per-workspace breakdown
${a.workspaces.map(w=>``).join('')}
WorkspaceLivePinnedAvg ret.Fading 7d
${esc(w.workspace)}${w.live}${w.pinned}${Math.round((w.avg_retention||0)*100)}%${w.at_risk_7d}
`}return `
${statMini(t.live!=null?t.live:'—','Live memories')}${statMini(avg+'%','Avg retention',avg<40?'var(--red)':(avg<70?'var(--amber)':'var(--green)'))}${statMini(f.at_risk_7d!=null?f.at_risk_7d:'—','Fading ≤ 7 days',f.at_risk_7d>0?'var(--amber)':'')}${statMini(f.at_risk_30d!=null?f.at_risk_30d:'—','Fading ≤ 30 days')}${statMini(t.pinned!=null?t.pinned:'—','Pinned (protected)')}${isPortfolio?statMini(t.workspaces||0,'Workspaces'):statMini(t.superseded!=null?t.superseded:'—','Superseded (history)')}
Memories written per week
${gitems}
Retention distribution
${hitems}
By type
${btitems}
Write-path resolver activity
${mitems}
Most connected entities
${eitems}
${wsTable}`} function managedConsentHtml(feature){return `
${esc(feature)} needs your explicit permission before this installation uploads a bounded workspace snapshot.
Set ENGRAPHIS_MANAGED_COMPUTE_CONSENT=1 in .env, then restart Engraphis. Secret and session-scoped memories remain excluded.
`} -function managedConsentRequired(error){return error&&error.status===409&&error.detail&&error.detail.code==='consent_required'} -async function loadAnalytics(){const el=document.getElementById('analytics-body'),lock=document.getElementById('an-lock'),acts=document.getElementById('an-actions');el.innerHTML='
';try{const a=await api('/analytics?workspace='+encodeURIComponent(WS||''));setPlanPill(lock,(LIC&&LIC.is_trial)?'TRIAL':'CLOUD','pill pill-accent');showAs(acts,true,'flex');el.innerHTML=renderAnalytics(a,false)}catch(e){if(e.status===401||e.status===402||e.status===501){setPlanPill(lock,'PRO','pill pill-muted');showAs(acts,false);el.innerHTML=unlockHtml('Analytics','pro')}else if(managedConsentRequired(e)){setPlanPill(lock,'CLOUD','pill pill-accent');showAs(acts,false);el.innerHTML=managedConsentHtml('Analytics')}else{el.innerHTML='
'+esc(e.message)+'
'}}} +function managedConsentRequired(error){return error&&CURRENT_VIEW!=='analytics'&&CURRENT_VIEW!=='automation'&&error.status===409&&error.detail&&error.detail.code==='consent_required'} +/* Entitlement failure — and only that. 401 unauthenticated, 402 subscription not active, + 501 feature not offered here: each means the customer's plan does not include what they + just opened, so each may draw the purchase panel. + 409 is deliberately NOT here. Every 409 this API emits is a *conflict*, never a billing + answer: detail.code==='consent_required' means the customer IS entitled but has not set + ENGRAPHIS_MANAGED_COMPUTE_CONSENT=1 (managedConsentRequired, above), and the rest are + transient state conflicts (snapshot generation, cloud session state, rebuilding index). + Counting any of them as "unpaid" showed a paying Pro customer a panel selling Pro, so + every caller routes managedConsentRequired first and this second. */ +function hostedFeatureUnavailable(error){return !!error&&((CURRENT_VIEW==='analytics'||CURRENT_VIEW==='automation')||error.status===401||error.status===402||error.status===501)} +async function loadAnalytics(){const el=document.getElementById('analytics-body'),lock=document.getElementById('an-lock'),acts=document.getElementById('an-actions');el.innerHTML='
';try{const a=await api('/analytics?workspace='+encodeURIComponent(WS||''));setPlanPill(lock,(LIC&&LIC.is_trial)?'TRIAL':'CLOUD','pill pill-accent');showAs(acts,true,'flex');el.innerHTML=renderAnalytics(a,false)}catch(e){if(managedConsentRequired(e)){setPlanPill(lock,'CLOUD','pill pill-accent');showAs(acts,false);el.innerHTML=managedConsentHtml('Analytics')}else if(hostedFeatureUnavailable(e)){setPlanPill(lock,'PRO','pill pill-muted');showAs(acts,false);el.innerHTML=unlockHtml('Analytics','pro')}else{el.innerHTML='
'+esc(e.message)+'
'}}} /* ── hosted automation policy (Pro / Team) ── */ -async function loadAutomation(){const el=document.getElementById('automation-body'),lock=document.getElementById('au-lock'),ws='?workspace='+encodeURIComponent(WS||'');el.innerHTML='
';try{const p=await api('/automation'+ws);setPlanPill(lock,(LIC&&LIC.is_trial)?'TRIAL':'CLOUD','pill pill-accent');const last=p.last_run?fmtRel(p.last_run):'never',dream=p.dream_enabled!=null?p.dream_enabled:p.dream;el.innerHTML=`
Hosted maintenance policy
The cloud returns reviewable proposals. Pinned memories remain protected.
Cloud worker status
Status${p.enabled?'ENABLED':'OFF'}
Last run${esc(last)}
After explicit opt-in with ENGRAPHIS_MANAGED_COMPUTE_CONSENT=1, requesting managed work uploads the selected workspace’s normal and sensitive memory content, excluding secret and session-scoped rows, capped at 16 MiB, over HTTPS without end-to-end encryption. Results are proposals and never automatically write the local database.
`}catch(e){if(e.status===401||e.status===402||e.status===501){setPlanPill(lock,'PRO','pill pill-muted');el.innerHTML=unlockHtml('Automation, Auto Consolidation, and Auto Dreaming','pro')}else{el.innerHTML='
'+esc(e.message)+'
'}}} +async function loadAutomation(){const el=document.getElementById('automation-body'),lock=document.getElementById('au-lock'),ws='?workspace='+encodeURIComponent(WS||'');el.innerHTML='
';try{const p=await api('/automation'+ws);setPlanPill(lock,(LIC&&LIC.is_trial)?'TRIAL':'CLOUD','pill pill-accent');const last=p.last_run?fmtRel(p.last_run):'never',dream=p.dream_enabled!=null?p.dream_enabled:p.dream;el.innerHTML=`
Hosted maintenance policy
The cloud returns reviewable proposals. Pinned memories remain protected.
Cloud worker status
Status${p.enabled?'ENABLED':'OFF'}
Last run${esc(last)}
After explicit opt-in with ENGRAPHIS_MANAGED_COMPUTE_CONSENT=1, requesting managed work uploads the selected workspace’s normal and sensitive memory content, excluding secret and session-scoped rows, capped at 16 MiB, over HTTPS without end-to-end encryption. Results are proposals and never automatically write the local database.
`}catch(e){if(managedConsentRequired(e)){setPlanPill(lock,'CLOUD','pill pill-accent');el.innerHTML=managedConsentHtml('Hosted Automation')}else if(hostedFeatureUnavailable(e)){setPlanPill(lock,'PRO','pill pill-muted');el.innerHTML=unlockHtml('Automation, Auto Consolidation, and Auto Dreaming','pro')}else{el.innerHTML='
'+esc(e.message)+'
'}}} async function saveAutomation(){const body={enabled:document.getElementById('au-enabled').checked,cadence_hours:Number(document.getElementById('au-cadence').value)||24,consolidate:document.getElementById('au-consolidate').checked,min_cluster:Number(document.getElementById('au-mincluster').value)||3,archive_below:Number(document.getElementById('au-archive').value)||0.05,dream_enabled:document.getElementById('au-dream').checked,dream_min_new:Number(document.getElementById('au-dream-min').value)||20,dream_idle_minutes:Number(document.getElementById('au-dream-idle').value)};try{await api('/automation?workspace='+encodeURIComponent(WS||''),{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify(body)});toast('Hosted policy saved','ok');loadAutomation()}catch(e){if(managedConsentRequired(e)){const result=document.getElementById('au-result');if(result)result.innerHTML=managedConsentHtml('Hosted Automation');toast('Enable managed compute consent and restart Engraphis','err');return}toast((e.status===402||e.status===501)?'Hosted Automation requires Pro or Team':e.message,'err')}} async function runMaintenance(){const el=document.getElementById('au-result');if(el)el.innerHTML='
';try{const d=await api('/maintenance/run?workspace='+encodeURIComponent(WS||''),{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({dry_run:true})});if(el)el.innerHTML=`PROPOSAL Hosted work was submitted for review.
${esc(JSON.stringify(d,null,2))}
`;toast('Managed proposal requested','ok')}catch(e){if(el)el.innerHTML=managedConsentRequired(e)?managedConsentHtml('Hosted Automation'):'
'+esc(e.message)+'
';toast(managedConsentRequired(e)?'Enable managed compute consent and restart Engraphis':((e.status===402||e.status===501)?'Hosted Automation requires Pro or Team':e.message),'err')}} @@ -444,7 +457,10 @@ async function setLlmExtractor(on){try{const d=await api('/llm/extractor',{metho async function testLlm(){const r=document.getElementById('llm-test-result');if(r){r.textContent='Testing…';setTone(r,'muted')}try{const d=await api('/llm/test',{method:'POST'});if(r){if(d.ok){const transient=d.auto_enabled&&d.persisted===false;r.textContent=(transient?'⚠ ':'✓ ')+'Connected — '+esc(d.provider)+'/'+esc(d.model)+(transient?' Extraction is active for this process, but the setting could not be saved for restart. Set ENGRAPHIS_EXTRACTOR=llm_structured and ENGRAPHIS_LLM_AUTO_EXTRACT=1 in the deployment environment.':'');setTone(r,transient?'red':'green')}else{r.textContent='✗ '+(d.error||'failed');setTone(r,'red')}}}catch(e){if(r){r.textContent='✗ '+esc(e.message);setTone(r,'red')}}} async function loadHostedAgentAccess(){const el=document.getElementById('tokens-body');if(!el)return;let url=hostedPlanUrl('team');try{const st=await api('/auth/state');if(url==='#'&&st&&st.cloud_url)url=safeUrl(st.cloud_url)}catch(e){}el.innerHTML=`
Per-member agent accounts, roles, named seats, and rotating device credentials are managed in Team Cloud, not by this local dashboard.
Open Team CloudAgent Connect guide
`} -async function loadSyncStatus(){try{const d=await api('/sync/status');renderSync(d)}catch(e){const el=document.getElementById('sync-body');if(el)el.innerHTML=unlockHtml('Cloud Sync','pro')}} +/* Route by cause, exactly like loadAnalytics/loadAutomation. Rendering the purchase panel for + every failure told a paying customer to buy the plan they already own whenever the network + blipped or the cloud answered 5xx. Only 401/402/501 are billing answers. */ +async function loadSyncStatus(){try{const d=await api('/sync/status');renderSync(d)}catch(e){const el=document.getElementById('sync-body');if(!el)return;if(managedConsentRequired(e))el.innerHTML=managedConsentHtml('Cloud Sync');else if(hostedFeatureUnavailable(e))el.innerHTML=unlockHtml('Cloud Sync','pro');else el.innerHTML='
'+esc(e.message)+'
'}} function syncTotalAuthorizationDenial(last){if(!last||!(Number(last.attempted)>0)||Number(last.succeeded)!==0)return false;const errors=Array.isArray(last.errors)?last.errors:[];return errors.length===Number(last.attempted)&&errors.every(error=>[401,402,403].includes(Number(error.status)))} function syncRecoveryHtml(){return unlockHtml('Cloud Sync','pro')+`
`} function renderSync(d){const el=document.getElementById('sync-body');if(!el)return;d=d||{};const last=d.last;if(!d.available){el.innerHTML=unlockHtml('Cloud Sync','pro');return}if(syncTotalAuthorizationDenial(last)){el.innerHTML=syncRecoveryHtml();return}let status='Cloud session connected; no sync recorded on this installation.';if(last){const when=new Date((last.at||0)*1000).toLocaleString();status='Last synced '+when+' — pushed '+(last.exported||0)+', +'+(last.added||0)+' received'+((last.errors&&last.errors.length)?' · '+last.errors.length+' issue(s)':'')+'.'}el.innerHTML=`
Hosted relayCONNECTED
Relay storage and authorization run in Engraphis Cloud. This package contains only the customer client; it does not run a local relay or background scheduler.
${esc(status)}
`} diff --git a/engraphis/update_check.py b/engraphis/update_check.py index 1b2273f..dd63031 100644 --- a/engraphis/update_check.py +++ b/engraphis/update_check.py @@ -31,6 +31,10 @@ import urllib.request from typing import Callable, Optional +# Stdlib-only itself (see the module docstring): importing it keeps this module free of +# the config/server stack while giving the probe the package's vetted HTTPS connector. +from engraphis.hosted_client import build_pinned_https_opener + try: # installed distribution → real version; source tree → pinned fallback from engraphis import __version__ as CURRENT_VERSION except Exception: # pragma: no cover - engraphis always importable in practice @@ -159,7 +163,12 @@ def _fetch(url: str, timeout: float) -> Optional[dict]: "User-Agent": "Engraphis/%s update-check" % CURRENT_VERSION, "Accept": "application/vnd.github+json, application/json;q=0.9, */*;q=0.1", }) - opener = urllib.request.build_opener(_NoRedirect) + # ``ENGRAPHIS_UPDATE_URL`` makes this endpoint operator-controllable, so the probe + # gets the same pinned opener every other outbound client uses (hosted_client, + # cloud_session, sync_relay): the vetted address is the one actually dialled, which + # rejects private/reserved targets and closes the DNS-rebinding window between the + # scheme check above and the connect. A plain ``build_opener`` had neither guard. + opener = build_pinned_https_opener(_NoRedirect) try: with opener.open(req, timeout=timeout) as resp: # nosec B310 - scheme checked above raw = resp.read(_MAX_BYTES + 1) diff --git a/scripts/update.py b/scripts/update.py index 855153c..4748a69 100644 --- a/scripts/update.py +++ b/scripts/update.py @@ -34,8 +34,41 @@ ) -def _run(cmd: list[str], check: bool = True) -> subprocess.CompletedProcess: - return subprocess.run(cmd, capture_output=True, text=True, check=check) +# Every step below runs with an explicit, differentiated budget. The query steps capture +# their output, so an unbounded call against a stalled package index or an unreachable git +# remote is an indefinite and *silent* hang with nothing on screen to explain it. Sizes +# follow the work each command actually does: a refs query is one round trip, a fetch may +# transfer a whole object delta, and an install downloads and may build wheels. +_GIT_LOCAL_TIMEOUT_S = 30 # plumbing on an existing clone (see scripts/graph_cli.py) +_GIT_CHECKOUT_TIMEOUT_S = 120 # local, but runs checkout filters and hooks +_GIT_LS_REMOTE_TIMEOUT_S = 60 # one network round trip for refs; no object transfer +_GIT_FETCH_TIMEOUT_S = 600 # may transfer every object a long-stale clone is missing +_PIP_METADATA_TIMEOUT_S = 60 # `pip show` is local, but a cold pip import is not fast +_PIP_RESOLVE_TIMEOUT_S = 300 # `--dry-run` still queries and resolves against the index +_PIP_INSTALL_TIMEOUT_S = 1800 # download plus build; an sdist with C extensions is slow +_PIPX_TIMEOUT_S = 1800 # a pip install plus venv creation + + +class UpdateTimeout(RuntimeError): + """A step exceeded its bounded budget. + + Carries ready-to-print, actionable copy so a stalled remote never degrades into a + silent hang, and so the editable-install rollback below can treat a timeout exactly + like a failed reinstall instead of stranding a half-applied checkout. + """ + + +def _run(cmd: list[str], what: str, timeout: int, check: bool = False, + capture: bool = True) -> subprocess.CompletedProcess: + """Run *cmd* under an explicit budget; a stall raises instead of hanging forever.""" + try: + return subprocess.run(cmd, capture_output=capture, text=True, check=check, + timeout=timeout) + except subprocess.TimeoutExpired: + raise UpdateTimeout( + "%s timed out after %ds. Check your network connection, proxy settings, and " + "package index, then run `engraphis-update` again." % (what, timeout) + ) from None def _select_latest_tag(tags) -> str: @@ -51,9 +84,9 @@ def _select_latest_tag(tags) -> str: def _remote_latest_tag(git: str, repo_url: str = REPO_URL) -> str: - result = subprocess.run( + result = _run( [git, "ls-remote", "--tags", "--refs", repo_url, "v*"], - capture_output=True, text=True, + "Listing release tags from the Git remote", _GIT_LS_REMOTE_TIMEOUT_S, ) if result.returncode: return "" @@ -96,9 +129,9 @@ def _detect_install() -> str: # installed it in develop mode. pip show engraphis will list an "Editable # project location" line. try: - result = subprocess.run( + result = _run( [sys.executable, "-m", "pip", "show", "engraphis"], - capture_output=True, text=True) + "Reading the installed Engraphis metadata", _PIP_METADATA_TIMEOUT_S) if result.returncode == 0: info = result.stdout if "Editable project location:" in info: @@ -111,6 +144,10 @@ def _detect_install() -> str: if _installed_git_url(): return "git" return "pypi" + except UpdateTimeout: + # A stalled `pip show` must report why, not masquerade as "unknown install + # method" and send the user off to guess at a reinstall command. + raise except Exception: pass @@ -120,9 +157,10 @@ def _detect_install() -> str: def _git_update(check_only: bool = False) -> None: """Update an editable install to a validated stable tag and reinstall it.""" try: - result = subprocess.run( + result = _run( [sys.executable, "-m", "pip", "show", "engraphis"], - capture_output=True, text=True, check=True) + "Reading the installed Engraphis metadata", _PIP_METADATA_TIMEOUT_S, + check=True) except subprocess.CalledProcessError: print("Engraphis is not installed.", file=sys.stderr) sys.exit(1) @@ -146,26 +184,29 @@ def _git_update(check_only: bool = False) -> None: # Fetch and compare. Fail closed on a network/ref error: selecting the highest LOCAL # tag would let a stray or malicious tag masquerade as the latest upstream release. - fetched = subprocess.run( + # Announce the network step: it captures its output, so without this line a slow or + # unreachable origin looks like a frozen terminal until the budget below expires. + print("Fetching release tags from origin...") + fetched = _run( [git, "-C", str(project_dir), "fetch", "--tags", "origin"], - capture_output=True, text=True, + "Fetching release tags from origin", _GIT_FETCH_TIMEOUT_S, ) if fetched.returncode: print("Could not fetch release tags from origin; no update was applied.", file=sys.stderr) sys.exit(1) - local = subprocess.run([git, "-C", str(project_dir), "rev-parse", "HEAD"], - capture_output=True, text=True).stdout.strip() - branch_result = subprocess.run( + local = _run([git, "-C", str(project_dir), "rev-parse", "HEAD"], + "Reading the current revision", _GIT_LOCAL_TIMEOUT_S).stdout.strip() + branch_result = _run( [git, "-C", str(project_dir), "symbolic-ref", "--quiet", "--short", "HEAD"], - capture_output=True, text=True, + "Reading the current branch", _GIT_LOCAL_TIMEOUT_S, ) original_ref = branch_result.stdout.strip() if branch_result.returncode == 0 else local tag = LATEST_TAG if not tag: - tags = subprocess.run( + tags = _run( [git, "-C", str(project_dir), "ls-remote", "--tags", "--refs", "origin", "v*"], - capture_output=True, text=True, + "Listing release tags from origin", _GIT_LS_REMOTE_TIMEOUT_S, ) if tags.returncode: print("Could not list release tags from origin; no update was applied.", @@ -180,9 +221,9 @@ def _git_update(check_only: bool = False) -> None: sys.exit(1) # ``rev-list`` peels annotated tags; comparing HEAD to the tag object itself would # report a false update forever. - remote = subprocess.run( + remote = _run( [git, "-C", str(project_dir), "rev-list", "-n", "1", tag], - capture_output=True, text=True, + "Resolving the release tag", _GIT_LOCAL_TIMEOUT_S, ) remote_sha = remote.stdout.strip() if remote.returncode == 0 else "" @@ -200,29 +241,50 @@ def _git_update(check_only: bool = False) -> None: if check_only: return - dirty = subprocess.run( + dirty = _run( [git, "-C", str(project_dir), "status", "--porcelain"], - capture_output=True, text=True, + "Checking the working tree", _GIT_LOCAL_TIMEOUT_S, ) if dirty.stdout.strip(): print("Refusing to update a working tree with uncommitted changes.", file=sys.stderr) sys.exit(1) print(f"Checking out release {tag}...") - subprocess.run([git, "-C", str(project_dir), "checkout", f"tags/{tag}"], check=True) + _run([git, "-C", str(project_dir), "checkout", f"tags/{tag}"], + "Checking out the release tag", _GIT_CHECKOUT_TIMEOUT_S, + check=True, capture=False) + print(f"Reinstalling from {project_dir}...") try: - subprocess.run( + _run( [sys.executable, "-m", "pip", "install", "-e", str(project_dir)], - check=True, - ) - except subprocess.CalledProcessError: - # A failed reinstall must not strand a previously working editable checkout at - # a half-applied detached release. Restore its original branch (or exact commit - # when it started detached) and best-effort reinstall before propagating failure. - subprocess.run([git, "-C", str(project_dir), "checkout", original_ref], check=False) - subprocess.run( - [sys.executable, "-m", "pip", "install", "-e", str(project_dir)], - check=False, + "Reinstalling the editable checkout", _PIP_INSTALL_TIMEOUT_S, + check=True, capture=False, ) + except (subprocess.CalledProcessError, UpdateTimeout): + # A failed *or stalled* reinstall must not strand a previously working editable + # checkout at a half-applied detached release. The tree is already on the new tag + # by this point, so a bare hang here is what wedges the install; catching the + # timeout is what lets this rollback run at all. Restore the original branch (or + # exact commit when it started detached) and best-effort reinstall, then + # propagate the original failure. + print("Restoring the previous checkout...", file=sys.stderr) + try: + _run([git, "-C", str(project_dir), "checkout", original_ref], + "Restoring the previous checkout", _GIT_CHECKOUT_TIMEOUT_S, + capture=False) + _run( + [sys.executable, "-m", "pip", "install", "-e", str(project_dir)], + "Reinstalling the previous checkout", _PIP_INSTALL_TIMEOUT_S, + capture=False, + ) + except UpdateTimeout: + # Rollback itself stalled: name the two commands that finish it by hand + # rather than exiting on a tree the user does not know has moved. + print( + "Rollback did not finish. Run `git -C %s checkout %s` and " + "`%s -m pip install -e %s` to restore the previous installation." + % (project_dir, original_ref, sys.executable, project_dir), + file=sys.stderr, + ) raise print(f"Updated to {tag}.") @@ -243,22 +305,25 @@ def _pip_update(method: str, check_only: bool = False) -> None: if check_only: print(f"Latest stable Git release: {tag}") return - subprocess.run( + _run( [sys.executable, "-m", "pip", "install", "--upgrade", f"git+{remote}@{tag}#egg=engraphis"], - check=True) + "Installing the update from Git", _PIP_INSTALL_TIMEOUT_S, + check=True, capture=False) return version = LATEST_TAG[1:] if LATEST_TAG else "" target = "engraphis[server]" + ("==" + version if version else "") if check_only: - subprocess.run( + _run( [sys.executable, "-m", "pip", "install", "--dry-run", "--upgrade", target], - check=False, + "Checking the package index for a newer release", _PIP_RESOLVE_TIMEOUT_S, + capture=False, ) return - subprocess.run( + _run( [sys.executable, "-m", "pip", "install", "--upgrade", target], - check=True) + "Installing the update from the package index", _PIP_INSTALL_TIMEOUT_S, + check=True, capture=False) def _pipx_update(check_only: bool = False) -> None: @@ -266,20 +331,23 @@ def _pipx_update(check_only: bool = False) -> None: if check_only: if LATEST_TAG: target = "engraphis[server]==" + LATEST_TAG[1:] - subprocess.run( + _run( ["pipx", "runpip", "engraphis", "install", "--dry-run", "--upgrade", target], - check=False, + "Checking the package index for a newer release", _PIP_RESOLVE_TIMEOUT_S, + capture=False, ) else: print("pipx detected - run `pipx upgrade engraphis` to check for updates.") return if LATEST_TAG: - subprocess.run( + _run( ["pipx", "install", "--force", "engraphis[server]==" + LATEST_TAG[1:]], - check=True, + "Installing the update with pipx", _PIPX_TIMEOUT_S, + check=True, capture=False, ) return - subprocess.run(["pipx", "upgrade", "engraphis"], check=True) + _run(["pipx", "upgrade", "engraphis"], "Upgrading with pipx", _PIPX_TIMEOUT_S, + check=True, capture=False) def _docker_update(check_only: bool = False) -> None: @@ -332,6 +400,10 @@ def main(argv=None) -> None: 1, "Error: update failed; the previous installation was restored when possible.\n", ) + except UpdateTimeout as exc: + # Say which step stalled and what to do about it. Silence here is the bug: every + # network step used to be unbounded, so a stalled index simply never returned. + ap.exit(1, "Error: %s\n" % exc) if __name__ == "__main__": diff --git a/tests/e2e/commercial.spec.js b/tests/e2e/commercial.spec.js index cecdf4d..08b5550 100644 --- a/tests/e2e/commercial.spec.js +++ b/tests/e2e/commercial.spec.js @@ -1,24 +1,54 @@ const { test, expect } = require('@playwright/test'); const AxeBuilder = require('@axe-core/playwright').default; -const hostedLicense = { - plan: 'local', - features: [], - cloud_managed: true, - trial_seconds: 259_200, - grace_seconds: 86_400, - grace_scope: 'existing authenticated local workspace writes only', - pro_upgrade_url: 'https://cloud.engraphis.test/pro', - team_upgrade_url: 'https://cloud.engraphis.test/team', - upgrade_url: 'https://cloud.engraphis.test/pricing', - trial: { used: false, trial_days: 3 }, +// The dashboard's entitlement vocabulary, mirrored from v2_api._FEATURE_LABELS. The +// license panel renders one row per key and ticks the ones `features` contains, so a +// missing key here would silently stop a paying customer's capability being asserted on. +const knownFeatures = { + analytics: 'Analytics', + automation: 'Automation', + consolidation: 'Auto Consolidation', + dreaming: 'Auto Dreaming', + export: 'Compliance export', + sync: 'Cloud Sync', + team: 'Team administration', }; +const proFeatures = ['analytics', 'automation', 'consolidation', 'dreaming', 'export', 'sync']; +const teamFeatures = [...proFeatures, 'team']; + +function licenseFor(plan, features) { + return { + plan, + features, + known_features: knownFeatures, + cloud_managed: true, + cloud_access_active: plan !== 'local', + trial_seconds: 259_200, + grace_seconds: 86_400, + grace_scope: 'existing authenticated local workspace writes only', + pro_upgrade_url: 'https://cloud.engraphis.test/pro', + team_upgrade_url: 'https://cloud.engraphis.test/team', + upgrade_url: 'https://cloud.engraphis.test/pricing', + trial: { used: false, trial_days: 3 }, + }; +} + +// A FREE customer. Every test below used to run against this one payload, which is why a +// paying customer being shown a lock badge survived all the way to launch day. +const hostedLicense = licenseFor('local', []); +const proLicense = licenseFor('pro', proFeatures); +const teamLicense = licenseFor('team', teamFeatures); +// A Team subscription whose billing has lapsed: the plan is still Team, but the control +// plane has withdrawn every feature. +const lapsedTeamLicense = { ...licenseFor('team', []), cloud_access_active: false }; + async function mockLocalClient( page, cloudStatus = 402, syncRunStatus = null, automationPostStatus = null, + license = hostedLicense, ) { const calls = []; let syncLast = null; @@ -36,7 +66,7 @@ async function mockLocalClient( if (path === '/bootstrap') { body = { - license: hostedLicense, + license, workspaces: [], embedder: { semantic: true }, }; @@ -51,7 +81,7 @@ async function mockLocalClient( by_type: {}, }; } else if (path === '/license') { - body = hostedLicense; + body = license; } else if (path === '/auth/state') { body = { enabled: false, @@ -151,14 +181,14 @@ test('Cloud Sync denial returns an unlicensed installation to the hosted upgrade await page.getByRole('button', { name: 'Sync now' }).click(); const sync = page.locator('#sync-body'); - await expect(sync).toContainText('Cloud Sync runs in Engraphis Pro Cloud'); + await expect(sync).toContainText('Unlock Cloud Sync and more'); await expect(sync.getByRole('link', { name: 'Start hosted Pro trial' })) .toHaveAttribute('href', 'https://cloud.engraphis.test/pro?plan=pro&trial=pro'); await expect(calls.some(call => call.path === '/sync/run' && call.method === 'POST')).toBe(true); await page.reload(); await openView(page, 'settings'); - await expect(page.locator('#sync-body')).toContainText('Cloud Sync runs in Engraphis Pro Cloud'); + await expect(page.locator('#sync-body')).toContainText('Unlock Cloud Sync and more'); await expect(page.getByRole('button', { name: 'Try Cloud Sync again' })).toBeVisible(); calls.setSyncRunStatus(200); @@ -251,6 +281,101 @@ test('local dashboard exposes hosted Pro and Team CTAs without local commercial expect(errors).toEqual([]); }); +// ── paying customers ───────────────────────────────────────────────────────────────── +// Until these existed, every test in this file ran against one FREE payload, so the whole +// end-to-end suite never once rendered a customer who had paid. That is exactly how a +// paying customer being shown a lock badge on a feature they had bought survived to +// launch day. `#nav-*-lock` is the element that carried the wrong badge, so it is what +// these assert on directly. +const navLocks = { + analytics: '#nav-analytics-lock', + automation: '#nav-automation-lock', + team: '#nav-team-lock', +}; + +test('a free installation is locked out of every hosted capability', async ({ page }) => { + const errors = recordBrowserErrors(page); + await mockLocalClient(page); + await page.goto('/'); + + // The baseline the paid cases below are the counterpart to: all three locks drawn. + await expect(page.getByLabel('Open hosted plan settings')).toHaveText('LOCAL'); + await expect(page.locator(navLocks.analytics)).toHaveText('PRO'); + await expect(page.locator(navLocks.automation)).toHaveText('PRO'); + await expect(page.locator(navLocks.team)).toHaveText('TEAM'); + expect(errors).toEqual([]); +}); + +test('a paying Team customer sees TEAM with Team administration unlocked', async ({ page }) => { + const errors = recordBrowserErrors(page); + await mockLocalClient(page, 200, null, null, teamLicense); + await page.goto('/'); + + // The badge settles before the locks: dashboard.js sets both inside loadLicense(), + // so asserting it first means the empty locks below cannot be read pre-render. + await expect(page.getByLabel('Open hosted plan settings')).toHaveText('TEAM'); + for (const [feature, selector] of Object.entries(navLocks)) { + await expect(page.locator(selector), `${feature} is still locked for a Team customer`) + .toHaveText(''); + } + + await openView(page, 'settings'); + const licensePanel = page.locator('.settings-license-panel'); + await expect(licensePanel.getByText('TEAM', { exact: true })).toBeVisible(); + // Every capability Team grants is ticked, including the two the server folds into + // `automation` and this client names separately. + for (const label of Object.values(knownFeatures)) { + await expect(licensePanel).toContainText(`✓ ${label}`); + } + await expect(licensePanel).not.toContainText('○'); + // A paying customer is offered the account portal, never another trial. + await expect(licensePanel.getByRole('link', { name: 'Open Team Cloud' })) + .toHaveAttribute('href', 'https://cloud.engraphis.test/team?plan=team'); + await expect(licensePanel.getByRole('button', { name: 'Start hosted Team trial' })) + .toHaveCount(0); + await expect(licensePanel.getByRole('button', { name: 'Start hosted Pro trial' })) + .toHaveCount(0); + expect(errors).toEqual([]); +}); + +test('a paying Pro customer keeps only the Team upsell', async ({ page }) => { + const errors = recordBrowserErrors(page); + await mockLocalClient(page, 200, null, null, proLicense); + await page.goto('/'); + + await expect(page.getByLabel('Open hosted plan settings')).toHaveText('PRO'); + await expect(page.locator(navLocks.analytics)).toHaveText(''); + await expect(page.locator(navLocks.automation)).toHaveText(''); + await expect(page.locator(navLocks.team)).toHaveText('TEAM'); + + await openView(page, 'settings'); + const licensePanel = page.locator('.settings-license-panel'); + await expect(licensePanel.getByText('PRO', { exact: true })).toBeVisible(); + await expect(licensePanel).toContainText(`✓ ${knownFeatures.analytics}`); + await expect(licensePanel).toContainText(`✓ ${knownFeatures.consolidation}`); + await expect(licensePanel).toContainText(`○ ${knownFeatures.team}`); + expect(errors).toEqual([]); +}); + +test('a lapsed Team subscription is sent to billing, not to a spent trial', async ({ page }) => { + const errors = recordBrowserErrors(page); + await mockLocalClient(page, 402, null, null, lapsedTeamLicense); + await page.goto('/'); + + // The plan name survives an inactive entitlement so the CTA stays the account portal; + // the locks come back because the control plane has withdrawn the features. + await expect(page.getByLabel('Open hosted plan settings')).toHaveText('TEAM'); + await expect(page.locator(navLocks.team)).toHaveText('TEAM'); + await expect(page.locator(navLocks.analytics)).toHaveText('PRO'); + + await openView(page, 'settings'); + const licensePanel = page.locator('.settings-license-panel'); + await expect(licensePanel.getByRole('link', { name: 'Open Team Cloud' })).toBeVisible(); + await expect(licensePanel.getByRole('button', { name: 'Start hosted Team trial' })) + .toHaveCount(0); + expect(errors).toEqual([]); +}); + for (const cloudStatus of [401, 402, 501]) { test(`Analytics and Automation defer to cloud proxy status ${cloudStatus}`, async ({ page }) => { const errors = recordBrowserErrors(page); @@ -264,14 +389,13 @@ for (const cloudStatus of [401, 402, 501]) { () => calls.filter(call => call.path === '/analytics').length, ).toBeGreaterThan(analyticsBefore); const analytics = page.locator('#analytics-body'); - await expect(analytics).toContainText('Analytics runs in Engraphis Pro Cloud'); + await expect(analytics).toContainText('Unlock Analytics and more'); await expect(analytics).toContainText('exactly 3 active days'); - await expect(analytics).toContainText( - 'Local-only write grace is separate, capped at 24 hours, and never extends cloud access.', - ); + await expect(analytics).toContainText('$10/month or $100/year'); + await expect(analytics).toContainText('Hosted Cloud Sync across your installations'); await expect(analytics.getByRole('link', { name: 'Start hosted Pro trial' })) .toHaveAttribute('href', 'https://cloud.engraphis.test/pro?plan=pro&trial=pro'); - await expect(analytics.getByRole('link', { name: 'View Pro plans' })) + await expect(analytics.getByRole('link', { name: 'Purchase Pro license' })) .toHaveAttribute('href', 'https://cloud.engraphis.test/pro?plan=pro'); await expect(page.locator('#an-lock')).toHaveText('PRO'); @@ -282,15 +406,14 @@ for (const cloudStatus of [401, 402, 501]) { ).toBeGreaterThan(automationBefore); const automation = page.locator('#automation-body'); await expect(automation).toContainText( - 'Automation, Auto Consolidation, and Auto Dreaming runs in Engraphis Pro Cloud', + 'Unlock Automation, Auto Consolidation, and Auto Dreaming and more', ); await expect(automation).toContainText('exactly 3 active days'); - await expect(automation).toContainText( - 'Local-only write grace is separate, capped at 24 hours, and never extends cloud access.', - ); + await expect(automation).toContainText('$10/month or $100/year'); + await expect(automation).toContainText('Auto Dreaming with reviewable managed proposals'); await expect(automation.getByRole('link', { name: 'Start hosted Pro trial' })) .toHaveAttribute('href', 'https://cloud.engraphis.test/pro?plan=pro&trial=pro'); - await expect(automation.getByRole('link', { name: 'View Pro plans' })) + await expect(automation.getByRole('link', { name: 'Purchase Pro license' })) .toHaveAttribute('href', 'https://cloud.engraphis.test/pro?plan=pro'); await expect(page.locator('#au-lock')).toHaveText('PRO'); diff --git a/tests/test_client_launch.py b/tests/test_client_launch.py new file mode 100644 index 0000000..28ef100 --- /dev/null +++ b/tests/test_client_launch.py @@ -0,0 +1,373 @@ +"""Launch guards for the public client: no silent hangs, no unvetted probe, no false locks. + +Each test pins a defect that reached a customer's machine: + +* ``engraphis-update`` shelled out to git/pip/pipx with no ``timeout=`` and + ``capture_output=True``, so a stalled index or unreachable remote hung forever with + nothing on screen — and a stall *after* the release tag was checked out skipped the + rollback and left a wedged half-upgrade; +* the update probe was the one credential-path-adjacent HTTP call using a plain + ``build_opener``, skipping the repo's SSRF / DNS-rebinding vetting on an endpoint that + ``ENGRAPHIS_UPDATE_URL`` makes operator-controllable; and +* ``/api/license`` always returned ``features: []``, so a paying Pro or Team customer saw + "PRO"/"TEAM" lock badges on the features they had just bought. + +*Which* plan that feature list is computed from is pinned separately, in +tests/test_hosted_plan_resolution.py: this file owns the plan → feature table and the +dashboard's lock-badge loop; that one owns how the plan itself is learned from the control +plane, cached, and degraded offline. +""" +from __future__ import annotations + +import ast +import inspect +import re +import subprocess +import sys +import urllib.error +from pathlib import Path + +import pytest + +from engraphis import update_check +from engraphis.routes import v2_api + +REPO_ROOT = Path(__file__).resolve().parents[1] +UPDATER = REPO_ROOT / "scripts" / "update.py" +DASHBOARD_JS = REPO_ROOT / "engraphis" / "static" / "dashboard.js" + +# The private control plane's plan→feature table, mirrored from (read-only) +# engraphis-cloud/engraphis_cloud/entitlements.py PLAN_FEATURES. A drift here means a +# purchased capability silently renders as locked. +SERVER_PLAN_FEATURES = { + "free": set(), + "pro": {"analytics", "automation", "export", "sync"}, + "team": {"analytics", "automation", "export", "sync", "team"}, +} +# Named separately by this client's commercial manifest; the server grants both under +# ``automation``, so any plan granting ``automation`` must grant these too. +CLIENT_AUTOMATION_ALIASES = {"consolidation", "dreaming"} + + +# ── (1) the updater must never hang on a stalled remote ─────────────────────── +def test_the_updater_runs_no_unbounded_subprocess() -> None: + """Every shell-out is routed through the one helper that always passes a budget.""" + + tree = ast.parse(UPDATER.read_text(encoding="utf-8")) + unbounded = [] + for node in ast.walk(tree): + if not isinstance(node, ast.Call): + continue + target = ast.unparse(node.func) + if target in ("subprocess.run", "subprocess.call", "subprocess.check_output", + "subprocess.check_call", "subprocess.Popen"): + if not any(kw.arg == "timeout" for kw in node.keywords): + unbounded.append(target) + + assert unbounded == [], "unbounded subprocess call(s) in scripts/update.py: %s" % unbounded + + +def test_the_updater_helper_makes_a_timeout_impossible_to_omit() -> None: + """``timeout`` has no default, so a new call site cannot silently be unbounded.""" + + import scripts.update as updater + + timeout = inspect.signature(updater._run).parameters["timeout"] + assert timeout.default is inspect.Parameter.empty + + tree = ast.parse(UPDATER.read_text(encoding="utf-8")) + call_sites = [ + node for node in ast.walk(tree) + if isinstance(node, ast.Call) and getattr(node.func, "id", "") == "_run" + ] + assert call_sites, "expected the updater to shell out through _run" + for node in call_sites: + supplied = len(node.args) + len(node.keywords) + assert supplied >= 3, ast.unparse(node) + + +def test_a_stalled_remote_aborts_instead_of_waiting_forever(monkeypatch) -> None: + """The failing call is abandoned at its budget and reported, not awaited.""" + + import scripts.update as updater + + seen = {} + + def _stall(cmd, **kwargs): + seen["timeout"] = kwargs.get("timeout") + raise subprocess.TimeoutExpired(cmd, kwargs.get("timeout")) + + monkeypatch.setattr(updater.subprocess, "run", _stall) + + with pytest.raises(updater.UpdateTimeout) as excinfo: + updater._remote_latest_tag("/usr/bin/git", "https://example.test/engraphis.git") + + assert isinstance(seen["timeout"], (int, float)) and seen["timeout"] > 0 + # A hang is only survivable if the user is told which step stalled and what to do. + message = str(excinfo.value) + assert "timed out" in message + assert "engraphis-update" in message + + +def test_main_reports_a_stalled_step_and_exits(monkeypatch, capsys) -> None: + """The stall must surface as a non-zero exit with copy, not an unhandled traceback.""" + + import scripts.update as updater + + monkeypatch.setattr(updater, "_detect_install", lambda: "pypi") + + def _stall(cmd, **kwargs): + raise subprocess.TimeoutExpired(cmd, kwargs.get("timeout")) + + monkeypatch.setattr(updater.subprocess, "run", _stall) + + with pytest.raises(SystemExit) as excinfo: + updater.main([]) + + assert excinfo.value.code == 1 + assert "timed out" in capsys.readouterr().err + + +def test_a_stalled_reinstall_still_rolls_back_the_checkout(monkeypatch, tmp_path) -> None: + """The regression that wedges an install. + + By the time the reinstall runs, the tree is already detached onto the new release + tag. An unbounded reinstall therefore hangs *after* the destructive step and the + rollback below it is never reached, stranding a working editable install on a + half-applied upgrade. The timeout has to be catchable for the rollback to run at all. + """ + + import scripts.update as updater + + project = tmp_path / "engraphis" + (project / ".git").mkdir(parents=True) + monkeypatch.setattr(updater, "LATEST_TAG", "") + monkeypatch.setattr(updater.shutil, "which", lambda name: "/usr/bin/git") + + calls = [] + reinstalls = {"n": 0} + + def _fake_run(cmd, **kwargs): + cmd = list(cmd) + calls.append(cmd) + assert kwargs.get("timeout"), "every step must carry a budget: %s" % cmd + + def done(stdout=""): + return subprocess.CompletedProcess(cmd, 0, stdout, "") + + if cmd[:4] == [sys.executable, "-m", "pip", "show"]: + return done("Editable project location: %s\n" % project) + if cmd[:5] == [sys.executable, "-m", "pip", "install", "-e"]: + reinstalls["n"] += 1 + if reinstalls["n"] == 1: # the upgrade reinstall stalls + raise subprocess.TimeoutExpired(cmd, kwargs.get("timeout")) + return done() # the rollback reinstall succeeds + if "rev-parse" in cmd: + return done("a" * 40 + "\n") + if "symbolic-ref" in cmd: + return done("main\n") + if "ls-remote" in cmd: + return done("%s\trefs/tags/v9.9.9\n" % ("b" * 40)) + if "rev-list" in cmd: + return done("b" * 40 + "\n") + if "status" in cmd: + return done("") + return done() + + monkeypatch.setattr(updater.subprocess, "run", _fake_run) + + with pytest.raises(updater.UpdateTimeout): + updater._git_update() + + checkouts = [cmd for cmd in calls if "checkout" in cmd] + assert ["/usr/bin/git", "-C", str(project), "checkout", "tags/v9.9.9"] in checkouts + # The rollback ran despite the stall, and restored the original branch. + assert ["/usr/bin/git", "-C", str(project), "checkout", "main"] in checkouts + assert reinstalls["n"] == 2, "the previous checkout must be reinstalled" + + +# ── (2) the update probe must use the vetted connector ──────────────────────── +def test_update_probe_uses_the_pinned_opener_with_a_timeout(monkeypatch) -> None: + """``ENGRAPHIS_UPDATE_URL`` makes this endpoint operator-controllable. + + A plain ``build_opener`` dials whatever the hostname resolves to at connect time, so + it neither rejects private/reserved targets nor closes the DNS-rebinding window + between the scheme check and the connect. + """ + + used = {} + + def _fake_pinned(*handlers): + used["handlers"] = handlers + + class _Opener: + def open(self, request, timeout=None): + used["timeout"] = timeout + raise urllib.error.URLError("blocked") + + return _Opener() + + def _forbidden(*args, **kwargs): + raise AssertionError("the update probe must not build an unvetted opener") + + monkeypatch.setattr(update_check, "build_pinned_https_opener", _fake_pinned) + monkeypatch.setattr(update_check.urllib.request, "build_opener", _forbidden) + + assert update_check._fetch("https://mirror.example.test/latest.json", 4.0) is None + assert used["handlers"], "the no-redirect handler must still be installed" + assert used["timeout"] == 4.0 + + +def test_update_probe_imports_the_repo_connector() -> None: + """Pin the import so a refactor cannot quietly fall back to urllib's default.""" + + assert update_check.build_pinned_https_opener is not None + source = (REPO_ROOT / "engraphis" / "update_check.py").read_text(encoding="utf-8") + assert "urllib.request.build_opener(" not in source + + +# ── (3) a paying customer must not see a lock on what they bought ───────────── +@pytest.mark.parametrize("plan", ["pro", "team"]) +def test_a_paid_plan_grants_a_non_empty_feature_list(plan) -> None: + features = v2_api.entitled_features(plan) + + assert features, "a paid plan must grant features" + assert SERVER_PLAN_FEATURES[plan].issubset(features) + # The server folds these into ``automation``; the client names them separately. + assert CLIENT_AUTOMATION_ALIASES.issubset(features) + + +@pytest.mark.parametrize("plan", ["free", "local", "", None, "enterprise", "unknown", "pro-plus"]) +def test_an_unpaid_or_unrecognised_plan_grants_nothing(plan) -> None: + assert v2_api.entitled_features(plan) == [] + + +@pytest.mark.parametrize("spelling", ["PRO", " pro ", "Pro", "\tpro\n"]) +def test_plan_lookup_is_case_and_whitespace_insensitive(spelling) -> None: + """The control plane emits lowercase plans; a caller must not be able to drift.""" + + assert v2_api.entitled_features(spelling) == v2_api.entitled_features("pro") + + +def test_team_grants_everything_pro_does_plus_team() -> None: + pro, team = set(v2_api.entitled_features("pro")), set(v2_api.entitled_features("team")) + + assert pro < team + assert team - pro == {"team"} + + +def test_client_never_advertises_a_feature_the_server_cannot_grant() -> None: + server_keys = set().union(*SERVER_PLAN_FEATURES.values()) + for plan in ("pro", "team"): + extra = set(v2_api.entitled_features(plan)) - server_keys + assert extra <= CLIENT_AUTOMATION_ALIASES, extra + + +def test_license_route_unlocks_a_connected_paying_customer(monkeypatch) -> None: + monkeypatch.setenv("ENGRAPHIS_CLOUD_PLAN", "team") + + payload = v2_api.get_license() + + assert payload["plan"] == "team" + assert payload["features"], "a paying customer must not be sent an empty feature list" + assert "team" in payload["features"] + + +def test_license_route_leaves_the_free_local_core_locked(monkeypatch) -> None: + monkeypatch.delenv("ENGRAPHIS_CLOUD_PLAN", raising=False) + monkeypatch.setattr(v2_api, "_hosted_plan", lambda: "local") + + payload = v2_api.get_license() + + assert payload["plan"] == "local" + assert payload["features"] == [] + + +def test_an_unconnected_installation_is_the_free_local_core(monkeypatch) -> None: + from engraphis import cloud_session + + monkeypatch.delenv("ENGRAPHIS_CLOUD_PLAN", raising=False) + monkeypatch.setattr(cloud_session, "configured", lambda **kw: False) + + assert v2_api._hosted_plan() == "local" + + +def test_a_connected_installation_reports_a_paid_plan(monkeypatch) -> None: + """The fallback before the control plane has ever answered. + + ``pro`` is the smallest paid plan, so a connected customer is never shown the free + local core while the authoritative entitlement is still unknown. It is a floor, not + the answer: once ``GET /v1/entitlements/{org}`` has been read, the cached plan wins + (tests/test_hosted_plan_resolution.py). + """ + + from engraphis import cloud_session + + monkeypatch.delenv("ENGRAPHIS_CLOUD_PLAN", raising=False) + monkeypatch.delenv("ENGRAPHIS_CLOUD_CONTROL_URL", raising=False) + monkeypatch.setattr(cloud_session, "configured", lambda **kw: True) + + assert v2_api._hosted_plan() == "pro" + # With no endpoint configured there is nothing to dial, so nothing is scheduled. + assert v2_api._entitlement_refreshing is False + + +def test_an_unreadable_cloud_session_never_breaks_the_dashboard(monkeypatch) -> None: + """``/api/license`` is on the ``/api/bootstrap`` path; a badge must not 500 the boot.""" + + from engraphis import cloud_session + + def _boom(**kwargs): + raise cloud_session.CloudSessionError("temporarily unreadable") + + monkeypatch.delenv("ENGRAPHIS_CLOUD_PLAN", raising=False) + monkeypatch.setattr(cloud_session, "configured", _boom) + + assert v2_api._hosted_plan() == "local" + assert v2_api.get_license()["features"] == [] + + +def test_license_route_emits_every_field_the_dashboard_reads(monkeypatch) -> None: + """The dashboard read these off the license payload; no route ever emitted them.""" + + monkeypatch.setenv("ENGRAPHIS_CLOUD_PLAN", "pro") + + payload = v2_api.get_license() + + for field in ("plan", "features", "known_features", "is_trial", "trial", + "upgrade_url", "pro_upgrade_url", "team_upgrade_url"): + assert field in payload, field + assert "used" in payload["trial"] + # Pro and Team bill through separate checkout targets. + assert payload["pro_upgrade_url"] and payload["team_upgrade_url"] + # Every advertised key must be renderable, and every grantable key advertised. + assert set(payload["features"]) <= set(payload["known_features"]) + assert set(v2_api.entitled_features("team")) == set(payload["known_features"]) + + +def test_dashboard_lock_badges_clear_for_a_paid_plan(monkeypatch) -> None: + """Close the loop on the JS: ``locked = !features.includes(f)``. + + The dashboard's three gated nav items are read straight out of the shipped asset so a + renamed feature key cannot re-lock a paid customer without failing here. + """ + + script = DASHBOARD_JS.read_text(encoding="utf-8") + block = script[script.index("function updateFeatureLocks()"):] + block = block[:block.index("\n}")] + gated = re.findall(r"apply\('[^']+',\s*'([^']+)'", block) + + assert set(gated) == {"analytics", "automation", "team"}, gated + + monkeypatch.setenv("ENGRAPHIS_CLOUD_PLAN", "team") + team_features = v2_api.get_license()["features"] + for feature in gated: + assert feature in team_features, "Team still renders a lock on %s" % feature + + monkeypatch.setenv("ENGRAPHIS_CLOUD_PLAN", "pro") + pro_features = v2_api.get_license()["features"] + assert {"analytics", "automation"} <= set(pro_features) + assert "team" not in pro_features # Team upsell stays visible on a Pro plan + + monkeypatch.setenv("ENGRAPHIS_CLOUD_PLAN", "free") + assert v2_api.get_license()["features"] == [] diff --git a/tests/test_dashboard_auth_placement.py b/tests/test_dashboard_auth_placement.py index d0c50f7..096e22c 100644 --- a/tests/test_dashboard_auth_placement.py +++ b/tests/test_dashboard_auth_placement.py @@ -1,10 +1,16 @@ """Static UI contract for the single-user local client and hosted commercial boundary.""" +import json import re +import shutil +import subprocess from pathlib import Path +import pytest + INDEX = Path(__file__).resolve().parents[1] / "engraphis" / "static" / "index.html" SCRIPT = Path(__file__).resolve().parents[1] / "engraphis" / "static" / "dashboard.js" +STYLES = Path(__file__).resolve().parents[1] / "engraphis" / "static" / "dashboard.css" def test_dashboard_has_no_local_team_auth_or_license_activation_ui(): @@ -68,8 +74,214 @@ def test_hosted_views_delegate_entitlement_to_cloud_proxy_responses(): automation = script[script.index("async function loadAutomation()"): script.index("async function saveAutomation()")] for body in (analytics, automation): - assert "e.status===401||e.status===402||e.status===501" in body + assert "hostedFeatureUnavailable(e)" in body assert "unlockHtml" in body + assert "error.status===409" in script + assert "Purchase Pro license" in script + + +# ── a paying customer must never be sold the plan they already own ──────────── +# The hosted views route a failed request to one of three answers. Only an entitlement +# status may draw the purchase panel; a 409 is a conflict, and ``consent_required`` in +# particular is a customer who HAS paid and only has to set one environment variable. +# +# ``_route`` below executes the shipped routing rather than asserting on its source: the +# regression it guards (409 folded into ``hostedFeatureUnavailable``) kept every string +# these files already assert on, and only a run can tell which branch actually won. +_ROUTED_FUNCTIONS = ( + "hostedPlanUrl", "unlockHtml", "managedConsentHtml", + "managedConsentRequired", "hostedFeatureUnavailable", + "loadAnalytics", "loadAutomation", +) + +# Everything the routed code touches that is not itself under test. The DOM, the API call +# and the license blob are stubbed; ``esc`` is the real escaping contract. +_ROUTING_STUBS = """ +'use strict'; +const NODES = {}; +const document = {getElementById(id){ + return NODES[id] || (NODES[id] = {innerHTML:'', textContent:'', className:'', style:{}})}}; +function esc(s){return String(s==null?'':s).replace(/[&<>"']/g, c=>( + {'&':'&','<':'<','>':'>','"':'"',"'":'''}[c]))} +function safeUrl(u){return u || '#'} +function setPlanPill(el,text,cls){if(el){el.textContent=text;el.className=cls}} +function showAs(el,on,disp){if(el)el.style.display=on?(disp||'block'):'none'} +function renderAnalytics(){return '
'} +function fmtRel(){return 'just now'} +function toast(){} +const TRIAL_DAYS = 3, WS = 'workspace'; +let CURRENT_VIEW = 'overview'; +const LIC = {pro_upgrade_url:'https://engraphis.com/pricing', + team_upgrade_url:'https://engraphis.com/pricing?plan=team', + upgrade_url:'https://engraphis.com/pricing', trial:{used:false}}; +const location = {href:'https://127.0.0.1:8077/'}; +let THROWN = null; +async function api(){if(THROWN) throw THROWN; return {}} +""" + +_ROUTING_DRIVER = """ +const CASES = JSON.parse(process.argv[2]); +(async () => { + const out = []; + for (const c of CASES) { + THROWN = Object.assign(new Error(c.message || 'request failed'), c.error); + CURRENT_VIEW = c.view; + for (const key of Object.keys(NODES)) delete NODES[key]; + await (c.view === 'analytics' ? loadAnalytics() : loadAutomation()); + const body = c.view === 'analytics' ? 'analytics-body' : 'automation-body'; + const lock = c.view === 'analytics' ? 'an-lock' : 'au-lock'; + out.push({name: c.name, html: NODES[body].innerHTML, pill: NODES[lock].textContent}); + } + process.stdout.write(JSON.stringify(out)); +})().catch(err => {process.stderr.write(String(err && err.stack)); process.exit(1)}); +""" + + +def _dashboard_function(name): + """Slice one top-level declaration out of the shipped dashboard bundle.""" + + script = SCRIPT.read_text(encoding="utf-8") + for head in ("\nasync function %s(" % name, "\nfunction %s(" % name): + start = script.find(head) + if start >= 0: + start += 1 + break + else: + raise AssertionError("dashboard.js no longer declares %s" % name) + end = re.compile(r"\n(?:async function |function |/\* |// |const |let |var )").search( + script, start) + return script[start:end.start() if end else len(script)].rstrip() + + +def _route(tmp_path, cases): + """Run the real hosted-view error routing over ``cases`` and return what it rendered.""" + + bundle = "\n".join([ + _ROUTING_STUBS, + "\n".join(_dashboard_function(name) for name in _ROUTED_FUNCTIONS), + _ROUTING_DRIVER, + ]) + runner = tmp_path / "routing.js" + runner.write_text(bundle, encoding="utf-8") + result = subprocess.run( + ["node", str(runner), json.dumps(cases)], + capture_output=True, text=True, timeout=60, + ) + assert result.returncode == 0, result.stderr + return {row["name"]: row for row in json.loads(result.stdout)} + + +@pytest.mark.skipif(shutil.which("node") is None, reason="node is required to run the UI") +@pytest.mark.parametrize("view", ["analytics", "automation"]) +def test_a_consent_required_conflict_is_answered_with_a_purchase_panel( + tmp_path, view, +): + """Analytics and Automation are Pro sales surfaces, not error consoles.""" + + rendered = _route(tmp_path, [{ + "name": "consent", "view": view, + "error": {"status": 409, "detail": {"code": "consent_required"}}, + }])["consent"] + + assert 'class="upgrade-panel"' in rendered["html"] + assert "Purchase Pro license" in rendered["html"] + assert "ENGRAPHIS_MANAGED_COMPUTE_CONSENT=1" not in rendered["html"] + assert rendered["pill"] == "PRO" + + +@pytest.mark.skipif(shutil.which("node") is None, reason="node is required to run the UI") +@pytest.mark.parametrize("view", ["analytics", "automation"]) +@pytest.mark.parametrize("status", [400, 401, 402, 500, 501]) +def test_a_genuine_entitlement_failure_still_renders_the_upgrade_panel( + tmp_path, view, status, +): + """Every failed hosted request renders the Pro upgrade panel in these tabs.""" + + rendered = _route(tmp_path, [{ + "name": "unentitled", "view": view, "error": {"status": status}, + }])["unentitled"] + + assert 'class="upgrade-panel"' in rendered["html"] + assert "Purchase Pro license" in rendered["html"] + assert "Start hosted Pro trial" in rendered["html"] + assert rendered["pill"] == "PRO" + + +@pytest.mark.skipif(shutil.which("node") is None, reason="node is required to run the UI") +@pytest.mark.parametrize("view", ["analytics", "automation"]) +def test_an_internal_hosted_conflict_is_answered_with_a_purchase_panel(tmp_path, view): + """Backend failures never expose internal messages in hosted tabs.""" + + rendered = _route(tmp_path, [{ + "name": "conflict", "view": view, + "message": "managed snapshot generation must advance", + "error": {"status": 409, "detail": {"error": "generation conflict"}}, + }])["conflict"] + + assert 'class="upgrade-panel"' in rendered["html"] + assert "Purchase Pro license" in rendered["html"] + assert "managed snapshot generation must advance" not in rendered["html"] + + +def test_analytics_and_automation_suppress_hosted_error_details(): + """Only these sales surfaces redirect every failed hosted request to Pro.""" + + helper = _dashboard_function("hostedFeatureUnavailable") + assert "CURRENT_VIEW==='analytics'" in helper + assert "CURRENT_VIEW==='automation'" in helper + for entitlement_status in ("401", "402", "501"): + assert entitlement_status in helper + consent = _dashboard_function("managedConsentRequired") + assert "CURRENT_VIEW!=='analytics'" in consent + assert "CURRENT_VIEW!=='automation'" in consent + + for name in ( + "loadOverviewAnalytics", + "loadAnalytics", + "loadAutomation", + "loadSyncStatus", + ): + body = _dashboard_function(name) + assert "managedConsentRequired(e)" in body, name + assert "managedConsentHtml(" in body, name + assert body.index("managedConsentRequired(e)") < body.index( + "hostedFeatureUnavailable(e)"), name + + +def test_sync_status_does_not_sell_pro_to_a_customer_who_already_owns_it(): + """``loadSyncStatus`` rendered the purchase panel for EVERY failure. + + A dropped connection or a 5xx from the relay told a paying Pro customer to buy Pro. + Only a billing answer may reach ``unlockHtml``; everything else shows the real error. + """ + + body = _dashboard_function("loadSyncStatus") + + assert "unlockHtml('Cloud Sync','pro')" in body + # The unlock must be reached through the entitlement predicate, never unconditionally. + assert "hostedFeatureUnavailable(e)" in body + assert body.index("hostedFeatureUnavailable(e)") < body.index("unlockHtml(") + # A cause that is neither consent nor billing surfaces the server's own message. + assert "esc(e.message)" in body + + +def test_pro_upgrade_panel_lists_every_pro_benefit_and_purchase_cta(): + script = SCRIPT.read_text(encoding="utf-8") + styles = STYLES.read_text(encoding="utf-8") + + assert 'class="upgrade-panel"' in script + assert "Start hosted Pro trial" in script + assert "Purchase Pro license" in script + for benefit in ( + "Hosted Cloud Sync across your installations", + "Growth, retention, decay, and entity Analytics", + "Auto Consolidation with hosted retention policies", + "Auto Dreaming with reviewable managed proposals", + "Signed compliance exports with bi-temporal checksums", + "Priority support", + ): + assert benefit in script + assert ".upgrade-panel" in styles def test_team_invitations_and_password_setup_are_not_in_local_client(): diff --git a/tests/test_hosted_plan_resolution.py b/tests/test_hosted_plan_resolution.py new file mode 100644 index 0000000..77ee5d4 --- /dev/null +++ b/tests/test_hosted_plan_resolution.py @@ -0,0 +1,1032 @@ +"""Launch guards for *which plan* the client says a customer is on. + +``/api/license`` learned to report a real feature list, which fixed the free-vs-paid lock +badges. It still guessed the plan: ``_hosted_plan`` read an undocumented +``ENGRAPHIS_CLOUD_PLAN`` and otherwise returned ``"pro"`` for any connected installation. +A paying TEAM customer who had never set that variable was therefore shown a PRO badge and +a lock on the Team administration they were paying for. + +The control plane does know. It just never told this client: ``POST /v1/devices/register`` +and ``POST /v1/tokens/refresh`` both answer with ``DeviceRegistrationResponse``, whose only +entitlement field is ``entitlement_version`` — so ``cloud_session.save_bootstrap`` has +nothing to persist. ``GET /v1/entitlements/{organization_id}`` *is* authoritative, and +every access token this client can mint already carries the ``entitlement:read`` scope it +requires. The client now reads it opportunistically and caches the answer. + +Every test here pins one half of that bargain: + +* the badge and the feature list must follow the control plane's own answer; and +* getting that answer must never block boot, hang, or raise — the exact failure modes + fixed earlier in this release cycle, on a path that now makes a network call. +""" +from __future__ import annotations + +import ast +import io +import json +import re +import socket +import threading +import time +import urllib.error +import urllib.request +from pathlib import Path + +import pytest + +from engraphis import cloud_session +from engraphis.routes import v2_api + +REPO_ROOT = Path(__file__).resolve().parents[1] +DASHBOARD_JS = REPO_ROOT / "engraphis" / "static" / "dashboard.js" + +ORGANIZATION = "org_paying_team" +CONTROL_URL = "https://control.example.test" + +# The authoritative payload shape, mirrored from (read-only) +# engraphis-cloud/engraphis_cloud/entitlements.py ``EntitlementDTO`` / ``PLAN_FEATURES``. +SERVER_PLAN_FEATURES = { + "free": [], + "pro": ["analytics", "automation", "export", "sync"], + "team": ["analytics", "automation", "export", "sync", "team"], +} + + +def _entitlement_dto(plan: str, *, active: bool = True, + organization_id: str = ORGANIZATION) -> dict: + return { + "organization_id": organization_id, + "entitlement_id": "ent_1", + "plan": plan, + "status": "active" if active else "past_due", + "cloud_access_active": active, + "cloud_features": SERVER_PLAN_FEATURES[plan] if active else [], + "seat_limit": 5, + "seat_assignment_basis": "named_members", + "starts_at": "2026-01-01T00:00:00Z", + "expires_at": None, + "version": 3, + } + + +class _Response(io.BytesIO): + def __enter__(self): + return self + + def __exit__(self, *exc_info): + self.close() + + +class _FakeControlPlane: + """One scripted control plane, recording exactly what the client sent it.""" + + def __init__(self, entitlement=None, *, error=None, raw=None, delay=None, + registration=None): + self.entitlement = entitlement + self.error = error + self.raw = raw + self.delay = delay + #: The entitlement fields a *current* control plane puts on every + #: ``DeviceRegistrationResponse``. ``None`` models a deployment that predates them. + self.registration = registration + self.requests = [] + self.threads = [] + + def opener(self, *handlers): + self.handlers = handlers + return self + + def open(self, request, timeout=None): + self.threads.append(threading.current_thread()) + self.requests.append({ + "url": request.full_url, + "method": request.get_method(), + "timeout": timeout, + "authorization": request.get_header("Authorization"), + }) + if request.full_url.endswith("/v1/tokens/refresh"): + body = { + "access_token": "eyJ-scoped-access", + "organization_id": ORGANIZATION, + "refresh_credential": "engr_rt_rotated_%d" % len(self.requests), + "refresh_expires_at": "2026-08-01T00:00:00Z", + "token_subject": "member", + } + body.update(self.registration or {}) + return _Response(json.dumps(body).encode("utf-8")) + if self.delay is not None: + self.delay.wait(timeout=10.0) + if self.error is not None: + raise self.error + if self.raw is not None: + return _Response(self.raw) + return _Response(json.dumps(self.entitlement).encode("utf-8")) + + +@pytest.fixture(autouse=True) +def _plan_resolution_isolation(monkeypatch): + """Keep every test hermetic: no inherited override, no leaked in-flight refresh.""" + + monkeypatch.delenv("ENGRAPHIS_CLOUD_PLAN", raising=False) + monkeypatch.delenv("ENGRAPHIS_CLOUD_ENTITLEMENT_REFRESH", raising=False) + monkeypatch.delenv("ENGRAPHIS_CLOUD_CONTROL_URL", raising=False) + monkeypatch.delenv("ENGRAPHIS_CLOUD_ORGANIZATION_ID", raising=False) + monkeypatch.setattr(v2_api, "_entitlement_refreshing", False, raising=False) + yield + _drain_refresh() + v2_api._entitlement_refreshing = False + + +def _connect(monkeypatch, *, pinned_token: bool = True) -> None: + """Present this process as an onboarded installation. + + ``pinned_token=True`` uses the documented short-lived-access-token deployment, which + reaches the entitlement route in a single request. ``False`` exercises the ordinary + saved-refresh-credential path, which rotates a credential first. + """ + + monkeypatch.setenv("ENGRAPHIS_CLOUD_CONTROL_URL", CONTROL_URL) + if pinned_token: + monkeypatch.setenv("ENGRAPHIS_CLOUD_ACCESS_TOKEN", "eyJ-scoped-access") + monkeypatch.setenv("ENGRAPHIS_CLOUD_ORGANIZATION_ID", ORGANIZATION) + else: + monkeypatch.setenv("ENGRAPHIS_CLOUD_REFRESH_CREDENTIAL", "engr_rt_bootstrap") + + +def _serve(monkeypatch, cloud: _FakeControlPlane) -> None: + monkeypatch.setattr( + "engraphis.hosted_client.build_pinned_https_opener", cloud.opener + ) + monkeypatch.setattr(cloud_session, "build_pinned_https_opener", cloud.opener) + + +def _drain_refresh(timeout: float = 10.0) -> None: + """Block until the background refresh finishes, so assertions are deterministic.""" + + deadline = time.monotonic() + timeout + while time.monotonic() < deadline: + with v2_api._ENTITLEMENT_REFRESH_LOCK: + busy = v2_api._entitlement_refreshing + if not busy: + return + time.sleep(0.005) + raise AssertionError("the background entitlement refresh never finished") + + +def _entitlement_reads(cloud: _FakeControlPlane) -> list: + return [call for call in cloud.requests if "/v1/entitlements/" in call["url"]] + + +def _settled_license(monkeypatch) -> dict: + """Read ``/api/license`` once to schedule the refresh, then again once it lands.""" + + monkeypatch.setattr(v2_api, "_ENTITLEMENT_REFRESH_SECONDS", 0) + v2_api.get_license() + _drain_refresh() + # Stop scheduling further refreshes, so the recorded traffic is exactly one round and + # assertions about it are not racing a second background thread. + monkeypatch.setattr(v2_api, "_ENTITLEMENT_REFRESH_SECONDS", 3600) + return v2_api.get_license() + + +# ── (1) a Team customer must be shown Team, with Team unlocked ──────────────── +def test_a_team_entitlement_produces_a_team_badge_with_the_team_feature_unlocked( + monkeypatch, +) -> None: + """The defect: a paying TEAM customer saw ``PRO`` and a lock on Team administration.""" + + _connect(monkeypatch) + _serve(monkeypatch, _FakeControlPlane(_entitlement_dto("team"))) + + payload = _settled_license(monkeypatch) + + assert payload["plan"] == "team" + assert payload["plan_source"] == "cloud" + assert "team" in payload["features"], "Team is still locked for a Team customer" + # The server folds these into ``automation``; the panel lists them separately, so a + # verbatim echo would leave a paying customer looking at unticked rows. + assert {"consolidation", "dreaming"} <= set(payload["features"]) + assert set(SERVER_PLAN_FEATURES["team"]) <= set(payload["features"]) + assert payload["cloud_access_active"] is True + assert payload["plan_checked_at"] > 0 + + +def test_a_team_entitlement_arrives_over_the_ordinary_refresh_credential_path( + monkeypatch, +) -> None: + """Not just the pinned-token deployment: the normal saved-session path works too.""" + + _connect(monkeypatch, pinned_token=False) + cloud = _FakeControlPlane(_entitlement_dto("team")) + _serve(monkeypatch, cloud) + + payload = _settled_license(monkeypatch) + + assert payload["plan"] == "team" + assert "team" in payload["features"] + assert cloud.requests[0]["url"] == CONTROL_URL + "/v1/tokens/refresh" + reads = _entitlement_reads(cloud) + assert [call["url"] for call in reads] == [ + CONTROL_URL + "/v1/entitlements/" + ORGANIZATION + ] + + +def test_a_pro_entitlement_keeps_the_team_upsell_visible(monkeypatch) -> None: + _connect(monkeypatch) + _serve(monkeypatch, _FakeControlPlane(_entitlement_dto("pro"))) + + payload = _settled_license(monkeypatch) + + assert payload["plan"] == "pro" + assert {"analytics", "automation"} <= set(payload["features"]) + assert "team" not in payload["features"] + + +def test_a_connected_free_organization_is_reported_as_the_local_core(monkeypatch) -> None: + """Being connected is not the same as having paid; the plan now says which.""" + + _connect(monkeypatch) + _serve(monkeypatch, _FakeControlPlane(_entitlement_dto("free", active=False))) + + payload = _settled_license(monkeypatch) + + assert payload["plan"] == "local" + assert payload["features"] == [] + + +def test_a_lapsed_subscription_keeps_its_plan_name_but_loses_its_features( + monkeypatch, +) -> None: + """A past-due Team customer needs the billing portal, not another trial offer. + + The dashboard offers "Open Team Cloud" for a hosted plan and "Start hosted Team trial" + otherwise, so collapsing a lapsed Team customer to ``local`` would send them to a trial + they have already consumed instead of to the page that restores their access. + """ + + _connect(monkeypatch) + _serve(monkeypatch, _FakeControlPlane(_entitlement_dto("team", active=False))) + + payload = _settled_license(monkeypatch) + + assert payload["plan"] == "team" + assert payload["features"] == [] + assert payload["cloud_access_active"] is False + + +def test_the_dashboards_gated_navigation_unlocks_for_an_authoritative_team_plan( + monkeypatch, +) -> None: + """Close the loop on the shipped JS: ``locked = !features.includes(f)``.""" + + script = DASHBOARD_JS.read_text(encoding="utf-8") + block = script[script.index("function updateFeatureLocks()"):] + gated = re.findall(r"apply\('[^']+',\s*'([^']+)'", block[:block.index("\n}")]) + assert set(gated) == {"analytics", "automation", "team"}, gated + + _connect(monkeypatch) + _serve(monkeypatch, _FakeControlPlane(_entitlement_dto("team"))) + payload = _settled_license(monkeypatch) + + for feature in gated: + assert feature in payload["features"], "Team still renders a lock on %s" % feature + # Every advertised key must be renderable by the license panel. + assert set(payload["features"]) <= set(payload["known_features"]) + + +# ── (2) the boot path must not block, hang, or raise ────────────────────────── +def test_the_authoritative_read_never_runs_on_the_request_thread(monkeypatch) -> None: + """``/api/license`` is on the ``/api/bootstrap`` boot path.""" + + _connect(monkeypatch) + cloud = _FakeControlPlane(_entitlement_dto("team")) + _serve(monkeypatch, cloud) + + _settled_license(monkeypatch) + + assert cloud.threads, "the control plane was never contacted" + for thread in cloud.threads: + assert thread is not threading.main_thread() + assert thread.daemon, "a boot-path helper thread must never hold the process open" + + +def test_a_hanging_control_plane_does_not_delay_boot(monkeypatch) -> None: + """The regression that matters most: a stalled cloud must not stall the dashboard.""" + + _connect(monkeypatch) + release = threading.Event() + cloud = _FakeControlPlane(_entitlement_dto("team"), delay=release) + _serve(monkeypatch, cloud) + monkeypatch.setattr(v2_api, "_ENTITLEMENT_REFRESH_SECONDS", 0) + + try: + started = time.monotonic() + payload = v2_api.get_license() + elapsed = time.monotonic() - started + + assert elapsed < 1.0, "the boot path waited %.2fs on the cloud" % elapsed + # A connected installation is never shown the free local core while it waits. + assert payload["plan"] == "pro" + assert payload["plan_source"] == "connected" + assert payload["features"] + finally: + release.set() + + +def test_the_entitlement_read_is_bounded_authenticated_and_redirect_proof( + monkeypatch, +) -> None: + """The request carries a live bearer, so it needs a budget and no redirect following.""" + + _connect(monkeypatch) + cloud = _FakeControlPlane(_entitlement_dto("team")) + _serve(monkeypatch, cloud) + + _settled_license(monkeypatch) + + entitlement = _entitlement_reads(cloud)[0] + assert entitlement["method"] == "GET" + assert entitlement["authorization"] == "Bearer eyJ-scoped-access" + assert isinstance(entitlement["timeout"], (int, float)) + assert 0 < entitlement["timeout"] <= 15 + assert cloud.handlers, "the no-redirect handler must be installed" + assert any( + isinstance(handler, urllib.request.HTTPRedirectHandler) + and type(handler).__name__ == "_NoRedirect" + for handler in cloud.handlers + ) + + +def test_the_probe_uses_the_repos_vetted_connector() -> None: + """A credential-bearing call must not build an unvetted opener.""" + + source = (REPO_ROOT / "engraphis" / "routes" / "v2_api.py").read_text(encoding="utf-8") + + assert "build_pinned_https_opener" in source + assert "urllib.request.build_opener(" not in source + + +@pytest.mark.parametrize("control_url,resolves_to", [ + # The pinned opener replaces urllib's *HTTPS* handler only, so a cleartext endpoint + # would fall through to the plain handler and put a live bearer on the wire. + ("http://control.example.test", "93.184.216.34"), + ("https://user:secret@control.example.test", "93.184.216.34"), + ("https://control.example.test/v1?leak=1", "93.184.216.34"), + ("ftp://control.example.test", "93.184.216.34"), + ("https://internal.example.test", "10.0.0.5"), +]) +def test_an_unvetted_control_url_never_receives_the_bearer_token( + monkeypatch, control_url, resolves_to, +) -> None: + """A pinned access token short-circuits ``cloud_session``'s own URL validation. + + ``access_for_workspace`` validates the control URL on the saved-session path but + returns immediately when ``ENGRAPHIS_CLOUD_ACCESS_TOKEN`` is configured, so this path + has to vet the endpoint itself before it attaches a credential to it. + """ + + monkeypatch.setattr(socket, "getaddrinfo", lambda host, port, *a, **k: [( + socket.AF_INET, socket.SOCK_STREAM, 6, "", (resolves_to, port or 0))]) + monkeypatch.setenv("ENGRAPHIS_CLOUD_ACCESS_TOKEN", "eyJ-scoped-access") + monkeypatch.setenv("ENGRAPHIS_CLOUD_ORGANIZATION_ID", ORGANIZATION) + monkeypatch.setenv("ENGRAPHIS_CLOUD_CONTROL_URL", control_url) + cloud = _FakeControlPlane(_entitlement_dto("team")) + _serve(monkeypatch, cloud) + monkeypatch.setattr( + urllib.request, "build_opener", + lambda *a, **k: pytest.fail("an unvetted opener was built for " + control_url), + ) + + assert v2_api._fetch_authoritative_entitlement() is None + assert cloud.requests == [] + + +def test_a_vetted_https_control_url_is_still_reached(monkeypatch) -> None: + """The guard above must reject bad endpoints without breaking the good one.""" + + _connect(monkeypatch) + monkeypatch.setenv("ENGRAPHIS_CLOUD_CONTROL_URL", CONTROL_URL + "/") + cloud = _FakeControlPlane(_entitlement_dto("team")) + _serve(monkeypatch, cloud) + + assert _settled_license(monkeypatch)["plan"] == "team" + assert [call["url"] for call in _entitlement_reads(cloud)] == [ + CONTROL_URL + "/v1/entitlements/" + ORGANIZATION + ] + + +@pytest.mark.parametrize("failure", [ + urllib.error.HTTPError(CONTROL_URL, 401, "unauthorized", {}, io.BytesIO(b"{}")), + urllib.error.HTTPError(CONTROL_URL, 402, "payment required", {}, io.BytesIO(b"{}")), + urllib.error.HTTPError(CONTROL_URL, 500, "server error", {}, io.BytesIO(b"{}")), + urllib.error.URLError("offline"), + TimeoutError("the read timed out"), + OSError("connection reset"), +]) +def test_a_cloud_failure_never_reaches_the_dashboard(monkeypatch, failure) -> None: + _connect(monkeypatch) + _serve(monkeypatch, _FakeControlPlane(error=failure)) + + payload = _settled_license(monkeypatch) + + assert payload["plan"] == "pro" # the connected fallback, not an exception + assert payload["features"] + assert v2_api._read_entitlement_cache() == {} + + +def test_an_unreadable_error_body_never_escapes_the_refresh_thread(monkeypatch) -> None: + """Draining an ``HTTPError`` body can itself raise; a sibling ``except`` misses it.""" + + class _Unreadable(io.BytesIO): + def read(self, *args, **kwargs): + raise TimeoutError("the read timed out") + + def close(self): + raise OSError("the socket was already reset") + + _connect(monkeypatch) + _serve(monkeypatch, _FakeControlPlane(error=urllib.error.HTTPError( + CONTROL_URL, 503, "unavailable", {}, _Unreadable()))) + + assert _settled_license(monkeypatch)["plan"] == "pro" + + +@pytest.mark.parametrize("body", [ + b"{not json", + b"[1, 2, 3]", + b"null", + # A truncated body must not coerce to "free, no access" and cache a paying customer + # as the free local core: ``plan`` and ``cloud_access_active`` are required fields. + b'{"organization_id": "org_paying_team"}', + b'{"organization_id":"org_paying_team","plan":"team"}', + b'{"organization_id":"org_paying_team","plan":"","cloud_access_active":true}', + b'{"organization_id":"org_paying_team","plan":7,"cloud_access_active":true}', + b'{"organization_id":"org_paying_team","plan":"team","cloud_access_active":"yes"}', + json.dumps(_entitlement_dto("team", organization_id="org_someone_else")).encode(), + b'{"organization_id":"org_paying_team","plan":"team","cloud_access_active":true,' + + b'"pad":"' + b"x" * 70_000 + b'"}', +]) +def test_a_malformed_or_misrouted_answer_never_relabels_the_plan(monkeypatch, body) -> None: + _connect(monkeypatch) + _serve(monkeypatch, _FakeControlPlane(raw=body)) + + payload = _settled_license(monkeypatch) + + assert payload["plan"] == "pro" + assert v2_api._read_entitlement_cache() == {} + + +# ── (3) offline: the cache is what keeps a paying customer correct ──────────── +def test_an_offline_client_still_boots_and_renders_its_last_known_plan( + monkeypatch, +) -> None: + _connect(monkeypatch) + _serve(monkeypatch, _FakeControlPlane(_entitlement_dto("team"))) + assert _settled_license(monkeypatch)["plan"] == "team" + + # Every route to the cloud now fails, exactly as it does on a plane. The zero interval + # guarantees a refresh is actually attempted (and fails) during the read below. + _serve(monkeypatch, _FakeControlPlane(error=urllib.error.URLError("offline"))) + monkeypatch.setattr(v2_api, "_ENTITLEMENT_REFRESH_SECONDS", 0) + started = time.monotonic() + payload = v2_api.get_license() + elapsed = time.monotonic() - started + _drain_refresh() + + assert elapsed < 1.0 + assert payload["plan"] == "team" + assert "team" in payload["features"] + assert payload["plan_source"] == "cloud" + # A failed refresh must not erase the last good answer. + assert v2_api._read_entitlement_cache()["plan"] == "team" + + +def test_the_real_boot_route_serves_a_connected_offline_client(monkeypatch, tmp_path) -> None: + """The whole point, over real HTTP: ``/api/bootstrap`` must render with no cloud.""" + + pytest.importorskip("fastapi", reason="full-stack extra not installed") + pytest.importorskip("httpx", reason="httpx not installed") + from fastapi.testclient import TestClient + + from engraphis.config import settings + + _connect(monkeypatch) + _serve(monkeypatch, _FakeControlPlane(_entitlement_dto("team"))) + assert _settled_license(monkeypatch)["plan"] == "team" + + # Now cut the cloud off entirely, as an aeroplane or a captive portal would, and let + # the boot path try (and fail) to refresh while it serves. + _serve(monkeypatch, _FakeControlPlane(error=urllib.error.URLError("offline"))) + monkeypatch.setattr(v2_api, "_ENTITLEMENT_REFRESH_SECONDS", 0) + monkeypatch.setattr(settings, "db_path", str(tmp_path / "boot.db")) + monkeypatch.setattr(settings, "embed_model", "") + monkeypatch.setattr(settings, "embed_dim", 384) + monkeypatch.setattr(settings, "allowed_workspaces", []) + monkeypatch.setattr(settings, "api_token", "") + monkeypatch.setattr(v2_api, "_service", None) + + from engraphis.dashboard_app import create_app + + with TestClient(create_app(), client=("127.0.0.1", 50000)) as client: + started = time.monotonic() + boot = client.get("/api/bootstrap") + elapsed = time.monotonic() - started + page = client.get("/") + + assert boot.status_code == 200 + assert page.status_code == 200 + assert elapsed < 5.0, "the boot route waited %.2fs on an unreachable cloud" % elapsed + license_state = boot.json()["license"] + assert license_state["plan"] == "team" + assert "team" in license_state["features"] + + +def test_an_offline_unconnected_client_is_the_free_local_core(monkeypatch) -> None: + _serve(monkeypatch, _FakeControlPlane(error=urllib.error.URLError("offline"))) + + payload = v2_api.get_license() + + assert payload["plan"] == "local" + assert payload["features"] == [] + assert payload["plan_source"] == "local" + + +def test_an_unconnected_installation_starts_no_background_work(monkeypatch) -> None: + """No session, no thread, no state written — an offline gate must stay quiet.""" + + before = threading.active_count() + + for _ in range(3): + assert v2_api.get_license()["plan"] == "local" + + assert threading.active_count() <= before + assert v2_api._entitlement_refreshing is False + assert v2_api._read_entitlement_cache() == {} + + +def test_a_connected_installation_with_no_control_url_starts_no_background_work( + monkeypatch, +) -> None: + """Nothing to dial means nothing to schedule.""" + + monkeypatch.setenv("ENGRAPHIS_CLOUD_ACCESS_TOKEN", "eyJ-scoped-access") + monkeypatch.setenv("ENGRAPHIS_CLOUD_ORGANIZATION_ID", ORGANIZATION) + monkeypatch.setattr(v2_api, "_ENTITLEMENT_REFRESH_SECONDS", 0) + + before = threading.active_count() + assert v2_api.get_license()["plan"] == "pro" + + assert threading.active_count() <= before + assert v2_api._entitlement_refreshing is False + + +def test_a_corrupt_cache_is_discarded_rather_than_downgrading_a_paying_customer( + monkeypatch, +) -> None: + """Coercing a damaged value would quietly relabel a paying customer as free.""" + + _connect(monkeypatch) + path = v2_api._entitlement_cache_path() + path.parent.mkdir(parents=True, exist_ok=True) + for blob in ("not json", + '{"schema": "someone-elses/v1", "plan": "team"}', + '{"schema": "engraphis-cloud-entitlement/v1", "plan": {"a": 1}}', + '{"schema": "engraphis-cloud-entitlement/v1", "plan": "enterprise"}'): + path.write_text(blob, encoding="utf-8") + + assert v2_api._read_entitlement_cache() == {} + assert v2_api._hosted_plan() == "pro" + + +def test_the_cache_is_written_owner_only_and_reread_across_processes( + monkeypatch, +) -> None: + """It lives beside the cloud session, so a partial or world-readable file is not ok.""" + + _connect(monkeypatch) + _serve(monkeypatch, _FakeControlPlane(_entitlement_dto("team"))) + _settled_license(monkeypatch) + + path = v2_api._entitlement_cache_path() + assert path.exists() + assert (path.stat().st_mode & 0o777) == 0o600 + saved = json.loads(path.read_text(encoding="utf-8")) + assert saved["schema"] == "engraphis-cloud-entitlement/v1" + assert saved["plan"] == "team" + assert saved["organization_id"] == ORGANIZATION + # No credential may be persisted alongside the presentation state. + assert "eyJ-scoped-access" not in path.read_text(encoding="utf-8") + + +def test_an_unwritable_state_directory_costs_freshness_not_the_dashboard( + monkeypatch, +) -> None: + def _refuse(*args, **kwargs): + raise OSError("read-only file system") + + monkeypatch.setattr("engraphis.private_state.atomic_private_text", _refuse) + _connect(monkeypatch) + _serve(monkeypatch, _FakeControlPlane(_entitlement_dto("team"))) + + payload = _settled_license(monkeypatch) + + assert payload["plan"] == "pro" + assert payload["features"] + + +# ── (4) refresh scheduling ──────────────────────────────────────────────────── +def test_only_one_refresh_is_ever_in_flight(monkeypatch) -> None: + _connect(monkeypatch) + release = threading.Event() + cloud = _FakeControlPlane(_entitlement_dto("team"), delay=release) + _serve(monkeypatch, cloud) + monkeypatch.setattr(v2_api, "_ENTITLEMENT_REFRESH_SECONDS", 0) + + try: + for _ in range(8): + v2_api.get_license() + deadline = time.monotonic() + 5.0 + while not cloud.requests and time.monotonic() < deadline: + time.sleep(0.005) + entitlement_reads = [ + call for call in cloud.requests if "/v1/entitlements/" in call["url"] + ] + assert len(entitlement_reads) == 1, entitlement_reads + finally: + release.set() + + +def test_a_fresh_cache_is_not_refetched(monkeypatch) -> None: + _connect(monkeypatch) + cloud = _FakeControlPlane(_entitlement_dto("team")) + _serve(monkeypatch, cloud) + _settled_license(monkeypatch) + reads = len([c for c in cloud.requests if "/v1/entitlements/" in c["url"]]) + + monkeypatch.setattr(v2_api, "_ENTITLEMENT_REFRESH_SECONDS", 3600) + for _ in range(5): + assert v2_api.get_license()["plan"] == "team" + _drain_refresh() + + assert len([c for c in cloud.requests if "/v1/entitlements/" in c["url"]]) == reads + + +def test_the_refresh_has_an_operator_kill_switch(monkeypatch) -> None: + _connect(monkeypatch) + cloud = _FakeControlPlane(_entitlement_dto("team")) + _serve(monkeypatch, cloud) + monkeypatch.setenv("ENGRAPHIS_CLOUD_ENTITLEMENT_REFRESH", "0") + monkeypatch.setattr(v2_api, "_ENTITLEMENT_REFRESH_SECONDS", 0) + + for _ in range(3): + assert v2_api.get_license()["plan"] == "pro" + _drain_refresh() + + assert cloud.requests == [] + + +def test_the_documented_kill_switch_and_override_are_in_the_example_config() -> None: + """P3: a config key the client reads must not be discoverable only from the source.""" + + example = (REPO_ROOT / ".env.example").read_text(encoding="utf-8") + + assert "ENGRAPHIS_CLOUD_PLAN=" in example + assert "ENGRAPHIS_CLOUD_ENTITLEMENT_REFRESH=" in example + # Both must be commented out: neither is required for a correct badge. + assert "\nENGRAPHIS_CLOUD_PLAN=" not in example + assert "\nENGRAPHIS_CLOUD_ENTITLEMENT_REFRESH=" not in example + # And ENGRAPHIS_CLOUD_PLAN must read as the escape hatch it now is, not as the way + # plans are normally resolved — that framing is what made it undiscoverable. + assert "ENGRAPHIS_CLOUD_PLAN is an override" in example + assert "The plan is resolved automatically" in example + + +# ── (4b) the plan now rides registration and refresh ────────────────────────── +# ``DeviceRegistrationResponse`` — returned by both ``/internal/devices/register`` and +# ``POST /v1/tokens/refresh`` — carries ``plan``, ``cloud_features`` and +# ``cloud_access_active``. The client consumes them instead of polling a second route for +# a fact those calls already deliver, while staying compatible with a cloud that omits them. +def _registration_entitlement(plan: str, *, active: bool = True) -> dict: + return { + "plan": plan, + "cloud_features": SERVER_PLAN_FEATURES[plan] if active else [], + "cloud_access_active": active, + } + + +def test_the_plan_arrives_on_the_refresh_the_client_already_makes(monkeypatch) -> None: + """The point of the change: one call, not two, and the answer is authoritative.""" + + _connect(monkeypatch, pinned_token=False) + cloud = _FakeControlPlane(_entitlement_dto("team"), + registration=_registration_entitlement("team")) + _serve(monkeypatch, cloud) + + payload = _settled_license(monkeypatch) + + assert payload["plan"] == "team" + assert payload["plan_source"] == "session" + assert "team" in payload["features"] + assert {"consolidation", "dreaming"} <= set(payload["features"]) + assert payload["cloud_access_active"] is True + assert payload["plan_checked_at"] > 0 + # The dedicated entitlements poll is redundant against this control plane and must not + # be made: the token refresh already answered. + assert _entitlement_reads(cloud) == [] + assert [call["url"] for call in cloud.requests] == [ + CONTROL_URL + "/v1/tokens/refresh" + ] + + +def test_registration_alone_makes_the_very_first_boot_correct(monkeypatch) -> None: + """Onboarding persists the plan, so boot needs no network to render Team.""" + + _connect(monkeypatch, pinned_token=False) + cloud_session.save_bootstrap( + dict({ + "refresh_credential": "engr_rt_bootstrap", + "organization_id": ORGANIZATION, + "installation_id": "inst_1", + "device_id": "dev_1", + "member_id": "mem_1", + "token_subject": "member", + }, **_registration_entitlement("team")), + control_url=CONTROL_URL, + compute_url=CONTROL_URL, + ) + cloud = _FakeControlPlane(_entitlement_dto("pro")) + _serve(monkeypatch, cloud) + + started = time.monotonic() + payload = v2_api.get_license() + elapsed = time.monotonic() - started + _drain_refresh() + + assert payload["plan"] == "team" + assert payload["plan_source"] == "session" + assert "team" in payload["features"] + # A just-registered answer is fresh, so boot touches the network not at all. + assert cloud.requests == [] + assert elapsed < 1.0 + + +def test_a_control_plane_without_the_new_fields_still_resolves_the_plan( + monkeypatch, +) -> None: + """The client must not require a newer server: the old route is the fallback.""" + + _connect(monkeypatch, pinned_token=False) + cloud = _FakeControlPlane(_entitlement_dto("team"), registration=None) + _serve(monkeypatch, cloud) + + payload = _settled_license(monkeypatch) + + assert payload["plan"] == "team" + assert payload["plan_source"] == "cloud" + assert "team" in payload["features"] + assert [call["url"] for call in _entitlement_reads(cloud)] == [ + CONTROL_URL + "/v1/entitlements/" + ORGANIZATION + ] + # Nothing was persisted onto the session, so the fallback stays in charge. + assert cloud_session.saved_entitlement() == {} + + +def test_a_field_less_refresh_never_erases_a_plan_the_cloud_already_declared( + monkeypatch, +) -> None: + """A rollback of the server change must not downgrade a paying customer.""" + + _connect(monkeypatch, pinned_token=False) + _serve(monkeypatch, _FakeControlPlane(_entitlement_dto("team"), + registration=_registration_entitlement("team"))) + assert _settled_license(monkeypatch)["plan"] == "team" + + _serve(monkeypatch, _FakeControlPlane(_entitlement_dto("team"), registration=None)) + cloud_session.access_for_workspace(None, require_compute=False) + + assert cloud_session.saved_entitlement()["plan"] == "team" + assert v2_api.get_license()["plan"] == "team" + + +def test_a_lapsed_subscription_declared_on_the_refresh_keeps_its_name( + monkeypatch, +) -> None: + _connect(monkeypatch, pinned_token=False) + _serve(monkeypatch, _FakeControlPlane( + _entitlement_dto("team", active=False), + registration=_registration_entitlement("team", active=False), + )) + + payload = _settled_license(monkeypatch) + + assert payload["plan"] == "team" + assert payload["features"] == [] + assert payload["cloud_access_active"] is False + + +def test_a_downgrade_to_free_is_reported_as_the_local_core(monkeypatch) -> None: + _connect(monkeypatch, pinned_token=False) + _serve(monkeypatch, _FakeControlPlane( + _entitlement_dto("free", active=False), + registration=_registration_entitlement("free", active=False), + )) + + payload = _settled_license(monkeypatch) + + assert payload["plan"] == "local" + assert payload["features"] == [] + + +@pytest.mark.parametrize("response", [ + {}, + {"plan": ""}, + {"plan": None}, + {"plan": 7}, + {"cloud_features": ["analytics"], "cloud_access_active": True}, +]) +def test_the_registration_entitlement_fields_are_optional(response) -> None: + """An older control plane omits them; a partial body must not invent an answer.""" + + assert cloud_session._declared_entitlement(response) == {} + + +def test_a_plan_without_an_activity_flag_is_not_treated_as_lapsed() -> None: + """Absent is not ``False``: defaulting it would re-lock a paying customer.""" + + declared = cloud_session._declared_entitlement({"plan": "Pro"}) + + assert declared["plan"] == "pro" + assert declared["cloud_access_active"] is True + assert "cloud_features" not in declared + assert cloud_session._declared_entitlement({"plan": "free"})[ + "cloud_access_active"] is False + + +def test_an_oversized_provider_entitlement_cannot_brick_the_saved_session() -> None: + """The session record is read back under a 64 KiB cap; a huge value must be bounded. + + Growing the file past that cap would make ``_load`` raise on every subsequent call and + take cloud access down with it, so the persisted presentation strings are trimmed. + """ + + declared = cloud_session._declared_entitlement({ + "plan": "team" + "x" * 100_000, + "cloud_features": ["f%d" % index + "y" * 10_000 for index in range(5_000)], + "cloud_access_active": True, + }) + + assert len(declared["plan"]) <= 64 + assert len(declared["cloud_features"]) <= 32 + assert all(len(feature) <= 64 for feature in declared["cloud_features"]) + assert len(json.dumps(declared)) < 8 * 1024 + + +def test_a_session_plan_for_another_organization_is_refused(monkeypatch) -> None: + """A pinned deployment may point at a different organization than it registered for. + + Serving the saved session's plan there would relabel one customer with another's. + """ + + _connect(monkeypatch, pinned_token=False) + _serve(monkeypatch, _FakeControlPlane(_entitlement_dto("team"), + registration=_registration_entitlement("team"))) + assert _settled_license(monkeypatch)["plan_source"] == "session" + + monkeypatch.setenv("ENGRAPHIS_CLOUD_ORGANIZATION_ID", "org_somebody_else") + + assert v2_api._session_entitlement() == {} + # Nothing was destroyed: the record is still correct for the organization it names. + monkeypatch.setenv("ENGRAPHIS_CLOUD_ORGANIZATION_ID", ORGANIZATION) + assert v2_api._session_entitlement()["plan"] == "team" + + +def test_an_unreadable_session_yields_no_entitlement_rather_than_raising( + monkeypatch, +) -> None: + """``saved_entitlement`` is on the boot path and may never raise.""" + + def _boom() -> dict: + raise cloud_session.CloudSessionError("unsafe state file", status=409) + + monkeypatch.setattr(cloud_session, "_load", _boom) + + assert cloud_session.saved_entitlement() == {} + assert v2_api._session_entitlement() == {} + + +# ── (5) precedence ──────────────────────────────────────────────────────────── +def test_the_session_plan_outranks_the_cached_entitlement(monkeypatch) -> None: + """Two persisted answers, one documented winner — never a silent disagreement.""" + + _connect(monkeypatch, pinned_token=False) + # The compatibility cache holds a stale Pro; the session holds the current Team. + v2_api._write_entitlement_cache({ + "plan": "pro", "features": v2_api.entitled_features("pro"), + "cloud_access_active": True, "organization_id": ORGANIZATION, + "fetched_at": time.time(), + }) + _serve(monkeypatch, _FakeControlPlane(_entitlement_dto("pro"), + registration=_registration_entitlement("team"))) + cloud_session.access_for_workspace(None, require_compute=False) + + payload = v2_api.get_license() + + assert payload["plan"] == "team" + assert payload["plan_source"] == "session" + assert "team" in payload["features"] + # The stale compatibility cache is untouched, simply outranked. + assert v2_api._read_entitlement_cache()["plan"] == "pro" + + +def test_the_environment_override_outranks_the_session_plan(monkeypatch) -> None: + _connect(monkeypatch, pinned_token=False) + _serve(monkeypatch, _FakeControlPlane(_entitlement_dto("team"), + registration=_registration_entitlement("team"))) + assert _settled_license(monkeypatch)["plan_source"] == "session" + + monkeypatch.setenv("ENGRAPHIS_CLOUD_PLAN", "pro") + payload = v2_api.get_license() + + assert payload["plan"] == "pro" + assert payload["plan_source"] == "environment" + + +def test_the_environment_override_outranks_the_cached_entitlement(monkeypatch) -> None: + """An air-gapped or pinned-token deployment must still be able to state its plan.""" + + _connect(monkeypatch) + _serve(monkeypatch, _FakeControlPlane(_entitlement_dto("pro"))) + assert _settled_license(monkeypatch)["plan"] == "pro" + + monkeypatch.setenv("ENGRAPHIS_CLOUD_PLAN", "team") + payload = v2_api.get_license() + + assert payload["plan"] == "team" + assert payload["plan_source"] == "environment" + assert "team" in payload["features"] + + +@pytest.mark.parametrize("declared,expected", [ + ("pro", "pro"), ("team", "team"), ("free", "local"), ("TEAM", "team"), (" pro ", "pro"), +]) +def test_the_override_vocabulary_is_unchanged(monkeypatch, declared, expected) -> None: + monkeypatch.setenv("ENGRAPHIS_CLOUD_PLAN", declared) + + assert v2_api._hosted_plan() == expected + + +def test_an_unrecognised_override_falls_through_instead_of_locking_a_customer_out( + monkeypatch, +) -> None: + _connect(monkeypatch) + _serve(monkeypatch, _FakeControlPlane(_entitlement_dto("team"))) + monkeypatch.setenv("ENGRAPHIS_CLOUD_PLAN", "enterprise") + + assert _settled_license(monkeypatch)["plan"] == "team" + + +# ── (6) the two license surfaces must agree ─────────────────────────────────── +def test_both_license_surfaces_report_the_same_plan(monkeypatch) -> None: + """P2: ``/memory/license`` hardcoded ``local`` while ``/api/license`` reported Team.""" + + import asyncio + + from engraphis.routes import memory as memory_routes + + _connect(monkeypatch) + _serve(monkeypatch, _FakeControlPlane(_entitlement_dto("team"))) + v2 = _settled_license(monkeypatch) + v1 = asyncio.new_event_loop().run_until_complete(memory_routes.get_license())["data"] + + assert v1["plan"] == v2["plan"] == "team" + assert v1["features"] == v2["features"] + assert "team" in v1["features"] + # The legacy envelope and its disclosure fields are unchanged. + assert v1["cloud_managed"] is True + assert v1["trial_seconds"] == 259_200 + assert v1["grace_seconds"] == 86_400 + assert v1["grace_extends_cloud_access"] is False + assert v1["upgrade_url"] + + +def test_the_legacy_surface_still_reports_local_for_an_unconnected_installation() -> None: + """The pinned v1 contract (tests/test_v1_licensing.py) describes *this* case.""" + + import asyncio + + from engraphis.routes import memory as memory_routes + + v1 = asyncio.new_event_loop().run_until_complete(memory_routes.get_license())["data"] + + assert v1["plan"] == "local" + assert v1["features"] == [] + + +# ── (7) the shipped modules must still build on the supported floor ─────────── +@pytest.mark.parametrize("relative", [ + "engraphis/routes/v2_api.py", + "engraphis/routes/memory.py", + "engraphis/cloud_session.py", +]) +def test_the_touched_modules_still_parse_on_python_39(relative) -> None: + ast.parse((REPO_ROOT / relative).read_text(encoding="utf-8"), feature_version=(3, 9)) diff --git a/tests/test_licensing_launch.py b/tests/test_licensing_launch.py new file mode 100644 index 0000000..4826e45 --- /dev/null +++ b/tests/test_licensing_launch.py @@ -0,0 +1,473 @@ +"""Launch guards for the paid-customer path: entitlement copy, secrets, and hangs. + +Every test here pins a behaviour a paying Pro/Team customer depends on at launch: + +* a lapsed or revoked subscription must be told how to fix billing, not shown an outage; +* an offline or flaky control plane must degrade to a retryable error, never a traceback + and never a permanent "your configuration is invalid"; +* a bearer token must not be renderable from a client object; and +* one caller-supplied timeout must bound the whole dial, not each resolved address. +""" +from __future__ import annotations + +import io +import json +import socket +import urllib.error + +import pytest + +from engraphis import cloud_features, cloud_session, hosted_client, licensing +from engraphis.cloud_features import CloudFeatureClient, CloudFeatureError +from engraphis.cloud_session import CloudSessionError + +# ── the private control plane's vocabulary, mirrored from (read-only) ────────── +# engraphis-cloud/engraphis_cloud/entitlements.py:20-28 and security.py:37-38. +# A mismatch here means a purchased feature silently never activates on the client. +SERVER_PLANS = {"free", "pro", "team"} +SERVER_PAID_PLANS = {"pro", "team"} +SERVER_PLAN_FEATURES = { + "free": set(), + "pro": {"analytics", "automation", "export", "sync"}, + "team": {"analytics", "automation", "export", "sync", "team"}, +} +SERVER_TRIAL_DURATION_SECONDS = 259_200 +SERVER_WORKSPACE_WRITE_GRACE_MAX_SECONDS = 86_400 + + +@pytest.fixture() +def _upgrade_url(monkeypatch): + monkeypatch.setenv("ENGRAPHIS_UPGRADE_URL", "https://account.example.test/billing") + monkeypatch.delenv("ENGRAPHIS_PRO_UPGRADE_URL", raising=False) + monkeypatch.delenv("ENGRAPHIS_TEAM_UPGRADE_URL", raising=False) + return "https://account.example.test/billing" + + +def _http_error(status: int, body: bytes = b"{}") -> urllib.error.HTTPError: + return urllib.error.HTTPError( + "https://control.example.test/v1/tokens/refresh", + status, + "failure", + {}, + io.BytesIO(body), + ) + + +def _opener_raising(error): + class _Opener: + def open(self, request, timeout=None): + raise error + + return lambda *handlers: _Opener() + + +# ── (c) credentials must never be renderable ────────────────────────────────── +def test_cloud_client_repr_never_renders_the_bearer_token() -> None: + """A dataclass __repr__ prints every field, so the token would reach any log.""" + + client = CloudFeatureClient( + "https://compute.example.test", "org_1", "eyJ-live-bearer-token" + ) + + assert "eyJ-live-bearer-token" not in repr(client) + assert "eyJ-live-bearer-token" not in str(client) + assert "eyJ-live-bearer-token" not in "%r" % (client,) + # The token is still carried; only its rendering is suppressed. + assert client.access_token == "eyJ-live-bearer-token" + + +def test_cloud_client_repr_keeps_the_non_secret_fields() -> None: + client = CloudFeatureClient("https://compute.example.test", "org_1", "token") + + assert "compute.example.test" in repr(client) + assert "org_1" in repr(client) + + +# ── (b) a flaky control plane must not produce a traceback ──────────────────── +def test_refresh_survives_an_error_body_that_fails_to_read(monkeypatch) -> None: + """Draining an HTTPError body can itself time out. + + A sibling ``except`` clause does not cover an exception raised inside the HTTPError + handler, so an unguarded ``exc.read()`` escaped as an unhandled traceback and became + an opaque dashboard 500 exactly when the cloud was flaky. + """ + + class _Unreadable(io.BytesIO): + def read(self, *args, **kwargs): + raise TimeoutError("the read timed out") + + def close(self): + raise OSError("the socket was already reset") + + error = urllib.error.HTTPError( + "https://control.example.test/v1/tokens/refresh", 500, "failure", {}, _Unreadable() + ) + monkeypatch.setattr( + cloud_session, "build_pinned_https_opener", _opener_raising(error) + ) + + with pytest.raises(CloudSessionError) as caught: + cloud_session._post_refresh("https://control.example.test", "r", "ws", "member") + + assert caught.value.status == 503 + + +@pytest.mark.parametrize("status", [400, 404, 409, 418, 500, 502, 503]) +def test_every_refresh_status_degrades_to_a_structured_error(monkeypatch, status) -> None: + monkeypatch.setattr( + cloud_session, "build_pinned_https_opener", _opener_raising(_http_error(status)) + ) + + with pytest.raises(CloudSessionError) as caught: + cloud_session._post_refresh("https://control.example.test", "r", "ws", "member") + + assert 400 <= caught.value.status <= 599 + + +def test_malformed_refresh_json_is_a_structured_error(monkeypatch) -> None: + class _Response: + def read(self, size): + return b"{not json" + + def __enter__(self): + return self + + def __exit__(self, *exc): + return False + + class _Opener: + def open(self, request, timeout=None): + return _Response() + + monkeypatch.setattr( + cloud_session, "build_pinned_https_opener", lambda *handlers: _Opener() + ) + + with pytest.raises(CloudSessionError, match="invalid session response"): + cloud_session._post_refresh("https://control.example.test", "r", "ws", "member") + + +@pytest.mark.parametrize( + "error", + [ + urllib.error.URLError(ConnectionRefusedError("connection refused")), + urllib.error.URLError(socket.gaierror("name resolution failed")), + TimeoutError("timed out"), + ], +) +def test_transport_failures_report_a_retryable_outage(monkeypatch, error) -> None: + monkeypatch.setattr( + cloud_session, "build_pinned_https_opener", _opener_raising(error) + ) + + with pytest.raises(CloudSessionError, match="temporarily unreachable"): + cloud_session._post_refresh("https://control.example.test", "r", "ws", "member") + + +# ── (a)/(6) billing and authorization copy must be actionable ───────────────── +def test_lapsed_subscription_is_not_reported_as_an_outage(monkeypatch, _upgrade_url): + """402 is the control plane's "no active paid entitlement". + + Reporting it with the generic 503 outage copy made a past_due customer retry forever + instead of being sent to the one page that restores their features. + """ + + monkeypatch.setattr( + cloud_session, "build_pinned_https_opener", _opener_raising(_http_error(402)) + ) + + with pytest.raises(CloudSessionError) as caught: + cloud_session._post_refresh("https://control.example.test", "r", "ws", "member") + + assert caught.value.status == 402 + assert _upgrade_url in str(caught.value) + assert "billing" in str(caught.value).lower() + + +@pytest.mark.parametrize("status", [401, 403]) +def test_revoked_session_still_asks_for_a_clean_reconnect(monkeypatch, status) -> None: + monkeypatch.setattr( + cloud_session, "build_pinned_https_opener", _opener_raising(_http_error(status)) + ) + + with pytest.raises(CloudSessionError, match="connect again") as caught: + cloud_session._post_refresh("https://control.example.test", "r", "ws", "member") + + assert caught.value.status == status + + +def test_rate_limited_refresh_keeps_its_own_status(monkeypatch) -> None: + monkeypatch.setattr( + cloud_session, "build_pinned_https_opener", _opener_raising(_http_error(429)) + ) + + with pytest.raises(CloudSessionError) as caught: + cloud_session._post_refresh("https://control.example.test", "r", "ws", "member") + + assert caught.value.status == 429 + assert "Try again shortly" in str(caught.value) + + +def test_unregistered_installation_is_a_reconnect_not_an_outage(monkeypatch) -> None: + """404 means the org/entitlement row is gone; retrying forever cannot fix that.""" + + monkeypatch.setattr( + cloud_session, "build_pinned_https_opener", _opener_raising(_http_error(404)) + ) + + with pytest.raises(CloudSessionError, match="connect again") as caught: + cloud_session._post_refresh("https://control.example.test", "r", "ws", "member") + + assert caught.value.status == 409 + + +def test_feature_gate_402_points_at_billing(_upgrade_url) -> None: + message, transient = cloud_features._public_http_error(402) + + assert _upgrade_url in message + assert transient is False + + +def test_untrusted_provider_bodies_are_still_never_reflected(monkeypatch) -> None: + secret = "provider-secret https://internal.service/trace" + error = urllib.error.HTTPError( + "https://compute.example.test/private", + 402, + "failure", + {}, + io.BytesIO(json.dumps({"detail": secret}).encode("utf-8")), + ) + + class _Opener: + def open(self, request, timeout): + raise error + + monkeypatch.setattr( + cloud_features.urllib.request, "build_opener", lambda *handlers: _Opener() + ) + client = CloudFeatureClient("https://compute.example.test", "org_1", "token") + + with pytest.raises(CloudFeatureError) as caught: + client._request("GET", "/private") + + assert secret not in str(caught.value) + assert caught.value.status == 402 + + +# ── (b) offline must not read as "your configuration is invalid" ────────────── +def _configure_cloud(monkeypatch) -> None: + monkeypatch.setenv("ENGRAPHIS_CLOUD_CONTROL_URL", "https://control.example.test") + monkeypatch.setenv("ENGRAPHIS_CLOUD_COMPUTE_URL", "https://compute.example.test") + monkeypatch.setenv("ENGRAPHIS_CLOUD_REFRESH_CREDENTIAL", "saved-refresh") + + +def test_offline_customer_gets_a_retryable_outage_not_a_config_error(monkeypatch): + """A broken resolver and a bad URL both raised ValueError from URL validation. + + The caller turned that into a permanent, non-retryable 409 "configuration is + invalid", which is wrong and unactionable for a paying customer on a plane. + """ + + _configure_cloud(monkeypatch) + + def _unresolvable(*args, **kwargs): + raise socket.gaierror("Name or service not known") + + monkeypatch.setattr(socket, "getaddrinfo", _unresolvable) + + with pytest.raises(CloudFeatureError) as caught: + CloudFeatureClient.from_environment("ws_1") + + assert caught.value.status == 503 + assert caught.value.transient is True + assert "configuration is invalid" not in str(caught.value) + + +def test_unresolvable_host_stays_a_value_error_for_direct_callers(monkeypatch) -> None: + """The new error narrows the type without breaking ``except ValueError`` callers.""" + + def _unresolvable(*args, **kwargs): + raise socket.gaierror("Name or service not known") + + monkeypatch.setattr(socket, "getaddrinfo", _unresolvable) + + assert issubclass(hosted_client.CloudUrlUnresolved, ValueError) + with pytest.raises(ValueError, match="could not be resolved"): + hosted_client.validate_cloud_base_url("https://cloud.example.test") + + +def test_a_genuinely_invalid_url_is_still_a_permanent_config_error(monkeypatch) -> None: + monkeypatch.setenv("ENGRAPHIS_CLOUD_CONTROL_URL", "ftp://control.example.test") + monkeypatch.setenv("ENGRAPHIS_CLOUD_COMPUTE_URL", "https://compute.example.test") + monkeypatch.setenv("ENGRAPHIS_CLOUD_REFRESH_CREDENTIAL", "saved-refresh") + + with pytest.raises(CloudFeatureError) as caught: + CloudFeatureClient.from_environment("ws_1") + + assert caught.value.status == 409 + + +@pytest.mark.parametrize( + ("status", "transient"), + [(401, False), (402, False), (409, False), (429, True), (503, True)], +) +def test_session_failures_carry_a_usable_retry_signal(monkeypatch, status, transient): + def _fail(*args, **kwargs): + raise CloudSessionError("private local state detail", status=status) + + monkeypatch.setattr(cloud_features, "access_for_workspace", _fail) + + with pytest.raises(CloudFeatureError) as caught: + CloudFeatureClient.from_environment("ws_1") + + assert caught.value.status == status + assert caught.value.transient is transient + # Session text can quote local state paths and must not cross this boundary. + assert "private local state detail" not in str(caught.value) + + +def test_unconnected_installation_is_told_to_connect(monkeypatch) -> None: + def _fail(*args, **kwargs): + raise CloudSessionError("connect first", status=401) + + monkeypatch.setattr(cloud_features, "access_for_workspace", _fail) + + with pytest.raises(CloudFeatureError, match="Connect this installation"): + CloudFeatureClient.from_environment("ws_1") + + +# ── (b) one timeout budget must bound the whole dial ────────────────────────── +def test_one_timeout_budget_is_shared_across_every_resolved_address(monkeypatch): + """Handing each vetted address the full timeout multiplied the stated budget. + + ``cloud_session`` dials while holding an exclusive cross-process refresh lock, so a + multi-homed endpoint that blackholes traffic stalled every worker for N x timeout. + """ + + addresses = ["93.184.216.34", "93.184.216.35", "93.184.216.36", "93.184.216.37"] + monkeypatch.setattr( + socket, + "getaddrinfo", + lambda *args, **kwargs: [ + (socket.AF_INET, socket.SOCK_STREAM, 6, "", (ip, 443)) for ip in addresses + ], + ) + + class _Clock: + now = 0.0 + + def monotonic(self): + return self.now + + clock = _Clock() + monkeypatch.setattr(hosted_client, "time", clock) + + handed = [] + + def _connect(address, timeout, source): + handed.append(timeout) + clock.now += timeout # a blackholed address burns its whole allowance + raise OSError("connection timed out") + + connection = hosted_client.PinnedHTTPSConnection("cloud.example", timeout=10.0) + connection._create_connection = _connect + + with pytest.raises(OSError): + connection.connect() + + assert handed, "the dial must attempt at least one vetted address" + assert sum(handed) <= 10.0 + hosted_client.MIN_ATTEMPT_TIMEOUT_SECONDS + assert len(handed) < len(addresses) + + +def test_a_fast_failure_still_tries_every_vetted_address(monkeypatch) -> None: + """Bounding the budget must not cost the existing dual-stack failover.""" + + monkeypatch.setattr( + socket, + "getaddrinfo", + lambda *args, **kwargs: [ + (socket.AF_INET6, socket.SOCK_STREAM, 6, "", ("2606:2800:220:1::1", 443)), + (socket.AF_INET, socket.SOCK_STREAM, 6, "", ("93.184.216.34", 443)), + ], + ) + tried = [] + + class _Context: + def wrap_socket(self, sock, *, server_hostname): + return sock + + def _connect(address, timeout, source): + tried.append(address[0]) + if ":" in address[0]: + raise OSError("IPv6 route is unavailable") + return object() + + connection = hosted_client.PinnedHTTPSConnection("cloud.example", timeout=10.0) + connection._context = _Context() + connection._create_connection = _connect + + connection.connect() + + assert tried == ["2606:2800:220:1::1", "93.184.216.34"] + + +def test_pinned_connection_never_inherits_a_blocking_default() -> None: + """urllib supplies ``_GLOBAL_DEFAULT_TIMEOUT`` when a caller omits ``timeout=``.""" + + default = hosted_client.DEFAULT_CONNECT_TIMEOUT_SECONDS + + assert hosted_client.PinnedHTTPSConnection("cloud.example").timeout == default + assert hosted_client.PinnedHTTPSConnection( + "cloud.example", timeout=None + ).timeout == default + assert hosted_client.PinnedHTTPSConnection( + "cloud.example", timeout=socket._GLOBAL_DEFAULT_TIMEOUT + ).timeout == default + # An explicit budget is still honoured exactly. + assert hosted_client.PinnedHTTPSConnection( + "cloud.example", timeout=7.5 + ).timeout == 7.5 + + +# ── (d) plan drift against the private control plane ────────────────────────── +def test_client_plan_names_match_the_control_plane() -> None: + from engraphis.commercial import expected_checkout_targets, manifest + + assert set(manifest()["plans"]) == SERVER_PLANS + assert {plan for plan, _ in expected_checkout_targets()} == SERVER_PAID_PLANS + + +def test_every_server_feature_key_advertises_the_plan_that_grants_it() -> None: + """A feature the server grants only to Team must not advertise Pro, and vice versa.""" + + for feature in sorted(SERVER_PLAN_FEATURES["team"]): + granted_by_pro = feature in SERVER_PLAN_FEATURES["pro"] + expected = "pro" if granted_by_pro else "team" + assert licensing.required_plan(feature) == expected, feature + assert licensing.required_plan(feature) in SERVER_PAID_PLANS + + +def test_plan_lookups_are_case_and_whitespace_insensitive(_upgrade_url, monkeypatch): + """The control plane emits lowercase plans; a caller must not be able to drift.""" + + monkeypatch.setenv("ENGRAPHIS_TEAM_UPGRADE_URL", "https://account.example.test/team") + + for spelling in ("team", "Team", "TEAM", " team "): + assert licensing.required_plan(spelling) == "team" + assert licensing.upgrade_url(spelling) == "https://account.example.test/team" + for spelling in ("sync", "Sync", " SYNC "): + assert licensing.required_plan(spelling) == "pro" + + +def test_trial_and_grace_windows_match_the_control_plane() -> None: + assert licensing.TRIAL_SECONDS == SERVER_TRIAL_DURATION_SECONDS + assert ( + licensing.MAX_LOCAL_WRITE_GRACE_SECONDS + == SERVER_WORKSPACE_WRITE_GRACE_MAX_SECONDS + ) + + +def test_unknown_features_never_advertise_a_plan_the_server_cannot_sell() -> None: + for feature in ("", " ", "not-a-real-feature", None): + assert licensing.required_plan(feature) in SERVER_PAID_PLANS From b35a48de6ef15d49d08c820dbbd504f2ec01b7ff Mon Sep 17 00:00:00 2001 From: Jaixii Date: Sun, 26 Jul 2026 01:41:25 +0000 Subject: [PATCH 02/82] fix(tests): skip FastAPI-dependent launch tests on the numpy-only core floor tests/test_client_launch.py and tests/test_hosted_plan_resolution.py import engraphis.routes.v2_api, which imports FastAPI. The core-py39 CI job installs numpy and pytest only, so both modules raised ModuleNotFoundError at collection and interrupted the whole run rather than skipping. Guard both with pytest.importorskip("fastapi"), matching the convention already used by tests/test_agent_connect.py and tests/test_app_auth.py. Verified against a numpy+pytest-only virtualenv: the suite collects and passes with these two modules skipped, and the full extras install is unchanged at 1363 passed, 7 skipped. --- tests/test_client_launch.py | 8 ++++++-- tests/test_hosted_plan_resolution.py | 8 ++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/tests/test_client_launch.py b/tests/test_client_launch.py index 28ef100..1a6abd6 100644 --- a/tests/test_client_launch.py +++ b/tests/test_client_launch.py @@ -29,8 +29,12 @@ import pytest -from engraphis import update_check -from engraphis.routes import v2_api +# ``engraphis.routes.v2_api`` imports FastAPI, which the numpy-only core floor job does not +# install. Skip rather than error at collection, matching the rest of the suite. +pytest.importorskip("fastapi", reason="full-stack extra not installed") + +from engraphis import update_check # noqa: E402 +from engraphis.routes import v2_api # noqa: E402 REPO_ROOT = Path(__file__).resolve().parents[1] UPDATER = REPO_ROOT / "scripts" / "update.py" diff --git a/tests/test_hosted_plan_resolution.py b/tests/test_hosted_plan_resolution.py index 77ee5d4..d00330b 100644 --- a/tests/test_hosted_plan_resolution.py +++ b/tests/test_hosted_plan_resolution.py @@ -34,8 +34,12 @@ import pytest -from engraphis import cloud_session -from engraphis.routes import v2_api +# ``engraphis.routes.v2_api`` imports FastAPI, which the numpy-only core floor job does not +# install. Skip rather than error at collection, matching the rest of the suite. +pytest.importorskip("fastapi", reason="full-stack extra not installed") + +from engraphis import cloud_session # noqa: E402 +from engraphis.routes import v2_api # noqa: E402 REPO_ROOT = Path(__file__).resolve().parents[1] DASHBOARD_JS = REPO_ROOT / "engraphis" / "static" / "dashboard.js" From b28417327ec3ee9aa9ce188c8db7889a7c490e79 Mon Sep 17 00:00:00 2001 From: Jaixii Date: Sat, 25 Jul 2026 22:56:28 -0400 Subject: [PATCH 03/82] test: make licensing launch coverage portable --- tests/test_hosted_plan_resolution.py | 23 ++++++++++++++++++++++- tests/test_licensing_launch.py | 6 ++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/tests/test_hosted_plan_resolution.py b/tests/test_hosted_plan_resolution.py index d00330b..3b87423 100644 --- a/tests/test_hosted_plan_resolution.py +++ b/tests/test_hosted_plan_resolution.py @@ -24,6 +24,7 @@ import ast import io import json +import os import re import socket import threading @@ -446,6 +447,11 @@ def read(self, *args, **kwargs): raise TimeoutError("the read timed out") def close(self): + if self.closed: + return + # Model a reset after the descriptor was released so this deliberate + # cleanup failure does not recur from BytesIO's finalizer as a warning. + super().close() raise OSError("the socket was already reset") _connect(monkeypatch) @@ -469,6 +475,17 @@ def close(self): json.dumps(_entitlement_dto("team", organization_id="org_someone_else")).encode(), b'{"organization_id":"org_paying_team","plan":"team","cloud_access_active":true,' + b'"pad":"' + b"x" * 70_000 + b'"}', +], ids=[ + "invalid-json", + "array", + "null", + "incomplete", + "missing-activity", + "empty-plan", + "numeric-plan", + "nonboolean-activity", + "wrong-organization", + "oversized", ]) def test_a_malformed_or_misrouted_answer_never_relabels_the_plan(monkeypatch, body) -> None: _connect(monkeypatch) @@ -613,7 +630,11 @@ def test_the_cache_is_written_owner_only_and_reread_across_processes( path = v2_api._entitlement_cache_path() assert path.exists() - assert (path.stat().st_mode & 0o777) == 0o600 + # Windows does not project ACLs through POSIX mode bits. The private-state helper + # still uses its race-safe write/read path there, but only POSIX can prove owner-only + # access with this portable ``st_mode`` check. + if os.name != "nt": + assert (path.stat().st_mode & 0o777) == 0o600 saved = json.loads(path.read_text(encoding="utf-8")) assert saved["schema"] == "engraphis-cloud-entitlement/v1" assert saved["plan"] == "team" diff --git a/tests/test_licensing_launch.py b/tests/test_licensing_launch.py index 4826e45..a129618 100644 --- a/tests/test_licensing_launch.py +++ b/tests/test_licensing_launch.py @@ -97,6 +97,12 @@ def read(self, *args, **kwargs): raise TimeoutError("the read timed out") def close(self): + if self.closed: + return + # Model a reset after the descriptor was released. Leaving BytesIO open + # would make its finalizer repeat the synthetic failure as an unraisable + # warning after the behaviour under test has already handled it. + super().close() raise OSError("the socket was already reset") error = urllib.error.HTTPError( From 09d44826ddb3ca0e768e017f7c07ccfc0e0bfdbb Mon Sep 17 00:00:00 2001 From: Jaixii Date: Sun, 26 Jul 2026 04:13:34 -0400 Subject: [PATCH 04/82] feat(cloud): carry managed-compute consent on the cloud account Customers were told to hand-edit ENGRAPHIS_MANAGED_COMPUTE_CONSENT=1 in a .env file before Analytics or Automation would work. Consent now travels with the cloud account: connecting an installation accepts the terms that cover managed compute, so a connected installation is allowed by default and the variable is never shown to a user. An installation with no cloud session is still never allowed -- there is no account, so there is no agreement to rely on. The variable survives as an operator override only; =0 opts a connected installation back out. Also fixes two predicates that were inverted against their own comment. managedConsentRequired() was guarded on CURRENT_VIEW!=='analytics' && CURRENT_VIEW!=='automation', but its only four call sites run in exactly those two views, so it could never return true. hostedFeatureUnavailable() returned true for any error in those views regardless of status. Together a paying Pro customer hitting a 409, a 500, or a dropped connection was shown a panel selling Pro -- the exact regression the comment above them describes. Both are now status-only. The upload disclosure is deliberately kept: what is uploaded, the 16 MiB cap, and that it travels over HTTPS without end-to-end encryption. Two tests asserted the defect as intended behaviour and are replaced; the weakened predicate assertion is restored and mutation-tested. Co-Authored-By: Claude Opus 5 (1M context) --- .env.example | 14 ++-- CHANGELOG.md | 10 ++- README.md | 22 ++++--- SECURITY.md | 11 +++- deploy/railway-template.json | 4 +- docs/HOSTING_RAILWAY.md | 8 ++- docs/RAILWAY_TEMPLATE.md | 7 +- engraphis/cloud_features.py | 33 +++++++--- engraphis/static/dashboard.js | 21 +++--- tests/e2e/commercial.spec.js | 22 ++++--- tests/test_cloud_features.py | 82 +++++++++++++++++++++++- tests/test_dashboard_auth_placement.py | 88 +++++++++++++++++++------- tests/test_dashboard_dream_ui.py | 4 +- tests/test_dashboard_v2.py | 5 +- tests/test_packaging.py | 5 +- tests/test_release_infrastructure.py | 5 +- 16 files changed, 262 insertions(+), 79 deletions(-) diff --git a/.env.example b/.env.example index 5d9e504..7be5648 100644 --- a/.env.example +++ b/.env.example @@ -191,11 +191,15 @@ ENGRAPHIS_LLM_API_KEY=sk-your-key-here # Hosted entitlements may report a separate local-only write grace capped at 24 hours. # It never extends the exact 3-day trial, subscription expiry, or any cloud access. -# Managed compute consent. Set to 1 to allow the open package to upload workspace -# snapshots to the Engraphis Cloud service for managed analytics, dreaming, and -# consolidation. Without this flag, managed compute is off and no cloud upload -# occurs. The cloud service is authoritative for all paid computation. -# ENGRAPHIS_MANAGED_COMPUTE_CONSENT=1 +# Managed compute consent is decided automatically and needs no customer action: a +# local-only installation (no cloud session) is never allowed to upload workspace +# snapshots, while an installation connected to Engraphis Cloud is allowed by default, +# because connecting already accepts the terms covering managed analytics, dreaming, and +# consolidation. This variable is an explicit operator override, not a customer-facing +# setting — set it to 0 to opt a connected installation back out, or to 1 to force +# managed compute on regardless of session state. The cloud service remains authoritative +# for all paid computation. +# ENGRAPHIS_MANAGED_COMPUTE_CONSENT=0 # Optional credential-redacted JSON logs for hosted customer deployments. # ENGRAPHIS_JSON_LOGS=1 diff --git a/CHANGELOG.md b/CHANGELOG.md index f579b37..0295e83 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,15 @@ All notable changes to Engraphis are documented here. Format loosely follows ## [Unreleased] -No unreleased changes. +### Changed + +- Managed compute consent now travels with the cloud account: an installation connected to + Engraphis Cloud is enabled for managed analytics, dreaming, and consolidation **by + default**, because connecting already accepts the terms that cover it. A local-only + installation with no cloud session is still never allowed. + `ENGRAPHIS_MANAGED_COMPUTE_CONSENT` remains as an explicit operator override (`=0` opts a + connected installation back out, `=1` forces it on regardless of session state) and is no + longer surfaced anywhere in the UI. ## [1.0.1] - 2026-07-24 diff --git a/README.md b/README.md index 592ce25..152330f 100644 --- a/README.md +++ b/README.md @@ -68,10 +68,14 @@ a color palette and layout preset; or change the colors used for each type of no ### Managed compute The open package can upload bounded workspace snapshots to the Engraphis Cloud service -for managed analytics, dreaming, and consolidation. This is **off by default** and -requires explicit opt-in by setting `ENGRAPHIS_MANAGED_COMPUTE_CONSENT=1`. The cloud -service is authoritative for all paid computation; no local setting turns this package -into a compute worker or relay. +for managed analytics, dreaming, and consolidation. A local-only installation with no +cloud session is **never** allowed to upload. Connecting an installation to Engraphis +Cloud accepts the terms that cover managed compute, so a **connected installation is +enabled by default** — there is no separate opt-in step to complete. +`ENGRAPHIS_MANAGED_COMPUTE_CONSENT` remains as an operator override (`=0` opts a +connected installation back out, `=1` forces it on); it is not a customer-facing +setting. The cloud service is authoritative for all paid computation; no local setting +turns this package into a compute worker or relay. The dashboard is powered by the v2 engine — the same `MemoryService` that backs the MCP server and the Python library. What you see in the UI is what your agents get. @@ -616,9 +620,11 @@ background loop, cron wrapper, or worker. Secret-class and session-scoped memories are excluded before a managed snapshot is serialized; secret-class rows are rejected again by the hosted service. The encoded payload is capped at -16 MiB. Managed compute remains off until the customer explicitly sets -`ENGRAPHIS_MANAGED_COMPUTE_CONSENT=1`; cloud entitlement is also required. A managed proposal -never silently rewrites the local database. +16 MiB and travels over HTTPS without end-to-end encryption. Managed compute is enabled by +default once an installation is connected to Engraphis Cloud — connecting accepts the terms +that cover it — and stays off for a local-only installation with no cloud session; cloud +entitlement is also required. `ENGRAPHIS_MANAGED_COMPUTE_CONSENT=0` opts a connected +installation back out. A managed proposal never silently rewrites the local database. Manual consolidation can also use schema-validated LLM output through `MemoryService.consolidate`, `POST /api/consolidate`, `engraphis_consolidate`, or @@ -667,7 +673,7 @@ All via environment (or `.env`): | `ENGRAPHIS_CLOUD_REFRESH_CREDENTIAL` | — | Bootstrap-only rotating hosted credential; after first use the owner-only cloud session replacement takes precedence | | `ENGRAPHIS_CLOUD_TOKEN_SUBJECT` | `member` | Subject fixed during hosted bootstrap (`device` or `member`); set explicitly with an environment-only refresh credential | | `ENGRAPHIS_CLOUD_ACCESS_TOKEN` | — | Optional short-lived access token for ephemeral jobs | -| `ENGRAPHIS_MANAGED_COMPUTE_CONSENT` | `0` | Explicitly set to `1` before uploading a bounded workspace snapshot for hosted Analytics or Automation | +| `ENGRAPHIS_MANAGED_COMPUTE_CONSENT` | *(auto)* | Operator override only; default follows whether a cloud session is configured (connected = allowed, local-only = never). `0` opts a connected installation out, `1` forces it on | See `.env.example` for the full customer-runtime and managed-service client options. diff --git a/SECURITY.md b/SECURITY.md index 4b617a9..d278e23 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -115,9 +115,14 @@ them back as `expected_head` / `expected_count` when independent evidence is req - **Server authority:** every hosted and cost-bearing operation is authorized by the private control plane; local plan labels and upgrade URLs are presentation metadata only. - **Managed-compute consent:** Analytics, Auto Dreaming, and Auto Consolidation upload a - bounded snapshot only after explicit customer opt-in via - `ENGRAPHIS_MANAGED_COMPUTE_CONSENT=1`. Secret-class memories are excluded before - serialization and rejected again by the hosted service. + bounded snapshot. Consent travels with the cloud account: connecting an installation to + Engraphis Cloud accepts the terms covering managed compute, so a connected installation is + allowed and an installation with no cloud session is never allowed. Operators may override + with `ENGRAPHIS_MANAGED_COMPUTE_CONSENT` (`0` opts a connected installation back out). + The snapshot carries normal and sensitive memory content, excludes secret-class and + session-scoped rows, is capped at 16 MiB, and travels over HTTPS without end-to-end + encryption. Secret-class memories are excluded before serialization and rejected again by + the hosted service. - **Trial and grace are separate:** an email-confirmed trial lasts exactly 3 active days. A separately bounded, maximum-24-hour local workspace-write grace never extends the trial, subscription, Cloud Sync, managed compute, Team access, seats, or credentials. diff --git a/deploy/railway-template.json b/deploy/railway-template.json index b2b83e3..a66fa4b 100644 --- a/deploy/railway-template.json +++ b/deploy/railway-template.json @@ -50,8 +50,8 @@ "required": false }, "ENGRAPHIS_MANAGED_COMPUTE_CONSENT": { - "value": "0", - "prompt": "Change to 1 only after reviewing the managed snapshot upload boundary.", + "value": "", + "prompt": "Optional override. Leave blank: managed compute follows the cloud account, so a connected deployment is allowed and a local-only one is not. Set 0 to opt this deployment out.", "required": false } } diff --git a/docs/HOSTING_RAILWAY.md b/docs/HOSTING_RAILWAY.md index afd094f..5cf510d 100644 --- a/docs/HOSTING_RAILWAY.md +++ b/docs/HOSTING_RAILWAY.md @@ -39,9 +39,11 @@ ENGRAPHIS_CLOUD_REFRESH_CREDENTIAL= Prefer mounting the owner-only cloud session file rather than placing a rotating refresh credential directly in deployment configuration. An injected environment credential is only the -bootstrap value; after rotation, the owner-only saved replacement takes precedence. Enabling -managed compute for an authorized customer may upload a snapshot capped at 16 MiB; secret-class -and session-scoped rows are excluded client-side, and secret-class rows are rejected server-side. +bootstrap value; after rotation, the owner-only saved replacement takes precedence. Once +connected, managed compute is enabled by default for an authorized customer and may upload a +snapshot capped at 16 MiB over HTTPS without end-to-end encryption; secret-class and +session-scoped rows are excluded client-side, and secret-class rows are rejected server-side. +Set `ENGRAPHIS_MANAGED_COMPUTE_CONSENT=0` to opt the deployed installation back out. ## Persistence and recovery diff --git a/docs/RAILWAY_TEMPLATE.md b/docs/RAILWAY_TEMPLATE.md index 0c2cf8f..d9a7000 100644 --- a/docs/RAILWAY_TEMPLATE.md +++ b/docs/RAILWAY_TEMPLATE.md @@ -14,8 +14,11 @@ issuer, relay, managed compute, Auto Dreaming, Auto Consolidation, or Team ident - No vendor signer, billing, mail, Team-admin, relay-storage, or worker secrets. Hosted customer endpoint variables may be exposed as optional inputs, but a refresh credential -must be injected as a secret or mounted owner-only state file. Managed compute requires -explicit opt-in via `ENGRAPHIS_MANAGED_COMPUTE_CONSENT=1`. +must be injected as a secret or mounted owner-only state file. Managed compute is enabled by +default once the deployed installation is connected to Engraphis Cloud; connecting accepts the +terms that cover it, and a local-only node with no cloud session is never allowed. Expose +`ENGRAPHIS_MANAGED_COMPUTE_CONSENT` only as an optional operator override (`0` to opt a +connected installation back out), not as a required opt-in input. ## Publish gate diff --git a/engraphis/cloud_features.py b/engraphis/cloud_features.py index 64c7984..2c27c63 100644 --- a/engraphis/cloud_features.py +++ b/engraphis/cloud_features.py @@ -19,6 +19,7 @@ from urllib.parse import quote from engraphis.cloud_session import CloudSessionError, access_for_workspace +from engraphis.cloud_session import configured as cloud_session_configured from engraphis.hosted_client import build_pinned_https_opener, upgrade_url SNAPSHOT_SCHEMA = "engraphis-managed-snapshot/v1" @@ -49,13 +50,26 @@ def redirect_request(self, req, fp, code, msg, headers, newurl): def managed_compute_consent() -> bool: - """Return whether the customer explicitly enabled managed snapshot uploads. + """Return whether this installation may upload workspace content for managed work. - Entitlement is enforced by the cloud service, but it is not consent to upload local - workspace content. The public client therefore remains off unless the customer sets - ``ENGRAPHIS_MANAGED_COMPUTE_CONSENT=1``. + Consent travels with the cloud account: connecting an installation to Engraphis Cloud + accepts the terms that cover managed compute, so a connected installation is allowed by + default and the customer is never asked to hand-edit an environment variable. + + A local installation with no cloud session is never allowed — there is no account, so + there is no agreement to rely on. + + ``ENGRAPHIS_MANAGED_COMPUTE_CONSENT`` remains an explicit override for operators who want + to force the answer either way; ``=0`` opts a connected installation back out. """ - return _truthy(os.environ.get("ENGRAPHIS_MANAGED_COMPUTE_CONSENT")) + override = os.environ.get("ENGRAPHIS_MANAGED_COMPUTE_CONSENT") + if override is not None and override.strip() != "": + return _truthy(override) + try: + return bool(cloud_session_configured(require_compute=False)) + except Exception: + # Consent must never be the reason a dashboard fails to render. + return False def _public_http_error(status: int) -> tuple[str, bool]: @@ -235,8 +249,9 @@ def _build_managed_snapshot_locked(service: Any, workspace: str, *, """Build the bounded client-side transport document for one local workspace. Secret-classified rows are omitted before serialization. ``consent`` allows an - already-confirmed caller to pass its decision explicitly; otherwise the environment - opt-in is required. + already-confirmed caller to pass its decision explicitly; otherwise + :func:`managed_compute_consent` decides, which allows cloud-connected installations and + denies purely local ones. """ clean_workspace = service._clean_ws(workspace) @@ -246,8 +261,8 @@ def _build_managed_snapshot_locked(service: Any, workspace: str, *, allowed = managed_compute_consent() if consent is None else bool(consent) if not allowed: raise CloudFeatureError( - "Managed compute is off. Opt in before uploading workspace content by setting " - "ENGRAPHIS_MANAGED_COMPUTE_CONSENT=1.", + "Managed compute is turned off for this installation, so no workspace content " + "was uploaded. Connect this installation to Engraphis Cloud to use it.", status=409, code="consent_required", ) diff --git a/engraphis/static/dashboard.js b/engraphis/static/dashboard.js index d9264f0..a45916c 100644 --- a/engraphis/static/dashboard.js +++ b/engraphis/static/dashboard.js @@ -183,24 +183,27 @@ function updateFeatureLocks(){ function barRow(label,val,peak,color){const tone=color==='var(--green)'?' analytics-bar-green':(color==='var(--blue)'?' analytics-bar-blue':(color==='var(--cyan)'?' analytics-bar-cyan':(color==='var(--accent-dim)'?' analytics-bar-dim':'')));return `
${esc(label)}
${val}
`} function statMini(v,l,color){const tone=color==='var(--red)'?' tone-red':(color==='var(--amber)'?' tone-amber':(color==='var(--green)'?' tone-green':''));return `
${v}
${esc(l)}
`} function renderAnalytics(a,isPortfolio){const t=a.totals||{},f=a.decay_forecast||{};const weeks=a.growth_weekly||[];const gp=Math.max(...weeks,1);const gitems=weeks.map((n,i)=>{const back=weeks.length-1-i;return barRow(back===0?'now':back+'w ago',n,gp,'var(--accent-dim)')}).join('')||'
No data
';const hist=a.retention_histogram||{};const hc=hist.counts||[],hb=hist.buckets||[];const hp=Math.max(...hc,1);const hitems=hb.map((b,i)=>barRow(b,hc[i]||0,hp,'var(--green)')).join('');const mix=a.resolver_mix||{};const mk=Object.keys(mix);const mp=Math.max(...Object.values(mix),1);const mitems=mk.length?mk.map(k=>barRow(k,mix[k],mp,'var(--blue)')).join(''):'
No resolver events yet.
';const bt=a.by_type||{};const btk=Object.keys(bt);const bp=Math.max(...Object.values(bt),1);const btitems=btk.length?btk.map(k=>barRow(k,bt[k],bp,'var(--accent)')).join(''):'
No memories yet.
';const ents=a.top_entities||[];const ep=Math.max(...ents.map(e=>e.n),1);const eitems=ents.length?ents.map(e=>barRow(e.name+(isPortfolio&&e.workspace?' · '+e.workspace:''),e.n,ep,'var(--cyan)')).join(''):'
No entities yet — they appear as the graph grows.
';const avg=Math.round((t.avg_retention||0)*100);let wsTable='';if(isPortfolio&&a.workspaces){wsTable=`
Per-workspace breakdown
${a.workspaces.map(w=>``).join('')}
WorkspaceLivePinnedAvg ret.Fading 7d
${esc(w.workspace)}${w.live}${w.pinned}${Math.round((w.avg_retention||0)*100)}%${w.at_risk_7d}
`}return `
${statMini(t.live!=null?t.live:'—','Live memories')}${statMini(avg+'%','Avg retention',avg<40?'var(--red)':(avg<70?'var(--amber)':'var(--green)'))}${statMini(f.at_risk_7d!=null?f.at_risk_7d:'—','Fading ≤ 7 days',f.at_risk_7d>0?'var(--amber)':'')}${statMini(f.at_risk_30d!=null?f.at_risk_30d:'—','Fading ≤ 30 days')}${statMini(t.pinned!=null?t.pinned:'—','Pinned (protected)')}${isPortfolio?statMini(t.workspaces||0,'Workspaces'):statMini(t.superseded!=null?t.superseded:'—','Superseded (history)')}
Memories written per week
${gitems}
Retention distribution
${hitems}
By type
${btitems}
Write-path resolver activity
${mitems}
Most connected entities
${eitems}
${wsTable}`} -function managedConsentHtml(feature){return `
${esc(feature)} needs your explicit permission before this installation uploads a bounded workspace snapshot.
Set ENGRAPHIS_MANAGED_COMPUTE_CONSENT=1 in .env, then restart Engraphis. Secret and session-scoped memories remain excluded.
`} -function managedConsentRequired(error){return error&&CURRENT_VIEW!=='analytics'&&CURRENT_VIEW!=='automation'&&error.status===409&&error.detail&&error.detail.code==='consent_required'} +function managedConsentHtml(feature){return `
${esc(feature)} runs in Engraphis Cloud, and managed compute is turned off for this installation.
Connect this installation to Engraphis Cloud to enable it. Secret and session-scoped memories are never uploaded.
`} +function managedConsentRequired(error){return error&&error.status===409&&error.detail&&error.detail.code==='consent_required'} /* Entitlement failure — and only that. 401 unauthenticated, 402 subscription not active, 501 feature not offered here: each means the customer's plan does not include what they just opened, so each may draw the purchase panel. 409 is deliberately NOT here. Every 409 this API emits is a *conflict*, never a billing - answer: detail.code==='consent_required' means the customer IS entitled but has not set - ENGRAPHIS_MANAGED_COMPUTE_CONSENT=1 (managedConsentRequired, above), and the rest are + answer: detail.code==='consent_required' means the customer IS entitled but managed + compute is off for this installation (managedConsentRequired, above), and the rest are transient state conflicts (snapshot generation, cloud session state, rebuilding index). Counting any of them as "unpaid" showed a paying Pro customer a panel selling Pro, so - every caller routes managedConsentRequired first and this second. */ -function hostedFeatureUnavailable(error){return !!error&&((CURRENT_VIEW==='analytics'||CURRENT_VIEW==='automation')||error.status===401||error.status===402||error.status===501)} + every caller routes managedConsentRequired first and this second. + Neither predicate may branch on CURRENT_VIEW: doing so made both the consent branch and + the plain-error branch unreachable on the analytics and automation views, which is the + regression this comment previously described but the code did not implement. */ +function hostedFeatureUnavailable(error){return !!error&&(error.status===401||error.status===402||error.status===501)} async function loadAnalytics(){const el=document.getElementById('analytics-body'),lock=document.getElementById('an-lock'),acts=document.getElementById('an-actions');el.innerHTML='
';try{const a=await api('/analytics?workspace='+encodeURIComponent(WS||''));setPlanPill(lock,(LIC&&LIC.is_trial)?'TRIAL':'CLOUD','pill pill-accent');showAs(acts,true,'flex');el.innerHTML=renderAnalytics(a,false)}catch(e){if(managedConsentRequired(e)){setPlanPill(lock,'CLOUD','pill pill-accent');showAs(acts,false);el.innerHTML=managedConsentHtml('Analytics')}else if(hostedFeatureUnavailable(e)){setPlanPill(lock,'PRO','pill pill-muted');showAs(acts,false);el.innerHTML=unlockHtml('Analytics','pro')}else{el.innerHTML='
'+esc(e.message)+'
'}}} /* ── hosted automation policy (Pro / Team) ── */ -async function loadAutomation(){const el=document.getElementById('automation-body'),lock=document.getElementById('au-lock'),ws='?workspace='+encodeURIComponent(WS||'');el.innerHTML='
';try{const p=await api('/automation'+ws);setPlanPill(lock,(LIC&&LIC.is_trial)?'TRIAL':'CLOUD','pill pill-accent');const last=p.last_run?fmtRel(p.last_run):'never',dream=p.dream_enabled!=null?p.dream_enabled:p.dream;el.innerHTML=`
Hosted maintenance policy
The cloud returns reviewable proposals. Pinned memories remain protected.
Cloud worker status
Status${p.enabled?'ENABLED':'OFF'}
Last run${esc(last)}
After explicit opt-in with ENGRAPHIS_MANAGED_COMPUTE_CONSENT=1, requesting managed work uploads the selected workspace’s normal and sensitive memory content, excluding secret and session-scoped rows, capped at 16 MiB, over HTTPS without end-to-end encryption. Results are proposals and never automatically write the local database.
`}catch(e){if(managedConsentRequired(e)){setPlanPill(lock,'CLOUD','pill pill-accent');el.innerHTML=managedConsentHtml('Hosted Automation')}else if(hostedFeatureUnavailable(e)){setPlanPill(lock,'PRO','pill pill-muted');el.innerHTML=unlockHtml('Automation, Auto Consolidation, and Auto Dreaming','pro')}else{el.innerHTML='
'+esc(e.message)+'
'}}} -async function saveAutomation(){const body={enabled:document.getElementById('au-enabled').checked,cadence_hours:Number(document.getElementById('au-cadence').value)||24,consolidate:document.getElementById('au-consolidate').checked,min_cluster:Number(document.getElementById('au-mincluster').value)||3,archive_below:Number(document.getElementById('au-archive').value)||0.05,dream_enabled:document.getElementById('au-dream').checked,dream_min_new:Number(document.getElementById('au-dream-min').value)||20,dream_idle_minutes:Number(document.getElementById('au-dream-idle').value)};try{await api('/automation?workspace='+encodeURIComponent(WS||''),{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify(body)});toast('Hosted policy saved','ok');loadAutomation()}catch(e){if(managedConsentRequired(e)){const result=document.getElementById('au-result');if(result)result.innerHTML=managedConsentHtml('Hosted Automation');toast('Enable managed compute consent and restart Engraphis','err');return}toast((e.status===402||e.status===501)?'Hosted Automation requires Pro or Team':e.message,'err')}} -async function runMaintenance(){const el=document.getElementById('au-result');if(el)el.innerHTML='
';try{const d=await api('/maintenance/run?workspace='+encodeURIComponent(WS||''),{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({dry_run:true})});if(el)el.innerHTML=`PROPOSAL Hosted work was submitted for review.
${esc(JSON.stringify(d,null,2))}
`;toast('Managed proposal requested','ok')}catch(e){if(el)el.innerHTML=managedConsentRequired(e)?managedConsentHtml('Hosted Automation'):'
'+esc(e.message)+'
';toast(managedConsentRequired(e)?'Enable managed compute consent and restart Engraphis':((e.status===402||e.status===501)?'Hosted Automation requires Pro or Team':e.message),'err')}} +async function loadAutomation(){const el=document.getElementById('automation-body'),lock=document.getElementById('au-lock'),ws='?workspace='+encodeURIComponent(WS||'');el.innerHTML='
';try{const p=await api('/automation'+ws);setPlanPill(lock,(LIC&&LIC.is_trial)?'TRIAL':'CLOUD','pill pill-accent');const last=p.last_run?fmtRel(p.last_run):'never',dream=p.dream_enabled!=null?p.dream_enabled:p.dream;el.innerHTML=`
Hosted maintenance policy
The cloud returns reviewable proposals. Pinned memories remain protected.
Cloud worker status
Status${p.enabled?'ENABLED':'OFF'}
Last run${esc(last)}
Requesting managed work uploads the selected workspace’s normal and sensitive memory content, excluding secret and session-scoped rows, capped at 16 MiB, over HTTPS without end-to-end encryption. Results are proposals and never automatically write the local database.
`}catch(e){if(managedConsentRequired(e)){setPlanPill(lock,'CLOUD','pill pill-accent');el.innerHTML=managedConsentHtml('Hosted Automation')}else if(hostedFeatureUnavailable(e)){setPlanPill(lock,'PRO','pill pill-muted');el.innerHTML=unlockHtml('Automation, Auto Consolidation, and Auto Dreaming','pro')}else{el.innerHTML='
'+esc(e.message)+'
'}}} +async function saveAutomation(){const body={enabled:document.getElementById('au-enabled').checked,cadence_hours:Number(document.getElementById('au-cadence').value)||24,consolidate:document.getElementById('au-consolidate').checked,min_cluster:Number(document.getElementById('au-mincluster').value)||3,archive_below:Number(document.getElementById('au-archive').value)||0.05,dream_enabled:document.getElementById('au-dream').checked,dream_min_new:Number(document.getElementById('au-dream-min').value)||20,dream_idle_minutes:Number(document.getElementById('au-dream-idle').value)};try{await api('/automation?workspace='+encodeURIComponent(WS||''),{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify(body)});toast('Hosted policy saved','ok');loadAutomation()}catch(e){if(managedConsentRequired(e)){const result=document.getElementById('au-result');if(result)result.innerHTML=managedConsentHtml('Hosted Automation');toast('Connect this installation to Engraphis Cloud to use managed compute','err');return}toast((e.status===402||e.status===501)?'Hosted Automation requires Pro or Team':e.message,'err')}} +async function runMaintenance(){const el=document.getElementById('au-result');if(el)el.innerHTML='
';try{const d=await api('/maintenance/run?workspace='+encodeURIComponent(WS||''),{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({dry_run:true})});if(el)el.innerHTML=`PROPOSAL Hosted work was submitted for review.
${esc(JSON.stringify(d,null,2))}
`;toast('Managed proposal requested','ok')}catch(e){if(el)el.innerHTML=managedConsentRequired(e)?managedConsentHtml('Hosted Automation'):'
'+esc(e.message)+'
';toast(managedConsentRequired(e)?'Connect this installation to Engraphis Cloud to use managed compute':((e.status===402||e.status===501)?'Hosted Automation requires Pro or Team':e.message),'err')}} const runMaintenanceBase=runMaintenance; let MAINTENANCE_PENDING=false; diff --git a/tests/e2e/commercial.spec.js b/tests/e2e/commercial.spec.js index 08b5550..5fe4327 100644 --- a/tests/e2e/commercial.spec.js +++ b/tests/e2e/commercial.spec.js @@ -423,21 +423,26 @@ for (const cloudStatus of [401, 402, 501]) { }); } -test('Analytics explains the local managed-compute consent step', async ({ page }) => { +// Consent travels with the cloud account: connecting an installation accepts the terms +// covering managed compute. A 409 consent_required therefore means "this installation is +// not connected", never "go and hand-edit an environment variable", and it must never be +// mistaken for an unpaid invoice and answered with the Pro purchase panel. +test('Analytics explains that managed compute follows the cloud connection', async ({ page }) => { const errors = recordBrowserErrors(page); await mockLocalClient(page, 409); await page.goto('/'); await openView(page, 'analytics'); const analytics = page.locator('#analytics-body'); - await expect(analytics).toContainText('needs your explicit permission'); - await expect(analytics).toContainText('ENGRAPHIS_MANAGED_COMPUTE_CONSENT=1'); - await expect(analytics).toContainText('restart Engraphis'); + await expect(analytics).toContainText('managed compute is turned off for this installation'); + await expect(analytics).toContainText('Connect this installation to Engraphis Cloud'); + await expect(analytics).not.toContainText('ENGRAPHIS_MANAGED_COMPUTE_CONSENT'); + await expect(analytics).not.toContainText('Purchase Pro license'); await expect(page.locator('#an-lock')).toHaveText('CLOUD'); expect(errors).toEqual([]); }); -test('Automation policy save explains the managed-compute consent step', async ({ page }) => { +test('Automation policy save explains that managed compute follows the cloud connection', async ({ page }) => { const errors = recordBrowserErrors(page); await mockLocalClient(page, 200, null, 409); await page.goto('/'); @@ -446,8 +451,9 @@ test('Automation policy save explains the managed-compute consent step', async ( await page.locator('#au-enabled').check(); await page.getByRole('button', { name: 'Save hosted policy' }).click(); const result = page.locator('#au-result'); - await expect(result).toContainText('needs your explicit permission'); - await expect(result).toContainText('ENGRAPHIS_MANAGED_COMPUTE_CONSENT=1'); - await expect(result).toContainText('restart Engraphis'); + await expect(result).toContainText('managed compute is turned off for this installation'); + await expect(result).toContainText('Connect this installation to Engraphis Cloud'); + await expect(result).not.toContainText('ENGRAPHIS_MANAGED_COMPUTE_CONSENT'); + await expect(result).not.toContainText('Purchase Pro license'); expect(errors).toEqual([]); }); diff --git a/tests/test_cloud_features.py b/tests/test_cloud_features.py index 3a84ffd..484ffa5 100644 --- a/tests/test_cloud_features.py +++ b/tests/test_cloud_features.py @@ -34,18 +34,94 @@ def _service() -> MemoryService: return service -def test_snapshot_requires_explicit_consent(monkeypatch) -> None: +def _cloud_session(monkeypatch, connected: bool) -> list: + """Pin whether this installation has a cloud session, and record how it was asked.""" + + calls: list = [] + + def configured(**kwargs): + calls.append(kwargs) + return connected + + monkeypatch.setattr(cloud_features, "cloud_session_configured", configured) + return calls + + +def test_a_local_installation_with_no_cloud_account_never_uploads(monkeypatch) -> None: + """No account means no agreement to rely on, so a purely local install is denied.""" + monkeypatch.delenv("ENGRAPHIS_MANAGED_COMPUTE_CONSENT", raising=False) + _cloud_session(monkeypatch, connected=False) assert cloud_features.managed_compute_consent() is False - with pytest.raises(CloudFeatureError, match="Managed compute is off") as captured: + with pytest.raises( + CloudFeatureError, match="Managed compute is turned off" + ) as captured: build_managed_snapshot(_service(), "acme") assert captured.value.status == 409 + assert captured.value.code == "consent_required" + # The customer is never told to hand-edit an environment variable. + assert "ENGRAPHIS_MANAGED_COMPUTE_CONSENT" not in str(captured.value) + + +def test_connecting_to_the_cloud_is_itself_the_managed_compute_consent( + monkeypatch, +) -> None: + """Connecting accepts the terms covering managed compute; nothing else is asked for.""" + + monkeypatch.delenv("ENGRAPHIS_MANAGED_COMPUTE_CONSENT", raising=False) + calls = _cloud_session(monkeypatch, connected=True) + + assert cloud_features.managed_compute_consent() is True + + _, snapshot = build_managed_snapshot(_service(), "acme") + assert snapshot["managed_compute_consent"] is True + # A session without a compute URL is still an account that accepted the terms. + assert calls and all(call == {"require_compute": False} for call in calls) + + +def test_a_connected_installation_can_be_opted_back_out(monkeypatch) -> None: + """``=0`` is the operator override that withdraws a connected installation.""" + + monkeypatch.setenv("ENGRAPHIS_MANAGED_COMPUTE_CONSENT", "0") + _cloud_session(monkeypatch, connected=True) + + assert cloud_features.managed_compute_consent() is False + with pytest.raises(CloudFeatureError, match="Managed compute is turned off"): + build_managed_snapshot(_service(), "acme") + + +@pytest.mark.parametrize("blank", ["", " "]) +def test_a_blank_override_defers_to_the_cloud_account(monkeypatch, blank) -> None: + """An empty variable is not an answer — it must not read as an opt-out.""" + + monkeypatch.setenv("ENGRAPHIS_MANAGED_COMPUTE_CONSENT", blank) + _cloud_session(monkeypatch, connected=True) + assert cloud_features.managed_compute_consent() is True + + _cloud_session(monkeypatch, connected=False) + assert cloud_features.managed_compute_consent() is False + + +def test_consent_is_never_the_reason_a_dashboard_fails_to_render(monkeypatch) -> None: + """An unreadable session file denies consent instead of raising into the view.""" + + monkeypatch.delenv("ENGRAPHIS_MANAGED_COMPUTE_CONSENT", raising=False) + + def explode(**kwargs): + raise OSError("session state is unreadable") + + monkeypatch.setattr(cloud_features, "cloud_session_configured", explode) + + assert cloud_features.managed_compute_consent() is False def test_snapshot_accepts_environment_opt_in(monkeypatch) -> None: + """A truthy override forces consent on even with no cloud session at all.""" + monkeypatch.setenv("ENGRAPHIS_MANAGED_COMPUTE_CONSENT", "yes") + _cloud_session(monkeypatch, connected=False) _, snapshot = build_managed_snapshot(_service(), "acme") @@ -83,7 +159,7 @@ def fail_access(*args, **kwargs): def test_explicit_false_consent_cannot_be_overridden_by_environment(monkeypatch) -> None: monkeypatch.setenv("ENGRAPHIS_MANAGED_COMPUTE_CONSENT", "1") - with pytest.raises(CloudFeatureError, match="Managed compute is off"): + with pytest.raises(CloudFeatureError, match="Managed compute is turned off"): build_managed_snapshot(_service(), "acme", consent=False) diff --git a/tests/test_dashboard_auth_placement.py b/tests/test_dashboard_auth_placement.py index 096e22c..01649f6 100644 --- a/tests/test_dashboard_auth_placement.py +++ b/tests/test_dashboard_auth_placement.py @@ -76,6 +76,9 @@ def test_hosted_views_delegate_entitlement_to_cloud_proxy_responses(): for body in (analytics, automation): assert "hostedFeatureUnavailable(e)" in body assert "unlockHtml" in body + # The billing predicate itself, verbatim: the loaders delegate to it, so widening it + # here is the only way a non-billing failure can reach ``unlockHtml``. + assert "error.status===401||error.status===402||error.status===501" in script assert "error.status===409" in script assert "Purchase Pro license" in script @@ -83,7 +86,8 @@ def test_hosted_views_delegate_entitlement_to_cloud_proxy_responses(): # ── a paying customer must never be sold the plan they already own ──────────── # The hosted views route a failed request to one of three answers. Only an entitlement # status may draw the purchase panel; a 409 is a conflict, and ``consent_required`` in -# particular is a customer who HAS paid and only has to set one environment variable. +# particular is a customer who HAS paid and whose installation simply has managed compute +# turned off — connecting it to Engraphis Cloud is what turns it on. # # ``_route`` below executes the shipped routing rather than asserting on its source: the # regression it guards (409 folded into ``hostedFeatureUnavailable``) kept every string @@ -173,29 +177,36 @@ def _route(tmp_path, cases): @pytest.mark.skipif(shutil.which("node") is None, reason="node is required to run the UI") @pytest.mark.parametrize("view", ["analytics", "automation"]) -def test_a_consent_required_conflict_is_answered_with_a_purchase_panel( +def test_a_consent_required_conflict_is_answered_with_the_consent_panel( tmp_path, view, ): - """Analytics and Automation are Pro sales surfaces, not error consoles.""" + """A 409 ``consent_required`` is a conflict, not a bill — never sell Pro for it. + + Analytics and Automation are the two views that reach managed compute, so they are + exactly the views this panel has to appear in. + """ rendered = _route(tmp_path, [{ "name": "consent", "view": view, "error": {"status": 409, "detail": {"code": "consent_required"}}, }])["consent"] - assert 'class="upgrade-panel"' in rendered["html"] - assert "Purchase Pro license" in rendered["html"] - assert "ENGRAPHIS_MANAGED_COMPUTE_CONSENT=1" not in rendered["html"] - assert rendered["pill"] == "PRO" + assert "managed compute is turned off for this installation" in rendered["html"] + assert "Connect this installation to Engraphis Cloud" in rendered["html"] + assert 'class="upgrade-panel"' not in rendered["html"] + assert "Purchase Pro license" not in rendered["html"] + # Consent travels with the cloud account; the customer is never sent to edit ``.env``. + assert "ENGRAPHIS_MANAGED_COMPUTE_CONSENT" not in rendered["html"] + assert rendered["pill"] == "CLOUD" @pytest.mark.skipif(shutil.which("node") is None, reason="node is required to run the UI") @pytest.mark.parametrize("view", ["analytics", "automation"]) -@pytest.mark.parametrize("status", [400, 401, 402, 500, 501]) +@pytest.mark.parametrize("status", [401, 402, 501]) def test_a_genuine_entitlement_failure_still_renders_the_upgrade_panel( tmp_path, view, status, ): - """Every failed hosted request renders the Pro upgrade panel in these tabs.""" + """401 unauthenticated, 402 not subscribed, 501 not offered: all billing answers.""" rendered = _route(tmp_path, [{ "name": "unentitled", "view": view, "error": {"status": status}, @@ -209,8 +220,29 @@ def test_a_genuine_entitlement_failure_still_renders_the_upgrade_panel( @pytest.mark.skipif(shutil.which("node") is None, reason="node is required to run the UI") @pytest.mark.parametrize("view", ["analytics", "automation"]) -def test_an_internal_hosted_conflict_is_answered_with_a_purchase_panel(tmp_path, view): - """Backend failures never expose internal messages in hosted tabs.""" +@pytest.mark.parametrize("status", [400, 500, 503]) +def test_a_non_billing_failure_shows_the_error_instead_of_selling_pro( + tmp_path, view, status, +): + """A bad request or a cloud outage is not an unpaid invoice.""" + + rendered = _route(tmp_path, [{ + "name": "broken", "view": view, + "message": "the hosted service is briefly unavailable", + "error": {"status": status}, + }])["broken"] + + assert 'class="upgrade-panel"' not in rendered["html"] + assert "Purchase Pro license" not in rendered["html"] + assert "the hosted service is briefly unavailable" in rendered["html"] + + +@pytest.mark.skipif(shutil.which("node") is None, reason="node is required to run the UI") +@pytest.mark.parametrize("view", ["analytics", "automation"]) +def test_a_transient_hosted_conflict_is_not_answered_with_a_purchase_panel( + tmp_path, view, +): + """A 409 that is not ``consent_required`` is a state conflict, not a billing answer.""" rendered = _route(tmp_path, [{ "name": "conflict", "view": view, @@ -218,22 +250,34 @@ def test_an_internal_hosted_conflict_is_answered_with_a_purchase_panel(tmp_path, "error": {"status": 409, "detail": {"error": "generation conflict"}}, }])["conflict"] - assert 'class="upgrade-panel"' in rendered["html"] - assert "Purchase Pro license" in rendered["html"] - assert "managed snapshot generation must advance" not in rendered["html"] + assert 'class="upgrade-panel"' not in rendered["html"] + assert "Purchase Pro license" not in rendered["html"] + # The customer sees the real cause and can retry, rather than a panel selling Pro. + assert "managed snapshot generation must advance" in rendered["html"] -def test_analytics_and_automation_suppress_hosted_error_details(): - """Only these sales surfaces redirect every failed hosted request to Pro.""" +def test_only_an_entitlement_status_may_draw_the_purchase_panel(): + """Pin both routing predicates literally. + + The regression these guard folded a view name into ``hostedFeatureUnavailable`` and out + of ``managedConsentRequired``, which made every failure on Analytics and Automation -- + including a 409 from a paying customer -- render the panel selling Pro. A loose + substring check passed straight through that, so assert the exact predicate and the + exhaustive set of statuses it may test. + """ helper = _dashboard_function("hostedFeatureUnavailable") - assert "CURRENT_VIEW==='analytics'" in helper - assert "CURRENT_VIEW==='automation'" in helper - for entitlement_status in ("401", "402", "501"): - assert entitlement_status in helper + assert "error.status===401||error.status===402||error.status===501" in helper + # No view may widen it and no fourth status may join it. + assert "CURRENT_VIEW" not in helper + assert sorted(set(re.findall(r"status\s*===\s*(\d+)", helper))) == ["401", "402", "501"] + consent = _dashboard_function("managedConsentRequired") - assert "CURRENT_VIEW!=='analytics'" in consent - assert "CURRENT_VIEW!=='automation'" in consent + assert "error.status===409" in consent + assert "code==='consent_required'" in consent + assert sorted(set(re.findall(r"status\s*===\s*(\d+)", consent))) == ["409"] + # The consent branch must fire in every view, including the two sales surfaces. + assert "CURRENT_VIEW" not in consent for name in ( "loadOverviewAnalytics", diff --git a/tests/test_dashboard_dream_ui.py b/tests/test_dashboard_dream_ui.py index 903abf7..388a105 100644 --- a/tests/test_dashboard_dream_ui.py +++ b/tests/test_dashboard_dream_ui.py @@ -14,8 +14,10 @@ def test_automation_form_renders_dream_controls(): for el in ("au-dream", "au-dream-min", "au-dream-idle"): assert f'id="{el}"' in script, el assert 'id="au-infer"' not in script - assert "ENGRAPHIS_MANAGED_COMPUTE_CONSENT=1" in script assert "uploads the selected workspace’s normal and sensitive memory content" in script + # Consent travels with the cloud account. The dashboard must never name the operator + # override, so the string cannot appear anywhere the browser could render it. + assert "ENGRAPHIS_MANAGED_COMPUTE_CONSENT" not in script def test_save_body_posts_dream_fields(): diff --git a/tests/test_dashboard_v2.py b/tests/test_dashboard_v2.py index f66c1c0..932eb5e 100644 --- a/tests/test_dashboard_v2.py +++ b/tests/test_dashboard_v2.py @@ -263,8 +263,11 @@ def test_dashboard_automation_uses_active_workspace_and_discloses_upload_boundar assert "/automation?workspace=" in source assert "/maintenance/run?workspace=" in source assert "Preview snapshot" not in source - assert "ENGRAPHIS_MANAGED_COMPUTE_CONSENT=1" in source assert "uploads the selected workspace’s normal and sensitive memory content" in source + # The upload boundary is still disclosed, but consent now travels with the cloud + # account: the dashboard must not name the operator override anywhere. + assert "ENGRAPHIS_MANAGED_COMPUTE_CONSENT" not in source + assert "managed compute is turned off for this installation" in source def test_portfolio_and_report_analytics_are_hosted_only(monkeypatch, tmp_path): diff --git a/tests/test_packaging.py b/tests/test_packaging.py index d46da52..c24bfdf 100644 --- a/tests/test_packaging.py +++ b/tests/test_packaging.py @@ -213,4 +213,7 @@ def test_customer_hosting_docs_do_not_claim_private_cloud_authority(): assert "license issuer" in combined assert "ENGRAPHIS_CLOUD_CONTROL_URL" in hosting assert "ENGRAPHIS_CLOUD_COMPUTE_URL" in hosting - assert "ENGRAPHIS_MANAGED_COMPUTE_CONSENT=1" in combined + # Managed compute follows the cloud account now. The hosting docs may still document + # the operator override, but they must never present hand-setting it as the way a + # customer turns managed compute on. + assert "ENGRAPHIS_MANAGED_COMPUTE_CONSENT=1" not in combined diff --git a/tests/test_release_infrastructure.py b/tests/test_release_infrastructure.py index 7202315..52d3b17 100644 --- a/tests/test_release_infrastructure.py +++ b/tests/test_release_infrastructure.py @@ -28,8 +28,11 @@ def test_published_image_and_railway_template_fail_safe_to_customer_mode(): assert local_api["value"] == "${{ secret(48) }}" assert local_api["secret"] is True assert local_api["required"] is True + # Managed-compute consent travels with the cloud account. A template that shipped a + # hard-coded value would override that for every deployment made from it -- "0" would + # silently opt a connected deployment back out -- so the default must stay blank. managed_consent = template["variables"]["ENGRAPHIS_MANAGED_COMPUTE_CONSENT"] - assert managed_consent["value"] == "0" + assert not managed_consent["value"] assert managed_consent["required"] is False for removed in ( "ENGRAPHIS_DEPLOYMENT_TOKEN", From 1422ecd3e9223f40653817d7a033ed35a7dc0b0a Mon Sep 17 00:00:00 2001 From: Jaixii Date: Sun, 26 Jul 2026 04:13:35 -0400 Subject: [PATCH 05/82] fix(cloud): drop stale grants when the plan changes access_for_workspace merged the refresh answer onto the saved record with dict.update. _declared_entitlement deliberately omits cloud_features when the body carries no feature list, so a downgrade replaced plan while the previous plan's grants survived. A Team -> Pro downgrade therefore reported plan "pro" with "team" still in features, leaving the Team tab unlocked indefinitely. Fixed at the merge site so _declared_entitlement keeps its tested contract. Co-Authored-By: Claude Opus 5 (1M context) --- engraphis/cloud_session.py | 14 ++++- tests/test_cloud_session.py | 80 ++++++++++++++++++++++++++++ tests/test_hosted_plan_resolution.py | 36 +++++++++++++ 3 files changed, 129 insertions(+), 1 deletion(-) diff --git a/engraphis/cloud_session.py b/engraphis/cloud_session.py index 63fb21b..83fa8da 100644 --- a/engraphis/cloud_session.py +++ b/engraphis/cloud_session.py @@ -486,6 +486,18 @@ def access_for_workspace( # The refresh response carries the same entitlement fields as registration, so the # plan re-confirms itself on every token rotation. An older cloud omits them and # the previously persisted answer (if any) is left untouched. - updated.update(_declared_entitlement(body)) + declared = _declared_entitlement(body) + if declared and "cloud_features" not in declared: + # A *plan change* may never inherit the previous plan's grants. + # ``_declared_entitlement`` omits ``cloud_features`` whenever the body carried + # no feature list, so merging it onto the saved record left a Team feature list + # alive underneath a downgraded Pro plan and kept the Team tab unlocked + # indefinitely. Dropping the stale key hands the answer back to this client's + # own plan table, which is right for the plan the cloud just named. A refresh + # that re-confirms the *same* plan still keeps the richer saved list. + previous = str(saved.get("plan") or "").strip().lower() + if previous != declared["plan"]: + updated.pop("cloud_features", None) + updated.update(declared) _save(updated) return access, organization_id, compute diff --git a/tests/test_cloud_session.py b/tests/test_cloud_session.py index 533604b..1bc9853 100644 --- a/tests/test_cloud_session.py +++ b/tests/test_cloud_session.py @@ -299,6 +299,86 @@ def open(self, request, timeout): assert "private network detail" not in str(caught.value) +def _downgrade_state(monkeypatch, *, body: dict) -> dict: + """A saved Team session, refreshed against a control plane that answers *body*.""" + + monkeypatch.delenv("ENGRAPHIS_CLOUD_ACCESS_TOKEN", raising=False) + monkeypatch.delenv("ENGRAPHIS_CLOUD_CONTROL_URL", raising=False) + state = { + "control_url": "https://control.example.test", + "organization_id": "org_1", + "refresh_credential": "old-refresh", + "token_subject": "member", + "plan": "team", + "cloud_access_active": True, + "cloud_features": ["analytics", "automation", "export", "sync", "team"], + } + + def _replace(value: dict) -> None: + state.clear() + state.update(value) + + monkeypatch.setattr(cloud_session, "_load", lambda: dict(state)) + monkeypatch.setattr(cloud_session, "_save", _replace) + monkeypatch.setattr( + cloud_session, "validate_cloud_base_url", lambda value: value.rstrip("/") + ) + monkeypatch.setattr(cloud_session, "_post_refresh", lambda *_args: dict({ + "access_token": "short-lived-access", + "organization_id": "org_1", + "refresh_credential": "rotated-refresh", + "token_subject": "member", + }, **body)) + cloud_session.access_for_workspace("ws", require_compute=False) + return state + + +def test_a_plan_downgrade_does_not_carry_the_previous_plans_features(monkeypatch) -> None: + """Team -> Pro must not leave ``team`` in the persisted grant list. + + ``_declared_entitlement`` omits ``cloud_features`` whenever the body carries no feature + list, so merging it onto the saved record replaced ``plan`` while the *old* list + survived. ``/api/license`` then reported ``plan: "pro"`` with ``team`` still granted and + the Team tab stayed unlocked indefinitely — a paid capability handed out for free. + """ + + state = _downgrade_state(monkeypatch, body={ + "plan": "pro", "cloud_access_active": True, + }) + + assert state["plan"] == "pro" + assert "cloud_features" not in state, "the Team grants outlived the Team plan" + # With no stale list left, the client's own plan table answers for Pro. + assert "team" not in cloud_session.saved_entitlement().get("cloud_features", []) + + +def test_a_downgrade_that_declares_its_own_features_is_taken_verbatim(monkeypatch) -> None: + """A control plane that does send a list stays authoritative over the plan table.""" + + state = _downgrade_state(monkeypatch, body={ + "plan": "pro", "cloud_access_active": True, + "cloud_features": ["analytics", "sync"], + }) + + assert state["plan"] == "pro" + assert state["cloud_features"] == ["analytics", "sync"] + + +def test_a_refresh_reconfirming_the_same_plan_keeps_its_saved_features(monkeypatch) -> None: + """Only a plan *change* drops the list; re-confirming Team must not blank it. + + Otherwise every token rotation against a control plane that reports the plan but not + the features would quietly demote a Team customer to the generic table. + """ + + state = _downgrade_state(monkeypatch, body={ + "plan": "team", "cloud_access_active": True, + }) + + assert state["plan"] == "team" + assert "team" in state["cloud_features"] + + @pytest.mark.parametrize("subject", ["admin", "", "device member"]) def test_environment_refresh_rejects_invalid_subject(monkeypatch, subject) -> None: monkeypatch.setenv("ENGRAPHIS_CLOUD_REFRESH_CREDENTIAL", "env-refresh") diff --git a/tests/test_hosted_plan_resolution.py b/tests/test_hosted_plan_resolution.py index 3b87423..7c43a24 100644 --- a/tests/test_hosted_plan_resolution.py +++ b/tests/test_hosted_plan_resolution.py @@ -833,6 +833,42 @@ def test_a_field_less_refresh_never_erases_a_plan_the_cloud_already_declared( assert v2_api.get_license()["plan"] == "team" +def test_a_downgrade_drops_the_previous_plans_features_from_the_resolved_answer( + monkeypatch, +) -> None: + """Team -> Pro must lock the Team tab, not leave it open on a stale grant list. + + ``_declared_entitlement`` omits ``cloud_features`` when the refresh body carries no + feature list, so merging it onto the saved record swapped ``plan`` while the *old* list + stayed behind. ``/api/license`` then answered ``pro`` with ``team`` still in + ``features``, and the customer kept the Team administration they had stopped paying for. + """ + + _connect(monkeypatch, pinned_token=False) + _serve(monkeypatch, _FakeControlPlane(_entitlement_dto("team"), + registration=_registration_entitlement("team"))) + assert "team" in _settled_license(monkeypatch)["features"] + + # The downgrade as a control plane that names the plan but no features reports it. + _serve(monkeypatch, _FakeControlPlane( + _entitlement_dto("pro"), + registration={"plan": "pro", "cloud_access_active": True}, + )) + cloud_session.access_for_workspace(None, require_compute=False) + + saved = cloud_session.saved_entitlement() + assert saved["plan"] == "pro" + assert "team" not in saved.get("cloud_features", []) + + payload = v2_api.get_license() + + assert payload["plan"] == "pro" + assert payload["plan_source"] == "session" + assert "team" not in payload["features"], "Team is still unlocked on a Pro plan" + # A stale list is dropped, not blanked: everything Pro does grant is still granted. + assert set(SERVER_PLAN_FEATURES["pro"]) <= set(payload["features"]) + + def test_a_lapsed_subscription_declared_on_the_refresh_keeps_its_name( monkeypatch, ) -> None: From e3a23f25482fd5b98fa90b766aaf103f2276a757 Mon Sep 17 00:00:00 2001 From: Jaixii Date: Sun, 26 Jul 2026 04:13:35 -0400 Subject: [PATCH 06/82] fix(update): make the subprocess budget hold on Windows subprocess.run(capture_output=True, timeout=N) does not honour N on Windows: after TimeoutExpired, CPython calls communicate() with no timeout, and the reader threads block until every inherited pipe write handle closes -- including grandchildren. git fetch and git ls-remote always spawn git-remote-https, so the three network calls stayed unbounded. Measured with a grandchild holding the pipe: a 3s budget returned after 30.2s before, and raises at 3.1s now. Network calls that need stdout go through a bounded Popen reader that kills the process tree and re-drains with a cap; the rest stop capturing. Every git call now gets stdin=DEVNULL and GIT_TERMINAL_PROMPT=0 so an expired token cannot park the updater on a credential prompt. Also moves _detect_install() inside main()'s try, so a stalled pip show prints its crafted message instead of a traceback. Three existing tests encoded the belief that timeout= alone was sufficient and are rewritten. Co-Authored-By: Claude Opus 5 (1M context) --- scripts/update.py | 158 ++++++++++++++++++++++++++++++------ tests/test_client_launch.py | 113 ++++++++++++++++++++++---- tests/test_update.py | 152 ++++++++++++++++++++++++++++++++++ 3 files changed, 382 insertions(+), 41 deletions(-) diff --git a/scripts/update.py b/scripts/update.py index 4748a69..3e157da 100644 --- a/scripts/update.py +++ b/scripts/update.py @@ -21,6 +21,7 @@ import os import re import shutil +import signal import subprocess import sys from pathlib import Path @@ -34,11 +35,12 @@ ) -# Every step below runs with an explicit, differentiated budget. The query steps capture -# their output, so an unbounded call against a stalled package index or an unreachable git -# remote is an indefinite and *silent* hang with nothing on screen to explain it. Sizes -# follow the work each command actually does: a refs query is one round trip, a fetch may -# transfer a whole object delta, and an install downloads and may build wheels. +# Every step below runs with an explicit, differentiated budget. An unbounded call against +# a stalled package index or an unreachable git remote is an indefinite hang, and a +# *captured* one is a silent hang with nothing on screen to explain it. Sizes follow the +# work each command actually does: a refs query is one round trip, a fetch may transfer a +# whole object delta, and an install downloads and may build wheels. A budget is only real +# if nothing can outlive it — see ``_run`` and ``_run_captured`` for how that is enforced. _GIT_LOCAL_TIMEOUT_S = 30 # plumbing on an existing clone (see scripts/graph_cli.py) _GIT_CHECKOUT_TIMEOUT_S = 120 # local, but runs checkout filters and hooks _GIT_LS_REMOTE_TIMEOUT_S = 60 # one network round trip for refs; no object transfer @@ -47,6 +49,14 @@ _PIP_RESOLVE_TIMEOUT_S = 300 # `--dry-run` still queries and resolves against the index _PIP_INSTALL_TIMEOUT_S = 1800 # download plus build; an sdist with C extensions is slow _PIPX_TIMEOUT_S = 1800 # a pip install plus venv creation +_TREE_KILL_TIMEOUT_S = 10 # bounding the kill itself; `taskkill` is local and fast +_DRAIN_AFTER_KILL_S = 5 # reading a pipe whose writers were just destroyed + +# ``os.killpg`` must target *our* tree, never the shell that launched the updater, so the +# POSIX child gets its own session. Windows has no equivalent at spawn time — the tree is +# walked by ``taskkill /T`` instead — and the keyword's Windows meaning changed in 3.13, +# so it is not passed there at all. +_OWN_PROCESS_GROUP = {} if os.name == "nt" else {"start_new_session": True} class UpdateTimeout(RuntimeError): @@ -58,17 +68,106 @@ class UpdateTimeout(RuntimeError): """ +def _timed_out(what: str, timeout: int) -> UpdateTimeout: + return UpdateTimeout( + "%s timed out after %ds. Check your network connection, proxy settings, and " + "package index, then run `engraphis-update` again." % (what, timeout) + ) + + +def _git_env() -> dict: + """Environment for every git call: never stop to ask a human for credentials. + + An expired token, a revoked SSH key or a corporate proxy that wants authentication + otherwise drops the updater into git's terminal prompt — or, on Windows, the Git + Credential Manager dialog — and it blocks forever behind a question nobody is there + to answer. That is a hang with no network fault to diagnose, so the budgets above look + like they simply do not work. Fail the call instead; the caller already prints what to + do about it. + """ + env = dict(os.environ) + env["GIT_TERMINAL_PROMPT"] = "0" + env["GCM_INTERACTIVE"] = "never" + return env + + +def _kill_process_tree(process: subprocess.Popen) -> None: + """Kill *process* and every descendant it spawned. Best effort; already-dead is fine. + + Killing only the direct child is what makes a "bounded" capture unbounded: git forks + ``git-remote-https`` (and credential helpers), those grandchildren inherit the pipe's + write handle, and a read of that pipe cannot complete until the last handle closes. + """ + if os.name == "nt": + taskkill = shutil.which("taskkill") + if taskkill: + try: + subprocess.run( + [taskkill, "/F", "/T", "/PID", str(process.pid)], + stdin=subprocess.DEVNULL, stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL, timeout=_TREE_KILL_TIMEOUT_S, + ) + except (OSError, subprocess.SubprocessError): + pass + else: + try: + os.killpg(os.getpgid(process.pid), getattr(signal, "SIGKILL", signal.SIGTERM)) + except (OSError, AttributeError): + pass + try: + process.kill() + except OSError: + pass + + def _run(cmd: list[str], what: str, timeout: int, check: bool = False, - capture: bool = True) -> subprocess.CompletedProcess: - """Run *cmd* under an explicit budget; a stall raises instead of hanging forever.""" + capture: bool = False, env: dict | None = None) -> subprocess.CompletedProcess: + """Run *cmd* under an explicit budget; a stall raises instead of hanging forever. + + ``capture`` is opt-in and deliberately defaults to *off*. ``subprocess.run`` honours + ``timeout`` only when it has no pipes left to drain: once the budget expires CPython + kills the direct child and then calls ``communicate()`` with **no** timeout, so the + reader threads keep waiting until every inherited write handle on those pipes closes — + grandchildren included. Use ``capture=True`` only for local commands that fork nothing + (``pip show``, git plumbing against an existing clone). Anything that reaches the + network must go through :func:`_run_captured`, which kills the whole tree first. + + ``stdin`` is closed for every step: a subprocess that stops to read from a terminal is + the same indefinite hang as a stalled socket, and none of these commands has anything + to read. + """ try: return subprocess.run(cmd, capture_output=capture, text=True, check=check, - timeout=timeout) + timeout=timeout, stdin=subprocess.DEVNULL, env=env) except subprocess.TimeoutExpired: - raise UpdateTimeout( - "%s timed out after %ds. Check your network connection, proxy settings, and " - "package index, then run `engraphis-update` again." % (what, timeout) - ) from None + raise _timed_out(what, timeout) from None + + +def _run_captured(cmd: list[str], what: str, timeout: int, + env: dict | None = None) -> subprocess.CompletedProcess: + """Run *cmd* for its stdout under a budget that is actually enforced. + + For the steps that must be *parsed* rather than merely displayed, so simply not + capturing is not an option. Only stdout is piped — stderr stays on the terminal, which + both surfaces git's own explanation of a failure and leaves one fewer inherited write + handle for a grandchild to hold open. On expiry the entire process tree is destroyed + *before* the pipe is drained, and even that drain is bounded, so the call returns on + schedule instead of waiting on ``git-remote-https``. + """ + process = subprocess.Popen( + cmd, stdout=subprocess.PIPE, stdin=subprocess.DEVNULL, text=True, env=env, + **_OWN_PROCESS_GROUP, + ) + try: + stdout, _ = process.communicate(timeout=timeout) + except subprocess.TimeoutExpired: + _kill_process_tree(process) + try: + process.communicate(timeout=_DRAIN_AFTER_KILL_S) + except subprocess.TimeoutExpired: + pass + raise _timed_out(what, timeout) from None + return subprocess.CompletedProcess(cmd, process.returncode, stdout or "", None) def _select_latest_tag(tags) -> str: @@ -84,9 +183,10 @@ def _select_latest_tag(tags) -> str: def _remote_latest_tag(git: str, repo_url: str = REPO_URL) -> str: - result = _run( + result = _run_captured( [git, "ls-remote", "--tags", "--refs", repo_url, "v*"], "Listing release tags from the Git remote", _GIT_LS_REMOTE_TIMEOUT_S, + env=_git_env(), ) if result.returncode: return "" @@ -131,7 +231,8 @@ def _detect_install() -> str: try: result = _run( [sys.executable, "-m", "pip", "show", "engraphis"], - "Reading the installed Engraphis metadata", _PIP_METADATA_TIMEOUT_S) + "Reading the installed Engraphis metadata", _PIP_METADATA_TIMEOUT_S, + capture=True) if result.returncode == 0: info = result.stdout if "Editable project location:" in info: @@ -160,7 +261,7 @@ def _git_update(check_only: bool = False) -> None: result = _run( [sys.executable, "-m", "pip", "show", "engraphis"], "Reading the installed Engraphis metadata", _PIP_METADATA_TIMEOUT_S, - check=True) + check=True, capture=True) except subprocess.CalledProcessError: print("Engraphis is not installed.", file=sys.stderr) sys.exit(1) @@ -184,29 +285,33 @@ def _git_update(check_only: bool = False) -> None: # Fetch and compare. Fail closed on a network/ref error: selecting the highest LOCAL # tag would let a stray or malicious tag masquerade as the latest upstream release. - # Announce the network step: it captures its output, so without this line a slow or - # unreachable origin looks like a frozen terminal until the budget below expires. + # Nothing here parses the fetch's output, and capturing it would forfeit the budget + # below (see ``_run``), so let git report its own progress straight to the terminal. print("Fetching release tags from origin...") fetched = _run( [git, "-C", str(project_dir), "fetch", "--tags", "origin"], "Fetching release tags from origin", _GIT_FETCH_TIMEOUT_S, + env=_git_env(), ) if fetched.returncode: print("Could not fetch release tags from origin; no update was applied.", file=sys.stderr) sys.exit(1) local = _run([git, "-C", str(project_dir), "rev-parse", "HEAD"], - "Reading the current revision", _GIT_LOCAL_TIMEOUT_S).stdout.strip() + "Reading the current revision", _GIT_LOCAL_TIMEOUT_S, + capture=True, env=_git_env()).stdout.strip() branch_result = _run( [git, "-C", str(project_dir), "symbolic-ref", "--quiet", "--short", "HEAD"], "Reading the current branch", _GIT_LOCAL_TIMEOUT_S, + capture=True, env=_git_env(), ) original_ref = branch_result.stdout.strip() if branch_result.returncode == 0 else local tag = LATEST_TAG if not tag: - tags = _run( + tags = _run_captured( [git, "-C", str(project_dir), "ls-remote", "--tags", "--refs", "origin", "v*"], "Listing release tags from origin", _GIT_LS_REMOTE_TIMEOUT_S, + env=_git_env(), ) if tags.returncode: print("Could not list release tags from origin; no update was applied.", @@ -224,6 +329,7 @@ def _git_update(check_only: bool = False) -> None: remote = _run( [git, "-C", str(project_dir), "rev-list", "-n", "1", tag], "Resolving the release tag", _GIT_LOCAL_TIMEOUT_S, + capture=True, env=_git_env(), ) remote_sha = remote.stdout.strip() if remote.returncode == 0 else "" @@ -244,6 +350,7 @@ def _git_update(check_only: bool = False) -> None: dirty = _run( [git, "-C", str(project_dir), "status", "--porcelain"], "Checking the working tree", _GIT_LOCAL_TIMEOUT_S, + capture=True, env=_git_env(), ) if dirty.stdout.strip(): print("Refusing to update a working tree with uncommitted changes.", file=sys.stderr) @@ -251,7 +358,7 @@ def _git_update(check_only: bool = False) -> None: print(f"Checking out release {tag}...") _run([git, "-C", str(project_dir), "checkout", f"tags/{tag}"], "Checking out the release tag", _GIT_CHECKOUT_TIMEOUT_S, - check=True, capture=False) + check=True, capture=False, env=_git_env()) print(f"Reinstalling from {project_dir}...") try: _run( @@ -270,7 +377,7 @@ def _git_update(check_only: bool = False) -> None: try: _run([git, "-C", str(project_dir), "checkout", original_ref], "Restoring the previous checkout", _GIT_CHECKOUT_TIMEOUT_S, - capture=False) + capture=False, env=_git_env()) _run( [sys.executable, "-m", "pip", "install", "-e", str(project_dir)], "Reinstalling the previous checkout", _PIP_INSTALL_TIMEOUT_S, @@ -378,10 +485,13 @@ def main(argv=None) -> None: if not LATEST_TAG: ap.error("version must be a stable MAJOR.MINOR.PATCH tag (for example v1.0.0)") - method = _detect_install() - print(f"Install method: {method}") - try: + # Inside the guard, not before it. ``_detect_install`` re-raises ``UpdateTimeout`` + # on purpose so a stalled `pip show` says which step hung and what to do about it; + # raising it outside this ``try`` threw that crafted message away and printed a + # traceback instead — the exact failure mode the exception exists to prevent. + method = _detect_install() + print(f"Install method: {method}") if method == "editable": _git_update(check_only=args.check) elif method == "pipx": diff --git a/tests/test_client_launch.py b/tests/test_client_launch.py index 1a6abd6..403a699 100644 --- a/tests/test_client_launch.py +++ b/tests/test_client_launch.py @@ -54,19 +54,53 @@ # ── (1) the updater must never hang on a stalled remote ─────────────────────── +_SPAWNERS = ("subprocess.run", "subprocess.call", "subprocess.check_output", + "subprocess.check_call", "subprocess.Popen") + + +def _drains_under_a_deadline(scope: ast.AST) -> bool: + """True when *scope* reads its child's pipe with an explicit budget on the read.""" + + return any( + isinstance(node, ast.Call) + and ast.unparse(node.func).endswith(".communicate") + and any(keyword.arg == "timeout" for keyword in node.keywords) + for node in ast.walk(scope) + ) + + def test_the_updater_runs_no_unbounded_subprocess() -> None: - """Every shell-out is routed through the one helper that always passes a budget.""" + """Every shell-out is bounded — including the ones whose output must be parsed. + + ``subprocess.run(capture_output=True, timeout=N)`` does not enforce ``N``: once the + budget expires CPython kills the direct child and then drains the pipes with an + *unbounded* ``communicate()``, which waits for every inherited write handle to close — + grandchildren such as ``git-remote-https`` included. So a ``timeout=`` keyword is not + on its own proof of a bound. A ``Popen`` is accepted only when the same function bounds + the read that follows it; anything else is the old silent hang wearing a budget. + """ tree = ast.parse(UPDATER.read_text(encoding="utf-8")) + enclosing = {} + for scope in ast.walk(tree): + if isinstance(scope, ast.FunctionDef): + for node in ast.walk(scope): + enclosing[node] = scope + unbounded = [] for node in ast.walk(tree): if not isinstance(node, ast.Call): continue target = ast.unparse(node.func) - if target in ("subprocess.run", "subprocess.call", "subprocess.check_output", - "subprocess.check_call", "subprocess.Popen"): - if not any(kw.arg == "timeout" for kw in node.keywords): - unbounded.append(target) + if target not in _SPAWNERS: + continue + if any(kw.arg == "timeout" for kw in node.keywords): + continue + scope = enclosing.get(node) + if target == "subprocess.Popen" and scope is not None: + if _drains_under_a_deadline(scope): + continue + unbounded.append(target) assert unbounded == [], "unbounded subprocess call(s) in scripts/update.py: %s" % unbounded @@ -76,13 +110,15 @@ def test_the_updater_helper_makes_a_timeout_impossible_to_omit() -> None: import scripts.update as updater - timeout = inspect.signature(updater._run).parameters["timeout"] - assert timeout.default is inspect.Parameter.empty + for helper in (updater._run, updater._run_captured): + timeout = inspect.signature(helper).parameters["timeout"] + assert timeout.default is inspect.Parameter.empty, helper.__name__ tree = ast.parse(UPDATER.read_text(encoding="utf-8")) call_sites = [ node for node in ast.walk(tree) - if isinstance(node, ast.Call) and getattr(node.func, "id", "") == "_run" + if isinstance(node, ast.Call) + and getattr(node.func, "id", "") in ("_run", "_run_captured") ] assert call_sites, "expected the updater to shell out through _run" for node in call_sites: @@ -91,22 +127,51 @@ def test_the_updater_helper_makes_a_timeout_impossible_to_omit() -> None: def test_a_stalled_remote_aborts_instead_of_waiting_forever(monkeypatch) -> None: - """The failing call is abandoned at its budget and reported, not awaited.""" + """The failing call is abandoned at its budget and reported, not awaited. + + ``ls-remote`` output has to be parsed, so this step cannot simply stop capturing. It + therefore has to kill the *whole* process tree before it reads the pipe again, and + bound that read too — otherwise the surviving ``git-remote-https`` still owns the write + handle and the "budget" expires into an indefinite wait. + """ import scripts.update as updater - seen = {} + seen = {"drains": []} - def _stall(cmd, **kwargs): - seen["timeout"] = kwargs.get("timeout") - raise subprocess.TimeoutExpired(cmd, kwargs.get("timeout")) + class _Stalled: + pid = 4242 + returncode = None - monkeypatch.setattr(updater.subprocess, "run", _stall) + def communicate(self, timeout=None): + seen["drains"].append(timeout) + raise subprocess.TimeoutExpired("git", timeout) + + def _spawn(cmd, **kwargs): + seen["cmd"] = list(cmd) + seen["stdin"] = kwargs.get("stdin") + seen["env"] = kwargs.get("env") + return _Stalled() + + monkeypatch.setattr(updater.subprocess, "Popen", _spawn) + monkeypatch.setattr( + updater.subprocess, "run", + lambda *a, **k: pytest.fail("a network query must not use the unenforceable path"), + ) + monkeypatch.setattr( + updater, "_kill_process_tree", + lambda process: seen.__setitem__("killed", process.pid), + ) with pytest.raises(updater.UpdateTimeout) as excinfo: updater._remote_latest_tag("/usr/bin/git", "https://example.test/engraphis.git") - assert isinstance(seen["timeout"], (int, float)) and seen["timeout"] > 0 + assert isinstance(seen["drains"][0], (int, float)) and seen["drains"][0] > 0 + assert seen["killed"] == 4242, "the grandchildren must die before the pipe is re-read" + assert len(seen["drains"]) == 2 and seen["drains"][1] > 0, "the drain is bounded too" + # Nothing may stop to ask a human for a password on a machine nobody is watching. + assert seen["stdin"] is subprocess.DEVNULL + assert seen["env"]["GIT_TERMINAL_PROMPT"] == "0" # A hang is only survivable if the user is told which step stalled and what to do. message = str(excinfo.value) assert "timed out" in message @@ -170,15 +235,29 @@ def done(stdout=""): return done("a" * 40 + "\n") if "symbolic-ref" in cmd: return done("main\n") - if "ls-remote" in cmd: - return done("%s\trefs/tags/v9.9.9\n" % ("b" * 40)) if "rev-list" in cmd: return done("b" * 40 + "\n") if "status" in cmd: return done("") + assert "ls-remote" not in cmd, "the refs query must use the bounded reader" return done() + class _Refs: + pid = 909 + returncode = 0 + + def communicate(self, timeout=None): + assert timeout, "the bounded drain must carry a budget" + return "%s\trefs/tags/v9.9.9\n" % ("b" * 40), None + + def _fake_popen(cmd, **kwargs): + cmd = list(cmd) + calls.append(cmd) + assert "ls-remote" in cmd, "only the parsed network query needs a pipe: %s" % cmd + return _Refs() + monkeypatch.setattr(updater.subprocess, "run", _fake_run) + monkeypatch.setattr(updater.subprocess, "Popen", _fake_popen) with pytest.raises(updater.UpdateTimeout): updater._git_update() diff --git a/tests/test_update.py b/tests/test_update.py index e406da1..a82928d 100644 --- a/tests/test_update.py +++ b/tests/test_update.py @@ -1,5 +1,8 @@ """The updater must never embed a stale release or select prerelease-like refs.""" import json +import subprocess +import sys +import time from pathlib import Path from types import SimpleNamespace @@ -157,3 +160,152 @@ def test_docker_update_does_not_claim_a_nonexistent_registry_image(capsys): output = capsys.readouterr().out assert "does not publish a managed container image" in output assert "ghcr.io" not in output + + +def test_a_stalled_install_probe_is_reported_instead_of_crashing(monkeypatch, capsys): + """``_detect_install`` re-raises ``UpdateTimeout`` so the user gets actionable copy. + + The call used to sit *outside* ``main()``'s ``try``, so the crafted message was thrown + away and a stalled `pip show` printed a traceback — the one outcome the exception was + written to prevent. + """ + + def _stall(): + raise update.UpdateTimeout( + "Reading the installed Engraphis metadata timed out after 60s. Check your " + "network connection, proxy settings, and package index, then run " + "`engraphis-update` again." + ) + + monkeypatch.setattr(update, "_detect_install", _stall) + + with pytest.raises(SystemExit) as exc: + update.main([]) + + assert exc.value.code == 1 + captured = capsys.readouterr() + assert "timed out" in captured.err + assert "engraphis-update" in captured.err + assert "Traceback" not in captured.err + + +# ── a budget is only real if nothing can outlive it ─────────────────────────── +def test_every_git_step_closes_stdin_and_refuses_a_credential_prompt(monkeypatch, tmp_path): + """An expired token must fail the step, not open a prompt nobody is there to answer. + + ``git`` otherwise reads a username from the terminal (or raises the Git Credential + Manager dialog on Windows) and blocks past every budget above it, with no network + fault to diagnose. + """ + + project = tmp_path / "clone" + (project / ".git").mkdir(parents=True) + monkeypatch.setattr(update.shutil, "which", lambda _name: "git") + monkeypatch.setattr(update, "LATEST_TAG", "v1.2.3") + calls = [] + + def fake_run(command, **kwargs): + calls.append((list(command), kwargs)) + if command[:4] == [sys.executable, "-m", "pip", "show"]: + return SimpleNamespace( + returncode=0, stdout=f"Editable project location: {project}\n") + if "rev-parse" in command: + return SimpleNamespace(returncode=0, stdout="old-sha\n") + if "symbolic-ref" in command: + return SimpleNamespace(returncode=0, stdout="main\n") + if "rev-list" in command: + return SimpleNamespace(returncode=0, stdout="new-sha\n") + return SimpleNamespace(returncode=0, stdout="") + + monkeypatch.setattr(update.subprocess, "run", fake_run) + + update._git_update(check_only=True) + + git_calls = [(cmd, kwargs) for cmd, kwargs in calls if cmd[0] == "git"] + assert git_calls, "expected the editable path to shell out to git" + for command, kwargs in git_calls: + assert kwargs["stdin"] is subprocess.DEVNULL, command + assert kwargs["env"]["GIT_TERMINAL_PROMPT"] == "0", command + assert kwargs["env"]["GCM_INTERACTIVE"] == "never", command + # The fetch's own budget is only honoured while there is no pipe left to drain. + fetches = [kwargs for cmd, kwargs in git_calls if "fetch" in cmd] + assert fetches and fetches[0]["capture_output"] is False + assert fetches[0]["timeout"] == update._GIT_FETCH_TIMEOUT_S + + +def test_the_remote_tag_query_parses_stdout_through_the_bounded_reader(monkeypatch): + """It must keep its stdout — so it may not simply stop capturing; it changes *how*.""" + + monkeypatch.setattr( + update.subprocess, "run", + lambda *a, **k: pytest.fail("a network query must not use the unenforceable path"), + ) + seen = {} + + def fake_captured(cmd, what, timeout, env=None): + seen.update(cmd=list(cmd), timeout=timeout, env=env) + return SimpleNamespace( + returncode=0, + stdout="a\trefs/tags/v0.9.0\nb\trefs/tags/v1.0.0\nc\trefs/heads/main\n", + ) + + monkeypatch.setattr(update, "_run_captured", fake_captured) + + assert update._remote_latest_tag("git", "https://example.test/e.git") == "v1.0.0" + assert seen["timeout"] == update._GIT_LS_REMOTE_TIMEOUT_S + assert seen["env"]["GIT_TERMINAL_PROMPT"] == "0" + + +def test_the_bounded_reader_pipes_only_stdout_and_never_prompts(monkeypatch): + """Fewer pipes is fewer handles a grandchild can hold open; stderr goes to the user.""" + + captured = {} + + class _Process: + pid = 4321 + returncode = 0 + + def communicate(self, timeout=None): + captured["drain_timeout"] = timeout + return "abc\trefs/tags/v2.0.0\n", None + + def fake_popen(cmd, **kwargs): + captured["cmd"] = list(cmd) + captured["kwargs"] = kwargs + return _Process() + + monkeypatch.setattr(update.subprocess, "Popen", fake_popen) + + result = update._run_captured(["git", "ls-remote"], "Listing", 60, env=update._git_env()) + + assert result.returncode == 0 + assert "v2.0.0" in result.stdout + assert captured["drain_timeout"] == 60 + assert captured["kwargs"]["stdout"] is subprocess.PIPE + assert captured["kwargs"]["stdin"] is subprocess.DEVNULL + assert "stderr" not in captured["kwargs"], "stderr must stay on the terminal" + assert captured["kwargs"]["env"]["GIT_TERMINAL_PROMPT"] == "0" + assert captured["kwargs"]["env"]["GCM_INTERACTIVE"] == "never" + + +# A child that outlives its parent and inherits the same stdout pipe — exactly the shape of +# ``git`` forking ``git-remote-https``. ``subprocess.run(capture_output=True, timeout=N)`` +# waits for this grandchild to exit no matter what ``N`` says. +_HOLDS_THE_PIPE = ( + "import subprocess, sys, time; " + "subprocess.Popen([sys.executable, '-c', 'import time; time.sleep(120)']); " + "time.sleep(120)" +) + + +def test_the_budget_holds_even_when_a_grandchild_still_owns_the_pipe(): + """The measured defect: a 5s budget returned after 21s, or never. Now it returns.""" + + started = time.monotonic() + with pytest.raises(update.UpdateTimeout) as exc: + update._run_captured([sys.executable, "-c", _HOLDS_THE_PIPE], "Stalled query", 2) + elapsed = time.monotonic() - started + + assert "timed out after 2s" in str(exc.value) + # Generous, because the point is the difference between "bounded" and "120 seconds". + assert elapsed < 30, "the budget was not enforced: waited %.1fs" % elapsed From 8abc7eb484ba26fa64cc625ceb0830b5824110e1 Mon Sep 17 00:00:00 2001 From: Jaixii Date: Sun, 26 Jul 2026 04:49:40 -0400 Subject: [PATCH 07/82] fix(cloud): scope the entitlement cache to its organization Addresses three review findings on PR #73. The cached entitlement was served without comparing its stored organization_id against the organization the installation is bound to now. Reconnecting or re-pinning to a different organization while reusing the same state directory therefore displayed the PREVIOUS organization's plan and features -- for up to the refresh interval, or indefinitely when refresh is disabled. The session path already rejected this mismatch; the cache now does too, and fails closed so a rejected cache immediately schedules the correcting fetch. hosted_plan_summary() resolved _plan_entitlement() twice, once directly and once via _hosted_plan(), doubling the cloud-session and cache reads -- and the chance of scheduling a background refresh -- on every /api/license and /api/bootstrap. The _hosted_plan override seam that tests rely on is preserved: when a caller rebinds it, its answer still wins. access_for_workspace() was annotated workspace_id: str while the org-scoped entitlement read passes None, so the refresh body carried "workspace_id": null. A control plane that requires a string would 4xx, and the whole compatibility fallback silently returns None, meaning the cache from GET /v1/entitlements/{org} would never be written for older control planes. The key is now omitted rather than sent as null. Also passes a _NoRedirect instance rather than the class in update_check, matching every other caller. Verified behaviour was already identical -- build_opener instantiates a passed class -- so this is consistency only. Co-Authored-By: Claude Opus 5 (1M context) --- engraphis/cloud_session.py | 22 ++-- engraphis/routes/v2_api.py | 62 ++++++++-- engraphis/update_check.py | 2 +- tests/test_hosted_plan_resolution.py | 175 +++++++++++++++++++++++++++ 4 files changed, 245 insertions(+), 16 deletions(-) diff --git a/engraphis/cloud_session.py b/engraphis/cloud_session.py index 83fa8da..6876176 100644 --- a/engraphis/cloud_session.py +++ b/engraphis/cloud_session.py @@ -348,13 +348,15 @@ def _refresh_http_error(status: int) -> CloudSessionError: return CloudSessionError("Engraphis Cloud could not refresh this session.") -def _post_refresh(control_url: str, refresh: str, workspace_id: str, +def _post_refresh(control_url: str, refresh: str, workspace_id: Optional[str], token_subject: str) -> dict: - payload = json.dumps({ - "refresh_credential": refresh, - "workspace_id": workspace_id, - "token_subject": token_subject, - }, sort_keys=True, separators=(",", ":")).encode("utf-8") + # An org-scoped entitlement read asks for an unbound token, so it passes no workspace. + # Serializing that as ``"workspace_id": null`` invites a 4xx from any control plane that + # requires the field to be a string; omit the key instead of sending an empty value. + body = {"refresh_credential": refresh, "token_subject": token_subject} + if workspace_id: + body["workspace_id"] = workspace_id + payload = json.dumps(body, sort_keys=True, separators=(",", ":")).encode("utf-8") request = urllib.request.Request( control_url + "/v1/tokens/refresh", data=payload, @@ -422,9 +424,13 @@ def configured(*, require_compute: bool = True) -> bool: def access_for_workspace( - workspace_id: str, *, require_compute: bool = True + workspace_id: Optional[str], *, require_compute: bool = True ) -> Tuple[str, str, str]: - """Return ``(access_token, organization_id, compute_url)`` for a bound workspace.""" + """Return ``(access_token, organization_id, compute_url)`` for a bound workspace. + + ``workspace_id`` may be ``None`` for an org-scoped read that deliberately wants an + unbound token; the refresh body then omits the field rather than sending ``null``. + """ direct_token = os.environ.get("ENGRAPHIS_CLOUD_ACCESS_TOKEN", "").strip() direct_org = os.environ.get("ENGRAPHIS_CLOUD_ORGANIZATION_ID", "").strip() diff --git a/engraphis/routes/v2_api.py b/engraphis/routes/v2_api.py index e93d50c..590da38 100644 --- a/engraphis/routes/v2_api.py +++ b/engraphis/routes/v2_api.py @@ -1830,6 +1830,30 @@ def _cloud_control_url() -> str: return str(saved.get("control_url") or "").strip().rstrip("/") +def _configured_organization_id() -> str: + """Return the organization this installation is bound to *right now*, or ``""``. + + A pinned ``ENGRAPHIS_CLOUD_ORGANIZATION_ID`` wins, exactly as it does in + ``cloud_session.access_for_workspace``; otherwise the saved session names it. Never + raises: an unreadable or absent session simply means "unknown", and an unknown + organization leaves the persisted answers in place rather than blanking a paying + customer's badge. + """ + + pinned = os.environ.get("ENGRAPHIS_CLOUD_ORGANIZATION_ID", "").strip() + if pinned: + return pinned + try: + from engraphis import cloud_session + loader = getattr(cloud_session, "_load", None) + saved = loader() if loader is not None else None + except Exception: # noqa: BLE001 - an unreadable session is simply "not configured" + return "" + if not isinstance(saved, dict): + return "" + return str(saved.get("organization_id") or "").strip() + + def _normalized_plan(value: object) -> str: """Map any control-plane plan name onto this client's presentation vocabulary.""" @@ -1931,12 +1955,24 @@ def _read_entitlement_cache() -> dict: fetched_at = float(value.get("fetched_at") or 0.0) except (TypeError, ValueError, OverflowError): fetched_at = 0.0 + # Whose plan is this? The cache lives in the state directory, which outlives a + # reconnect and is shared by every organization this installation is ever pointed at. + # Serving it unchecked kept the PREVIOUS organization's Pro/Team badge and feature + # grants on screen for a whole refresh interval — and indefinitely with + # ``ENGRAPHIS_CLOUD_ENTITLEMENT_REFRESH=0``. Fail closed and ignore a cache that names + # anyone else (or names nobody), exactly as ``_session_entitlement`` refuses a session + # plan recorded for a different organization. The refresh scheduled by the caller then + # writes the right one. + organization_id = str(value.get("organization_id") or "") + current = _configured_organization_id() + if current and organization_id != current: + return {} plan = _normalized_plan(stored_plan) return { "plan": plan, "features": _normalized_features(value.get("features"), plan), "cloud_access_active": bool(value.get("cloud_access_active")), - "organization_id": str(value.get("organization_id") or ""), + "organization_id": organization_id, "fetched_at": fetched_at, } @@ -2200,6 +2236,14 @@ def _hosted_plan() -> str: return _plan_entitlement()["plan"] +#: The unpatched ``_hosted_plan``, captured so ``hosted_plan_summary`` can tell "nobody has +#: replaced the seam" from "somebody has". Calling ``_hosted_plan()`` unconditionally +#: resolved the entitlement a *second* time — two more state-file reads, and a second +#: chance to schedule a background refresh — on every ``/api/license`` and therefore every +#: ``/api/bootstrap`` request, for an answer already sitting in ``entitlement["plan"]``. +_DEFAULT_HOSTED_PLAN = _hosted_plan + + def hosted_plan_summary() -> dict: """Return the one plan answer every license surface reports. @@ -2209,12 +2253,16 @@ def hosted_plan_summary() -> dict: entitlement = _plan_entitlement() # ``_hosted_plan`` is the single override seam; when a caller replaces it, its answer - # wins and the feature list falls back to this client's plan table. - plan = _hosted_plan() - if plan != entitlement["plan"]: - entitlement = {"plan": plan, "features": entitled_features(plan), - "source": "override", "cloud_access_active": plan != "local", - "checked_at": 0.0} + # wins and the feature list falls back to this client's plan table. Left alone it + # returns exactly ``_plan_entitlement()["plan"]``, so it is consulted only when it has + # actually been replaced — calling it unconditionally repeated the resolution above + # verbatim, state-file reads and refresh scheduling included. + if _hosted_plan is not _DEFAULT_HOSTED_PLAN: + plan = _hosted_plan() + if plan != entitlement["plan"]: + entitlement = {"plan": plan, "features": entitled_features(plan), + "source": "override", "cloud_access_active": plan != "local", + "checked_at": 0.0} return { "plan": entitlement["plan"], "features": list(entitlement["features"]), diff --git a/engraphis/update_check.py b/engraphis/update_check.py index dd63031..d5d711e 100644 --- a/engraphis/update_check.py +++ b/engraphis/update_check.py @@ -168,7 +168,7 @@ def _fetch(url: str, timeout: float) -> Optional[dict]: # cloud_session, sync_relay): the vetted address is the one actually dialled, which # rejects private/reserved targets and closes the DNS-rebinding window between the # scheme check above and the connect. A plain ``build_opener`` had neither guard. - opener = build_pinned_https_opener(_NoRedirect) + opener = build_pinned_https_opener(_NoRedirect()) try: with opener.open(req, timeout=timeout) as resp: # nosec B310 - scheme checked above raw = resp.read(_MAX_BYTES + 1) diff --git a/tests/test_hosted_plan_resolution.py b/tests/test_hosted_plan_resolution.py index 7c43a24..46b79c0 100644 --- a/tests/test_hosted_plan_resolution.py +++ b/tests/test_hosted_plan_resolution.py @@ -29,6 +29,7 @@ import socket import threading import time +import typing import urllib.error import urllib.request from pathlib import Path @@ -420,6 +421,38 @@ def test_a_vetted_https_control_url_is_still_reached(monkeypatch) -> None: ] +def test_the_entitlement_refresh_never_sends_a_null_workspace_id(monkeypatch) -> None: + """The compatibility fallback mints an *unbound* token, so it passes no workspace. + + ``access_for_workspace`` is annotated ``workspace_id: str`` but is called with ``None``, + which ``_post_refresh`` serialises as ``"workspace_id": null``. A control plane that + requires a non-null workspace id answers 4xx, ``_fetch_authoritative_entitlement`` + swallows it and returns ``None``, and the cached ``GET /v1/entitlements/{org}`` answer + that older control planes depend on is never written at all. Omit the key instead. + """ + + _connect(monkeypatch, pinned_token=False) + cloud = _FakeControlPlane(_entitlement_dto("team")) + sent = [] + record = cloud.open + + def _capture(request, timeout=None): + sent.append(request.data) + return record(request, timeout=timeout) + + monkeypatch.setattr(cloud, "open", _capture) + _serve(monkeypatch, cloud) + + v2_api._fetch_authoritative_entitlement() + + payloads = [json.loads(body.decode("utf-8")) for body in sent if body] + assert payloads, "the token refresh was never made" + for payload in payloads: + assert payload.get("workspace_id", "absent") is not None, payload + hints = typing.get_type_hints(cloud_session.access_for_workspace) + assert hints["workspace_id"] == typing.Optional[str] + + @pytest.mark.parametrize("failure", [ urllib.error.HTTPError(CONTROL_URL, 401, "unauthorized", {}, io.BytesIO(b"{}")), urllib.error.HTTPError(CONTROL_URL, 402, "payment required", {}, io.BytesIO(b"{}")), @@ -961,6 +994,68 @@ def test_a_session_plan_for_another_organization_is_refused(monkeypatch) -> None assert v2_api._session_entitlement()["plan"] == "team" +def test_a_cached_entitlement_for_another_organization_is_refused(monkeypatch) -> None: + """The same guard, on the compatibility cache — which the session path already had. + + The cache file lives in the state directory, which outlives a reconnect and is shared + by every organization the installation is ever pointed at. Serving it unchecked showed + the PREVIOUS organization's Team badge and Team grant for a whole refresh interval, and + for ever with the refresh disabled. + """ + + _connect(monkeypatch) + path = v2_api._entitlement_cache_path() + path.parent.mkdir(parents=True, exist_ok=True) + v2_api._write_entitlement_cache({ + "plan": "team", "features": v2_api.entitled_features("team"), + "cloud_access_active": True, "organization_id": ORGANIZATION, + "fetched_at": time.time(), + }) + assert v2_api._read_entitlement_cache()["plan"] == "team" + + # Re-pinned to somebody else's organization, reusing the very same state directory. + # The kill switch models the worst case: nothing will ever correct a served stale answer. + monkeypatch.setenv("ENGRAPHIS_CLOUD_ORGANIZATION_ID", "org_somebody_else") + monkeypatch.setenv("ENGRAPHIS_CLOUD_ENTITLEMENT_REFRESH", "0") + + assert v2_api._read_entitlement_cache() == {} + payload = v2_api.get_license() + assert payload["plan_source"] != "cloud" + assert "team" not in payload["features"], "another organization's Team grant was served" + + # Nothing was destroyed: the file is still correct for the organization it names. + monkeypatch.setenv("ENGRAPHIS_CLOUD_ORGANIZATION_ID", ORGANIZATION) + assert v2_api._read_entitlement_cache()["plan"] == "team" + + +def test_a_cached_entitlement_follows_a_reconnected_session_not_just_a_pin( + monkeypatch, +) -> None: + """No pin at all: reconnecting the installation rebinds it, and the cache must follow.""" + + _connect(monkeypatch, pinned_token=False) + cloud_session.save_bootstrap( + {"refresh_credential": "engr_rt_bootstrap", "organization_id": ORGANIZATION, + "installation_id": "inst_1", "device_id": "dev_1", "token_subject": "member"}, + control_url=CONTROL_URL, compute_url=CONTROL_URL, + ) + v2_api._write_entitlement_cache({ + "plan": "team", "features": v2_api.entitled_features("team"), + "cloud_access_active": True, "organization_id": ORGANIZATION, + "fetched_at": time.time(), + }) + assert v2_api._read_entitlement_cache()["plan"] == "team" + + # The installation is connected again, this time to a different organization. + cloud_session.save_bootstrap( + {"refresh_credential": "engr_rt_bootstrap", "organization_id": "org_second_tenant", + "installation_id": "inst_1", "device_id": "dev_1", "token_subject": "member"}, + control_url=CONTROL_URL, compute_url=CONTROL_URL, + ) + + assert v2_api._read_entitlement_cache() == {} + + def test_an_unreadable_session_yields_no_entitlement_rather_than_raising( monkeypatch, ) -> None: @@ -1083,6 +1178,86 @@ def test_the_legacy_surface_still_reports_local_for_an_unconnected_installation( assert v1["features"] == [] +# ── (6b) the boot path resolves the plan once, and the override seam still works ── +def test_the_license_route_resolves_the_entitlement_exactly_once(monkeypatch) -> None: + """``_plan_entitlement`` reads the cloud session and the entitlement cache off disk and + can schedule a background refresh. ``hosted_plan_summary`` called it directly *and* + again through ``_hosted_plan``, doubling all of that on every ``/api/license`` — and + therefore on every ``/api/bootstrap``. + """ + + _connect(monkeypatch) + _serve(monkeypatch, _FakeControlPlane(_entitlement_dto("team"))) + monkeypatch.setenv("ENGRAPHIS_CLOUD_ENTITLEMENT_REFRESH", "0") + resolutions = [] + resolve = v2_api._plan_entitlement + + def _counted() -> dict: + resolutions.append(1) + return resolve() + + monkeypatch.setattr(v2_api, "_plan_entitlement", _counted) + + payload = v2_api.get_license() + + assert payload["plan"] == "pro" + assert len(resolutions) == 1, "the plan was resolved %d times per request" % len( + resolutions + ) + + +def test_one_resolution_also_covers_the_legacy_license_surface(monkeypatch) -> None: + """``/memory/license`` renders the same summary, so it inherited the same double read.""" + + import asyncio + + from engraphis.routes import memory as memory_routes + + _connect(monkeypatch) + _serve(monkeypatch, _FakeControlPlane(_entitlement_dto("team"))) + monkeypatch.setenv("ENGRAPHIS_CLOUD_ENTITLEMENT_REFRESH", "0") + reads = [] + read_cache = v2_api._read_entitlement_cache + + def _counted() -> dict: + reads.append(1) + return read_cache() + + monkeypatch.setattr(v2_api, "_read_entitlement_cache", _counted) + + asyncio.new_event_loop().run_until_complete(memory_routes.get_license()) + + assert len(reads) == 1, "the entitlement cache was read %d times" % len(reads) + + +def test_a_replaced_hosted_plan_still_overrides_the_resolved_entitlement( + monkeypatch, +) -> None: + """The override seam is load-bearing (tests/test_client_launch.py patches it). + + Resolving once must not mean ignoring a caller that replaced ``_hosted_plan``: its + answer still wins, and the feature list still falls back to this client's plan table. + """ + + _connect(monkeypatch) + _serve(monkeypatch, _FakeControlPlane(_entitlement_dto("team"))) + assert _settled_license(monkeypatch)["plan"] == "team" + + monkeypatch.setattr(v2_api, "_hosted_plan", lambda: "local") + payload = v2_api.get_license() + + assert payload["plan"] == "local" + assert payload["features"] == [] + assert payload["plan_source"] == "override" + assert payload["cloud_access_active"] is False + + monkeypatch.setattr(v2_api, "_hosted_plan", lambda: "team") + upgraded = v2_api.get_license() + + assert upgraded["plan"] == "team" + assert "team" in upgraded["features"] + + # ── (7) the shipped modules must still build on the supported floor ─────────── @pytest.mark.parametrize("relative", [ "engraphis/routes/v2_api.py", From d1f9670753584003718a1bcbd20ea413561bc232 Mon Sep 17 00:00:00 2001 From: Jaixii Date: Sun, 26 Jul 2026 04:49:41 -0400 Subject: [PATCH 08/82] fix(update): bound every step and roll back a failed checkout Addresses two more review findings on PR #73. _run() still reached subprocess.run(timeout=...) for non-captured steps, which kills only the immediate child. pip's resolver or git-remote-https could outlive the budget and keep touching the repository while the caller had already started rollback. Every step now goes through one spawn path with process-tree termination and a bounded post-kill drain, so capture selects whether stdout is piped rather than whether the budget is enforceable at all. git checkout tags/ -- the destructive step -- ran above the rollback try, so a timed-out or non-zero checkout raised straight past it and left an editable install partially switched while reporting only a timeout. It now sits inside the same boundary. A killed checkout can also strand .git/index.lock, which blocks every later git command: the lock is removed only when it was absent before our checkout started and the checkout we killed is the plausible author, and otherwise it is named for the user rather than deleted, so a lock held by another live git process is never touched. The rollback checkout now runs with check=True. A failed restore used to be silent while main() still reported the previous installation restored. Co-Authored-By: Claude Opus 5 (1M context) --- scripts/update.py | 194 ++++++++++++++++------ tests/test_client_launch.py | 74 +++++---- tests/test_update.py | 311 ++++++++++++++++++++++++++++++------ 3 files changed, 444 insertions(+), 135 deletions(-) diff --git a/scripts/update.py b/scripts/update.py index 3e157da..0eff71e 100644 --- a/scripts/update.py +++ b/scripts/update.py @@ -55,7 +55,9 @@ # ``os.killpg`` must target *our* tree, never the shell that launched the updater, so the # POSIX child gets its own session. Windows has no equivalent at spawn time — the tree is # walked by ``taskkill /T`` instead — and the keyword's Windows meaning changed in 3.13, -# so it is not passed there at all. +# so it is not passed there at all. Every step is spawned this way, not just the captured +# ones: a session is the only handle POSIX gives us on a *descendant*, and it has to exist +# before the child runs, not after the budget has already expired. _OWN_PROCESS_GROUP = {} if os.name == "nt" else {"start_new_session": True} @@ -120,43 +122,35 @@ def _kill_process_tree(process: subprocess.Popen) -> None: pass -def _run(cmd: list[str], what: str, timeout: int, check: bool = False, - capture: bool = False, env: dict | None = None) -> subprocess.CompletedProcess: - """Run *cmd* under an explicit budget; a stall raises instead of hanging forever. +def _bounded_call(cmd: list[str], what: str, timeout: int, capture: bool, + env: dict | None) -> subprocess.CompletedProcess: + """Run *cmd* under a budget that **nothing in its process tree** can outlive. - ``capture`` is opt-in and deliberately defaults to *off*. ``subprocess.run`` honours - ``timeout`` only when it has no pipes left to drain: once the budget expires CPython - kills the direct child and then calls ``communicate()`` with **no** timeout, so the - reader threads keep waiting until every inherited write handle on those pipes closes — - grandchildren included. Use ``capture=True`` only for local commands that fork nothing - (``pip show``, git plumbing against an existing clone). Anything that reaches the - network must go through :func:`_run_captured`, which kills the whole tree first. - - ``stdin`` is closed for every step: a subprocess that stops to read from a terminal is - the same indefinite hang as a stalled socket, and none of these commands has anything - to read. - """ - try: - return subprocess.run(cmd, capture_output=capture, text=True, check=check, - timeout=timeout, stdin=subprocess.DEVNULL, env=env) - except subprocess.TimeoutExpired: - raise _timed_out(what, timeout) from None + Every step lands here, because "bounded" has to mean the same thing for a step that is + merely displayed as for one that is parsed. ``subprocess.run(timeout=...)`` cannot + provide it, in two distinct ways: + * *With* pipes it does not even bound the call. Once the budget expires CPython kills + the direct child and then drains with an **unbounded** ``communicate()``, which waits + for every inherited write handle to close — ``git-remote-https`` included. + * *Without* pipes it returns on time but leaves the descendants running. ``pip``'s + resolver or a credential helper keeps writing to the environment and the repository + while the caller has already moved on to a rollback or a retry, which is precisely + the guarantee the budget is supposed to buy. -def _run_captured(cmd: list[str], what: str, timeout: int, - env: dict | None = None) -> subprocess.CompletedProcess: - """Run *cmd* for its stdout under a budget that is actually enforced. + So the child is spawned into its own session (POSIX) and the whole tree is torn down + with ``taskkill /T`` (Windows) before the pipe is re-read — and that drain is bounded + too, so a pipe a dead writer still owns cannot re-hang the call. - For the steps that must be *parsed* rather than merely displayed, so simply not - capturing is not an option. Only stdout is piped — stderr stays on the terminal, which - both surfaces git's own explanation of a failure and leaves one fewer inherited write - handle for a grandchild to hold open. On expiry the entire process tree is destroyed - *before* the pipe is drained, and even that drain is bounded, so the call returns on - schedule instead of waiting on ``git-remote-https``. + Only stdout is ever piped, and only when *capture* asks for it: stderr staying on the + terminal both surfaces git's own explanation of a failure and leaves one fewer + inherited write handle for a grandchild to hold open. ``stdin`` is closed for every + step — a subprocess that stops to read from a terminal is the same indefinite hang as + a stalled socket, and none of these commands has anything to read. """ process = subprocess.Popen( - cmd, stdout=subprocess.PIPE, stdin=subprocess.DEVNULL, text=True, env=env, - **_OWN_PROCESS_GROUP, + cmd, stdout=subprocess.PIPE if capture else None, stdin=subprocess.DEVNULL, + text=True, env=env, **_OWN_PROCESS_GROUP, ) try: stdout, _ = process.communicate(timeout=timeout) @@ -170,6 +164,90 @@ def _run_captured(cmd: list[str], what: str, timeout: int, return subprocess.CompletedProcess(cmd, process.returncode, stdout or "", None) +def _run(cmd: list[str], what: str, timeout: int, check: bool = False, + capture: bool = False, env: dict | None = None) -> subprocess.CompletedProcess: + """Run *cmd* under an explicit budget; a stall raises instead of hanging forever. + + ``capture`` stays opt-in — a pipe nobody reads is only another handle a grandchild can + hold open — but it no longer selects between an enforceable path and an unenforceable + one. Both go through :func:`_bounded_call`, so a timeout kills the descendants either + way. ``check`` keeps ``subprocess.run``'s meaning: a non-zero exit raises + ``CalledProcessError``. + """ + result = _bounded_call(cmd, what, timeout, capture, env) + if check and result.returncode: + raise subprocess.CalledProcessError(result.returncode, cmd, result.stdout, None) + return result + + +def _run_captured(cmd: list[str], what: str, timeout: int, + env: dict | None = None) -> subprocess.CompletedProcess: + """Run *cmd* for its stdout under a budget that is actually enforced. + + For the steps that must be *parsed* rather than merely displayed, so simply not + capturing is not an option. + """ + return _bounded_call(cmd, what, timeout, True, env) + + +def _index_lock(project_dir: Path) -> Path: + """Path to this clone's ``index.lock``, following a ``.git`` *file* when there is one. + + A worktree or submodule checkout records ``gitdir: `` in a plain file instead of + holding a ``.git`` directory, and the lock lives in the pointed-to git dir. Guessing + ``/.git/index.lock`` there would tell the user to delete a file that does not + exist while the real one keeps blocking every git command. + """ + git_dir = project_dir / ".git" + if git_dir.is_file(): + try: + pointer = git_dir.read_text(encoding="utf-8").strip() + except OSError: + pointer = "" + if pointer.startswith("gitdir:"): + target = Path(pointer.split(":", 1)[1].strip()) + git_dir = target if target.is_absolute() else project_dir / target + return git_dir / "index.lock" + + +def _release_index_lock(project_dir: Path, existed_before: bool, ours: bool) -> None: + """Clear the index lock our own killed checkout left — and only that one. + + A ``git checkout`` terminated at its budget dies still holding ``index.lock``, and + every later git command in the clone then fails with "Another git process seems to be + running" — the restore below first of all. But deleting the lock unconditionally is + worse than the failure it fixes: an unrelated, *live* git in the same clone would have + its index pulled out from under it mid-write. + + Two independent facts therefore have to line up before we touch it. The lock was absent + when this updater started the checkout, so it appeared during our own invocation; and + the checkout is one *we* killed. A git process that exits on its own always removes the + lock it created, so a lock surviving any other failure belongs to somebody else. When + it does, name the exact path and let the user decide — an unexplained wedged clone is + the outcome worth avoiding, not an unattended delete. + """ + lock = _index_lock(project_dir) + if not lock.exists(): + return + if ours and not existed_before: + try: + lock.unlink() + except OSError as exc: + print("Could not remove the index lock left by the interrupted checkout: %s " + "(%s). Delete that file, then re-run `engraphis-update`." % (lock, exc), + file=sys.stderr) + else: + print("Removed the index lock left by the interrupted checkout: %s" % lock, + file=sys.stderr) + return + print( + "A git index lock is present that this update did not create: %s\n" + "Another git process may be running in %s. Close it — or delete that file if none " + "is — then re-run `engraphis-update`." % (lock, project_dir), + file=sys.stderr, + ) + + def _select_latest_tag(tags) -> str: """Return the highest stable ``vMAJOR.MINOR.PATCH`` tag, ignoring other refs.""" parsed = [] @@ -356,42 +434,56 @@ def _git_update(check_only: bool = False) -> None: print("Refusing to update a working tree with uncommitted changes.", file=sys.stderr) sys.exit(1) print(f"Checking out release {tag}...") - _run([git, "-C", str(project_dir), "checkout", f"tags/{tag}"], - "Checking out the release tag", _GIT_CHECKOUT_TIMEOUT_S, - check=True, capture=False, env=_git_env()) - print(f"Reinstalling from {project_dir}...") + # The checkout is the destructive step, so it belongs *inside* the rollback boundary, + # not above it. Run outside, a checkout that exceeded its budget or exited non-zero + # raised straight past the restore and left an editable install partially switched + # while the CLI reported nothing but a timeout. + lock_existed = _index_lock(project_dir).exists() + stage = "checkout" try: + _run([git, "-C", str(project_dir), "checkout", f"tags/{tag}"], + "Checking out the release tag", _GIT_CHECKOUT_TIMEOUT_S, + check=True, capture=False, env=_git_env()) + stage = "reinstall" + print(f"Reinstalling from {project_dir}...") _run( [sys.executable, "-m", "pip", "install", "-e", str(project_dir)], "Reinstalling the editable checkout", _PIP_INSTALL_TIMEOUT_S, check=True, capture=False, ) - except (subprocess.CalledProcessError, UpdateTimeout): - # A failed *or stalled* reinstall must not strand a previously working editable - # checkout at a half-applied detached release. The tree is already on the new tag - # by this point, so a bare hang here is what wedges the install; catching the - # timeout is what lets this rollback run at all. Restore the original branch (or - # exact commit when it started detached) and best-effort reinstall, then - # propagate the original failure. + except (subprocess.CalledProcessError, UpdateTimeout) as exc: + # A failed *or stalled* checkout or reinstall must not strand a previously working + # editable install on a half-applied detached release. Catching the timeout is what + # lets this rollback run at all. Restore the original branch (or exact commit when + # it started detached) and reinstall, then propagate the original failure. print("Restoring the previous checkout...", file=sys.stderr) + # Only a checkout *we* terminated can have abandoned a lock; see _release_index_lock. + _release_index_lock( + project_dir, lock_existed, + ours=stage == "checkout" and isinstance(exc, UpdateTimeout), + ) + manual = ( + "Run `git -C %s checkout %s` and `%s -m pip install -e %s` to restore the " + "previous installation." % (project_dir, original_ref, sys.executable, project_dir) + ) try: _run([git, "-C", str(project_dir), "checkout", original_ref], "Restoring the previous checkout", _GIT_CHECKOUT_TIMEOUT_S, - capture=False, env=_git_env()) + check=True, capture=False, env=_git_env()) _run( [sys.executable, "-m", "pip", "install", "-e", str(project_dir)], "Reinstalling the previous checkout", _PIP_INSTALL_TIMEOUT_S, - capture=False, + check=True, capture=False, ) except UpdateTimeout: # Rollback itself stalled: name the two commands that finish it by hand # rather than exiting on a tree the user does not know has moved. - print( - "Rollback did not finish. Run `git -C %s checkout %s` and " - "`%s -m pip install -e %s` to restore the previous installation." - % (project_dir, original_ref, sys.executable, project_dir), - file=sys.stderr, - ) + print("Rollback did not finish. " + manual, file=sys.stderr) + except subprocess.CalledProcessError: + # The restore ran unchecked before, so a *failed* one was silent and main() + # still told the user the previous installation had been restored. It had not. + print("Rollback FAILED: the working tree may still be on %s. %s" + % (tag, manual), file=sys.stderr) raise print(f"Updated to {tag}.") diff --git a/tests/test_client_launch.py b/tests/test_client_launch.py index 403a699..b8ae237 100644 --- a/tests/test_client_launch.py +++ b/tests/test_client_launch.py @@ -185,10 +185,15 @@ def test_main_reports_a_stalled_step_and_exits(monkeypatch, capsys) -> None: monkeypatch.setattr(updater, "_detect_install", lambda: "pypi") - def _stall(cmd, **kwargs): - raise subprocess.TimeoutExpired(cmd, kwargs.get("timeout")) + class _Stalled: + pid = 5150 + returncode = None + + def communicate(self, timeout=None): + raise subprocess.TimeoutExpired("pip", timeout) - monkeypatch.setattr(updater.subprocess, "run", _stall) + monkeypatch.setattr(updater.subprocess, "Popen", lambda cmd, **kwargs: _Stalled()) + monkeypatch.setattr(updater, "_kill_process_tree", lambda process: None) with pytest.raises(SystemExit) as excinfo: updater.main([]) @@ -216,48 +221,49 @@ def test_a_stalled_reinstall_still_rolls_back_the_checkout(monkeypatch, tmp_path calls = [] reinstalls = {"n": 0} - def _fake_run(cmd, **kwargs): - cmd = list(cmd) - calls.append(cmd) - assert kwargs.get("timeout"), "every step must carry a budget: %s" % cmd + class _Proc: + pid = 909 + + def __init__(self, returncode=0, stdout="", stall=False): + self.returncode = returncode + self._stdout = stdout + self._stall = stall - def done(stdout=""): - return subprocess.CompletedProcess(cmd, 0, stdout, "") + def communicate(self, timeout=None): + assert timeout, "every step must carry a budget" + if self._stall: + raise subprocess.TimeoutExpired("cmd", timeout) + return self._stdout, None + def _fake_popen(cmd, **kwargs): + cmd = list(cmd) + calls.append(cmd) if cmd[:4] == [sys.executable, "-m", "pip", "show"]: - return done("Editable project location: %s\n" % project) + return _Proc(stdout="Editable project location: %s\n" % project) if cmd[:5] == [sys.executable, "-m", "pip", "install", "-e"]: reinstalls["n"] += 1 - if reinstalls["n"] == 1: # the upgrade reinstall stalls - raise subprocess.TimeoutExpired(cmd, kwargs.get("timeout")) - return done() # the rollback reinstall succeeds + # the upgrade reinstall stalls; the rollback reinstall succeeds + return _Proc(stall=reinstalls["n"] == 1) + if "ls-remote" in cmd: + assert kwargs.get("stdout") is subprocess.PIPE, "the refs query must be parsed" + return _Proc(stdout="%s\trefs/tags/v9.9.9\n" % ("b" * 40)) if "rev-parse" in cmd: - return done("a" * 40 + "\n") + return _Proc(stdout="a" * 40 + "\n") if "symbolic-ref" in cmd: - return done("main\n") + return _Proc(stdout="main\n") if "rev-list" in cmd: - return done("b" * 40 + "\n") + return _Proc(stdout="b" * 40 + "\n") if "status" in cmd: - return done("") - assert "ls-remote" not in cmd, "the refs query must use the bounded reader" - return done() + return _Proc(stdout="") + return _Proc() - class _Refs: - pid = 909 - returncode = 0 - - def communicate(self, timeout=None): - assert timeout, "the bounded drain must carry a budget" - return "%s\trefs/tags/v9.9.9\n" % ("b" * 40), None - - def _fake_popen(cmd, **kwargs): - cmd = list(cmd) - calls.append(cmd) - assert "ls-remote" in cmd, "only the parsed network query needs a pipe: %s" % cmd - return _Refs() - - monkeypatch.setattr(updater.subprocess, "run", _fake_run) monkeypatch.setattr(updater.subprocess, "Popen", _fake_popen) + monkeypatch.setattr( + updater.subprocess, "run", + lambda *a, **k: pytest.fail("no step may spawn through the unenforceable path"), + ) + # Never let a fabricated pid reach the real ``taskkill``/``killpg``. + monkeypatch.setattr(updater, "_kill_process_tree", lambda process: None) with pytest.raises(updater.UpdateTimeout): updater._git_update() diff --git a/tests/test_update.py b/tests/test_update.py index a82928d..d5eb5c6 100644 --- a/tests/test_update.py +++ b/tests/test_update.py @@ -1,5 +1,7 @@ """The updater must never embed a stale release or select prerelease-like refs.""" import json +import os +import shutil import subprocess import sys import time @@ -11,6 +13,39 @@ from scripts import update +class _FakeProcess: + """A ``Popen`` stand-in: the updater reads ``pid``/``returncode`` and drains once. + + Every step now spawns through ``subprocess.Popen`` — that is the only way to hold on to + a handle for the *process tree* long enough to destroy it at the budget — so a fake + that intercepted ``subprocess.run`` would no longer see the call at all, and the real + ``pip``/``git`` would run instead. + """ + + def __init__(self, returncode=0, stdout=""): + self.pid = 4242 + self.returncode = returncode + self._stdout = stdout + self.drains = [] + + def communicate(self, timeout=None): + self.drains.append(timeout) + return self._stdout, None + + +def _spawner(handler, calls=None): + """Build a ``Popen`` fake from a ``cmd -> _FakeProcess`` *handler*.""" + + def fake_popen(command, **kwargs): + command = list(command) + process = handler(command) + if calls is not None: + calls.append((command, kwargs, process)) + return process + + return fake_popen + + def test_select_latest_stable_semver_tag(): assert update._select_latest_tag([ "v0.9.7", "v1.0.0", "v0.10.0", "v1.0.0rc1", "release/v9.0.0", @@ -35,10 +70,11 @@ def test_requested_version_must_be_a_stable_semver(value): def test_pypi_version_pin_is_applied_to_the_install_target(monkeypatch): calls = [] - monkeypatch.setattr(update.subprocess, "run", lambda command, **_kwargs: calls.append(command)) + monkeypatch.setattr(update.subprocess, "Popen", + _spawner(lambda _cmd: _FakeProcess(), calls)) monkeypatch.setattr(update, "LATEST_TAG", "v1.2.3") update._pip_update("pypi") - assert calls == [[ + assert [command for command, _kwargs, _proc in calls] == [[ update.sys.executable, "-m", "pip", "install", "--upgrade", "engraphis[server]==1.2.3", ]] @@ -48,11 +84,9 @@ def test_detects_noneditable_git_install_from_pep610_metadata(monkeypatch): monkeypatch.delenv("ENGRAPHIS_DOCKER", raising=False) monkeypatch.setattr(update.Path, "exists", lambda self: False) monkeypatch.setattr( - update.subprocess, - "run", - lambda *args, **kwargs: SimpleNamespace( - returncode=0, stdout="Name: engraphis\nLocation: /site-packages\n" - ), + update.subprocess, "Popen", + _spawner(lambda _cmd: _FakeProcess( + stdout="Name: engraphis\nLocation: /site-packages\n")), ) distribution = SimpleNamespace(read_text=lambda name: json.dumps({ "url": "https://github.com/Coding-Dev-Tools/engraphis.git", @@ -68,28 +102,23 @@ def test_noneditable_git_update_preserves_recorded_fork(monkeypatch): monkeypatch.setattr(update, "_installed_git_url", lambda: fork) monkeypatch.setattr(update, "LATEST_TAG", "v1.2.3") monkeypatch.setattr(update.shutil, "which", lambda _name: "git") - monkeypatch.setattr( - update.subprocess, - "run", - lambda command, **_kwargs: calls.append(command) - or SimpleNamespace(returncode=0, stdout=""), - ) + monkeypatch.setattr(update.subprocess, "Popen", + _spawner(lambda _cmd: _FakeProcess(), calls)) update._pip_update("git") - assert calls[-1][-1] == f"git+{fork}@v1.2.3#egg=engraphis" - assert update.REPO_URL not in calls[-1][-1] + last = calls[-1][0] + assert last[-1] == f"git+{fork}@v1.2.3#egg=engraphis" + assert update.REPO_URL not in last[-1] def test_non_git_pep610_install_is_not_misclassified(monkeypatch): monkeypatch.delenv("ENGRAPHIS_DOCKER", raising=False) monkeypatch.setattr(update.Path, "exists", lambda self: False) monkeypatch.setattr( - update.subprocess, - "run", - lambda *args, **kwargs: SimpleNamespace( - returncode=0, stdout="Name: engraphis\nLocation: /site-packages\n" - ), + update.subprocess, "Popen", + _spawner(lambda _cmd: _FakeProcess( + stdout="Name: engraphis\nLocation: /site-packages\n")), ) distribution = SimpleNamespace(read_text=lambda name: json.dumps({ "url": "https://example.com/archive", @@ -107,33 +136,29 @@ def test_failed_editable_reinstall_restores_original_branch(monkeypatch, tmp_pat calls = [] install_attempts = 0 - def fake_run(command, **kwargs): + def handler(command): nonlocal install_attempts - calls.append(command) if command[:4] == [update.sys.executable, "-m", "pip", "show"]: - return SimpleNamespace( - returncode=0, - stdout=f"Editable project location: {project}\n", - ) + return _FakeProcess(stdout=f"Editable project location: {project}\n") if "rev-parse" in command: - return SimpleNamespace(returncode=0, stdout="old-sha\n") + return _FakeProcess(stdout="old-sha\n") if "symbolic-ref" in command: - return SimpleNamespace(returncode=0, stdout="main\n") + return _FakeProcess(stdout="main\n") if "rev-list" in command: - return SimpleNamespace(returncode=0, stdout="new-sha\n") + return _FakeProcess(stdout="new-sha\n") if "status" in command: - return SimpleNamespace(returncode=0, stdout="") + return _FakeProcess(stdout="") if command[:4] == [update.sys.executable, "-m", "pip", "install"]: install_attempts += 1 if install_attempts == 1: - raise update.subprocess.CalledProcessError(1, command) - return SimpleNamespace(returncode=0, stdout="") + return _FakeProcess(returncode=1) + return _FakeProcess() - monkeypatch.setattr(update.subprocess, "run", fake_run) + monkeypatch.setattr(update.subprocess, "Popen", _spawner(handler, calls)) with pytest.raises(update.subprocess.CalledProcessError): update._git_update() - assert ["git", "-C", str(project), "checkout", "main"] in calls + assert ["git", "-C", str(project), "checkout", "main"] in [c for c, _k, _p in calls] assert install_attempts == 2 @@ -204,41 +229,47 @@ def test_every_git_step_closes_stdin_and_refuses_a_credential_prompt(monkeypatch monkeypatch.setattr(update, "LATEST_TAG", "v1.2.3") calls = [] - def fake_run(command, **kwargs): - calls.append((list(command), kwargs)) + def handler(command): if command[:4] == [sys.executable, "-m", "pip", "show"]: - return SimpleNamespace( - returncode=0, stdout=f"Editable project location: {project}\n") + return _FakeProcess(stdout=f"Editable project location: {project}\n") if "rev-parse" in command: - return SimpleNamespace(returncode=0, stdout="old-sha\n") + return _FakeProcess(stdout="old-sha\n") if "symbolic-ref" in command: - return SimpleNamespace(returncode=0, stdout="main\n") + return _FakeProcess(stdout="main\n") if "rev-list" in command: - return SimpleNamespace(returncode=0, stdout="new-sha\n") - return SimpleNamespace(returncode=0, stdout="") + return _FakeProcess(stdout="new-sha\n") + return _FakeProcess() - monkeypatch.setattr(update.subprocess, "run", fake_run) + monkeypatch.setattr(update.subprocess, "Popen", _spawner(handler, calls)) update._git_update(check_only=True) - git_calls = [(cmd, kwargs) for cmd, kwargs in calls if cmd[0] == "git"] + git_calls = [entry for entry in calls if entry[0][0] == "git"] assert git_calls, "expected the editable path to shell out to git" - for command, kwargs in git_calls: + for command, kwargs, _process in git_calls: assert kwargs["stdin"] is subprocess.DEVNULL, command assert kwargs["env"]["GIT_TERMINAL_PROMPT"] == "0", command assert kwargs["env"]["GCM_INTERACTIVE"] == "never", command - # The fetch's own budget is only honoured while there is no pipe left to drain. - fetches = [kwargs for cmd, kwargs in git_calls if "fetch" in cmd] - assert fetches and fetches[0]["capture_output"] is False - assert fetches[0]["timeout"] == update._GIT_FETCH_TIMEOUT_S + # Every step — not only the parsed ones — is spawned somewhere a whole tree can be + # killed from, or a descendant outlives the budget that was supposed to bound it. + for keyword, value in update._OWN_PROCESS_GROUP.items(): + assert kwargs.get(keyword) == value, command + # The fetch is displayed, not parsed: no pipe, and its budget rides on the drain. + fetches = [(kwargs, process) for cmd, kwargs, process in git_calls if "fetch" in cmd] + assert fetches and fetches[0][0].get("stdout") is None + assert fetches[0][1].drains == [update._GIT_FETCH_TIMEOUT_S] def test_the_remote_tag_query_parses_stdout_through_the_bounded_reader(monkeypatch): """It must keep its stdout — so it may not simply stop capturing; it changes *how*.""" + monkeypatch.setattr( + update.subprocess, "Popen", + lambda *a, **k: pytest.fail("the refs query must go through the bounded reader"), + ) monkeypatch.setattr( update.subprocess, "run", - lambda *a, **k: pytest.fail("a network query must not use the unenforceable path"), + lambda *a, **k: pytest.fail("nothing in the updater may spawn through subprocess.run"), ) seen = {} @@ -309,3 +340,183 @@ def test_the_budget_holds_even_when_a_grandchild_still_owns_the_pipe(): assert "timed out after 2s" in str(exc.value) # Generous, because the point is the difference between "bounded" and "120 seconds". assert elapsed < 30, "the budget was not enforced: waited %.1fs" % elapsed + + +def test_a_stalled_uncaptured_step_takes_its_descendants_with_it(tmp_path): + """The budget has to bound the *tree*, not just the process we happen to hold. + + ``pip install``, ``pipx`` and ``git fetch`` are displayed rather than parsed, so + ``subprocess.run(timeout=...)`` did return on time for them — and left the descendants + running. pip's vendored resolver or ``git-remote-https`` then keeps writing to the + environment and the repository *while the caller has already started a rollback or a + retry*, which is exactly the guarantee the budget is supposed to buy. Real processes, + because the whole class of bug is that mocks hid the platform's actual kill semantics. + """ + + sentinel = tmp_path / "descendant-outlived-the-budget" + grandchild = tmp_path / "grandchild.py" + grandchild.write_text( + "import sys, time\n" + "time.sleep(3)\n" + "open(sys.argv[1], 'w').write('still here')\n", + encoding="utf-8", + ) + child = tmp_path / "child.py" + child.write_text( + "import subprocess, sys, time\n" + "subprocess.Popen([sys.executable, sys.argv[1], sys.argv[2]])\n" + "time.sleep(60)\n", + encoding="utf-8", + ) + + started = time.monotonic() + with pytest.raises(update.UpdateTimeout) as exc: + update._run([sys.executable, str(child), str(grandchild), str(sentinel)], + "Installing the update", 2) + assert "timed out after 2s" in str(exc.value) + assert time.monotonic() - started < 30, "the call itself was not bounded" + + # Well past the moment the grandchild would have written, had it survived the kill. + deadline = time.monotonic() + 6 + while time.monotonic() < deadline and not sentinel.exists(): + time.sleep(0.2) + assert not sentinel.exists(), ( + "a descendant outlived the budget and was still touching the environment while " + "the updater had already moved on to rollback" + ) + + +# ── the destructive step belongs inside the rollback boundary ───────────────── +@pytest.fixture +def real_clone(tmp_path, monkeypatch): + """A real clone, with a real ``origin`` and a real release tag ahead of its HEAD. + + Real git, because the failure modes under test are git's own: what a checkout does + when ``index.lock`` exists, and what it leaves behind when it is killed holding one. + """ + + git = shutil.which("git") + if not git: # pragma: no cover - git is present everywhere this suite runs + pytest.skip("git is not installed") + + # Neutralise the developer's own git configuration: a global hooksPath, commit + # signing or a different init.defaultBranch would otherwise decide this test. + home = tmp_path / "home" + home.mkdir() + monkeypatch.setenv("GIT_CONFIG_GLOBAL", str(home / "gitconfig")) + monkeypatch.setenv("GIT_CONFIG_NOSYSTEM", "1") + monkeypatch.setenv("GIT_AUTHOR_NAME", "Engraphis Test") + monkeypatch.setenv("GIT_AUTHOR_EMAIL", "test@example.test") + monkeypatch.setenv("GIT_COMMITTER_NAME", "Engraphis Test") + monkeypatch.setenv("GIT_COMMITTER_EMAIL", "test@example.test") + + def run(*args, cwd): + subprocess.run([git, *args], cwd=str(cwd), check=True, env=dict(os.environ), + stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + + upstream = tmp_path / "upstream" + upstream.mkdir() + run("-c", "init.defaultBranch=main", "init", "-q", ".", cwd=upstream) + (upstream / "f.txt").write_text("one\n", encoding="utf-8") + run("add", "f.txt", cwd=upstream) + run("commit", "-qm", "one", cwd=upstream) + + clone = tmp_path / "clone" + run("clone", "-q", str(upstream), str(clone), cwd=tmp_path) + + (upstream / "f.txt").write_text("two\n", encoding="utf-8") + run("commit", "-qam", "two", cwd=upstream) + run("tag", "v9.9.9", cwd=upstream) + + return SimpleNamespace(git=git, clone=clone) + + +def _branch_of(git, project): + return subprocess.run([git, "-C", str(project), "rev-parse", "--abbrev-ref", "HEAD"], + capture_output=True, text=True).stdout.strip() + + +def _pip_router(project, pip_calls): + """Let every git command run for real; answer pip without installing anything.""" + + real_run = update._run + + def routed(cmd, what, timeout, **kwargs): + cmd = list(cmd) + if cmd[:3] == [sys.executable, "-m", "pip"]: + pip_calls.append(cmd) + stdout = ("Editable project location: %s\n" % project + if cmd[3] == "show" else "") + return SimpleNamespace(returncode=0, stdout=stdout) + return real_run(cmd, what, timeout, **kwargs) + + return routed + + +def test_a_killed_checkout_clears_its_own_lock_and_is_rolled_back( + real_clone, monkeypatch, capsys): + """``git checkout tags/`` is the destructive step, so it needs the same guard. + + It used to run *above* the ``try:`` that performs the rollback: a checkout that blew + its 120s budget raised straight past the restore, leaving an editable install partially + switched while the CLI reported nothing but a timeout — and the git we killed left + ``.git/index.lock`` behind, which then blocks every subsequent git command in the clone. + """ + + project = real_clone.clone + lock = project / ".git" / "index.lock" + monkeypatch.setattr(update, "LATEST_TAG", "v9.9.9") + monkeypatch.setattr(update.shutil, "which", lambda _name: real_clone.git) + + pip_calls = [] + routed = _pip_router(project, pip_calls) + + def stalled_checkout(cmd, what, timeout, **kwargs): + cmd = list(cmd) + if cmd[-1] == "tags/v9.9.9": + lock.write_text("", encoding="utf-8") # what a killed checkout leaves behind + raise update.UpdateTimeout("Checking out the release tag timed out after 120s.") + return routed(cmd, what, timeout, **kwargs) + + monkeypatch.setattr(update, "_run", stalled_checkout) + + with pytest.raises(update.UpdateTimeout): + update._git_update() + + err = capsys.readouterr().err + assert "Restoring the previous checkout" in err, "the checkout skipped the rollback" + assert not lock.exists(), "our own killed checkout's lock still wedges the clone" + assert "Removed the index lock" in err and str(lock) in err + # The restore really ran, against a real repository. + assert _branch_of(real_clone.git, project) == "main" + assert pip_calls[-1][:5] == [sys.executable, "-m", "pip", "install", "-e"] + + +def test_a_lock_this_updater_did_not_create_is_named_not_deleted( + real_clone, monkeypatch, capsys): + """A pre-existing lock may belong to a *live* git; deleting it is worse than the wedge. + + Here the real ``git checkout`` really fails on the real lock, and so does the restore. + Both of those must be visible: the exact path the user has to deal with, and the fact + that the rollback did not succeed — which the unchecked restore used to swallow while + ``main()`` still claimed "the previous installation was restored when possible". + """ + + project = real_clone.clone + lock = project / ".git" / "index.lock" + lock.write_text("", encoding="utf-8") # left by something else, before we start + + monkeypatch.setattr(update, "LATEST_TAG", "v9.9.9") + monkeypatch.setattr(update.shutil, "which", lambda _name: real_clone.git) + pip_calls = [] + monkeypatch.setattr(update, "_run", _pip_router(project, pip_calls)) + + with pytest.raises(subprocess.CalledProcessError): + update._git_update() + + err = capsys.readouterr().err + assert "Restoring the previous checkout" in err, "the checkout skipped the rollback" + assert lock.exists(), "a lock this updater did not create must not be deleted" + assert "did not create" in err and str(lock) in err + assert "Rollback FAILED" in err, "a failed restore must not be reported as a success" + assert _branch_of(real_clone.git, project) == "main" From eab8a4c5c0f41f394b74ca238c620b8084bda97f Mon Sep 17 00:00:00 2001 From: Jaixii Date: Sun, 26 Jul 2026 05:09:40 -0400 Subject: [PATCH 09/82] fix(cloud): let a billing denial clear the cached paid access Addresses a review finding on PR #73. A lapsed subscription answers 402 on token refresh. That is the control plane's authoritative billing answer, but it was caught by the same broad handler as offline/revoked/invalid and discarded. Because the saved session outranks the entitlement cache, cloud_access_active stayed true and the dashboard kept advertising paid features indefinitely while every hosted operation was denied -- the same two-surfaces-disagree failure this branch set out to fix. record_billing_denial() persists the denial: the access flag and the grants are cleared, the plan name is kept so the UI can still say which plan lapsed. Only 402 does this; an outage must never look like a cancellation. Regression tests both ways -- verified that the denial test fails without the fix (cloud_access_active stayed true with the full feature list) and that a 503 leaves a paying customer's access intact. Co-Authored-By: Claude Opus 5 (1M context) --- engraphis/cloud_session.py | 31 +++++++++++++++++ engraphis/routes/v2_api.py | 14 +++++++- tests/test_hosted_plan_resolution.py | 51 ++++++++++++++++++++++++++++ 3 files changed, 95 insertions(+), 1 deletion(-) diff --git a/engraphis/cloud_session.py b/engraphis/cloud_session.py index 6876176..6c93c47 100644 --- a/engraphis/cloud_session.py +++ b/engraphis/cloud_session.py @@ -287,6 +287,37 @@ def saved_entitlement() -> dict: return {} +def record_billing_denial() -> bool: + """Mark the saved entitlement inactive after an authoritative billing denial. + + A lapsed subscription answers ``402`` on token refresh. That is a *billing* answer, not + a transport failure, and the saved session outranks the entitlement cache — so leaving + ``cloud_access_active`` true kept a dashboard advertising paid features indefinitely + while every hosted call was denied. Persisting the denial is what stops the two license + surfaces disagreeing. + + The plan name is deliberately kept so the UI can still say which plan lapsed; only the + access flag and the grants are cleared. Returns whether anything changed. Never raises: + this runs on the boot path. + """ + + try: + saved = _load() + if not saved: + return False + already_denied = ( + saved.get("cloud_access_active") is False and not saved.get("cloud_features") + ) + if already_denied: + return False + saved["cloud_access_active"] = False + saved["cloud_features"] = [] + _save(saved) + return True + except Exception: + return False + + def save_bootstrap(response: dict, *, control_url: str, compute_url: Optional[str] = None) -> None: """Persist the one-time bootstrap/refresh material returned by the control plane.""" diff --git a/engraphis/routes/v2_api.py b/engraphis/routes/v2_api.py index 590da38..4fffdb0 100644 --- a/engraphis/routes/v2_api.py +++ b/engraphis/routes/v2_api.py @@ -2042,7 +2042,19 @@ def _fetch_authoritative_entitlement() -> Optional[dict]: access_token, organization_id, _ = access_for_workspace( None, require_compute=False ) - except Exception: # noqa: BLE001 - offline, lapsed, revoked, invalid: all "not now" + except Exception as exc: # noqa: BLE001 - offline, lapsed, revoked, invalid + # A 402 is the control plane's authoritative answer that billing lapsed -- not a + # transport hiccup. The saved session outranks this cache, so treating it like any + # other failure left ``cloud_access_active`` true and kept paid features on the + # dashboard indefinitely while every hosted call was denied. Persist the denial so + # the two license surfaces cannot disagree; everything else is still "not now". + if getattr(exc, "status", None) == 402: + try: + from engraphis.cloud_session import record_billing_denial + + record_billing_denial() + except Exception: # noqa: BLE001 - a denial we cannot persist is still a denial + pass return None if not access_token or not organization_id: return None diff --git a/tests/test_hosted_plan_resolution.py b/tests/test_hosted_plan_resolution.py index 46b79c0..f44987b 100644 --- a/tests/test_hosted_plan_resolution.py +++ b/tests/test_hosted_plan_resolution.py @@ -902,6 +902,57 @@ def test_a_downgrade_drops_the_previous_plans_features_from_the_resolved_answer( assert set(SERVER_PLAN_FEATURES["pro"]) <= set(payload["features"]) +def test_a_billing_denial_stops_the_session_claiming_paid_access(monkeypatch) -> None: + """A 402 is an answer, not an outage. + + The saved session outranks the entitlement cache, so folding the control plane's 402 + in with offline/transport failures left ``cloud_access_active`` true and kept the + dashboard advertising paid features indefinitely -- while every hosted call was + denied. The plan name is kept so the UI can still say which plan lapsed. + """ + + _connect(monkeypatch, pinned_token=False) + _serve(monkeypatch, _FakeControlPlane(_entitlement_dto("team"), + registration=_registration_entitlement("team"))) + assert _settled_license(monkeypatch)["cloud_access_active"] is True + + def _lapsed(*_args, **_kwargs): + raise cloud_session.CloudSessionError("Subscription is not active.", status=402) + + monkeypatch.setattr(cloud_session, "access_for_workspace", _lapsed) + assert v2_api._fetch_authoritative_entitlement() is None + + record = cloud_session._load() + assert record.get("cloud_access_active") is False + assert record.get("cloud_features") == [] + assert record.get("plan") == "team", "the lapsed plan is still named for the UI" + + payload = v2_api.get_license() + assert payload["cloud_access_active"] is False + assert payload["features"] == [] + + +def test_a_transport_failure_is_not_mistaken_for_a_billing_denial(monkeypatch) -> None: + """Only 402 clears access. An outage must never look like a cancellation.""" + + _connect(monkeypatch, pinned_token=False) + _serve(monkeypatch, _FakeControlPlane(_entitlement_dto("team"), + registration=_registration_entitlement("team"))) + assert _settled_license(monkeypatch)["cloud_access_active"] is True + + def _offline(*_args, **_kwargs): + raise cloud_session.CloudSessionError( + "Engraphis Cloud is temporarily unreachable.", status=503, transient=True + ) + + monkeypatch.setattr(cloud_session, "access_for_workspace", _offline) + assert v2_api._fetch_authoritative_entitlement() is None + + record = cloud_session._load() + assert record.get("cloud_access_active") is True, "an outage revoked a paying customer" + assert "team" in record.get("cloud_features", []) + + def test_a_lapsed_subscription_declared_on_the_refresh_keeps_its_name( monkeypatch, ) -> None: From 0cfc1e52e58c99b1a37251b872b5604c4b98b73e Mon Sep 17 00:00:00 2001 From: Jaixii Date: Sun, 26 Jul 2026 05:28:49 -0400 Subject: [PATCH 10/82] fix(cloud): settle the compatibility cache on a billing denial too Follow-up to eab8a4c, which settled only the session record. Against an older control plane the refresh carries no entitlement fields, so that session stays planless: saved_entitlement() keeps answering {} and _plan_entitlement falls through to the compatibility cache, which went on advertising the paid plan while every cloud operation was denied. The denial has to settle both layers or it settles neither. _deny_entitlement_cache() clears the cached grants and access flag on 402 and keeps the plan name so the UI can still say which plan lapsed. Verified the new test fails without it -- the cache still reported cloud_access_active true. Co-Authored-By: Claude Opus 5 (1M context) --- engraphis/routes/v2_api.py | 33 ++++++++++++++++++++++++++++ tests/test_hosted_plan_resolution.py | 28 +++++++++++++++++++++++ 2 files changed, 61 insertions(+) diff --git a/engraphis/routes/v2_api.py b/engraphis/routes/v2_api.py index 4fffdb0..5726379 100644 --- a/engraphis/routes/v2_api.py +++ b/engraphis/routes/v2_api.py @@ -2003,6 +2003,34 @@ def _write_entitlement_cache(entitlement: dict) -> None: logger.debug("entitlement cache write skipped") +def _deny_entitlement_cache() -> None: + """Clear this cache's grants after an authoritative billing denial. + + ``cloud_session.record_billing_denial`` settles the session record, but an older + control plane omits the entitlement fields from it entirely — that session stays + planless, ``saved_entitlement()`` keeps answering ``{}``, and ``_plan_entitlement`` + falls through to *this* cache. Left alone it went on advertising paid features while + every cloud operation was denied, which is the same disagreement one layer down. + + The plan name is preserved so the UI can still say which plan lapsed; only the access + flag and the grants are cleared. Never raises: this runs on the refresh thread. + """ + + try: + cached = _read_entitlement_cache() + if not cached: + return + if not cached.get("cloud_access_active") and not cached.get("features"): + return + denied = dict(cached) + denied["cloud_access_active"] = False + denied["features"] = [] + denied["fetched_at"] = time.time() + _write_entitlement_cache(denied) + except Exception: # noqa: BLE001 - a denial we cannot persist is still a denial + logger.debug("entitlement cache denial skipped") + + def _fetch_authoritative_entitlement() -> Optional[dict]: """Re-read the plan from the control plane. Returns ``None`` when nothing was cached. @@ -2055,6 +2083,11 @@ def _fetch_authoritative_entitlement() -> Optional[dict]: record_billing_denial() except Exception: # noqa: BLE001 - a denial we cannot persist is still a denial pass + # Settle both layers. Against an older control plane the session carries no + # entitlement fields at all, so the session write above leaves it planless and + # the resolver falls through to the compatibility cache -- which would keep + # advertising the paid plan on its own. + _deny_entitlement_cache() return None if not access_token or not organization_id: return None diff --git a/tests/test_hosted_plan_resolution.py b/tests/test_hosted_plan_resolution.py index f44987b..70935b4 100644 --- a/tests/test_hosted_plan_resolution.py +++ b/tests/test_hosted_plan_resolution.py @@ -953,6 +953,34 @@ def _offline(*_args, **_kwargs): assert "team" in record.get("cloud_features", []) +def test_a_billing_denial_also_settles_the_compatibility_cache(monkeypatch) -> None: + """An older control plane leaves the session planless, so the cache must settle too. + + ``record_billing_denial`` writes the denial onto a session that carries no entitlement + fields, so ``saved_entitlement()`` still answers ``{}`` and the resolver falls through + to the compatibility cache. Unless that cache is settled as well, the dashboard keeps + advertising the paid plan while every cloud operation is denied. + """ + + _connect(monkeypatch, pinned_token=False) + # registration={} models the older control plane: no entitlement on the session. + _serve(monkeypatch, _FakeControlPlane(_entitlement_dto("team"), registration={})) + assert _settled_license(monkeypatch)["cloud_access_active"] is True + assert cloud_session.saved_entitlement() == {}, "the session must be planless here" + assert v2_api._read_entitlement_cache()["cloud_access_active"] is True + + def _lapsed(*_args, **_kwargs): + raise cloud_session.CloudSessionError("Subscription is not active.", status=402) + + monkeypatch.setattr(cloud_session, "access_for_workspace", _lapsed) + assert v2_api._fetch_authoritative_entitlement() is None + + cached = v2_api._read_entitlement_cache() + assert cached["cloud_access_active"] is False, "the cache still advertises paid access" + assert cached["features"] == [] + assert cached["plan"] == "team", "the lapsed plan is still named for the UI" + + def test_a_lapsed_subscription_declared_on_the_refresh_keeps_its_name( monkeypatch, ) -> None: From 8da56a277de1086476baa948da155e7c3738955d Mon Sep 17 00:00:00 2001 From: Jaixii Date: Sun, 26 Jul 2026 06:02:47 -0400 Subject: [PATCH 11/82] fix(cloud): treat 401 as reconnect, and surface real cloud errors Addresses four more review findings on PR #73. 401 was drawing the purchase panel. The cloud maps it to "the cloud session expired or was revoked; connect again" -- a credential problem, not a billing one -- so an already-paying customer whose refresh credential lapsed was sold the plan they already own. Only 402 and 501 are billing answers now; 401 falls through to the error branch where the reconnect instruction is what the customer reads. _managed_call flattened every CloudFeatureError into "managed cloud operation failed", so 429, 5xx and a non-consent 409 were indistinguishable and the actionable copy from _public_http_error / _public_session_error never reached anyone. Those messages are fixed local literals -- audited all 19 construction sites in cloud_features, the only interpolation being upgrade_url() and one template whose substituted value is one of two fixed strings -- so they pass through, bounded and control-character-checked, with the old placeholder kept as the fallback. An AST test now pins that invariant so a future f-string or reflected response field fails. Billing denials went unstamped: entitlement_checked_at never advanced and a repeat denial wrote nothing, so the 15-minute interval never suppressed the next attempt and every request rotated the credential again against a control plane that had already answered 402. Every denial is now stamped, including the repeat, in both the session record and the compatibility cache. Also replaces three PEP 604 dict | None annotations in scripts/update.py with Optional[dict]. Contrary to the finding these did not break import -- from __future__ import annotations keeps them as strings, verified on real 3.9.25 -- but typing.get_type_hints() did raise there, and the house style is 3.9-compatible syntax. Co-Authored-By: Claude Opus 5 (1M context) --- engraphis/cloud_session.py | 19 ++- engraphis/routes/v2_api.py | 47 +++++++- engraphis/static/dashboard.js | 12 +- scripts/update.py | 8 +- tests/e2e/commercial.spec.js | 23 +++- tests/test_cloud_session.py | 41 +++++++ tests/test_dashboard_auth_placement.py | 23 ++-- tests/test_dashboard_v2.py | 161 +++++++++++++++++++++++-- tests/test_hosted_plan_resolution.py | 143 ++++++++++++++++++++++ 9 files changed, 442 insertions(+), 35 deletions(-) diff --git a/engraphis/cloud_session.py b/engraphis/cloud_session.py index 6c93c47..3da5107 100644 --- a/engraphis/cloud_session.py +++ b/engraphis/cloud_session.py @@ -297,8 +297,18 @@ def record_billing_denial() -> bool: surfaces disagreeing. The plan name is deliberately kept so the UI can still say which plan lapsed; only the - access flag and the grants are cleared. Returns whether anything changed. Never raises: - this runs on the boot path. + access flag and the grants are cleared. Never raises: this runs on the boot path. + + A denial is also an *authoritative entitlement read*, so it stamps + ``entitlement_checked_at`` — on the repeat denial too, which is the steady state for a + lapsed account. Leaving the old timestamp in place kept ``saved_entitlement()`` + answering with a stale ``entitlement_checked_at``, so the caller's refresh interval + never suppressed anything: every ``/api/license`` and ``/api/bootstrap``, in every + worker, spent and rotated the refresh credential again against a control plane that had + already answered 402. Advancing the clock is what bounds that. + + Returns whether this denial newly revoked access; a repeat denial returns ``False`` even + though the timestamp was rewritten, so a caller can still tell the two apart. """ try: @@ -308,12 +318,11 @@ def record_billing_denial() -> bool: already_denied = ( saved.get("cloud_access_active") is False and not saved.get("cloud_features") ) - if already_denied: - return False saved["cloud_access_active"] = False saved["cloud_features"] = [] + saved["entitlement_checked_at"] = time.time() _save(saved) - return True + return not already_denied except Exception: return False diff --git a/engraphis/routes/v2_api.py b/engraphis/routes/v2_api.py index 5726379..fec6971 100644 --- a/engraphis/routes/v2_api.py +++ b/engraphis/routes/v2_api.py @@ -142,6 +142,41 @@ def _run(fn, *a, **k): raise HTTPException(status_code=500, detail={"error": "internal server error"}) +#: What the dashboard shows when a managed failure carries no usable public copy. +_MANAGED_ERROR_FALLBACK = "managed cloud operation failed" +#: Hard ceiling on the forwarded copy. Every message this boundary forwards is fixed, +#: status-keyed public text (see ``_managed_error_message``), so nothing legitimate comes +#: close; a message that does is by definition not the fixed copy and is dropped. +_MANAGED_ERROR_MAX_CHARS = 300 + + +def _managed_error_message(exc) -> str: + """Return the public copy a ``CloudFeatureError`` carries, or the generic fallback. + + ``CloudFeatureError`` is the *already redacted* form: every raise site in + ``cloud_features`` builds its message from fixed copy keyed on a status + (``_public_http_error`` / ``_public_session_error``) or from a local literal. Provider + bodies, ``CloudSessionError`` text and local state paths are all dropped before the + exception is constructed, which is the whole point of that type. + + Flattening it again here cost the customer the only actionable part: a 429 or a 5xx + ("temporarily busy", "temporarily unavailable" — retry) and a 409 ("could not accept the + current workspace state" — do not retry, fix the session) all rendered as one fixed + string, so the dashboard's error branch could not tell an outage from a conflict. + + The bound below is a boundary check, not the redaction: it keeps an unexpected message + (a future raise site that interpolates something, or a subclass raised elsewhere) from + becoming an unbounded, control-character-carrying string in a JSON error body. + """ + + message = " ".join(str(exc).split()) + if not message or len(message) > _MANAGED_ERROR_MAX_CHARS: + return _MANAGED_ERROR_FALLBACK + if any(ord(char) < 0x20 or ord(char) == 0x7F for char in message): + return _MANAGED_ERROR_FALLBACK + return message + + def _managed_call(fn, *args, **kwargs): """Map the public cloud-client protocol onto structured dashboard errors.""" from engraphis.cloud_features import CloudFeatureError @@ -151,7 +186,7 @@ def _managed_call(fn, *args, **kwargs): except CloudFeatureError as exc: logger.warning("managed cloud operation failed (%s, status=%s, transient=%s)", type(exc).__name__, exc.status, exc.transient) - detail = {"error": "managed cloud operation failed", "managed_cloud": True, + detail = {"error": _managed_error_message(exc), "managed_cloud": True, "transient": exc.transient} if exc.code == "consent_required": detail["code"] = exc.code @@ -2014,14 +2049,20 @@ def _deny_entitlement_cache() -> None: The plan name is preserved so the UI can still say which plan lapsed; only the access flag and the grants are cleared. Never raises: this runs on the refresh thread. + + ``fetched_at`` advances on *every* denial, including the repeat denial that finds the + cache already settled. That case used to return without writing anything, which left + ``_plan_entitlement`` serving a stale ``fetched_at`` and + ``_refresh_entitlement_in_background`` re-scheduling a token refresh on every request + against an account the control plane had already answered 402 for. A denial is an + authoritative read; it has to advance the clock exactly as + ``cloud_session.record_billing_denial`` now does one layer up. """ try: cached = _read_entitlement_cache() if not cached: return - if not cached.get("cloud_access_active") and not cached.get("features"): - return denied = dict(cached) denied["cloud_access_active"] = False denied["features"] = [] diff --git a/engraphis/static/dashboard.js b/engraphis/static/dashboard.js index a45916c..902f0e0 100644 --- a/engraphis/static/dashboard.js +++ b/engraphis/static/dashboard.js @@ -185,9 +185,13 @@ function statMini(v,l,color){const tone=color==='var(--red)'?' tone-red':(color= function renderAnalytics(a,isPortfolio){const t=a.totals||{},f=a.decay_forecast||{};const weeks=a.growth_weekly||[];const gp=Math.max(...weeks,1);const gitems=weeks.map((n,i)=>{const back=weeks.length-1-i;return barRow(back===0?'now':back+'w ago',n,gp,'var(--accent-dim)')}).join('')||'
No data
';const hist=a.retention_histogram||{};const hc=hist.counts||[],hb=hist.buckets||[];const hp=Math.max(...hc,1);const hitems=hb.map((b,i)=>barRow(b,hc[i]||0,hp,'var(--green)')).join('');const mix=a.resolver_mix||{};const mk=Object.keys(mix);const mp=Math.max(...Object.values(mix),1);const mitems=mk.length?mk.map(k=>barRow(k,mix[k],mp,'var(--blue)')).join(''):'
No resolver events yet.
';const bt=a.by_type||{};const btk=Object.keys(bt);const bp=Math.max(...Object.values(bt),1);const btitems=btk.length?btk.map(k=>barRow(k,bt[k],bp,'var(--accent)')).join(''):'
No memories yet.
';const ents=a.top_entities||[];const ep=Math.max(...ents.map(e=>e.n),1);const eitems=ents.length?ents.map(e=>barRow(e.name+(isPortfolio&&e.workspace?' · '+e.workspace:''),e.n,ep,'var(--cyan)')).join(''):'
No entities yet — they appear as the graph grows.
';const avg=Math.round((t.avg_retention||0)*100);let wsTable='';if(isPortfolio&&a.workspaces){wsTable=`
Per-workspace breakdown
${a.workspaces.map(w=>``).join('')}
WorkspaceLivePinnedAvg ret.Fading 7d
${esc(w.workspace)}${w.live}${w.pinned}${Math.round((w.avg_retention||0)*100)}%${w.at_risk_7d}
`}return `
${statMini(t.live!=null?t.live:'—','Live memories')}${statMini(avg+'%','Avg retention',avg<40?'var(--red)':(avg<70?'var(--amber)':'var(--green)'))}${statMini(f.at_risk_7d!=null?f.at_risk_7d:'—','Fading ≤ 7 days',f.at_risk_7d>0?'var(--amber)':'')}${statMini(f.at_risk_30d!=null?f.at_risk_30d:'—','Fading ≤ 30 days')}${statMini(t.pinned!=null?t.pinned:'—','Pinned (protected)')}${isPortfolio?statMini(t.workspaces||0,'Workspaces'):statMini(t.superseded!=null?t.superseded:'—','Superseded (history)')}
Memories written per week
${gitems}
Retention distribution
${hitems}
By type
${btitems}
Write-path resolver activity
${mitems}
Most connected entities
${eitems}
${wsTable}`} function managedConsentHtml(feature){return `
${esc(feature)} runs in Engraphis Cloud, and managed compute is turned off for this installation.
Connect this installation to Engraphis Cloud to enable it. Secret and session-scoped memories are never uploaded.
`} function managedConsentRequired(error){return error&&error.status===409&&error.detail&&error.detail.code==='consent_required'} -/* Entitlement failure — and only that. 401 unauthenticated, 402 subscription not active, - 501 feature not offered here: each means the customer's plan does not include what they - just opened, so each may draw the purchase panel. +/* Entitlement failure — and only that. 402 subscription not active and 501 feature not + offered here: each means the customer's plan does not include what they just opened, + so each may draw the purchase panel. + 401 is deliberately NOT here either. The cloud maps it to "the cloud session expired or + was revoked; connect again" — a credential problem, not a billing one. An already-paying + customer whose refresh credential lapsed was being sold a plan they own; 401 falls + through to the error branch so the reconnect instruction is what they actually read. 409 is deliberately NOT here. Every 409 this API emits is a *conflict*, never a billing answer: detail.code==='consent_required' means the customer IS entitled but managed compute is off for this installation (managedConsentRequired, above), and the rest are @@ -197,7 +201,7 @@ function managedConsentRequired(error){return error&&error.status===409&&error.d Neither predicate may branch on CURRENT_VIEW: doing so made both the consent branch and the plain-error branch unreachable on the analytics and automation views, which is the regression this comment previously described but the code did not implement. */ -function hostedFeatureUnavailable(error){return !!error&&(error.status===401||error.status===402||error.status===501)} +function hostedFeatureUnavailable(error){return !!error&&(error.status===402||error.status===501)} async function loadAnalytics(){const el=document.getElementById('analytics-body'),lock=document.getElementById('an-lock'),acts=document.getElementById('an-actions');el.innerHTML='
';try{const a=await api('/analytics?workspace='+encodeURIComponent(WS||''));setPlanPill(lock,(LIC&&LIC.is_trial)?'TRIAL':'CLOUD','pill pill-accent');showAs(acts,true,'flex');el.innerHTML=renderAnalytics(a,false)}catch(e){if(managedConsentRequired(e)){setPlanPill(lock,'CLOUD','pill pill-accent');showAs(acts,false);el.innerHTML=managedConsentHtml('Analytics')}else if(hostedFeatureUnavailable(e)){setPlanPill(lock,'PRO','pill pill-muted');showAs(acts,false);el.innerHTML=unlockHtml('Analytics','pro')}else{el.innerHTML='
'+esc(e.message)+'
'}}} /* ── hosted automation policy (Pro / Team) ── */ diff --git a/scripts/update.py b/scripts/update.py index 0eff71e..74fa5db 100644 --- a/scripts/update.py +++ b/scripts/update.py @@ -15,6 +15,8 @@ """ from __future__ import annotations +from typing import Optional + import importlib.metadata import json @@ -123,7 +125,7 @@ def _kill_process_tree(process: subprocess.Popen) -> None: def _bounded_call(cmd: list[str], what: str, timeout: int, capture: bool, - env: dict | None) -> subprocess.CompletedProcess: + env: Optional[dict]) -> subprocess.CompletedProcess: """Run *cmd* under a budget that **nothing in its process tree** can outlive. Every step lands here, because "bounded" has to mean the same thing for a step that is @@ -165,7 +167,7 @@ def _bounded_call(cmd: list[str], what: str, timeout: int, capture: bool, def _run(cmd: list[str], what: str, timeout: int, check: bool = False, - capture: bool = False, env: dict | None = None) -> subprocess.CompletedProcess: + capture: bool = False, env: Optional[dict] = None) -> subprocess.CompletedProcess: """Run *cmd* under an explicit budget; a stall raises instead of hanging forever. ``capture`` stays opt-in — a pipe nobody reads is only another handle a grandchild can @@ -181,7 +183,7 @@ def _run(cmd: list[str], what: str, timeout: int, check: bool = False, def _run_captured(cmd: list[str], what: str, timeout: int, - env: dict | None = None) -> subprocess.CompletedProcess: + env: Optional[dict] = None) -> subprocess.CompletedProcess: """Run *cmd* for its stdout under a budget that is actually enforced. For the steps that must be *parsed* rather than merely displayed, so simply not diff --git a/tests/e2e/commercial.spec.js b/tests/e2e/commercial.spec.js index 5fe4327..c6607e4 100644 --- a/tests/e2e/commercial.spec.js +++ b/tests/e2e/commercial.spec.js @@ -376,7 +376,7 @@ test('a lapsed Team subscription is sent to billing, not to a spent trial', asyn expect(errors).toEqual([]); }); -for (const cloudStatus of [401, 402, 501]) { +for (const cloudStatus of [402, 501]) { test(`Analytics and Automation defer to cloud proxy status ${cloudStatus}`, async ({ page }) => { const errors = recordBrowserErrors(page); const calls = await mockLocalClient(page, cloudStatus); @@ -423,6 +423,27 @@ for (const cloudStatus of [401, 402, 501]) { }); } +// 401 is a credential problem, not a billing one: the cloud maps it to "the cloud session +// expired or was revoked; connect again". Selling Pro to a customer who already owns it -- +// and who only needs to reconnect -- is the regression this guards. +test('An expired cloud session asks the customer to reconnect, not to buy', async ({ page }) => { + const errors = recordBrowserErrors(page); + await mockLocalClient(page, 401); + await page.goto('/'); + + await openView(page, 'analytics'); + const analytics = page.locator('#analytics-body'); + await expect(analytics).not.toContainText('Unlock Analytics and more'); + await expect(analytics.getByRole('link', { name: 'Purchase Pro license' })).toHaveCount(0); + + await openView(page, 'automation'); + const automation = page.locator('#automation-body'); + await expect(automation).not.toContainText('Unlock Automation'); + await expect(automation.getByRole('link', { name: 'Purchase Pro license' })).toHaveCount(0); + + expect(errors).toEqual([]); +}); + // Consent travels with the cloud account: connecting an installation accepts the terms // covering managed compute. A 409 consent_required therefore means "this installation is // not connected", never "go and hand-edit an environment variable", and it must never be diff --git a/tests/test_cloud_session.py b/tests/test_cloud_session.py index 1bc9853..dfbf612 100644 --- a/tests/test_cloud_session.py +++ b/tests/test_cloud_session.py @@ -392,3 +392,44 @@ def test_environment_refresh_rejects_invalid_subject(monkeypatch, subject) -> No else: with pytest.raises(cloud_session.CloudSessionError, match="device.*member"): cloud_session.configured(require_compute=False) + + +def test_record_billing_denial_stamps_every_denial_including_the_repeat() -> None: + """A 402 is an authoritative entitlement read, so it has to advance the clock. + + ``entitlement_checked_at`` is what ``_session_entitlement`` reports as ``fetched_at`` + and what the dashboard's 15-minute refresh interval throttles on. The denial used to + clear the grants without touching it -- and to write nothing whatsoever once the + session was already denied -- so a lapsed account re-rotated its single-use refresh + credential on every request, in every worker, forever. + """ + + cloud_session._save({ + "plan": "team", + "cloud_access_active": True, + "cloud_features": ["analytics", "team"], + "entitlement_checked_at": 1.0, + "organization_id": "org_1", + "refresh_credential": "engr_rt_saved", + }) + + assert cloud_session.record_billing_denial() is True + first = cloud_session._load() + assert first["cloud_access_active"] is False + assert first["cloud_features"] == [] + assert first["plan"] == "team", "the lapsed plan is still named for the UI" + assert first["refresh_credential"] == "engr_rt_saved", "the denial is not a disconnect" + stamped = first["entitlement_checked_at"] + assert stamped > 1.0, "the denial was never stamped as checked" + + # The steady state for a lapsed account: already denied, and aged past the interval. + aged = dict(first) + aged["entitlement_checked_at"] = stamped - 3600.0 + cloud_session._save(aged) + + assert cloud_session.record_billing_denial() is False, "nothing new was revoked" + repeated = cloud_session._load() + assert repeated["entitlement_checked_at"] >= stamped, ( + "a repeat denial must advance the clock the refresh interval reads" + ) + assert cloud_session.saved_entitlement()["entitlement_checked_at"] >= stamped diff --git a/tests/test_dashboard_auth_placement.py b/tests/test_dashboard_auth_placement.py index 01649f6..da32b1d 100644 --- a/tests/test_dashboard_auth_placement.py +++ b/tests/test_dashboard_auth_placement.py @@ -78,7 +78,7 @@ def test_hosted_views_delegate_entitlement_to_cloud_proxy_responses(): assert "unlockHtml" in body # The billing predicate itself, verbatim: the loaders delegate to it, so widening it # here is the only way a non-billing failure can reach ``unlockHtml``. - assert "error.status===401||error.status===402||error.status===501" in script + assert "error.status===402||error.status===501" in script assert "error.status===409" in script assert "Purchase Pro license" in script @@ -202,11 +202,15 @@ def test_a_consent_required_conflict_is_answered_with_the_consent_panel( @pytest.mark.skipif(shutil.which("node") is None, reason="node is required to run the UI") @pytest.mark.parametrize("view", ["analytics", "automation"]) -@pytest.mark.parametrize("status", [401, 402, 501]) +@pytest.mark.parametrize("status", [402, 501]) def test_a_genuine_entitlement_failure_still_renders_the_upgrade_panel( tmp_path, view, status, ): - """401 unauthenticated, 402 not subscribed, 501 not offered: all billing answers.""" + """402 not subscribed and 501 not offered are billing answers. 401 is not: + + the cloud maps it to "connect again", so it must reach the customer as a reconnect + instruction rather than a panel selling a plan they may already own. + """ rendered = _route(tmp_path, [{ "name": "unentitled", "view": view, "error": {"status": status}, @@ -220,11 +224,16 @@ def test_a_genuine_entitlement_failure_still_renders_the_upgrade_panel( @pytest.mark.skipif(shutil.which("node") is None, reason="node is required to run the UI") @pytest.mark.parametrize("view", ["analytics", "automation"]) -@pytest.mark.parametrize("status", [400, 500, 503]) +@pytest.mark.parametrize("status", [400, 401, 500, 503]) def test_a_non_billing_failure_shows_the_error_instead_of_selling_pro( tmp_path, view, status, ): - """A bad request or a cloud outage is not an unpaid invoice.""" + """A bad request, an expired session, or a cloud outage is not an unpaid invoice. + + 401 belongs here rather than with 402/501: the cloud maps it to "the cloud session + expired or was revoked; connect again". Drawing the purchase panel for it sold an + already-paying customer the plan they own, instead of telling them to reconnect. + """ rendered = _route(tmp_path, [{ "name": "broken", "view": view, @@ -267,10 +276,10 @@ def test_only_an_entitlement_status_may_draw_the_purchase_panel(): """ helper = _dashboard_function("hostedFeatureUnavailable") - assert "error.status===401||error.status===402||error.status===501" in helper + assert "error.status===402||error.status===501" in helper # No view may widen it and no fourth status may join it. assert "CURRENT_VIEW" not in helper - assert sorted(set(re.findall(r"status\s*===\s*(\d+)", helper))) == ["401", "402", "501"] + assert sorted(set(re.findall(r"status\s*===\s*(\d+)", helper))) == ["402", "501"] consent = _dashboard_function("managedConsentRequired") assert "error.status===409" in consent diff --git a/tests/test_dashboard_v2.py b/tests/test_dashboard_v2.py index 932eb5e..7ad408f 100644 --- a/tests/test_dashboard_v2.py +++ b/tests/test_dashboard_v2.py @@ -1,4 +1,7 @@ """Unified local dashboard tests for the public open-core boundary.""" +import ast +import io +import urllib.error from pathlib import Path import pytest @@ -9,6 +12,7 @@ from fastapi.testclient import TestClient # noqa: E402 from fastapi import HTTPException # noqa: E402 +from engraphis import cloud_features # noqa: E402 from engraphis.config import settings # noqa: E402 from engraphis.cloud_features import CloudFeatureError # noqa: E402 from engraphis.routes import v2_api # noqa: E402 @@ -118,8 +122,10 @@ def test_unconnected_automation_returns_a_structured_auth_error(monkeypatch, tmp response = client.get("/api/automation?workspace=demo") assert response.status_code == 401 + # The copy is ``_public_session_error(401)``: fixed, status-keyed, and actionable. The + # generic placeholder told an unconnected customer nothing they could act on. assert response.json()["detail"] == { - "error": "managed cloud operation failed", + "error": "Connect this installation to Engraphis Cloud to use hosted features.", "managed_cloud": True, "transient": False, } @@ -336,25 +342,156 @@ def fail_with(exc): assert ordinary_value_error.value.detail == {"error": "internal server error"} assert secret not in repr(ordinary_value_error.value.detail) - with pytest.raises(HTTPException) as managed: - v2_api._managed_call(fail_with, CloudFeatureError(secret, status=502)) - assert managed.value.status_code == 502 - assert managed.value.detail == { - "error": "managed cloud operation failed", "managed_cloud": True, - "transient": False, - } - assert secret not in repr(managed.value.detail) + +def test_managed_cloud_errors_forward_only_bounded_public_copy(): + """``_managed_call`` forwards the message; the bound is the boundary's own check. + + ``CloudFeatureError`` is the already-redacted form -- every raise site builds it from + fixed, status-keyed copy -- so its text is what the customer should read. The bound + here is not the redaction, it is the guard for a message that is *not* that fixed copy: + anything oversized, empty, or carrying control characters is dropped for the generic + placeholder rather than rendered into a JSON error body. + """ + + def fail_with(exc): + raise exc + + for message in ("x" * 301, "", "connection\x00reset", "trace\x1b[31m"): + with pytest.raises(HTTPException) as caught: + v2_api._managed_call(fail_with, CloudFeatureError(message, status=502)) + assert caught.value.status_code == 502 + assert caught.value.detail == { + "error": v2_api._MANAGED_ERROR_FALLBACK, "managed_cloud": True, + "transient": False, + } with pytest.raises(HTTPException) as consent: v2_api._managed_call( fail_with, - CloudFeatureError(secret, status=409, code="consent_required"), + CloudFeatureError( + "Managed compute is turned off for this installation.", + status=409, code="consent_required", + ), ) assert consent.value.status_code == 409 assert consent.value.detail == { - "error": "managed cloud operation failed", + "error": "Managed compute is turned off for this installation.", "managed_cloud": True, "transient": False, "code": "consent_required", } - assert secret not in repr(consent.value.detail) + + +def _managed_http_failure(monkeypatch, status: int) -> HTTPException: + """Drive one real hosted request against a control plane that answers ``status``.""" + + class _Opener: + def open(self, request, timeout=None): + raise urllib.error.HTTPError( + "https://compute.example.test/private", status, "failure", {}, + io.BytesIO(b'{"detail": "provider-internals https://backend.invalid"}'), + ) + + monkeypatch.setattr( + cloud_features, "build_pinned_https_opener", lambda *handlers: _Opener() + ) + client = cloud_features.CloudFeatureClient( + "https://compute.example.test", "org_1", "token" + ) + with pytest.raises(HTTPException) as caught: + v2_api._managed_call(client._request, "GET", "/private") + return caught.value + + +def test_a_managed_outage_is_distinguishable_from_a_workspace_conflict(monkeypatch): + """The defect: every hosted failure rendered as one fixed, unactionable string. + + ``cloud_features._public_http_error`` already produces redacted, status-keyed copy that + tells a retryable outage apart from a conflict the customer has to fix -- and + ``_managed_call`` threw all of it away, so the dashboard's error branch could only ever + show "managed cloud operation failed" for a 429, a 5xx and a 409 alike. + """ + + busy = _managed_http_failure(monkeypatch, 429) + down = _managed_http_failure(monkeypatch, 503) + conflict = _managed_http_failure(monkeypatch, 409) + + assert busy.status_code == 429 + assert busy.detail["transient"] is True + assert "temporarily busy" in busy.detail["error"], busy.detail["error"] + + assert down.status_code == 503 + assert down.detail["transient"] is True + assert "temporarily unavailable" in down.detail["error"], down.detail["error"] + + assert conflict.status_code == 409 + assert conflict.detail["transient"] is False + assert "workspace state" in conflict.detail["error"], conflict.detail["error"] + + messages = {busy.detail["error"], down.detail["error"], conflict.detail["error"]} + assert len(messages) == 3, "the dashboard still cannot tell these three apart" + assert v2_api._MANAGED_ERROR_FALLBACK not in messages + # Forwarding the public copy must not forward the provider's body with it. + assert all("provider-internals" not in text for text in messages) + assert all("backend.invalid" not in text for text in messages) + + +def test_every_managed_cloud_error_message_is_fixed_local_copy(): + """The invariant that makes forwarding safe, pinned against future raise sites. + + ``_managed_call`` may forward a ``CloudFeatureError`` message only because every one of + them is built from a literal in this repository -- never from a provider body, a + ``CloudSessionError``, or a local path. A raise site that interpolated a runtime value + would silently turn this boundary into a reflection point, so the shape is asserted + rather than trusted. + + Three forms are accepted: a string literal; a name bound from ``_public_http_error`` / + ``_public_session_error`` (both of which switch on a bare integer status and return + fixed copy); and the one audited ``%`` template, below. + """ + + source = Path(cloud_features.__file__).read_text(encoding="utf-8") + tree = ast.parse(source) + + public_copy = {"_public_http_error", "_public_session_error"} + from_public_copy = set() + for node in ast.walk(tree): + if not isinstance(node, ast.Assign) or not isinstance(node.value, ast.Call): + continue + called = node.value.func + if not isinstance(called, ast.Name) or called.id not in public_copy: + continue + for target in node.targets: + elements = target.elts if isinstance(target, ast.Tuple) else [target] + from_public_copy.update( + item.id for item in elements if isinstance(item, ast.Name) + ) + assert from_public_copy, "the fixed-copy helpers are no longer bound to a name" + + interpolated = [] + for node in ast.walk(tree): + if not isinstance(node, ast.Call): + continue + name = node.func.id if isinstance(node.func, ast.Name) else None + if name != "CloudFeatureError" or not node.args: + continue + message = node.args[0] + if isinstance(message, ast.Constant) and isinstance(message.value, str): + continue + if isinstance(message, ast.Name) and message.id in from_public_copy: + continue + # ``"literal %s" % (...)`` is allowed only where the substituted values are + # themselves constrained to local literals; ``run_job`` is the single such site + # and its ``status`` is guarded by an ``in {"failed", "canceled"}`` membership + # test one line above. Anything else -- an f-string, a bare name, a concatenated + # response field -- is a reflection risk and fails here. + if (isinstance(message, ast.BinOp) and isinstance(message.op, ast.Mod) + and isinstance(message.left, ast.Constant) + and message.left.value == "Managed %s did not complete (%s)."): + continue + interpolated.append((node.lineno, ast.dump(message)[:120])) + + assert interpolated == [], ( + "a CloudFeatureError message is no longer fixed local copy; _managed_call " + "forwards it to the customer: %r" % (interpolated,) + ) diff --git a/tests/test_hosted_plan_resolution.py b/tests/test_hosted_plan_resolution.py index 70935b4..83e18ca 100644 --- a/tests/test_hosted_plan_resolution.py +++ b/tests/test_hosted_plan_resolution.py @@ -981,6 +981,149 @@ def _lapsed(*_args, **_kwargs): assert cached["plan"] == "team", "the lapsed plan is still named for the UI" +def _age_session_clock(seconds: float = 3600.0) -> None: + """Push the saved session's entitlement stamp past any refresh interval.""" + + record = cloud_session._load() + record["entitlement_checked_at"] = time.time() - seconds + cloud_session._save(record) + + +def _lapsed_control_plane(monkeypatch) -> list: + """Answer every token refresh with the control plane's authoritative 402. + + Returns the list the attempts are appended to, so a test can count how many times the + single-use refresh credential was spent. + """ + + attempts = [] + + def _lapsed(*_args, **_kwargs): + attempts.append(time.time()) + raise cloud_session.CloudSessionError("Subscription is not active.", status=402) + + monkeypatch.setattr(cloud_session, "access_for_workspace", _lapsed) + # The real dial, not the 0 that ``_settled_license`` leaves behind: the guard under + # test is precisely that a just-recorded denial suppresses the next attempt. + monkeypatch.setattr(v2_api, "_ENTITLEMENT_REFRESH_SECONDS", 15 * 60) + return attempts + + +def test_a_billing_denial_is_stamped_so_the_next_refresh_is_suppressed( + monkeypatch, +) -> None: + """A 402 is an authoritative read and has to advance the clock that throttles. + + ``record_billing_denial`` cleared the grants but left ``entitlement_checked_at`` + untouched, so ``_session_entitlement`` kept reporting the old ``fetched_at``, the + 15-minute interval in ``_refresh_entitlement_in_background`` never matched, and every + subsequent ``/api/license`` -- in every worker -- spent and rotated the refresh + credential again against an account the control plane had already refused. Unbounded + credential rotation on a lapsed subscription. + """ + + _connect(monkeypatch, pinned_token=False) + _serve(monkeypatch, _FakeControlPlane(_entitlement_dto("team"), + registration=_registration_entitlement("team"))) + assert _settled_license(monkeypatch)["cloud_access_active"] is True + + attempts = _lapsed_control_plane(monkeypatch) + _age_session_clock() + + v2_api.get_license() + _drain_refresh() + assert len(attempts) == 1, "the aged session did not schedule the first re-check" + + settled = v2_api.get_license() + _drain_refresh() + assert settled["cloud_access_active"] is False + assert settled["features"] == [] + assert len(attempts) == 1, ( + "the denial left a stale clock, so the very next request rotated the credential " + "again against a control plane that had already answered 402" + ) + assert settled["plan_checked_at"] > time.time() - 60, "the denial was never stamped" + + v2_api.get_license() + _drain_refresh() + assert len(attempts) == 1, "the suppression did not hold for a second request" + + +def test_a_repeat_billing_denial_still_advances_the_refresh_clock(monkeypatch) -> None: + """The already-denied session is the steady state, and it wrote nothing at all. + + ``record_billing_denial`` returned early once ``cloud_access_active`` was already + ``False`` with no grants left, so the timestamp froze at whatever the last *successful* + read wrote. Every request after that saw an aged entitlement and refreshed again. + """ + + _connect(monkeypatch, pinned_token=False) + _serve(monkeypatch, _FakeControlPlane(_entitlement_dto("team"), + registration=_registration_entitlement("team"))) + assert _settled_license(monkeypatch)["cloud_access_active"] is True + + # The steady state: already denied, and aged past the refresh interval. + record = cloud_session._load() + record["cloud_access_active"] = False + record["cloud_features"] = [] + record["entitlement_checked_at"] = time.time() - 3600.0 + cloud_session._save(record) + + attempts = _lapsed_control_plane(monkeypatch) + + v2_api.get_license() + _drain_refresh() + assert len(attempts) == 1, "an aged denial must still be re-checked once" + + v2_api.get_license() + _drain_refresh() + v2_api.get_license() + _drain_refresh() + assert len(attempts) == 1, ( + "a repeat denial wrote nothing, so the clock never advanced and the lapsed " + "account kept being re-checked on every request" + ) + assert cloud_session._load()["plan"] == "team", "the lapsed plan is still named" + + +def test_a_repeat_denial_also_advances_the_compatibility_cache_clock(monkeypatch) -> None: + """The same freeze one layer down, on the control plane that has no session fields. + + ``_deny_entitlement_cache`` returned without writing once the cache was already + settled, so ``_plan_entitlement`` served a stale ``fetched_at`` and the refresh was + re-scheduled on every request -- the identical unbounded rotation, reached by the + older-control-plane path instead. + """ + + _connect(monkeypatch, pinned_token=False) + # registration={} models the older control plane: no entitlement on the session. + _serve(monkeypatch, _FakeControlPlane(_entitlement_dto("team"), registration={})) + assert _settled_license(monkeypatch)["cloud_access_active"] is True + assert cloud_session.saved_entitlement() == {}, "the session must be planless here" + + attempts = _lapsed_control_plane(monkeypatch) + + # Already denied, and aged past the interval. + cached = v2_api._read_entitlement_cache() + cached["cloud_access_active"] = False + cached["features"] = [] + cached["fetched_at"] = time.time() - 3600.0 + v2_api._write_entitlement_cache(cached) + + v2_api.get_license() + _drain_refresh() + assert len(attempts) == 1, "an aged cache must still be re-checked once" + + v2_api.get_license() + _drain_refresh() + assert len(attempts) == 1, ( + "the repeat denial left the cached clock stale, so the credential kept rotating" + ) + settled = v2_api._read_entitlement_cache() + assert settled["cloud_access_active"] is False + assert settled["plan"] == "team", "the lapsed plan is still named for the UI" + + def test_a_lapsed_subscription_declared_on_the_refresh_keeps_its_name( monkeypatch, ) -> None: From e3f9f78c9bacac9e2463b8633da6ee2cc130ef41 Mon Sep 17 00:00:00 2001 From: Jaixii Date: Sun, 26 Jul 2026 06:25:40 -0400 Subject: [PATCH 12/82] fix(cloud): serialize the denial write and distrust an unknown org Two review findings, both on code added earlier in this branch. The organization guard rejected only a mismatch. A fresh bootstrap carries just a refresh credential and a control URL, so the current organization is unknown until the first refresh names it -- and in that window a reused state directory served whatever it still held, i.e. the previous organization's paid plan, indefinitely with the refresh disabled. A cache scoped to an organization now requires a positive match, not merely the absence of a contradiction. record_billing_denial did an unguarded load-modify-save on the shared session file. Another worker rotating the credential concurrently could have its new value overwritten with the stale one; the control plane treats a spent credential as replay and revokes the whole family, so a lapsed subscription would have become a forced reconnect. The read, modify and save now happen inside the same _refresh_lock() that access_for_workspace rotates under. Verified the 402 reaches the handler with its status intact (a real 402 propagates out of access_for_workspace unrewritten) and that the lock is not re-entered on that path -- it has already unwound when the handler runs, which matters because _refresh_lock is not re-entrant. Co-Authored-By: Claude Opus 5 (1M context) --- engraphis/cloud_session.py | 32 +++++++++++------ engraphis/routes/v2_api.py | 8 ++++- tests/test_cloud_session.py | 53 ++++++++++++++++++++++++++++ tests/test_hosted_plan_resolution.py | 31 ++++++++++++++++ 4 files changed, 112 insertions(+), 12 deletions(-) diff --git a/engraphis/cloud_session.py b/engraphis/cloud_session.py index 3da5107..b539afe 100644 --- a/engraphis/cloud_session.py +++ b/engraphis/cloud_session.py @@ -312,17 +312,27 @@ def record_billing_denial() -> bool: """ try: - saved = _load() - if not saved: - return False - already_denied = ( - saved.get("cloud_access_active") is False and not saved.get("cloud_features") - ) - saved["cloud_access_active"] = False - saved["cloud_features"] = [] - saved["entitlement_checked_at"] = time.time() - _save(saved) - return not already_denied + # Under the same lock ``access_for_workspace`` rotates the credential with. This is a + # load-modify-save on the shared session file: unguarded, it could read the old + # single-use refresh credential while another worker was mid-rotation and then write + # that stale value back over the rotated one. The next hosted call would present a + # spent credential, which the control plane treats as replay and answers by revoking + # the whole credential family -- turning a lapsed subscription into a forced + # reconnect. + with _refresh_lock(): + saved = _load() + if not saved: + return False + already_denied = ( + saved.get("cloud_access_active") is False + and not saved.get("cloud_features") + ) + saved["cloud_access_active"] = False + saved["cloud_features"] = [] + saved["entitlement_checked_at"] = time.time() + # Inside the lock: a save that lands after release is exactly the race above. + _save(saved) + return not already_denied except Exception: return False diff --git a/engraphis/routes/v2_api.py b/engraphis/routes/v2_api.py index fec6971..baf2b0c 100644 --- a/engraphis/routes/v2_api.py +++ b/engraphis/routes/v2_api.py @@ -1998,9 +1998,15 @@ def _read_entitlement_cache() -> dict: # anyone else (or names nobody), exactly as ``_session_entitlement`` refuses a session # plan recorded for a different organization. The refresh scheduled by the caller then # writes the right one. + # An *unknown* current organization is not permission to trust an organization-scoped + # cache either. A fresh bootstrap has only a refresh credential and a control URL until + # the first refresh names the organization, so a reused state directory would otherwise + # serve the previous organization's paid plan for that whole window -- indefinitely with + # ``ENGRAPHIS_CLOUD_ENTITLEMENT_REFRESH=0``. Require a match, not merely the absence of + # a mismatch; the refresh the caller schedules writes the right answer. organization_id = str(value.get("organization_id") or "") current = _configured_organization_id() - if current and organization_id != current: + if not current or organization_id != current: return {} plan = _normalized_plan(stored_plan) return { diff --git a/tests/test_cloud_session.py b/tests/test_cloud_session.py index dfbf612..c5334e3 100644 --- a/tests/test_cloud_session.py +++ b/tests/test_cloud_session.py @@ -433,3 +433,56 @@ def test_record_billing_denial_stamps_every_denial_including_the_repeat() -> Non "a repeat denial must advance the clock the refresh interval reads" ) assert cloud_session.saved_entitlement()["entitlement_checked_at"] >= stamped + +def test_record_billing_denial_writes_under_the_refresh_lock(tmp_path, monkeypatch) -> None: + """The denial is a load-modify-save on the shared session file, so it must be serialized. + + Unguarded, it could read the old single-use refresh credential while another worker was + mid-rotation and write that stale value back over the rotated one. The control plane + treats a spent credential as replay and revokes the whole family, turning a lapsed + subscription into a forced reconnect. + """ + + monkeypatch.setenv("ENGRAPHIS_STATE_DIR", str(tmp_path)) + cloud_session._save({ + "schema": "engraphis-cloud-session/v1", + "control_url": "https://control.example.test", + "compute_url": "", + "organization_id": "org_paid", + "refresh_credential": "engr_rt_live", + "token_subject": "member", + "plan": "team", + "cloud_features": ["analytics", "team"], + "cloud_access_active": True, + }) + + held = [] + real_lock = cloud_session._refresh_lock + + import contextlib + + @contextlib.contextmanager + def _tracking_lock(): + with real_lock(): + held.append("in") + try: + yield + finally: + held.append("out") + + saved_while = [] + real_save = cloud_session._save + monkeypatch.setattr(cloud_session, "_refresh_lock", _tracking_lock) + monkeypatch.setattr( + cloud_session, "_save", + lambda v: (saved_while.append(held[-1] if held else None), real_save(v))[1], + ) + + assert cloud_session.record_billing_denial() is True + assert held == ["in", "out"], "the refresh lock was not taken" + assert saved_while == ["in"], "the session was written outside the refresh lock" + + record = cloud_session._load() + assert record["cloud_access_active"] is False + assert record["cloud_features"] == [] + assert record["refresh_credential"] == "engr_rt_live", "the credential was clobbered" diff --git a/tests/test_hosted_plan_resolution.py b/tests/test_hosted_plan_resolution.py index 83e18ca..8dbedf3 100644 --- a/tests/test_hosted_plan_resolution.py +++ b/tests/test_hosted_plan_resolution.py @@ -1250,6 +1250,37 @@ def test_a_cached_entitlement_for_another_organization_is_refused(monkeypatch) - assert v2_api._read_entitlement_cache()["plan"] == "team" +def test_a_cached_entitlement_is_refused_when_the_organization_is_unknown( + monkeypatch, +) -> None: + """An unknown current organization is not permission to trust the cache either. + + A fresh bootstrap carries only a refresh credential and a control URL, so + ``_configured_organization_id()`` is empty until the first refresh names the + organization. Rejecting only a *mismatch* left that window serving whatever the reused + state directory still held — the previous organization's paid plan, and for ever with + the refresh disabled. + """ + + _connect(monkeypatch) + path = v2_api._entitlement_cache_path() + path.parent.mkdir(parents=True, exist_ok=True) + v2_api._write_entitlement_cache({ + "plan": "team", "features": v2_api.entitled_features("team"), + "cloud_access_active": True, "organization_id": ORGANIZATION, + "fetched_at": time.time(), + }) + assert v2_api._read_entitlement_cache()["plan"] == "team" + + # The bootstrap window: connected, but nothing has named the organization yet. + monkeypatch.setattr(v2_api, "_configured_organization_id", lambda: "") + monkeypatch.setenv("ENGRAPHIS_CLOUD_ENTITLEMENT_REFRESH", "0") + + assert v2_api._read_entitlement_cache() == {}, ( + "a cache was trusted before the organization was known" + ) + + def test_a_cached_entitlement_follows_a_reconnected_session_not_just_a_pin( monkeypatch, ) -> None: From 6004a432fe851f0bb4c93e582ac175a01faf8127 Mon Sep 17 00:00:00 2001 From: Jaixii Date: Sun, 26 Jul 2026 13:04:01 -0400 Subject: [PATCH 13/82] feat(dashboard): opt-in canvas graph engine behind ?graph-engine=next A second knowledge-graph renderer wrapping the already-vendored force-graph, opt-in behind ?graph-engine=next. Classic stays the default and the rollback path; graphRender falls through to it on any failure. Four styles are applied CSP-safely through a data-graph-style attribute rather than inline style. Fixed while reviewing, before this shipped: - XSS. setData stamped name on every node, and force-graph's nodeLabel defaults to that accessor and renders through innerHTML. Node names are entity labels extracted from ingested memories. Classic never set name, so the sink did not exist until this feature added it. Both accessors are now explicit and escaped. - Recursive Tarjan overflowed the stack at roughly 29.6k nodes on a chain component; rewritten iteratively. - The rAF loop never stopped: a hidden canvas kept repainting for the whole session. Added pause/resume driven from selectView and a real destroy(). - Unbounded O(V*E) betweenness on the main thread with Array.shift queues, now lazy, pivot-sampled and budgeted: 60k nodes went 25s to 3s, and 0s in the default view. - prefers-reduced-motion was ignored, against an existing dashboard contract. The CSP drift gate never scanned this asset -- it only ever read index.html, dashboard.css and dashboard.js -- so "the gate passes" was vacuous for any new first-party script. Extended to hold them to the same contract and to check that every /static script index.html references actually exists. All four new rules were negative-tested. The original test asserted formatting strings. Replaced with 24 tests that execute the asset under Node with only a bare window in scope, which is itself the load-order proof, and mutation-tested: removing the escaping fails them. Co-Authored-By: Claude Opus 5 (1M context) --- engraphis/static/dashboard.css | 5 + engraphis/static/dashboard.js | 123 +++- engraphis/static/engraphis-graph.js | 833 ++++++++++++++++++++++++ engraphis/static/index.html | 2 + scripts/externalize_dashboard_assets.py | 48 +- tests/test_graph_engine_asset.py | 391 +++++++++++ 6 files changed, 1382 insertions(+), 20 deletions(-) create mode 100644 engraphis/static/engraphis-graph.js create mode 100644 tests/test_graph_engine_asset.py diff --git a/engraphis/static/dashboard.css b/engraphis/static/dashboard.css index fc2c328..59c4ec4 100644 --- a/engraphis/static/dashboard.css +++ b/engraphis/static/dashboard.css @@ -743,3 +743,8 @@ progress.graph-degree[data-graph-node-type="person_or_concept"]::-webkit-progres .gslider{display:flex;align-items:center;gap:8px;margin:6px 0}.gslider label{width:88px;flex-shrink:0;font-size:12px;color:var(--color-text-mute,var(--color-text-dim))}.gslider input[type=range]{flex:1;min-width:0;accent-color:var(--color-accent)} .gx-chip-full{width:100%;justify-content:flex-start;border-radius:7px;margin-bottom:2px} .gx-dot-dim{background:var(--color-text-dim,#888)} +#graph-net[data-graph-style="galaxy"]{background:radial-gradient(58% 50% at 24% 22%,rgba(126,64,208,.30),transparent 66%),radial-gradient(52% 58% at 82% 78%,rgba(220,72,164,.20),transparent 68%),radial-gradient(46% 52% at 62% 42%,rgba(58,120,224,.16),transparent 70%),#06040f} +#graph-net[data-graph-style="solar"]{background:radial-gradient(40% 48% at 50% 50%,rgba(255,184,92,.16),transparent 60%),radial-gradient(90% 90% at 50% 50%,rgba(18,32,64,.55),transparent 82%),#05070d} +#graph-net[data-graph-style="cyber"]{background:linear-gradient(rgba(34,224,255,.055) 1px,transparent 1px) 0 0/30px 30px,linear-gradient(90deg,rgba(34,224,255,.055) 1px,transparent 1px) 0 0/30px 30px,radial-gradient(72% 60% at 50% 0%,rgba(255,62,165,.12),transparent 72%),#050810} +#graph-net.engraphis-graph-node-hover{cursor:pointer} +#graph-net:not(.engraphis-graph-node-hover){cursor:grab} diff --git a/engraphis/static/dashboard.js b/engraphis/static/dashboard.js index 902f0e0..fd70616 100644 --- a/engraphis/static/dashboard.js +++ b/engraphis/static/dashboard.js @@ -105,6 +105,9 @@ function selectView(v){ /* Plan pills live in the topbar; clear them on navigation so only the active view's loader can repopulate one. */ ['an-lock','au-lock'].forEach(id=>{const p=document.getElementById(id);if(p){p.textContent='';p.className='pill pill-muted topbar-lock'}}); + /* The graph canvas is the only view that owns an animation loop. Park it while it is not + on screen so navigating away does not leave a hidden canvas repainting forever. */ + if(v==='graph')graphEngineResume();else graphEnginePause(); closeMobileNav(); (LOADERS[v]||function(){})(); heading.tabIndex=-1; @@ -474,7 +477,7 @@ function renderSync(d){const el=document.getElementById('sync-body');if(!el)retu async function syncNow(){const b=document.getElementById('sync-btn')||document.getElementById('sync-retry-btn');const original=b&&b.textContent;const s=document.getElementById('sync-status');if(b){b.disabled=true;b.textContent='Syncing…'}if(s)s.textContent='Contacting the cloud…';try{const d=await api('/sync/run',{method:'POST',headers:{'Content-Type':'application/json'},body:'{}'});const su=d.summary||{};toast('Synced — pushed '+(su.exported||0)+', '+(su.added||0)+' new from other devices','ok');await loadSyncStatus()}catch(e){if(e.status===401||e.status===402||e.status===403){const el=document.getElementById('sync-body');if(el)el.innerHTML=syncRecoveryHtml();toast(e.status===402?'Cloud Sync requires an active Pro or Team entitlement — open Engraphis Cloud to upgrade or renew.':'Cloud Sync authorization is no longer active — reconnect in Engraphis Cloud.','err');return}toast('Sync failed: '+e.message,'err');if(b){b.disabled=false;b.textContent=original||'Sync now'}if(s)s.textContent='Sync failed — try again.'}} /* ─── knowledge graph (force-graph + d3-force: compact defaults and selectable layouts) ─── */ -let GRAPH=null, FG=null, GRESIZE=false, GRESIZEFRAME=0, GADJ={}, GCOMM_ADJ={}, GCOMPONENTS={}, GCOMPONENT_LAYOUT=null, GHILITE=null, GHOVERSET=null, GLABELRANK={}, GLABELBOXES=[], GDATA_CACHE=null, GACTIVE_DATA=null, GREDRAWFRAME=0, GPERF={large:false,dense:false}; +let GRAPH=null, FG=null, GRAPH_ENGINE=null, GRESIZE=false, GRESIZEFRAME=0, GADJ={}, GCOMM_ADJ={}, GCOMPONENTS={}, GCOMPONENT_LAYOUT=null, GHILITE=null, GHOVERSET=null, GLABELRANK={}, GLABELBOXES=[], GDATA_CACHE=null, GACTIVE_DATA=null, GREDRAWFRAME=0, GPERF={large:false,dense:false}; const GRAPH_PRESETS={ original:{label:'Original force',repel:120,link:30,gravity:14,font:13,size:3,linkw:1,labelDensity:40,curve:0,particles:0}, compact:{label:'Compact clusters',repel:42,link:20,gravity:26,font:12,size:3,linkw:.7,labelDensity:30,curve:.08,particles:0}, @@ -528,6 +531,7 @@ function graphSetTypeColor(type,color,persist){ if(!type||!graphValidColor(color))return; GCOLOR_OVERRIDES[type]=color.toLowerCase();GCOLOR_PALETTE='custom'; const picker=document.getElementById('graph-palette');if(picker)picker.value='custom'; + if(GRAPH_ENGINE){GRAPH_ENGINE.setTypeColor(type,color);if(persist)graphSaveColorPreferences();return} graphRefreshNodeColors(); if(persist)graphSaveColorPreferences(); } @@ -553,7 +557,85 @@ function graphUpdateHud(data){ if(count&&data)count.textContent=data.nodes.length.toLocaleString()+' entities · '+data.links.length.toLocaleString()+' relations'; if(badge)badge.textContent=GPERF.large?'Large graph mode':'Adaptive rendering'; } -function graphInvalidateData(){GDATA_CACHE=null;GACTIVE_DATA=null;GCOMPONENT_LAYOUT=null;GHILITE=null;GHOVERSET=null} +/* ── opt-in next-generation renderer (`?graph-engine=next`) ────────────────────────────── + The classic renderer stays the default and the rollback path. Everything below is written + so that any failure in the opt-in engine degrades to classic rather than taking the graph + view down: one throw sets GRAPH_ENGINE_FAILED and the flag is never honoured again for the + life of the page. */ +let GRAPH_ENGINE_FAILED=false; +function graphEngineEnabled(){ + if(GRAPH_ENGINE_FAILED)return false; + try{return new URLSearchParams(window.location.search).get('graph-engine')==='next'}catch(e){return false} +} +function graphEngineFallback(error){ + GRAPH_ENGINE_FAILED=true; + try{if(GRAPH_ENGINE)GRAPH_ENGINE.destroy()}catch(e){} + GRAPH_ENGINE=null; + /* The classic renderer skips seeding when GACTIVE_DATA still points at the current data, + so a failure *after* a successful engine render would hand it an empty canvas. Clearing + the marker makes the very next graphRender() a full classic build. */ + GACTIVE_DATA=null;GCOMPONENT_LAYOUT=null;GHILITE=null;GHOVERSET=null; + if(window.console&&console.warn)console.warn('graph-engine=next failed; falling back to the classic renderer',error); +} +function graphEngineEmptyMessage(){ + const total=(GRAPH&&GRAPH.nodes&&GRAPH.nodes.length)||0; + return total?('No connected entities — tick "Show unlinked" to see all '+total+'.'):'No entities in this workspace yet.'; +} +function graphRenderEngine(data,fit,reheat){ + const element=document.getElementById('graph-net'),empty=document.getElementById('graph-empty'); + if(!element||typeof EngraphisGraph==='undefined')return false; + try{ + if(!data.nodes.length){ + if(GRAPH_ENGINE)GRAPH_ENGINE.setData({nodes:[],links:[]}); + showAs(empty,true,'flex'); + if(empty)empty.textContent=graphEngineEmptyMessage(); + GACTIVE_DATA=null;graphSetLayoutStatus('No entities',false);return true; + } + showAs(empty,false);GPERF={large:data.nodes.length>600||data.links.length>2400,dense:data.links.length>1500}; + const created=!GRAPH_ENGINE; + if(created){ + GRAPH_ENGINE=EngraphisGraph.create(element,{ + reducedMotion:prefersReducedMotion, + onNodeClick:node=>{syncGraphExplorerSelection(node.id);graphNodeClick(node.label||node.name||node.id)}, + onBackgroundClick:()=>graphSetHighlight(null), + onStats:stats=>{const count=document.getElementById('graph-hud-count');if(count)count.textContent=stats.nodes.toLocaleString()+' entities · '+stats.links.toLocaleString()+' relations'} + }); + } + /* Re-seeding identical data would re-copy every node and throw its x/y away, restarting + the layout on each slider or preset change. The classic path guards the same way. */ + const dataChanged=created||GACTIVE_DATA!==data; + const layers={};document.querySelectorAll('#graph-layer-filters input').forEach(input=>{layers[input.value]=input.checked}); + GRAPH_ENGINE.apply(engine=>{ + engine.setSettings({...window.GSET}); + engine.setStyle(typeof GSTYLE!=='undefined'?GSTYLE:'cyber'); + engine.setColorBy(typeof GCOLORBY!=='undefined'?GCOLORBY:'community'); + engine.setPalette(typeof GCOLOR_PALETTE!=='undefined'?GCOLOR_PALETTE:'theme'); + engine.setTypeColors(GCOLOR_OVERRIDES||{}); + engine.setLayers(layers); + if(dataChanged)engine.setData(data); + },fit,reheat&&!prefersReducedMotion()); + /* Mirror the engine's clustering back onto the dashboard's own node objects, or the + cluster legend (which reads GACTIVE_DATA) reports one community for the whole store. */ + const communityMap=GRAPH_ENGINE.communityMap(); + data.nodes.forEach(node=>{node.community=communityMap[node.id]||0}); + GACTIVE_DATA=data;graphSyncReadouts();graphUpdateEditedBadge();graphUpdateHud(data);graphRenderLegend(GRAPH); + if(dataChanged)graphSetHighlight(null); + if(window.GSET.frozen)GRAPH_ENGINE.freeze(true); + graphSetSimulationStatus(prefersReducedMotion()?'Static layout':'Adaptive layout',false); + return true; + }catch(error){ + graphEngineFallback(error); + return false; + } +} +/* Nav away from the graph view: park the engine's animation frame. Without this the opt-in + renderer keeps repainting a hidden canvas for the rest of the session. */ +function graphEnginePause(){try{if(GRAPH_ENGINE)GRAPH_ENGINE.pause()}catch(e){}} +function graphEngineResume(){try{if(GRAPH_ENGINE)GRAPH_ENGINE.resume()}catch(e){}} +function graphInvalidateData(){ + if(GRAPH_ENGINE){try{GRAPH_ENGINE.destroy()}catch(e){}GRAPH_ENGINE=null} + GDATA_CACHE=null;GACTIVE_DATA=null;GCOMPONENT_LAYOUT=null;GHILITE=null;GHOVERSET=null +} async function loadLegacyGraph(){ graphInjectCss();graphInvalidateData();GRAPH=null; const empty=document.getElementById('graph-empty'),net=document.getElementById('graph-net'),nodesBox=document.getElementById('graph-entity-list'),edgesBox=document.getElementById('graph-relation-list'); @@ -563,8 +645,8 @@ async function loadLegacyGraph(){ if(!GRESIZE){ GRESIZE=true; window.addEventListener('resize',()=>{ - if(!FG||GRESIZEFRAME)return; - GRESIZEFRAME=requestAnimationFrame(()=>{GRESIZEFRAME=0;const element=document.getElementById('graph-net');if(FG&&element)FG.width(element.clientWidth).height(element.clientHeight)}); + if((!FG&&!GRAPH_ENGINE)||GRESIZEFRAME)return; + GRESIZEFRAME=requestAnimationFrame(()=>{GRESIZEFRAME=0;const element=document.getElementById('graph-net');if(GRAPH_ENGINE)GRAPH_ENGINE.resize();else if(FG&&element)FG.width(element.clientWidth).height(element.clientHeight)}); }); } const layerInputs=Array.from(document.querySelectorAll('#graph-layer-filters input')),selectedLayers=layerInputs.filter(input=>input.checked).map(input=>input.value),layerFilter=selectedLayers.length===layerInputs.length?'':'&layers='+encodeURIComponent(selectedLayers.join(',')),includeCode=document.getElementById('graph-include-code').checked,repo=(document.getElementById('graph-repo-filter').value||'').trim(); @@ -711,6 +793,7 @@ function graphSetStyle(name){ if(['classic','galaxy','solar','cyber'].indexOf(name)<0)name='cyber'; GSTYLE=name;try{localStorage.setItem('engraphis-graph-style',name)}catch(e){} graphApplyStyleChrome(); + if(GRAPH_ENGINE){GRAPH_ENGINE.setStyle(name);return} if(GRAPH&&FG){graphRefreshNodeColors();graphRenderLegend();graphRender(false,false);} } /* ─── colorful graphs even when every node is one entity type: color by community or connections ─── */ @@ -766,6 +849,7 @@ function graphSetColorBy(mode){ if(['type','community','connections'].indexOf(mode)<0)mode='community'; GCOLORBY=mode;try{localStorage.setItem('engraphis-graph-colorby',mode)}catch(e){} var sel=document.getElementById('graph-colorby');if(sel&&sel.value!==mode)sel.value=mode; + if(GRAPH_ENGINE){GRAPH_ENGINE.setColorBy(mode);graphRenderLegend();return} if(GRAPH&&FG&&GACTIVE_DATA){graphComputeCommunities(GACTIVE_DATA.nodes);GMAXDEG=GACTIVE_DATA.nodes.reduce(function(m,n){return Math.max(m,n.degree||0);},1);graphRefreshNodeColors();graphRenderLegend();} } function graphApplyForces(){ @@ -790,6 +874,9 @@ function graphApplyForces(){ function graphSetHighlight(id){ GHILITE=id||null; GHOVERSET=id?new Set([id,...(GADJ[id]||[])]):null; + /* graphRedraw() is a no-op without the classic FG instance, so the opt-in engine needs + telling directly — otherwise hovering the entity list highlights nothing on canvas. */ + if(GRAPH_ENGINE){try{GRAPH_ENGINE.setHighlight(GHILITE)}catch(e){}return} graphRedraw(); } function graphRefreshNodeMetrics(){ @@ -824,7 +911,11 @@ function graphRender(fit=true,reheat=true){ }); return; } - const element=document.getElementById('graph-net'),settings=window.GSET,mode=GRAPH_PRESETS[settings.mode]||GRAPH_PRESETS.compact,data=graphData(),dataChanged=GACTIVE_DATA!==data; + const element=document.getElementById('graph-net'),settings=window.GSET,mode=GRAPH_PRESETS[settings.mode]||GRAPH_PRESETS.compact,data=graphData(); + if(graphEngineEnabled()&&graphRenderEngine(data,fit,reheat))return; + /* Read AFTER the opt-in attempt: a failing engine resets GACTIVE_DATA precisely so the + classic renderer below rebuilds from scratch instead of assuming the canvas is current. */ + const dataChanged=GACTIVE_DATA!==data; GPERF={large:data.nodes.length>600||data.links.length>2400,dense:data.links.length>1500}; graphSyncReadouts();graphUpdateEditedBadge(); if(dataChanged){ @@ -924,6 +1015,7 @@ function graphSet(key,value){ const rd=document.querySelector('[data-graph-val="'+key+'"]'); if(rd)rd.textContent=key==='linkw'?Number(value).toFixed(1):(key==='size'?String(+Number(value).toFixed(1)):String(Math.round(value))); graphUpdateEditedBadge(); + if(GRAPH_ENGINE){GRAPH_ENGINE.setSettings({[key]:Number(value)});return} if(!FG)return; const layout=key==='repel'||key==='link'||key==='gravity'||key==='size'; if(key==='size')graphRefreshNodeMetrics(); @@ -953,7 +1045,7 @@ function graphApplyPreset(name){ const help=document.getElementById('graph-preset-help'),largeNote=GPERF.large?' Expensive animation, curves, and arrows stay off for this large graph.':''; if(help)help.textContent=notes[window.GSET.mode]+largeNote; graphRefreshNodeMetrics();graphSyncReadouts();graphUpdateEditedBadge(); - if(FG)graphRender(true,true); + if(FG||GRAPH_ENGINE)graphRender(true,true); } function graphSyncReadouts(){ ['repel','link','gravity','font','size','linkw','labelDensity'].forEach(k=>{const rd=document.querySelector('[data-graph-val="'+k+'"]');if(!rd)return;const v=window.GSET[k];rd.textContent=k==='linkw'?Number(v).toFixed(1):(k==='size'?String(+Number(v).toFixed(1)):String(Math.round(v)));const ctl=document.querySelector('[data-graph-setting="'+k+'"]');if(ctl)ctl.value=v*(Number(ctl.dataset.graphScale)||1);}); @@ -975,28 +1067,39 @@ function graphUpdateEditedBadge(){ showAs(btn,edited); } function graphResetPreset(){graphApplyPreset(window.GSET.mode==='custom'?'compact':window.GSET.mode);toast('Preset restored','ok')} -function graphToggleFlow(control){window.GSET.flow=control.checked;if(FG)graphRender(false,false)} +function graphToggleFlow(control){window.GSET.flow=control.checked;if(GRAPH_ENGINE)GRAPH_ENGINE.setSettings({flow:control.checked});else if(FG)graphRender(false,false)} function graphToggleFreeze(control){ - window.GSET.frozen=control.checked;if(!FG)return; + window.GSET.frozen=control.checked;if(GRAPH_ENGINE){GRAPH_ENGINE.freeze(control.checked);return}if(!FG)return; const ns=(FG.graphData().nodes)||[]; if(control.checked){ns.forEach(n=>{n.fx=n.x;n.fy=n.y});graphSetSimulationStatus('Layout frozen')} else{ns.forEach(n=>{n.fx=null;n.fy=null});if(!prefersReducedMotion())FG.d3ReheatSimulation()} } -function graphToggleLabels(control){window.GSET.labels=control.checked;if(FG)graphRender(false,false)} +function graphToggleLabels(control){window.GSET.labels=control.checked;if(GRAPH_ENGINE)GRAPH_ENGINE.setSettings({labels:control.checked});else if(FG)graphRender(false,false)} function graphRecolor(){ renderGraphColorControls(); + if(GRAPH_ENGINE){GRAPH_ENGINE.apply(engine=>{engine.setPalette(typeof GCOLOR_PALETTE!=='undefined'?GCOLOR_PALETTE:'theme');engine.setTypeColors(GCOLOR_OVERRIDES||{})},false,false);return} if(!FG)return; window.GCOL=graphReadThemeColors();graphRefreshNodeColors(); FG.linkColor(FG.linkColor());FG.linkWidth(FG.linkWidth());graphRedraw(); } -function graphFit(){if(FG)FG.zoomToFit(prefersReducedMotion()?0:500,72)} +function graphFit(){if(GRAPH_ENGINE)GRAPH_ENGINE.fit();else if(FG)FG.zoomToFit(prefersReducedMotion()?0:500,72)} function graphReheat(){ + if(GRAPH_ENGINE){if(prefersReducedMotion()){toast('Layout motion is off because reduced motion is enabled.','ok');return}GRAPH_ENGINE.reheat();return} if(!FG)return; if(prefersReducedMotion()){toast('Layout motion is off because reduced motion is enabled.','ok');return} graphSetSimulationStatus('Reheating layout',true);FG.d3ReheatSimulation(); } function graphFocus(name){ clearTimeout(window.__gfit); + if(GRAPH_ENGINE){ + /* Keep the classic contract: highlight, sync the explorer, and if the entity is filtered + out, offer the same "show unlinked" recovery instead of silently doing nothing. */ + if(GRAPH_ENGINE.zoomToNode(name)){graphSetHighlight(name);syncGraphExplorerSelection(name);return} + const isolated=document.getElementById('graph-show-iso'); + if(isolated&&!isolated.checked){isolated.checked=true;graphRender(false,true);setTimeout(()=>graphFocus(name),prefersReducedMotion()?0:500)} + else toast('Entity not in view','err'); + return; + } const node=FG&&(FG.graphData().nodes||[]).find(item=>item.id===name),duration=prefersReducedMotion()?0:550; if(node&&node.x!=null){graphSetHighlight(name);FG.centerAt(node.x,node.y,duration);FG.zoom(5,duration);syncGraphExplorerSelection(name)} else{const show=document.getElementById('graph-show-iso');if(show&&!show.checked){show.checked=true;graphRender(false,true);setTimeout(()=>graphFocus(name),duration?500:0)}else toast('Entity not in view','err')} diff --git a/engraphis/static/engraphis-graph.js b/engraphis/static/engraphis-graph.js new file mode 100644 index 0000000..6314077 --- /dev/null +++ b/engraphis/static/engraphis-graph.js @@ -0,0 +1,833 @@ +/* Engraphis knowledge graph — the dashboard's opt-in force-graph engine. + Restores the shipped behaviour: GRAPH_PRESETS, GSTYLE render modes (cyber/galaxy/solar/classic), + STYLE_PAL / STYLE_LAYERS / STYLE_BG, COMMUNITY_PALS, GRAPH_HEAT, colour-by community/type/connections, + GRAPH_PALETTES with per-entity-type overrides, d3 force wiring, directional particles, label ranking, + hover neighbourhood highlight, freeze, fit and reheat. Values copied from dashboard.js. + + The public graph endpoint calls its fields `label`, `from` and `to`; the engine also + accepts the renderer-friendly `name`, `source` and `target` aliases so it can be used + with both the dashboard adapter and standalone scene payloads. */ +(function () { + const PRESETS = { + original: { label: 'Original force', repel: 120, link: 30, gravity: 14, font: 13, size: 3, linkw: 1, labelDensity: 40, curve: 0, particles: 0 }, + compact: { label: 'Compact clusters', repel: 42, link: 20, gravity: 26, font: 12, size: 3, linkw: 0.7, labelDensity: 30, curve: 0.08, particles: 0 }, + communities: { label: 'Community islands', repel: 48, link: 16, gravity: 48, font: 12, size: 3, linkw: 0.72, labelDensity: 24, curve: 0.12, particles: 0 }, + radial: { label: 'Radial orbit', repel: 68, link: 26, gravity: 12, font: 13, size: 3, linkw: 0.75, labelDensity: 55, curve: 0.22, particles: 0 }, + constellation: { label: 'Constellation flow', repel: 34, link: 16, gravity: 38, font: 12, size: 3, linkw: 0.65, labelDensity: 35, curve: 0.32, particles: 2 }, + custom: { label: 'Custom tuning', curve: 0.1, particles: 0 } + }; + + const STYLE_PAL = { + galaxy: { person_or_concept: '#b789ff', mention: '#7bb4ff', hashtag: '#ffcf6b', email: '#8aa2ff', organization: '#66e0d0', location: '#ff7ea8' }, + solar: { person_or_concept: '#ffb454', mention: '#3fd2c7', hashtag: '#ffd68a', email: '#8ea8ff', organization: '#5b9bff', location: '#ff8f6b' }, + cyber: { person_or_concept: '#ff3ea5', mention: '#b6ff3c', hashtag: '#ffe14d', email: '#8b7bff', organization: '#22e0ff', location: '#ff5c7a' } + }; + const STYLE_LAYERS = { + classic: { temporal: '#6f9fd8', entity: '#5aafb3', causal: '#d7a84b', semantic: '#8c83e8' }, + galaxy: { temporal: '#7bb4ff', entity: '#66e0d0', causal: '#ffcf6b', semantic: '#b789ff' }, + solar: { temporal: '#5b9bff', entity: '#3fd2c7', causal: '#ffb454', semantic: '#ffd68a' }, + cyber: { temporal: '#22e0ff', entity: '#b6ff3c', causal: '#ffe14d', semantic: '#ff3ea5' } + }; + /* The per-style pane backgrounds are NOT defined here. `style-src-attr 'none'` forbids + writing them onto the element, so dashboard.css owns them behind + `#graph-net[data-graph-style="galaxy|solar|cyber"]` and this file only sets that + attribute. Keeping a second copy of the gradients in JS would be dead drift. */ + const PALETTES = { + theme: null, + aurora: { person_or_concept: '#8b7cf6', mention: '#2dd4bf', hashtag: '#fbbf24', email: '#60a5fa', organization: '#f472b6', location: '#a3e635' }, + ocean: { person_or_concept: '#38bdf8', mention: '#2dd4bf', hashtag: '#facc15', email: '#818cf8', organization: '#22d3ee', location: '#34d399' }, + ember: { person_or_concept: '#f97316', mention: '#fb7185', hashtag: '#facc15', email: '#a78bfa', organization: '#ef4444', location: '#84cc16' }, + contrast: { person_or_concept: '#0072b2', mention: '#009e73', hashtag: '#e69f00', email: '#56b4e9', organization: '#cc79a7', location: '#d55e00' } + }; + const THEME_ETYPE = { person_or_concept: '#8c83e8', mention: '#5aafb3', hashtag: '#d7a84b', email: '#6f9fd8', organization: '#58b882', location: '#df7478' }; + const COMMUNITY_PALS = { + classic: ['#8c83e8', '#5aafb3', '#d7a84b', '#6f9fd8', '#58b882', '#df7478', '#b07de0', '#4fb0a0', '#e0894a', '#7c9be0', '#e06a9a', '#9ac25a'], + galaxy: ['#b789ff', '#7bb4ff', '#66e0d0', '#ffcf6b', '#ff7ea8', '#8aa2ff', '#c98bff', '#5ad0e0', '#ffa0d0', '#9d7bff', '#6ad0b0', '#ffb060'], + solar: ['#ffb454', '#3fd2c7', '#ffd68a', '#5b9bff', '#ff8f6b', '#8ea8ff', '#ffc98a', '#4fc0b0', '#ff9f5b', '#7fb0ff', '#ffd0a0', '#5ad0c0'], + cyber: ['#ff3ea5', '#22e0ff', '#b6ff3c', '#ffe14d', '#8b7bff', '#ff5c7a', '#3cffd0', '#ff9ae0', '#5ce0ff', '#d0ff3c', '#ffb03c', '#a06bff'] + }; + const GRAPH_HEAT = ['#3f7bff', '#6a5cff', '#a24bff', '#e0479f', '#ff6b6b', '#ffc23d']; + + function idOf(value) { return value && typeof value === 'object' ? value.id : value; } + function nodeName(node) { return String(node.name || node.label || node.id || ''); } + function linkEndpoint(link, side) { + return idOf(link[side] !== undefined ? link[side] : link[side === 'source' ? 'from' : 'to']); + } + function asOfValue(value) { + if (value instanceof Date) return value.getTime(); + if (typeof value === 'number') return Number.isFinite(value) ? value * (value < 1e11 ? 1000 : 1) : null; + if (typeof value === 'string' && value.trim()) { + const numeric = Number(value); + if (Number.isFinite(numeric)) return asOfValue(numeric); + const parsed = Date.parse(value); + return Number.isFinite(parsed) ? parsed : null; + } + return null; + } + function temporalValue(item, key, fallback) { + const value = item[key] !== undefined ? item[key] : item[key === 'valid_from' ? 'born' : 'closed']; + if (value === undefined || value === null || value === '') return fallback; + return asOfValue(value); + } + + /* Node and link labels come from ingested memories, i.e. untrusted text. force-graph's + tooltip renders a string label through `innerHTML` (see float-tooltip in + vendor/force-graph.min.js), so every label handed to it must already be escaped. */ + function esc(value) { + if (value === undefined || value === null) return ''; + return String(value) + .replace(/&/g, '&').replace(//g, '>') + .replace(/"/g, '"').replace(/'/g, '''); + } + + function hexRgb(c) { + if (!c) return [140, 131, 232]; + if (c[0] === '#') { + const hex = c.length === 4 ? c[1] + c[1] + c[2] + c[2] + c[3] + c[3] : c.slice(1, 7); + const n = parseInt(hex, 16); + if (!Number.isFinite(n)) return [140, 131, 232]; + return [n >> 16 & 255, n >> 8 & 255, n & 255]; + } + const m = c.match(/\d+/g) || [140, 131, 232]; + return [+m[0], +m[1], +m[2]]; + } + function alpha(c, a) { const [r, g, b] = hexRgb(c); return 'rgba(' + r + ',' + g + ',' + b + ',' + a + ')'; } + function lighten(c, amt) { let [r, g, b] = hexRgb(c); r = Math.round(r + (255 - r) * amt); g = Math.round(g + (255 - g) * amt); b = Math.round(b + (255 - b) * amt); return 'rgb(' + r + ',' + g + ',' + b + ')'; } + function contrastOn(c) { const [r, g, b] = hexRgb(c); return (0.2126 * r + 0.7152 * g + 0.0722 * b) > 150 ? '#111827' : '#f8fafc'; } + + function makeStars() { + const a = [], c = ['#dfe6ff', '#dfe6ff', '#c9b6ff', '#a7c6ff', '#ffd9ef']; + for (let i = 0; i < 110; i++) a.push({ x: (Math.random() - 0.5) * 1200, y: (Math.random() - 0.5) * 1200, r: Math.random() * 1.1 + 0.25, a: Math.random() * 0.7 + 0.25, tw: Math.random() * 1.6 + 0.4, ph: Math.random() * 6.28, c: c[i % c.length] }); + return a; + } + const STARS = makeStars(); + + function communities(nodes, links) { + const adj = {}; + const nodesById = new Map(nodes.map(node => [node.id, node])); + nodes.forEach(n => { adj[n.id] = []; }); + links.forEach(l => { + const s = linkEndpoint(l, 'source'), t = linkEndpoint(l, 'target'); + if (adj[s]) adj[s].push(t); + if (adj[t]) adj[t].push(s); + }); + // Respect clusters supplied with the data (a store that already knows its topics); + // otherwise fall back to connected-component BFS, as the dashboard does. + if (nodes.length && nodes.every(n => typeof n.community === 'number')) return adj; + const seen = new Set(); + let group = 0; + nodes.forEach(n => { + if (seen.has(n.id)) return; + // Read head instead of Array#shift: shift() is O(n) per pop, which turns this BFS + // quadratic on the large stores the dashboard is expected to open. + const queue = [n.id]; + let head = 0; + seen.add(n.id); + while (head < queue.length) { + const id = queue[head++]; + const node = nodesById.get(id); + if (node) node.community = group; + (adj[id] || []).forEach(next => { if (!seen.has(next)) { seen.add(next); queue.push(next); } }); + } + group++; + }); + return adj; + } + + function maxOf(values, floor) { + // Math.max(...array) throws RangeError once the array outgrows the argument limit, + // which a real store reaches long before the renderer gets slow. + let best = floor; + for (let i = 0; i < values.length; i++) if (values[i] > best) best = values[i]; + return best; + } + + /* Brandes betweenness — which entity is the bridge whose loss would split a topic. + Brandes is O(V·E); on a large store that is seconds of blocked main thread, so above + BETWEENNESS_PIVOTS sources we run the standard pivot approximation over a deterministic, + evenly-spaced sample. The score is only ever used as a *relative* size/highlight signal + (it is normalised to the maximum), so a sampled estimate is fit for purpose. */ + const BETWEENNESS_PIVOTS = 220; + const BETWEENNESS_BUDGET = 1.5e6; + function betweenness(nodes, adj) { + const bc = {}; + nodes.forEach(n => { bc[n.id] = 0; }); + // Each pivot costs O(V) just to initialise its bookkeeping, so cap pivots by total work + // as well as by count: without the budget a 60k-entity store blocks the main thread for + // ~25s. This is a relative sizing signal, so fewer pivots degrades quality, not truth. + const pivots = Math.max(1, Math.min( + BETWEENNESS_PIVOTS, + Math.floor(BETWEENNESS_BUDGET / Math.max(1, nodes.length)) + )); + const stride = nodes.length > pivots ? Math.ceil(nodes.length / pivots) : 1; + for (let index = 0; index < nodes.length; index += stride) { + const src = nodes[index]; + const stack = [], pred = {}, sigma = {}, dist = {}, delta = {}; + nodes.forEach(n => { pred[n.id] = []; sigma[n.id] = 0; dist[n.id] = -1; delta[n.id] = 0; }); + sigma[src.id] = 1; dist[src.id] = 0; + const queue = [src.id]; + let head = 0; + while (head < queue.length) { + const v = queue[head++]; + stack.push(v); + (adj[v] || []).forEach(w => { + if (dist[w] < 0) { dist[w] = dist[v] + 1; queue.push(w); } + if (dist[w] === dist[v] + 1) { sigma[w] += sigma[v]; pred[w].push(v); } + }); + } + while (stack.length) { + const w = stack.pop(); + pred[w].forEach(v => { delta[v] += (sigma[v] / sigma[w]) * (1 + delta[w]); }); + if (w !== src.id) bc[w] += delta[w]; + } + } + const max = maxOf(Object.values(bc), 1); + nodes.forEach(n => { n.betweenness = bc[n.id] / max; }); + return bc; + } + + /* Bridge edges (Tarjan): removing one disconnects part of the store. */ + function findBridges(nodes, links, adj) { + const disc = {}, low = {}, parent = {}, bridges = new Set(); + const multiplicity = {}; + links.forEach(link => { + const s = linkEndpoint(link, 'source'), t = linkEndpoint(link, 'target'); + const key = s < t ? s + '|' + t : t + '|' + s; + multiplicity[key] = (multiplicity[key] || 0) + 1; + }); + let timer = 0; + // Iterative Tarjan. The recursive form recurses once per node along a path, so a + // chain-shaped component of a few thousand entities overflows the call stack and takes + // the whole render down with it — an explicit frame stack has no such ceiling. + const visit = root => { + const frames = [{ u: root, i: 0 }]; + disc[root] = low[root] = ++timer; + while (frames.length) { + const frame = frames[frames.length - 1]; + const u = frame.u, neighbors = adj[u] || []; + if (frame.i < neighbors.length) { + const v = neighbors[frame.i++]; + if (!disc[v]) { + parent[v] = u; + disc[v] = low[v] = ++timer; + frames.push({ u: v, i: 0 }); + } else if (v !== parent[u]) { + low[u] = Math.min(low[u], disc[v]); + } + continue; + } + frames.pop(); + const p = parent[u]; + if (p !== undefined) { + low[p] = Math.min(low[p], low[u]); + const key = p < u ? p + '|' + u : u + '|' + p; + if (low[u] > disc[p] && multiplicity[key] === 1) { + bridges.add(p + '|' + u); + bridges.add(u + '|' + p); + } + } + } + }; + nodes.forEach(n => { if (!disc[n.id]) visit(n.id); }); + links.forEach(l => { + const s = linkEndpoint(l, 'source'), t = linkEndpoint(l, 'target'); + l.bridge = bridges.has(s + '|' + t); + }); + return bridges; + } + + function create(el, options) { + if (typeof ForceGraph === 'undefined') throw new Error('force-graph not loaded'); + if (!el || typeof el.getAttribute !== 'function') throw new Error('graph container missing'); + const opts = options || {}; + const state = { + // Named `styleName`, not `style`: scripts/externalize_dashboard_assets.py scans this + // asset for runtime inline-style mutation with a text pattern, and a plain data field + // by the shorter name reads as one. The longer name keeps that gate honest. + styleName: 'cyber', colorBy: 'community', palette: 'theme', overrides: {}, + settings: Object.assign({}, PRESETS.communities, { mode: 'communities', labels: false, flow: true, frozen: false }), + minDegree: 1, showUnlinked: false, focusId: null, depth: 2, layers: { temporal: true, entity: true, causal: true, semantic: true, code: false }, + path: null, asOf: null, ghost: true, sizeBy: 'degree', bridges: false, suggestions: false, collapse: 'auto' + }; + let raw = { nodes: [], links: [], suggestions: [] }, adj = {}, hilite = null, hoverSet = null, maxDeg = 1; + let zoom = 1, collapsed = false; + let destroyed = false, running = true, fitTimer = 0, suspended = 0, pendingRender = null; + let betweennessReady = false; + const fg = ForceGraph()(el); + const api = {}; + + /* The dashboard already honours `prefers-reduced-motion` for the classic renderer; this + engine must not quietly reintroduce perpetual motion for the same user. */ + function reduced() { + if (typeof opts.reducedMotion === 'function') return !!opts.reducedMotion(); + try { + return !!(window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches); + } catch (e) { return false; } + } + /* force-graph already keeps redrawing while the simulation runs or any link still has + particles in flight, so `autoPauseRedraw(false)` is only needed for paint this engine + does behind its back: the galaxy starfield lives in onRenderFramePre and is invisible + to that change detection. Everywhere else, letting force-graph park the redraw is what + keeps a settled graph off the CPU. */ + function needsContinuousFrames() { + return !reduced() && state.styleName === 'galaxy'; + } + /* Betweenness is the one analysis that is superlinear in the store size, and nothing in + the default view consumes it — the bridge overlay and betweenness-sizing are both off. + Computing it lazily keeps opening the graph cheap; the first toggle pays for it once. */ + function ensureBetweenness() { + if (betweennessReady) return; + betweennessReady = true; + betweenness(raw.nodes, adj); + } + /* Apply a batch of setters with exactly one render at the end. Each public setter renders + on its own, so a single dashboard sync used to cost six full re-simulations (and six + zoom-to-fit timers). The caller also states the intent explicitly, because the merged + intent of the individual setters is not the caller's: `setSettings` always asks for a + reheat, which would reheat even on a `render(false, false)` refresh. */ + function batch(fn, fit, reheat) { + suspended++; + try { fn(api); } finally { + suspended--; + pendingRender = null; + render(!!fit, !!reheat); + } + } + + function etypeColor(type) { + if (state.overrides[type]) return state.overrides[type]; + if (state.styleName !== 'classic' && STYLE_PAL[state.styleName] && STYLE_PAL[state.styleName][type]) return STYLE_PAL[state.styleName][type]; + return THEME_ETYPE[type] || '#8c83e8'; + } + function commPal() { return COMMUNITY_PALS[state.styleName] || COMMUNITY_PALS.classic; } + function heatColor(node) { + const t = (node.rank || 0) / Math.max(1, raw.nodes.length - 1); + return GRAPH_HEAT[Math.min(GRAPH_HEAT.length - 1, Math.floor(t * GRAPH_HEAT.length))]; + } + function nodeColor(node) { + if (state.colorBy === 'community') { const p = commPal(); return p[(node.community || 0) % p.length]; } + if (state.colorBy === 'connections') return heatColor(node); + return etypeColor(node.etype); + } + function layerColor(layer) { return (STYLE_LAYERS[state.styleName] || STYLE_LAYERS.classic)[layer] || '#8c83e8'; } + + function born(item) { return temporalValue(item, 'valid_from', -Infinity); } + function closed(item) { return temporalValue(item, 'valid_to', null); } + function aliveAt(item, date) { + const start = born(item), end = closed(item); + return start <= date && (end === null || end > date); + } + + function collapsedData(nodes, links) { + const groups = {}; + nodes.forEach(n => { + const c = n.community || 0; + if (!groups[c]) groups[c] = { id: 'cluster-' + c, cluster: true, community: c, name: (n.topic || 'Cluster ' + (c + 1)), etype: n.etype, members: 0, degree: 0, betweenness: 0 }; + groups[c].members++; + groups[c].degree += n.degree || 0; + groups[c].betweenness = Math.max(groups[c].betweenness, n.betweenness || 0); + }); + const cnodes = Object.values(groups); + const seen = {}; + const clinks = []; + // Indexed lookup, not Array#find per endpoint: auto-collapse fires on every zoom-out, + // and the scan made that O(nodes x links) — a visible freeze on a real store. + const byId = new Map(raw.nodes.map(n => [n.id, n])); + links.forEach(l => { + const s = byId.get(linkEndpoint(l, 'source')); + const t = byId.get(linkEndpoint(l, 'target')); + if (!s || !t) return; + const a = 'cluster-' + (s.community || 0), b = 'cluster-' + (t.community || 0); + if (a === b) return; + const key = a < b ? a + '|' + b : b + '|' + a; + if (seen[key]) { seen[key].weight++; return; } + const link = { source: a, target: b, layer: l.layer, weight: 1, aggregate: true }; + seen[key] = link; + clinks.push(link); + }); + return { nodes: cnodes, links: clinks }; + } + + function visible() { + const keepLayer = l => state.layers[l.layer] !== false; + let nodes = raw.nodes.filter(n => (state.showUnlinked || n.degree > 0) && n.degree >= state.minDegree); + if (state.repo) nodes = nodes.filter(n => (n.repo || n.topic || '').toLowerCase().includes(state.repo) || nodeName(n).toLowerCase().includes(state.repo)); + if (state.asOf !== null) { + const live = nodes.filter(n => aliveAt(n, state.asOf)); + const ghosts = state.ghost ? nodes.filter(n => !aliveAt(n, state.asOf) && born(n) <= state.asOf).map(n => Object.assign(n, { ghost: true })) : []; + live.forEach(n => { n.ghost = false; }); + nodes = live.concat(ghosts); + } else { + nodes.forEach(n => { n.ghost = false; }); + } + if (state.focusId != null) { + const keep = new Set([state.focusId]); + let frontier = [state.focusId]; + for (let h = 0; h < state.depth; h++) { + const next = []; + frontier.forEach(id => (adj[id] || []).forEach(n => { if (!keep.has(n)) { keep.add(n); next.push(n); } })); + frontier = next; + } + nodes = nodes.filter(n => keep.has(n.id)); + } + const ids = new Set(nodes.map(n => n.id)); + let links = raw.links.filter(l => keepLayer(l) && ids.has(linkEndpoint(l, 'source')) && ids.has(linkEndpoint(l, 'target'))); + if (state.asOf !== null) { + links.forEach(l => { l.ghost = !aliveAt(l, state.asOf); }); + if (!state.ghost) links = links.filter(l => !l.ghost); + links = links.filter(l => born(l) <= state.asOf); + } else { + links.forEach(l => { l.ghost = false; }); + } + if (state.suggestions && raw.suggestions) { + raw.suggestions.forEach(s => { + const source = linkEndpoint(s, 'source'), target = linkEndpoint(s, 'target'); + if (ids.has(source) && ids.has(target)) links = links.concat([Object.assign({}, s, { source, target, layer: 'semantic', suggested: true })]); + }); + } + if (collapsed) return collapsedData(nodes, links.filter(l => !l.suggested)); + return { nodes, links }; + } + + function applyForces() { + const s = state.settings, mode = s.mode || 'compact'; + fg.d3Force('charge').strength(-s.repel); + fg.d3Force('link').distance(s.link); + if (typeof d3 === 'undefined') return; + fg.d3Force('radial', null); + if (mode === 'communities') { + const target = node => { + const c = node.community || 0; + const ring = 240 + (c % 3) * 90; + const a = (c * 2.399); + return { x: Math.cos(a) * ring, y: Math.sin(a) * ring * 0.62 }; + }; + fg.d3Force('x', d3.forceX(n => target(n).x).strength(s.gravity / 100)); + fg.d3Force('y', d3.forceY(n => target(n).y).strength(s.gravity / 100)); + } else { + const centering = mode === 'radial' ? Math.max(0.04, s.gravity / 300) : s.gravity / 100; + fg.d3Force('x', d3.forceX(0).strength(centering)); + fg.d3Force('y', d3.forceY(0).strength(centering)); + if (mode === 'radial' && d3.forceRadial) fg.d3Force('radial', d3.forceRadial(n => Math.max(0, 5 - Math.min(5, n.degree || 0)) * Math.max(8, s.link * 0.72)).strength(0.32)); + } + if (d3.forceCollide) fg.d3Force('collide', d3.forceCollide(n => n.radius + 1.5).iterations(2)); + } + + function styleBackground(ctx, scale) { + if (state.styleName === 'galaxy') { + const t = performance.now() / 1000; + ctx.save(); + ctx.globalCompositeOperation = 'lighter'; + for (let i = 0; i < STARS.length; i++) { + const s = STARS[i], al = s.a * (0.5 + 0.5 * Math.sin(t * s.tw + s.ph)); + if (al <= 0.02) continue; + ctx.globalAlpha = al; + ctx.beginPath(); + ctx.arc(s.x, s.y, s.r, 0, 6.2832); + ctx.fillStyle = s.c; + ctx.fill(); + } + ctx.restore(); + } else if (state.styleName === 'solar') { + ctx.save(); + const g = ctx.createRadialGradient(0, 0, 2, 0, 0, 130); + g.addColorStop(0, 'rgba(255,192,112,.20)'); + g.addColorStop(0.6, 'rgba(255,150,80,.05)'); + g.addColorStop(1, 'rgba(255,150,80,0)'); + ctx.fillStyle = g; + ctx.beginPath(); + ctx.arc(0, 0, 130, 0, 6.2832); + ctx.fill(); + ctx.strokeStyle = 'rgba(255,190,120,.10)'; + ctx.lineWidth = 1 / scale; + [72, 132, 200, 286, 384].forEach(r => { ctx.beginPath(); ctx.ellipse(0, 0, r, r * 0.66, 0, 0, 6.2832); ctx.stroke(); }); + ctx.restore(); + } + } + + function styleNode(node, ctx, scale) { + if (!Number.isFinite(node.x) || !Number.isFinite(node.y)) return; + const focus = hoverSet && hoverSet.size > 1, neighbor = focus && hoverSet.has(node.id), dim = focus && !neighbor; + let r = node.radius; + const col = node.color, rich = node.id === hilite || neighbor || node.hub || node.degree >= 3; + ctx.globalAlpha = node.ghost ? 0.22 : (dim ? 0.12 : 1); + if (node.ghost) { + ctx.lineWidth = 1.1 / scale; + ctx.strokeStyle = col; + ctx.beginPath(); ctx.arc(node.x, node.y, r, 0, 6.2832); ctx.stroke(); + ctx.globalAlpha = 1; + return; + } + if (node.cluster) { + const g = ctx.createRadialGradient(node.x, node.y, r * 0.2, node.x, node.y, r * 1.5); + g.addColorStop(0, alpha(col, 0.9)); + g.addColorStop(0.7, alpha(col, 0.35)); + g.addColorStop(1, alpha(col, 0)); + ctx.fillStyle = g; + ctx.beginPath(); ctx.arc(node.x, node.y, r * 1.5, 0, 6.2832); ctx.fill(); + ctx.fillStyle = contrastOn(col); + ctx.font = '600 ' + Math.max(3, r * 0.55) + 'px system-ui, sans-serif'; + ctx.textAlign = 'center'; + ctx.textBaseline = 'middle'; + ctx.fillText(String(node.members), node.x, node.y); + ctx.font = '500 ' + Math.max(2.6, r * 0.4) + 'px system-ui, sans-serif'; + ctx.fillStyle = 'rgba(232,236,245,.9)'; + ctx.fillText(nodeName(node), node.x, node.y + r * 1.5 + r * 0.5); + ctx.textAlign = 'left'; + ctx.globalAlpha = 1; + return; + } + if (state.bridges && node.betweenness > 0.35) { + ctx.save(); + ctx.strokeStyle = alpha('#ff5c7a', 0.75); + ctx.lineWidth = 1.2 / scale; + ctx.setLineDash([2 / scale, 2 / scale]); + ctx.beginPath(); ctx.arc(node.x, node.y, r + 3 / scale, 0, 6.2832); ctx.stroke(); + ctx.restore(); + } + if (state.styleName === 'galaxy') { + if (rich) { + ctx.save(); + ctx.globalCompositeOperation = 'lighter'; + const R = r * (node.id === hilite ? 4.4 : 3.0); + const g = ctx.createRadialGradient(node.x, node.y, 0, node.x, node.y, R); + g.addColorStop(0, alpha(col, dim ? 0.15 : 0.6)); + g.addColorStop(0.42, alpha(col, dim ? 0.05 : 0.16)); + g.addColorStop(1, alpha(col, 0)); + ctx.fillStyle = g; + ctx.beginPath(); + ctx.arc(node.x, node.y, R, 0, 6.2832); + ctx.fill(); + ctx.restore(); + } + ctx.beginPath(); ctx.arc(node.x, node.y, r, 0, 6.2832); ctx.fillStyle = col; ctx.fill(); + ctx.beginPath(); ctx.arc(node.x, node.y, Math.max(0.4, r * 0.4), 0, 6.2832); ctx.fillStyle = 'rgba(255,255,255,.9)'; ctx.fill(); + } else if (state.styleName === 'solar') { + const sun = node.rank === 0; + if (sun) r *= 1.7; + if (rich) { + ctx.save(); + ctx.globalCompositeOperation = 'lighter'; + const cc = sun ? '#ffcf6b' : col, R2 = r * (sun ? 3.4 : 2.1); + const g2 = ctx.createRadialGradient(node.x, node.y, 0, node.x, node.y, R2); + g2.addColorStop(0, alpha(cc, dim ? 0.1 : (sun ? 0.6 : 0.3))); + g2.addColorStop(1, alpha(cc, 0)); + ctx.fillStyle = g2; + ctx.beginPath(); ctx.arc(node.x, node.y, R2, 0, 6.2832); ctx.fill(); + ctx.restore(); + } + const sg = ctx.createRadialGradient(node.x - r * 0.4, node.y - r * 0.4, Math.max(0.1, r * 0.12), node.x, node.y, r); + sg.addColorStop(0, lighten(sun ? '#ffe4ad' : col, 0.5)); + sg.addColorStop(1, sun ? '#e08a25' : col); + ctx.fillStyle = sg; + ctx.beginPath(); ctx.arc(node.x, node.y, r, 0, 6.2832); ctx.fill(); + } else if (state.styleName === 'cyber') { + ctx.save(); + if (rich) { ctx.shadowColor = col; ctx.shadowBlur = dim ? 2 : r * 2.6; } + ctx.beginPath(); ctx.arc(node.x, node.y, r, 0, 6.2832); ctx.fillStyle = col; ctx.fill(); + ctx.restore(); + ctx.beginPath(); ctx.arc(node.x, node.y, Math.max(0.4, r * 0.42), 0, 6.2832); ctx.fillStyle = '#eafcff'; ctx.fill(); + } else { + ctx.beginPath(); ctx.arc(node.x, node.y, r, 0, 6.2832); ctx.fillStyle = col; ctx.fill(); + if (node.hub) { ctx.lineWidth = 0.8 / scale; ctx.strokeStyle = node.stroke; ctx.stroke(); } + } + if (node.id === hilite) { + ctx.lineWidth = 1.3 / scale; + ctx.strokeStyle = state.styleName === 'cyber' ? '#ffffff' : 'rgba(255,255,255,.9)'; + ctx.beginPath(); ctx.arc(node.x, node.y, r + 1.4 / scale, 0, 6.2832); ctx.stroke(); + } + const showLabel = (state.settings.labels && node.degree >= Math.max(1, 12 - state.settings.labelDensity / 6)) || node.id === hilite || neighbor; + if (showLabel && scale > 0.35) { + const size = Math.max(2, state.settings.font / scale / 3.4); + ctx.font = '500 ' + size + 'px system-ui, sans-serif'; + ctx.textBaseline = 'middle'; + ctx.fillStyle = 'rgba(0,0,0,.5)'; + ctx.fillText(nodeName(node), node.x + r + 1.6 + 0.3, node.y + 0.3); + ctx.fillStyle = node.id === hilite ? '#ffffff' : 'rgba(232,236,245,.86)'; + ctx.fillText(nodeName(node), node.x + r + 1.6, node.y); + } + ctx.globalAlpha = 1; + } + + function applyChrome() { + // Keep the asset compatible with `style-src-attr 'none'`: the CSP-safe dashboard + // stylesheet owns the visual backgrounds, while the canvas owns the data-driven paint. + el.setAttribute('data-graph-style', state.styleName); + } + + function refreshColors() { + const nodes = fg.graphData().nodes || []; + nodes.forEach(n => { n.color = nodeColor(n); n.stroke = contrastOn(n.color); }); + fg.nodeCanvasObject(fg.nodeCanvasObject()); + } + + function render(fit, reheat) { + if (destroyed) return; + if (suspended) { + pendingRender = pendingRender ? [pendingRender[0] || fit, pendingRender[1] || reheat] : [fit, reheat]; + return; + } + const motion = !reduced(); + const data = visible(); + const sizeMetric = n => state.sizeBy === 'betweenness' ? (n.betweenness || 0) : ((n.degree || 0) / Math.max(1, maxDeg)); + data.nodes.forEach(n => { + const base = (state.settings.size || 3); + n.radius = n.cluster + ? Math.max(3, base * (1.4 + Math.min(3, Math.sqrt(n.members || 1) * 0.7))) + : Math.max(0.8, base * (0.55 + Math.min(1.6, sizeMetric(n) * 1.9))); + n.color = nodeColor(n); + n.stroke = contrastOn(n.color); + }); + applyChrome(); + fg.graphData(data); + applyForces(); + fg.autoPauseRedraw(!needsContinuousFrames()); + if (fg.d3AlphaDecay) fg.d3AlphaDecay(0.035); + if (fg.d3VelocityDecay) fg.d3VelocityDecay(0.38); + if (fg.linkCurvature) fg.linkCurvature((PRESETS[state.settings.mode] || PRESETS.compact).curve || 0); + fg.linkDirectionalArrowLength(2.5).linkDirectionalArrowRelPos(1); + if (fg.linkDirectionalParticles) { + const particles = (state.settings.flow === false || !motion) + ? 0 + : (state.styleName === 'cyber' ? 3 : ((PRESETS[state.settings.mode] || {}).particles || 2)); + fg.linkDirectionalParticles(l => l.suggested || l.ghost ? 0 : particles) + .linkDirectionalParticleWidth(2) + .linkDirectionalParticleColor(l => alpha(layerColor(l.layer), 0.95)) + .linkDirectionalParticleSpeed(l => 0.002 + ((state.settings.flowSpeed || 45) / 100) * 0.008); + } + if (reheat && motion && !state.settings.frozen && fg.d3ReheatSimulation) fg.d3ReheatSimulation(); + if ((state.settings.frozen || !motion) && fg.d3AlphaDecay) { /* keep painting, stop layout */ fg.d3AlphaDecay(1); } + if (fit) { + clearTimeout(fitTimer); + fitTimer = setTimeout(() => { if (!destroyed) fg.zoomToFit(motion ? 600 : 0, 40); }, motion ? 320 : 0); + } + if (opts.onStats) opts.onStats({ nodes: data.nodes.length, links: data.links.length, total: raw.nodes.length, totalLinks: raw.links.length, preset: (PRESETS[state.settings.mode] || PRESETS.compact).label, collapsed: collapsed, ghosts: data.nodes.filter(n => n.ghost).length, bridges: data.links.filter(l => l.bridge).length, suggested: data.links.filter(l => l.suggested).length }); + } + + fg.backgroundColor('rgba(0,0,0,0)').nodeRelSize(1).autoPauseRedraw(true) + /* force-graph's default `nodeLabel`/`linkLabel` is the literal accessor "name", and its + tooltip renders a string label with innerHTML. Node names here are entity labels + extracted from ingested memories — untrusted input — so both accessors are set + explicitly and escaped rather than left on the vendor default. */ + .nodeLabel(node => esc(nodeName(node))) + .linkLabel(link => esc(link && link.label ? link.label : '')) + .onRenderFramePre((ctx, scale) => { try { styleBackground(ctx, scale); } catch (e) { } }) + .nodeCanvasObject((node, ctx, scale) => styleNode(node, ctx, scale)) + .nodePointerAreaPaint((node, color, ctx) => { ctx.fillStyle = color; ctx.beginPath(); ctx.arc(node.x, node.y, node.radius + 2, 0, 6.2832); ctx.fill(); }) + .linkColor(l => { + const focus = hoverSet && hoverSet.size > 1; + const s = linkEndpoint(l, 'source'), t = linkEndpoint(l, 'target'); + const active = !focus || s === hilite || t === hilite; + if (l.suggested) return alpha('#ffffff', active ? 0.34 : 0.1); + if (l.ghost) return alpha(layerColor(l.layer), 0.12); + if (state.bridges && l.bridge) return alpha('#ff5c7a', active ? 0.95 : 0.5); + const base = layerColor(l.layer); + return active ? alpha(base, focus ? 0.85 : 0.4) : alpha(base, 0.06); + }) + .linkLineDash(l => l.suggested ? [2, 2] : (l.ghost ? [1, 3] : null)) + .linkWidth(l => { + const w = state.settings.linkw || 1; + const focus = hoverSet && hoverSet.size > 1; + const s = linkEndpoint(l, 'source'), t = linkEndpoint(l, 'target'); + if (l.aggregate) return Math.min(6, 0.6 + Math.log2(1 + (l.weight || 1)) * 1.4) * w; + if (state.bridges && l.bridge) return 2.6 * w; + if (!focus) return 0.82 * w; + return (s === hilite || t === hilite) ? 2.4 * w : 0.4 * w; + }) + .onNodeHover(node => { + hilite = node ? node.id : null; + hoverSet = node ? new Set([node.id].concat(adj[node.id] || [])) : null; + el.classList.toggle('engraphis-graph-node-hover', !!node); + }) + .onNodeClick(node => { + if (node.cluster) { collapsed = false; state.collapse = false; render(false, true); setTimeout(() => { fg.centerAt(node.x, node.y, 500); fg.zoom(1.6, 500); }, 60); if (opts.onCollapseChange) opts.onCollapseChange(false); return; } + if (opts.onNodeClick) opts.onNodeClick(node); + }) + .onNodeDragEnd(node => { node.fx = node.x; node.fy = node.y; }) + .onBackgroundClick(() => { if (opts.onBackgroundClick) opts.onBackgroundClick(); }) + .onZoom(z => { + zoom = z.k || 1; + if (state.collapse !== 'auto') return; + const next = zoom < 0.55; + if (next !== collapsed) { + collapsed = next; + render(false, true); + if (opts.onCollapseChange) opts.onCollapseChange(collapsed); + } + }); + + api.setData = data => { + const inputNodes = Array.isArray(data && data.nodes) ? data.nodes : []; + const nodes = inputNodes + .filter(node => node && node.id != null) + .map(node => Object.assign({}, node, { name: nodeName(node) })); + const nodeIds = new Set(nodes.map(node => node.id)); + const links = (Array.isArray(data && (data.links || data.edges)) ? (data.links || data.edges) : []) + .map(link => { + const source = linkEndpoint(link, 'source'), target = linkEndpoint(link, 'target'); + return Object.assign({}, link, { source, target }); + }) + .filter(link => link.source != null && link.target != null && nodeIds.has(link.source) && nodeIds.has(link.target)); + const suggestions = (Array.isArray(data && data.suggestions) ? data.suggestions : []) + .map(link => Object.assign({}, link, { source: linkEndpoint(link, 'source'), target: linkEndpoint(link, 'target') })) + .filter(link => link.source != null && link.target != null); + raw = { nodes, links, suggestions }; + adj = communities(raw.nodes, raw.links); + const deg = {}; + raw.links.forEach(l => { const s = linkEndpoint(l, 'source'), t = linkEndpoint(l, 'target'); deg[s] = (deg[s] || 0) + 1; deg[t] = (deg[t] || 0) + 1; }); + raw.nodes.forEach(n => { n.degree = deg[n.id] || 0; n.betweenness = 0; }); + maxDeg = maxOf(raw.nodes.map(n => n.degree), 1); + const ranked = [...raw.nodes].sort((a, b) => b.degree - a.degree); + ranked.forEach((n, i) => { n.rank = i; n.hub = i < 6; }); + // Bridge *edges* are cheap (linear) and feed the stats readout, so they stay eager. + // Betweenness is not: see ensureBetweenness. + findBridges(raw.nodes, raw.links, adj); + betweennessReady = false; + if (state.bridges || state.sizeBy === 'betweenness') ensureBetweenness(); + render(true, true); + }; + api.setSettings = patch => { Object.assign(state.settings, patch); render(false, patch.mode !== undefined); }; + api.setPreset = name => { + const p = PRESETS[name] || PRESETS.compact; + state.settings.mode = PRESETS[name] ? name : 'compact'; + ['repel', 'link', 'gravity', 'font', 'size', 'linkw', 'labelDensity'].forEach(k => { if (p[k] !== undefined) state.settings[k] = p[k]; }); + render(true, true); + return { ...state.settings }; + }; + api.setStyle = name => { state.styleName = ['classic', 'galaxy', 'solar', 'cyber'].indexOf(name) < 0 ? 'cyber' : name; render(false, false); }; + api.setColorBy = name => { state.colorBy = name; refreshColors(); render(false, false); }; + api.setPalette = name => { state.palette = name; state.overrides = PALETTES[name] ? { ...PALETTES[name] } : {}; refreshColors(); }; + api.setTypeColor = (type, color) => { state.overrides[type] = color; state.palette = 'custom'; refreshColors(); }; + /* Rehydrating saved overrides is not a user edit, so it must not flip the palette + selector to "custom" behind the user's back the way setTypeColor deliberately does. */ + api.setTypeColors = map => { Object.assign(state.overrides, map || {}); refreshColors(); }; + /* One render for a whole batch of setters — see `batch`. */ + api.apply = (fn, fit, reheat) => { batch(fn, fit, reheat); }; + api.setHighlight = id => { + hilite = id == null ? null : id; + hoverSet = id == null ? null : new Set([id].concat(adj[id] || [])); + if (!destroyed) fg.nodeCanvasObject(fg.nodeCanvasObject()); + }; + api.setScope = patch => { Object.assign(state, patch); render(false, true); }; + api.setLayers = layers => { state.layers = layers; render(false, false); }; + api.focus = id => { state.focusId = id; render(true, true); }; + api.clearFocus = () => { state.focusId = null; render(true, true); }; + api.fit = () => { if (!destroyed) fg.zoomToFit(reduced() ? 0 : 500, 40); }; + api.reheat = () => { + if (destroyed || reduced()) return; + raw.nodes.forEach(n => { n.fx = undefined; n.fy = undefined; }); + if (fg.d3ReheatSimulation) { fg.d3AlphaDecay(0.035); fg.d3ReheatSimulation(); } + }; + api.freeze = on => { + state.settings.frozen = on; + if (on) { fg.d3Force('charge').strength(0); fg.d3AlphaDecay(1); return; } + applyForces(); + if (reduced()) return; + fg.d3AlphaDecay(0.035); + if (fg.d3ReheatSimulation) fg.d3ReheatSimulation(); + }; + api.zoomToNode = id => { + const n = raw.nodes.find(x => x.id === id); + if (!n || !Number.isFinite(n.x) || !Number.isFinite(n.y)) return false; + const duration = reduced() ? 0 : 500; + fg.centerAt(n.x, n.y, duration); + fg.zoom(3, duration); + return true; + }; + api.state = () => ({ ...state, collapsed }); + /* The engine clusters its own copies of the nodes, so a caller that renders a cluster + legend from the source data would otherwise report a single community. */ + api.communityMap = () => { + const map = {}; + raw.nodes.forEach(n => { map[n.id] = n.community || 0; }); + return map; + }; + api.setGhosts = on => { state.ghost = on; render(false, false); }; + api.setRepoFilter = repo => { state.repo = (repo || '').trim().toLowerCase(); render(false, true); }; + api.setAsOf = date => { state.asOf = asOfValue(date); render(false, true); }; + api.setSizeBy = metric => { + state.sizeBy = metric === 'betweenness' ? metric : 'degree'; + if (state.sizeBy === 'betweenness') ensureBetweenness(); + render(false, false); + }; + api.setBridges = on => { state.bridges = on; if (on) ensureBetweenness(); render(false, false); }; + /* Forces the lazy analysis; the dashboard does not display these yet, so nothing calls it + on the render path. Kept as the seam a "most load-bearing entity" panel would use. */ + api.metrics = () => { + ensureBetweenness(); + return { + top: [...raw.nodes].sort((a, b) => b.betweenness - a.betweenness).slice(0, 5) + .map(n => ({ id: n.id, name: nodeName(n), score: n.betweenness })), + bridges: raw.links.filter(l => l.bridge).length + }; + }; + api.setSuggestions = on => { state.suggestions = on; render(false, true); }; + api.setCollapse = mode => { + state.collapse = mode; + const next = mode === true || (mode === 'auto' && zoom < 0.55); + collapsed = next; + render(true, true); + }; + api.presets = PRESETS; + api.resize = () => { measure(); }; + /* Leaving the graph view must stop the simulation loop. force-graph keeps a rAF alive + for as long as it is resumed, so a hidden pane would otherwise repaint forever. */ + api.pause = () => { + if (destroyed || !running) return; + running = false; + if (fg.pauseAnimation) fg.pauseAnimation(); + }; + api.resume = () => { + if (destroyed || running) return; + running = true; + if (fg.resumeAnimation) fg.resumeAnimation(); + measure(); + }; + api.destroyed = () => destroyed; + api.destroy = () => { + if (destroyed) return; + destroyed = true; + clearTimeout(fitTimer); + try { + if (api._ro) { api._ro.disconnect(); api._ro = null; } + // `_destructor` pauses the rAF and drops the graph data; it does not detach the + // canvas, so clear the container too or a re-create leaves the old one attached. + if (fg._destructor) fg._destructor(); + el.removeAttribute('data-graph-style'); + el.classList.remove('engraphis-graph-node-hover'); + el.innerHTML = ''; + } catch (e) { /* teardown is best-effort: never let it block a view change */ } + raw = { nodes: [], links: [], suggestions: [] }; + adj = {}; + hilite = null; + hoverSet = null; + }; + + // A hidden pane measures 0x0; writing that into force-graph collapses the canvas and + // nothing restores it, so only a real box is ever applied. + const measure = () => { + if (destroyed) return; + const w = el.clientWidth, h = el.clientHeight; + if (w > 0 && h > 0) fg.width(w).height(h); + }; + measure(); + requestAnimationFrame(() => { if (destroyed) return; measure(); fg.zoomToFit(reduced() ? 0 : 400, 40); }); + if (typeof ResizeObserver !== 'undefined') { + api._ro = new ResizeObserver(() => measure()); + api._ro.observe(el); + } + applyChrome(); + return api; + } + + window.EngraphisGraph = { + create, PRESETS, PALETTES, STYLE_LAYERS, COMMUNITY_PALS, GRAPH_HEAT, THEME_ETYPE, STYLE_PAL, + /* Pure helpers, exported so the offline test suite can assert real behaviour (escaping, + component labelling, bridge detection, stack safety) without a browser or a bundler. + Nothing in the dashboard uses these; treat them as the engine's unit-test seam. */ + _internals: { + esc, hexRgb, alpha, contrastOn, communities, betweenness, findBridges, maxOf, + nodeName, linkEndpoint, asOfValue + } + }; +})(); diff --git a/engraphis/static/index.html b/engraphis/static/index.html index f92f8c5..4ce68af 100644 --- a/engraphis/static/index.html +++ b/engraphis/static/index.html @@ -323,6 +323,8 @@ + + diff --git a/scripts/externalize_dashboard_assets.py b/scripts/externalize_dashboard_assets.py index 4c27b2d..d34a9b6 100644 --- a/scripts/externalize_dashboard_assets.py +++ b/scripts/externalize_dashboard_assets.py @@ -19,6 +19,14 @@ CSS = STATIC / "dashboard.css" JS = STATIC / "dashboard.js" +#: First-party scripts the dashboard page loads besides ``dashboard.js``. They run under the +#: same strict CSP, so they are held to the same no-inline-style/no-inline-handler contract. +#: Vendored bundles under ``static/vendor`` are excluded: they are third-party artefacts we +#: do not rewrite, and pinning them is the job of the commercial-manifest check. +EXTRA_SCRIPTS = (STATIC / "engraphis-graph.js",) + +SCRIPT_SRC = re.compile(r']+src=["\'](/static/[^"\']+)["\']') + STYLE_ATTR = re.compile(r"\sstyle=(?:\"([^\"]*)\"|'([^']*)')") EVENT_ATTR = re.compile(r"\s(on[a-z]+)=(?:\"([^\"]*)\"|'([^']*)')") STYLE_REF = re.compile(r'data-csp-style=["\'](s\d+)["\']') @@ -208,24 +216,44 @@ def check() -> None: failures.append("inline event attribute") if not CSS.is_file() or not JS.is_file(): failures.append("missing external asset") - if STYLE_ATTR.search(js): - failures.append("inline style attribute in generated dashboard markup") - if EVENT_ATTR.search(js): - failures.append("inline event attribute in generated dashboard markup") - if re.search(r"\.(?:style|cssText)\b|(?:get|set)Attribute\([\"']style[\"']", js): - failures.append("runtime inline-style mutation") - if re.search(r"\[on[a-z]+|(?:get|set)Attribute\([\"']on[a-z]+[\"']", js): - failures.append("legacy inline-handler selector") + extra = {path.name: path.read_text(encoding="utf-8") for path in EXTRA_SCRIPTS if path.is_file()} + missing_scripts = sorted(path.name for path in EXTRA_SCRIPTS if not path.is_file()) + if missing_scripts: + failures.append("missing first-party script: " + ", ".join(missing_scripts)) + + # Every /static asset the page asks for must exist, or the dashboard 404s at load time + # and the strict CSP turns a typo into a silently broken view. + absent = sorted( + { + reference + for reference in SCRIPT_SRC.findall(html) + if not (ROOT / "engraphis" / reference.lstrip("/")).is_file() + } + ) + if absent: + failures.append("index.html loads missing script: " + ", ".join(absent)) + + for name, source in [("dashboard.js", js), *extra.items()]: + if STYLE_ATTR.search(source): + failures.append(f"inline style attribute in {name}") + if EVENT_ATTR.search(source): + failures.append(f"inline event attribute in {name}") + if re.search(r"\.(?:style|cssText)\b|(?:get|set)Attribute\([\"']style[\"']", source): + failures.append(f"runtime inline-style mutation in {name}") + if re.search(r"\[on[a-z]+|(?:get|set)Attribute\([\"']on[a-z]+[\"']", source): + failures.append(f"legacy inline-handler selector in {name}") if "${" in css or "'+" in css or "+'" in css: failures.append("unresolved JavaScript interpolation in CSS") - style_refs = set(STYLE_REF.findall(html + "\n" + js)) + style_refs = set(STYLE_REF.findall("\n".join([html, js, *extra.values()]))) style_rules = set(STYLE_RULE.findall(css)) missing_styles = sorted(style_refs - style_rules) if missing_styles: failures.append("missing CSP style rules: " + ", ".join(missing_styles)) - handler_refs = HANDLER_REF.findall(html + "\n" + js) + # Handler *definitions* only ever live in the generated dashboard.js registry, but any + # first-party script may reference one, so references are collected across all of them. + handler_refs = HANDLER_REF.findall("\n".join([html, js, *extra.values()])) handler_ids = {handler_id for _event, handler_id in handler_refs} handler_defs = set(HANDLER_DEF.findall(js)) missing_handlers = sorted(handler_ids - handler_defs) diff --git a/tests/test_graph_engine_asset.py b/tests/test_graph_engine_asset.py new file mode 100644 index 0000000..9194a78 --- /dev/null +++ b/tests/test_graph_engine_asset.py @@ -0,0 +1,391 @@ +"""Contract checks for the opt-in browser graph engine (``?graph-engine=next``). + +These tests intentionally stay dependency-light: the dashboard's offline CI floor does +not need a browser or a JavaScript package manager just to validate a shipped static +asset. Where Node is available the asset is *executed* rather than pattern-matched, so +the checks assert behaviour (escaping, bridge detection, stack safety, load-order +independence) instead of the presence of source substrings. + +The properties guarded here are the ones whose failure is silent in a browser: + +* the asset must define its global without touching ``ForceGraph``/``document``, so a + blocked or missing vendor bundle degrades instead of white-screening the dashboard; +* every label crossing into force-graph must be escaped, because force-graph's tooltip + is an ``innerHTML`` sink and entity labels come from ingested memories; +* the client-side graph analysis must not recurse per node or run unbounded work; +* the per-style pane backgrounds must stay in CSS, since the production CSP sets + ``style-src-attr 'none'``. +""" + +from __future__ import annotations + +import json +import re +import shutil +import subprocess +from pathlib import Path + +import pytest + +ROOT = Path(__file__).resolve().parents[1] +STATIC = ROOT / "engraphis" / "static" +ASSET = STATIC / "engraphis-graph.js" +INDEX = STATIC / "index.html" +CSS = STATIC / "dashboard.css" +DASHBOARD = STATIC / "dashboard.js" +VENDOR = STATIC / "vendor" / "force-graph.min.js" + +NODE = shutil.which("node") +requires_node = pytest.mark.skipif(NODE is None, reason="node is not installed") + +#: Evaluates the asset with nothing but a bare ``window`` object in scope. Any top-level +#: use of a browser or vendor global would raise here, which is the point. +PRELUDE = """ +const fs = require('fs'); +const source = fs.readFileSync(process.argv[1], 'utf8'); +const window = {}; +new Function('window', source)(window); +const G = window.EngraphisGraph; +const I = G._internals; +const emit = value => console.log(JSON.stringify(value)); +""" + + +def _run_node(script: str) -> object: + result = subprocess.run( + [NODE, "-e", PRELUDE + script, str(ASSET)], + cwd=ROOT, + capture_output=True, + text=True, + check=False, + ) + assert result.returncode == 0, result.stderr + return json.loads(result.stdout.strip().splitlines()[-1]) + + +# ── load order and failure isolation ──────────────────────────────────────────────── + + +def test_opt_in_graph_asset_is_loaded_after_its_dependencies() -> None: + html = INDEX.read_text(encoding="utf-8") + d3 = html.index("/static/vendor/d3.min.js") + force_graph = html.index("/static/vendor/force-graph.min.js") + engine = html.index("/static/engraphis-graph.js") + dashboard = html.index("/static/dashboard.js") + assert d3 < force_graph < engine < dashboard + + +@requires_node +def test_graph_asset_defines_its_global_without_touching_its_dependencies() -> None: + """Nothing may run at parse time except pure setup. + + ``PRELUDE`` supplies no ``ForceGraph``, no ``document`` and no ``requestAnimationFrame``. + If the asset reached for any of them at the top level this would throw, and in a browser + the same reach would abort the script and take ``window.EngraphisGraph`` with it. + """ + report = _run_node( + """ + emit({ + create: typeof G.create, + presets: Object.keys(G.PRESETS).sort(), + styles: Object.keys(G.STYLE_LAYERS).sort(), + }); + """ + ) + assert report["create"] == "function" + assert "communities" in report["presets"] + assert report["styles"] == ["classic", "cyber", "galaxy", "solar"] + + +@requires_node +def test_create_fails_loudly_when_force_graph_is_unavailable() -> None: + """A blocked vendor bundle must raise, not half-initialise a dead canvas.""" + report = _run_node( + """ + let message = null; + try { G.create({ getAttribute() { return null; } }, {}); } + catch (error) { message = error.message; } + emit({ message }); + """ + ) + assert report["message"] == "force-graph not loaded" + + +def test_dashboard_falls_back_to_the_classic_renderer_when_the_engine_throws() -> None: + source = DASHBOARD.read_text(encoding="utf-8") + # The opt-in flag must be latched off after a failure, and the render path must catch. + assert "GRAPH_ENGINE_FAILED" in source + assert "if(GRAPH_ENGINE_FAILED)return false" in source + assert "graphEngineFallback(error)" in source + engine_path = source[source.index("function graphRenderEngine"):] + engine_path = engine_path[: engine_path.index("\nfunction ")] + assert "try{" in engine_path and "}catch(error){" in engine_path + + +# ── XSS: untrusted entity labels reaching force-graph ─────────────────────────────── + + +def test_force_graph_tooltip_is_still_an_inner_html_sink() -> None: + """Guards the *reason* the engine sets its own label accessors. + + force-graph defaults ``nodeLabel``/``linkLabel`` to the accessor ``"name"`` and renders a + string label through ``innerHTML``. Node names here are entity labels extracted from + ingested memories, i.e. untrusted. If a vendor bump ever changes this, revisit whether + the explicit escaped accessors below are still the right shape. + """ + vendor = VENDOR.read_text(encoding="utf-8", errors="ignore") + assert 'nodeLabel:{default:"name"' in vendor + assert 'linkLabel:{default:"name"' in vendor + + +def test_engine_never_relies_on_the_default_label_accessor() -> None: + source = ASSET.read_text(encoding="utf-8") + assert ".nodeLabel(node => esc(nodeName(node)))" in source + assert ".linkLabel(" in source + assert "eval(" not in source + # The engine paints to canvas; the only markup sink it may use is clearing its own + # container on teardown. Anything else would be a route for an unescaped entity label. + writes = re.findall(r"\w+\.(?:inner|outer)HTML\s*=\s*[^;]+", source) + assert writes == ["el.innerHTML = ''"], writes + assert not re.search(r"insertAdjacentHTML|document\.write|createContextualFragment", source) + + +@requires_node +@pytest.mark.parametrize( + "payload", + [ + "", + "", + "\" onmouseover=\"alert(1)", + "", + ], +) +def test_entity_labels_are_escaped_before_they_can_reach_a_dom_sink(payload: str) -> None: + report = _run_node( + "emit({ escaped: I.esc(%s), named: I.nodeName({ label: %s }) });" + % (json.dumps(payload), json.dumps(payload)) + ) + escaped = report["escaped"] + assert "<" not in escaped and ">" not in escaped + assert '"' not in escaped and "'" not in escaped + assert "<" in escaped or """ in escaped + # nodeName is the raw value; escaping is the accessor's job, so this documents the split. + assert report["named"] == payload + + +# ── payload compatibility with the shipped /graph endpoint ────────────────────────── + + +@requires_node +def test_engine_accepts_both_the_api_and_renderer_link_shapes() -> None: + report = _run_node( + """ + const api = { from: 'a', to: 'b' }; + const renderer = { source: { id: 'c' }, target: 'd' }; + emit({ + apiSource: I.linkEndpoint(api, 'source'), + apiTarget: I.linkEndpoint(api, 'target'), + rendererSource: I.linkEndpoint(renderer, 'source'), + rendererTarget: I.linkEndpoint(renderer, 'target'), + label: I.nodeName({ label: 'Ada' }), + name: I.nodeName({ name: 'Grace' }), + fallback: I.nodeName({ id: 'ent_1' }), + }); + """ + ) + assert report["apiSource"] == "a" and report["apiTarget"] == "b" + assert report["rendererSource"] == "c" and report["rendererTarget"] == "d" + assert report["label"] == "Ada" + assert report["name"] == "Grace" + assert report["fallback"] == "ent_1" + + +@requires_node +def test_valid_time_accepts_seconds_milliseconds_and_iso_strings() -> None: + report = _run_node( + """ + emit({ + seconds: I.asOfValue(1700000000), + millis: I.asOfValue(1700000000000), + iso: I.asOfValue('2023-11-14T22:13:20Z'), + blank: I.asOfValue(''), + junk: I.asOfValue('not a date'), + }); + """ + ) + assert report["seconds"] == report["millis"] == 1700000000000 + assert report["iso"] == 1700000000000 + assert report["blank"] is None and report["junk"] is None + + +# ── client-side analysis: correctness and cost ────────────────────────────────────── + + +@requires_node +def test_bridge_detection_matches_a_known_graph() -> None: + """A triangle has no bridges; the tail hanging off it is all bridges.""" + report = _run_node( + """ + const nodes = ['a', 'b', 'c', 'd', 'e'].map(id => ({ id })); + const links = [['a','b'], ['b','c'], ['c','a'], ['c','d'], ['d','e']] + .map(([source, target]) => ({ source, target })); + const adj = I.communities(nodes, links); + I.findBridges(nodes, links, adj); + emit({ + bridges: links.filter(l => l.bridge).map(l => l.source + '-' + l.target), + communities: new Set(nodes.map(n => n.community)).size, + }); + """ + ) + assert report["bridges"] == ["c-d", "d-e"] + assert report["communities"] == 1 + + +@requires_node +def test_parallel_edges_are_not_reported_as_bridges() -> None: + report = _run_node( + """ + const nodes = [{ id: 'a' }, { id: 'b' }]; + const links = [{ source: 'a', target: 'b' }, { source: 'a', target: 'b' }]; + const adj = I.communities(nodes, links); + I.findBridges(nodes, links, adj); + emit({ bridges: links.filter(l => l.bridge).length }); + """ + ) + assert report["bridges"] == 0 + + +@requires_node +def test_disconnected_entities_are_labelled_as_separate_communities() -> None: + report = _run_node( + """ + const nodes = ['a', 'b', 'c', 'd'].map(id => ({ id })); + const links = [{ source: 'a', target: 'b' }, { source: 'c', target: 'd' }]; + const adj = I.communities(nodes, links); + emit({ groups: new Set(nodes.map(n => n.community)).size }); + """ + ) + assert report["groups"] == 2 + + +@requires_node +def test_graph_analysis_is_stack_safe_and_bounded_on_a_large_store() -> None: + """A long chain of entities is the worst case for both analyses. + + A recursive Tarjan overflows the call stack here, and exact Brandes betweenness is + O(V*E) — minutes of blocked main thread. Both are guarded, so this must finish well + inside the bound even on a slow machine. + """ + report = _run_node( + """ + const N = 40000; + const nodes = [], links = []; + for (let i = 0; i < N; i++) { + nodes.push({ id: 'n' + i }); + if (i) links.push({ source: 'n' + (i - 1), target: 'n' + i }); + } + const adj = I.communities(nodes, links); + const started = Date.now(); + I.findBridges(nodes, links, adj); + I.betweenness(nodes, adj); + const scores = nodes.map(n => n.betweenness); + emit({ + ms: Date.now() - started, + allBridges: links.every(l => l.bridge), + finite: scores.every(Number.isFinite), + peak: Math.max.apply(null, scores.slice(0, 1000).concat(scores.slice(-1000))), + }); + """ + ) + assert report["allBridges"] is True + assert report["finite"] is True + # Ends of a chain are never on a shortest path between others. + assert report["peak"] < 0.5 + assert report["ms"] < 30000, f"graph analysis took {report['ms']}ms on 40k entities" + + +@requires_node +def test_max_helper_survives_arrays_past_the_spread_limit() -> None: + """``Math.max(...array)`` throws RangeError long before a store is unrenderable.""" + report = _run_node("emit({ max: I.maxOf(new Array(400000).fill(7), 1) });") + assert report["max"] == 7 + + +@requires_node +def test_colour_helpers_handle_the_shorthand_hex_the_palettes_may_carry() -> None: + report = _run_node( + """ + emit({ + short: I.hexRgb('#abc'), + long: I.hexRgb('#8c83e8'), + empty: I.hexRgb(''), + light: I.contrastOn('#ffffff'), + dark: I.contrastOn('#000000'), + }); + """ + ) + assert report["short"] == [170, 187, 204] + assert report["long"] == [140, 131, 232] + assert report["empty"] == [140, 131, 232] + assert report["light"] == "#111827" + assert report["dark"] == "#f8fafc" + + +# ── CSP, styling and lifecycle ────────────────────────────────────────────────────── + + +def test_pane_backgrounds_are_owned_by_css_not_by_the_asset() -> None: + """``style-src-attr 'none'`` forbids writing these onto the element.""" + css = CSS.read_text(encoding="utf-8") + source = ASSET.read_text(encoding="utf-8") + for style in ("galaxy", "solar", "cyber"): + assert f'#graph-net[data-graph-style="{style}"]' in css + assert "data-graph-style" in source + # The gradients must exist in exactly one place, or the two copies drift. + assert "radial-gradient" not in source + assert "linear-gradient" not in source + + +def test_hover_cursor_class_the_asset_toggles_exists_in_css() -> None: + css = CSS.read_text(encoding="utf-8") + source = ASSET.read_text(encoding="utf-8") + assert "engraphis-graph-node-hover" in source + assert ".engraphis-graph-node-hover" in css + + +def test_csp_gate_covers_the_graph_asset() -> None: + from scripts.externalize_dashboard_assets import EXTRA_SCRIPTS, check + + assert ASSET in EXTRA_SCRIPTS, "the graph engine must be inside the CSP drift gate" + check() + + +def test_engine_exposes_a_teardown_and_the_dashboard_drives_it() -> None: + source = ASSET.read_text(encoding="utf-8") + dashboard = DASHBOARD.read_text(encoding="utf-8") + for member in ("api.destroy", "api.pause", "api.resume", "api.resize"): + assert member in source + # force-graph keeps a rAF alive while resumed; leaving the view must park it. + assert "if(v==='graph')graphEngineResume();else graphEnginePause()" in dashboard + assert "GRAPH_ENGINE.destroy()" in dashboard + + +def test_reduced_motion_is_honoured_by_the_opt_in_renderer() -> None: + source = ASSET.read_text(encoding="utf-8") + dashboard = DASHBOARD.read_text(encoding="utf-8") + assert "prefers-reduced-motion: reduce" in source + assert "opts.reducedMotion" in source + assert "reducedMotion:prefersReducedMotion" in dashboard + + +def test_graph_engine_is_syntactically_valid_when_node_is_installed() -> None: + if NODE is None: + pytest.skip("node is not installed") + result = subprocess.run( + [NODE, "--check", str(ASSET)], + cwd=ROOT, + capture_output=True, + text=True, + check=False, + ) + assert result.returncode == 0, result.stderr From 23b5ca531a11dc90162ca71cc3f85226e5d304f7 Mon Sep 17 00:00:00 2001 From: Jaixii Date: Sun, 26 Jul 2026 13:51:56 -0400 Subject: [PATCH 14/82] fix(dashboard): lazy-load the graph assets so the CSP stays clean Adding force-graph.min.js and engraphis-graph.js to index.html loaded them on every dashboard page, not just the graph view. force-graph applies inline styles at runtime, the production CSP is style-src 'self', so the browser blocked them and logged an error per attempt. Eleven pre-existing e2e tests assert a clean console and failed -- a regression this branch introduced. dashboard.js already had loadForceGraph() lazily fetching the vendor bundle for the Classic renderer, so neither script ever needed to be in index.html. Both tags are removed and engraphis-graph.js gets a matching memoized loader. The naive version of that would silently downgrade a ?graph-engine=next deep link to Classic, because graphRenderEngine's guard cannot tell "not fetched yet" from "unavailable". The engine fetch now starts alongside the vendor bundle -- one round trip, not two -- and graphRender waits on it and re-enters, so only a genuine load failure degrades, and that path warns. Proved by executing the real routing source under Node with a stub DOM: deep link renders the engine, a failing asset falls back and warns. Both are tests, and reverting to defer-without-await fails them. The "referenced scripts exist" gate rule became three, so removing the tags strengthens it rather than hollowing it out: lazy script.src references are existence-checked (their only reference is a JS string literal), neither asset may reappear as a parsed script src in index.html, and each must keep a lazy loader so deferring cannot orphan them. All negative-tested. Local gate: 1429 passed, 0 failed. The CSP fix itself cannot be proven locally -- Playwright needs node_modules, which is not installed here -- so CI is the real verification for the 11 e2e assertions. Co-Authored-By: Claude Opus 5 (1M context) --- engraphis/static/dashboard.js | 44 ++++++ engraphis/static/index.html | 8 +- scripts/externalize_dashboard_assets.py | 41 +++++- tests/test_externalize_dashboard_assets.py | 85 ++++++++++- tests/test_graph_engine_asset.py | 158 ++++++++++++++++++++- 5 files changed, 323 insertions(+), 13 deletions(-) diff --git a/engraphis/static/dashboard.js b/engraphis/static/dashboard.js index fd70616..9816239 100644 --- a/engraphis/static/dashboard.js +++ b/engraphis/static/dashboard.js @@ -887,6 +887,12 @@ function graphRedraw(){ if(!FG||GREDRAWFRAME)return; GREDRAWFRAME=requestAnimationFrame(()=>{GREDRAWFRAME=0;if(FG)FG.nodeCanvasObject(FG.nodeCanvasObject())}); } +/* ── on-demand graph assets ─────────────────────────────────────────────────────────────── + Neither script is in index.html. force-graph.min.js applies inline styles at runtime, and + under the production CSP (`style-src 'self'`) every one of those is blocked and reported; + loading it on a page that never opens the graph turns a plain dashboard view into a wall of + console errors. Both loaders are memoized, so a re-entrant graphRender() reuses the in-flight + fetch rather than appending a second " "" - "", + "", encoding="utf-8", ) monkeypatch.setattr(assets, "INDEX", index) @@ -52,3 +57,81 @@ def test_check_rejects_unclosed_inline_asset_at_eof(tmp_path, monkeypatch, tag): with pytest.raises(SystemExit, match=f"inline {tag} block"): assets.check() + + +# ── deferred graph assets ─────────────────────────────────────────────────────────────── +# force-graph.min.js applies inline styles at runtime, so under `style-src 'self'` loading it +# on every page reported a CSP violation per attempt. It and the opt-in engine are fetched on +# demand instead; these rules keep that true and keep the deferred references checked. + +_LOADERS = ( + "script.src='/static/vendor/force-graph.min.js';" + "script.src='/static/engraphis-graph.js';" +) + + +def _gate(tmp_path, monkeypatch, html: str, js: str) -> None: + index, css, script = ( + tmp_path / "index.html", + tmp_path / "dashboard.css", + tmp_path / "dashboard.js", + ) + index.write_text(html, encoding="utf-8") + css.write_text("", encoding="utf-8") + script.write_text(js, encoding="utf-8") + monkeypatch.setattr(assets, "INDEX", index) + monkeypatch.setattr(assets, "CSS", css) + monkeypatch.setattr(assets, "JS", script) + # Isolate these cases to the script-reference rules; the first-party CSP scan has its own. + monkeypatch.setattr(assets, "EXTRA_SCRIPTS", ()) + + +def test_check_rejects_an_eagerly_loaded_csp_hostile_script(tmp_path, monkeypatch): + """Putting the tag back in index.html is precisely the regression this rule catches.""" + _gate( + tmp_path, + monkeypatch, + '', + _LOADERS, + ) + + with pytest.raises(SystemExit, match="must not eagerly load: /static/vendor/force-graph"): + assets.check() + + +def test_check_allows_a_deferred_script_named_only_in_a_comment(tmp_path, monkeypatch): + """The rule reads parsed ``' + "" + '' + '' + "" + "" + "" + ) + + assert found == [ + "/static/vendor/force-graph.min.js", + "/static/engraphis-graph.js", + "/static/dashboard.js", + ] + + +def test_check_rejects_an_eagerly_loaded_script_in_any_tag_case(tmp_path, monkeypatch): + """The uppercase spelling is loaded by browsers, so it must fail the same rule.""" + _gate( + tmp_path, + monkeypatch, + '', + _LOADERS, + ) + + with pytest.raises(SystemExit, match="must not eagerly load: /static/vendor/force-graph"): + assets.check() + + +def test_check_rejects_a_mixed_case_reference_to_a_missing_file(tmp_path, monkeypatch): + """The existence check must not have a case-shaped hole either.""" + _gate( + tmp_path, + monkeypatch, + "", + _LOADERS, + ) + + with pytest.raises(SystemExit, match=r"referenced script is missing: .*renamed-bundle\.js"): + assets.check() + + +def test_uppercase_script_src_is_not_mistaken_for_an_inline_block(tmp_path, monkeypatch): + """The inline-block rule reads the same parse, so an external tag stays external.""" + _gate( + tmp_path, + monkeypatch, + '', + _LOADERS, + ) + + assets.check() diff --git a/tests/test_graph_engine_asset.py b/tests/test_graph_engine_asset.py index 629cb18..d1daa21 100644 --- a/tests/test_graph_engine_asset.py +++ b/tests/test_graph_engine_asset.py @@ -51,9 +51,51 @@ """ -def _run_node(script: str) -> object: +#: Same, plus a recording stand-in for force-graph so ``create()`` can be *driven*. Every +#: accessor is a chainable setter that returns the stored value when called with no arguments — +#: force-graph's own kapsule semantics — so the paint configuration the engine installs can be +#: read back and invoked instead of pattern-matched. ``calls`` counts the invalidations the +#: engine requests, which is the only observable form a "redraw now" takes. +ENGINE_PRELUDE = """ +const fs = require('fs'); +const source = fs.readFileSync(process.argv[1], 'utf8'); +const window = {}; +globalThis.requestAnimationFrame = () => {}; +const store = {}, calls = {}; +const fg = new Proxy({}, { + get: (_target, prop) => (...args) => { + if (!args.length) return store[prop]; + calls[prop] = (calls[prop] || 0) + 1; + store[prop] = args.length === 1 ? args[0] : args; + return fg; + }, +}); +globalThis.ForceGraph = () => () => fg; +const el = { + attrs: {}, innerHTML: '', clientWidth: 800, clientHeight: 600, + getAttribute(name) { return this.attrs[name] === undefined ? null : this.attrs[name]; }, + setAttribute(name, value) { this.attrs[name] = value; }, + removeAttribute(name) { delete this.attrs[name]; }, + classList: { toggle() {}, remove() {} }, +}; +const chain = count => { + const nodes = [], links = []; + for (let i = 0; i <= count; i++) nodes.push({ id: 'n' + i }); + for (let i = 0; i < count; i++) { + links.push({ source: 'n' + i, target: 'n' + (i + 1), layer: 'semantic' }); + } + return { nodes, links }; +}; +new Function('window', source)(window); +const G = window.EngraphisGraph; +const I = G._internals; +const emit = value => console.log(JSON.stringify(value)); +""" + + +def _run_node(script: str, prelude: str = PRELUDE) -> object: result = subprocess.run( - [NODE, "-e", PRELUDE + script, str(ASSET)], + [NODE, "-e", prelude + script, str(ASSET)], cwd=ROOT, capture_output=True, text=True, @@ -63,6 +105,10 @@ def _run_node(script: str) -> object: return json.loads(result.stdout.strip().splitlines()[-1]) +def _run_engine(script: str) -> object: + return _run_node(script, prelude=ENGINE_PRELUDE) + + # ── load order and failure isolation ──────────────────────────────────────────────── @@ -450,6 +496,41 @@ def test_graph_analysis_is_stack_safe_and_bounded_on_a_large_store() -> None: assert report["ms"] < 30000, f"graph analysis took {report['ms']}ms on 40k entities" +@requires_node +def test_influence_relations_do_not_merge_two_topics_into_one_community() -> None: + """Community Islands must not fuse two topics over a single cross-topic relation. + + ``influences`` edges routinely span otherwise separate bodies of work. The classic + renderer keeps them drawn and traversable but builds its clustering adjacency without + them (``GCOMM_ADJ``); adding every link to one adjacency gives both topics the same + colour and the same force centre. + """ + report = _run_node( + """ + const nodes = ['a', 'b', 'c', 'd'].map(id => ({ id })); + const links = [ + { source: 'a', target: 'b', label: 'mentions' }, + { source: 'c', target: 'd', label: 'mentions' }, + { source: 'b', target: 'c', label: 'influences' }, + ]; + const adj = I.communities(nodes, links); + I.findBridges(nodes, links, adj); + emit({ + groups: new Set(nodes.map(n => n.community)).size, + merged: nodes[1].community === nodes[2].community, + neighbours: (adj.b || []).slice().sort(), + bridges: links.filter(l => l.bridge).length, + }); + """ + ) + assert report["groups"] == 2 + assert report["merged"] is False + # The relation itself stays in the traversal adjacency: hover neighbourhood, focus depth + # and bridge detection all still see it. Only the clustering ignores it. + assert report["neighbours"] == ["a", "c"] + assert report["bridges"] == 3 + + @requires_node def test_max_helper_survives_arrays_past_the_spread_limit() -> None: """``Math.max(...array)`` throws RangeError long before a store is unrenderable.""" @@ -477,6 +558,206 @@ def test_colour_helpers_handle_the_shorthand_hex_the_palettes_may_carry() -> Non assert report["dark"] == "#f8fafc" +# ── render configuration: what the engine actually installs on force-graph ────────── + + +@requires_node +def test_flow_particles_are_capped_on_a_large_relation_set() -> None: + """Three animated particles per relation does not survive a real ``/graph`` response. + + force-graph advances every particle on every frame, so a few thousand relations is tens + of thousands of animated objects and an unusable canvas. The classic renderer refuses to + draw them past 800 links; the opt-in engine must use the same cutoff rather than trusting + that no store is big. + """ + report = _run_engine( + """ + const api = G.create(el, {}); + const particlesFor = link => store.linkDirectionalParticles(link || { layer: 'semantic' }); + api.setStyle('cyber'); + api.setSettings({ flow: true }); + api.setData(chain(40)); + const small = particlesFor(); + api.setData(chain(800)); + const atLimit = particlesFor(); + api.setData(chain(801)); + const overLimit = particlesFor(); + api.setData(chain(4000)); + emit({ small, atLimit, overLimit, realistic: particlesFor() * 4000 }); + """ + ) + assert report["small"] == 3 + assert report["atLimit"] == 3 + assert report["overLimit"] == 0 + # The number this guards: 4k relations x 3 particles was 12,000 animated objects a frame. + assert report["realistic"] == 0 + + +@requires_node +def test_hovering_a_node_asks_for_a_redraw() -> None: + """A highlight nobody repaints is invisible. + + ``onNodeHover`` mutates closure state the paint callbacks read. With reduced motion on, + flow disabled, or a settled simulation, force-graph's ``autoPauseRedraw`` loop has nothing + left to animate and will not repaint just because the callback fired. + """ + report = _run_engine( + """ + const api = G.create(el, { reducedMotion: () => true }); + api.setData({ nodes: [{ id: 'a' }, { id: 'b' }], links: [{ source: 'a', target: 'b' }] }); + const settled = calls.nodeCanvasObject; + store.onNodeHover({ id: 'a' }); + const hovered = calls.nodeCanvasObject; + store.onNodeHover(null); + emit({ + settled, hovered, cleared: calls.nodeCanvasObject, + particles: store.linkDirectionalParticles({ layer: 'semantic' }), + }); + """ + ) + # Reduced motion: nothing is in flight, so an unrequested redraw would never arrive. + assert report["particles"] == 0 + assert report["hovered"] > report["settled"] + assert report["cleared"] > report["hovered"] + + +@requires_node +def test_unlinked_entities_are_shown_only_when_the_engine_is_told_to() -> None: + """The lever the dashboard has to pull for its "Show unlinked nodes" checkbox.""" + report = _run_engine( + """ + const seen = []; + const api = G.create(el, { onStats: stats => seen.push(stats.nodes) }); + api.setData({ + nodes: [{ id: 'a' }, { id: 'b' }, { id: 'lonely' }], + links: [{ source: 'a', target: 'b' }], + }); + const hidden = seen[seen.length - 1]; + api.setScope({ showUnlinked: true, minDegree: 0 }); + emit({ hidden, shown: seen[seen.length - 1] }); + """ + ) + assert report["hidden"] == 2 + assert report["shown"] == 3 + + +#: Executes the *real* ``graphRenderEngine`` source against stubs. Only its collaborators are +#: faked; the function itself is a verbatim slice, so what it forwards to the engine — and when +#: it parks a freshly created renderer — is observed rather than asserted about the source text. +RENDER_HARNESS = """ +const fs = require('fs'); +const src = fs.readFileSync(process.argv.slice(1).find(a => a.endsWith('dashboard.js')), 'utf8'); +const scenario = JSON.parse(process.argv[process.argv.length - 1]); +const start = src.indexOf('function graphRenderEngine('); +const slice = src.slice(start, src.indexOf('/* Nav away from the graph view', start)); + +const log = { created: 0, paused: 0, seeded: 0, scope: null, error: null }; +const checkbox = { checked: scenario.showUnlinked }; +const element = { classList: { toggle() {} }, setAttribute() {}, set textContent(value) {} }; +globalThis.document = { + getElementById: id => (id === 'graph-show-iso' ? checkbox : element), + querySelectorAll: () => [], +}; +const engine = { + setSettings() {}, setStyle() {}, setColorBy() {}, setPalette() {}, setTypeColors() {}, + setLayers() {}, setScope(patch) { log.scope = patch; }, + setData(data) { log.seeded = data.nodes.length; }, +}; +const api = { + apply(fn) { fn(engine); }, communityMap: () => ({}), + freeze() {}, destroy() {}, resume() {}, pause() { log.paused += 1; }, +}; +globalThis.EngraphisGraph = { create() { log.created += 1; return api; } }; +globalThis.window = { GSET: { mode: 'compact', frozen: false } }; +globalThis.GRAPH = { nodes: [] }; +globalThis.GRAPH_ENGINE = null; +globalThis.GACTIVE_DATA = null; +globalThis.GCOLOR_OVERRIDES = {}; +/* The state the nav-away pause recorded while GRAPH_ENGINE was still null. */ +globalThis.GRAPH_ENGINE_PARKED = scenario.parked; +globalThis.showAs = () => {}; +globalThis.prefersReducedMotion = () => false; +for (const name of ['graphSetLayoutStatus', 'graphSyncReadouts', 'graphUpdateEditedBadge', + 'graphUpdateHud', 'graphRenderLegend', 'graphSetHighlight', + 'graphSetSimulationStatus', 'syncGraphExplorerSelection', 'graphNodeClick', + 'graphEngineEmptyMessage']) globalThis[name] = () => {}; +globalThis.graphEngineFallback = error => { + log.error = String((error && error.message) || error); +}; + +const graphRenderEngine = new Function(slice + '\\nreturn graphRenderEngine;')(); +const rendered = graphRenderEngine({ + nodes: [{ id: 'a' }, { id: 'b' }, { id: 'lonely' }], + links: [{ source: 'a', target: 'b' }], +}, true, true); +console.log(JSON.stringify(Object.assign({ rendered }, log))); +""" + + +def _run_render(*, show_unlinked: bool = False, parked: bool = False) -> dict: + source = DASHBOARD.read_text(encoding="utf-8") + # The harness slices real source; keep its landmarks honest. + assert "function graphRenderEngine(" in source + assert "/* Nav away from the graph view" in source + scenario = json.dumps({"showUnlinked": show_unlinked, "parked": parked}) + result = subprocess.run( + [NODE, "-e", RENDER_HARNESS, str(DASHBOARD), scenario], + cwd=ROOT, + capture_output=True, + text=True, + check=False, + ) + assert result.returncode == 0, result.stderr + report = json.loads(result.stdout.strip().splitlines()[-1]) + assert report["error"] is None, report["error"] + assert report["rendered"] is True + return report + + +@requires_node +@pytest.mark.parametrize("checked", [False, True]) +def test_dashboard_tells_the_engine_whether_to_show_unlinked_entities(checked: bool) -> None: + """"Show unlinked nodes" is filtered twice, and only one half was wired up. + + ``graphData()`` starts supplying degree-zero entities when the box is ticked, but the + engine re-filters on its own ``showUnlinked``/``minDegree`` state — which stays at the + defaults that drop exactly those entities — unless the dashboard says otherwise. + """ + report = _run_render(show_unlinked=checked) + + assert report["scope"] is not None, "the engine never learns the checkbox state" + assert report["scope"]["showUnlinked"] is checked + # minDegree matters just as much: showUnlinked alone still loses to `degree >= 1`. + assert report["scope"]["minDegree"] == (0 if checked else 1) + + +@requires_node +def test_a_renderer_created_after_leaving_the_graph_view_is_born_paused() -> None: + """The rAF leak this PR already fixed once, reached by a different route. + + ``/graph`` and both lazy scripts resolve asynchronously. Leaving Graph before they do runs + the pause while ``GRAPH_ENGINE`` is still null, so the pending callback would create and + start a renderer against a hidden pane that nothing ever pauses again. + """ + parked = _run_render(parked=True) + assert parked["created"] == 1 + assert parked["paused"] == 1, "a renderer created off-view keeps repainting forever" + + # On the view, the same path must not park a renderer the user is looking at. + live = _run_render(parked=False) + assert live["created"] == 1 + assert live["paused"] == 0 + + +def test_leaving_the_graph_view_records_the_pause_as_well_as_applying_it() -> None: + source = DASHBOARD.read_text(encoding="utf-8") + assert "if(v==='graph')graphEngineResume();else graphEnginePause()" in source + pause = source[source.index("function graphEnginePause()"):] + pause = pause[: pause.index("\nfunction graphInvalidateData")] + assert "GRAPH_ENGINE_PARKED=true" in pause + assert "GRAPH_ENGINE_PARKED=false" in pause + + # ── CSP, styling and lifecycle ────────────────────────────────────────────────────── From 9d77f4f728a34af13bda102df3c48c92b62b5927 Mon Sep 17 00:00:00 2001 From: Jaixii Date: Sun, 26 Jul 2026 17:42:20 -0400 Subject: [PATCH 19/82] Address connect review: manifest compute endpoint, timeout and save races Three unresolved review threads on #75, plus one semantic conflict the merge with main could not see. `default_compute_url` now reads the manifest's `compute_plane` and falls back to `DEFAULT_COMPUTE_URL`. The review asked for the constant to be replaced outright, but the shipped `engraphis-commercial/v2` manifest declares only `control_plane`: reading the absent key alone resolves `""`, and `cloud_session.configured()` then rejects the session a production connect just saved, leaving a paying customer "connected" but unusable. Preferring the key removes the drift point the review named -- a manifest-only endpoint change needs no code change -- while the constant stays as the fallback that keeps today's manifest working. `_validated_timeout` refuses a non-finite or non-positive timeout. `argparse`'s `type=float` accepts `nan` and `inf`, which reach the pinned opener's deadline arithmetic and raise `ValueError`/`OverflowError` from inside `urllib`, neither caught by `post_connect`. That broke this module's contract that every failure is a `DeviceConnectError`, so `engraphis connect --timeout nan` printed a traceback instead of the command's error and exit code. Checked at the top of `connect()` so a bad flag is reported as a bad flag rather than masked by whatever the identity or storage pre-flight hits first, and again in `post_connect()` because it is public and owns the socket call. `connect()` now also translates `OSError` from `save_bootstrap`. The pre-flight added in aae7d93 closes the common case, but the state directory can still change between the pre-flight and the write, and `UnsafeStateFile` is an `OSError`, not a `CloudSessionError`, so it escaped as a traceback at the worst moment. The token is spent by then, so the copy says so instead of promising a retry with the same one. The `REGISTRATION` fixture no longer claims the cloud grants `export`. #76 removed that key from the plan->feature tables in both repos because the signed compliance export was never implemented; a fixture asserting the control plane returns it would re-establish exactly the drift that removal cleaned up. Co-Authored-By: Claude Opus 5 --- engraphis/device_connect.py | 68 ++++++++++++++++++++++++-- tests/test_device_connect.py | 93 +++++++++++++++++++++++++++++++++++- 2 files changed, 157 insertions(+), 4 deletions(-) diff --git a/engraphis/device_connect.py b/engraphis/device_connect.py index 6856ee2..d0698bb 100644 --- a/engraphis/device_connect.py +++ b/engraphis/device_connect.py @@ -26,6 +26,7 @@ from __future__ import annotations import json +import math import os import platform import re @@ -85,6 +86,12 @@ #: shipped control plane would otherwise leave a customer "connected" but not configured. #: Applied *only* when the control plane is the shipped one: a self-hosted or staging #: control URL gets no guess, and the caller is told to supply the compute URL. +#: +#: This is the *fallback*, not the authority: ``default_compute_url`` prefers the +#: manifest's ``compute_plane`` whenever it carries one. The shipped +#: ``engraphis-commercial/v2`` manifest does not declare that key, so without a constant +#: here a production connect would resolve an empty compute URL and save an unconfigured +#: session. DEFAULT_COMPUTE_URL = "https://compute.engraphis.com" @@ -241,23 +248,61 @@ def default_control_url() -> str: def default_compute_url(control_url: str) -> str: - """Resolve the compute plane, guessing only for the shipped control plane.""" + """Resolve the compute plane, guessing only for the shipped control plane. + + The manifest is the authority for shipped endpoint metadata, so a ``compute_plane`` + key wins if one is ever published -- a manifest-only endpoint change then needs no + code change here. The current ``engraphis-commercial/v2`` manifest declares only + ``control_plane``, so :data:`DEFAULT_COMPUTE_URL` is what production actually + resolves; reading the absent key alone would yield ``""`` and save a session + ``cloud_session.configured()`` rejects. + """ configured = os.environ.get("ENGRAPHIS_CLOUD_COMPUTE_URL", "").strip() if configured: return configured shipped = "" + shipped_compute = "" try: from engraphis.commercial import manifest - shipped = str(manifest().get("control_plane") or "").strip() + data = manifest() + shipped = str(data.get("control_plane") or "").strip() + shipped_compute = str(data.get("compute_plane") or "").strip() except Exception: # pragma: no cover - manifest ships with the package return "" if shipped and control_url.rstrip("/") == shipped.rstrip("/"): - return DEFAULT_COMPUTE_URL + return shipped_compute or DEFAULT_COMPUTE_URL return "" +def _validated_timeout(value: object) -> float: + """Reject a timeout the socket layer cannot use, before any request is started. + + ``float("nan")`` and ``float("inf")`` are values ``argparse``'s ``type=float`` + accepts happily, but they reach the pinned opener's deadline arithmetic and raise + ``ValueError``/``OverflowError`` from inside ``urllib`` -- neither of which + :func:`post_connect` catches. That breaks this module's contract that every failure + is a :class:`DeviceConnectError` with actionable copy, so ``--timeout nan`` printed a + traceback instead of an error and an exit code. Non-positive values are refused for + the same reason: a ``0`` or negative socket timeout is not a shorter wait, it is a + different (non-blocking) mode the caller did not ask for. + """ + + try: + timeout = float(value) + except (TypeError, ValueError) as exc: + raise DeviceConnectError( + "The connect timeout must be a number of seconds.", status=400 + ) from exc + if not math.isfinite(timeout) or timeout <= 0: + raise DeviceConnectError( + "The connect timeout must be a positive, finite number of seconds.", + status=400, + ) + return timeout + + def _validated_control_url(value: str) -> str: if not str(value or "").strip(): raise DeviceConnectError( @@ -362,6 +407,7 @@ def post_connect(control_url: str, token: str, *, installation_client_id: str, deliberately no ``organization_id``: the token carries the organization. """ + timeout = _validated_timeout(timeout) body = { "connect_token": token, "installation_client_id": installation_client_id, @@ -491,6 +537,10 @@ def connect(token: object, *, control_url: Optional[str] = None, never containing the token. Nothing is written unless the exchange succeeded. """ + # Argument checks first: a bad ``--timeout`` must be reported as a bad timeout, not + # masked by whatever the identity or storage pre-flight happens to hit on the way to + # the same rejection inside ``post_connect``. + timeout = _validated_timeout(timeout) normalized = normalize_connect_token(token) resolved_control = _validated_control_url( control_url if control_url is not None else default_control_url() @@ -541,6 +591,18 @@ def connect(token: object, *, control_url: Optional[str] = None, ) except cloud_session.CloudSessionError as exc: raise DeviceConnectError(str(exc), status=getattr(exc, "status", 503)) from exc + except OSError as exc: + # The pre-flight cleared this exact path moments ago, so arriving here means the + # state directory changed underneath the exchange. ``UnsafeStateFile`` is an + # ``OSError`` and not a ``CloudSessionError``, so without this clause it escapes + # as a raw traceback at the worst possible moment -- the token is already spent, + # and the customer needs to be told that plainly rather than shown a stack. + raise DeviceConnectError( + "Engraphis Cloud accepted the token, but the session could not be written to " + "%s. Fix that path, then connect again with a new token from your account " + "portal -- this one has been used." % session_path, + status=409, + ) from exc summary = summarize(response) summary["control_url"] = resolved_control diff --git a/tests/test_device_connect.py b/tests/test_device_connect.py index 16d8a09..2367fa5 100644 --- a/tests/test_device_connect.py +++ b/tests/test_device_connect.py @@ -17,6 +17,7 @@ import pytest from engraphis import cloud_session, device_connect +from engraphis.private_state import UnsafeStateFile from scripts import connect as connect_cli CONTROL_URL = "https://control.example.test" @@ -40,7 +41,10 @@ "entitlement_version": 7, "plan": "team", "cloud_access_active": True, - "cloud_features": ["analytics", "automation", "export", "sync", "team"], + # No ``export``: the signed compliance export was never implemented and is no longer + # in either repo's plan->feature table, so a fixture claiming the cloud grants it + # would re-establish exactly the drift that removal cleaned up. + "cloud_features": ["analytics", "automation", "sync", "team"], } @@ -658,6 +662,93 @@ def test_control_url_defaults_to_the_shipped_manifest(monkeypatch): assert device_connect.default_compute_url(CONTROL_URL) == "" +def test_the_manifest_outranks_the_compute_constant(monkeypatch): + """A published ``compute_plane`` wins, so the manifest stays the endpoint authority. + + The constant is only the fallback for today's manifest, which declares no + ``compute_plane``; reading the key alone would resolve ``""`` and save a session + ``configured()`` rejects. + """ + + from engraphis.commercial import manifest + + shipped = manifest()["control_plane"] + monkeypatch.setattr( + "engraphis.commercial.manifest", + lambda: {"control_plane": shipped, "compute_plane": COMPUTE_URL}, + ) + + assert device_connect.default_compute_url(shipped) == COMPUTE_URL + # A self-hosted control plane still gets no guess from either source. + assert device_connect.default_compute_url(CONTROL_URL) == "" + + +@pytest.mark.parametrize("bad", ["nan", "inf", "-inf", "0", "-5"]) +def test_a_non_finite_timeout_is_refused_before_any_request(monkeypatch, bad): + """``argparse``'s ``type=float`` accepts ``nan``/``inf``; the socket layer does not. + + Those reach ``urllib``'s deadline arithmetic and raise ``ValueError``/``OverflowError`` + that ``post_connect`` does not catch, so the CLI printed a traceback instead of its + structured error. Nothing may be sent, either. + """ + + class _Exploding: + @staticmethod + def open(request, timeout=None): # pragma: no cover - must never run + raise AssertionError("a request was started with an unusable timeout") + + _install_opener(monkeypatch, _Exploding()) + + with pytest.raises(device_connect.DeviceConnectError) as caught: + device_connect.connect(TOKEN, control_url=CONTROL_URL, timeout=float(bad)) + + assert caught.value.status == 400 + assert "timeout" in str(caught.value) + + +def test_the_cli_reports_a_bad_timeout_instead_of_a_traceback(monkeypatch, capsys): + class _Exploding: + @staticmethod + def open(request, timeout=None): # pragma: no cover - must never run + raise AssertionError("a request was started with an unusable timeout") + + _install_opener(monkeypatch, _Exploding()) + + code = connect_cli.main( + ["--token", TOKEN, "--control-url", CONTROL_URL, "--timeout", "nan"] + ) + + assert code == 1 + err = capsys.readouterr().err + assert "timeout" in err + assert "Traceback" not in err + + +def test_a_storage_fault_racing_the_save_is_not_a_traceback(monkeypatch): + """``UnsafeStateFile`` is an ``OSError``, not a ``CloudSessionError``. + + The pre-flight closes the common case, but the state directory can still change + between the pre-flight and the write. The token is spent by then, so the customer + must be told that plainly rather than shown a stack trace. + """ + + _install_opener(monkeypatch, _Opener(body=REGISTRATION)) + + def _boom(*args, **kwargs): + raise UnsafeStateFile("cloud_session.json is not a plain private file") + + monkeypatch.setattr(cloud_session, "save_bootstrap", _boom) + + with pytest.raises(device_connect.DeviceConnectError) as caught: + device_connect.connect(TOKEN, control_url=CONTROL_URL) + + message = str(caught.value) + assert caught.value.status == 409 + # The token is gone; the copy must not promise it can be reused. + assert "has been used" in message + assert TOKEN not in message + + def test_control_url_env_override_wins(monkeypatch): monkeypatch.setenv("ENGRAPHIS_CLOUD_CONTROL_URL", CONTROL_URL) assert device_connect.default_control_url() == CONTROL_URL From b20742e71a1451b60568254d03841bea667ed9e3 Mon Sep 17 00:00:00 2001 From: Jaixii Date: Sun, 26 Jul 2026 17:47:41 -0400 Subject: [PATCH 20/82] fix(graph): rank communities, settle large galaxy graphs, follow the theme Three further findings from PR #74 review. Community IDs were assigned in raw payload order while graphRenderLegend() sorts communities by size and calls the largest "Cluster 1". Node colour indexes the palette by the ID itself, so whenever a smaller component appeared first the legend described one component with another's swatch. Components are now ranked by size before the IDs escape, matching the classic graphComputeCommunities(). Galaxy style held autoPauseRedraw(false) unconditionally, so a settled large graph repainted every node and link every frame forever. The starfield is the only paint force-graph cannot see; the classic path drops it past GPERF.large, so the same 600-node/2400-link signal now skips it and hands the redraw loop back to the vendor. Type colours resolved from hard-coded dark-theme constants, so switching to Light, Midnight, Solarized or Sepia moved the legend and controls while the canvas stayed dark. The engine cannot read CSS custom properties from a canvas, so the dashboard resolves --entity-* and supplies them through a new setThemeColors(), below style palettes and user overrides in priority. 1446 passed, 0 failed (+5 tests). ruff, externalize and manifest gates pass. Co-Authored-By: Claude Opus 5 --- engraphis/static/dashboard.js | 7 +- engraphis/static/engraphis-graph.js | 50 ++++++- tests/test_graph_engine_asset.py | 197 +++++++++++++++++++++++++++- 3 files changed, 244 insertions(+), 10 deletions(-) diff --git a/engraphis/static/dashboard.js b/engraphis/static/dashboard.js index fe26969..f20be54 100644 --- a/engraphis/static/dashboard.js +++ b/engraphis/static/dashboard.js @@ -510,6 +510,10 @@ function graphLoadColorPreferences(){ } function graphSaveColorPreferences(){try{localStorage.setItem(GRAPH_COLOR_KEY,JSON.stringify({palette:GCOLOR_PALETTE,colors:GCOLOR_OVERRIDES}))}catch(e){}} function graphTypeColor(type){if(GCOLOR_OVERRIDES[type])return GCOLOR_OVERRIDES[type];if(typeof GSTYLE!=='undefined'&&GSTYLE&&GSTYLE!=='classic'&&STYLE_PAL[GSTYLE]&&STYLE_PAL[GSTYLE][type])return STYLE_PAL[GSTYLE][type];return cssvar(ETYPE_TOKEN[type]||'--entity-concept',cssvar('--color-accent','#8c83e8'))} +/* The engine renders to a canvas, so it cannot read `--entity-*` itself the way the legend and + the controls do. Resolve the active theme's values here and hand them over; without this the + opt-in canvas keeps dark-theme node colours after a switch to Light/Solarized/Sepia. */ +function graphThemeTypeColors(){const colors={},fallback=cssvar('--color-accent','#8c83e8');Object.keys(ETYPE_TOKEN).forEach(type=>{colors[type]=cssvar(ETYPE_TOKEN[type],fallback)});return colors} function graphContrastColor(color){if(!graphValidColor(color))return cssvar('--color-canvas','#0e1014');const n=parseInt(color.slice(1),16),lum=.2126*(n>>16)+.7152*((n>>8)&255)+.0722*(n&255);return lum>150?'#111827':'#f8fafc'} const ETYPE_COLOR=new Proxy({},{get:(_,type)=>graphTypeColor(type)}); graphLoadColorPreferences(); @@ -614,6 +618,7 @@ function graphRenderEngine(data,fit,reheat){ engine.setSettings({...window.GSET}); engine.setStyle(typeof GSTYLE!=='undefined'?GSTYLE:'cyber'); engine.setColorBy(typeof GCOLORBY!=='undefined'?GCOLORBY:'community'); + engine.setThemeColors(graphThemeTypeColors()); engine.setPalette(typeof GCOLOR_PALETTE!=='undefined'?GCOLOR_PALETTE:'theme'); engine.setTypeColors(GCOLOR_OVERRIDES||{}); engine.setLayers(layers); @@ -1137,7 +1142,7 @@ function graphToggleFreeze(control){ function graphToggleLabels(control){window.GSET.labels=control.checked;if(GRAPH_ENGINE)GRAPH_ENGINE.setSettings({labels:control.checked});else if(FG)graphRender(false,false)} function graphRecolor(){ renderGraphColorControls(); - if(GRAPH_ENGINE){GRAPH_ENGINE.apply(engine=>{engine.setPalette(typeof GCOLOR_PALETTE!=='undefined'?GCOLOR_PALETTE:'theme');engine.setTypeColors(GCOLOR_OVERRIDES||{})},false,false);return} + if(GRAPH_ENGINE){GRAPH_ENGINE.apply(engine=>{engine.setThemeColors(graphThemeTypeColors());engine.setPalette(typeof GCOLOR_PALETTE!=='undefined'?GCOLOR_PALETTE:'theme');engine.setTypeColors(GCOLOR_OVERRIDES||{})},false,false);return} if(!FG)return; window.GCOL=graphReadThemeColors();graphRefreshNodeColors(); FG.linkColor(FG.linkColor());FG.linkWidth(FG.linkWidth());graphRedraw(); diff --git a/engraphis/static/engraphis-graph.js b/engraphis/static/engraphis-graph.js index 9a23a07..28ba123 100644 --- a/engraphis/static/engraphis-graph.js +++ b/engraphis/static/engraphis-graph.js @@ -55,6 +55,14 @@ opt-in engine uses the same cutoff rather than inventing a second large-graph signal. */ const PARTICLE_LINK_LIMIT = 800; + /* The classic renderer's large-graph signal (`GPERF` in dashboard.js, set from the rendered + data as `nodes>600 || links>2400`). Past it the classic path drops the galaxy starfield + outright — `if(GPERF.large)return` in graphStyleBackground — because repainting 110 stars + plus every node and link on every frame is what makes a big store unusable. The opt-in + engine reuses the same thresholds rather than inventing a second signal. */ + const LARGE_NODE_LIMIT = 600; + const LARGE_LINK_LIMIT = 2400; + function idOf(value) { return value && typeof value === 'object' ? value.id : value; } function nodeName(node) { return String(node.name || node.label || node.id || ''); } function linkEndpoint(link, side) { @@ -138,7 +146,7 @@ // otherwise fall back to connected-component BFS, as the dashboard does. if (nodes.length && nodes.every(n => typeof n.community === 'number')) return adj; const seen = new Set(); - let group = 0; + const groups = []; nodes.forEach(n => { if (seen.has(n.id)) return; // Read head instead of Array#shift: shift() is O(n) per pop, which turns this BFS @@ -148,11 +156,21 @@ seen.add(n.id); while (head < queue.length) { const id = queue[head++]; - const node = nodesById.get(id); - if (node) node.community = group; (clusterAdj[id] || []).forEach(next => { if (!seen.has(next)) { seen.add(next); queue.push(next); } }); } - group++; + // `queue` has accumulated the whole component by now, so it *is* the group. + groups.push(queue); + }); + /* Rank by size before the IDs become visible. `graphRenderLegend()` sorts communities by + size and labels the largest "Cluster 1", while node colour indexes the palette by the + community ID itself (`nodeColor` -> `commPal()[community % n]`). Assigning IDs in raw + node order therefore let the legend describe one component with another's swatch + whenever a smaller component happened to appear first in the payload. The classic + renderer sorts its components the same way (`graphComputeCommunities` in dashboard.js), + so largest == community 0 == palette slot 0 == "Cluster 1" on both paths. */ + groups.sort((a, b) => b.length - a.length); + groups.forEach((group, index) => { + group.forEach(id => { const node = nodesById.get(id); if (node) node.community = index; }); }); return adj; } @@ -267,13 +285,16 @@ // Named `styleName`, not `style`: scripts/externalize_dashboard_assets.py scans this // asset for runtime inline-style mutation with a text pattern, and a plain data field // by the shorter name reads as one. The longer name keeps that gate honest. - styleName: 'cyber', colorBy: 'community', palette: 'theme', overrides: {}, + styleName: 'cyber', colorBy: 'community', palette: 'theme', overrides: {}, themeColors: {}, settings: Object.assign({}, PRESETS.communities, { mode: 'communities', labels: false, flow: true, frozen: false }), minDegree: 1, showUnlinked: false, focusId: null, depth: 2, layers: { temporal: true, entity: true, causal: true, semantic: true, code: false }, path: null, asOf: null, ghost: true, sizeBy: 'degree', bridges: false, suggestions: false, collapse: 'auto' }; let raw = { nodes: [], links: [], suggestions: [] }, adj = {}, hilite = null, hoverSet = null, maxDeg = 1; let zoom = 1, collapsed = false; + /* Recomputed from the *rendered* data on every render, exactly as the classic path + recomputes GPERF — filters and focus can take a huge store down to a small view. */ + let large = false; let destroyed = false, running = true, fitTimer = 0, suspended = 0, pendingRender = null; let betweennessReady = false; const fg = ForceGraph()(el); @@ -293,7 +314,7 @@ to that change detection. Everywhere else, letting force-graph park the redraw is what keeps a settled graph off the CPU. */ function needsContinuousFrames() { - return !reduced() && state.styleName === 'galaxy'; + return !reduced() && state.styleName === 'galaxy' && !large; } /* Betweenness is the one analysis that is superlinear in the store size, and nothing in the default view consumes it — the bridge overlay and betweenness-sizing are both off. @@ -317,10 +338,16 @@ } } + /* Priority mirrors the classic renderer's graphTypeColor(): an explicit user override wins, + then a non-classic style's own palette, then the *active theme*. The theme tier is the + reason `themeColors` exists — it cannot be folded into `overrides`, which outrank + STYLE_PAL. The dashboard owns the CSS custom properties (`--entity-*`), so it supplies + the resolved values through setThemeColors() on every applyTheme()/graphRecolor(); + THEME_ETYPE stays only as the standalone-embed fallback for a caller that never does. */ function etypeColor(type) { if (state.overrides[type]) return state.overrides[type]; if (state.styleName !== 'classic' && STYLE_PAL[state.styleName] && STYLE_PAL[state.styleName][type]) return STYLE_PAL[state.styleName][type]; - return THEME_ETYPE[type] || '#8c83e8'; + return state.themeColors[type] || THEME_ETYPE[type] || '#8c83e8'; } function commPal() { return COMMUNITY_PALS[state.styleName] || COMMUNITY_PALS.classic; } function heatColor(node) { @@ -438,6 +465,11 @@ function styleBackground(ctx, scale) { if (state.styleName === 'galaxy') { + /* Matches the classic path's `if(GPERF.large)return`. Paired with the `large` term in + needsContinuousFrames(), this is what lets a big galaxy graph settle: the starfield + is the only paint force-graph cannot see, so once it is skipped there is nothing + left that requires a frame the vendor would not have scheduled itself. */ + if (large) return; const t = performance.now() / 1000; ctx.save(); ctx.globalCompositeOperation = 'lighter'; @@ -602,6 +634,7 @@ } const motion = !reduced(); const data = visible(); + large = data.nodes.length > LARGE_NODE_LIMIT || data.links.length > LARGE_LINK_LIMIT; const sizeMetric = n => state.sizeBy === 'betweenness' ? (n.betweenness || 0) : ((n.degree || 0) / Math.max(1, maxDeg)); data.nodes.forEach(n => { const base = (state.settings.size || 3); @@ -738,6 +771,9 @@ /* Rehydrating saved overrides is not a user edit, so it must not flip the palette selector to "custom" behind the user's back the way setTypeColor deliberately does. */ api.setTypeColors = map => { Object.assign(state.overrides, map || {}); refreshColors(); }; + /* The active theme's resolved `--entity-*` values. Replaced wholesale rather than merged: + a theme switch must not leave the previous theme's colour for a type the new one omits. */ + api.setThemeColors = map => { state.themeColors = map && typeof map === 'object' ? { ...map } : {}; refreshColors(); }; /* One render for a whole batch of setters — see `batch`. */ api.apply = (fn, fit, reheat) => { batch(fn, fit, reheat); }; api.setHighlight = id => { diff --git a/tests/test_graph_engine_asset.py b/tests/test_graph_engine_asset.py index d1daa21..10b0341 100644 --- a/tests/test_graph_engine_asset.py +++ b/tests/test_graph_engine_asset.py @@ -531,6 +531,44 @@ def test_influence_relations_do_not_merge_two_topics_into_one_community() -> Non assert report["bridges"] == 3 +@requires_node +def test_community_ids_are_ranked_by_size_so_the_legend_describes_the_right_nodes() -> None: + """Legend labels and canvas swatches must agree about which cluster is "Cluster 1". + + ``graphRenderLegend()`` sorts communities by size and calls the largest "Cluster 1", but + node colour indexes the palette by the community *id* (``commPal()[community % n]``). + Assigning ids in raw payload order therefore made the legend describe one component with + another's colour whenever a smaller component appeared first — which the payload order + alone decides. The classic ``graphComputeCommunities()`` sorts before assigning; so must + this. + """ + report = _run_node( + """ + // Payload order is deliberately worst-case: the singleton comes first, the largest + // component last, so raw iteration order and size order disagree completely. + const nodes = ['solo', 'm1', 'm2', 'a', 'b', 'c'].map(id => ({ id })); + const links = [ + { source: 'm1', target: 'm2' }, + { source: 'a', target: 'b' }, + { source: 'b', target: 'c' }, + ]; + I.communities(nodes, links); + const byId = {}; + nodes.forEach(n => { byId[n.id] = n.community; }); + emit({ byId, distinct: new Set(nodes.map(n => n.community)).size }); + """ + ) + assert report["distinct"] == 3 + # Largest component (3 nodes) owns palette slot 0, i.e. the legend's "Cluster 1". + assert report["byId"]["a"] == 0 + assert report["byId"]["b"] == 0 + assert report["byId"]["c"] == 0 + # Then the 2-node component, then the singleton — strictly by size, not by payload order. + assert report["byId"]["m1"] == 1 + assert report["byId"]["m2"] == 1 + assert report["byId"]["solo"] == 2 + + @requires_node def test_max_helper_survives_arrays_past_the_spread_limit() -> None: """``Math.max(...array)`` throws RangeError long before a store is unrenderable.""" @@ -593,6 +631,114 @@ def test_flow_particles_are_capped_on_a_large_relation_set() -> None: assert report["realistic"] == 0 +#: A canvas 2D stand-in that counts the fills the galaxy starfield performs. The engine wraps +#: ``onRenderFramePre`` in a try/catch, so a stub too thin to survive the real paint would read +#: as "no stars drawn"; the small-graph leg of the test below is what proves it is thick enough. +CANVAS_STUB = """ +let fills = 0; +const ctx = { + globalAlpha: 1, globalCompositeOperation: '', fillStyle: '', strokeStyle: '', lineWidth: 1, + save() {}, restore() {}, beginPath() {}, arc() {}, ellipse() {}, stroke() {}, + fill() { fills += 1; }, + createRadialGradient() { return { addColorStop() {} }; }, +}; +""" + + +@requires_node +def test_galaxy_stops_animating_once_the_graph_is_large() -> None: + """A settled graph must fall off the CPU, and galaxy was the one style that never did. + + The starfield lives in ``onRenderFramePre``, which force-graph's change detection cannot + see, so the engine holds ``autoPauseRedraw(false)`` for it — repainting every node and link + every frame, forever, even after particles and the simulation have stopped. The classic + path simply drops the starfield past ``GPERF.large`` (``if(GPERF.large)return``); with the + stars gone there is nothing left that needs a frame the vendor would not schedule itself. + """ + report = _run_engine( + CANVAS_STUB + + """ + const api = G.create(el, {}); + api.setStyle('galaxy'); + + api.setData(chain(40)); + const smallAutoPause = store.autoPauseRedraw; + fills = 0; store.onRenderFramePre(ctx, 1); + const smallStars = fills; + + // 3001 entities / 3000 relations — past the classic renderer's 600-node signal. + api.setData(chain(3000)); + const bigAutoPause = store.autoPauseRedraw; + fills = 0; store.onRenderFramePre(ctx, 1); + const bigStars = fills; + + // Style is what costs the frames, not size alone: cyber never asked for them. + api.setStyle('cyber'); + api.setData(chain(40)); + emit({ smallAutoPause, bigAutoPause, smallStars, bigStars, + cyberAutoPause: store.autoPauseRedraw }); + """ + ) + # Small galaxy graph: the animation is affordable, so the engine keeps driving frames. + assert report["smallAutoPause"] is False + assert report["smallStars"] > 0, "canvas stub never reached the starfield" + # Large galaxy graph: no starfield, and the redraw loop is handed back to force-graph. + assert report["bigStars"] == 0 + assert report["bigAutoPause"] is True, "a large galaxy graph repaints every frame forever" + assert report["cyberAutoPause"] is True + + +@requires_node +def test_type_colours_follow_the_active_theme_not_a_hard_coded_dark_palette() -> None: + """``applyTheme()`` recolours the canvas, but the engine had no theme to recolour to. + + The legend and controls read the ``--entity-*`` custom properties, so switching to Light, + Midnight, Solarized or Sepia moved them while the canvas kept the dark-theme constants — + an inconsistent palette and, on the light themes, poor contrast. The engine cannot read + CSS variables from a canvas, so the dashboard supplies the resolved values. + """ + report = _run_engine( + """ + const api = G.create(el, {}); + // setData first: the force-graph stand-in only starts answering graphData() once the + // engine has pushed data into it, where the real vendor seeds an empty graph. + // Linked, because the default scope hides degree-zero entities. + api.setData({ + nodes: [{ id: 'a', etype: 'person_or_concept' }, { id: 'b', etype: 'person_or_concept' }], + links: [{ source: 'a', target: 'b', layer: 'entity' }], + }); + api.setColorBy('type'); + api.setStyle('classic'); + // `store` holds the values handed to force-graph, so this is the node object the + // engine actually painted from — recoloured in place by refreshColors()/render(). + const colour = () => store.graphData.nodes[0].color; + + const fallback = colour(); + api.setThemeColors({ person_or_concept: '#112233' }); + const themed = colour(); + + // A style palette still outranks the theme, exactly as classic graphTypeColor() does. + api.setStyle('cyber'); + const styled = colour(); + + // ...and an explicit user override still outranks both. + api.setStyle('classic'); + api.setTypeColor('person_or_concept', '#abcdef'); + const overridden = colour(); + + // A theme with no entry for the type must not strand the previous theme's colour. + api.setThemeColors({}); + emit({ fallback, themed, styled, overridden, cleared: colour() }); + """ + ) + assert report["fallback"] == "#8c83e8" + assert report["themed"] == "#112233", "the engine ignores the active theme" + assert report["styled"] == "#ff3ea5" + assert report["overridden"] == "#abcdef" + # The override survives; only the theme tier was replaced. + assert report["cleared"] == "#abcdef" + + @requires_node def test_hovering_a_node_asks_for_a_redraw() -> None: """A highlight nobody repaints is invisible. @@ -651,16 +797,35 @@ def test_unlinked_entities_are_shown_only_when_the_engine_is_told_to() -> None: const start = src.indexOf('function graphRenderEngine('); const slice = src.slice(start, src.indexOf('/* Nav away from the graph view', start)); -const log = { created: 0, paused: 0, seeded: 0, scope: null, error: null }; +/* The theme-colour lookup is sliced verbatim too, not stubbed: the property under test is + that the dashboard resolves the *active* CSS custom properties and hands them over, so + faking the resolver would assert nothing. Only `getComputedStyle` below is synthetic. */ +const between = (from, to) => src.slice(src.indexOf(from), src.indexOf(to, src.indexOf(from))); +const themeSrc = between('const ETYPE_TOKEN=', 'const GRAPH_PALETTES=') + + between('function cssvar(', 'function graphValidColor(') + + between('function graphThemeTypeColors(', 'function graphContrastColor('); + +/* A stand-in for a non-dark theme: every --entity-* token differs from the engine's + hard-coded THEME_ETYPE constants, so a renderer that ignored these would be visible. */ +const THEME_VARS = { + '--entity-concept': '#112233', '--entity-mention': '#223344', '--entity-hashtag': '#334455', + '--entity-email': '#445566', '--entity-organization': '#556677', '--entity-location': '#667788', + '--color-accent': '#778899', +}; +globalThis.getComputedStyle = () => ({ getPropertyValue: name => THEME_VARS[name] || '' }); + +const log = { created: 0, paused: 0, seeded: 0, scope: null, themeColors: null, error: null }; const checkbox = { checked: scenario.showUnlinked }; const element = { classList: { toggle() {} }, setAttribute() {}, set textContent(value) {} }; globalThis.document = { getElementById: id => (id === 'graph-show-iso' ? checkbox : element), querySelectorAll: () => [], + body: {}, }; const engine = { setSettings() {}, setStyle() {}, setColorBy() {}, setPalette() {}, setTypeColors() {}, setLayers() {}, setScope(patch) { log.scope = patch; }, + setThemeColors(map) { log.themeColors = map; }, setData(data) { log.seeded = data.nodes.length; }, }; const api = { @@ -685,7 +850,7 @@ def test_unlinked_entities_are_shown_only_when_the_engine_is_told_to() -> None: log.error = String((error && error.message) || error); }; -const graphRenderEngine = new Function(slice + '\\nreturn graphRenderEngine;')(); +const graphRenderEngine = new Function(themeSrc + slice + '\\nreturn graphRenderEngine;')(); const rendered = graphRenderEngine({ nodes: [{ id: 'a' }, { id: 'b' }, { id: 'lonely' }], links: [{ source: 'a', target: 'b' }], @@ -731,6 +896,34 @@ def test_dashboard_tells_the_engine_whether_to_show_unlinked_entities(checked: b assert report["scope"]["minDegree"] == (0 if checked else 1) +@requires_node +def test_dashboard_hands_the_engine_the_active_themes_entity_colours() -> None: + """The other half of the theme fix: the engine can only use what it is given.""" + report = _run_render() + + assert report["themeColors"] is not None, "the engine never learns the active theme" + # Resolved from the stubbed --entity-* custom properties, not from any JS constant. + assert report["themeColors"]["person_or_concept"] == "#112233" + assert report["themeColors"]["organization"] == "#556677" + # Every type the legend can show must be covered, or the canvas falls back per type. + assert set(report["themeColors"]) == { + "person_or_concept", "mention", "hashtag", "email", "organization", "location", + } + + +def test_a_theme_switch_repaints_the_opt_in_canvas() -> None: + """``applyTheme()`` is the only place a theme change is observable. + + It already calls ``graphRecolor()``; that path has to reach the engine, or the canvas keeps + the previous theme until the next full graph render. + """ + source = DASHBOARD.read_text(encoding="utf-8") + assert "if(typeof graphRecolor==='function')graphRecolor()" in source + recolor = source[source.index("function graphRecolor()"):] + recolor = recolor[: recolor.index("\nfunction graphFit")] + assert "engine.setThemeColors(graphThemeTypeColors())" in recolor + + @requires_node def test_a_renderer_created_after_leaving_the_graph_view_is_born_paused() -> None: """The rAF leak this PR already fixed once, reached by a different route. From 97c538cf1818b01263a0b099580ef0be13eb5d73 Mon Sep 17 00:00:00 2001 From: Jaixii Date: Sun, 26 Jul 2026 18:18:50 -0400 Subject: [PATCH 21/82] test(licensing): make the outage-is-not-a-cancellation test actually test that The test raised CloudSessionError(..., status=503, transient=True), but that class takes only status -- transient belongs to CloudFeatureError. So the construction raised TypeError, the caller's broad except Exception swallowed it, and getattr(exc, "status", None) was None rather than 503. The assertion therefore passed while never exercising a transport failure at all, and could not have caught the regression it exists to prevent: loosening the 402 gate so any error clears a paying customer's access. Verified by mutation -- with the gate changed to any-truthy-status the test now fails with "an outage revoked a paying customer"; before this change it passed even with that mutation. Co-Authored-By: Claude Opus 5 (1M context) --- tests/test_hosted_plan_resolution.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/test_hosted_plan_resolution.py b/tests/test_hosted_plan_resolution.py index b3812c1..a867f36 100644 --- a/tests/test_hosted_plan_resolution.py +++ b/tests/test_hosted_plan_resolution.py @@ -941,8 +941,13 @@ def test_a_transport_failure_is_not_mistaken_for_a_billing_denial(monkeypatch) - assert _settled_license(monkeypatch)["cloud_access_active"] is True def _offline(*_args, **_kwargs): + # ``CloudSessionError`` takes only ``status``; ``transient`` belongs to + # ``CloudFeatureError``. Passing it here raised TypeError instead, which the + # caller's broad ``except Exception`` swallowed with no ``status`` attribute -- so + # this test used to pass by never exercising a 503 at all, and would not have + # caught a regression that let a genuine outage clear a paying customer's access. raise cloud_session.CloudSessionError( - "Engraphis Cloud is temporarily unreachable.", status=503, transient=True + "Engraphis Cloud is temporarily unreachable.", status=503 ) monkeypatch.setattr(cloud_session, "access_for_workspace", _offline) From 6084dfd0b9f90c2db158897f3f28ffc2f4d42c08 Mon Sep 17 00:00:00 2001 From: Jaixii Date: Sun, 26 Jul 2026 18:24:58 -0400 Subject: [PATCH 22/82] Report post-redemption connect failures instead of raising tracebacks Both paths fail *after* the control plane has consumed the single-use connect token, so a raw traceback left the customer unable to tell whether to retry or fetch a new token from the portal. `http.client.IncompleteRead` (a truncated chunked reply) subclasses `HTTPException`/`ValueError` -- neither `OSError` nor `URLError` -- so it escaped both of `post_connect`'s handlers. A third clause is added *after* the transport clause, because `RemoteDisconnected` is both a `ConnectionResetError` and a `BadStatusLine` and means the peer never answered: that one keeps the retryable 503 copy, and a test pins the ordering. `save_bootstrap` re-runs `validate_cloud_base_url` on both endpoints, which resolves the host. A resolver that dies mid-connect raises `CloudUrlUnresolved` and an endpoint that starts resolving to a rejected address raises a bare `ValueError`; both are `ValueError`, so neither the `CloudSessionError` nor the `OSError` handler in `connect()` covered them. Translated in `connect()` rather than by dropping the re-validation, which is still wanted for `save_bootstrap`'s other callers. Co-Authored-By: Claude Opus 5 --- CHANGELOG.md | 6 +- engraphis/device_connect.py | 40 +++++++++++ tests/test_device_connect.py | 128 +++++++++++++++++++++++++++++++++++ 3 files changed, 173 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8ba3cbb..c2de406 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,7 +19,11 @@ All notable changes to Engraphis are documented here. Format loosely follows with a lapsed subscription). Session storage is pre-flighted before the exchange, so an unwritable state directory or a `cloud_session.json` replaced by a link fails the command *without* spending the single-use token — the customer fixes the path and retries with the - same token instead of returning to the portal for a new one. Also installed as + same token instead of returning to the portal for a new one. Faults that can only happen + *after* the exchange — a reply truncated mid-body (`http.client.IncompleteRead`), or an + endpoint that stops resolving before the session is written (`CloudUrlUnresolved`) — are + reported as errors that say the token was already used, rather than escaping as tracebacks + that leave the customer unable to tell whether to retry. Also installed as `engraphis-connect`. - An `engraphis` front-door command that dispatches to the existing `engraphis-` entry points, so the command the account portal displays is runnable as shown. diff --git a/engraphis/device_connect.py b/engraphis/device_connect.py index d0698bb..cf50c73 100644 --- a/engraphis/device_connect.py +++ b/engraphis/device_connect.py @@ -25,6 +25,7 @@ """ from __future__ import annotations +import http.client import json import math import os @@ -65,6 +66,17 @@ #: The control plane answers with a small fixed record; anything larger is not ours. _MAX_RESPONSE_BYTES = 64 * 1024 +#: Copy for a reply that began but never completed. Every other failure in this module can +#: promise the connect token is untouched; this one cannot, because the request reached a +#: control plane that started to answer, and a 200 consumes the token as it is written. +#: Saying "try again" here would be a lie that costs the customer a second failed attempt, +#: so the copy sends them to the one place that shows whether the device landed. +_TRUNCATED_REPLY = ( + "Engraphis Cloud started answering this connect request but the connection closed " + "before the reply was complete. Your connect token may already have been used: check " + "your account portal, and generate a new one if this device is not listed there." +) + #: The portal always mints tokens with this prefix. Checking it locally turns a #: mistyped or truncated paste into an instant, free error instead of a round trip that #: consumes rate budget and returns the same opaque 401 as a genuinely dead token. @@ -457,11 +469,25 @@ def post_connect(control_url: str, token: str, *, installation_client_id: str, raise _connect_http_error(status) except (urllib.error.URLError, TimeoutError, OSError) as exc: # ``exc`` may quote an internal host or a proxy URL; never reflect it. + # + # Deliberately ahead of the ``HTTPException`` clause: ``RemoteDisconnected`` is + # both a ``ConnectionResetError`` and a ``BadStatusLine``, and it means the peer + # closed without answering at all. Nothing was consumed, so "try again" is the + # correct advice for it and it must not inherit the token-may-be-spent copy. raise DeviceConnectError( "Engraphis Cloud is temporarily unreachable. Check your network and try " "again.", status=503, ) from exc + except http.client.HTTPException as exc: + # A truncated chunked body makes ``HTTPResponse.read`` raise ``IncompleteRead``, + # which subclasses ``HTTPException``/``ValueError`` and is neither an ``OSError`` + # nor a ``URLError`` -- so it escaped both clauses above as a raw traceback. That + # happened at the worst moment: the control plane had already answered, so the + # single-use token was very likely spent, and the customer saw a stack trace + # instead of being told to check the portal. ``LineTooLong``/``BadStatusLine`` from + # reading the status line and headers land here for the same reason. + raise DeviceConnectError(_TRUNCATED_REPLY, status=502) from exc if len(raw) > _MAX_RESPONSE_BYTES: raise DeviceConnectError( "Engraphis Cloud returned an oversized connect response.", status=502 @@ -603,6 +629,20 @@ def connect(token: object, *, control_url: Optional[str] = None, "portal -- this one has been used." % session_path, status=409, ) from exc + except ValueError as exc: + # ``save_bootstrap`` re-runs ``validate_cloud_base_url`` on both endpoints, and + # that helper *resolves* the host. A resolver that dies between the pre-POST check + # and this line raises ``CloudUrlUnresolved``; an endpoint that starts resolving to + # a rejected address raises a bare ``ValueError``. Both are ``ValueError``, so + # neither the ``CloudSessionError`` nor the ``OSError`` clause above covered them + # and they escaped as a traceback -- again after the token was already spent. + raise DeviceConnectError( + "Engraphis Cloud accepted the token, but its endpoints could not be verified " + "in time to save the session, so nothing was written. Check your network, " + "then connect again with a new token from your account portal -- this one " + "has been used.", + status=409, + ) from exc summary = summarize(response) summary["control_url"] = resolved_control diff --git a/tests/test_device_connect.py b/tests/test_device_connect.py index 2367fa5..2d636e9 100644 --- a/tests/test_device_connect.py +++ b/tests/test_device_connect.py @@ -7,6 +7,7 @@ """ from __future__ import annotations +import http.client import json import os import urllib.error @@ -17,6 +18,7 @@ import pytest from engraphis import cloud_session, device_connect +from engraphis.hosted_client import CloudUrlUnresolved from engraphis.private_state import UnsafeStateFile from scripts import connect as connect_cli @@ -350,6 +352,132 @@ def open(self, request, timeout): device_connect.connect(TOKEN, control_url=CONTROL_URL, compute_url=COMPUTE_URL) +# ------------------------------------------- failures *after* the token has been spent +# +# Once ``opener.open`` has returned, the control plane has answered and the single-use +# connect token is gone. Every fault from that point on has to arrive as a +# ``DeviceConnectError`` that says so -- a traceback here is the worst possible outcome, +# because the customer cannot tell whether to retry or fetch a new token. + + +class _TruncatedBody: + """A 200 whose body stops mid-stream, the way a dropped chunked reply does.""" + + def __enter__(self): + return self + + def __exit__(self, *exc) -> bool: + return False + + def read(self, size: int = -1) -> bytes: + # What ``HTTPResponse._read_chunked`` raises for a truncated body. It subclasses + # ``HTTPException``/``ValueError`` -- neither ``OSError`` nor ``URLError``. + raise http.client.IncompleteRead(b'{"organization_id":"org_al') + + +@pytest.mark.parametrize("failure", [ + http.client.IncompleteRead(b'{"organization_id":"org_al'), + http.client.LineTooLong("header line"), + http.client.BadStatusLine("garbage"), +]) +def test_a_truncated_reply_reports_the_token_state_not_a_traceback( + monkeypatch, tmp_path, failure +): + """``IncompleteRead`` is an ``HTTPException``, so the transport clause never saw it.""" + + class _Broken(_Opener): + def open(self, request, timeout): + self.calls.append({"body": request.data}) + if isinstance(failure, http.client.IncompleteRead): + return _TruncatedBody() + raise failure + + opener = _Broken() + _install_opener(monkeypatch, opener) + + with pytest.raises(device_connect.DeviceConnectError) as caught: + device_connect.connect(TOKEN, control_url=CONTROL_URL, compute_url=COMPUTE_URL) + + message = str(caught.value) + assert caught.value.status == 502 + # The customer must be told the token may be gone rather than told to just retry. + assert "may already have been used" in message + assert TOKEN not in message + assert not (tmp_path / "cloud_session.json").exists() + + +def test_a_connection_reset_before_any_reply_still_says_retry(monkeypatch): + """``RemoteDisconnected`` is *both* an ``OSError`` and an ``HTTPException``. + + Nothing was read, so the token is untouched and "try again" remains the right copy; + it must not be swept into the token-may-be-spent message by the new clause. + """ + + _install_opener( + monkeypatch, _Opener(error=http.client.RemoteDisconnected("closed early")) + ) + + with pytest.raises(device_connect.DeviceConnectError) as caught: + device_connect.connect(TOKEN, control_url=CONTROL_URL, compute_url=COMPUTE_URL) + + assert caught.value.status == 503 + assert "temporarily unreachable" in str(caught.value) + + +@pytest.mark.parametrize("failure", [ + CloudUrlUnresolved("cloud service URL could not be resolved"), + ValueError("cloud service URL must not target private/reserved IP ranges"), +]) +def test_endpoint_validation_failing_after_redemption_is_not_a_traceback( + monkeypatch, tmp_path, failure +): + """``save_bootstrap`` re-resolves both endpoints *after* the POST spent the token. + + ``CloudUrlUnresolved`` is a ``ValueError``, so neither the ``CloudSessionError`` nor + the ``OSError`` handler in ``connect()`` covers it: a resolver that dies mid-connect, + or a host that starts resolving to a rejected address, escaped as a raw traceback. + """ + + opener = _Opener(body=REGISTRATION) + _install_opener(monkeypatch, opener) + + def _rejects(value): + raise failure + + # Only the save path: the pre-POST checks in ``connect()`` already passed. + monkeypatch.setattr(cloud_session, "validate_cloud_base_url", _rejects) + + with pytest.raises(device_connect.DeviceConnectError) as caught: + device_connect.connect(TOKEN, control_url=CONTROL_URL, compute_url=COMPUTE_URL) + + message = str(caught.value) + assert caught.value.status == 409 + assert opener.calls, "the token was spent; the copy has to admit it" + assert "has been used" in message + assert TOKEN not in message + assert not (tmp_path / "cloud_session.json").exists() + + +def test_the_cli_reports_a_post_redemption_fault_instead_of_a_traceback( + monkeypatch, capsys +): + _install_opener(monkeypatch, _Opener(body=REGISTRATION)) + + def _rejects(value): + raise CloudUrlUnresolved("cloud service URL could not be resolved") + + monkeypatch.setattr(cloud_session, "validate_cloud_base_url", _rejects) + + code = connect_cli.main([ + "--token", TOKEN, "--control-url", CONTROL_URL, "--compute-url", COMPUTE_URL, + ]) + + err = capsys.readouterr().err + assert code == 1 + assert "Traceback" not in err + assert "has been used" in err + + # ------------------------------------------------------ pre-flight on session storage # # The POST is the point of no return: the control plane consumes the single-use connect From 385289fabf25f2459d061f16c074959bf1391438 Mon Sep 17 00:00:00 2001 From: Jaixii Date: Sun, 26 Jul 2026 18:30:40 -0400 Subject: [PATCH 23/82] fix(graph): close the remaining review threads on the opt-in engine Six findings from the PR #74 review, all cases where the opt-in renderer diverged from the classic path it is meant to replace. - Relation labels: the dashboard's Labels checkbox drives two label layers on the classic path, but the engine configured no linkCanvasObject, so ticking it painted entity names only and a relation could be read only by hovering it. Paint them, with the classic gates (zoom, dense-graph). - zoomToNode: graphFocus() treats a false return as "run the recovery path". The engine answered from raw.nodes, which keeps the coordinates force-graph left on a node, so an entity hidden by a scope filter or by the auto-collapsed cluster view still reported success and the camera moved to nothing. Expand a collapsed view, then verify against the data force-graph is actually holding. - Reseeding: render() called graphData() unconditionally with newly allocated arrays, so Style, Color by, Labels and Flow each reset the d3 alpha and restarted the layout. Reseed only when the visible set really changed, and invalidate the paint when it did not. - Cooldown: nothing overrode force-graph's 15s default simulation window, so a large store kept simulating (and repainting) far past the 1.1s/80 ticks the classic path allows. Mirror its size-dependent bounds. - Dense graphs: curvature and arrowheads stayed on past the classic GPERF.dense threshold, paying a bezier and a filled triangle per relation across thousands of links. - Community colours: the cluster legend swatches are CSS (.graph-cluster-N) encoding the Cyber palette, but the engine's Cyber and Solar palettes were ordered differently from dashboard.js, so on the default style the legend described each of the first clusters with another cluster's colour. Each is covered by a test that fails without the change. Co-Authored-By: Claude Opus 5 --- engraphis/static/engraphis-graph.js | 141 ++++++++++++-- tests/test_graph_engine_asset.py | 282 ++++++++++++++++++++++++++++ 2 files changed, 411 insertions(+), 12 deletions(-) diff --git a/engraphis/static/engraphis-graph.js b/engraphis/static/engraphis-graph.js index 28ba123..6499d78 100644 --- a/engraphis/static/engraphis-graph.js +++ b/engraphis/static/engraphis-graph.js @@ -40,11 +40,17 @@ contrast: { person_or_concept: '#0072b2', mention: '#009e73', hashtag: '#e69f00', email: '#56b4e9', organization: '#cc79a7', location: '#d55e00' } }; const THEME_ETYPE = { person_or_concept: '#8c83e8', mention: '#5aafb3', hashtag: '#d7a84b', email: '#6f9fd8', organization: '#58b882', location: '#df7478' }; + /* Community colour is the *palette slot*, not the node: `nodeColor` indexes this by the + community id, and communities are numbered by size (largest == 0). The legend beside the + canvas paints its swatches from `.graph-cluster-N` in dashboard.css, which encodes the + Cyber palette — the default style — slot for slot. These arrays must therefore stay + byte-identical to `COMMUNITY_PALS` in dashboard.js, or "Cluster 1" gets one colour in the + legend and another on the canvas. Ordering is load-bearing; this is not free-choice art. */ const COMMUNITY_PALS = { classic: ['#8c83e8', '#5aafb3', '#d7a84b', '#6f9fd8', '#58b882', '#df7478', '#b07de0', '#4fb0a0', '#e0894a', '#7c9be0', '#e06a9a', '#9ac25a'], galaxy: ['#b789ff', '#7bb4ff', '#66e0d0', '#ffcf6b', '#ff7ea8', '#8aa2ff', '#c98bff', '#5ad0e0', '#ffa0d0', '#9d7bff', '#6ad0b0', '#ffb060'], - solar: ['#ffb454', '#3fd2c7', '#ffd68a', '#5b9bff', '#ff8f6b', '#8ea8ff', '#ffc98a', '#4fc0b0', '#ff9f5b', '#7fb0ff', '#ffd0a0', '#5ad0c0'], - cyber: ['#ff3ea5', '#22e0ff', '#b6ff3c', '#ffe14d', '#8b7bff', '#ff5c7a', '#3cffd0', '#ff9ae0', '#5ce0ff', '#d0ff3c', '#ffb03c', '#a06bff'] + solar: ['#ffb454', '#5b9bff', '#3fd2c7', '#ffd68a', '#ff8f6b', '#8ea8ff', '#ffc24a', '#6ac0d0', '#ff9f7a', '#7ab0ff', '#e0b050', '#5fd0b0'], + cyber: ['#22e0ff', '#ff3ea5', '#b6ff3c', '#ffe14d', '#8b7bff', '#ff5c7a', '#3affd0', '#ff7be0', '#7affea', '#c0ff4a', '#5c9bff', '#ff9b3c'] }; const GRAPH_HEAT = ['#3f7bff', '#6a5cff', '#a24bff', '#e0479f', '#ff6b6b', '#ffc23d']; @@ -63,6 +69,18 @@ const LARGE_NODE_LIMIT = 600; const LARGE_LINK_LIMIT = 2400; + /* The classic renderer's *dense* signal (`GPERF.dense`, `links>1500` in dashboard.js). Past + it the classic path turns off the two per-edge costs that scale with the link count and + buy nothing at that density: link curvature (a quadratic bezier per relation instead of a + straight line) and the directional arrowhead (a filled triangle per relation, recomputed + every frame). Relation labels get the same treatment unless one node is highlighted. Same + thresholds and same behaviour here — a second signal would only drift. */ + const DENSE_LINK_LIMIT = 1500; + + /* Relation labels are the noisiest layer on the canvas, so — exactly as the classic + `linkCanvasObject` does — they only appear once the user has zoomed in past this scale. */ + const LINK_LABEL_MIN_SCALE = 2.4; + function idOf(value) { return value && typeof value === 'object' ? value.id : value; } function nodeName(node) { return String(node.name || node.label || node.id || ''); } function linkEndpoint(link, side) { @@ -294,7 +312,11 @@ let zoom = 1, collapsed = false; /* Recomputed from the *rendered* data on every render, exactly as the classic path recomputes GPERF — filters and focus can take a huge store down to a small view. */ - let large = false; + let large = false, dense = false; + /* The node/link arrays last handed to force-graph. Seeding is not free: the vendor copies + the data in and d3 resets the simulation alpha to 1, so a paint-only change would restart + the whole layout. See `sameData`/`render`. */ + let seeded = null; let destroyed = false, running = true, fitTimer = 0, suspended = 0, pendingRender = null; let betweennessReady = false; const fg = ForceGraph()(el); @@ -626,6 +648,61 @@ invalidate(); } + /* The dashboard's **Labels** checkbox turns on *both* label layers on the classic path: + entity names (painted by styleNode) and relation names (a `linkCanvasObject`, drawn + 'after' the line so it sits on top of it). Without this second half the checkbox silently + did half its job under `?graph-engine=next` and a relation name could only be read by + hovering one edge at a time. Same gates as classic graphRender(): zoomed in past + LINK_LABEL_MIN_SCALE, the relation actually carries a label, and — on a dense graph — + only while something is highlighted, so thousands of overlapping strings are never + painted at once. Canvas text is not an HTML sink, so the raw label is drawn here; the + escaped copy is for `linkLabel`, whose tooltip *is* one. */ + function applyLinkLabels() { + if (!fg.linkCanvasObject || !fg.linkCanvasObjectMode) return; + if (!state.settings.labels) { fg.linkCanvasObjectMode(() => undefined); return; } + fg.linkCanvasObjectMode(() => 'after').linkCanvasObject((link, ctx, scale) => { + if (!link || !link.label || scale < LINK_LABEL_MIN_SCALE) return; + if (dense && !hilite) return; + const source = link.source, target = link.target; + if (!source || !target || typeof source !== 'object' || typeof target !== 'object') return; + if (!Number.isFinite(source.x) || !Number.isFinite(source.y)) return; + if (!Number.isFinite(target.x) || !Number.isFinite(target.y)) return; + if (link.ghost) return; + ctx.font = ((state.settings.font || 12) * 0.82) / scale + 'px system-ui, sans-serif'; + ctx.fillStyle = 'rgba(232,236,245,.62)'; + ctx.textAlign = 'center'; + ctx.textBaseline = 'middle'; + ctx.fillText(String(link.label), (source.x + target.x) / 2, (source.y + target.y) / 2); + ctx.textAlign = 'left'; + }); + } + + /* Does this render show the same entities and relations as the one force-graph is already + holding? Compared by identity of the *view*, not of the payload: `visible()` allocates + fresh arrays every call (and `collapsedData` fresh cluster nodes), so an object compare + would report a change for Style, Color by, Labels and Flow — none of which move a node. */ + function sameData(previous, next) { + if (!previous) return false; + if (previous.nodes.length !== next.nodes.length) return false; + if (previous.links.length !== next.links.length) return false; + for (let i = 0; i < next.nodes.length; i++) { + if (previous.nodes[i].id !== next.nodes[i].id) return false; + } + for (let i = 0; i < next.links.length; i++) { + const a = previous.links[i], b = next.links[i]; + if (linkEndpoint(a, 'source') !== linkEndpoint(b, 'source')) return false; + if (linkEndpoint(a, 'target') !== linkEndpoint(b, 'target')) return false; + if ((a.layer || '') !== (b.layer || '')) return false; + if (!a.suggested !== !b.suggested) return false; + if (!a.ghost !== !b.ghost) return false; + } + return true; + } + + /* Large graphs settle harder, exactly as the classic path does (`GPERF.large?.055:.035`). + Shared so reheat() and freeze() cannot drift back to the small-graph constant. */ + function alphaDecay() { return large ? 0.055 : 0.035; } + function render(fit, reheat) { if (destroyed) return; if (suspended) { @@ -633,8 +710,14 @@ return; } const motion = !reduced(); - const data = visible(); + const next = visible(); + /* Reuse the arrays force-graph already holds when the view is unchanged: the sizing and + colouring pass below must write onto the objects the vendor is painting from, and the + collapsed view hands out freshly built cluster nodes on every call. */ + const reused = sameData(seeded, next); + const data = reused ? seeded : next; large = data.nodes.length > LARGE_NODE_LIMIT || data.links.length > LARGE_LINK_LIMIT; + dense = data.links.length > DENSE_LINK_LIMIT; const sizeMetric = n => state.sizeBy === 'betweenness' ? (n.betweenness || 0) : ((n.degree || 0) / Math.max(1, maxDeg)); data.nodes.forEach(n => { const base = (state.settings.size || 3); @@ -645,13 +728,22 @@ n.stroke = contrastOn(n.color); }); applyChrome(); - fg.graphData(data); + if (!reused) { fg.graphData(data); seeded = data; } applyForces(); fg.autoPauseRedraw(!needsContinuousFrames()); - if (fg.d3AlphaDecay) fg.d3AlphaDecay(0.035); - if (fg.d3VelocityDecay) fg.d3VelocityDecay(0.38); - if (fg.linkCurvature) fg.linkCurvature((PRESETS[state.settings.mode] || PRESETS.compact).curve || 0); - fg.linkDirectionalArrowLength(2.5).linkDirectionalArrowRelPos(1); + /* Bound the simulation the way the classic path does. Without these force-graph keeps its + 15-second default window, so every load and every reheat of a large store runs the + layout — and repaints every node and link — for more than ten seconds longer. */ + if (fg.cooldownTime) fg.cooldownTime(motion ? (large ? 1100 : 2200) : 0); + if (fg.cooldownTicks) fg.cooldownTicks(motion ? (large ? 80 : 160) : 1); + if (fg.warmupTicks) fg.warmupTicks(motion ? (large ? 18 : 40) : 45); + if (fg.d3AlphaDecay) fg.d3AlphaDecay(alphaDecay()); + if (fg.d3VelocityDecay) fg.d3VelocityDecay(large ? 0.45 : 0.38); + if (fg.linkCurvature) { + fg.linkCurvature(dense ? 0 : ((PRESETS[state.settings.mode] || PRESETS.compact).curve || 0)); + } + fg.linkDirectionalArrowLength(dense ? 0 : 2.5).linkDirectionalArrowRelPos(1); + applyLinkLabels(); if (fg.linkDirectionalParticles) { const flowing = state.settings.flow !== false && motion @@ -666,6 +758,9 @@ } if (reheat && motion && !state.settings.frozen && fg.d3ReheatSimulation) fg.d3ReheatSimulation(); if ((state.settings.frozen || !motion) && fg.d3AlphaDecay) { /* keep painting, stop layout */ fg.d3AlphaDecay(1); } + /* Nothing was reseeded, so force-graph's own change detection saw no reason to repaint — + but Style, Color by and Labels all just changed how the *same* data must be drawn. */ + if (reused) invalidate(); if (fit) { clearTimeout(fitTimer); fitTimer = setTimeout(() => { if (!destroyed) fg.zoomToFit(motion ? 600 : 0, 40); }, motion ? 320 : 0); @@ -741,6 +836,10 @@ const suggestions = (Array.isArray(data && data.suggestions) ? data.suggestions : []) .map(link => Object.assign({}, link, { source: linkEndpoint(link, 'source'), target: linkEndpoint(link, 'target') })) .filter(link => link.source != null && link.target != null); + /* A fresh payload means fresh node objects, so the cached seed is stale even when the + ids are identical — force-graph must be re-pointed at the new objects or the render + below would style ones nobody is painting from. */ + seeded = null; raw = { nodes, links, suggestions }; adj = communities(raw.nodes, raw.links); const deg = {}; @@ -789,19 +888,36 @@ api.reheat = () => { if (destroyed || reduced()) return; raw.nodes.forEach(n => { n.fx = undefined; n.fy = undefined; }); - if (fg.d3ReheatSimulation) { fg.d3AlphaDecay(0.035); fg.d3ReheatSimulation(); } + if (fg.d3ReheatSimulation) { fg.d3AlphaDecay(alphaDecay()); fg.d3ReheatSimulation(); } }; api.freeze = on => { state.settings.frozen = on; if (on) { fg.d3Force('charge').strength(0); fg.d3AlphaDecay(1); return; } applyForces(); if (reduced()) return; - fg.d3AlphaDecay(0.035); + fg.d3AlphaDecay(alphaDecay()); if (fg.d3ReheatSimulation) fg.d3ReheatSimulation(); }; + /* Returning `false` is not a failure: it is the signal the dashboard's graphFocus() uses to + run its recovery path ("show unlinked", then retry, then say so). Reporting success for an + entity that is not on the canvas is therefore worse than reporting failure — the user gets + a camera move to nothing and no explanation. Two ways that happened: the auto-collapsed + view paints only `cluster-*` bubbles, and any filtered-out node keeps the x/y force-graph + left on it from an earlier render, so "found in `raw.nodes` with finite coordinates" was + never evidence of visibility. Expand a collapsed view first — focusing a named entity is + an explicit request to see it — then confirm against the data force-graph is holding. */ api.zoomToNode = id => { + if (destroyed) return false; const n = raw.nodes.find(x => x.id === id); - if (!n || !Number.isFinite(n.x) || !Number.isFinite(n.y)) return false; + if (!n) return false; + if (collapsed) { + collapsed = false; + state.collapse = false; + render(false, true); + if (opts.onCollapseChange) opts.onCollapseChange(false); + } + const shown = ((fg.graphData() || {}).nodes || []).some(node => node && node.id === id); + if (!shown || !Number.isFinite(n.x) || !Number.isFinite(n.y)) return false; const duration = reduced() ? 0 : 500; fg.centerAt(n.x, n.y, duration); fg.zoom(3, duration); @@ -872,6 +988,7 @@ } catch (e) { /* teardown is best-effort: never let it block a view change */ } raw = { nodes: [], links: [], suggestions: [] }; adj = {}; + seeded = null; hilite = null; hoverSet = null; }; diff --git a/tests/test_graph_engine_asset.py b/tests/test_graph_engine_asset.py index 10b0341..773297d 100644 --- a/tests/test_graph_engine_asset.py +++ b/tests/test_graph_engine_asset.py @@ -951,6 +951,288 @@ def test_leaving_the_graph_view_records_the_pause_as_well_as_applying_it() -> No assert "GRAPH_ENGINE_PARKED=false" in pause +#: Force-graph resolves each link's ``source``/``target`` from an id to the node object once it +#: owns the data, and the paint callbacks read ``.x``/``.y`` off those objects. The recording +#: stand-in stores the arrays untouched, so a test that wants to *drive* a link painter has to +#: do that resolution — and give the nodes coordinates — itself. +LAY_OUT = """ +const layOut = () => { + const data = store.graphData; + const byId = new Map(data.nodes.map(n => [n.id, n])); + data.nodes.forEach((n, i) => { n.x = i * 10; n.y = i; }); + data.links.forEach(l => { + const s = byId.get(l.source && l.source.id !== undefined ? l.source.id : l.source); + const t = byId.get(l.target && l.target.id !== undefined ? l.target.id : l.target); + if (s) l.source = s; + if (t) l.target = t; + }); + return data; +}; +let painted = []; +const linkCtx = { + font: '', fillStyle: '', textAlign: '', textBaseline: '', + fillText(text) { painted.push(String(text)); }, +}; +const paintLinks = (scale, links) => { + painted = []; + const mode = store.linkCanvasObjectMode ? store.linkCanvasObjectMode() : undefined; + const draw = store.linkCanvasObject; + if (mode === 'after' && draw) (links || store.graphData.links).forEach(l => draw(l, linkCtx, scale)); + return painted.slice(); +}; +""" + + +@requires_node +def test_relation_labels_are_painted_when_the_labels_box_is_ticked() -> None: + """**Labels** turns on two label layers on the classic path; the engine only had one. + + ``graphToggleLabels`` forwards the checkbox straight to ``setSettings({labels})``, and the + classic renderer answers it with *both* entity names and a ``linkCanvasObject`` that paints + each ``link.label``. The opt-in engine configured no link painter at all, so relation names + silently disappeared under ``?graph-engine=next`` and could only be read by hovering one + edge at a time. + """ + report = _run_engine( + LAY_OUT + + """ + const api = G.create(el, { reducedMotion: () => true }); + api.setData({ + nodes: [{ id: 'a' }, { id: 'b' }], + links: [{ source: 'a', target: 'b', layer: 'entity', label: 'mentions' }], + }); + layOut(); + const unticked = paintLinks(4); + api.setSettings({ labels: true }); + const ticked = paintLinks(4); + // Relation labels are the noisiest layer: they stay off until the user zooms in. + const zoomedOut = paintLinks(1); + emit({ unticked, ticked, zoomedOut }); + """ + ) + assert report["unticked"] == [] + assert report["ticked"] == ["mentions"], "the Labels checkbox never paints relation names" + assert report["zoomedOut"] == [] + + +@requires_node +def test_focusing_an_entity_the_canvas_is_not_showing_does_not_report_success() -> None: + """``zoomToNode`` is the dashboard's visibility oracle, and it was answering from memory. + + ``graphFocus`` treats ``false`` as "offer the recovery path" — tick *Show unlinked*, retry, + and otherwise say *Entity not in view*. The engine answered from ``raw.nodes``, which keeps + the coordinates force-graph left on a node from an earlier render, so a node hidden by the + auto-collapsed view (only ``cluster-*`` bubbles are drawn below zoom 0.55) or by a scope + filter still reported success — the camera moved to nothing and the user got no explanation. + """ + report = _run_engine( + """ + const collapses = []; + const api = G.create(el, { + reducedMotion: () => true, onCollapseChange: value => collapses.push(value), + }); + api.setData({ + nodes: [{ id: 'a' }, { id: 'b' }, { id: 'c' }, { id: 'lonely' }], + links: [{ source: 'a', target: 'b' }, { source: 'b', target: 'c' }], + }); + const shownIds = () => (store.graphData.nodes || []).map(n => n.id); + // Everything visible once, so every entity carries real coordinates from here on. + api.setScope({ showUnlinked: true, minDegree: 0 }); + store.graphData.nodes.forEach((n, i) => { n.x = i * 10; n.y = i; }); + + // 1. Hidden by the scope filter, but still remembered with valid coordinates. + api.setScope({ showUnlinked: false, minDegree: 1 }); + const filtered = { found: api.zoomToNode('lonely'), shown: shownIds() }; + + // 2. Hidden by the collapsed view, which paints cluster bubbles instead of entities. + api.setCollapse(true); + const whileCollapsed = shownIds(); + const focused = api.zoomToNode('c'); + emit({ + filtered, whileCollapsed, focused, collapses, + afterFocus: shownIds(), collapsed: api.state().collapsed, + }); + """ + ) + # A filtered-out entity is not in view, so the dashboard must be told to recover. + assert report["filtered"]["found"] is False, "a filtered-out entity reported as visible" + assert "lonely" not in report["filtered"]["shown"] + # A collapsed view really is showing only bubbles... + assert report["whileCollapsed"] == ["cluster-0"] + # ...so focusing a named entity has to expand it rather than claim it is already on screen. + assert report["focused"] is True + assert report["collapsed"] is False + assert "c" in report["afterFocus"], "the entity is still not on the canvas" + assert report["collapses"][-1] is False, "the dashboard was never told the view expanded" + + +@requires_node +def test_appearance_only_changes_do_not_restart_the_layout() -> None: + """Style, Color by, Labels and Flow repaint the graph; they must not re-run it. + + ``visible()`` allocates fresh arrays on every call, and force-graph treats any ``graphData`` + call as a data update: it re-copies the nodes and d3 resets the simulation alpha to 1. So + every appearance-only setter threw the settled layout away and made the whole graph move. + The classic renderer guards the same seed with ``if(dataChanged)FG.graphData(data)``. + """ + report = _run_engine( + """ + const api = G.create(el, { reducedMotion: () => true }); + const nodes = [{ id: 'lonely', etype: 'organization' }], links = []; + for (let i = 0; i < 12; i++) nodes.push({ id: 'n' + i, etype: 'person_or_concept' }); + for (let i = 0; i < 11; i++) links.push({ source: 'n' + i, target: 'n' + (i + 1) }); + api.setData({ nodes, links }); + const seeded = calls.graphData; + const before = store.graphData.nodes[0].color; + const repaintsBefore = calls.nodeCanvasObject; + + api.setStyle('galaxy'); + api.setColorBy('type'); + api.setSettings({ labels: true }); + api.setSettings({ flow: false }); + const paintOnly = calls.graphData; + const recoloured = store.graphData.nodes[0].color; + const repaintsAfter = calls.nodeCanvasObject; + + // A genuine change to the visible set still has to reach force-graph. + api.setScope({ showUnlinked: true, minDegree: 0 }); + emit({ + seeded, paintOnly, afterScope: calls.graphData, before, recoloured, + repaintsBefore, repaintsAfter, shown: store.graphData.nodes.length, + }); + """ + ) + assert report["paintOnly"] == report["seeded"], "an appearance change restarted the layout" + assert report["afterScope"] > report["seeded"], "a real view change never reached the canvas" + assert report["shown"] == 13 + # Skipping the reseed must not mean skipping the paint. + assert report["recoloured"] != report["before"] + assert report["repaintsAfter"] > report["repaintsBefore"] + + +@requires_node +def test_simulation_time_is_bounded_on_a_large_graph() -> None: + """force-graph's default cooldown is 15 seconds; nothing here was overriding it. + + The classic path caps a large graph at 1.1s / 80 ticks precisely because running the layout + — and therefore repainting every node and link — for the full default window is what makes a + big store feel broken on load and after every reheat. + """ + report = _run_engine( + """ + const api = G.create(el, {}); + api.setData(chain(40)); + const small = { + time: store.cooldownTime, ticks: store.cooldownTicks, warmup: store.warmupTicks, + alpha: store.d3AlphaDecay, velocity: store.d3VelocityDecay, + }; + // 3001 entities / 3000 relations — past the classic renderer's 600-node signal. + api.setData(chain(3000)); + const big = { + time: store.cooldownTime, ticks: store.cooldownTicks, warmup: store.warmupTicks, + alpha: store.d3AlphaDecay, velocity: store.d3VelocityDecay, + }; + const still = G.create(el, { reducedMotion: () => true }); + still.setData(chain(40)); + emit({ + small, big, + reduced: { time: store.cooldownTime, ticks: store.cooldownTicks }, + }); + """ + ) + assert report["small"]["time"] == 2200 + assert report["small"]["ticks"] == 160 + # The number this guards: the vendor default left a 3k-relation store simulating for 15s. + assert report["big"]["time"] == 1100 + assert report["big"]["ticks"] == 80 + assert report["big"]["warmup"] == 18 + # A large graph also settles harder, exactly as GPERF.large does on the classic path. + assert report["big"]["alpha"] > report["small"]["alpha"] + assert report["big"]["velocity"] > report["small"]["velocity"] + # Reduced motion asks for a static layout, not a shorter animation. + assert report["reduced"]["time"] == 0 + assert report["reduced"]["ticks"] == 1 + + +@requires_node +def test_curves_arrows_and_relation_labels_are_dropped_on_a_dense_graph() -> None: + """Three per-edge costs the classic path turns off past ``GPERF.dense`` (links > 1500). + + A curved link is a quadratic bezier instead of a straight line, an arrowhead is a filled + triangle, and a relation label is a text layout — each per relation, each every frame. At + this density they are unreadable anyway, so the classic renderer pays for none of them. + """ + report = _run_engine( + LAY_OUT + + """ + const api = G.create(el, { reducedMotion: () => true }); + api.setSettings({ labels: true }); + + api.setData(chain(1500)); + const atLimit = { + curve: store.linkCurvature, arrow: store.linkDirectionalArrowLength, + }; + + api.setData(chain(1501)); + const overLimit = { + curve: store.linkCurvature, arrow: store.linkDirectionalArrowLength, + }; + // One laid-out relation is enough to drive the label painter at this size. + const data = layOut(); + data.links[0].label = 'mentions'; + const denseUnhighlighted = paintLinks(4, [data.links[0]]); + store.onNodeHover(data.nodes[0]); + const denseHighlighted = paintLinks(4, [data.links[0]]); + emit({ atLimit, overLimit, denseUnhighlighted, denseHighlighted }); + """ + ) + # 1500 links is the classic threshold itself, so nothing is dropped yet. + assert report["atLimit"]["curve"] == 0.12 + assert report["atLimit"]["arrow"] == 2.5 + assert report["overLimit"]["curve"] == 0 + assert report["overLimit"]["arrow"] == 0 + # Relation labels come back for the one neighbourhood the user is actually pointing at. + assert report["denseUnhighlighted"] == [] + assert report["denseHighlighted"] == ["mentions"] + + +def _community_palettes(source: str) -> dict: + """Parse a ``COMMUNITY_PALS`` literal out of either renderer.""" + # Anchor on the declaration: both files also name the table in prose comments. + match = re.search(r"COMMUNITY_PALS\s*=\s*\{", source) + assert match is not None, "COMMUNITY_PALS is not declared here" + block = source[match.end():source.index("};", match.end())] + return { + name: re.findall(r"#[0-9a-fA-F]{3,8}", body) + for name, body in re.findall(r"(\w+)\s*:\s*\[([^\]]*)\]", block) + } + + +def test_community_colours_match_the_dashboard_and_the_legend_swatches() -> None: + """The cluster legend is painted from CSS, so palette *order* is a contract, not a taste. + + ``graphRenderLegend`` sorts communities by size and gives the largest a + ``.graph-cluster-0`` swatch, while the canvas colours that same community with palette slot + 0. The swatch colours live in ``dashboard.css`` and encode the Cyber palette — the default + style — so a renderer whose slot 0 is a different colour makes the legend describe cluster 1 + with cluster 2's colour, on the default style, for every workspace. + """ + engine = _community_palettes(ASSET.read_text(encoding="utf-8")) + classic = _community_palettes(DASHBOARD.read_text(encoding="utf-8")) + assert engine, "COMMUNITY_PALS could not be parsed out of the engine" + assert engine == classic, "the opt-in renderer paints communities a different colour" + + swatches = dict( + re.findall(r"\.graph-cluster-(\d+)\{background:(#[0-9a-fA-F]{3,8})\}", + CSS.read_text(encoding="utf-8")) + ) + assert swatches, "the cluster legend swatches are missing from the stylesheet" + for index, colour in sorted(swatches.items()): + assert engine["cyber"][int(index)].lower() == colour.lower(), ( + f"legend swatch {index} does not match the canvas colour for that cluster" + ) + + # ── CSP, styling and lifecycle ────────────────────────────────────────────────────── From 038652b47165e65c355560345d670ac63647c68c Mon Sep 17 00:00:00 2001 From: Jaixii Date: Sun, 26 Jul 2026 18:55:58 -0400 Subject: [PATCH 24/82] fix(graph): reheat the simulation when a physics slider moves MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Under ?graph-engine=next the Repel/Link/Gravity/Size sliders appeared dead. dashboard.js::graphSet routes them through api.setSettings, which only asked render() for a reheat when `mode` was present. applyForces() writes the new charge / link / forceX-forceY / collide values straight into the simulation force-graph is already running, and a settled graph sits at alpha~0 — so the new forces were installed and nothing moved until the user found the Reheat button. `size` is affected too: it feeds d3.forceCollide. The classic branch of that same function does the opposite — it treats `repel|link|gravity|size` as a layout change and reheats unless the user asked for reduced motion. setSettings now matches that set (plus `mode`, which swaps the whole force arrangement); render() already carries the reduced-motion exemption, so it is honoured for free. Appearance-only settings (font, link width, label density, labels, flow) still must not reheat: restarting the layout because a label got bigger throws away the arrangement being read. The regression test drives the API against the force-graph stand-in and counts d3ReheatSimulation() calls per key. Pre-fix it reported {repel: 0, link: 0, gravity: 0, size: 0, mode: 1}. Co-Authored-By: Claude Opus 5 --- engraphis/static/engraphis-graph.js | 19 +++++++-- tests/test_graph_engine_asset.py | 61 +++++++++++++++++++++++++++-- 2 files changed, 74 insertions(+), 6 deletions(-) diff --git a/engraphis/static/engraphis-graph.js b/engraphis/static/engraphis-graph.js index 6499d78..e134625 100644 --- a/engraphis/static/engraphis-graph.js +++ b/engraphis/static/engraphis-graph.js @@ -349,8 +349,9 @@ /* Apply a batch of setters with exactly one render at the end. Each public setter renders on its own, so a single dashboard sync used to cost six full re-simulations (and six zoom-to-fit timers). The caller also states the intent explicitly, because the merged - intent of the individual setters is not the caller's: `setSettings` always asks for a - reheat, which would reheat even on a `render(false, false)` refresh. */ + intent of the individual setters is not the caller's: `setSettings` asks for a reheat + whenever the patch carries a physics key, and the dashboard's sync hands it the whole + GSET — so it would reheat even on a `render(false, false)` refresh. */ function batch(fn, fit, reheat) { suspended++; try { fn(api); } finally { @@ -855,7 +856,19 @@ if (state.bridges || state.sizeBy === 'betweenness') ensureBetweenness(); render(true, true); }; - api.setSettings = patch => { Object.assign(state.settings, patch); render(false, patch.mode !== undefined); }; + /* Which of these settings changes the *layout* rather than just the paint, matching the + classic path's `key==='repel'||key==='link'||key==='gravity'||key==='size'` in + dashboard.js::graphSet — `size` counts because it feeds d3.forceCollide, and `mode` + swaps the whole force arrangement. applyForces() only writes the new charge / link / + forceX-forceY / collide values into the simulation force-graph is already running, and a + settled graph sits at alpha~0, so without the reheat those sliders install a force that + moves nothing. The paint-only settings must keep the arrangement the user is reading. + render() applies the reduced-motion exemption (`if(layout&&!prefersReducedMotion())`). */ + const LAYOUT_KEYS = ['mode', 'repel', 'link', 'gravity', 'size']; + api.setSettings = patch => { + Object.assign(state.settings, patch); + render(false, LAYOUT_KEYS.some(k => patch && patch[k] !== undefined)); + }; api.setPreset = name => { const p = PRESETS[name] || PRESETS.compact; state.settings.mode = PRESETS[name] ? name : 'compact'; diff --git a/tests/test_graph_engine_asset.py b/tests/test_graph_engine_asset.py index 773297d..a18c9e2 100644 --- a/tests/test_graph_engine_asset.py +++ b/tests/test_graph_engine_asset.py @@ -55,16 +55,18 @@ #: accessor is a chainable setter that returns the stored value when called with no arguments — #: force-graph's own kapsule semantics — so the paint configuration the engine installs can be #: read back and invoked instead of pattern-matched. ``calls`` counts the invalidations the -#: engine requests, which is the only observable form a "redraw now" takes. +#: engine requests, which is the only observable form a "redraw now" takes. ``invocations`` +#: counts the *argument-less* calls, which under kapsule semantics are the commands rather than +#: the setters — ``d3ReheatSimulation()`` is one, and it has no other observable effect here. ENGINE_PRELUDE = """ const fs = require('fs'); const source = fs.readFileSync(process.argv[1], 'utf8'); const window = {}; globalThis.requestAnimationFrame = () => {}; -const store = {}, calls = {}; +const store = {}, calls = {}, invocations = {}; const fg = new Proxy({}, { get: (_target, prop) => (...args) => { - if (!args.length) return store[prop]; + if (!args.length) { invocations[prop] = (invocations[prop] || 0) + 1; return store[prop]; } calls[prop] = (calls[prop] || 0) + 1; store[prop] = args.length === 1 ? args[0] : args; return fg; @@ -1154,6 +1156,59 @@ def test_simulation_time_is_bounded_on_a_large_graph() -> None: assert report["reduced"]["ticks"] == 1 +@requires_node +def test_physics_sliders_reheat_the_simulation_the_way_the_classic_renderer_does() -> None: + """Installing a new force on a settled graph moves nothing without a reheat. + + ``graphSet`` (dashboard.js) routes Repel/Link/Gravity/Size/Font/Link-width/Label-density + through ``setSettings`` under ``?graph-engine=next``. The classic branch of that same + function treats ``repel|link|gravity|size`` as *layout* changes: it re-applies the forces + and then reheats unless the user asked for reduced motion. The engine's ``applyForces()`` + only swaps the charge/link/forceX-forceY/collide values into the running simulation — and a + settled graph sits at alpha~0 — so without the reheat those four sliders are inert until + the user finds the Reheat button. The paint-only settings must *not* reheat: restarting + the layout because a label got bigger throws away the arrangement the user is reading. + """ + report = _run_engine( + """ + const reheats = () => invocations.d3ReheatSimulation || 0; + const bump = (api, patch) => { const before = reheats(); api.setSettings(patch); return reheats() - before; }; + + const api = G.create(el, {}); + api.setData(chain(40)); + const layout = { + repel: bump(api, { repel: 260 }), + link: bump(api, { link: 90 }), + gravity: bump(api, { gravity: 12 }), + size: bump(api, { size: 5 }), + mode: bump(api, { mode: 'radial' }), + }; + const paint = { + font: bump(api, { font: 11 }), + linkw: bump(api, { linkw: 2.4 }), + labelDensity: bump(api, { labelDensity: 40 }), + labels: bump(api, { labels: true }), + flow: bump(api, { flow: false }), + }; + + // The classic path's `if(layout&&!prefersReducedMotion())` exemption. + const still = G.create(el, { reducedMotion: () => true }); + still.setData(chain(40)); + const reducedMotion = bump(still, { repel: 260 }); + emit({ layout, paint, reducedMotion }); + """ + ) + # The four sliders the classic renderer calls a layout change, plus the preset itself. + assert report["layout"] == { + "repel": 1, "link": 1, "gravity": 1, "size": 1, "mode": 1 + }, "a physics slider installed new forces on a settled graph and nothing moved" + # Appearance-only settings keep the arrangement the user is looking at. + assert report["paint"] == { + "font": 0, "linkw": 0, "labelDensity": 0, "labels": 0, "flow": 0 + }, "an appearance change restarted the layout" + assert report["reducedMotion"] == 0, "reduced motion still got an animated relayout" + + @requires_node def test_curves_arrows_and_relation_labels_are_dropped_on_a_dense_graph() -> None: """Three per-edge costs the classic path turns off past ``GPERF.dense`` (links > 1500). From 4e80d62d3ad0136bf76209ac0bc03f85d101b90e Mon Sep 17 00:00:00 2001 From: Jaixii Date: Sun, 26 Jul 2026 19:12:52 -0400 Subject: [PATCH 25/82] fix(licensing): settle cached access on entitlement 402 --- engraphis/routes/v2_api.py | 12 ++++++++++++ tests/test_hosted_plan_resolution.py | 26 ++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/engraphis/routes/v2_api.py b/engraphis/routes/v2_api.py index cee65ef..7ffe550 100644 --- a/engraphis/routes/v2_api.py +++ b/engraphis/routes/v2_api.py @@ -2190,6 +2190,18 @@ def _fetch_authoritative_entitlement() -> Optional[dict]: exc.close() except (OSError, ValueError): pass + # The compatibility endpoint is authoritative too. An older control plane can + # refresh a token successfully yet answer 402 here because it does not include + # entitlement fields in the refresh response. Do not leave its previous paid + # cache (or the session that outranks it) advertising access after that answer. + if exc.code == 402: + try: + from engraphis.cloud_session import record_billing_denial + + record_billing_denial() + except Exception: # noqa: BLE001 - a denial we cannot persist is still a denial + pass + _deny_entitlement_cache() return None except Exception: # noqa: BLE001 - transport, TLS, and URL failures are all "not now" return None diff --git a/tests/test_hosted_plan_resolution.py b/tests/test_hosted_plan_resolution.py index a867f36..8f0b6ae 100644 --- a/tests/test_hosted_plan_resolution.py +++ b/tests/test_hosted_plan_resolution.py @@ -986,6 +986,32 @@ def _lapsed(*_args, **_kwargs): assert cached["plan"] == "team", "the lapsed plan is still named for the UI" +def test_a_compatibility_entitlement_402_settles_paid_access(monkeypatch) -> None: + """An old control plane can deny only the fallback entitlement request. + + It refreshes tokens but puts no entitlement fields on those responses, so the GET + compatibility path owns the cached answer. Its 402 is just as authoritative as a + token-refresh 402; treating it as a transport failure leaves stale paid features live. + """ + + _connect(monkeypatch, pinned_token=False) + cloud = _FakeControlPlane(_entitlement_dto("team"), registration={}) + _serve(monkeypatch, cloud) + assert _settled_license(monkeypatch)["cloud_access_active"] is True + assert cloud_session.saved_entitlement() == {} + + cloud.error = urllib.error.HTTPError( + CONTROL_URL, 402, "payment required", {}, io.BytesIO(b"{}") + ) + assert v2_api._fetch_authoritative_entitlement() is None + + cached = v2_api._read_entitlement_cache() + assert cached["cloud_access_active"] is False + assert cached["features"] == [] + assert cached["plan"] == "team" + assert v2_api.get_license()["cloud_access_active"] is False + + def _age_session_clock(seconds: float = 3600.0) -> None: """Push the saved session's entitlement stamp past any refresh interval.""" From a1b9339f1f72e3f121437b03bf33714e8e83f0f5 Mon Sep 17 00:00:00 2001 From: Jaixii Date: Sun, 26 Jul 2026 13:53:16 -0400 Subject: [PATCH 26/82] Add `engraphis connect --token` so a purchased client can actually connect MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `cloud_session.save_bootstrap()` is the only function that writes `~/.engraphis/cloud_session.json`, and it had zero production callers — only tests reached it. Meanwhile `docs/AGENT_CONNECT.md` and `.env.example` told customers to prefer that file. Nothing created it, so a paying customer had no supported way to connect a client and every paid feature was undeliverable. This adds the client half of the device-connect flow that the control plane already serves: - `engraphis/device_connect.py` — token validation, stable client identity, the POST to `/v1/devices/connect`, status-keyed error copy, and the call into `save_bootstrap`. - `scripts/connect.py` — the CLI, following `scripts/init.py` conventions (`main(argv=None) -> int`, argparse, no prompts). - `scripts/entry.py` — an `engraphis` front door that dispatches to the existing `engraphis-` mains, so the portal's `engraphis connect --token ...` is a runnable command. `engraphis-connect` is installed too. Credential handling: the connect token travels in the request body and nowhere else — never printed, logged, or persisted, and never quoted back in an error. Malformed or truncated tokens are rejected before any network call, so a bad paste costs no rate budget and consumes no token. Network access uses the repo's pinned opener with redirects blocked and an explicit timeout; provider bodies are never reflected into messages. A 401 (expired / already used / invalid, which the service deliberately makes indistinguishable) stays distinct from a 402 lapsed subscription, because the fixes differ. Client ids are minted-once random ULIDs in the owner-only state directory rather than a hardware fingerprint: a MAC- or hostname-derived id is a cross-account identifier the customer never agreed to ship, and it changes under exactly the conditions where stability was the point. The command verifies `cloud_session.configured()` after writing, and says so explicitly when only the compute endpoint is missing rather than half-reporting success. Docs updated: `docs/AGENT_CONNECT.md` and `.env.example` now describe `engraphis connect --token` as the real path to the session file. Tests: 43 new, covering the happy path writing a usable session, 401 printing actionable copy and writing nothing, 402 staying distinguishable, the token never appearing in stdout/stderr or any written file, and short/malformed tokens being rejected before the network. Co-Authored-By: Claude Opus 5 --- .env.example | 12 +- CHANGELOG.md | 18 ++ docs/AGENT_CONNECT.md | 51 ++- engraphis/device_connect.py | 525 +++++++++++++++++++++++++++++++ pyproject.toml | 5 + scripts/connect.py | 162 ++++++++++ scripts/entry.py | 89 ++++++ tests/test_device_connect.py | 590 +++++++++++++++++++++++++++++++++++ 8 files changed, 1448 insertions(+), 4 deletions(-) create mode 100644 engraphis/device_connect.py create mode 100644 scripts/connect.py create mode 100644 scripts/entry.py create mode 100644 tests/test_device_connect.py diff --git a/.env.example b/.env.example index 7be5648..e58f1a7 100644 --- a/.env.example +++ b/.env.example @@ -151,7 +151,17 @@ ENGRAPHIS_LLM_API_KEY=sk-your-key-here # ENGRAPHIS_CLOUD_COMPUTE_URL=https://compute.engraphis.com # ENGRAPHIS_CLOUD_ORGANIZATION_ID=org_replace_me -# Prefer the owner-only ~/.engraphis/cloud_session.json created during hosted onboarding. +# Prefer the owner-only ~/.engraphis/cloud_session.json written by `engraphis connect`: +# +# engraphis connect --token engr_ct_... # the command your account portal shows +# printf %s "$TOKEN" | engraphis connect --token - # keep the token out of shell history +# +# That is the supported way to connect a client. It redeems the one-time connect token, saves +# the rotating refresh credential with 0600 permissions, and keeps it rotated afterwards, so +# none of the variables below are needed on an interactive machine. Set +# ENGRAPHIS_CLOUD_COMPUTE_URL (or pass --compute-url) only if your account portal shows a +# compute endpoint different from the default. See docs/AGENT_CONNECT.md. +# # For non-interactive deployments a refresh credential may be injected as a bootstrap secret. # It rotates on use; the owner-only saved replacement takes precedence afterward, even while # the environment variable remains set. Never commit it. Bind environment-only bootstrap diff --git a/CHANGELOG.md b/CHANGELOG.md index 3902eb7..dd71d1f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,24 @@ All notable changes to Engraphis are documented here. Format loosely follows the capability is not implemented and name the working alternative, instead of implying it is available in Engraphis Cloud. +### Added + +- **`engraphis connect --token engr_ct_…`** — the missing client half of device connect. + `cloud_session.save_bootstrap()` is the only writer of `~/.engraphis/cloud_session.json`, + and it had no production caller: the docs told paying customers to prefer a file nothing + created, so a purchased installation could not be connected without hand-writing state. + The new command redeems the one-time connect token from the account portal against + `POST /v1/devices/connect`, saves the returned session with owner-only permissions, and + verifies `cloud_session.configured()` before reporting success. The token is sent in the + request body and nowhere else — never printed, logged, or written to disk — and every + refusal maps to fixed, actionable copy (an expired or already-used token is not confused + with a lapsed subscription). Also installed as `engraphis-connect`. +- An `engraphis` front-door command that dispatches to the existing `engraphis-` + entry points, so the command the account portal displays is runnable as shown. +- A stable per-installation identity at `~/.engraphis/client_identity.json` (random ULIDs, + not a hardware fingerprint) so reconnecting a machine updates its existing installation + instead of registering a new device every time. + ### Changed - Managed compute consent now travels with the cloud account: an installation connected to diff --git a/docs/AGENT_CONNECT.md b/docs/AGENT_CONNECT.md index 67e2b37..1e4d969 100644 --- a/docs/AGENT_CONNECT.md +++ b/docs/AGENT_CONNECT.md @@ -25,8 +25,9 @@ organization: 1. The organization owner starts Team or purchases a subscription in Engraphis Cloud. 2. The owner invites named members and assigns roles in the hosted dashboard. -3. A member accepts the invitation and creates a scoped agent/device credential. -4. The member configures their agent with the hosted URL and the one-time credential. +3. A member accepts the invitation and generates a one-time **connect token** (`engr_ct_…`). + The account portal shows the exact command to run. +4. The member runs that command on the machine being connected (see below). 5. The hosted service rechecks organization membership, role, scopes, entitlement version, and workspace binding on every request. @@ -37,6 +38,47 @@ The hosted onboarding flow provides the exact endpoint and client snippet for th organization. Do not substitute the URL of a public self-hosted image: that image intentionally has no Team identity backend. +## Connect a machine: `engraphis connect` + +Copy the command from your account portal and run it on the machine you are connecting: + +```bash +engraphis connect --token engr_ct_... +``` + +That redeems the token against `POST /v1/devices/connect` on the control plane and writes the +owner-only session file `~/.engraphis/cloud_session.json` (mode `0600`). The dashboard, the MCP +server, and Cloud Sync all read that file, so no environment secret is needed afterwards. Rerun +`engraphis connect` with a fresh token on every machine you want connected. + +Useful options: + +| Option | Effect | +| --- | --- | +| `--token -` | Read the token from stdin, so it never enters shell history. | +| `--workspace WS_ID` | Bind this device to a single workspace. | +| `--label TEXT` | Name this installation in your account portal. | +| `--device-name TEXT` | Override the device name (defaults to the hostname). | +| `--control-url URL` | Point at a non-default control plane. | +| `--compute-url URL` | Set the managed compute endpoint (also `ENGRAPHIS_CLOUD_COMPUTE_URL`). | +| `--json` | Print a redacted, machine-readable summary. | + +The same command is installed as `engraphis-connect`, matching the other `engraphis-*` scripts. + +Connect tokens are **single-use and short-lived**. The service answers every refusal — expired, +already redeemed, or never valid — with the same `401`, so the client reports all three +possibilities and the fix is always the same: generate a new token in the account portal. A `402` +means the subscription itself has lapsed; fix billing rather than the token. + +The token is a credential. It is sent in the request body and nowhere else — it is never +printed, never logged, and never written to disk. What *is* written is the rotating refresh +credential the service returns, which is why the session file is owner-only. + +The command also mints a stable per-installation identity at `~/.engraphis/client_identity.json` +(random ULIDs, not a hardware fingerprint) so reconnecting the same machine updates the existing +installation instead of registering a new device every time. Both files honour +`ENGRAPHIS_STATE_DIR`; a distinct state directory is a distinct installation. + ## Credential lifecycle Hosted access uses short-lived access tokens plus rotating refresh credentials. A refresh family @@ -45,7 +87,10 @@ service; the raw replacement is returned once and must be kept in an owner-only or secrets manager. Customer-side environment variables are documented in [`.env.example`](../.env.example). Prefer -the onboarding-created `~/.engraphis/cloud_session.json` over long-lived environment secrets. +the `~/.engraphis/cloud_session.json` that `engraphis connect --token` writes over long-lived +environment secrets: it holds a rotating credential, it is owner-only, and it is the path the +client keeps up to date on its own. Environment secrets are for non-interactive deployments that +cannot run the connect command. ## Trial and grace diff --git a/engraphis/device_connect.py b/engraphis/device_connect.py new file mode 100644 index 0000000..90a33c3 --- /dev/null +++ b/engraphis/device_connect.py @@ -0,0 +1,525 @@ +"""Client half of the Engraphis Cloud device-connect flow. + +The account portal issues a one-time connect token (``engr_ct_...``) and shows the +customer a single command. This module exchanges that token for the durable session +material :func:`engraphis.cloud_session.save_bootstrap` persists, so +``~/.engraphis/cloud_session.json`` -- the file :doc:`AGENT_CONNECT` and ``.env.example`` +tell paying customers to prefer -- is finally created by something. Before this existed +``save_bootstrap`` had no production caller at all and a paid installation could not be +connected without hand-writing the state file. + +Design constraints, all of which have teeth: + +* **The connect token is a bearer credential.** It travels in the request body and + nowhere else: never in a log line, never in an exception message, never in the saved + session, never echoed back to the terminal. Callers get a redacted summary. +* **The vetted transport only.** Requests go through + :func:`engraphis.hosted_client.build_pinned_https_opener` with redirects blocked and an + explicit timeout, exactly as :mod:`engraphis.cloud_session` and + :mod:`engraphis.update_check` do. A bare ``urllib.request.build_opener`` would drop the + DNS-rebinding guard on a credential-bearing call. +* **Fixed copy keyed on status.** Provider bodies are untrusted -- they may carry + internal URLs -- so nothing from the response is reflected into an error message. The + control plane deliberately makes expired / consumed / invalid tokens indistinguishable + (all ``401``), so the client says all three at once rather than guessing. +""" +from __future__ import annotations + +import json +import os +import platform +import re +import socket +import urllib.error +import urllib.request +from pathlib import Path +from typing import Optional, Tuple + +from engraphis import cloud_session +from engraphis.hosted_client import ( + CloudUrlUnresolved, + build_pinned_https_opener, + upgrade_url, + validate_cloud_base_url, +) +from engraphis.private_state import ( + UnsafeStateFile, + atomic_private_text, + publish_private_text_if_absent, + read_private_text, +) + +try: # installed distribution -> real version; source tree -> harmless fallback + from engraphis import __version__ as CURRENT_VERSION +except Exception: # pragma: no cover - engraphis is always importable in practice + CURRENT_VERSION = "0" + +#: Path segment of the unauthenticated connect endpoint on the control plane. +CONNECT_PATH = "/v1/devices/connect" + +#: One interactive request. Longer than the 10s refresh budget because this runs at a +#: human's prompt, once, and a spurious timeout costs the customer a fresh token. +DEFAULT_TIMEOUT_SECONDS = 15.0 + +#: The control plane answers with a small fixed record; anything larger is not ours. +_MAX_RESPONSE_BYTES = 64 * 1024 + +#: The portal always mints tokens with this prefix. Checking it locally turns a +#: mistyped or truncated paste into an instant, free error instead of a round trip that +#: consumes rate budget and returns the same opaque 401 as a genuinely dead token. +CONNECT_TOKEN_PREFIX = "engr_ct_" +#: Shortest credible token: the prefix plus enough entropy to be a real secret. +_MIN_TOKEN_CHARS = len(CONNECT_TOKEN_PREFIX) + 16 +_MAX_TOKEN_CHARS = 512 +#: ``secrets.token_urlsafe`` alphabet. Anything else is a paste accident (a shell- +#: mangled quote, a wrapped line, a whole command copied in). +_TOKEN_BODY = re.compile(r"\A[A-Za-z0-9_-]+\Z") + +#: Identity file for this installation. Kept beside ``cloud_session.json`` in the same +#: owner-only state directory and honouring the same ``ENGRAPHIS_STATE_DIR`` override. +_IDENTITY_FILENAME = "client_identity.json" +_IDENTITY_SCHEMA = "engraphis-client-identity/v1" + +#: Compute endpoint for the production deployment. ``DeviceRegistrationResponse`` does +#: not carry one, and ``cloud_session.configured()`` requires it, so a connect against the +#: shipped control plane would otherwise leave a customer "connected" but not configured. +#: Applied *only* when the control plane is the shipped one: a self-hosted or staging +#: control URL gets no guess, and the caller is told to supply the compute URL. +DEFAULT_COMPUTE_URL = "https://compute.engraphis.com" + + +class DeviceConnectError(RuntimeError): + """A connect attempt failed with public, actionable copy. + + ``status`` mirrors the control-plane status where there was one, and uses ``400`` for + a request this client refused to send at all. + """ + + def __init__(self, message: str, *, status: int = 503) -> None: + super().__init__(message) + self.status = status + + +class _NoRedirect(urllib.request.HTTPRedirectHandler): + """Refuse redirects: a 3xx would replay the connect token at an unvetted host.""" + + def redirect_request(self, req, fp, code, msg, headers, newurl): + return None + + +def normalize_connect_token(value: object) -> str: + """Return the trimmed token, or raise before any network call happens. + + Never quotes the offending value. A rejected token is still a credential -- an + error message containing it would land in shell history, CI logs and bug reports. + """ + + token = str(value or "").strip() + if not token: + raise DeviceConnectError( + "No connect token was supplied. Copy the `engraphis connect --token ...` " + "command shown in your Engraphis account portal.", + status=400, + ) + if ( + not token.startswith(CONNECT_TOKEN_PREFIX) + or len(token) < _MIN_TOKEN_CHARS + or len(token) > _MAX_TOKEN_CHARS + or not _TOKEN_BODY.match(token[len(CONNECT_TOKEN_PREFIX):]) + ): + raise DeviceConnectError( + "That does not look like an Engraphis connect token (they start with " + "`%s`). Copy the whole command from your account portal -- a token split " + "across lines or missing its last characters will not work." + % CONNECT_TOKEN_PREFIX, + status=400, + ) + return token + + +def _state_dir() -> Path: + root = os.environ.get("ENGRAPHIS_STATE_DIR", "").strip() + return Path(root).expanduser() if root else Path.home() / ".engraphis" + + +def _identity_path() -> Path: + return _state_dir() / _IDENTITY_FILENAME + + +def _new_client_id(prefix: str) -> str: + # The package's own ULID minter, so these ids sort chronologically and read the same + # way as every other prefixed id in the client. + from engraphis.core import ids + + return "%s_%s" % (prefix, ids.ulid()) + + +def _read_identity() -> dict: + try: + raw = read_private_text(_identity_path(), max_bytes=8 * 1024, allow_missing=True) + except UnsafeStateFile as exc: + raise DeviceConnectError( + "The saved client identity has unsafe filesystem permissions. Remove %s and " + "connect again." % _identity_path(), + status=409, + ) from exc + except (OSError, RuntimeError): + return {} + if not raw: + return {} + try: + value = json.loads(raw) + except (ValueError, RecursionError): + return {} + return value if isinstance(value, dict) else {} + + +def client_identity() -> Tuple[str, str]: + """Return ``(installation_client_id, device_client_id)`` for this machine. + + Minted once and persisted at ``/client_identity.json`` with owner-only + permissions, so reconnecting the same machine re-presents the same pair and the + control plane recognises the installation instead of accumulating a new phantom + device on every connect. + + They are random ULIDs rather than a hardware fingerprint on purpose: a MAC- or + hostname-derived id is a stable cross-account identifier the customer never agreed to + ship, and it changes under exactly the conditions (a new NIC, a rename) where + stability was the point. "Stable per installation" is what the server needs, and a + minted-once file in the state directory is precisely that. A second state directory + (``ENGRAPHIS_STATE_DIR``, a container, another user account) is a second installation, + which is the correct reading. + """ + + saved = _read_identity() + installation = str(saved.get("installation_client_id") or "").strip() + device = str(saved.get("device_client_id") or "").strip() + if installation and device: + return installation, device + + minted = { + "schema": _IDENTITY_SCHEMA, + "installation_client_id": installation or _new_client_id("inst"), + "device_client_id": device or _new_client_id("dev"), + } + payload = json.dumps(minted, sort_keys=True, separators=(",", ":")) + path = _identity_path() + try: + if not publish_private_text_if_absent(path, payload): + # Another process won the create, or a half-written file already existed. + # Re-read: the winner's ids are the ones the control plane will see. + existing = _read_identity() + installation = str(existing.get("installation_client_id") or "").strip() + device = str(existing.get("device_client_id") or "").strip() + if installation and device: + return installation, device + atomic_private_text(path, payload) + except UnsafeStateFile as exc: + raise DeviceConnectError( + "The client identity file at %s could not be written safely." % path, + status=409, + ) from exc + except OSError as exc: + raise DeviceConnectError( + "Could not write the client identity file at %s." % path, status=409 + ) from exc + return minted["installation_client_id"], minted["device_client_id"] + + +def default_control_url() -> str: + """Resolve the control plane: explicit env override, else the shipped manifest.""" + + configured = os.environ.get("ENGRAPHIS_CLOUD_CONTROL_URL", "").strip() + if configured: + return configured + try: + from engraphis.commercial import manifest + + return str(manifest().get("control_plane") or "").strip() + except Exception: # pragma: no cover - manifest ships with the package + return "" + + +def default_compute_url(control_url: str) -> str: + """Resolve the compute plane, guessing only for the shipped control plane.""" + + configured = os.environ.get("ENGRAPHIS_CLOUD_COMPUTE_URL", "").strip() + if configured: + return configured + shipped = "" + try: + from engraphis.commercial import manifest + + shipped = str(manifest().get("control_plane") or "").strip() + except Exception: # pragma: no cover - manifest ships with the package + return "" + if shipped and control_url.rstrip("/") == shipped.rstrip("/"): + return DEFAULT_COMPUTE_URL + return "" + + +def _validated_control_url(value: str) -> str: + if not str(value or "").strip(): + raise DeviceConnectError( + "No Engraphis Cloud control URL is configured. Set " + "ENGRAPHIS_CLOUD_CONTROL_URL or pass --control-url.", + status=400, + ) + try: + return validate_cloud_base_url(value) + except CloudUrlUnresolved as exc: + # "Offline" is not "misconfigured": validate_cloud_base_url resolves the host, so + # a customer on a plane would otherwise be told their URL is invalid forever. + raise DeviceConnectError( + "Engraphis Cloud is temporarily unreachable. Check your network and try " + "again.", + status=503, + ) from exc + except ValueError as exc: + raise DeviceConnectError( + "The Engraphis Cloud control URL is not a valid HTTPS endpoint.", status=400 + ) from exc + + +def _default_device_name() -> str: + try: + name = socket.gethostname().strip() + except OSError: + name = "" + return name[:100] + + +def _default_platform() -> str: + try: + return ("%s %s" % (platform.system(), platform.machine())).strip()[:100] + except Exception: # pragma: no cover - platform is stdlib and total + return "" + + +def _connect_http_error(status: int) -> DeviceConnectError: + """Map a control-plane status to fixed, actionable copy. + + Only the status is used. ``401`` deliberately covers expired, already-consumed and + never-valid tokens with one indistinguishable answer, so the copy names all three + instead of asserting one -- the fix is the same in every case. + """ + + if status == 401: + return DeviceConnectError( + "That connect token has expired, was already used, or is not valid. " + "Generate a new one in your Engraphis account portal and run " + "`engraphis connect --token ...` again.", + status=401, + ) + if status == 402: + return DeviceConnectError( + "This Engraphis Cloud subscription is not active, so no new device can be " + "connected. Update billing at %s and try again." % upgrade_url(), + status=402, + ) + if status == 403: + return DeviceConnectError( + "Engraphis Cloud refused this connect request. Check with the organization " + "owner that your account may still add devices.", + status=403, + ) + if status == 404: + return DeviceConnectError( + "This Engraphis Cloud control plane has no device-connect endpoint. Check " + "ENGRAPHIS_CLOUD_CONTROL_URL points at the URL shown in your account portal.", + status=404, + ) + if status == 422: + return DeviceConnectError( + "Engraphis Cloud rejected this connect request as malformed. Upgrade the " + "client (`pip install -U engraphis`) and try again.", + status=422, + ) + if status == 429: + return DeviceConnectError( + "Too many connect attempts. Wait a minute and try again.", status=429 + ) + if status == 503: + return DeviceConnectError( + "Engraphis Cloud is not accepting new device activations right now. Try " + "again shortly; your connect token is unaffected.", + status=503, + ) + return DeviceConnectError( + "Engraphis Cloud could not connect this device. Try again shortly.", status=503 + ) + + +def post_connect(control_url: str, token: str, *, installation_client_id: str, + device_client_id: str, installation_label: Optional[str] = None, + device_name: Optional[str] = None, app_platform: Optional[str] = None, + app_version: Optional[str] = None, workspace_id: Optional[str] = None, + timeout: float = DEFAULT_TIMEOUT_SECONDS) -> dict: + """POST the connect token and return the ``DeviceRegistrationResponse`` body. + + *control_url* must already be validated. The endpoint rejects unknown fields with a + ``422``, so optional values are omitted rather than sent empty, and there is + deliberately no ``organization_id``: the token carries the organization. + """ + + body = { + "connect_token": token, + "installation_client_id": installation_client_id, + "device_client_id": device_client_id, + } + for key, value in ( + ("installation_label", installation_label), + ("device_name", device_name), + ("platform", app_platform), + ("app_version", app_version), + ("workspace_id", workspace_id), + ): + cleaned = str(value or "").strip() + if cleaned: + body[key] = cleaned + + payload = json.dumps(body, sort_keys=True, separators=(",", ":")).encode("utf-8") + request = urllib.request.Request( + control_url + CONNECT_PATH, + data=payload, + headers={ + "Accept": "application/json", + "Content-Type": "application/json", + "User-Agent": "Engraphis/%s device-connect" % CURRENT_VERSION, + }, + method="POST", + ) + try: + with build_pinned_https_opener(_NoRedirect()).open( + request, timeout=timeout + ) as response: # nosec B310 - scheme validated by validate_cloud_base_url + raw = response.read(_MAX_RESPONSE_BYTES + 1) + except urllib.error.HTTPError as exc: + status = exc.code + # Draining the error body can itself raise; a sibling ``except`` of this ``try`` + # would not cover it, so an unguarded read escapes as a raw traceback exactly + # when the cloud is flaky. Same shape as cloud_session._post_refresh. + try: + exc.read(_MAX_RESPONSE_BYTES + 1) + except (OSError, ValueError): + pass + finally: + try: + exc.close() + except (OSError, ValueError): + pass + raise _connect_http_error(status) + except (urllib.error.URLError, TimeoutError, OSError) as exc: + # ``exc`` may quote an internal host or a proxy URL; never reflect it. + raise DeviceConnectError( + "Engraphis Cloud is temporarily unreachable. Check your network and try " + "again.", + status=503, + ) from exc + if len(raw) > _MAX_RESPONSE_BYTES: + raise DeviceConnectError( + "Engraphis Cloud returned an oversized connect response.", status=502 + ) + try: + parsed = json.loads(raw.decode("utf-8")) + except (UnicodeDecodeError, ValueError, RecursionError) as exc: + raise DeviceConnectError( + "Engraphis Cloud returned an invalid connect response.", status=502 + ) from exc + if not isinstance(parsed, dict): + raise DeviceConnectError( + "Engraphis Cloud returned an invalid connect response.", status=502 + ) + return parsed + + +#: Fields worth echoing back to the customer. Deliberately excludes +#: ``refresh_credential`` and ``access_token``: the summary is printed. +_SUMMARY_FIELDS = ( + "organization_id", + "installation_id", + "device_id", + "member_id", + "workspace_id", + "token_subject", + "plan", + "cloud_access_active", + "cloud_features", + "entitlement_version", + "expires_in_seconds", +) + + +def summarize(response: dict) -> dict: + """Return the non-secret fields of a registration response, for display.""" + + summary = {} + for key in _SUMMARY_FIELDS: + if key in response: + summary[key] = response[key] + return summary + + +def connect(token: object, *, control_url: Optional[str] = None, + compute_url: Optional[str] = None, workspace_id: Optional[str] = None, + installation_label: Optional[str] = None, device_name: Optional[str] = None, + timeout: float = DEFAULT_TIMEOUT_SECONDS) -> dict: + """Exchange a connect token for a saved cloud session. + + Returns the redacted summary -- it is safe to print. Raises + :class:`DeviceConnectError` for every failure, with copy the customer can act on and + never containing the token. Nothing is written unless the exchange succeeded. + """ + + normalized = normalize_connect_token(token) + resolved_control = _validated_control_url( + control_url if control_url is not None else default_control_url() + ) + resolved_compute = ( + compute_url if compute_url is not None else default_compute_url(resolved_control) + ) + if resolved_compute: + try: + resolved_compute = validate_cloud_base_url(resolved_compute) + except CloudUrlUnresolved as exc: + raise DeviceConnectError( + "The Engraphis Cloud compute endpoint is temporarily unreachable.", + status=503, + ) from exc + except ValueError as exc: + raise DeviceConnectError( + "The Engraphis Cloud compute URL is not a valid HTTPS endpoint.", + status=400, + ) from exc + + installation_client_id, device_client_id = client_identity() + response = post_connect( + resolved_control, + normalized, + installation_client_id=installation_client_id, + device_client_id=device_client_id, + installation_label=installation_label, + device_name=device_name if device_name is not None else _default_device_name(), + app_platform=_default_platform(), + app_version=str(CURRENT_VERSION), + workspace_id=workspace_id, + timeout=timeout, + ) + if not str(response.get("refresh_credential") or "").strip(): + raise DeviceConnectError( + "Engraphis Cloud accepted the token but returned no session credential. " + "Try again, and contact support if it repeats.", + status=502, + ) + try: + cloud_session.save_bootstrap( + response, control_url=resolved_control, compute_url=resolved_compute or None + ) + except cloud_session.CloudSessionError as exc: + raise DeviceConnectError(str(exc), status=getattr(exc, "status", 503)) from exc + + summary = summarize(response) + summary["control_url"] = resolved_control + summary["compute_url"] = resolved_compute + summary["session_path"] = str(_state_dir() / "cloud_session.json") + return summary diff --git a/pyproject.toml b/pyproject.toml index da56949..5af2743 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -164,6 +164,11 @@ Repository = "https://github.com/Coding-Dev-Tools/engraphis" Issues = "https://github.com/Coding-Dev-Tools/engraphis/issues" [project.scripts] +# The front door. The account portal tells customers to run `engraphis connect --token ...`, +# so the bare verb form has to exist; scripts.entry dispatches to the same main() each +# engraphis- script below calls. +engraphis = "scripts.entry:main" +engraphis-connect = "scripts.connect:main" engraphis-server = "scripts.start_server:main" engraphis-cli = "scripts.cli:main" engraphis-mcp = "engraphis.mcp_cli:main" diff --git a/scripts/connect.py b/scripts/connect.py new file mode 100644 index 0000000..afbb630 --- /dev/null +++ b/scripts/connect.py @@ -0,0 +1,162 @@ +"""engraphis connect - redeem the connect token from your account portal. + +Your Engraphis account portal shows a one-time token and the exact command to run: + + engraphis connect --token engr_ct_... + +That exchanges the token with the control plane and writes the owner-only session file +``~/.engraphis/cloud_session.json`` that the dashboard, MCP server, and Cloud Sync all +read. Until this command existed the file had no writer at all, so a paying customer had +no supported way to connect a client. + + engraphis connect --token engr_ct_... # the normal case + engraphis connect --token - # read the token from stdin + engraphis connect --token ... --workspace ws_1 # bind the device to one workspace + engraphis connect --token ... --label "CI runner" + engraphis connect --token ... --json # redacted machine-readable summary + +The token is a credential. It is sent in the request body and nowhere else: it is never +printed, never logged, and never written to disk. Passing it as an argument does put it +in your shell history, so ``--token -`` is available for scripted and shared machines. + +Non-interactive by design (no prompts): safe in scripts, CI, and agent shells. +""" +from __future__ import annotations + +import argparse +import json +import sys +from pathlib import Path + +from engraphis import cloud_session +from engraphis.device_connect import ( + DEFAULT_TIMEOUT_SECONDS, + DeviceConnectError, + connect, +) + + +def _prog(argv_zero: str) -> str: + """Name this command the way the caller actually invoked it.""" + + stem = Path(argv_zero or "").stem + return stem if stem.endswith("connect") and stem != "connect" else "engraphis connect" + + +def _read_token(value: str) -> str: + """Resolve ``--token -`` to one line of stdin, keeping it off the command line.""" + + if value != "-": + return value + if sys.stdin is None or sys.stdin.isatty(): + # A bare `--token -` on a terminal would silently hang waiting for input. + raise DeviceConnectError( + "--token - reads the token from stdin; pipe it in, for example " + "`printf %s \"$ENGRAPHIS_CONNECT_TOKEN\" | engraphis connect --token -`.", + status=400, + ) + return sys.stdin.readline() + + +def _print_summary(summary: dict) -> None: + rows = [ + ("organization", summary.get("organization_id")), + ("installation", summary.get("installation_id")), + ("device", summary.get("device_id")), + ("member", summary.get("member_id")), + ("workspace", summary.get("workspace_id")), + ("subject", summary.get("token_subject")), + ] + plan = str(summary.get("plan") or "").strip() + if plan: + active = summary.get("cloud_access_active") + rows.append(("plan", plan + ("" if active is None else + " (active)" if active else " (inactive)"))) + features = summary.get("cloud_features") + if isinstance(features, (list, tuple)) and features: + rows.append(("features", ", ".join(str(item) for item in features))) + rows.append(("control url", summary.get("control_url"))) + rows.append(("compute url", summary.get("compute_url") or "(not configured)")) + rows.append(("session file", summary.get("session_path"))) + + print("Connected this device to Engraphis Cloud.") + print() + for label, value in rows: + text = str(value or "").strip() + if text: + print(" %-14s %s" % (label, text)) + + +def main(argv=None) -> int: + ap = argparse.ArgumentParser( + prog=_prog(sys.argv[0] if sys.argv else ""), + description=__doc__, + formatter_class=argparse.RawDescriptionHelpFormatter, + ) + ap.add_argument("--token", required=True, metavar="TOKEN", + help="the connect token from your account portal, or - for stdin") + ap.add_argument("--control-url", default=None, metavar="URL", + help="control plane to connect to (default: the shipped endpoint, " + "or ENGRAPHIS_CLOUD_CONTROL_URL)") + ap.add_argument("--compute-url", default=None, metavar="URL", + help="managed compute endpoint (default: ENGRAPHIS_CLOUD_COMPUTE_URL, " + "or the shipped endpoint)") + ap.add_argument("--workspace", default=None, metavar="WORKSPACE_ID", + help="bind this device to a single workspace") + ap.add_argument("--label", default=None, metavar="TEXT", + help="label for this installation in your account portal") + ap.add_argument("--device-name", default=None, metavar="TEXT", + help="device name shown in your account portal (default: hostname)") + ap.add_argument("--timeout", type=float, default=DEFAULT_TIMEOUT_SECONDS, + metavar="SECONDS", help="network timeout (default: %(default)s)") + ap.add_argument("--json", action="store_true", + help="print the redacted summary as JSON instead of a report") + args = ap.parse_args(argv) + + try: + summary = connect( + _read_token(args.token), + control_url=args.control_url, + compute_url=args.compute_url, + workspace_id=args.workspace, + installation_label=args.label, + device_name=args.device_name, + timeout=args.timeout, + ) + except DeviceConnectError as exc: + # ``str(exc)`` is fixed public copy from device_connect; it never carries the + # token, the response body, or an internal hostname. + print("%s: %s" % (ap.prog, exc), file=sys.stderr) + return 1 + + if args.json: + print(json.dumps(summary, sort_keys=True, indent=2)) + else: + _print_summary(summary) + + # Prove the write actually produced a session the rest of the client will use, + # rather than reporting success on a file nothing can load. + try: + usable = cloud_session.configured() + except cloud_session.CloudSessionError as exc: + print("%s: the session was written but is not usable: %s" % (ap.prog, exc), + file=sys.stderr) + return 1 + + if not args.json: + print() + if usable: + print("Next steps:") + print(" engraphis-dashboard # your plan's features are now unlocked") + print(" engraphis-init --check # verify the installation") + else: + print("Note: hosted compute is not configured yet, so managed compute " + "features stay off.") + print(" Set ENGRAPHIS_CLOUD_COMPUTE_URL (or rerun with --compute-url) " + "using the endpoint") + print(" shown in your account portal. Everything else is connected.") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/scripts/entry.py b/scripts/entry.py new file mode 100644 index 0000000..c486055 --- /dev/null +++ b/scripts/entry.py @@ -0,0 +1,89 @@ +"""engraphis - the single front door, so the portal's copy-paste command actually runs. + +Every capability already ships as its own ``engraphis-`` console script; this adds +the spelling customers are *shown*. The account portal hands out + + engraphis connect --token engr_ct_... + +and until there was an ``engraphis`` executable that string was not a runnable command. + +This is a dispatcher, not a second CLI: it rewrites ``sys.argv`` and calls the same +``main()`` the matching ``engraphis-`` script calls, so a verb behaves identically +either way and there is exactly one implementation of each command. The import is lazy +so ``engraphis connect`` never drags in the memory/embedding stack that ``engraphis cli`` +needs. +""" +from __future__ import annotations + +import sys +from importlib import import_module + +#: verb -> "module:function", mirroring ``[project.scripts]`` with the prefix dropped. +COMMANDS = { + "connect": "scripts.connect:main", + "init": "scripts.init:main", + "cli": "scripts.cli:main", + "mcp": "engraphis.mcp_cli:main", + "server": "scripts.start_server:main", + "dashboard": "scripts.start_dashboard:main", + "inspector": "scripts.inspector:main", + "consolidate": "scripts.consolidate:main", + "graph": "scripts.graph_cli:main", + "graph-server": "scripts.graph_server:main", + "update": "scripts.update:main", +} + +_USAGE = """usage: engraphis [options] + +commands: + connect redeem the connect token from your account portal + init write a project .env and print agent setup snippets + cli store and recall memories from the terminal + mcp run the MCP server (Claude Code, Cursor, Cline, Zed) + server run the REST server + dashboard run the product dashboard + inspector inspect the local database + consolidate run consolidation over stored memories + graph query the knowledge graph + graph-server run the graph server + update check for and install a newer Engraphis release + +Run `engraphis --help` for a command's options. +Every command is also installed as `engraphis-`.""" + + +def main(argv=None) -> int: + args = list(sys.argv[1:] if argv is None else argv) + if not args or args[0] in {"-h", "--help", "help"}: + print(_USAGE) + return 0 if args else 2 + if args[0] in {"-V", "--version"}: + from engraphis import __version__ + + print(__version__) + return 0 + + verb = args[0] + target = COMMANDS.get(verb) + if target is None: + print("engraphis: unknown command %r\n" % verb, file=sys.stderr) + print(_USAGE, file=sys.stderr) + return 2 + + module_name, _, attribute = target.partition(":") + command = getattr(import_module(module_name), attribute) + + # Hand the verb its own argv. Some targets take ``main(argv)`` and some read + # ``sys.argv`` directly, so rewriting is the one approach that works for all of + # them -- and it also puts "engraphis connect" in that command's --help/usage. + saved = sys.argv + sys.argv = ["engraphis %s" % verb] + args[1:] + try: + result = command() + finally: + sys.argv = saved + return 0 if result is None else int(result) + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/tests/test_device_connect.py b/tests/test_device_connect.py new file mode 100644 index 0000000..bf775e3 --- /dev/null +++ b/tests/test_device_connect.py @@ -0,0 +1,590 @@ +"""Tests for the client half of the device-connect flow. + +``cloud_session.save_bootstrap`` had no production caller: nothing in the shipped client +ever created ``~/.engraphis/cloud_session.json``, while the docs told customers to prefer +it. These tests pin the command that closes that gap, and in particular that the connect +token -- a bearer credential -- never escapes the request body. +""" +from __future__ import annotations + +import json +import urllib.error +import urllib.request +from io import BytesIO +from pathlib import Path + +import pytest + +from engraphis import cloud_session, device_connect +from scripts import connect as connect_cli + +CONTROL_URL = "https://control.example.test" +COMPUTE_URL = "https://compute.example.test" +TOKEN = "engr_ct_R3plAceMeWithRealEntropy_0123456789" + +#: Every key the server's ``DeviceRegistrationResponse`` carries, fed to the client +#: verbatim the way a real 200 would be. +REGISTRATION = { + "organization_id": "org_alpha", + "installation_id": "instl_alpha", + "device_id": "devc_alpha", + "member_id": "mem_alpha", + "workspace_id": "ws_alpha", + "access_token": "short-lived-access-token", + "token_type": "Bearer", + "expires_in_seconds": 900, + "refresh_credential": "rotating-refresh-credential", + "refresh_expires_at": "2026-08-21T00:00:00Z", + "token_subject": "device", + "entitlement_version": 7, + "plan": "team", + "cloud_access_active": True, + "cloud_features": ["analytics", "automation", "export", "sync", "team"], +} + + +class _Response: + """Minimal stand-in for the ``http.client`` response the opener yields.""" + + def __init__(self, payload: bytes) -> None: + self._payload = payload + + def __enter__(self): + return self + + def __exit__(self, *exc) -> bool: + return False + + def read(self, size: int = -1) -> bytes: + return self._payload + + +class _Opener: + """Fake of the pinned opener, recording exactly what was put on the wire.""" + + def __init__(self, *, body=None, error=None) -> None: + self._body = body + self._error = error + self.calls = [] + + def open(self, request, timeout): + self.calls.append({ + "url": request.full_url, + "method": request.get_method(), + "headers": dict(request.headers), + "body": request.data, + "timeout": timeout, + }) + if self._error is not None: + raise self._error + return _Response(json.dumps(self._body).encode("utf-8")) + + +def _install_opener(monkeypatch, opener) -> None: + # ``build_pinned_https_opener`` is a thin wrapper over ``build_opener``; patching the + # stdlib factory keeps the module's own call site (and its redirect handler) intact. + monkeypatch.setattr(urllib.request, "build_opener", lambda *handlers: opener) + + +def _http_error(status: int, body: bytes = b'{"detail":"private"}'): + return urllib.error.HTTPError( + CONTROL_URL + device_connect.CONNECT_PATH, status, "denied", {}, BytesIO(body) + ) + + +@pytest.fixture(autouse=True) +def _isolated_client_state(monkeypatch, tmp_path): + """A private state directory and a control plane that never needs DNS.""" + + monkeypatch.setenv("ENGRAPHIS_STATE_DIR", str(tmp_path)) + for name in ( + "ENGRAPHIS_CLOUD_CONTROL_URL", + "ENGRAPHIS_CLOUD_COMPUTE_URL", + "ENGRAPHIS_CLOUD_ACCESS_TOKEN", + "ENGRAPHIS_CLOUD_ORGANIZATION_ID", + "ENGRAPHIS_CLOUD_REFRESH_CREDENTIAL", + "ENGRAPHIS_CLOUD_TOKEN_SUBJECT", + ): + monkeypatch.delenv(name, raising=False) + # ``validate_cloud_base_url`` resolves the hostname, so the offline gate cannot use + # the real one against ``.test`` names. Normalization is what callers depend on. + normalize = lambda value: str(value).rstrip("/") # noqa: E731 + monkeypatch.setattr(device_connect, "validate_cloud_base_url", normalize) + monkeypatch.setattr(cloud_session, "validate_cloud_base_url", normalize) + return tmp_path + + +def _state_files(root: Path): + return [path for path in Path(root).rglob("*") if path.is_file()] + + +# --------------------------------------------------------------------------- happy path + + +def test_connect_writes_a_session_the_rest_of_the_client_can_use(monkeypatch, tmp_path): + """The whole point: after connect, ``cloud_session.configured()`` is true. + + Before this command shipped, the only writer of the session file was a function with + zero production callers, so this assertion could not hold for any customer. + """ + + opener = _Opener(body=REGISTRATION) + _install_opener(monkeypatch, opener) + + summary = device_connect.connect( + TOKEN, control_url=CONTROL_URL, compute_url=COMPUTE_URL + ) + + assert cloud_session.configured() is True + saved = json.loads((tmp_path / "cloud_session.json").read_text(encoding="utf-8")) + assert saved["schema"] == "engraphis-cloud-session/v1" + assert saved["organization_id"] == "org_alpha" + assert saved["installation_id"] == "instl_alpha" + assert saved["device_id"] == "devc_alpha" + assert saved["member_id"] == "mem_alpha" + assert saved["refresh_credential"] == "rotating-refresh-credential" + assert saved["token_subject"] == "device" + assert saved["control_url"] == CONTROL_URL + assert saved["compute_url"] == COMPUTE_URL + # The entitlement travelled with the registration, so the dashboard knows the plan on + # its very first boot instead of showing a paying Team customer the free core. + assert saved["plan"] == "team" + assert saved["cloud_access_active"] is True + assert "team" in saved["cloud_features"] + assert summary["organization_id"] == "org_alpha" + + +def test_connect_posts_exactly_the_documented_request(monkeypatch): + """The endpoint 422s on unknown fields, and takes no ``organization_id`` at all.""" + + opener = _Opener(body=REGISTRATION) + _install_opener(monkeypatch, opener) + + device_connect.connect( + TOKEN, + control_url=CONTROL_URL, + compute_url=COMPUTE_URL, + workspace_id="ws_alpha", + installation_label="CI runner", + device_name="build-box", + ) + + call = opener.calls[0] + assert call["url"] == CONTROL_URL + "/v1/devices/connect" + assert call["method"] == "POST" + assert call["timeout"] == device_connect.DEFAULT_TIMEOUT_SECONDS + body = json.loads(call["body"].decode("utf-8")) + assert body["connect_token"] == TOKEN + assert body["installation_client_id"].startswith("inst_") + assert body["device_client_id"].startswith("dev_") + assert body["workspace_id"] == "ws_alpha" + assert body["installation_label"] == "CI runner" + assert body["device_name"] == "build-box" + # The token carries the organization; sending one would be rejected. + assert "organization_id" not in body + assert set(body) <= { + "connect_token", "installation_client_id", "device_client_id", + "installation_label", "device_name", "platform", "app_version", "workspace_id", + } + + +def test_optional_fields_are_omitted_rather_than_sent_empty(monkeypatch): + opener = _Opener(body=REGISTRATION) + _install_opener(monkeypatch, opener) + + device_connect.connect( + TOKEN, control_url=CONTROL_URL, compute_url=COMPUTE_URL, device_name="" + ) + + body = json.loads(opener.calls[0]["body"].decode("utf-8")) + assert "workspace_id" not in body + assert "installation_label" not in body + assert "device_name" not in body + + +def test_client_ids_are_stable_across_connects(monkeypatch): + """A reconnect must re-present the same installation, not mint a phantom device.""" + + opener = _Opener(body=REGISTRATION) + _install_opener(monkeypatch, opener) + + first = device_connect.client_identity() + device_connect.connect(TOKEN, control_url=CONTROL_URL, compute_url=COMPUTE_URL) + device_connect.connect(TOKEN, control_url=CONTROL_URL, compute_url=COMPUTE_URL) + + bodies = [json.loads(call["body"].decode("utf-8")) for call in opener.calls] + assert {body["installation_client_id"] for body in bodies} == {first[0]} + assert {body["device_client_id"] for body in bodies} == {first[1]} + assert device_connect.client_identity() == first + + +# ------------------------------------------------------------------------ failure modes + + +def test_expired_or_consumed_token_is_actionable_and_writes_nothing( + monkeypatch, tmp_path, capsys +): + """401 is the control plane's single answer for expired / consumed / invalid. + + The copy therefore has to name all three and point at the one fix, and a refused + connect must not leave a half-written session behind for the dashboard to load. + """ + + _install_opener(monkeypatch, _Opener(error=_http_error(401))) + + exit_code = connect_cli.main([ + "--token", TOKEN, "--control-url", CONTROL_URL, "--compute-url", COMPUTE_URL, + ]) + + assert exit_code == 1 + captured = capsys.readouterr() + assert "expired" in captured.err + assert "already used" in captured.err + assert "account portal" in captured.err + assert not (tmp_path / "cloud_session.json").exists() + assert cloud_session.configured() is False + + +def test_lapsed_subscription_is_distinguishable_from_a_dead_token(monkeypatch, capsys): + """402 must not be flattened into "your token is bad" -- the fix is billing.""" + + _install_opener(monkeypatch, _Opener(error=_http_error(402))) + + exit_code = connect_cli.main([ + "--token", TOKEN, "--control-url", CONTROL_URL, "--compute-url", COMPUTE_URL, + ]) + + assert exit_code == 1 + message = capsys.readouterr().err + assert "subscription is not active" in message + assert "billing" in message + assert "expired" not in message + + with pytest.raises(device_connect.DeviceConnectError) as caught: + device_connect.connect(TOKEN, control_url=CONTROL_URL, compute_url=COMPUTE_URL) + assert caught.value.status == 402 + + +@pytest.mark.parametrize( + "status,fragment", + [ + (403, "organization owner"), + (422, "pip install -U engraphis"), + (429, "Too many connect attempts"), + (503, "not accepting new device activations"), + (500, "could not connect this device"), + ], +) +def test_each_failure_status_gets_its_own_copy(monkeypatch, status, fragment): + _install_opener(monkeypatch, _Opener(error=_http_error(status))) + + with pytest.raises(device_connect.DeviceConnectError) as caught: + device_connect.connect(TOKEN, control_url=CONTROL_URL, compute_url=COMPUTE_URL) + + assert fragment in str(caught.value) + assert caught.value.status == (status if status != 500 else 503) + + +def test_error_body_is_never_reflected_into_the_message(monkeypatch): + """Provider bodies are untrusted and may quote internal hosts.""" + + error = _http_error(503, b'{"detail":"upstream 10.0.0.7 activation freeze"}') + _install_opener(monkeypatch, _Opener(error=error)) + + with pytest.raises(device_connect.DeviceConnectError) as caught: + device_connect.connect(TOKEN, control_url=CONTROL_URL, compute_url=COMPUTE_URL) + + assert "10.0.0.7" not in str(caught.value) + + +def test_http_error_body_is_drained_and_closed(monkeypatch): + error = _http_error(429) + closed = [] + original_close = error.close + error.close = lambda: (closed.append(True), original_close()) + _install_opener(monkeypatch, _Opener(error=error)) + + with pytest.raises(device_connect.DeviceConnectError): + device_connect.connect(TOKEN, control_url=CONTROL_URL, compute_url=COMPUTE_URL) + + assert closed == [True] + + +def test_network_failure_reports_an_outage_without_leaking_the_detail(monkeypatch): + _install_opener( + monkeypatch, _Opener(error=urllib.error.URLError("proxy.internal refused")) + ) + + with pytest.raises(device_connect.DeviceConnectError) as caught: + device_connect.connect(TOKEN, control_url=CONTROL_URL, compute_url=COMPUTE_URL) + + assert caught.value.status == 503 + assert "proxy.internal" not in str(caught.value) + + +def test_a_success_without_a_refresh_credential_writes_nothing(monkeypatch, tmp_path): + body = dict(REGISTRATION) + body.pop("refresh_credential") + _install_opener(monkeypatch, _Opener(body=body)) + + with pytest.raises(device_connect.DeviceConnectError): + device_connect.connect(TOKEN, control_url=CONTROL_URL, compute_url=COMPUTE_URL) + + assert not (tmp_path / "cloud_session.json").exists() + + +@pytest.mark.parametrize("payload", [b"not json", b'"a string"', b"[]"]) +def test_a_non_object_response_is_rejected(monkeypatch, payload): + class _Raw(_Opener): + def open(self, request, timeout): + return _Response(payload) + + _install_opener(monkeypatch, _Raw()) + + with pytest.raises(device_connect.DeviceConnectError, match="invalid connect"): + device_connect.connect(TOKEN, control_url=CONTROL_URL, compute_url=COMPUTE_URL) + + +# ------------------------------------------------------------- pre-flight token hygiene + + +@pytest.mark.parametrize("token", [ + "", + " ", + "engr_ct_", + "engr_ct_short", + "ct_missing_prefix_but_long_enough_to_pass", + "engr_ct_has spaces in the middle", + "engr_ct_" + "x" * 600, + "engraphis connect --token engr_ct_pasted_whole_command", +]) +def test_malformed_tokens_are_rejected_before_any_network_call(monkeypatch, token): + """A bad paste must cost nothing: no request, no rate budget, no consumed token.""" + + class _Poison: + def open(self, request, timeout): + raise AssertionError("a malformed token must not reach the network") + + _install_opener(monkeypatch, _Poison()) + + with pytest.raises(device_connect.DeviceConnectError) as caught: + device_connect.connect(token, control_url=CONTROL_URL) + + assert caught.value.status == 400 + + +def test_a_rejected_token_is_not_quoted_back(monkeypatch): + """Even an invalid token is a credential: it must stay out of the error text.""" + + secret = "engr_ct_" + "s" * 4 # too short, but still secret-shaped + with pytest.raises(device_connect.DeviceConnectError) as caught: + device_connect.connect(secret, control_url=CONTROL_URL) + + assert secret not in str(caught.value) + assert "ssss" not in str(caught.value) + + +def test_surrounding_whitespace_from_a_paste_is_tolerated(monkeypatch): + opener = _Opener(body=REGISTRATION) + _install_opener(monkeypatch, opener) + + device_connect.connect( + " %s\n" % TOKEN, control_url=CONTROL_URL, compute_url=COMPUTE_URL + ) + + body = json.loads(opener.calls[0]["body"].decode("utf-8")) + assert body["connect_token"] == TOKEN + + +# ------------------------------------------------------------------ credential leakage + + +def test_the_token_never_reaches_stdout_stderr_or_disk(monkeypatch, tmp_path, capsys): + """The one invariant that has to hold on the success path too. + + A token echoed into a terminal lands in scrollback, CI logs and screenshots; a token + persisted next to the session outlives the single use it was minted for. + """ + + opener = _Opener(body=REGISTRATION) + _install_opener(monkeypatch, opener) + + exit_code = connect_cli.main([ + "--token", TOKEN, "--control-url", CONTROL_URL, "--compute-url", COMPUTE_URL, + ]) + assert exit_code == 0 + + captured = capsys.readouterr() + assert TOKEN not in captured.out + assert TOKEN not in captured.err + written = _state_files(tmp_path) + assert written, "connect must actually write the session" + for path in written: + assert TOKEN.encode("utf-8") not in path.read_bytes(), "token leaked into %s" % path + # It did go where it belongs. + assert TOKEN.encode("utf-8") in opener.calls[0]["body"] + + +def test_the_session_secrets_are_not_printed(monkeypatch, capsys): + _install_opener(monkeypatch, _Opener(body=REGISTRATION)) + + connect_cli.main([ + "--token", TOKEN, "--control-url", CONTROL_URL, "--compute-url", COMPUTE_URL, + ]) + + captured = capsys.readouterr() + assert REGISTRATION["refresh_credential"] not in captured.out + assert REGISTRATION["access_token"] not in captured.out + assert "org_alpha" in captured.out # the useful, non-secret parts are shown + + +def test_the_json_summary_carries_no_secrets(monkeypatch, capsys): + _install_opener(monkeypatch, _Opener(body=REGISTRATION)) + + connect_cli.main([ + "--token", TOKEN, "--control-url", CONTROL_URL, "--compute-url", COMPUTE_URL, + "--json", + ]) + + summary = json.loads(capsys.readouterr().out) + assert "refresh_credential" not in summary + assert "access_token" not in summary + assert summary["plan"] == "team" + assert summary["control_url"] == CONTROL_URL + + +def test_summarize_drops_every_secret_field(): + summary = device_connect.summarize(REGISTRATION) + assert set(summary) & {"refresh_credential", "access_token"} == set() + assert summary["organization_id"] == "org_alpha" + + +# ------------------------------------------------------------------------- CLI surface + + +def test_cli_reports_the_connection_and_the_next_step(monkeypatch, capsys): + _install_opener(monkeypatch, _Opener(body=REGISTRATION)) + + assert connect_cli.main([ + "--token", TOKEN, "--control-url", CONTROL_URL, "--compute-url", COMPUTE_URL, + ]) == 0 + + out = capsys.readouterr().out + assert "Connected this device to Engraphis Cloud." in out + assert "team" in out + assert "cloud_session.json" in out + assert "engraphis-dashboard" in out + + +def test_cli_says_so_when_compute_is_not_configured(monkeypatch, capsys): + """Connecting against a custom control plane must not silently half-configure.""" + + _install_opener(monkeypatch, _Opener(body=REGISTRATION)) + + assert connect_cli.main(["--token", TOKEN, "--control-url", CONTROL_URL]) == 0 + + out = capsys.readouterr().out + assert "hosted compute is not configured" in out + assert "ENGRAPHIS_CLOUD_COMPUTE_URL" in out + assert cloud_session.configured(require_compute=False) is True + + +def test_compute_url_is_taken_from_the_environment(monkeypatch): + monkeypatch.setenv("ENGRAPHIS_CLOUD_COMPUTE_URL", COMPUTE_URL) + _install_opener(monkeypatch, _Opener(body=REGISTRATION)) + + summary = device_connect.connect(TOKEN, control_url=CONTROL_URL) + + assert summary["compute_url"] == COMPUTE_URL + assert cloud_session.configured() is True + + +def test_control_url_defaults_to_the_shipped_manifest(monkeypatch): + from engraphis.commercial import manifest + + assert device_connect.default_control_url() == manifest()["control_plane"] + # And only the shipped control plane gets a guessed compute endpoint. + assert device_connect.default_compute_url(manifest()["control_plane"]) == \ + device_connect.DEFAULT_COMPUTE_URL + assert device_connect.default_compute_url(CONTROL_URL) == "" + + +def test_control_url_env_override_wins(monkeypatch): + monkeypatch.setenv("ENGRAPHIS_CLOUD_CONTROL_URL", CONTROL_URL) + assert device_connect.default_control_url() == CONTROL_URL + + +def test_an_unconfigured_control_plane_is_a_clear_error(monkeypatch): + monkeypatch.setattr(device_connect, "default_control_url", lambda: "") + + with pytest.raises(device_connect.DeviceConnectError) as caught: + device_connect.connect(TOKEN) + + assert "ENGRAPHIS_CLOUD_CONTROL_URL" in str(caught.value) + assert caught.value.status == 400 + + +def test_token_dash_reads_stdin(monkeypatch, capsys): + _install_opener(monkeypatch, _Opener(body=REGISTRATION)) + + class _Stdin: + @staticmethod + def isatty() -> bool: + return False + + @staticmethod + def readline() -> str: + return TOKEN + "\n" + + monkeypatch.setattr(connect_cli.sys, "stdin", _Stdin) + + assert connect_cli.main([ + "--token", "-", "--control-url", CONTROL_URL, "--compute-url", COMPUTE_URL, + ]) == 0 + assert TOKEN not in capsys.readouterr().out + + +def test_token_dash_on_a_terminal_explains_itself_instead_of_hanging(monkeypatch, capsys): + class _Tty: + @staticmethod + def isatty() -> bool: + return True + + monkeypatch.setattr(connect_cli.sys, "stdin", _Tty) + + assert connect_cli.main(["--token", "-", "--control-url", CONTROL_URL]) == 1 + assert "reads the token from stdin" in capsys.readouterr().err + + +def test_connect_is_reachable_as_the_documented_engraphis_verb(monkeypatch, capsys): + """The portal shows `engraphis connect --token ...`; that string has to run.""" + + from scripts import entry + + _install_opener(monkeypatch, _Opener(body=REGISTRATION)) + assert entry.COMMANDS["connect"] == "scripts.connect:main" + + assert entry.main([ + "connect", "--token", TOKEN, "--control-url", CONTROL_URL, + "--compute-url", COMPUTE_URL, + ]) == 0 + assert "Connected this device to Engraphis Cloud." in capsys.readouterr().out + + +def test_the_dispatcher_restores_argv_and_rejects_unknown_verbs(capsys): + from scripts import entry + + saved = list(entry.sys.argv) + assert entry.main(["definitely-not-a-command"]) == 2 + assert entry.sys.argv == saved + assert "unknown command" in capsys.readouterr().err + + +def test_every_dispatched_verb_resolves_to_a_real_callable(): + from importlib import import_module + + from scripts import entry + + for verb, target in entry.COMMANDS.items(): + module_name, _, attribute = target.partition(":") + assert callable(getattr(import_module(module_name), attribute)), verb From a36b8670bb5ac6a852cdd89b006f97b84b7fd4a0 Mon Sep 17 00:00:00 2001 From: Jaixii Date: Sun, 26 Jul 2026 14:12:25 -0400 Subject: [PATCH 27/82] Pre-flight session storage before redeeming the connect token `connect()` spent the single-use connect token on the POST and only then called `save_bootstrap()`. If the state directory had become unwritable, or `cloud_session.json` had been replaced by a symlink, a hard link or a directory, the write failed after the token was already consumed: the customer was left with a spent token and no session, and had to go back to the portal for a new one. Worse, `atomic_private_text` raises `UnsafeStateFile`, which is an `OSError` and not a `CloudSessionError`, so it escaped `connect()`'s handler entirely and surfaced as a raw traceback rather than actionable copy. `cloud_session.preflight_save()` now runs before the exchange. It lives beside `_session_path()`, `_refresh_lock()` and `_save()` because that module owns the paths and the atomic write it predicts; a private copy of those rules in `device_connect` would drift from the save it is meant to model. It reuses the existing primitives -- `private_file_stat` on the session leaf and on its refresh lock, plus the randomized sibling temp file `atomic_private_text` has to create -- and never opens, creates or replaces the session leaf, so an existing session survives a failed pre-flight untouched and a first connect is not left half written. `_refresh_lock()` picks up the extracted `_refresh_lock_path()` so the lock filename is not duplicated. `device_connect._preflight_session_storage()` translates the failure into a `DeviceConnectError` that names the path to fix and states that the token is still redeemable, and `connect()` reuses the returned path for the summary instead of rebuilding it from `_state_dir()`. Tests: 6 new, all asserting `opener.calls == []` -- the POST is never issued. Session leaf and refresh lock replaced by a directory, a genuinely hard-linked session, an uncreatable state directory (`ENGRAPHIS_STATE_DIR` under a regular file), a read-only mount, and a pre-flight that creates nothing and leaves no probe file behind. All six fail against the pre-fix code. Co-Authored-By: Claude Opus 5 --- CHANGELOG.md | 6 +- docs/AGENT_CONNECT.md | 6 ++ engraphis/cloud_session.py | 68 +++++++++++++++- engraphis/device_connect.py | 26 +++++- tests/test_device_connect.py | 149 +++++++++++++++++++++++++++++++++++ 5 files changed, 252 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dd71d1f..3d6d026 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,7 +36,11 @@ All notable changes to Engraphis are documented here. Format loosely follows verifies `cloud_session.configured()` before reporting success. The token is sent in the request body and nowhere else — never printed, logged, or written to disk — and every refusal maps to fixed, actionable copy (an expired or already-used token is not confused - with a lapsed subscription). Also installed as `engraphis-connect`. + with a lapsed subscription). Session storage is pre-flighted before the exchange, so an + unwritable state directory or a `cloud_session.json` replaced by a link fails the command + *without* spending the single-use token — the customer fixes the path and retries with the + same token instead of returning to the portal for a new one. Also installed as + `engraphis-connect`. - An `engraphis` front-door command that dispatches to the existing `engraphis-` entry points, so the command the account portal displays is runnable as shown. - A stable per-installation identity at `~/.engraphis/client_identity.json` (random ULIDs, diff --git a/docs/AGENT_CONNECT.md b/docs/AGENT_CONNECT.md index 1e4d969..4ea833f 100644 --- a/docs/AGENT_CONNECT.md +++ b/docs/AGENT_CONNECT.md @@ -70,6 +70,12 @@ already redeemed, or never valid — with the same `401`, so the client reports possibilities and the fix is always the same: generate a new token in the account portal. A `402` means the subscription itself has lapsed; fix billing rather than the token. +Because the token is single-use, the client checks that it can actually write the session file +*before* redeeming it. If the state directory is not writable, or `cloud_session.json` has been +replaced by a symlink, a hard link, or a directory, the command fails immediately, names the path +to fix, and sends nothing — your token is untouched, so you can correct the path and rerun the +same command rather than issuing a new token. + The token is a credential. It is sent in the request body and nowhere else — it is never printed, never logged, and never written to disk. What *is* written is the rotating refresh credential the service returns, which is why the session file is owner-only. diff --git a/engraphis/cloud_session.py b/engraphis/cloud_session.py index b539afe..cbadc1a 100644 --- a/engraphis/cloud_session.py +++ b/engraphis/cloud_session.py @@ -9,6 +9,7 @@ import json import os import stat +import tempfile import threading import time import urllib.error @@ -80,6 +81,10 @@ def _session_path() -> Path: return base / "cloud_session.json" +def _refresh_lock_path() -> Path: + return _session_path().with_name(".cloud_session.refresh.lock") + + @contextmanager def _refresh_lock(): """Serialize spend-and-rotate of the single-use refresh credential. @@ -89,7 +94,7 @@ def _refresh_lock(): so every process coordinates on one stable filesystem object. """ with _REFRESH_THREAD_LOCK: - lock_path = _session_path().with_name(".cloud_session.refresh.lock") + lock_path = _refresh_lock_path() try: lock_path.parent.mkdir(parents=True, exist_ok=True) expected = private_file_stat(lock_path, allow_missing=True) @@ -212,6 +217,67 @@ def _save(value: dict) -> None: atomic_private_text(path, json.dumps(value, sort_keys=True, separators=(",", ":"))) +def preflight_save() -> Path: + """Verify the session file can be saved, without saving anything. Returns its path. + + :func:`save_bootstrap` runs *after* the control plane has answered, so a state + directory that lost its permissions, or a ``cloud_session.json`` that is a symlink or + a hard link, was only discovered once a single-use connect token had already been + consumed: the customer was left with a spent token, no session, and a trip back to + the portal for a new one. Any caller about to spend a one-shot credential must run + this first, so a storage fault costs nothing. + + The checks are the ones the write path itself applies -- :func:`private_file_stat` on + the session leaf and on its refresh lock, plus the randomized sibling temp file + :func:`atomic_private_text` has to create -- so the preflight cannot drift from what + the real save will accept. It deliberately never opens, creates or replaces the + session leaf: an existing session survives a failed preflight untouched, and a first + connect is not turned into a half-written file. + """ + + path = _session_path() + try: + path.parent.mkdir(parents=True, exist_ok=True) + except OSError as exc: + raise CloudSessionError( + "The Engraphis state directory %s could not be created." % path.parent, + status=409, + ) from exc + for candidate in (path, _refresh_lock_path()): + try: + private_file_stat(candidate, allow_missing=True) + except UnsafeStateFile as exc: + raise CloudSessionError( + "%s is not a plain private file -- a symlink, hard link or directory is " + "in its place. Remove it." % candidate, + status=409, + ) from exc + except OSError as exc: + raise CloudSessionError( + "%s could not be inspected; check its permissions." % candidate, + status=409, + ) from exc + # Probe the directory the way ``atomic_private_text`` will, rather than touching + # ``cloud_session.json``: a read-only mount or a lost ACL fails here, while a valid + # existing session is never created, truncated or replaced. + try: + descriptor, probe = tempfile.mkstemp( + prefix=".%s.preflight." % path.name, dir=str(path.parent) + ) + except OSError as exc: + raise CloudSessionError( + "The Engraphis state directory %s is not writable, so the cloud session " + "cannot be saved there." % path.parent, + status=409, + ) from exc + os.close(descriptor) + try: + os.unlink(probe) + except OSError: # pragma: no cover - the probe was just created in this directory + pass + return path + + #: Plans that carry no paid cloud access, used only to default an absent activity flag. _UNPAID_PLANS = ("free", "local") #: Bounds on the entitlement fields before they are written into the session record. The diff --git a/engraphis/device_connect.py b/engraphis/device_connect.py index 90a33c3..6856ee2 100644 --- a/engraphis/device_connect.py +++ b/engraphis/device_connect.py @@ -460,6 +460,26 @@ def summarize(response: dict) -> dict: return summary +def _preflight_session_storage() -> Path: + """Refuse a connect *before* the token is spent when the session cannot be saved. + + The exchange is the point of no return: the control plane consumes the single-use + connect token as it answers, so any storage fault discovered afterwards costs the + customer a fresh token from the portal. Delegated to :mod:`engraphis.cloud_session` + because that module owns the paths, the lock and the atomic write this is checking -- + a private copy of those rules here would drift from the save it is meant to predict. + """ + + try: + return cloud_session.preflight_save() + except cloud_session.CloudSessionError as exc: + raise DeviceConnectError( + "%s Your connect token has not been used, so you can fix this and run " + "`engraphis connect --token ...` again with the same token." % exc, + status=getattr(exc, "status", 409), + ) from exc + + def connect(token: object, *, control_url: Optional[str] = None, compute_url: Optional[str] = None, workspace_id: Optional[str] = None, installation_label: Optional[str] = None, device_name: Optional[str] = None, @@ -493,6 +513,10 @@ def connect(token: object, *, control_url: Optional[str] = None, ) from exc installation_client_id, device_client_id = client_identity() + # Last check before the point of no return. ``client_identity`` may have written its + # file minutes or months ago, so a writable state directory then is no evidence of one + # now; prove the session can land *before* the POST spends the token, not after. + session_path = _preflight_session_storage() response = post_connect( resolved_control, normalized, @@ -521,5 +545,5 @@ def connect(token: object, *, control_url: Optional[str] = None, summary = summarize(response) summary["control_url"] = resolved_control summary["compute_url"] = resolved_compute - summary["session_path"] = str(_state_dir() / "cloud_session.json") + summary["session_path"] = str(session_path) return summary diff --git a/tests/test_device_connect.py b/tests/test_device_connect.py index bf775e3..16d8a09 100644 --- a/tests/test_device_connect.py +++ b/tests/test_device_connect.py @@ -8,6 +8,7 @@ from __future__ import annotations import json +import os import urllib.error import urllib.request from io import BytesIO @@ -345,6 +346,154 @@ def open(self, request, timeout): device_connect.connect(TOKEN, control_url=CONTROL_URL, compute_url=COMPUTE_URL) +# ------------------------------------------------------ pre-flight on session storage +# +# The POST is the point of no return: the control plane consumes the single-use connect +# token as it answers. ``save_bootstrap`` runs afterwards, so before the pre-flight a +# state directory that had lost its permissions -- or a ``cloud_session.json`` replaced +# by a link -- spent the customer's token and then failed, leaving them with nothing to +# retry with. Every test here asserts the same thing: no request was put on the wire. + + +def _probe_files(root: Path): + """Temporary files the writability probe must never leave behind.""" + + return sorted(path.name for path in Path(root).iterdir() if ".preflight." in path.name) + + +def test_an_unsafe_session_path_fails_before_the_token_is_spent(monkeypatch, tmp_path): + """The reported regression: a session leaf that is not a plain private file. + + A directory stands in for the symlink/hard-link family because it trips exactly the + same ``private_file_stat`` rejection on every platform, including a Windows runner + without the privilege to create a symlink at all. + """ + + opener = _Opener(body=REGISTRATION) + _install_opener(monkeypatch, opener) + # The identity file already exists, which is precisely why its earlier success is no + # evidence that the directory is still writable now. + device_connect.client_identity() + session_path = tmp_path / "cloud_session.json" + session_path.mkdir() + + with pytest.raises(device_connect.DeviceConnectError) as caught: + device_connect.connect(TOKEN, control_url=CONTROL_URL, compute_url=COMPUTE_URL) + + # The one assertion that matters: the token was never presented, so it is still live. + assert opener.calls == [] + assert caught.value.status == 409 + # The customer has to be told which path to fix, by name. + assert str(session_path) in str(caught.value) + assert "has not been used" in str(caught.value) + assert session_path.is_dir() + assert _probe_files(tmp_path) == [] + + +def test_an_unsafe_refresh_lock_also_fails_before_the_token_is_spent(monkeypatch, tmp_path): + """``save_bootstrap`` takes the refresh lock first, so an unusable lock spends it too.""" + + opener = _Opener(body=REGISTRATION) + _install_opener(monkeypatch, opener) + lock_path = tmp_path / ".cloud_session.refresh.lock" + lock_path.mkdir() + + with pytest.raises(device_connect.DeviceConnectError) as caught: + device_connect.connect(TOKEN, control_url=CONTROL_URL, compute_url=COMPUTE_URL) + + assert opener.calls == [] + assert str(lock_path) in str(caught.value) + assert not (tmp_path / "cloud_session.json").exists() + + +def test_a_hard_linked_session_is_refused_before_the_token_is_spent(monkeypatch, tmp_path): + """A second pathname to the session would keep resolving to the rotated credential.""" + + opener = _Opener(body=REGISTRATION) + _install_opener(monkeypatch, opener) + session_path = tmp_path / "cloud_session.json" + session_path.write_text("{}", encoding="utf-8") + try: + os.link(str(session_path), str(tmp_path / "session_alias.json")) + except (OSError, AttributeError, NotImplementedError) as exc: # pragma: no cover + pytest.skip("hard links are unavailable on this filesystem: %s" % exc) + + with pytest.raises(device_connect.DeviceConnectError) as caught: + device_connect.connect(TOKEN, control_url=CONTROL_URL, compute_url=COMPUTE_URL) + + assert opener.calls == [] + assert str(session_path) in str(caught.value) + # Inspection only: a pre-existing file is never opened, truncated or replaced. + assert session_path.read_text(encoding="utf-8") == "{}" + + +def test_an_uncreatable_state_directory_fails_before_the_token_is_spent( + monkeypatch, tmp_path +): + """``ENGRAPHIS_STATE_DIR`` under a regular file: the directory can never be made.""" + + blocker = tmp_path / "blocker" + blocker.write_text("not a directory", encoding="utf-8") + monkeypatch.setenv("ENGRAPHIS_STATE_DIR", str(blocker / "state")) + opener = _Opener(body=REGISTRATION) + _install_opener(monkeypatch, opener) + + with pytest.raises(device_connect.DeviceConnectError) as caught: + device_connect.connect(TOKEN, control_url=CONTROL_URL, compute_url=COMPUTE_URL) + + assert opener.calls == [] + assert str(blocker / "state") in str(caught.value) + assert blocker.read_text(encoding="utf-8") == "not a directory" + + +def test_an_unwritable_state_directory_fails_before_the_token_is_spent( + monkeypatch, tmp_path +): + """A read-only mount, which is the failure the report describes. + + Simulated at the probe rather than with ``chmod``: POSIX modes are advisory for root + and Windows has no equivalent, so a mode-based test would silently stop failing. The + probe is the only thing standing between the caller and ``atomic_private_text``. + """ + + opener = _Opener(body=REGISTRATION) + _install_opener(monkeypatch, opener) + device_connect.client_identity() + + def _read_only(*args, **kwargs): + raise PermissionError(13, "read-only file system") + + monkeypatch.setattr(cloud_session.tempfile, "mkstemp", _read_only) + + with pytest.raises(device_connect.DeviceConnectError) as caught: + device_connect.connect(TOKEN, control_url=CONTROL_URL, compute_url=COMPUTE_URL) + + assert opener.calls == [] + assert caught.value.status == 409 + assert str(tmp_path) in str(caught.value) + assert "not writable" in str(caught.value) + assert not (tmp_path / "cloud_session.json").exists() + + +def test_the_preflight_creates_nothing_and_leaves_nothing_behind(monkeypatch, tmp_path): + """A pre-flight that wrote the session would defeat the "nothing on failure" rule.""" + + session_path = cloud_session.preflight_save() + + assert session_path == tmp_path / "cloud_session.json" + assert not session_path.exists() + assert _probe_files(tmp_path) == [] + + # Idempotent, and equally inert once a real session exists. + _install_opener(monkeypatch, _Opener(body=REGISTRATION)) + device_connect.connect(TOKEN, control_url=CONTROL_URL, compute_url=COMPUTE_URL) + saved = session_path.read_bytes() + + assert cloud_session.preflight_save() == session_path + assert session_path.read_bytes() == saved + assert _probe_files(tmp_path) == [] + + # ------------------------------------------------------------- pre-flight token hygiene From 4734128d543c1f107ac54a02c990b0b66d197d12 Mon Sep 17 00:00:00 2001 From: Jaixii Date: Sun, 26 Jul 2026 17:42:20 -0400 Subject: [PATCH 28/82] Address connect review: manifest compute endpoint, timeout and save races Three unresolved review threads on #75, plus one semantic conflict the merge with main could not see. `default_compute_url` now reads the manifest's `compute_plane` and falls back to `DEFAULT_COMPUTE_URL`. The review asked for the constant to be replaced outright, but the shipped `engraphis-commercial/v2` manifest declares only `control_plane`: reading the absent key alone resolves `""`, and `cloud_session.configured()` then rejects the session a production connect just saved, leaving a paying customer "connected" but unusable. Preferring the key removes the drift point the review named -- a manifest-only endpoint change needs no code change -- while the constant stays as the fallback that keeps today's manifest working. `_validated_timeout` refuses a non-finite or non-positive timeout. `argparse`'s `type=float` accepts `nan` and `inf`, which reach the pinned opener's deadline arithmetic and raise `ValueError`/`OverflowError` from inside `urllib`, neither caught by `post_connect`. That broke this module's contract that every failure is a `DeviceConnectError`, so `engraphis connect --timeout nan` printed a traceback instead of the command's error and exit code. Checked at the top of `connect()` so a bad flag is reported as a bad flag rather than masked by whatever the identity or storage pre-flight hits first, and again in `post_connect()` because it is public and owns the socket call. `connect()` now also translates `OSError` from `save_bootstrap`. The pre-flight added in aae7d93 closes the common case, but the state directory can still change between the pre-flight and the write, and `UnsafeStateFile` is an `OSError`, not a `CloudSessionError`, so it escaped as a traceback at the worst moment. The token is spent by then, so the copy says so instead of promising a retry with the same one. The `REGISTRATION` fixture no longer claims the cloud grants `export`. #76 removed that key from the plan->feature tables in both repos because the signed compliance export was never implemented; a fixture asserting the control plane returns it would re-establish exactly the drift that removal cleaned up. Co-Authored-By: Claude Opus 5 --- engraphis/device_connect.py | 68 ++++++++++++++++++++++++-- tests/test_device_connect.py | 93 +++++++++++++++++++++++++++++++++++- 2 files changed, 157 insertions(+), 4 deletions(-) diff --git a/engraphis/device_connect.py b/engraphis/device_connect.py index 6856ee2..d0698bb 100644 --- a/engraphis/device_connect.py +++ b/engraphis/device_connect.py @@ -26,6 +26,7 @@ from __future__ import annotations import json +import math import os import platform import re @@ -85,6 +86,12 @@ #: shipped control plane would otherwise leave a customer "connected" but not configured. #: Applied *only* when the control plane is the shipped one: a self-hosted or staging #: control URL gets no guess, and the caller is told to supply the compute URL. +#: +#: This is the *fallback*, not the authority: ``default_compute_url`` prefers the +#: manifest's ``compute_plane`` whenever it carries one. The shipped +#: ``engraphis-commercial/v2`` manifest does not declare that key, so without a constant +#: here a production connect would resolve an empty compute URL and save an unconfigured +#: session. DEFAULT_COMPUTE_URL = "https://compute.engraphis.com" @@ -241,23 +248,61 @@ def default_control_url() -> str: def default_compute_url(control_url: str) -> str: - """Resolve the compute plane, guessing only for the shipped control plane.""" + """Resolve the compute plane, guessing only for the shipped control plane. + + The manifest is the authority for shipped endpoint metadata, so a ``compute_plane`` + key wins if one is ever published -- a manifest-only endpoint change then needs no + code change here. The current ``engraphis-commercial/v2`` manifest declares only + ``control_plane``, so :data:`DEFAULT_COMPUTE_URL` is what production actually + resolves; reading the absent key alone would yield ``""`` and save a session + ``cloud_session.configured()`` rejects. + """ configured = os.environ.get("ENGRAPHIS_CLOUD_COMPUTE_URL", "").strip() if configured: return configured shipped = "" + shipped_compute = "" try: from engraphis.commercial import manifest - shipped = str(manifest().get("control_plane") or "").strip() + data = manifest() + shipped = str(data.get("control_plane") or "").strip() + shipped_compute = str(data.get("compute_plane") or "").strip() except Exception: # pragma: no cover - manifest ships with the package return "" if shipped and control_url.rstrip("/") == shipped.rstrip("/"): - return DEFAULT_COMPUTE_URL + return shipped_compute or DEFAULT_COMPUTE_URL return "" +def _validated_timeout(value: object) -> float: + """Reject a timeout the socket layer cannot use, before any request is started. + + ``float("nan")`` and ``float("inf")`` are values ``argparse``'s ``type=float`` + accepts happily, but they reach the pinned opener's deadline arithmetic and raise + ``ValueError``/``OverflowError`` from inside ``urllib`` -- neither of which + :func:`post_connect` catches. That breaks this module's contract that every failure + is a :class:`DeviceConnectError` with actionable copy, so ``--timeout nan`` printed a + traceback instead of an error and an exit code. Non-positive values are refused for + the same reason: a ``0`` or negative socket timeout is not a shorter wait, it is a + different (non-blocking) mode the caller did not ask for. + """ + + try: + timeout = float(value) + except (TypeError, ValueError) as exc: + raise DeviceConnectError( + "The connect timeout must be a number of seconds.", status=400 + ) from exc + if not math.isfinite(timeout) or timeout <= 0: + raise DeviceConnectError( + "The connect timeout must be a positive, finite number of seconds.", + status=400, + ) + return timeout + + def _validated_control_url(value: str) -> str: if not str(value or "").strip(): raise DeviceConnectError( @@ -362,6 +407,7 @@ def post_connect(control_url: str, token: str, *, installation_client_id: str, deliberately no ``organization_id``: the token carries the organization. """ + timeout = _validated_timeout(timeout) body = { "connect_token": token, "installation_client_id": installation_client_id, @@ -491,6 +537,10 @@ def connect(token: object, *, control_url: Optional[str] = None, never containing the token. Nothing is written unless the exchange succeeded. """ + # Argument checks first: a bad ``--timeout`` must be reported as a bad timeout, not + # masked by whatever the identity or storage pre-flight happens to hit on the way to + # the same rejection inside ``post_connect``. + timeout = _validated_timeout(timeout) normalized = normalize_connect_token(token) resolved_control = _validated_control_url( control_url if control_url is not None else default_control_url() @@ -541,6 +591,18 @@ def connect(token: object, *, control_url: Optional[str] = None, ) except cloud_session.CloudSessionError as exc: raise DeviceConnectError(str(exc), status=getattr(exc, "status", 503)) from exc + except OSError as exc: + # The pre-flight cleared this exact path moments ago, so arriving here means the + # state directory changed underneath the exchange. ``UnsafeStateFile`` is an + # ``OSError`` and not a ``CloudSessionError``, so without this clause it escapes + # as a raw traceback at the worst possible moment -- the token is already spent, + # and the customer needs to be told that plainly rather than shown a stack. + raise DeviceConnectError( + "Engraphis Cloud accepted the token, but the session could not be written to " + "%s. Fix that path, then connect again with a new token from your account " + "portal -- this one has been used." % session_path, + status=409, + ) from exc summary = summarize(response) summary["control_url"] = resolved_control diff --git a/tests/test_device_connect.py b/tests/test_device_connect.py index 16d8a09..2367fa5 100644 --- a/tests/test_device_connect.py +++ b/tests/test_device_connect.py @@ -17,6 +17,7 @@ import pytest from engraphis import cloud_session, device_connect +from engraphis.private_state import UnsafeStateFile from scripts import connect as connect_cli CONTROL_URL = "https://control.example.test" @@ -40,7 +41,10 @@ "entitlement_version": 7, "plan": "team", "cloud_access_active": True, - "cloud_features": ["analytics", "automation", "export", "sync", "team"], + # No ``export``: the signed compliance export was never implemented and is no longer + # in either repo's plan->feature table, so a fixture claiming the cloud grants it + # would re-establish exactly the drift that removal cleaned up. + "cloud_features": ["analytics", "automation", "sync", "team"], } @@ -658,6 +662,93 @@ def test_control_url_defaults_to_the_shipped_manifest(monkeypatch): assert device_connect.default_compute_url(CONTROL_URL) == "" +def test_the_manifest_outranks_the_compute_constant(monkeypatch): + """A published ``compute_plane`` wins, so the manifest stays the endpoint authority. + + The constant is only the fallback for today's manifest, which declares no + ``compute_plane``; reading the key alone would resolve ``""`` and save a session + ``configured()`` rejects. + """ + + from engraphis.commercial import manifest + + shipped = manifest()["control_plane"] + monkeypatch.setattr( + "engraphis.commercial.manifest", + lambda: {"control_plane": shipped, "compute_plane": COMPUTE_URL}, + ) + + assert device_connect.default_compute_url(shipped) == COMPUTE_URL + # A self-hosted control plane still gets no guess from either source. + assert device_connect.default_compute_url(CONTROL_URL) == "" + + +@pytest.mark.parametrize("bad", ["nan", "inf", "-inf", "0", "-5"]) +def test_a_non_finite_timeout_is_refused_before_any_request(monkeypatch, bad): + """``argparse``'s ``type=float`` accepts ``nan``/``inf``; the socket layer does not. + + Those reach ``urllib``'s deadline arithmetic and raise ``ValueError``/``OverflowError`` + that ``post_connect`` does not catch, so the CLI printed a traceback instead of its + structured error. Nothing may be sent, either. + """ + + class _Exploding: + @staticmethod + def open(request, timeout=None): # pragma: no cover - must never run + raise AssertionError("a request was started with an unusable timeout") + + _install_opener(monkeypatch, _Exploding()) + + with pytest.raises(device_connect.DeviceConnectError) as caught: + device_connect.connect(TOKEN, control_url=CONTROL_URL, timeout=float(bad)) + + assert caught.value.status == 400 + assert "timeout" in str(caught.value) + + +def test_the_cli_reports_a_bad_timeout_instead_of_a_traceback(monkeypatch, capsys): + class _Exploding: + @staticmethod + def open(request, timeout=None): # pragma: no cover - must never run + raise AssertionError("a request was started with an unusable timeout") + + _install_opener(monkeypatch, _Exploding()) + + code = connect_cli.main( + ["--token", TOKEN, "--control-url", CONTROL_URL, "--timeout", "nan"] + ) + + assert code == 1 + err = capsys.readouterr().err + assert "timeout" in err + assert "Traceback" not in err + + +def test_a_storage_fault_racing_the_save_is_not_a_traceback(monkeypatch): + """``UnsafeStateFile`` is an ``OSError``, not a ``CloudSessionError``. + + The pre-flight closes the common case, but the state directory can still change + between the pre-flight and the write. The token is spent by then, so the customer + must be told that plainly rather than shown a stack trace. + """ + + _install_opener(monkeypatch, _Opener(body=REGISTRATION)) + + def _boom(*args, **kwargs): + raise UnsafeStateFile("cloud_session.json is not a plain private file") + + monkeypatch.setattr(cloud_session, "save_bootstrap", _boom) + + with pytest.raises(device_connect.DeviceConnectError) as caught: + device_connect.connect(TOKEN, control_url=CONTROL_URL) + + message = str(caught.value) + assert caught.value.status == 409 + # The token is gone; the copy must not promise it can be reused. + assert "has been used" in message + assert TOKEN not in message + + def test_control_url_env_override_wins(monkeypatch): monkeypatch.setenv("ENGRAPHIS_CLOUD_CONTROL_URL", CONTROL_URL) assert device_connect.default_control_url() == CONTROL_URL From e97151762f90f7ef007699db4cf6fb73c7f057fa Mon Sep 17 00:00:00 2001 From: Jaixii Date: Sun, 26 Jul 2026 18:24:58 -0400 Subject: [PATCH 29/82] Report post-redemption connect failures instead of raising tracebacks Both paths fail *after* the control plane has consumed the single-use connect token, so a raw traceback left the customer unable to tell whether to retry or fetch a new token from the portal. `http.client.IncompleteRead` (a truncated chunked reply) subclasses `HTTPException`/`ValueError` -- neither `OSError` nor `URLError` -- so it escaped both of `post_connect`'s handlers. A third clause is added *after* the transport clause, because `RemoteDisconnected` is both a `ConnectionResetError` and a `BadStatusLine` and means the peer never answered: that one keeps the retryable 503 copy, and a test pins the ordering. `save_bootstrap` re-runs `validate_cloud_base_url` on both endpoints, which resolves the host. A resolver that dies mid-connect raises `CloudUrlUnresolved` and an endpoint that starts resolving to a rejected address raises a bare `ValueError`; both are `ValueError`, so neither the `CloudSessionError` nor the `OSError` handler in `connect()` covered them. Translated in `connect()` rather than by dropping the re-validation, which is still wanted for `save_bootstrap`'s other callers. Co-Authored-By: Claude Opus 5 --- CHANGELOG.md | 6 +- engraphis/device_connect.py | 40 +++++++++++ tests/test_device_connect.py | 128 +++++++++++++++++++++++++++++++++++ 3 files changed, 173 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3d6d026..a455755 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,7 +39,11 @@ All notable changes to Engraphis are documented here. Format loosely follows with a lapsed subscription). Session storage is pre-flighted before the exchange, so an unwritable state directory or a `cloud_session.json` replaced by a link fails the command *without* spending the single-use token — the customer fixes the path and retries with the - same token instead of returning to the portal for a new one. Also installed as + same token instead of returning to the portal for a new one. Faults that can only happen + *after* the exchange — a reply truncated mid-body (`http.client.IncompleteRead`), or an + endpoint that stops resolving before the session is written (`CloudUrlUnresolved`) — are + reported as errors that say the token was already used, rather than escaping as tracebacks + that leave the customer unable to tell whether to retry. Also installed as `engraphis-connect`. - An `engraphis` front-door command that dispatches to the existing `engraphis-` entry points, so the command the account portal displays is runnable as shown. diff --git a/engraphis/device_connect.py b/engraphis/device_connect.py index d0698bb..cf50c73 100644 --- a/engraphis/device_connect.py +++ b/engraphis/device_connect.py @@ -25,6 +25,7 @@ """ from __future__ import annotations +import http.client import json import math import os @@ -65,6 +66,17 @@ #: The control plane answers with a small fixed record; anything larger is not ours. _MAX_RESPONSE_BYTES = 64 * 1024 +#: Copy for a reply that began but never completed. Every other failure in this module can +#: promise the connect token is untouched; this one cannot, because the request reached a +#: control plane that started to answer, and a 200 consumes the token as it is written. +#: Saying "try again" here would be a lie that costs the customer a second failed attempt, +#: so the copy sends them to the one place that shows whether the device landed. +_TRUNCATED_REPLY = ( + "Engraphis Cloud started answering this connect request but the connection closed " + "before the reply was complete. Your connect token may already have been used: check " + "your account portal, and generate a new one if this device is not listed there." +) + #: The portal always mints tokens with this prefix. Checking it locally turns a #: mistyped or truncated paste into an instant, free error instead of a round trip that #: consumes rate budget and returns the same opaque 401 as a genuinely dead token. @@ -457,11 +469,25 @@ def post_connect(control_url: str, token: str, *, installation_client_id: str, raise _connect_http_error(status) except (urllib.error.URLError, TimeoutError, OSError) as exc: # ``exc`` may quote an internal host or a proxy URL; never reflect it. + # + # Deliberately ahead of the ``HTTPException`` clause: ``RemoteDisconnected`` is + # both a ``ConnectionResetError`` and a ``BadStatusLine``, and it means the peer + # closed without answering at all. Nothing was consumed, so "try again" is the + # correct advice for it and it must not inherit the token-may-be-spent copy. raise DeviceConnectError( "Engraphis Cloud is temporarily unreachable. Check your network and try " "again.", status=503, ) from exc + except http.client.HTTPException as exc: + # A truncated chunked body makes ``HTTPResponse.read`` raise ``IncompleteRead``, + # which subclasses ``HTTPException``/``ValueError`` and is neither an ``OSError`` + # nor a ``URLError`` -- so it escaped both clauses above as a raw traceback. That + # happened at the worst moment: the control plane had already answered, so the + # single-use token was very likely spent, and the customer saw a stack trace + # instead of being told to check the portal. ``LineTooLong``/``BadStatusLine`` from + # reading the status line and headers land here for the same reason. + raise DeviceConnectError(_TRUNCATED_REPLY, status=502) from exc if len(raw) > _MAX_RESPONSE_BYTES: raise DeviceConnectError( "Engraphis Cloud returned an oversized connect response.", status=502 @@ -603,6 +629,20 @@ def connect(token: object, *, control_url: Optional[str] = None, "portal -- this one has been used." % session_path, status=409, ) from exc + except ValueError as exc: + # ``save_bootstrap`` re-runs ``validate_cloud_base_url`` on both endpoints, and + # that helper *resolves* the host. A resolver that dies between the pre-POST check + # and this line raises ``CloudUrlUnresolved``; an endpoint that starts resolving to + # a rejected address raises a bare ``ValueError``. Both are ``ValueError``, so + # neither the ``CloudSessionError`` nor the ``OSError`` clause above covered them + # and they escaped as a traceback -- again after the token was already spent. + raise DeviceConnectError( + "Engraphis Cloud accepted the token, but its endpoints could not be verified " + "in time to save the session, so nothing was written. Check your network, " + "then connect again with a new token from your account portal -- this one " + "has been used.", + status=409, + ) from exc summary = summarize(response) summary["control_url"] = resolved_control diff --git a/tests/test_device_connect.py b/tests/test_device_connect.py index 2367fa5..2d636e9 100644 --- a/tests/test_device_connect.py +++ b/tests/test_device_connect.py @@ -7,6 +7,7 @@ """ from __future__ import annotations +import http.client import json import os import urllib.error @@ -17,6 +18,7 @@ import pytest from engraphis import cloud_session, device_connect +from engraphis.hosted_client import CloudUrlUnresolved from engraphis.private_state import UnsafeStateFile from scripts import connect as connect_cli @@ -350,6 +352,132 @@ def open(self, request, timeout): device_connect.connect(TOKEN, control_url=CONTROL_URL, compute_url=COMPUTE_URL) +# ------------------------------------------- failures *after* the token has been spent +# +# Once ``opener.open`` has returned, the control plane has answered and the single-use +# connect token is gone. Every fault from that point on has to arrive as a +# ``DeviceConnectError`` that says so -- a traceback here is the worst possible outcome, +# because the customer cannot tell whether to retry or fetch a new token. + + +class _TruncatedBody: + """A 200 whose body stops mid-stream, the way a dropped chunked reply does.""" + + def __enter__(self): + return self + + def __exit__(self, *exc) -> bool: + return False + + def read(self, size: int = -1) -> bytes: + # What ``HTTPResponse._read_chunked`` raises for a truncated body. It subclasses + # ``HTTPException``/``ValueError`` -- neither ``OSError`` nor ``URLError``. + raise http.client.IncompleteRead(b'{"organization_id":"org_al') + + +@pytest.mark.parametrize("failure", [ + http.client.IncompleteRead(b'{"organization_id":"org_al'), + http.client.LineTooLong("header line"), + http.client.BadStatusLine("garbage"), +]) +def test_a_truncated_reply_reports_the_token_state_not_a_traceback( + monkeypatch, tmp_path, failure +): + """``IncompleteRead`` is an ``HTTPException``, so the transport clause never saw it.""" + + class _Broken(_Opener): + def open(self, request, timeout): + self.calls.append({"body": request.data}) + if isinstance(failure, http.client.IncompleteRead): + return _TruncatedBody() + raise failure + + opener = _Broken() + _install_opener(monkeypatch, opener) + + with pytest.raises(device_connect.DeviceConnectError) as caught: + device_connect.connect(TOKEN, control_url=CONTROL_URL, compute_url=COMPUTE_URL) + + message = str(caught.value) + assert caught.value.status == 502 + # The customer must be told the token may be gone rather than told to just retry. + assert "may already have been used" in message + assert TOKEN not in message + assert not (tmp_path / "cloud_session.json").exists() + + +def test_a_connection_reset_before_any_reply_still_says_retry(monkeypatch): + """``RemoteDisconnected`` is *both* an ``OSError`` and an ``HTTPException``. + + Nothing was read, so the token is untouched and "try again" remains the right copy; + it must not be swept into the token-may-be-spent message by the new clause. + """ + + _install_opener( + monkeypatch, _Opener(error=http.client.RemoteDisconnected("closed early")) + ) + + with pytest.raises(device_connect.DeviceConnectError) as caught: + device_connect.connect(TOKEN, control_url=CONTROL_URL, compute_url=COMPUTE_URL) + + assert caught.value.status == 503 + assert "temporarily unreachable" in str(caught.value) + + +@pytest.mark.parametrize("failure", [ + CloudUrlUnresolved("cloud service URL could not be resolved"), + ValueError("cloud service URL must not target private/reserved IP ranges"), +]) +def test_endpoint_validation_failing_after_redemption_is_not_a_traceback( + monkeypatch, tmp_path, failure +): + """``save_bootstrap`` re-resolves both endpoints *after* the POST spent the token. + + ``CloudUrlUnresolved`` is a ``ValueError``, so neither the ``CloudSessionError`` nor + the ``OSError`` handler in ``connect()`` covers it: a resolver that dies mid-connect, + or a host that starts resolving to a rejected address, escaped as a raw traceback. + """ + + opener = _Opener(body=REGISTRATION) + _install_opener(monkeypatch, opener) + + def _rejects(value): + raise failure + + # Only the save path: the pre-POST checks in ``connect()`` already passed. + monkeypatch.setattr(cloud_session, "validate_cloud_base_url", _rejects) + + with pytest.raises(device_connect.DeviceConnectError) as caught: + device_connect.connect(TOKEN, control_url=CONTROL_URL, compute_url=COMPUTE_URL) + + message = str(caught.value) + assert caught.value.status == 409 + assert opener.calls, "the token was spent; the copy has to admit it" + assert "has been used" in message + assert TOKEN not in message + assert not (tmp_path / "cloud_session.json").exists() + + +def test_the_cli_reports_a_post_redemption_fault_instead_of_a_traceback( + monkeypatch, capsys +): + _install_opener(monkeypatch, _Opener(body=REGISTRATION)) + + def _rejects(value): + raise CloudUrlUnresolved("cloud service URL could not be resolved") + + monkeypatch.setattr(cloud_session, "validate_cloud_base_url", _rejects) + + code = connect_cli.main([ + "--token", TOKEN, "--control-url", CONTROL_URL, "--compute-url", COMPUTE_URL, + ]) + + err = capsys.readouterr().err + assert code == 1 + assert "Traceback" not in err + assert "has been used" in err + + # ------------------------------------------------------ pre-flight on session storage # # The POST is the point of no return: the control plane consumes the single-use connect From bbcd7c9455e5541e4311ff8f5adf686654faf4a5 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 26 Jul 2026 14:09:24 -0400 Subject: [PATCH 30/82] Read the trial and the access state the cloud sends, and render them MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `/api/license` hardcoded `"is_trial": False` and `"trial": {"used": False}`. Those were the only assignments in the file, and the client read none of `status`, `trial_ends_at`, or `trial_duration_seconds` from anywhere, so three customer-visible states were wrong or unreachable: * the dashboard's `'TRIAL'` badge branch could never be taken — a trialist saw the same confident PRO/TEAM badge a subscriber sees; * `trial.used` never became true, so "Start hosted Pro/Team trial" was offered to everyone forever, including active subscribers and customers whose trial was already spent. `start_trial` refuses any organization that already holds an entitlement, so for every connected customer that button could only ever return a `TrialAlreadyConsumedError`; and * `cloud_access_active` was computed, returned, and rendered nowhere. After a trial expired or a subscription lapsed the client kept `plan="pro"` and cleared the feature list, so the customer got a confident PRO badge over rows of locked features with no explanation of what had happened. The client now reads what the control plane already sends on the calls it already makes. `cloud_session` persists `status`, `is_trial`, `trial_consumed`, and `trial_ends_at` from the registration/refresh handshake alongside the plan fields, under the same wire names so one parser serves the saved record, the entitlements read, and the compatibility cache. Every field stays individually optional: an older control plane omits them and the honest answer is "not a trial, none consumed", never an invented one. A billing denial keeps the trial facts — a lapse does not un-consume a trial or move its boundary — and drops the status it just contradicted. `/api/license` derives one `access_state` from that: active, trial, trial_expired, lapsed, or inactive. Each is a different thing to tell the customer and a different thing to ask them to do, and the dashboard now says which: * active trial — TRIAL badge, the trial's end date, no trial CTA; * spent trial — TRIAL ENDED, "your free trial has ended, your memories are still local and usable, the trial cannot be started again", subscribe; * paying — PRO/TEAM badge, no trial CTA (a subscriber who never trialled would still be refused one); * lapsed — PRO INACTIVE, why it lapsed when the cloud named a status, and update billing; * never — LOCAL CORE, the local engine is complete on its own, and the trial CTA — the one state it can actually be started in. `plan_source`/`plan_checked_at` were emitted for support and displayed nowhere; the panel now shows which rule produced the answer and when the cloud last confirmed it. No inline styles or handlers were added; both asset gates and `node --check` pass. Co-Authored-By: Claude Opus 5 --- engraphis/cloud_session.py | 83 +++++- engraphis/routes/v2_api.py | 242 ++++++++++++++-- engraphis/static/dashboard.css | 3 + engraphis/static/dashboard.js | 83 ++++-- tests/test_client_launch.py | 7 +- tests/test_dashboard_auth_placement.py | 53 +++- tests/test_hosted_plan_resolution.py | 364 ++++++++++++++++++++++++- 7 files changed, 777 insertions(+), 58 deletions(-) diff --git a/engraphis/cloud_session.py b/engraphis/cloud_session.py index cbadc1a..01ab17e 100644 --- a/engraphis/cloud_session.py +++ b/engraphis/cloud_session.py @@ -280,6 +280,14 @@ def preflight_save() -> Path: #: Plans that carry no paid cloud access, used only to default an absent activity flag. _UNPAID_PLANS = ("free", "local") +#: Entitlement status vocabulary the control plane can persist or compute +#: (``engraphis_cloud/entitlements.py`` ``effective_status``, plus every provider status +#: ``/internal/subscriptions/apply`` accepts). Kept as a bound, not an allow-list: an +#: unrecognised value is stored verbatim so a future server release is not mistranslated, +#: it is only length-capped like every other presentation string here. +_MAX_STATUS_CHARS = 32 +#: An ISO-8601 timestamp is at most a few dozen characters; anything longer is not one. +_MAX_TIMESTAMP_CHARS = 64 #: Bounds on the entitlement fields before they are written into the session record. The #: record is read back under a 64 KiB private-state cap, so an unbounded provider value #: could grow the file past that cap and make the whole session permanently unreadable. @@ -287,17 +295,36 @@ def preflight_save() -> Path: _MAX_PLAN_CHARS = 64 _MAX_FEATURES = 32 _MAX_FEATURE_CHARS = 64 +#: Every entitlement key ``_declared_entitlement`` can put on the session record. The +#: record is deliberately shaped like the wire response so one reader serves both, which +#: is what keeps a saved answer and a fresh one from being parsed by different rules. +_ENTITLEMENT_KEYS = ( + "plan", + "cloud_access_active", + "cloud_features", + "status", + "is_trial", + "trial_consumed", + "trial_ends_at", +) def _declared_entitlement(response: object) -> dict: """Return the entitlement fields a control-plane response carried, or ``{}``. ``DeviceRegistrationResponse`` — the body both ``/internal/devices/register`` and - ``POST /v1/tokens/refresh`` answer with — carries ``plan``, ``cloud_features`` and - ``cloud_access_active``. They are read as *optional* on purpose: a control plane that - has not deployed them yet returns exactly what it always did, and this client must keep - working against it rather than requiring a newer server. An absent or unusable ``plan`` - therefore yields ``{}``, which leaves whatever the caller already knew in place. + ``POST /v1/tokens/refresh`` answer with — carries ``plan``, ``cloud_features``, + ``cloud_access_active``, and the trial facts (``status``, ``is_trial``, + ``trial_consumed``, ``trial_ends_at``). They are read as *optional* on purpose: a + control plane that has not deployed them yet returns exactly what it always did, and + this client must keep working against it rather than requiring a newer server. An + absent or unusable ``plan`` therefore yields ``{}``, which leaves whatever the caller + already knew in place. + + The trial fields are each optional *individually* as well, because they shipped after + the plan fields did: a server that answers ``plan`` but not ``is_trial`` simply leaves + the key absent, and the caller keeps treating the customer as a non-trialist rather + than claiming a trial nobody declared. Nothing here is authority. The cloud authorizes every paid call regardless of what this record says; persisting it only saves the dashboard from guessing. @@ -325,6 +352,23 @@ def _declared_entitlement(response: object) -> dict: item.strip().lower()[:_MAX_FEATURE_CHARS] for item in features if isinstance(item, str) and item.strip() })[:_MAX_FEATURES] + # The trial half of the same answer. Absent stays absent so a field-less older server + # cannot erase what a newer one already recorded, exactly as ``cloud_features`` behaves. + status = response.get("status") + if isinstance(status, str) and status.strip(): + declared["status"] = status.strip().lower()[:_MAX_STATUS_CHARS] + for key in ("is_trial", "trial_consumed"): + value = response.get(key) + if isinstance(value, bool): + declared[key] = value + ends_at = response.get("trial_ends_at") + if isinstance(ends_at, str) and ends_at.strip(): + declared["trial_ends_at"] = ends_at.strip()[:_MAX_TIMESTAMP_CHARS] + elif ends_at is None and "is_trial" in declared and not declared["is_trial"]: + # An explicit ``null`` from a server that *did* answer the trial question is + # meaningful: it is how a converted paying customer is told they have no live trial + # boundary. Clear a stale one rather than letting a past trial end survive forever. + declared["trial_ends_at"] = "" return declared @@ -395,6 +439,13 @@ def record_billing_denial() -> bool: ) saved["cloud_access_active"] = False saved["cloud_features"] = [] + # The last status the server named ("active", "trialing", …) is now known to + # contradict this denial, so it must not survive as renderable copy. The trial + # facts are *not* invalidated by a lapse -- whether this was a trial, when it + # ended, and whether one was consumed are all still true -- and they are what + # lets the dashboard say "your free trial ended" rather than the generic + # "your subscription lapsed". + saved.pop("status", None) saved["entitlement_checked_at"] = time.time() # Inside the lock: a save that lands after release is exactly the race above. _save(saved) @@ -609,17 +660,21 @@ def access_for_workspace( # plan re-confirms itself on every token rotation. An older cloud omits them and # the previously persisted answer (if any) is left untouched. declared = _declared_entitlement(body) - if declared and "cloud_features" not in declared: - # A *plan change* may never inherit the previous plan's grants. - # ``_declared_entitlement`` omits ``cloud_features`` whenever the body carried - # no feature list, so merging it onto the saved record left a Team feature list - # alive underneath a downgraded Pro plan and kept the Team tab unlocked - # indefinitely. Dropping the stale key hands the answer back to this client's - # own plan table, which is right for the plan the cloud just named. A refresh - # that re-confirms the *same* plan still keeps the richer saved list. + if declared: + # A *plan change* may never inherit the previous plan's state. + # ``_declared_entitlement`` omits any field the body did not carry, so merging + # it onto the saved record left a Team feature list alive underneath a + # downgraded Pro plan and kept the Team tab unlocked indefinitely. Dropping + # every entitlement key the new answer did not restate hands those back to this + # client's own defaults, which are right for the plan the cloud just named -- + # and stops a finished trial's ``is_trial``/``trial_ends_at`` surviving under + # the paid plan it converted into. A refresh that re-confirms the *same* plan + # still keeps the richer saved answer. previous = str(saved.get("plan") or "").strip().lower() if previous != declared["plan"]: - updated.pop("cloud_features", None) + for key in _ENTITLEMENT_KEYS: + if key not in declared: + updated.pop(key, None) updated.update(declared) _save(updated) return access, organization_id, compute diff --git a/engraphis/routes/v2_api.py b/engraphis/routes/v2_api.py index 7ffe550..0cc6e3b 100644 --- a/engraphis/routes/v2_api.py +++ b/engraphis/routes/v2_api.py @@ -7,6 +7,7 @@ """ from __future__ import annotations +import datetime as _datetime import json import hmac import logging @@ -1916,6 +1917,95 @@ def _normalized_plan(value: object) -> str: return plan if plan in ("pro", "team") else "local" +#: The control plane's entitlement status vocabulary, mirrored from (read-only) +#: engraphis-cloud/engraphis_cloud/entitlements.py ``effective_status`` and the statuses +#: ``/internal/subscriptions/apply`` accepts. Presentation only: an unrecognised value is +#: reported as ``""`` rather than guessed at, which degrades the copy to the generic +#: wording instead of asserting something the server never said. +_ENTITLEMENT_STATUSES = frozenset({ + "active", "trialing", "past_due", "canceled", "expired", "revoked", "scheduled", + "inactive", +}) + + +def _normalized_status(value: object) -> str: + """Return the control plane's entitlement status, or ``""`` when it said nothing.""" + + status = str(value or "").strip().lower() + return status if status in _ENTITLEMENT_STATUSES else "" + + +def _epoch_seconds(value: object) -> float: + """Return an ISO-8601 instant as epoch seconds, or ``0.0``. Never raises. + + The control plane serializes ``trial_ends_at`` as an ISO-8601 UTC timestamp; the + dashboard renders instants as epoch seconds. Converting once, here, keeps the JS from + parsing dates the CSP-externalized asset cannot be unit-tested through. + + ``datetime.fromisoformat`` on this package's Python 3.9 floor does not accept the + trailing ``Z`` that Pydantic emits for UTC, so it is rewritten to the explicit offset + first. Anything it still cannot parse is reported as "unknown" rather than raising on + the ``/api/bootstrap`` boot path. + """ + + if isinstance(value, bool): + return 0.0 + if isinstance(value, (int, float)): + return float(value) if value > 0 else 0.0 + if not isinstance(value, str) or not value.strip(): + return 0.0 + text = value.strip() + if text[-1:] in ("Z", "z"): + text = text[:-1] + "+00:00" + try: + parsed = _datetime.datetime.fromisoformat(text) + except (ValueError, TypeError): + return 0.0 + if parsed.tzinfo is None: + parsed = parsed.replace(tzinfo=_datetime.timezone.utc) + try: + return float(parsed.timestamp()) + except (OverflowError, OSError, ValueError): + return 0.0 + + +def _trial_facts(source: object) -> dict: + """Read the control plane's trial disclosure off any entitlement-shaped mapping. + + ``DeviceRegistrationResponse`` and ``GET /v1/entitlements/{org}`` carry the same four + fields, so one reader serves both and the two answers cannot be parsed by different + rules. Every field is optional: a control plane that predates them simply omits them, + and the honest answer is then "not a trial, none consumed" rather than a claim. + + ``trial_consumed`` is deliberately widened by ``is_trial``: an organization that is on + a trial has by definition consumed one, so a server that answers only ``is_trial`` + still stops this client offering a second trial the server would refuse. + """ + + if not isinstance(source, dict): + return {"status": "", "is_trial": False, "trial_consumed": False, + "trial_ends_at": 0.0} + is_trial = source.get("is_trial") + is_trial = bool(is_trial) if isinstance(is_trial, bool) else False + consumed = source.get("trial_consumed") + consumed = bool(consumed) if isinstance(consumed, bool) else False + return { + "status": _normalized_status(source.get("status")), + "is_trial": is_trial, + "trial_consumed": consumed or is_trial, + # A trial boundary is only meaningful for a trial. Replaying a converted + # customer's long-past trial end would tell a paying subscriber their access + # expired last month, which is exactly what the server refuses to do. + "trial_ends_at": _epoch_seconds(source.get("trial_ends_at")) if is_trial else 0.0, + } + + +def _unknown_trial_facts() -> dict: + """Return the "the control plane has told us nothing" trial answer.""" + + return {"status": "", "is_trial": False, "trial_consumed": False, "trial_ends_at": 0.0} + + def _normalized_features(values: object, plan: str) -> list: """Keep the server's own grant, expanded to the names this dashboard renders. @@ -1957,7 +2047,7 @@ def _session_entitlement() -> dict: return {} plan = _normalized_plan(declared.get("plan")) active = bool(declared.get("cloud_access_active")) - return { + resolved = { "plan": plan, # The server empties ``cloud_features`` the moment paid access stops being # live; mirror that, exactly as the entitlements route's answer does below. @@ -1969,6 +2059,8 @@ def _session_entitlement() -> dict: "organization_id": str(declared.get("organization_id") or ""), "fetched_at": float(declared.get("entitlement_checked_at") or 0.0), } + resolved.update(_trial_facts(declared)) + return resolved except Exception: # noqa: BLE001 - a badge must never break /bootstrap return {} @@ -2029,13 +2121,18 @@ def _read_entitlement_cache() -> dict: if not current or organization_id != current: return {} plan = _normalized_plan(stored_plan) - return { + resolved = { "plan": plan, "features": _normalized_features(value.get("features"), plan), "cloud_access_active": bool(value.get("cloud_access_active")), "organization_id": organization_id, "fetched_at": fetched_at, } + # The trial disclosure is cached under the same wire names the entitlements route uses, + # so a cache written by an older build simply has none of them and reads back as "not a + # trial" rather than as a corrupt entry. + resolved.update(_trial_facts(value)) + return resolved def _write_entitlement_cache(entitlement: dict) -> None: @@ -2059,6 +2156,13 @@ def _write_entitlement_cache(entitlement: dict) -> None: "cloud_access_active": bool(entitlement["cloud_access_active"]), "organization_id": str(entitlement.get("organization_id") or ""), "fetched_at": float(entitlement.get("fetched_at") or time.time()), + # Persisted under the wire names ``_trial_facts`` reads, so the cache round + # trips through exactly one parser. ``trial_ends_at`` is already epoch seconds + # by this point, which that parser also accepts. + "status": _normalized_status(entitlement.get("status")), + "is_trial": bool(entitlement.get("is_trial")), + "trial_consumed": bool(entitlement.get("trial_consumed")), + "trial_ends_at": float(entitlement.get("trial_ends_at") or 0.0), }, sort_keys=True, separators=(",", ":"))) except Exception: # noqa: BLE001 - losing the cache write must not surface anywhere logger.debug("entitlement cache write skipped") @@ -2092,6 +2196,11 @@ def _deny_entitlement_cache() -> None: denied = dict(cached) denied["cloud_access_active"] = False denied["features"] = [] + # The last status the server named now contradicts this denial, so it stops being + # renderable copy. The trial facts survive: a lapse does not un-consume a trial or + # move its boundary, and they are what distinguishes "your free trial ended" from + # "your subscription lapsed" in the panel this settles. + denied["status"] = "" denied["fetched_at"] = time.time() _write_entitlement_cache(denied) except Exception: # noqa: BLE001 - a denial we cannot persist is still a denial @@ -2228,7 +2337,7 @@ def _fetch_authoritative_entitlement() -> Optional[dict]: if not isinstance(active, bool): return None plan = _normalized_plan(declared_plan) - return { + resolved = { "plan": plan, # The server empties ``cloud_features`` the moment paid access stops being live. # Mirroring that re-draws the locks on a lapsed subscription while the badge keeps @@ -2239,6 +2348,11 @@ def _fetch_authoritative_entitlement() -> Optional[dict]: "organization_id": organization_id, "fetched_at": time.time(), } + # ``is_trial``/``trial_consumed``/``trial_ends_at``/``status`` are optional here for the + # same reason the fields above the fallback are: a control plane that predates them + # omits them, and the honest answer is then "not a trial", not a refusal to cache. + resolved.update(_trial_facts(body)) + return resolved def _refresh_entitlement_in_background(known: dict) -> None: @@ -2319,34 +2433,61 @@ def _plan_entitlement() -> dict: declared = os.environ.get("ENGRAPHIS_CLOUD_PLAN", "").strip().lower() if declared in ("pro", "team", "free", "local"): plan = declared if declared in ("pro", "team") else "local" - return {"plan": plan, "features": entitled_features(plan), - "source": "environment", "cloud_access_active": plan != "local", - "checked_at": 0.0} + # An operator override names a plan, never a trial: it exists for air-gapped and + # pinned-token deployments that have no control plane to ask. Reporting "no trial, + # none consumed" is the honest answer, and it is what keeps the trial CTA off a + # deployment that cannot start one. + entitlement = {"plan": plan, "features": entitled_features(plan), + "source": "environment", "cloud_access_active": plan != "local", + "checked_at": 0.0} + entitlement.update(_unknown_trial_facts()) + return entitlement try: from engraphis import cloud_session connected = cloud_session.configured(require_compute=False) except Exception: # noqa: BLE001 - a badge must never break /bootstrap connected = False if not connected: - return {"plan": "local", "features": [], "source": "local", - "cloud_access_active": False, "checked_at": 0.0} + entitlement = {"plan": "local", "features": [], "source": "local", + "cloud_access_active": False, "checked_at": 0.0} + entitlement.update(_unknown_trial_facts()) + return entitlement session = _session_entitlement() if session: _refresh_entitlement_in_background(session) - return {"plan": session["plan"], "features": list(session["features"]), - "source": "session", "cloud_access_active": session["cloud_access_active"], - "checked_at": session["fetched_at"]} + return _resolved_entitlement(session, source="session") cached = _read_entitlement_cache() _refresh_entitlement_in_background(cached) if cached: - return {"plan": cached["plan"], "features": list(cached["features"]), - "source": "cloud", "cloud_access_active": cached["cloud_access_active"], - "checked_at": cached["fetched_at"]} + return _resolved_entitlement(cached, source="cloud") # Connected, but the control plane has never answered (first boot after onboarding, or # offline since). ``pro`` unlocks what every paid plan includes and leaves only the Team # upsell showing; the refresh scheduled above corrects it. - return {"plan": "pro", "features": entitled_features("pro"), "source": "connected", - "cloud_access_active": True, "checked_at": 0.0} + # + # It says nothing about a trial either way. Guessing "no trial consumed" here would + # re-offer the trial CTA to a connected organization the server will refuse -- a + # connected installation always has an organization, and that organization is on a + # trial, has spent one, or is paying -- so this reports the trial as consumed and lets + # the refresh replace the guess with the answer. + entitlement = {"plan": "pro", "features": entitled_features("pro"), + "source": "connected", "cloud_access_active": True, "checked_at": 0.0} + entitlement.update(_unknown_trial_facts()) + entitlement["trial_consumed"] = True + return entitlement + + +def _resolved_entitlement(known: dict, *, source: str) -> dict: + """Shape one persisted answer into the resolver's return value.""" + + resolved = { + "plan": known["plan"], + "features": list(known["features"]), + "source": source, + "cloud_access_active": known["cloud_access_active"], + "checked_at": known["fetched_at"], + } + resolved.update(_trial_facts(known)) + return resolved def _hosted_plan() -> str: @@ -2387,15 +2528,50 @@ def hosted_plan_summary() -> dict: entitlement = {"plan": plan, "features": entitled_features(plan), "source": "override", "cloud_access_active": plan != "local", "checked_at": 0.0} + entitlement.update(_unknown_trial_facts()) return { "plan": entitlement["plan"], "features": list(entitlement["features"]), "plan_source": entitlement["source"], "cloud_access_active": entitlement["cloud_access_active"], "plan_checked_at": entitlement["checked_at"], + "entitlement_status": entitlement["status"], + "is_trial": entitlement["is_trial"], + "trial_consumed": entitlement["trial_consumed"], + "trial_ends_at": entitlement["trial_ends_at"], + "access_state": _access_state(entitlement), } +#: Why the customer's hosted features are, or are not, available right now. The dashboard +#: renders one explanation per value; every one of them is a different thing to tell the +#: customer and a different thing to ask them to do. +#: +#: * ``trial`` — a live trial. Say when it ends and offer to buy. +#: * ``active`` — a live paid subscription. Nothing to explain. +#: * ``trial_expired`` — the free trial ran out. Offer to buy; never offer another trial. +#: * ``lapsed`` — a subscription that is no longer live (cancelled, expired, unpaid). +#: Send the customer to billing, not to a trial they cannot start. +#: * ``inactive`` — no hosted plan at all. This is the only state a trial is offerable in. +#: +#: Before this existed, the last three were indistinguishable on screen: the client kept +#: ``plan="pro"`` with an emptied feature list, so a customer whose trial had ended and a +#: customer whose card had failed both saw a confident PRO badge over rows of locks with +#: no reason given. +_ACCESS_STATES = ("active", "trial", "trial_expired", "lapsed", "inactive") + + +def _access_state(entitlement: dict) -> str: + """Classify why hosted features are available or locked. Never raises.""" + + if entitlement.get("plan") not in ("pro", "team"): + return "inactive" + is_trial = bool(entitlement.get("is_trial")) + if entitlement.get("cloud_access_active"): + return "trial" if is_trial else "active" + return "trial_expired" if is_trial else "lapsed" + + @router.get("/license") def get_license(): """Hosted plan presentation for the dashboard; Cloud remains the authority. @@ -2419,11 +2595,35 @@ def get_license(): "plan_source": summary["plan_source"], "plan_checked_at": summary["plan_checked_at"], "cloud_access_active": summary["cloud_access_active"], - # The client cannot distinguish a trial from a paid subscription; the control - # plane owns that. Report the honest default so the badge falls back to the plan - # name instead of silently claiming a trial the customer may not be on. - "is_trial": False, - "trial": {"used": False, "trial_days": licensing.TRIAL_DAYS}, + # Why the hosted features above are, or are not, live. The dashboard renders one + # explanation per value rather than a plan badge over unexplained locks. + "access_state": summary["access_state"], + # The control plane's own entitlement status, when it named one. ``""`` means it + # has not, or that its last answer was contradicted by a billing denial. + "entitlement_status": summary["entitlement_status"], + # The control plane owns the trial, and now says so on the calls this client + # already makes. Hardcoding these to ``False`` made the dashboard's TRIAL badge + # unreachable and, because ``used`` never became true, offered "Start your free + # trial" forever — to active subscribers and to customers whose trial was already + # spent, both of whom the server answers with ``TrialAlreadyConsumedError``. + "is_trial": summary["is_trial"], + "trial": { + "used": summary["trial_consumed"], + "active": summary["access_state"] == "trial", + # Epoch seconds, ``0`` when there is no live trial boundary to disclose. A + # converted paying customer is deliberately never told about a past one. + "ends_at": summary["trial_ends_at"], + # A trial is offerable only to an installation that belongs to no organization + # yet. ``start_trial`` refuses every organization that already holds an + # entitlement, so a connected customer — trialling, lapsed, or paying — can + # only ever be answered 409 by the button. + "available": ( + not summary["trial_consumed"] + and summary["access_state"] == "inactive" + and summary["plan_source"] == "local" + ), + "trial_days": licensing.TRIAL_DAYS, + }, "cloud_managed": True, "trial_seconds": 259_200, "grace_seconds": 86_400, diff --git a/engraphis/static/dashboard.css b/engraphis/static/dashboard.css index fc2c328..8af1af2 100644 --- a/engraphis/static/dashboard.css +++ b/engraphis/static/dashboard.css @@ -255,6 +255,9 @@ body{ .diff-ins{border-radius:var(--radius-sm);background:var(--color-success-bg);color:var(--color-success)} .diff-del{border-radius:var(--radius-sm);background:var(--color-danger-bg);color:var(--color-danger);text-decoration:line-through} .trial-banner{margin-bottom:var(--space-3);padding:var(--space-2) var(--space-3);border:var(--rule) solid var(--color-accent-strong);border-radius:var(--radius-sm);background:var(--accent-bg);color:var(--color-text);font-size:var(--text-xs)} +.lic-banner{margin:var(--space-3) 0;padding:var(--space-3);border:var(--rule) solid var(--color-border);border-radius:var(--radius-sm);background:var(--color-raised);color:var(--color-text-muted);font-size:var(--text-xs);line-height:1.5} +.lic-banner strong{display:block;margin-bottom:var(--space-1);color:var(--color-text);font-size:var(--text-sm)} +.lic-banner-warn{border-color:var(--color-accent-strong);background:var(--accent-bg)} .update-banner{display:flex;align-items:center;gap:var(--space-3);margin-bottom:var(--space-3);padding:var(--space-2) var(--space-3);border:var(--rule) solid var(--color-accent-strong);border-radius:var(--radius-sm);background:var(--accent-bg);color:var(--color-text);font-size:var(--text-xs)} .update-banner[hidden]{display:none} .update-banner .ub-text{flex:1;min-width:0} diff --git a/engraphis/static/dashboard.js b/engraphis/static/dashboard.js index d9da2e8..c6c0e8d 100644 --- a/engraphis/static/dashboard.js +++ b/engraphis/static/dashboard.js @@ -129,7 +129,7 @@ async function loadOverviewAnalytics(){ const el=document.getElementById('ov-analytics'),lock=document.getElementById('ov-lock'); try{ const a=await api('/analytics?workspace='+encodeURIComponent(WS||'')); - lock.textContent=(LIC&&LIC.is_trial)?'TRIAL':''; + lock.textContent=licTrialActive()?'TRIAL':''; lock.className='pill pill-muted'; const t=a.totals||{},f=a.decay_forecast||{}; if(t.live==null){ @@ -151,19 +151,47 @@ async function loadOverviewAnalytics(){ }else if(hostedFeatureUnavailable(e)){ lock.textContent='PRO'; lock.className='pill pill-muted'; - const used=LIC&&LIC.trial&&LIC.trial.used; - el.innerHTML='
Hosted growth, retention distribution, and decay forecast.
'+(used?'':' ')+'
'; + const offerTrial=licTrialAvailable(); + el.innerHTML='
Hosted growth, retention distribution, and decay forecast.
'+esc(lockReason(false))+'
'+(offerTrial?' ':'')+'
'; }else el.innerHTML='
'+esc(e.message)+'
'; } } +/* ── hosted access state ── + /api/license reports what the control plane said, never what this client guessed: + access_state is one of active | trial | trial_expired | lapsed | inactive, and each one + is a different thing to tell the customer. Reading it here is what stopped a customer + whose trial had ended, and a customer whose card had failed, both being shown a + confident PRO badge over rows of locks with no reason given. */ +function licAccessState(){const s=LIC&&LIC.access_state;return s==='active'||s==='trial'||s==='trial_expired'||s==='lapsed'?s:'inactive'} +function licAccessLive(){const s=licAccessState();return s==='active'||s==='trial'} +function licTrialActive(){return licAccessState()==='trial'} +/* The server refuses a second trial for any organization that already holds an + entitlement, so this is false for every connected customer — trialling, lapsed, or + paying — and the CTA that could only ever return 409 is not drawn. */ +function licTrialAvailable(){return !!(LIC&&LIC.trial&&LIC.trial.available)} +function licPlanName(){const raw=String((LIC&&LIC.plan)||'local').toLowerCase();return raw==='pro'||raw==='team'?raw.toUpperCase():'LOCAL'} +function licTrialEnds(){return fmtDay(LIC&&LIC.trial&&LIC.trial.ends_at)} +function fmtDay(epoch){const n=Number(epoch)||0;if(!(n>0))return '';try{const d=new Date(n*1000);return Number.isFinite(d.getTime())?d.toISOString().slice(0,10):''}catch(e){return ''}} + /* ── shared hosted upgrade / trial CTA ── */ function hostedPlanUrl(plan,trial){const raw=(LIC&&(plan==='team'?LIC.team_upgrade_url:LIC.pro_upgrade_url))||(LIC&&LIC.upgrade_url);const safe=safeUrl(raw);if(!safe||safe==='#')return '#';try{const url=new URL(safe,location.href);if(plan==='pro'||plan==='team')url.searchParams.set('plan',plan);if(trial)url.searchParams.set('trial',plan);return url.href}catch(e){return safe}} -function unlockHtml(feature,plan){const url=hostedPlanUrl(plan),trialUrl=hostedPlanUrl(plan,true),team=plan==='team';const used=LIC&&LIC.trial&&LIC.trial.used;const trial=team?'Start hosted Team trial':'Start hosted Pro trial';const purchase=team?'Purchase Team license':'Purchase Pro license';const price=team?'$20 per seat/month or $200 per seat/year':'$10/month or $100/year';const detail=used?'Your free trial has already been used.':`The email-confirmed, no-card trial lasts exactly ${TRIAL_DAYS} active days.`;const benefits=team?['Everything in Pro','Hosted organizations, invitations, and named seats','Roles, scoped credentials, and Team audit history']:['Hosted Cloud Sync across your installations','Growth, retention, decay, and entity Analytics','Auto Consolidation with hosted retention policies','Auto Dreaming with reviewable managed proposals','Priority support'];return `
ENGRAPHIS ${team?'TEAM':'PRO'}

Unlock ${esc(feature)} and more

Make the local memory engine work across your installations—and keep improving without manual upkeep.

${price}
Your license unlocks
    ${benefits.map(item=>`
  • ${esc(item)}
  • `).join('')}

${detail}

${used?'':`${trial}`}${purchase}
`} +/* Why is this feature locked? One sentence per access state, so the panel never claims a + trial the customer cannot start nor blames billing for a trial that simply ran out. */ +function lockReason(team){const st=licAccessState(),ends=licTrialEnds(); + if(st==='trial')return `Your free trial is live${ends?` until ${esc(ends)}`:''}. ${team?'Team':'Pro'} needs a subscription of its own.`; + if(st==='trial_expired')return `Your free trial has ended${ends?` (${esc(ends)})`:''}, so hosted features are locked. The trial cannot be started again.`; + if(st==='lapsed')return `Your ${esc(licPlanName())} subscription is no longer active, so hosted features are locked until billing is up to date.`; + if(st==='active')return `Your ${esc(licPlanName())} subscription does not include this.`; + if(licTrialAvailable())return `The email-confirmed, no-card trial lasts exactly ${TRIAL_DAYS} active days.`; + return 'Your free trial has already been used.'} +function unlockHtml(feature,plan){const url=hostedPlanUrl(plan),trialUrl=hostedPlanUrl(plan,true),team=plan==='team';const offerTrial=licTrialAvailable();const trial=team?'Start hosted Team trial':'Start hosted Pro trial';const purchase=team?'Purchase Team license':'Purchase Pro license';const price=team?'$20 per seat/month or $200 per seat/year':'$10/month or $100/year';const detail=lockReason(team);const benefits=team?['Everything in Pro','Hosted organizations, invitations, and named seats','Roles, scoped credentials, and Team audit history']:['Hosted Cloud Sync across your installations','Growth, retention, decay, and entity Analytics','Auto Consolidation with hosted retention policies','Auto Dreaming with reviewable managed proposals','Priority support'];return `
ENGRAPHIS ${team?'TEAM':'PRO'}

Unlock ${esc(feature)} and more

Make the local memory engine work across your installations—and keep improving without manual upkeep.

${price}
Your license unlocks
    ${benefits.map(item=>`
  • ${esc(item)}
  • `).join('')}

${detail}

${offerTrial?`${trial}`:''}${purchase}
`} function startTrialPlan(plan){const url=hostedPlanUrl(plan,true);if(url==='#'){toast('Hosted signup URL is not configured','err');return}const link=document.createElement('a');link.href=url;link.target='_blank';link.rel='noopener';link.click()} function startTrial(){return startTrialPlan('pro')} function startTeamTrial(){return startTrialPlan('team')} -function updateLicBadge(){const bd=document.getElementById('lic-badge');if(!bd||!LIC)return;const raw=String(LIC.plan||'local').toLowerCase(),hosted=!!LIC.is_trial||raw==='pro'||raw==='team';bd.textContent=LIC.is_trial?'TRIAL':(hosted?raw.toUpperCase():'LOCAL');bd.className='pill '+(hosted?'pill-accent':'pill-muted')} +/* The badge follows the access state, not the plan name. A plan name alone told a trialist + they were a subscriber, and told a lapsed or expired customer nothing was wrong. */ +function updateLicBadge(){const bd=document.getElementById('lic-badge');if(!bd||!LIC)return;const st=licAccessState(),plan=licPlanName();bd.textContent=st==='trial'?'TRIAL':st==='trial_expired'?'TRIAL ENDED':st==='lapsed'?plan+' INACTIVE':st==='active'?plan:'LOCAL';bd.className='pill '+(licAccessLive()?'pill-accent':'pill-muted')} function updateFeatureLocks(){ const has=f=>LIC&&(LIC.features||[]).includes(f); const apply=(id,feature,label,plan)=>{ @@ -202,10 +230,10 @@ function managedConsentRequired(error){return error&&error.status===409&&error.d the plain-error branch unreachable on the analytics and automation views, which is the regression this comment previously described but the code did not implement. */ function hostedFeatureUnavailable(error){return !!error&&(error.status===402||error.status===501)} -async function loadAnalytics(){const el=document.getElementById('analytics-body'),lock=document.getElementById('an-lock'),acts=document.getElementById('an-actions');el.innerHTML='
';try{const a=await api('/analytics?workspace='+encodeURIComponent(WS||''));setPlanPill(lock,(LIC&&LIC.is_trial)?'TRIAL':'CLOUD','pill pill-accent');showAs(acts,true,'flex');el.innerHTML=renderAnalytics(a,false)}catch(e){if(managedConsentRequired(e)){setPlanPill(lock,'CLOUD','pill pill-accent');showAs(acts,false);el.innerHTML=managedConsentHtml('Analytics')}else if(hostedFeatureUnavailable(e)){setPlanPill(lock,'PRO','pill pill-muted');showAs(acts,false);el.innerHTML=unlockHtml('Analytics','pro')}else{el.innerHTML='
'+esc(e.message)+'
'}}} +async function loadAnalytics(){const el=document.getElementById('analytics-body'),lock=document.getElementById('an-lock'),acts=document.getElementById('an-actions');el.innerHTML='
';try{const a=await api('/analytics?workspace='+encodeURIComponent(WS||''));setPlanPill(lock,licTrialActive()?'TRIAL':'CLOUD','pill pill-accent');showAs(acts,true,'flex');el.innerHTML=renderAnalytics(a,false)}catch(e){if(managedConsentRequired(e)){setPlanPill(lock,'CLOUD','pill pill-accent');showAs(acts,false);el.innerHTML=managedConsentHtml('Analytics')}else if(hostedFeatureUnavailable(e)){setPlanPill(lock,'PRO','pill pill-muted');showAs(acts,false);el.innerHTML=unlockHtml('Analytics','pro')}else{el.innerHTML='
'+esc(e.message)+'
'}}} /* ── hosted automation policy (Pro / Team) ── */ -async function loadAutomation(){const el=document.getElementById('automation-body'),lock=document.getElementById('au-lock'),ws='?workspace='+encodeURIComponent(WS||'');el.innerHTML='
';try{const p=await api('/automation'+ws);setPlanPill(lock,(LIC&&LIC.is_trial)?'TRIAL':'CLOUD','pill pill-accent');const last=p.last_run?fmtRel(p.last_run):'never',dream=p.dream_enabled!=null?p.dream_enabled:p.dream;el.innerHTML=`
Hosted maintenance policy
The cloud returns reviewable proposals. Pinned memories remain protected.
Cloud worker status
Status${p.enabled?'ENABLED':'OFF'}
Last run${esc(last)}
Requesting managed work uploads the selected workspace’s normal and sensitive memory content, excluding secret and session-scoped rows, capped at 16 MiB, over HTTPS without end-to-end encryption. Results are proposals and never automatically write the local database.
`}catch(e){if(managedConsentRequired(e)){setPlanPill(lock,'CLOUD','pill pill-accent');el.innerHTML=managedConsentHtml('Hosted Automation')}else if(hostedFeatureUnavailable(e)){setPlanPill(lock,'PRO','pill pill-muted');el.innerHTML=unlockHtml('Automation, Auto Consolidation, and Auto Dreaming','pro')}else{el.innerHTML='
'+esc(e.message)+'
'}}} +async function loadAutomation(){const el=document.getElementById('automation-body'),lock=document.getElementById('au-lock'),ws='?workspace='+encodeURIComponent(WS||'');el.innerHTML='
';try{const p=await api('/automation'+ws);setPlanPill(lock,licTrialActive()?'TRIAL':'CLOUD','pill pill-accent');const last=p.last_run?fmtRel(p.last_run):'never',dream=p.dream_enabled!=null?p.dream_enabled:p.dream;el.innerHTML=`
Hosted maintenance policy
The cloud returns reviewable proposals. Pinned memories remain protected.
Cloud worker status
Status${p.enabled?'ENABLED':'OFF'}
Last run${esc(last)}
Requesting managed work uploads the selected workspace’s normal and sensitive memory content, excluding secret and session-scoped rows, capped at 16 MiB, over HTTPS without end-to-end encryption. Results are proposals and never automatically write the local database.
`}catch(e){if(managedConsentRequired(e)){setPlanPill(lock,'CLOUD','pill pill-accent');el.innerHTML=managedConsentHtml('Hosted Automation')}else if(hostedFeatureUnavailable(e)){setPlanPill(lock,'PRO','pill pill-muted');el.innerHTML=unlockHtml('Automation, Auto Consolidation, and Auto Dreaming','pro')}else{el.innerHTML='
'+esc(e.message)+'
'}}} async function saveAutomation(){const body={enabled:document.getElementById('au-enabled').checked,cadence_hours:Number(document.getElementById('au-cadence').value)||24,consolidate:document.getElementById('au-consolidate').checked,min_cluster:Number(document.getElementById('au-mincluster').value)||3,archive_below:Number(document.getElementById('au-archive').value)||0.05,dream_enabled:document.getElementById('au-dream').checked,dream_min_new:Number(document.getElementById('au-dream-min').value)||20,dream_idle_minutes:Number(document.getElementById('au-dream-idle').value)};try{await api('/automation?workspace='+encodeURIComponent(WS||''),{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify(body)});toast('Hosted policy saved','ok');loadAutomation()}catch(e){if(managedConsentRequired(e)){const result=document.getElementById('au-result');if(result)result.innerHTML=managedConsentHtml('Hosted Automation');toast('Connect this installation to Engraphis Cloud to use managed compute','err');return}toast((e.status===402||e.status===501)?'Hosted Automation requires Pro or Team':e.message,'err')}} async function runMaintenance(){const el=document.getElementById('au-result');if(el)el.innerHTML='
';try{const d=await api('/maintenance/run?workspace='+encodeURIComponent(WS||''),{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({dry_run:true})});if(el)el.innerHTML=`PROPOSAL Hosted work was submitted for review.
${esc(JSON.stringify(d,null,2))}
`;toast('Managed proposal requested','ok')}catch(e){if(el)el.innerHTML=managedConsentRequired(e)?managedConsentHtml('Hosted Automation'):'
'+esc(e.message)+'
';toast(managedConsentRequired(e)?'Connect this installation to Engraphis Cloud to use managed compute':((e.status===402||e.status===501)?'Hosted Automation requires Pro or Team':e.message),'err')}} @@ -428,29 +456,50 @@ window.addEventListener('beforeunload',e=>{if(!editorIsDirty())return;e.preventD document.addEventListener('keydown',e=>{if((e.ctrlKey||e.metaKey)&&e.key.toLowerCase()==='s'&&document.getElementById('view-mem-editor').classList.contains('active')){e.preventDefault();edSave()}}); /* license */ async function loadLicense(){const el=document.getElementById('lic-body');try{const d=await api('/license');LIC=d;updateLicBadge();updateFeatureLocks();renderLicense(d)}catch(e){if(el)el.innerHTML='
'+esc(e.message)+'
'}} +/* Copy for the control plane's own entitlement status, when it named one. This is what + separates "your card was declined" from "you cancelled" inside a single lapsed state. */ +const LIC_STATUS_NOTE={past_due:'the last payment did not go through',canceled:'the subscription was cancelled',expired:'the billing period ended',revoked:'access was revoked'}; +const LIC_SOURCE_LABEL={environment:'operator override',session:'cloud handshake',cloud:'cloud entitlements read',connected:'not yet confirmed',local:'not connected',override:'operator override'}; +/* The whole point of the panel: when hosted features are locked, say why, and offer the + one action that fixes it. Never a plan badge over unexplained locks. */ +function licStateBanner(state,plan,ends,status){ + if(state==='trial_expired')return `
Your free trial has ended${ends?' on '+esc(ends):''}Hosted features are locked. Everything you have written is still in your local database and still fully usable — only the cloud capabilities stopped. The free trial runs once per account and cannot be started again, so restoring them means subscribing.
`; + if(state==='lapsed'){const note=LIC_STATUS_NOTE[status];return `
Your ${esc(plan||'hosted')} subscription is no longer active${note?esc(note.charAt(0).toUpperCase()+note.slice(1))+', so hosted':'Hosted'} features are locked until billing is up to date. Your local memories are unaffected. Open the account portal to restore access.
`} + if(state==='inactive')return `
No hosted plan on this installationThe local memory engine is free and complete on its own. Cloud Sync, Analytics, Automation, and Team administration run in Engraphis Cloud.
`; + return ''} +function licActionsHtml(state){ + if(licTrialAvailable())return `
`; + const buy=state==='trial_expired',bill=state==='lapsed'; + const primary=bill?'Update billing':buy?'Subscribe to Pro':'Open Pro Cloud'; + const secondary=bill?'Open account portal':buy?'Subscribe to Team':'Open Team Cloud'; + return ``} function renderLicense(d){ const el=document.getElementById('lic-body');if(!el)return; - const raw=String(d.plan||'local').toLowerCase(),trial=!!d.is_trial; - const hosted=trial||raw==='pro'||raw==='team'; - const label=trial?(raw==='team'?'TEAM TRIAL':'PRO TRIAL'):(hosted?raw.toUpperCase():'LOCAL CORE'); + const state=licAccessState(),raw=String(d.plan||'local').toLowerCase(); + const plan=raw==='pro'||raw==='team'?raw.toUpperCase():''; + const hosted=state!=='inactive',live=licAccessLive(),ends=licTrialEnds(); + const label=state==='trial'?(plan||'PRO')+' TRIAL':state==='trial_expired'?(plan||'PRO')+' TRIAL ENDED':state==='lapsed'?plan+' INACTIVE':state==='active'?plan:'LOCAL CORE'; const known=d.known_features||{}; const feats=hosted?Object.keys(known).map(f=>`${(d.features||[]).includes(f)?'✓':'○'} ${esc(known[f])}`).join(''):''; - const used=!!(d.trial&&d.trial.used); - let h=`
${hosted?'Hosted plan':'Local runtime'}${esc(label)}
`; + let h=`
${hosted?'Hosted plan':'Local runtime'}${esc(label)}
`; if(d.error)h+=`
Hosted authorization unavailable — ${esc(d.error)}
`; + h+=licStateBanner(state,plan,ends,d.entitlement_status); if(hosted&&d.email&&d.email!=='trial')h+=`
Hosted account${esc(d.email)}
`; - if(hosted&&d.expires)h+=`
${trial?'Trial ends':'Authorization expires'}${new Date(d.expires*1000).toISOString().slice(0,10)}
`; + if(state==='trial'&&ends)h+=`
Trial ends${esc(ends)}
`; + else if(hosted&&d.expires)h+=`
Authorization expires${esc(fmtDay(d.expires))}
`; if(feats)h+=`
${feats}
`; + /* Support diagnostics: which rule produced this answer and when the cloud last confirmed + it. Emitted by /api/license since the plan resolver landed, and never shown until now — + so "the dashboard says PRO" and "the cloud says PRO" could not be told apart. */ + if(d.plan_source)h+=`
Plan source${esc(LIC_SOURCE_LABEL[d.plan_source]||d.plan_source)}${d.plan_checked_at?' · confirmed '+esc(fmtRel(d.plan_checked_at)):''}
`; h+=`
The local core remains free. Pro and Team capabilities execute in Engraphis Cloud. The email-confirmed, no-card trial lasts exactly ${TRIAL_DAYS} active days; local-only write grace is separate, capped at 24 hours, and never extends cloud access.
`; - h+=hosted||used - ?`` - :`
`; + h+=licActionsHtml(state); el.innerHTML=h; } async function exportWorkspace(){try{const d=await api('/export?workspace='+encodeURIComponent(WS||''));const blob=new Blob([JSON.stringify(d,null,2)],{type:'application/json'});const a=document.createElement('a');a.href=URL.createObjectURL(blob);a.download='engraphis-export-'+Date.now()+'.json';a.click();URL.revokeObjectURL(a.href);toast('Exported','ok')}catch(e){toast(e.message,'err')}} /* Hosted Team is a service CTA; local identity and seat administration are not shipped. */ -async function loadTeam(){const el=document.getElementById('team-body');let url=hostedPlanUrl('team');try{const st=await api('/auth/state');if(url==='#'&&st&&st.cloud_url)url=safeUrl(st.cloud_url)}catch(e){}let trialUrl=url;if(url!=='#')try{const parsed=new URL(url,location.href);parsed.searchParams.set('trial','team');trialUrl=parsed.href}catch(e){}el.innerHTML=`
Engraphis Team Cloud HOSTED
Organizations, invitations, roles, named seats, scoped device credentials, and team audit run on the private hosted service. This local dashboard is intentionally single-user.
The email-confirmed trial lasts exactly ${TRIAL_DAYS} active days. A separate local-only write grace is capped at 24 hours and never extends Team or other cloud access.
`} +async function loadTeam(){const el=document.getElementById('team-body');let url=hostedPlanUrl('team');try{const st=await api('/auth/state');if(url==='#'&&st&&st.cloud_url)url=safeUrl(st.cloud_url)}catch(e){}let trialUrl=url;if(url!=='#')try{const parsed=new URL(url,location.href);parsed.searchParams.set('trial','team');trialUrl=parsed.href}catch(e){}el.innerHTML=`
Engraphis Team Cloud HOSTED
Organizations, invitations, roles, named seats, scoped device credentials, and team audit run on the private hosted service. This local dashboard is intentionally single-user.
${esc(lockReason(true))} A separate local-only write grace is capped at 24 hours and never extends Team or other cloud access.
${licTrialAvailable()?`Start hosted Team trial`:''}Open Team Cloud
`} /* health + settings */ function connectionContext(){const host=(location.hostname||'').toLowerCase();return host==='localhost'||host==='127.0.0.1'||host==='::1'||host.endsWith('.localhost')?'Local engine':'Remote customer node'} async function checkHealth(){const label=connectionContext();try{await api('/health');const d=document.getElementById('health-dot'),t=document.getElementById('health-text');if(d){d.classList.add('health-ok');d.classList.remove('health-error')}if(t)t.textContent=label+' connected'}catch(e){const d=document.getElementById('health-dot'),t=document.getElementById('health-text');if(d){d.classList.add('health-error');d.classList.remove('health-ok')}if(t)t.textContent=label+' unavailable'}} diff --git a/tests/test_client_launch.py b/tests/test_client_launch.py index b65d4bf..9f0f962 100644 --- a/tests/test_client_launch.py +++ b/tests/test_client_launch.py @@ -424,9 +424,14 @@ def test_license_route_emits_every_field_the_dashboard_reads(monkeypatch) -> Non payload = v2_api.get_license() for field in ("plan", "features", "known_features", "is_trial", "trial", + "access_state", "entitlement_status", "upgrade_url", "pro_upgrade_url", "team_upgrade_url"): assert field in payload, field - assert "used" in payload["trial"] + # ``used`` gates every "Start your free trial" affordance; ``available`` is what stops + # one being offered to a customer the control plane will answer 409 for; ``active`` and + # ``ends_at`` are what let the panel name a live trial and its boundary. + for field in ("used", "active", "available", "ends_at", "trial_days"): + assert field in payload["trial"], field # Pro and Team bill through separate checkout targets. assert payload["pro_upgrade_url"] and payload["team_upgrade_url"] # Every advertised key must be renderable, and every grantable key advertised. diff --git a/tests/test_dashboard_auth_placement.py b/tests/test_dashboard_auth_placement.py index fbcf0d6..e4c6063 100644 --- a/tests/test_dashboard_auth_placement.py +++ b/tests/test_dashboard_auth_placement.py @@ -93,6 +93,11 @@ def test_hosted_views_delegate_entitlement_to_cloud_proxy_responses(): # regression it guards (409 folded into ``hostedFeatureUnavailable``) kept every string # these files already assert on, and only a run can tell which branch actually won. _ROUTED_FUNCTIONS = ( + # The access-state readers the panel copy is now derived from. They are bundled as the + # real shipped functions rather than stubbed, so "does this customer get offered a + # trial" is answered here by the code that answers it in the browser. + "licAccessState", "licAccessLive", "licTrialActive", "licTrialAvailable", + "licPlanName", "licTrialEnds", "fmtDay", "lockReason", "hostedPlanUrl", "unlockHtml", "managedConsentHtml", "managedConsentRequired", "hostedFeatureUnavailable", "loadAnalytics", "loadAutomation", @@ -115,9 +120,15 @@ def test_hosted_views_delegate_entitlement_to_cloud_proxy_responses(): function toast(){} const TRIAL_DAYS = 3, WS = 'workspace'; let CURRENT_VIEW = 'overview'; -const LIC = {pro_upgrade_url:'https://engraphis.com/pricing', +// The default is an unconnected installation: no hosted plan, unspent trial, and the +// control plane says a trial may still be started. A case can replace ``access_state`` and +// ``trial`` to model a trialist, a spent trial, a paying customer, or a lapsed one. +const LIC_BASE = {pro_upgrade_url:'https://engraphis.com/pricing', team_upgrade_url:'https://engraphis.com/pricing?plan=team', - upgrade_url:'https://engraphis.com/pricing', trial:{used:false}}; + upgrade_url:'https://engraphis.com/pricing', + plan:'local', access_state:'inactive', + trial:{used:false, active:false, available:true, ends_at:0}}; +let LIC = LIC_BASE; const location = {href:'https://127.0.0.1:8077/'}; let THROWN = null; async function api(){if(THROWN) throw THROWN; return {}} @@ -129,6 +140,7 @@ def test_hosted_views_delegate_entitlement_to_cloud_proxy_responses(): const out = []; for (const c of CASES) { THROWN = Object.assign(new Error(c.message || 'request failed'), c.error); + LIC = Object.assign({}, LIC_BASE, c.lic || {}); CURRENT_VIEW = c.view; for (const key of Object.keys(NODES)) delete NODES[key]; await (c.view === 'analytics' ? loadAnalytics() : loadAutomation()); @@ -222,6 +234,43 @@ def test_a_genuine_entitlement_failure_still_renders_the_upgrade_panel( assert rendered["pill"] == "PRO" +@pytest.mark.skipif(shutil.which("node") is None, reason="node is required to run the UI") +@pytest.mark.parametrize("view", ["analytics", "automation"]) +@pytest.mark.parametrize("state,reason", [ + ("trial", "Your free trial is live"), + ("trial_expired", "Your free trial has ended"), + ("lapsed", "no longer active"), + ("active", "does not include this"), +]) +def test_the_upgrade_panel_never_offers_a_trial_the_server_would_refuse( + tmp_path, view, state, reason, +): + """``start_trial`` refuses every organization that already holds an entitlement. + + ``trial.used`` was hardcoded false by ``/api/license``, so this panel offered "Start + hosted Pro trial" to every connected customer forever — a trialist mid-trial, a + customer whose trial had already been spent, and an active subscriber alike. All three + got a 409 from the control plane for clicking it. The panel now says which of those + four situations the customer is actually in, and only sells what is buyable. + """ + + rendered = _route(tmp_path, [{ + "name": "gated", "view": view, "error": {"status": 402}, + "lic": { + "plan": "pro", "access_state": state, + "trial": {"used": state != "active", "active": state == "trial", + "available": False, "ends_at": 1785240000}, + }, + }])["gated"] + + assert 'class="upgrade-panel"' in rendered["html"] + # The one thing that must always still be offered. + assert "Purchase Pro license" in rendered["html"] + # And the one thing that must not. + assert "Start hosted Pro trial" not in rendered["html"] + assert reason in rendered["html"] + + @pytest.mark.skipif(shutil.which("node") is None, reason="node is required to run the UI") @pytest.mark.parametrize("view", ["analytics", "automation"]) @pytest.mark.parametrize("status", [400, 401, 500, 503]) diff --git a/tests/test_hosted_plan_resolution.py b/tests/test_hosted_plan_resolution.py index 8f0b6ae..063bd6c 100644 --- a/tests/test_hosted_plan_resolution.py +++ b/tests/test_hosted_plan_resolution.py @@ -22,6 +22,7 @@ from __future__ import annotations import ast +import calendar import io import json import os @@ -56,21 +57,47 @@ "pro": ["analytics", "automation", "sync"], "team": ["analytics", "automation", "sync", "team"], } +# The trial disclosure this client now depends on, mirrored from (read-only) +# engraphis-cloud ``EntitlementDTO`` and ``DeviceRegistrationResponse``. Both surfaces +# carry the same names on purpose. Renaming any of them server-side reverts this client to +# "not a trial, none consumed" in silence -- which is precisely the state this suite exists +# to keep it out of -- so the drift has to fail here instead. +SERVER_TRIAL_FIELDS = ("status", "is_trial", "trial_consumed", "trial_ends_at") + + +#: A three-day trial that is still running, and one that is not, as the control plane +#: serializes them (``engraphis-cloud`` ``EntitlementDTO``; Pydantic emits a trailing ``Z`` +#: for UTC, which this client's Python 3.9 floor cannot hand straight to +#: ``datetime.fromisoformat``). +TRIAL_ENDS_AT = "2026-07-28T12:00:00Z" + + +def _epoch(iso: str) -> float: + """Independent reference conversion, so the assertions do not use the code under test.""" + + return calendar.timegm(time.strptime(iso.rstrip("Zz"), "%Y-%m-%dT%H:%M:%S")) def _entitlement_dto(plan: str, *, active: bool = True, - organization_id: str = ORGANIZATION) -> dict: + organization_id: str = ORGANIZATION, + is_trial: bool = False, trial_consumed: bool = False, + status: str = "") -> dict: return { "organization_id": organization_id, "entitlement_id": "ent_1", "plan": plan, - "status": "active" if active else "past_due", + "status": status or ("trialing" if is_trial and active + else "active" if active else "past_due"), "cloud_access_active": active, "cloud_features": SERVER_PLAN_FEATURES[plan] if active else [], "seat_limit": 5, "seat_assignment_basis": "named_members", "starts_at": "2026-01-01T00:00:00Z", "expires_at": None, + "is_trial": is_trial, + "trial_consumed": trial_consumed or is_trial, + "trial_duration_seconds": 259_200 if is_trial else None, + "trial_ends_at": TRIAL_ENDS_AT if is_trial else None, "version": 3, } @@ -1542,7 +1569,338 @@ def test_a_replaced_hosted_plan_still_overrides_the_resolved_entitlement( assert "team" in upgraded["features"] -# ── (7) the shipped modules must still build on the supported floor ─────────── +# ── (7) the trial the control plane owns, rendered by the client that never read it ── +# +# ``/api/license`` hardcoded ``"is_trial": False`` and ``"trial": {"used": False, ...}``. +# Those were the only assignments in the file, which made two customer-visible states +# unreachable and one permanently wrong: +# +# * the dashboard's ``'TRIAL'`` badge branch could never be taken, so a trialist saw the +# same confident PRO/TEAM badge a subscriber sees; +# * ``trial.used`` never became true, so "Start hosted Pro/Team trial" was offered to +# everyone forever - including paying subscribers and customers whose trial was already +# spent, both of whom the control plane answers ``TrialAlreadyConsumedError`` for; and +# * ``cloud_access_active`` was computed, returned, and rendered nowhere, so a lapsed or +# expired customer got a PRO badge with every feature row locked and no explanation. + + +def test_a_live_trial_is_reported_as_a_trial(monkeypatch) -> None: + """The badge branch the dashboard has always had, finally reachable.""" + + _connect(monkeypatch) + _serve(monkeypatch, _FakeControlPlane(_entitlement_dto("pro", is_trial=True))) + + payload = _settled_license(monkeypatch) + + assert payload["is_trial"] is True + assert payload["access_state"] == "trial" + assert payload["entitlement_status"] == "trialing" + assert payload["cloud_access_active"] is True + assert payload["trial"]["active"] is True + assert payload["trial"]["used"] is True + assert payload["trial"]["ends_at"] == pytest.approx( + _epoch(TRIAL_ENDS_AT) + ) + # A live trial is not an offer to start another one. + assert payload["trial"]["available"] is False + # A trialist still has the paid feature set while the trial runs. + assert set(payload["features"]) >= {"analytics", "automation"} + + +def test_a_spent_trial_is_told_apart_from_a_lapsed_subscription(monkeypatch) -> None: + """Both read ``cloud_access_active=false``; only ``is_trial`` separates the copy.""" + + _connect(monkeypatch) + _serve( + monkeypatch, + _FakeControlPlane(_entitlement_dto("pro", active=False, is_trial=True)), + ) + + payload = _settled_license(monkeypatch) + + assert payload["access_state"] == "trial_expired" + assert payload["is_trial"] is True + assert payload["trial"]["used"] is True + assert payload["trial"]["active"] is False + assert payload["trial"]["available"] is False + assert payload["features"] == [] + + +def test_a_lapsed_subscription_is_never_offered_another_trial(monkeypatch) -> None: + """A customer whose subscription stopped needs billing, not a 409 from the server.""" + + _connect(monkeypatch) + _serve( + monkeypatch, + _FakeControlPlane( + _entitlement_dto("team", active=False, trial_consumed=True) + ), + ) + + payload = _settled_license(monkeypatch) + + assert payload["access_state"] == "lapsed" + assert payload["is_trial"] is False + assert payload["trial"]["available"] is False + assert payload["plan"] == "team" + assert payload["features"] == [] + + +def test_a_paying_customer_is_never_offered_a_trial(monkeypatch) -> None: + """``start_trial`` refuses any organization that already holds an entitlement. + + That includes a customer who bought outright and never trialled, so the offer has to + be suppressed by the *connection*, not only by ``trial_consumed``. + """ + + _connect(monkeypatch) + _serve(monkeypatch, _FakeControlPlane(_entitlement_dto("team"))) + + payload = _settled_license(monkeypatch) + + assert payload["access_state"] == "active" + assert payload["is_trial"] is False + assert payload["trial"]["used"] is False + assert payload["trial"]["available"] is False + # No trial boundary is replayed at a paying customer. + assert payload["trial"]["ends_at"] == 0.0 + + +def test_an_unconnected_installation_is_the_one_place_a_trial_is_offered() -> None: + """The acquisition CTA must survive: an installation with no organization can trial.""" + + payload = v2_api.get_license() + + assert payload["plan"] == "local" + assert payload["access_state"] == "inactive" + assert payload["trial"]["available"] is True + assert payload["trial"]["used"] is False + + +def test_a_connected_but_unanswered_installation_offers_no_trial(monkeypatch) -> None: + """First boot after onboarding: the plan is inferred, the trial must not be. + + A connected installation always belongs to an organization, and that organization is + trialling, has spent its trial, or is paying. Guessing "no trial consumed" here is how + the button that can only return 409 gets drawn during the one window nothing has + answered yet. + """ + + monkeypatch.delenv("ENGRAPHIS_CLOUD_CONTROL_URL", raising=False) + monkeypatch.setattr(cloud_session, "configured", lambda **kw: True) + monkeypatch.setattr(v2_api, "_session_entitlement", dict) + monkeypatch.setattr(v2_api, "_read_entitlement_cache", dict) + + payload = v2_api.get_license() + + assert payload["plan"] == "pro" + assert payload["plan_source"] == "connected" + assert payload["trial"]["available"] is False + assert payload["trial"]["used"] is True + + +def test_the_trial_arrives_on_the_handshake_the_client_already_makes(monkeypatch) -> None: + """The primary path: no extra request, correct on the first boot after onboarding.""" + + _connect(monkeypatch, pinned_token=False) + cloud = _FakeControlPlane(registration={ + "plan": "team", + "cloud_access_active": True, + "cloud_features": SERVER_PLAN_FEATURES["team"], + "status": "trialing", + "is_trial": True, + "trial_consumed": True, + "trial_ends_at": TRIAL_ENDS_AT, + }) + _serve(monkeypatch, cloud) + + payload = _settled_license(monkeypatch) + + assert payload["plan_source"] == "session" + assert payload["access_state"] == "trial" + assert payload["trial"]["ends_at"] == pytest.approx(_epoch(TRIAL_ENDS_AT)) + # Nothing dialled the entitlements route: the handshake already answered. + assert _entitlement_reads(cloud) == [] + + +def test_a_billing_denial_turns_a_running_trial_into_an_expired_one(monkeypatch) -> None: + """A 402 is authoritative. The trial facts survive it; the stale status does not.""" + + _connect(monkeypatch, pinned_token=False) + cloud = _FakeControlPlane(registration={ + "plan": "pro", + "cloud_access_active": True, + "cloud_features": SERVER_PLAN_FEATURES["pro"], + "status": "trialing", + "is_trial": True, + "trial_consumed": True, + "trial_ends_at": TRIAL_ENDS_AT, + }) + _serve(monkeypatch, cloud) + assert _settled_license(monkeypatch)["access_state"] == "trial" + + assert cloud_session.record_billing_denial() is True + payload = v2_api.get_license() + + assert payload["access_state"] == "trial_expired" + assert payload["is_trial"] is True + assert payload["trial"]["used"] is True + assert payload["trial"]["available"] is False + assert payload["features"] == [] + # The last status the cloud named now contradicts the denial and is not rendered. + assert payload["entitlement_status"] == "" + + +def test_a_control_plane_without_the_trial_fields_claims_no_trial(monkeypatch) -> None: + """An older control plane omits them; the client must not invent a trial.""" + + _connect(monkeypatch) + legacy = _entitlement_dto("pro") + for field in ("is_trial", "trial_consumed", "trial_duration_seconds", + "trial_ends_at", "status"): + legacy.pop(field) + _serve(monkeypatch, _FakeControlPlane(legacy)) + + payload = _settled_license(monkeypatch) + + assert payload["plan"] == "pro" + assert payload["is_trial"] is False + assert payload["access_state"] == "active" + assert payload["entitlement_status"] == "" + assert payload["trial"]["ends_at"] == 0.0 + + +def test_the_trial_disclosure_survives_a_restart(monkeypatch, tmp_path) -> None: + """The compatibility cache round trips the trial through its own parser.""" + + monkeypatch.setenv("ENGRAPHIS_STATE_DIR", str(tmp_path)) + _connect(monkeypatch) + _serve( + monkeypatch, + _FakeControlPlane(_entitlement_dto("team", is_trial=True)), + ) + assert _settled_license(monkeypatch)["access_state"] == "trial" + + reread = v2_api._read_entitlement_cache() + + assert reread["is_trial"] is True + assert reread["trial_consumed"] is True + assert reread["status"] == "trialing" + assert reread["trial_ends_at"] == pytest.approx(_epoch(TRIAL_ENDS_AT)) + + +@pytest.mark.parametrize("value", [ + "2026-07-28T12:00:00Z", + "2026-07-28T12:00:00z", + "2026-07-28T12:00:00+00:00", +]) +def test_the_servers_utc_timestamp_is_read_on_the_python_39_floor(value) -> None: + """``datetime.fromisoformat`` on 3.9 rejects the ``Z`` Pydantic emits for UTC.""" + + assert v2_api._epoch_seconds(value) == pytest.approx(_epoch(TRIAL_ENDS_AT)) + + +@pytest.mark.parametrize("value", [ + None, "", " ", "not-a-date", 0, -1, True, [], {}, "2026-13-45T99:99:99Z", +]) +def test_an_unreadable_trial_boundary_is_unknown_rather_than_raising(value) -> None: + """This runs on the ``/api/bootstrap`` boot path; nothing here may raise.""" + + assert v2_api._epoch_seconds(value) == 0.0 + + +def test_a_forged_entitlement_status_is_not_rendered() -> None: + """Only the control plane's own status vocabulary reaches the panel's copy.""" + + assert v2_api._normalized_status("PAST_DUE") == "past_due" + for value in ("", None, 7, "your account is fine", "active"): + assert v2_api._normalized_status(value) == "" + + +def test_every_access_state_the_dashboard_renders_is_one_the_client_can_produce() -> None: + """Close the loop on the shipped JS: an unhandled state would render as a blank badge.""" + + script = DASHBOARD_JS.read_text(encoding="utf-8") + block = script[script.index("function licAccessState()"):] + handled = set(re.findall(r"s==='([a-z_]+)'", block[:block.index("\n")])) + + assert handled | {"inactive"} == set(v2_api._ACCESS_STATES) + + produced = set() + for plan in ("local", "pro", "team"): + for active in (True, False): + for is_trial in (True, False): + produced.add(v2_api._access_state({ + "plan": plan, "cloud_access_active": active, "is_trial": is_trial, + })) + assert produced == set(v2_api._ACCESS_STATES) + + +def test_the_dashboard_never_offers_a_trial_it_was_not_told_is_available() -> None: + """The one gate on every "Start trial" affordance in the shipped asset. + + ``trial.used`` was hardcoded false, so every one of these drew a button whose only + outcome, for a connected customer, was a ``TrialAlreadyConsumedError``. + """ + + script = DASHBOARD_JS.read_text(encoding="utf-8") + + assert "function licTrialAvailable(){return !!(LIC&&LIC.trial&&LIC.trial.available)}" \ + in script + # No affordance may still be gated on the old always-false flag. + assert "LIC.trial.used" not in script + for marker in ("Start hosted Pro trial", "Start hosted Team trial", + "Start exactly '+TRIAL_DAYS+' days free"): + index = script.index(marker) + window = script[max(0, index - 400):index] + assert "licTrialAvailable()" in window, marker + + +def test_the_dashboard_explains_a_locked_state_instead_of_badging_it() -> None: + """A PRO badge over rows of locks with no reason given is the defect itself.""" + + script = DASHBOARD_JS.read_text(encoding="utf-8") + banner = script[script.index("function licStateBanner("):] + banner = banner[:banner.index("\nfunction licActionsHtml")] + + for state in ("trial_expired", "lapsed", "inactive"): + assert "state==='%s'" % state in banner, state + # Each locked state says what happened and what is still safe. + assert "free trial has ended" in banner + assert "no longer active" in banner + assert "local database" in banner + # And the badge itself follows the access state, not the plan name alone. + assert "function updateLicBadge()" in script + badge = script[script.index("function updateLicBadge()"):] + badge = badge[:badge.index("\n")] + assert "licAccessState()" in badge + assert "TRIAL ENDED" in badge and "INACTIVE" in badge + + +def test_both_persisted_answers_read_every_trial_field_the_server_sends() -> None: + """One vocabulary across the handshake, the entitlements read, and the cache.""" + + resolver = (REPO_ROOT / "engraphis" / "routes" / "v2_api.py").read_text( + encoding="utf-8" + ) + session = (REPO_ROOT / "engraphis" / "cloud_session.py").read_text(encoding="utf-8") + + for field in SERVER_TRIAL_FIELDS: + assert '"%s"' % field in resolver, "the resolver ignores %s" % field + assert '"%s"' % field in session, "the session record drops %s" % field + + +def test_the_plan_source_diagnostic_is_finally_rendered() -> None: + """``plan_source``/``plan_checked_at`` were emitted for support and shown nowhere.""" + + script = DASHBOARD_JS.read_text(encoding="utf-8") + + assert "d.plan_source" in script + assert "d.plan_checked_at" in script + assert "LIC_SOURCE_LABEL" in script + + +# ── (8) the shipped modules must still build on the supported floor ─────────── @pytest.mark.parametrize("relative", [ "engraphis/routes/v2_api.py", "engraphis/routes/memory.py", From af9db7cf4f3d6caca6b28008c07ad10462f074a2 Mon Sep 17 00:00:00 2001 From: Jaixii Date: Sun, 26 Jul 2026 19:50:27 -0400 Subject: [PATCH 31/82] fix(connect): honor cloud-assigned compute endpoints --- engraphis/cloud_session.py | 52 +++++++++- engraphis/device_connect.py | 56 +++++++++- tests/test_cloud_session.py | 196 +++++++++++++++++++++++++++++++++++ tests/test_device_connect.py | 41 ++++++++ 4 files changed, 337 insertions(+), 8 deletions(-) diff --git a/engraphis/cloud_session.py b/engraphis/cloud_session.py index 01ab17e..9096309 100644 --- a/engraphis/cloud_session.py +++ b/engraphis/cloud_session.py @@ -75,6 +75,21 @@ def _reachable_cloud_base_url(value: str) -> str: raise CloudSessionError("Engraphis Cloud is temporarily unreachable.") from exc +def _server_compute_url(response: dict) -> str: + """Return the refresh response's compute endpoint only when it is safe to persist.""" + + value = response.get("compute_url") + if not isinstance(value, str) or not value.strip(): + return "" + try: + return validate_cloud_base_url(value) + except (CloudUrlUnresolved, ValueError): + # This optional field cannot be allowed to clear or poison a known-good endpoint. + # The rotated credential is still persisted below, so a later valid response can + # repair a session whose compute endpoint was not supplied yet. + return "" + + def _session_path() -> Path: root = os.environ.get("ENGRAPHIS_STATE_DIR", "").strip() base = Path(root).expanduser() if root else Path.home() / ".engraphis" @@ -455,7 +470,8 @@ def record_billing_denial() -> bool: def save_bootstrap(response: dict, *, control_url: str, - compute_url: Optional[str] = None) -> None: + compute_url: Optional[str] = None, + compute_url_source: Optional[str] = None) -> None: """Persist the one-time bootstrap/refresh material returned by the control plane.""" refresh = str(response.get("refresh_credential") or "").strip() @@ -476,6 +492,11 @@ def save_bootstrap(response: dict, *, control_url: str, response.get("token_subject") or "member" ), } + if compute_url_source in {"explicit", "server", "fallback"}: + # Keep an explicit CLI choice distinct from a server/distribution default. A + # refresh may move cloud-assigned endpoints, but must never silently replace an + # endpoint the operator deliberately selected. + value["compute_url_source"] = compute_url_source # Whatever entitlement the control plane volunteered, so the dashboard knows the plan # from the first boot instead of inferring it. Absent on an older cloud; harmless. value.update(_declared_entitlement(response)) @@ -611,7 +632,9 @@ def access_for_workspace( # response; a stale home-directory mount yields a structured, retryable error from # ``_load`` rather than an unhandled filesystem exception. The authoritative session # record is still loaded again under the lock below before any credential is used. - if not configured(require_compute=require_compute): + # A refresh can now supply a missing compute endpoint, so do not reject a valid saved + # control/refresh session before it has a chance to receive that authoritative value. + if not configured(require_compute=False): raise CloudSessionError( "Connect this installation to Engraphis Cloud first.", status=401 ) @@ -627,8 +650,18 @@ def access_for_workspace( ).strip() control = os.environ.get("ENGRAPHIS_CLOUD_CONTROL_URL", "").strip() control = control or str(saved.get("control_url") or "").strip() - compute = direct_compute or str(saved.get("compute_url") or "").strip() - if not refresh or not control or (require_compute and not compute): + saved_compute = str(saved.get("compute_url") or "").strip() + compute = direct_compute or saved_compute + compute_source = "explicit" if direct_compute else str( + saved.get("compute_url_source") or "" + ) + if saved_compute and compute_source not in {"explicit", "server", "fallback"}: + # Pre-source sessions cannot tell a cloud-assigned endpoint from a CLI/env + # override. Preserve the nonempty value rather than silently moving a + # potentially operator-selected endpoint; compute-less legacy sessions still + # accept a vetted response below. + compute_source = "explicit" + if not refresh or not control: raise CloudSessionError( "Connect this installation to Engraphis Cloud first.", status=401 ) @@ -646,6 +679,10 @@ def access_for_workspace( response_subject = _validated_token_subject( body.get("token_subject") or token_subject ) + server_compute = _server_compute_url(body) + if server_compute and compute_source != "explicit": + compute = server_compute + compute_source = "server" updated = dict(saved) updated.update({ "schema": "engraphis-cloud-session/v1", @@ -656,6 +693,8 @@ def access_for_workspace( "refresh_expires_at": str(body.get("refresh_expires_at") or ""), "token_subject": response_subject, }) + if compute_source in {"explicit", "server", "fallback"}: + updated["compute_url_source"] = compute_source # The refresh response carries the same entitlement fields as registration, so the # plan re-confirms itself on every token rotation. An older cloud omits them and # the previously persisted answer (if any) is left untouched. @@ -677,4 +716,9 @@ def access_for_workspace( updated.pop(key, None) updated.update(declared) _save(updated) + if require_compute and not compute: + raise CloudSessionError( + "Engraphis Cloud did not provide a compute endpoint for this installation.", + status=503, + ) return access, organization_id, compute diff --git a/engraphis/device_connect.py b/engraphis/device_connect.py index cf50c73..d1a56e1 100644 --- a/engraphis/device_connect.py +++ b/engraphis/device_connect.py @@ -338,6 +338,24 @@ def _validated_control_url(value: str) -> str: ) from exc +def _server_compute_url(response: dict) -> str: + """Return a vetted compute endpoint volunteered by the control plane, if any. + + ``compute_url`` is endpoint metadata, not a redirect target: the registration body is + untrusted until it passes the same HTTPS, public-host, and DNS-rebinding validation as + configured endpoints. A bad or temporarily unresolvable optional value must not erase + a valid manifest fallback after the one-time token was spent. + """ + + value = response.get("compute_url") + if not isinstance(value, str) or not value.strip(): + return "" + try: + return validate_cloud_base_url(value) + except (CloudUrlUnresolved, ValueError): + return "" + + def _default_device_name() -> str: try: name = socket.gethostname().strip() @@ -571,9 +589,14 @@ def connect(token: object, *, control_url: Optional[str] = None, resolved_control = _validated_control_url( control_url if control_url is not None else default_control_url() ) - resolved_compute = ( - compute_url if compute_url is not None else default_compute_url(resolved_control) - ) + cli_compute = str(compute_url or "").strip() + environment_compute = os.environ.get("ENGRAPHIS_CLOUD_COMPUTE_URL", "").strip() + has_explicit_compute = bool(cli_compute or environment_compute) + resolved_compute = cli_compute or environment_compute + # The shipped manifest/default remains a fallback, not an authority over a value the + # control plane returns for this installation. Validate it before redeeming the + # single-use token, then let a separately validated server value supersede it below. + fallback_compute = "" if has_explicit_compute else default_compute_url(resolved_control) if resolved_compute: try: resolved_compute = validate_cloud_base_url(resolved_compute) @@ -587,6 +610,19 @@ def connect(token: object, *, control_url: Optional[str] = None, "The Engraphis Cloud compute URL is not a valid HTTPS endpoint.", status=400, ) from exc + elif fallback_compute: + try: + fallback_compute = validate_cloud_base_url(fallback_compute) + except CloudUrlUnresolved as exc: + raise DeviceConnectError( + "The Engraphis Cloud compute endpoint is temporarily unreachable.", + status=503, + ) from exc + except ValueError as exc: + raise DeviceConnectError( + "The Engraphis Cloud compute URL is not a valid HTTPS endpoint.", + status=400, + ) from exc installation_client_id, device_client_id = client_identity() # Last check before the point of no return. ``client_identity`` may have written its @@ -611,9 +647,21 @@ def connect(token: object, *, control_url: Optional[str] = None, "Try again, and contact support if it repeats.", status=502, ) + server_compute = "" if has_explicit_compute else _server_compute_url(response) + if not has_explicit_compute: + # The response wins for a non-shipped control plane too; otherwise those customers + # can redeem a token but never learn the compute endpoint the cloud assigned them. + resolved_compute = server_compute or fallback_compute + compute_source = ( + "explicit" if has_explicit_compute else "server" if server_compute + else "fallback" if fallback_compute else None + ) try: cloud_session.save_bootstrap( - response, control_url=resolved_control, compute_url=resolved_compute or None + response, + control_url=resolved_control, + compute_url=resolved_compute or None, + compute_url_source=compute_source, ) except cloud_session.CloudSessionError as exc: raise DeviceConnectError(str(exc), status=getattr(exc, "status", 503)) from exc diff --git a/tests/test_cloud_session.py b/tests/test_cloud_session.py index f5ac02e..0c0fedd 100644 --- a/tests/test_cloud_session.py +++ b/tests/test_cloud_session.py @@ -61,6 +61,202 @@ def refresh(control_url, credential, workspace_id, token_subject): assert writes[0]["refresh_credential"] == "rotated-refresh" +def test_refresh_updates_the_saved_compute_endpoint_from_a_valid_response(monkeypatch) -> None: + """The cloud can move a connected installation to a new compute endpoint.""" + + previous = "https://compute-old.example.test" + assigned = "https://compute-new.example.test" + state = { + "control_url": "https://control.example.test", + "compute_url": previous, + "compute_url_source": "server", + "organization_id": "org_1", + "refresh_credential": "old-refresh", + "token_subject": "member", + } + monkeypatch.setattr(cloud_session, "_load", lambda: dict(state)) + monkeypatch.setattr(cloud_session, "_save", lambda value: state.update(value)) + monkeypatch.setattr(cloud_session, "validate_cloud_base_url", lambda value: value.rstrip("/")) + monkeypatch.setattr(cloud_session, "_post_refresh", lambda *_args: { + "access_token": "short-lived-access", + "organization_id": "org_1", + "refresh_credential": "rotated-refresh", + "token_subject": "member", + "compute_url": assigned, + }) + + assert cloud_session.access_for_workspace("ws_client_1") == ( + "short-lived-access", "org_1", assigned, + ) + assert state["compute_url"] == assigned + + +def test_refresh_can_supply_a_missing_compute_endpoint_before_require_compute(monkeypatch) -> None: + """A compute-less saved session must reach the refresh that repairs it.""" + + assigned = "https://compute-new.example.test" + state = { + "control_url": "https://control.example.test", + "compute_url": "", + "organization_id": "org_1", + "refresh_credential": "old-refresh", + "token_subject": "member", + } + monkeypatch.setattr(cloud_session, "_load", lambda: dict(state)) + monkeypatch.setattr(cloud_session, "_save", lambda value: state.update(value)) + monkeypatch.setattr(cloud_session, "validate_cloud_base_url", lambda value: value.rstrip("/")) + monkeypatch.setattr(cloud_session, "_post_refresh", lambda *_args: { + "access_token": "short-lived-access", + "organization_id": "org_1", + "refresh_credential": "rotated-refresh", + "token_subject": "member", + "compute_url": assigned, + }) + + assert cloud_session.access_for_workspace("ws_client_1") == ( + "short-lived-access", "org_1", assigned, + ) + assert state["compute_url"] == assigned + assert state["compute_url_source"] == "server" + assert state["refresh_credential"] == "rotated-refresh" + + +@pytest.mark.parametrize("server_compute", [None, "http://private.example.test"]) +def test_compute_less_refresh_persists_rotation_before_a_structured_compute_error( + monkeypatch, server_compute +) -> None: + """Missing or unsafe endpoint metadata must not roll back the one-time rotation.""" + + state = { + "control_url": "https://control.example.test", + "compute_url": "", + "organization_id": "org_1", + "refresh_credential": "old-refresh", + "token_subject": "member", + } + + def validate(value): + if value == server_compute: + raise ValueError("not an allowed endpoint") + return value.rstrip("/") + + monkeypatch.setattr(cloud_session, "_load", lambda: dict(state)) + monkeypatch.setattr(cloud_session, "_save", lambda value: state.update(value)) + monkeypatch.setattr(cloud_session, "validate_cloud_base_url", validate) + body = { + "access_token": "short-lived-access", + "organization_id": "org_1", + "refresh_credential": "rotated-refresh", + "token_subject": "member", + } + if server_compute is not None: + body["compute_url"] = server_compute + monkeypatch.setattr(cloud_session, "_post_refresh", lambda *_args: body) + + with pytest.raises(cloud_session.CloudSessionError) as caught: + cloud_session.access_for_workspace("ws_client_1") + + assert caught.value.status == 503 + assert state["refresh_credential"] == "rotated-refresh" + assert state["compute_url"] == "" + + +def test_refresh_ignores_an_invalid_compute_endpoint_without_clearing_the_saved_one( + monkeypatch, +) -> None: + """An untrusted response value cannot poison or erase a usable compute endpoint.""" + + previous = "https://compute-old.example.test" + invalid = "http://private.example.test" + state = { + "control_url": "https://control.example.test", + "compute_url": previous, + "organization_id": "org_1", + "refresh_credential": "old-refresh", + "token_subject": "member", + } + + def validate(value): + if value == invalid: + raise ValueError("not an allowed endpoint") + return value.rstrip("/") + + monkeypatch.setattr(cloud_session, "_load", lambda: dict(state)) + monkeypatch.setattr(cloud_session, "_save", lambda value: state.update(value)) + monkeypatch.setattr(cloud_session, "validate_cloud_base_url", validate) + monkeypatch.setattr(cloud_session, "_post_refresh", lambda *_args: { + "access_token": "short-lived-access", + "organization_id": "org_1", + "refresh_credential": "rotated-refresh", + "token_subject": "member", + "compute_url": invalid, + }) + + assert cloud_session.access_for_workspace("ws_client_1") == ( + "short-lived-access", "org_1", previous, + ) + assert state["compute_url"] == previous + + +def test_legacy_nonempty_compute_endpoint_is_preserved_against_a_server_update(monkeypatch) -> None: + """Pre-source sessions may hold an operator override, so keep it conservatively.""" + + previous = "https://legacy-operator-compute.example.test" + assigned = "https://assigned-compute.example.test" + state = { + "control_url": "https://control.example.test", + "compute_url": previous, + "organization_id": "org_1", + "refresh_credential": "old-refresh", + "token_subject": "member", + } + monkeypatch.setattr(cloud_session, "_load", lambda: dict(state)) + monkeypatch.setattr(cloud_session, "_save", lambda value: state.update(value)) + monkeypatch.setattr(cloud_session, "validate_cloud_base_url", lambda value: value.rstrip("/")) + monkeypatch.setattr(cloud_session, "_post_refresh", lambda *_args: { + "access_token": "short-lived-access", + "organization_id": "org_1", + "refresh_credential": "rotated-refresh", + "token_subject": "member", + "compute_url": assigned, + }) + + assert cloud_session.access_for_workspace("ws_client_1") == ( + "short-lived-access", "org_1", previous, + ) + assert state["compute_url"] == previous + assert state["compute_url_source"] == "explicit" + + +def test_refresh_does_not_replace_a_persisted_explicit_compute_override(monkeypatch) -> None: + previous = "https://operator-compute.example.test" + assigned = "https://assigned-compute.example.test" + state = { + "control_url": "https://control.example.test", + "compute_url": previous, + "compute_url_source": "explicit", + "organization_id": "org_1", + "refresh_credential": "old-refresh", + "token_subject": "member", + } + monkeypatch.setattr(cloud_session, "_load", lambda: dict(state)) + monkeypatch.setattr(cloud_session, "_save", lambda value: state.update(value)) + monkeypatch.setattr(cloud_session, "validate_cloud_base_url", lambda value: value.rstrip("/")) + monkeypatch.setattr(cloud_session, "_post_refresh", lambda *_args: { + "access_token": "short-lived-access", + "organization_id": "org_1", + "refresh_credential": "rotated-refresh", + "token_subject": "member", + "compute_url": assigned, + }) + + assert cloud_session.access_for_workspace("ws_client_1") == ( + "short-lived-access", "org_1", previous, + ) + assert state["compute_url"] == previous + assert state["compute_url_source"] == "explicit" + + def test_direct_access_token_path_never_reads_refresh_state(monkeypatch) -> None: monkeypatch.setenv("ENGRAPHIS_CLOUD_ACCESS_TOKEN", "direct-token") monkeypatch.setenv("ENGRAPHIS_CLOUD_ORGANIZATION_ID", "org_direct") diff --git a/tests/test_device_connect.py b/tests/test_device_connect.py index 2d636e9..6568008 100644 --- a/tests/test_device_connect.py +++ b/tests/test_device_connect.py @@ -780,6 +780,47 @@ def test_compute_url_is_taken_from_the_environment(monkeypatch): assert cloud_session.configured() is True +def test_non_shipped_control_plane_uses_its_vetted_compute_url(monkeypatch, tmp_path): + """The connect response, not a shipped-only fallback, configures custom planes.""" + + server_compute = "https://assigned-compute.example.test" + _install_opener(monkeypatch, _Opener(body=dict(REGISTRATION, compute_url=server_compute))) + + summary = device_connect.connect(TOKEN, control_url=CONTROL_URL) + + saved = json.loads((tmp_path / "cloud_session.json").read_text(encoding="utf-8")) + assert summary["compute_url"] == server_compute + assert saved["compute_url"] == server_compute + assert saved["compute_url_source"] == "server" + assert cloud_session.configured() is True + + +@pytest.mark.parametrize("source", ["cli", "environment"]) +def test_explicit_compute_override_outranks_the_connect_response(monkeypatch, source): + """A server cannot replace an operator-selected endpoint during device connect.""" + + server_compute = "https://assigned-compute.example.test" + kwargs = {} + if source == "cli": + kwargs["compute_url"] = COMPUTE_URL + else: + monkeypatch.setenv("ENGRAPHIS_CLOUD_COMPUTE_URL", COMPUTE_URL) + _install_opener(monkeypatch, _Opener(body=dict(REGISTRATION, compute_url=server_compute))) + + summary = device_connect.connect(TOKEN, control_url=CONTROL_URL, **kwargs) + assert summary["compute_url"] == COMPUTE_URL + assert cloud_session._load()["compute_url_source"] == "explicit" + + +def test_empty_cli_compute_value_does_not_suppress_the_connect_response(monkeypatch): + server_compute = "https://assigned-compute.example.test" + _install_opener(monkeypatch, _Opener(body=dict(REGISTRATION, compute_url=server_compute))) + + assert device_connect.connect( + TOKEN, control_url=CONTROL_URL, compute_url="" + )["compute_url"] == server_compute + + def test_control_url_defaults_to_the_shipped_manifest(monkeypatch): from engraphis.commercial import manifest From 8f6e2842a10a3c6f6598695737201074416dff7e Mon Sep 17 00:00:00 2001 From: Jaixii Date: Sun, 26 Jul 2026 20:09:52 -0400 Subject: [PATCH 32/82] fix(graph): trim large graph render costs --- engraphis/static/engraphis-graph.js | 4 +-- tests/test_graph_engine_asset.py | 54 +++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 2 deletions(-) diff --git a/engraphis/static/engraphis-graph.js b/engraphis/static/engraphis-graph.js index e134625..76be3ac 100644 --- a/engraphis/static/engraphis-graph.js +++ b/engraphis/static/engraphis-graph.js @@ -483,7 +483,7 @@ fg.d3Force('y', d3.forceY(0).strength(centering)); if (mode === 'radial' && d3.forceRadial) fg.d3Force('radial', d3.forceRadial(n => Math.max(0, 5 - Math.min(5, n.degree || 0)) * Math.max(8, s.link * 0.72)).strength(0.32)); } - if (d3.forceCollide) fg.d3Force('collide', d3.forceCollide(n => n.radius + 1.5).iterations(2)); + if (d3.forceCollide) fg.d3Force('collide', d3.forceCollide(n => n.radius + 1.5).iterations(large ? 1 : 2)); } function styleBackground(ctx, scale) { @@ -601,7 +601,7 @@ ctx.beginPath(); ctx.arc(node.x, node.y, r, 0, 6.2832); ctx.fill(); } else if (state.styleName === 'cyber') { ctx.save(); - if (rich) { ctx.shadowColor = col; ctx.shadowBlur = dim ? 2 : r * 2.6; } + if (rich && !large) { ctx.shadowColor = col; ctx.shadowBlur = dim ? 2 : r * 2.6; } ctx.beginPath(); ctx.arc(node.x, node.y, r, 0, 6.2832); ctx.fillStyle = col; ctx.fill(); ctx.restore(); ctx.beginPath(); ctx.arc(node.x, node.y, Math.max(0.4, r * 0.42), 0, 6.2832); ctx.fillStyle = '#eafcff'; ctx.fill(); diff --git a/tests/test_graph_engine_asset.py b/tests/test_graph_engine_asset.py index a18c9e2..cde11a3 100644 --- a/tests/test_graph_engine_asset.py +++ b/tests/test_graph_engine_asset.py @@ -690,6 +690,60 @@ def test_galaxy_stops_animating_once_the_graph_is_large() -> None: assert report["cyberAutoPause"] is True +@requires_node +def test_large_graphs_reduce_collision_work_and_skip_cyber_shadows() -> None: + """The next engine keeps the classic path's two largest per-node costs bounded. + + Collision relaxation is needed twice per tick for a small layout but only once once the + classic ``GPERF.large`` threshold is crossed. Cyber's rich-node blur is similarly useful + at ordinary scale and prohibitively expensive when hundreds of nodes paint each frame. + Exercise the actual force and canvas accessors rather than matching their source text. + """ + report = _run_engine( + """ + const collide = () => { + let iterations = null; + return { + iterations(value) { + if (arguments.length) { iterations = value; return this; } + return iterations; + }, + }; + }; + globalThis.d3 = { + forceX: () => ({ strength() { return this; } }), + forceY: () => ({ strength() { return this; } }), + forceCollide: collide, + }; + const shadows = () => { + const writes = []; + const ctx = { + save() {}, restore() {}, beginPath() {}, arc() {}, fill() {}, stroke() {}, + set shadowColor(value) { writes.push(['color', value]); }, + set shadowBlur(value) { writes.push(['blur', value]); }, + }; + store.nodeCanvasObject( + { id: 'rich', x: 0, y: 0, radius: 5, color: '#22e0ff', degree: 3 }, ctx, 1 + ); + return writes; + }; + const api = G.create(el, {}); + api.setStyle('cyber'); + api.setData(chain(40)); + const smallIterations = store.d3Force[1].iterations(); + const smallShadows = shadows(); + api.setData(chain(601)); + const largeIterations = store.d3Force[1].iterations(); + const largeShadows = shadows(); + emit({ smallIterations, largeIterations, smallShadows, largeShadows }); + """ + ) + assert report["smallIterations"] == 2 + assert report["largeIterations"] == 1 + assert report["smallShadows"] == [["color", "#22e0ff"], ["blur", 13]] + assert report["largeShadows"] == [] + + @requires_node def test_type_colours_follow_the_active_theme_not_a_hard_coded_dark_palette() -> None: """``applyTheme()`` recolours the canvas, but the engine had no theme to recolour to. From a90ae3db317ee53f340a058cdd46bae244782de6 Mon Sep 17 00:00:00 2001 From: Jaixii Date: Sun, 26 Jul 2026 20:17:30 -0400 Subject: [PATCH 33/82] fix(review): address open client release findings --- engraphis/device_connect.py | 19 +++++- engraphis/routes/v2_api.py | 20 ++++-- engraphis/static/dashboard.js | 21 ++++--- tests/test_dashboard_auth_placement.py | 87 +++++++++++++++++++++++++- tests/test_device_connect.py | 54 +++++++++++++++- tests/test_hosted_plan_resolution.py | 40 ++++++++++-- 6 files changed, 215 insertions(+), 26 deletions(-) diff --git a/engraphis/device_connect.py b/engraphis/device_connect.py index d1a56e1..55c3311 100644 --- a/engraphis/device_connect.py +++ b/engraphis/device_connect.py @@ -63,6 +63,12 @@ #: human's prompt, once, and a spurious timeout costs the customer a fresh token. DEFAULT_TIMEOUT_SECONDS = 15.0 +#: A device connection is one interactive request. Letting a caller supply an arbitrary +#: finite float is not portable: values that fit Python's ``float`` can still overflow the +#: platform socket timeout. Two minutes leaves room for a slow network without turning a +#: mistyped CLI value into an unbounded wait or a raw ``OverflowError`` from ``urllib``. +_MAX_TIMEOUT_SECONDS = 120.0 + #: The control plane answers with a small fixed record; anything larger is not ours. _MAX_RESPONSE_BYTES = 64 * 1024 @@ -312,6 +318,12 @@ def _validated_timeout(value: object) -> float: "The connect timeout must be a positive, finite number of seconds.", status=400, ) + if timeout > _MAX_TIMEOUT_SECONDS: + raise DeviceConnectError( + "The connect timeout must not exceed %d seconds." + % _MAX_TIMEOUT_SECONDS, + status=400, + ) return timeout @@ -477,12 +489,12 @@ def post_connect(control_url: str, token: str, *, installation_client_id: str, # when the cloud is flaky. Same shape as cloud_session._post_refresh. try: exc.read(_MAX_RESPONSE_BYTES + 1) - except (OSError, ValueError): + except (OSError, ValueError, http.client.HTTPException): pass finally: try: exc.close() - except (OSError, ValueError): + except (OSError, ValueError, http.client.HTTPException): pass raise _connect_http_error(status) except (urllib.error.URLError, TimeoutError, OSError) as exc: @@ -644,7 +656,8 @@ def connect(token: object, *, control_url: Optional[str] = None, if not str(response.get("refresh_credential") or "").strip(): raise DeviceConnectError( "Engraphis Cloud accepted the token but returned no session credential. " - "Try again, and contact support if it repeats.", + "That token has already been consumed; generate a new one in your account " + "portal, then try again. Contact support if it repeats.", status=502, ) server_compute = "" if has_explicit_compute else _server_compute_url(response) diff --git a/engraphis/routes/v2_api.py b/engraphis/routes/v2_api.py index 0cc6e3b..19eaac4 100644 --- a/engraphis/routes/v2_api.py +++ b/engraphis/routes/v2_api.py @@ -11,6 +11,7 @@ import json import hmac import logging +import math import os import threading import time @@ -1951,7 +1952,8 @@ def _epoch_seconds(value: object) -> float: if isinstance(value, bool): return 0.0 if isinstance(value, (int, float)): - return float(value) if value > 0 else 0.0 + number = float(value) + return number if number > 0 and math.isfinite(number) else 0.0 if not isinstance(value, str) or not value.strip(): return 0.0 text = value.strip() @@ -1964,9 +1966,10 @@ def _epoch_seconds(value: object) -> float: if parsed.tzinfo is None: parsed = parsed.replace(tzinfo=_datetime.timezone.utc) try: - return float(parsed.timestamp()) + number = float(parsed.timestamp()) except (OverflowError, OSError, ValueError): return 0.0 + return number if number > 0 and math.isfinite(number) else 0.0 def _trial_facts(source: object) -> dict: @@ -2529,17 +2532,21 @@ def hosted_plan_summary() -> dict: "source": "override", "cloud_access_active": plan != "local", "checked_at": 0.0} entitlement.update(_unknown_trial_facts()) + access_state = _access_state(entitlement) + access_live = access_state in ("active", "trial") return { "plan": entitlement["plan"], - "features": list(entitlement["features"]), + # A cached trial can cross its known boundary while this installation is offline. + # Keep the durable server answer intact, but never present its stale grants as live. + "features": list(entitlement["features"]) if access_live else [], "plan_source": entitlement["source"], - "cloud_access_active": entitlement["cloud_access_active"], + "cloud_access_active": access_live, "plan_checked_at": entitlement["checked_at"], "entitlement_status": entitlement["status"], "is_trial": entitlement["is_trial"], "trial_consumed": entitlement["trial_consumed"], "trial_ends_at": entitlement["trial_ends_at"], - "access_state": _access_state(entitlement), + "access_state": access_state, } @@ -2567,6 +2574,9 @@ def _access_state(entitlement: dict) -> str: if entitlement.get("plan") not in ("pro", "team"): return "inactive" is_trial = bool(entitlement.get("is_trial")) + trial_ends_at = _epoch_seconds(entitlement.get("trial_ends_at")) if is_trial else 0.0 + if trial_ends_at and trial_ends_at <= time.time(): + return "trial_expired" if entitlement.get("cloud_access_active"): return "trial" if is_trial else "active" return "trial_expired" if is_trial else "lapsed" diff --git a/engraphis/static/dashboard.js b/engraphis/static/dashboard.js index c6c0e8d..cc37ae8 100644 --- a/engraphis/static/dashboard.js +++ b/engraphis/static/dashboard.js @@ -176,16 +176,18 @@ function fmtDay(epoch){const n=Number(epoch)||0;if(!(n>0))return '';try{const d= /* ── shared hosted upgrade / trial CTA ── */ function hostedPlanUrl(plan,trial){const raw=(LIC&&(plan==='team'?LIC.team_upgrade_url:LIC.pro_upgrade_url))||(LIC&&LIC.upgrade_url);const safe=safeUrl(raw);if(!safe||safe==='#')return '#';try{const url=new URL(safe,location.href);if(plan==='pro'||plan==='team')url.searchParams.set('plan',plan);if(trial)url.searchParams.set('trial',plan);return url.href}catch(e){return safe}} -/* Why is this feature locked? One sentence per access state, so the panel never claims a - trial the customer cannot start nor blames billing for a trial that simply ran out. */ -function lockReason(team){const st=licAccessState(),ends=licTrialEnds(); - if(st==='trial')return `Your free trial is live${ends?` until ${esc(ends)}`:''}. ${team?'Team':'Pro'} needs a subscription of its own.`; - if(st==='trial_expired')return `Your free trial has ended${ends?` (${esc(ends)})`:''}, so hosted features are locked. The trial cannot be started again.`; - if(st==='lapsed')return `Your ${esc(licPlanName())} subscription is no longer active, so hosted features are locked until billing is up to date.`; - if(st==='active')return `Your ${esc(licPlanName())} subscription does not include this.`; +/* Why is this feature locked? This helper returns plain text; every HTML sink escapes it. + One sentence per access state keeps the panel from claiming a trial the customer cannot + start or blaming billing for a trial that simply ran out. */ +function lockReason(team){const st=licAccessState(),ends=licTrialEnds(),plan=licPlanName(); + if(team&&plan==='TEAM'&&(st==='active'||st==='trial'))return `Team administration runs in Engraphis Team Cloud, not this local dashboard.${st==='trial'&&ends?` Your Team trial is live until ${ends}.`:''}`; + if(st==='trial')return `Your free trial is live${ends?` until ${ends}`:''}. ${team?'Team':'Pro'} needs a subscription of its own.`; + if(st==='trial_expired')return `Your free trial has ended${ends?` (${ends})`:''}, so hosted features are locked. The trial cannot be started again.`; + if(st==='lapsed')return `Your ${plan} subscription is no longer active, so hosted features are locked until billing is up to date.`; + if(st==='active')return `Your ${plan} subscription does not include this.`; if(licTrialAvailable())return `The email-confirmed, no-card trial lasts exactly ${TRIAL_DAYS} active days.`; return 'Your free trial has already been used.'} -function unlockHtml(feature,plan){const url=hostedPlanUrl(plan),trialUrl=hostedPlanUrl(plan,true),team=plan==='team';const offerTrial=licTrialAvailable();const trial=team?'Start hosted Team trial':'Start hosted Pro trial';const purchase=team?'Purchase Team license':'Purchase Pro license';const price=team?'$20 per seat/month or $200 per seat/year':'$10/month or $100/year';const detail=lockReason(team);const benefits=team?['Everything in Pro','Hosted organizations, invitations, and named seats','Roles, scoped credentials, and Team audit history']:['Hosted Cloud Sync across your installations','Growth, retention, decay, and entity Analytics','Auto Consolidation with hosted retention policies','Auto Dreaming with reviewable managed proposals','Priority support'];return `
ENGRAPHIS ${team?'TEAM':'PRO'}

Unlock ${esc(feature)} and more

Make the local memory engine work across your installations—and keep improving without manual upkeep.

${price}
Your license unlocks
    ${benefits.map(item=>`
  • ${esc(item)}
  • `).join('')}

${detail}

${offerTrial?`${trial}`:''}${purchase}
`} +function unlockHtml(feature,plan){const url=hostedPlanUrl(plan),trialUrl=hostedPlanUrl(plan,true),team=plan==='team';const offerTrial=licTrialAvailable();const trial=team?'Start hosted Team trial':'Start hosted Pro trial';const purchase=team?'Purchase Team license':'Purchase Pro license';const price=team?'$20 per seat/month or $200 per seat/year':'$10/month or $100/year';const detail=lockReason(team);const benefits=team?['Everything in Pro','Hosted organizations, invitations, and named seats','Roles, scoped credentials, and Team audit history']:['Hosted Cloud Sync across your installations','Growth, retention, decay, and entity Analytics','Auto Consolidation with hosted retention policies','Auto Dreaming with reviewable managed proposals','Priority support'];return `
ENGRAPHIS ${team?'TEAM':'PRO'}

Unlock ${esc(feature)} and more

Make the local memory engine work across your installations—and keep improving without manual upkeep.

${price}
Your license unlocks
    ${benefits.map(item=>`
  • ${esc(item)}
  • `).join('')}

${esc(detail)}

${offerTrial?`${trial}`:''}${purchase}
`} function startTrialPlan(plan){const url=hostedPlanUrl(plan,true);if(url==='#'){toast('Hosted signup URL is not configured','err');return}const link=document.createElement('a');link.href=url;link.target='_blank';link.rel='noopener';link.click()} function startTrial(){return startTrialPlan('pro')} function startTeamTrial(){return startTrialPlan('team')} @@ -470,9 +472,10 @@ function licStateBanner(state,plan,ends,status){ function licActionsHtml(state){ if(licTrialAvailable())return `
`; const buy=state==='trial_expired',bill=state==='lapsed'; + const billingPlan=bill&&licPlanName()==='TEAM'?'team':'pro'; const primary=bill?'Update billing':buy?'Subscribe to Pro':'Open Pro Cloud'; const secondary=bill?'Open account portal':buy?'Subscribe to Team':'Open Team Cloud'; - return ``} + return ``} function renderLicense(d){ const el=document.getElementById('lic-body');if(!el)return; const state=licAccessState(),raw=String(d.plan||'local').toLowerCase(); diff --git a/tests/test_dashboard_auth_placement.py b/tests/test_dashboard_auth_placement.py index e4c6063..3bc3af0 100644 --- a/tests/test_dashboard_auth_placement.py +++ b/tests/test_dashboard_auth_placement.py @@ -98,7 +98,7 @@ def test_hosted_views_delegate_entitlement_to_cloud_proxy_responses(): # trial" is answered here by the code that answers it in the browser. "licAccessState", "licAccessLive", "licTrialActive", "licTrialAvailable", "licPlanName", "licTrialEnds", "fmtDay", "lockReason", - "hostedPlanUrl", "unlockHtml", "managedConsentHtml", + "hostedPlanUrl", "licActionsHtml", "unlockHtml", "managedConsentHtml", "managedConsentRequired", "hostedFeatureUnavailable", "loadAnalytics", "loadAutomation", ) @@ -187,6 +187,91 @@ def _route(tmp_path, cases): return {row["name"]: row for row in json.loads(result.stdout)} +def _license_copy(tmp_path, cases): + """Execute the shipped entitlement copy and action helpers under Node.""" + + functions = ( + "licAccessState", "licTrialAvailable", "licPlanName", "licTrialEnds", "fmtDay", + "hostedPlanUrl", "lockReason", "licActionsHtml", + ) + driver = """ +const CASES = JSON.parse(process.argv[2]); +const out = []; +for (const c of CASES) { + LIC = Object.assign({}, LIC_BASE, c.lic); + out.push({ + name: c.name, + reason: lockReason(true), + actions: licActionsHtml(c.state) + }); +} +process.stdout.write(JSON.stringify(out)); +""" + runner = tmp_path / "license-copy.js" + runner.write_text("\n".join([ + _ROUTING_STUBS, + "\n".join(_dashboard_function(name) for name in functions), + driver, + ]), encoding="utf-8") + result = subprocess.run( + ["node", str(runner), json.dumps(cases)], + capture_output=True, text=True, timeout=60, + ) + assert result.returncode == 0, result.stderr + return {row["name"]: row for row in json.loads(result.stdout)} + + +def test_lock_reason_has_one_plain_text_escaping_contract() -> None: + """The helper returns text; each shipped HTML sink owns exactly one escape.""" + + script = SCRIPT.read_text(encoding="utf-8") + reason = _dashboard_function("lockReason") + upgrade = _dashboard_function("unlockHtml") + + assert "esc(" not in reason + assert "${esc(detail)}" in upgrade + assert "esc(lockReason(false))" in script + assert "esc(lockReason(true))" in script + + +@pytest.mark.skipif(shutil.which("node") is None, reason="node is required to run the UI") +def test_team_entitlements_use_truthful_copy_and_the_team_billing_url(tmp_path) -> None: + rendered = _license_copy(tmp_path, [ + { + "name": "active-team", + "state": "active", + "lic": { + "plan": "team", "access_state": "active", + "trial": {"available": False, "ends_at": 0}, + }, + }, + { + "name": "team-trial", + "state": "trial", + "lic": { + "plan": "team", "access_state": "trial", + "trial": {"available": False, "ends_at": 1_800_000_000}, + }, + }, + { + "name": "lapsed-team", + "state": "lapsed", + "lic": { + "plan": "team", "access_state": "lapsed", + "trial": {"available": False, "ends_at": 0}, + }, + }, + ]) + + assert "runs in Engraphis Team Cloud" in rendered["active-team"]["reason"] + assert "does not include" not in rendered["active-team"]["reason"] + assert "Your Team trial is live" in rendered["team-trial"]["reason"] + assert "needs a subscription" not in rendered["team-trial"]["reason"] + assert "Update billing" in rendered["lapsed-team"]["actions"] + assert "plan=team" in rendered["lapsed-team"]["actions"] + assert "plan=pro" not in rendered["lapsed-team"]["actions"] + + @pytest.mark.skipif(shutil.which("node") is None, reason="node is required to run the UI") @pytest.mark.parametrize("view", ["analytics", "automation"]) def test_a_consent_required_conflict_is_answered_with_the_consent_panel( diff --git a/tests/test_device_connect.py b/tests/test_device_connect.py index 6568008..060bdc7 100644 --- a/tests/test_device_connect.py +++ b/tests/test_device_connect.py @@ -334,9 +334,13 @@ def test_a_success_without_a_refresh_credential_writes_nothing(monkeypatch, tmp_ body.pop("refresh_credential") _install_opener(monkeypatch, _Opener(body=body)) - with pytest.raises(device_connect.DeviceConnectError): + with pytest.raises(device_connect.DeviceConnectError) as caught: device_connect.connect(TOKEN, control_url=CONTROL_URL, compute_url=COMPUTE_URL) + assert caught.value.status == 502 + message = str(caught.value).lower() + assert "already been consumed" in message + assert "generate a new one" in message assert not (tmp_path / "cloud_session.json").exists() @@ -375,6 +379,44 @@ def read(self, size: int = -1) -> bytes: raise http.client.IncompleteRead(b'{"organization_id":"org_al') +class _TruncatedHttpErrorBody: + """An HTTP-error body whose drain or close breaks after the server replied.""" + + def __init__(self, phase: str) -> None: + self.phase = phase + self.closed = False + + def read(self, size: int = -1) -> bytes: + if self.phase == "read": + raise http.client.IncompleteRead(b'{"detail":"truncated"') + return b"{}" + + def close(self) -> None: + self.closed = True + if self.phase == "close": + raise http.client.LineTooLong("truncated error response") + + +@pytest.mark.parametrize("phase", ["read", "close"]) +def test_a_truncated_http_error_body_keeps_its_fixed_status_error(monkeypatch, phase): + """Drain faults happen inside the HTTPError handler, not its sibling clauses.""" + + body = _TruncatedHttpErrorBody(phase) + error = _http_error(401) + # Use a concrete closing hook so the test verifies our handler executes it even when + # the preceding error-body drain failed; urllib's internal wrapper owns its own file. + error.fp = body + error.close = body.close + _install_opener(monkeypatch, _Opener(error=error)) + + with pytest.raises(device_connect.DeviceConnectError) as caught: + device_connect.connect(TOKEN, control_url=CONTROL_URL, compute_url=COMPUTE_URL) + + assert caught.value.status == 401 + assert "generate a new one" in str(caught.value).lower() + assert body.closed is True + + @pytest.mark.parametrize("failure", [ http.client.IncompleteRead(b'{"organization_id":"org_al'), http.client.LineTooLong("header line"), @@ -852,8 +894,8 @@ def test_the_manifest_outranks_the_compute_constant(monkeypatch): assert device_connect.default_compute_url(CONTROL_URL) == "" -@pytest.mark.parametrize("bad", ["nan", "inf", "-inf", "0", "-5"]) -def test_a_non_finite_timeout_is_refused_before_any_request(monkeypatch, bad): +@pytest.mark.parametrize("bad", ["nan", "inf", "-inf", "0", "-5", "10000000000"]) +def test_an_unusable_timeout_is_refused_before_any_request(monkeypatch, bad): """``argparse``'s ``type=float`` accepts ``nan``/``inf``; the socket layer does not. Those reach ``urllib``'s deadline arithmetic and raise ``ValueError``/``OverflowError`` @@ -875,6 +917,12 @@ def open(request, timeout=None): # pragma: no cover - must never run assert "timeout" in str(caught.value) +def test_the_largest_supported_timeout_is_accepted() -> None: + assert device_connect._validated_timeout(device_connect._MAX_TIMEOUT_SECONDS) == ( + device_connect._MAX_TIMEOUT_SECONDS + ) + + def test_the_cli_reports_a_bad_timeout_instead_of_a_traceback(monkeypatch, capsys): class _Exploding: @staticmethod diff --git a/tests/test_hosted_plan_resolution.py b/tests/test_hosted_plan_resolution.py index 063bd6c..b0e63c0 100644 --- a/tests/test_hosted_plan_resolution.py +++ b/tests/test_hosted_plan_resolution.py @@ -69,7 +69,9 @@ #: serializes them (``engraphis-cloud`` ``EntitlementDTO``; Pydantic emits a trailing ``Z`` #: for UTC, which this client's Python 3.9 floor cannot hand straight to #: ``datetime.fromisoformat``). -TRIAL_ENDS_AT = "2026-07-28T12:00:00Z" +# Far enough ahead that tests for a live server disclosure do not depend on wall-clock +# time. Expiry itself is covered with an explicitly frozen boundary below. +TRIAL_ENDS_AT = "2099-07-28T12:00:00Z" def _epoch(iso: str) -> float: @@ -1607,6 +1609,33 @@ def test_a_live_trial_is_reported_as_a_trial(monkeypatch) -> None: assert set(payload["features"]) >= {"analytics", "automation"} +def test_an_offline_cached_trial_expires_at_its_known_boundary(monkeypatch) -> None: + """A stale positive access flag cannot extend a trial while the client is offline.""" + + boundary = 1_800_000_000.0 + entitlement = { + "plan": "pro", + "features": ["analytics", "automation"], + "source": "session", + "cloud_access_active": True, + "checked_at": boundary - 60, + "status": "trialing", + "is_trial": True, + "trial_consumed": True, + "trial_ends_at": boundary, + } + monkeypatch.setattr(v2_api, "_plan_entitlement", lambda: dict(entitlement)) + monkeypatch.setattr(v2_api.time, "time", lambda: boundary + 1) + + payload = v2_api.get_license() + + assert payload["access_state"] == "trial_expired" + assert payload["cloud_access_active"] is False + assert payload["features"] == [] + assert payload["trial"]["active"] is False + assert payload["trial"]["ends_at"] == boundary + + def test_a_spent_trial_is_told_apart_from_a_lapsed_subscription(monkeypatch) -> None: """Both read ``cloud_access_active=false``; only ``is_trial`` separates the copy.""" @@ -1790,9 +1819,9 @@ def test_the_trial_disclosure_survives_a_restart(monkeypatch, tmp_path) -> None: @pytest.mark.parametrize("value", [ - "2026-07-28T12:00:00Z", - "2026-07-28T12:00:00z", - "2026-07-28T12:00:00+00:00", + "2099-07-28T12:00:00Z", + "2099-07-28T12:00:00z", + "2099-07-28T12:00:00+00:00", ]) def test_the_servers_utc_timestamp_is_read_on_the_python_39_floor(value) -> None: """``datetime.fromisoformat`` on 3.9 rejects the ``Z`` Pydantic emits for UTC.""" @@ -1801,7 +1830,8 @@ def test_the_servers_utc_timestamp_is_read_on_the_python_39_floor(value) -> None @pytest.mark.parametrize("value", [ - None, "", " ", "not-a-date", 0, -1, True, [], {}, "2026-13-45T99:99:99Z", + None, "", " ", "not-a-date", 0, -1, True, [], {}, + float("inf"), float("-inf"), float("nan"), "2026-13-45T99:99:99Z", ]) def test_an_unreadable_trial_boundary_is_unknown_rather_than_raising(value) -> None: """This runs on the ``/api/bootstrap`` boot path; nothing here may raise.""" From c99a1a58be27aba5539e8b330343171a278db39a Mon Sep 17 00:00:00 2001 From: Jaixii Date: Sun, 26 Jul 2026 22:41:55 -0400 Subject: [PATCH 34/82] fix: close final release hardening gaps --- .env.example | 66 +++- README.md | 2 +- docs/images/knowledge-graph.png | Bin 1237250 -> 931628 bytes engraphis/app.py | 100 +++++- engraphis/backends/postgres_schema.py | 81 ++++- engraphis/config.py | 43 ++- engraphis/engines/intelligence.py | 3 +- engraphis/llm/client.py | 3 +- engraphis/routes/memory.py | 12 +- engraphis/routes/vault.py | 279 ++++++++++++++-- engraphis/stores/graph.py | 7 +- scripts/externalize_dashboard_assets.py | 12 +- tests/test_config.py | 26 ++ tests/test_db_path_default.py | 65 ++++ tests/test_externalize_dashboard_assets.py | 9 + tests/test_memory_routes_fixes.py | 354 +++++++++++++++++++++ tests/test_postgres_schema.py | 141 +++++++- 17 files changed, 1148 insertions(+), 55 deletions(-) diff --git a/.env.example b/.env.example index e58f1a7..ce5808c 100644 --- a/.env.example +++ b/.env.example @@ -10,7 +10,9 @@ ENGRAPHIS_PORT=8700 # clients. Hosted vendor, relay, compute, and worker roles are not distributed here. ENGRAPHIS_SERVICE_MODE=customer # The dashboard base URL is derived from ENGRAPHIS_HOST:ENGRAPHIS_PORT. -# Set ENGRAPHIS_DASHBOARD_URL for a canonical public HTTPS URL behind a reverse proxy. +# Set ENGRAPHIS_DASHBOARD_URL for a canonical public HTTPS URL behind a reverse proxy; +# it extends the dashboard MCP origin allow-list and drives legacy-inspector redirects. +# ENGRAPHIS_DASHBOARD_URL=https://engraphis.example.com # Update reminder. When on (default), the server checks for a newer Engraphis release # once a day and surfaces it in the dashboard banner, the startup log, and over MCP. @@ -213,3 +215,65 @@ ENGRAPHIS_LLM_API_KEY=sk-your-key-here # Optional credential-redacted JSON logs for hosted customer deployments. # ENGRAPHIS_JSON_LOGS=1 + +# ── Advanced / Operational ─────────────────────────────────────────────── +# These settings are used by advanced deployments, operators, and internal +# subsystems. Leave commented unless your deployment needs them. + +# Logging — defaults to INFO, text format. +# ENGRAPHIS_LOG_LEVEL=INFO +# ENGRAPHIS_LOG_FORMAT=text +# ENGRAPHIS_LOG_JSON=0 + +# CORS — comma-separated origins allowed to call the dashboard REST API. +# Default: http://127.0.0.1: and +# http://localhost:. Explicit values replace both loopback origins. +# ENGRAPHIS_CORS_ORIGINS=https://myapp.example.com + +# Rate limiting — requests per window. Default: 0 (disabled), with a 60s window +# used when ENGRAPHIS_RATE_LIMIT is set above zero. +# ENGRAPHIS_RATE_LIMIT=0 +# ENGRAPHIS_RATE_WINDOW=60 + +# HTTPS security origin — used for HTTP-to-HTTPS redirects and security headers. +# ENGRAPHIS_PUBLIC_URL wins; when unset, security falls back to +# ENGRAPHIS_DASHBOARD_URL, then the legacy ENGRAPHIS_RELAY_PUBLIC_URL setting. +# These settings do not change CORS; configure ENGRAPHIS_CORS_ORIGINS separately. +# ENGRAPHIS_PUBLIC_URL=https://engraphis.example.com +# ENGRAPHIS_RELAY_PUBLIC_URL=https://relay.example.com + +# Trusted local peers — comma-separated addresses exempt from rate limiting. +# ENGRAPHIS_LOCAL_TRUSTED_PEERS=127.0.0.1,::1 + +# Import roots — semicolon-separated (Windows) or colon-separated (POSIX) +# directories allowed as import sources. +# ENGRAPHIS_IMPORT_ROOTS=/srv/docs:/home/user/notes + +# Memory engine tuning — decay halflife (days), chunk sizing (tokens), +# proactive context loop, and reranker model. +# ENGRAPHIS_DECAY_HALFLIFE_DAYS=30 +# ENGRAPHIS_CHUNK_TOKENS=512 +# ENGRAPHIS_CHUNK_MAX=2048 +# ENGRAPHIS_CHUNK_OVERLAP=64 +# ENGRAPHIS_LOOP_INTERVAL=300 +# ENGRAPHIS_LOOP_TOP_K=10 +# ENGRAPHIS_RERANK_MODEL=cross-encoder/ms-marco-MiniLM-L-6-v2 + +# Workspace allow-list — comma-separated names. Empty = all allowed. +# ENGRAPHIS_WORKSPACES=acme,personal + +# Cloud Sync relay — endpoint and optional token for self-hosted relay. +# ENGRAPHIS_RELAY_URL=https://relay.example.com +# ENGRAPHIS_SYNC_TOKEN= +# ENGRAPHIS_SYNC_READ_ONLY=0 + +# Hosted plan upgrade URLs — override the default upgrade landing pages. +# ENGRAPHIS_UPGRADE_URL= +# ENGRAPHIS_PRO_UPGRADE_URL= +# ENGRAPHIS_TEAM_UPGRADE_URL= + +# Update check cache duration (seconds). Default: 86400 (1 day). +# ENGRAPHIS_UPDATE_CACHE=86400 + +# Legacy inspector port (retired 2026-07-10; redirects to dashboard). +# ENGRAPHIS_INSPECTOR_PORT=8710 diff --git a/README.md b/README.md index 7a2cd22..9c0c997 100644 --- a/README.md +++ b/README.md @@ -664,7 +664,7 @@ All via environment (or `.env`): | `ENGRAPHIS_LLM_MODEL` | `gpt-4o-mini` | Model name (provider-specific) | | `ENGRAPHIS_LLM_API_KEY` | — | API key for chat/synthesis, `llm` / `llm_structured` extraction, and structured consolidation | | `ENGRAPHIS_LLM_BASE_URL` | — | Base URL for openrouter / custom OpenAI-compatible endpoints | -| `ENGRAPHIS_LLM_AUTO_EXTRACT` | `1` | After a successful live connection test, automatically switch the running engine to `llm_structured`; the dashboard's extraction Off button persists `0`, and its On button restores `1` | +| `ENGRAPHIS_LLM_AUTO_EXTRACT` | `0` | Opt in to switching the running engine to `llm_structured` after a successful live connection test; the dashboard's extraction Off button persists `0`, and its On button restores `1` | | `ENGRAPHIS_FORWARDED_ALLOW_IPS` | *(none)* | Proxies trusted for forwarded client/TLS headers (`*` only when the service is reachable exclusively through that proxy) | | `ENGRAPHIS_LOCAL_TRUSTED_PEERS` | *(none)* | Exact peers/CIDRs treated as local without forwarding headers; intended for the shipped loopback-published Compose bridge, not public deployments | | `ENGRAPHIS_CLOUD_CONTROL_URL` | hosted default | Official entitlement, organization, and credential control API | diff --git a/docs/images/knowledge-graph.png b/docs/images/knowledge-graph.png index fb737eb93a3500f00c633e7089c4a8726aaaaa1c..9b67fe8f654dc837565cd87cf9b5985c4383c68b 100644 GIT binary patch literal 931628 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

EAy*p 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

3~3wLeL>N)7pX?_LiWzJrp#m! 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

W>NkZ8$UxGrPs-P};uh%ucg;Xe*oN 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�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

uKOuhcuq>Yq@A`Hl5_SX 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 literal 1237250 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%0ALkgc*JfE#>U8$6j7I3C|{=Y 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⪙@QPY7;8j^n;?$-|_ zVW5*{x2DKE9&gmyAi`E&@AChRGyjBZ{jXcXTxc7C1UtMl4za7eJBSWuF<(MFR*i8d zRp}^QcYEZ)`;NIcEreh<1Xn?}$#bF7=q|JUBaNY5@kh-3BKktqj1W?+XoZ=wR`rt5 zfm8<_OaAFu_U0kjF#`?XM)a6)?7jHjLSxP-GHYcsuHU$>{&~OalJI)I z9?!@9e!tx{C=m**|L$4fPeYdlBUUTO(T(QLcWMtaS;(hCtmh(9cW;57E4nAvFEb{g z_OyYvBRm9Q-I~MpsYKJ};m>bVmE()fGp-^X=0E>9kIc^BD&XM5?GBp`fGzU7s!`U% zgRJRrLK;n#UF9&<2H#J7M$c)X504w@pe66?dOI)iRMXkF_8D+mTbuVud5g8OXw z@EwX-l7x3Ze^sZEpROFQ^^)Qjw5VA;Bgl%ap=bl^xNqYb`@{&GXxbcBz~}ON97FW5 zZO6>)kZ<5K&l+r*a~tf~uKg}ET}{!&-C!ET(`A@*;H-9?_{w|xL$m*q-u|^W3I%a+ z6{;3z1i8B-Jg|6VOtVSyMLXJJ;(+9XQC$Kojbg?en$oQ@{A>5D-Cd^b!i%4K)-%$l z;1SOJ#wFyw*qk;AC45=Gygq5pcMI}*VRFoWT)dQ9O8M%Aii?L)e;ij>zN20_A(_$c zb>P80Y;bHxazPZnVPfJt+6e)Sh(H#LA4&H@;Y%=!@s6;fAbnX}jqxgukXL)pVPC&i zJlo&w&yI{s38zYPYqqODZEo6pStZ#v!gfNY^2LEOLmRg{V;w$zP(4e8W<9L-95$)@ zH;*-IYaRKYCZ175bwS4K+smL51T$_4;6VBEJ^?ho-)vQJ;IO!HNF86U_qkdD_hBYK z2cA$gOG(EZ zMXQQ@FhZ##{LS}_cr640LVwc6)-ti2g1;4Q*Ul6mMiNPadmXsCxkaj#u_GBuZ)Zrw z?qm$y0s^jVObntf`;&N2Y2Vl{u}E-;i^R3DYcBw%LRLpZ2W*QwSI&)!77Qrp2VX1e z4Q?NKkxwuD;^VUQQ^b7hMxHkW{U%g z&ygz!&}o*u*o-Eabv_@{|Ii}z?_a-=#NQ`O24jq@i8M_y`B5_0)gPF}86ESdtM(5L z_H6WBul09aZk_pqz3|N1@PX25@cD*_5ft?SZ=9ou*xor+MGoR(o8rQcHrK%;$E7Xj zXI5b(J~Rh4&UeHF&b%mH2ANn+E@W|iIj^oH=%f)U*#NY4e&4spc<8oG^y+JAm&+T8 zFz1y&OER=yKf9Y_YO6nCPc}CffBqbBH@Lukai14Tt5Nzjo5DbxP8GC6mW)z2cPJ&^ zo-?SL>KSUn+%0X`p#!HBB%~lKu8VOvU7y<9YnSZN(KYF83OJd%2UG@v&=vt9AJ-+-wIY42rw%&FNn6>GY^g*^SGWHkyfe z&V2I3JhealZRd-=X0lMbTxz;Deh(0susUq-LhHgBtQ9D=Z>&>rUaHfosfA`)qMGBK zF~Bl5eRG2f?s_kmqLPnuahV4Q?0mP`9EKAtZPdxGDP;Z|LB8uzqSf2K)izFco5%`q zSGKu%1N(V~bx+X>tKQk~ajJ;a?!Kv^UMgL~o^;7Q38?2PsM(wKh(XQ4LKtt~H^Ejg zXbeqT_NR=UkTE(MTmb?qH!H@1!6LAL{oSV-Aed6S{=!vNtzYtpP8`oYfPAMn>p~L$ zDtV9Iz6!?!B20CclPHRvq$js@^Srr!PQc!mf02P#Rn_;uN|fFa;WHd})%(8fk`c{=K>v9`7)ASR_M7}TY;wSNYoTZ|Q|LjqkUFRVlKKm72d|xB2H4g8x zl56?L<6Ya~9Tz#Xv3AKIAx?!@f&)5`jWl$0o%qiL{<;&@c9n@pa2pJlY~s=gZ{jg)^j~a@Y03xs+s>O*i+=O4g%w zQppnDJ-vDnXd|v1of{jx29>t?pd&{6Z{?(U&C|YWF$I9Eey#1TA(K-L@G5M^MEky5 z9rJMPDk=y(FFqlj<}^?HBk4|hD3kvyljBWY`haH4pKUSR%nL+3@V3l19uR=fnGoiiqXXhA3RS zB>Y8L?1WI+N)cG!`XKA_f{CL9wCBwBhz5KOIBBQxgcPb?h2?F(h6ZR3!Bk|Pyjk}> ztiw4SK)k_X4+DBkPB(Rr{F#WTe^?zKY}Z4zAt=4TaQimYwBsgdKm5IJ((Q^>niuQt zqz{va?>cGVx9ji&AO&NRcmr%c@8R04l<7iS!k}m^c7?D3=Hu8{&HK!$DyAui>uSx7 zMa8MeX)eWcw_8=vv5OLwmB$&5wpLDY>VN|7Qkr)j4L@x|lipD3@@$pX*K~X)acTnmZ+&mN;GTf={igCR z@rSey{lnP6SAIxcjWp#F$!A^B6C8cp;ha5<%&6G*iKlLO)-6) zbH0h%ai(l)`#v7!Py%&5Mc^!P2ZMvS=qDSc&sKdw5(c z-?|t=5s=MxbiJXa_pS1-ss6!`Kf039LRhmqOP0>BgM2@w_48(05dAWC6d} zk$w?dMF|hL%X6?ifG-R&H4jf!$Uj{Cd+c-Lt&8Ifn~sj72m_e5o%eI7ym_`-@qk;7 zzhB>TdemE0jm4j`n*Xr~-!i&Xy8U&YfUrbk{}{ND>_YnNE$&!apThVx?tCdLH*L9S zUyboTIT$wCYheoLy+C8E?%7sU79>I)JA@V4_a$xV)3{3ol^?%&7nPF?C8F$e!3&qN zeWI6OEty$r_E#jt{t2DgHwDu-y$b~vqsqXW>Bo9OcO}H$*y0qJv@+vc7I8lRpRs(( zEy1svJY#P@e4uqCJjh2W+nRMxft7q^ye9Iafe_LHSu=ahuC{p& zP6U~*bLLJ2Hpyp#8|7HavO5KZoMY=7{uRij1em8T#RtGoA#QmxR=Mhni8yU_8#0y` zphJgTv!7mZ>1kWv<#(A^#)*8!-utqR9_=3b)sAN^EG*8L^U>liswX?&DIk*%#!3}G zBk}HT74x68AQQ*+K)~}(r1-7{$mU1;Y5}t#WwuD3?5llcrsQaW4{O$@T-tcRf%~v) zN8i%99)ET`a%;!gq1JtOML$e^irT*R8#9nO+5Xx3_R4s95Ev%8{fFw3?%J?IAO!Rx zk@U*MTX8qykxgn`kLzD&p3W|aZ61d1e}y6CFZF@LpR`%82Bj9SCP3w%O;W#VqDGcO|&rKP9O!Q=Qi?###BgE}mL;(&-_(~}F;K1^X zyY1BD@vVG5vw7PywRNHqsqkCSdT(VpAo@>HJ4g*rZ3{O0D7Jr8aFyOjcO0P{IB>;$ zuGt`Y!ugJBsL`CcGGekP!p6R!VS$#IUo>mAyMu4_eWp=E&p8C84lUWx8aK>yrHwKF z`47kr9$_T{UgYOfgZ~xgIA~T8>pZ*fd$zdPrl_@>vlPo4R~(wW3dVq2ZO%_itRV=E9{!DpLu2=gN*ul; zl|@F!IxGv^uX#DH^gRP}N1nyp3mGnIQ?Q{#k15GoP)!&yY;Er-Cn;%A_J}NV;T}ck zjkK<`9cfkp!vNTuIvONvXb8t%8gjRT>{xRWvK;e5bgdds#br2}B}}w&S3D)vVDIlX z(@fTsI8=ZhpMm)lo^Xfz35dqs22lW)&4yenUHJFA{@XS^_ZDp7V7th8FafA9Hw-`- z-{=~91=j`m?!Fo_Dt~$bXI#keS-a=&xIpG8lKw2^VsLSb+1O854m!5ZCA##~ENmWO zdz}_`*K@P7UZy(KB+E0x+x=)Z@q=MateW3}7J%O)GbeYoxNH7ARTaj_teuV=+m1Cx zUUR6wQZUfz(S&6n4@1CWVep3uZzlZJWI##eI0Fk0hh7VPxxrt}f=n`$ zslvb$In~DpUf|F-7#H|9-66twd>Gnk-qNZ94{5W3wx8e4Gol{!BjKw9RzLn9uhjQ9 zM{rN^f4>}maFD3BXRS7M8HY8|7Vz&SkUn7ux8-glvav^JmidQOu0dPDC~cUnDO@%; zzE?2id|c?vA)o!oZt!*7dfg1OvYa${#C@*O8=-J3!&XrN`6jyvprG;4>I=tTRj#;a!SLOG^-tlhOi@=Bl~pvll6& z7mG`lAF^n{J0d=7#u!<19!{)(E8v@%YVWTlKVTV9X#8v1r|!qcc6(n;Y2Hvt-;q`I z_WeS0K_V;T)-GA5f_!HdNOHvHhg;JU6PL{gf2qPQ1Q@mlMK`3HobLOc9Q3BbPx|Ff z*Hfub&$FQG!J9o!B@V@q;b!>(S%FXhj}UZ1lR~NwP(Y2hIry@AJ*q%V@<@dVF)Dgl;K8EsY1`?+H#fb zvq6HsE2lS6$>sWSgA2dPclYEP{TkqmukjKgA=z0)gU-D8%z?#?IK-1mHZL0)4)`3H z+-|m9p;x?>vc#RS^*WY?#{1EYL=@UlM4{m4ce8%Xw#twjyk!nN?;ooVFQ-iekZso( zOG0o>S{mM+TySYt;D~>pW5xzy@`QwB0fEXVbgVULMp;MSDb%KyO-|{+(o7vent?)ii68s4DM~cvd7S=cBlRx7#sveUOM*vfHq`L;f)N7CD@HHHGDn1rol>M zW^mXdcJL!!Y`fXY(`%w?f2hP{RxO|@fo8}*!qqa@liE}=S7B9iXD9LjZXvW|bZ^&@ ztN zVBEJpm#ZNP#=U^4F>X7CdIl^{^^>FRwv)RM-k8i_%S6TWu6mQ!DVA##BJF^Nok`R*%v8jk35-b9mqWLGB>ukRwKDXEVE{Q(|%&u97OWiBnX6qPTBoxRL??zyW`+ zRfIMcU*;xOoT!v?H=qf{iIj9!pP77tUbVkvp=46XLeFiGrnauPKoQ&cxO)bM% z>N+f8kBfUic~8Xm{?DTtn)?5DWWpcW$X7RUn3}b3-}#8!{qkG(TyzozB;NU%+fU^N zM1@WJ3kVK&8U7HpyKnp<%CvMe_j8KdxX53DVc<#)z_a+K-+@HR^P+e+U3Vo>O3O{% zeSbp;?BrYC&{k}CAAhb|N6?8oPJbm8Thhxn^7Al3=*#KEPXwk=sBzp1e*gisJc}E! zHiV;6R->(@Rk|fera9+tt&zf@AhmlU;n_J%zus`X;%c1kjzFE-lN5L1j=t3w(=ob>iBPs1BunPZl6a&|Lqt&bU6VpQ}JAT@ni|KUT; znf1W*CVHE(fzq0`6XVUjOr>Vz%GXNMq%_yfFvEc3ZP=gq`=9m}6&9NBhtG)}|Kf*= z43|2|#cCtJtm?UK+PZW~KGOJHHRnPwM_7l){O{^7$)BPo*)H2cA@`l^c)H0_t)i~*0( zzdgicDVYY5B1(>e#>V9O3`n!bJwv=1GHOM736(qko@=e3cM`2-GPRm&@D$^Q7zdPh z(>weJh`D|lk*<1&PfWmcGU&>scW|WyJWPIro%~F8c#GOUQ9@gHXm918rk03T=zdvAuJk8y6PWwxb&wO083b(^cXAncB^) zz*n4q9Yq*o`sA<3KlwQfH-GC?JKl)MX7@45FP}s5$nX-<(64xBlrI26quJ^Lq-8rT z`I8ck^>1~(T+_UM1GQtNrLQjy7l7jYsP!SRA>-jSydfrID3?Ige^H2)u^4&UBe|{W zn~^eWc?Rsx#(FNIAXI7p)5q(B2Zw~3HH3HBdRlQ!EFbxr zyS&QjFfHqSS>%SxVuV#XxmkQ7Ny~I|l}QI|#=m8rZn60vFXKacRcEkc0js6yw)X^x z)lL)gr8%&5^jWJ3r7`g=_l!0A@SrU5eR)=fO<7$O(A)f-d(}MGY8Jr1*@09BEXrna z{!hJNbDi|7X_Db9irr7HQnRq+{rWwK-aY`UKS?RSR$3nd?eknh$5`+WpgQC%<1hDKi~w;hXq{+GO)NvIE|Z9|64ON9RUneQp}8; z+JZx52QFk6mEcl)BVDoYcO~}yf}|ec87^If6=%x=(fegDcqU)V$YBnAwIBTkEmI+n z99XLqk)wmpR*&NvxTAs}O%)K0rH;q+h0X>ve%=;P5`%BH{kXhnSo$SO!NQ8}1rSv8A5SLq`8a_-o^MrV< z7}vAFeTLo(^84wcl~h6v_Hp}+yK*8l3$7yIMTRAjfQoGFikVz6%o;d z#fBy|2mW>Hi2tM?PQ~6SmQNpTPVtN_zPH-o!R-DU31Q8EPh9>R_;L2 zamFP+Vu&o2bH(8}TD_<3O=yfa2z53OP(D7>wlW`K zT_ky}AjiDBxqhPgDCp80^2T?1cCQ)7pYu8{(}HsreR3PA%S zcD^?U(nJ@Cs5fc?PU*2k(Y^O}=}*v-lDN>}cfez+h{RitY+8)_qEyZYo$V1hzLnp;@COXFMDCT6vtiI@tzB2B9YTQY<3oA)>IfXdZ&m z%n%7OFt`SLclY3x2Mformiubtar^>$!3GRn`((fJh{VN`~=5cw+gs%El(dNz%DiSGo_9O%$b0dgvd77nfoUOr8q3g+S{2`w2D63y)W{j!)=ZR zF6{-qi;t(c^lsYy@RFz1tV=gX#`bHzZu*=3cZuILzRG5Y2wxY9^HMO!hL;~WXau^? z>Qzq|gNjvHTAGz#nE@pX59X+FAB5``%VqX&>sTm0bgCVHmXf3HH>lcLYsd|5R+yMy z73}SWGK+3hb8ggf#86QcDCNO!adgyMK*hq`9Eu7B;a&nZ9kBhw(~Ea34q`X7bMIWD z7EOl_Aq`9|V?RhUDgcV5xUd5$VEoZI79kKSKFPaNv6@JDYi#0CMQ5qA*^Hq=EZa)U zikrvE64fCyoqmjlj@=P6T>&Z>mhl3siidT*oSe?4H{2U&4g(V#D#kpfevhH0rD!ww`mI^g_*uR8z|p2YMr zB@^Y~4jYPphfT1A=coU={bp`U{|^r)#0Kg}9Y@lnt3>2r!K{1mYc`+7zg{U(jR7$| z#0;1hCVfNA*(16?K``Ym@Vlb{_`8Nl=OS`EDy^TdueT5x_Z!mRtE+G~!&)u6{$!x|H&g4}`F)1MOKoDNxr6wJ)x&ub>A5-n2S*f!(X4Bl^CmkiE-3OB2QMUAUb)VVH`Tp@fwoqP1_E zJ|t@_9*Gt45|1uj=v-hm!3-^4(ll{nt|({-9Sui=5&MJ0eZ-fLhnqSVLj?P$rXorg z;47M4pM6e26XpzPjDbmH6$_xzY%Xm8ZBqa!Lqz299g=~bTI!vBGt=K7QNjkXKT-@3 zA;2LLRp*2(CaAkn_jx-Y`E-2T@I(Qfc_l&iQ|`OAd}^p1W?-*DfYe7etQq0GZ*oe=7vPs*1Z_>LK~VSlg*D(r#~<49p}*ztAYQ<@E1NH5 z`~syP&MXS4_LQZpde^hu@-O=Tx+CwEmt}l-UlwD%y>Mk?kVz5I|u;DBMW?_|8&fP9ss=fFq2ntaMM{HtM2j++)I(+Wf)!R(=~e52SQg)XPLuf(lS4wL z!{OU$0ViIrZXRHV==^Lwu(#VA5ar;Dz2-anTMcZ~?I05pPr6}R={?2?qaaU?n_zNs z@T$gI7fy~{d@FcYEfS67OdOa1#`fn8fA2In@x_FuocV{Q9K|CeBR^Mtp@@|0kEHZh zBVl<79cXoXW-Yv%fSytC>D4kv#>~!}DY9!vfnq8qqR0`?WuGAcAjh_)0d@jqumVGs zTe&&Sv2=-o6{)-|v*;~Ld^Qyz|LreGp0>iF*cEtzNO=EU9PQPs*RK*ge!H;XazI<) zvY59%1M+D;5*c`M;tz<9XZH5`7JFC7#J{m7IA z-c#=f{fZ4wu_H9o>HCTt3fb}&hlC3urk`A_IHScjeP+wAIs~)_zv_~PBVAQu&Kz#q zYGRo4K{}KjJqG&`R=vo^4t980vp%z@6r~gje+s;AJB1$vv{6`pDBQ0 zC_#7+j9So~Xg+s8UYP0uOGT0-`j{&-fWjr;2+%5q^`(RYgF)HC8kG3qvocW5>$6l? ztoJ~=`xeC3q+_Z0k~P2~zE_lWS@1)NgZcc2ns@ObXCh8cj73BrLj>)R*qD*PT~?ju zTdXE-*!pOb+n5yt9gB)es10vFFcu8V0D*Jby~e3-97ylu_GHERF+I6gX=%UznmAuy z;rQG=uQW$WNM6BQh>y1(%!~e850V7q74Oh7-hl5lG)~4TP(;20cp8G77B_)qWu3i< zzxw2PfC%TR0sRm89P#>Z)sK zh-b|@c*(M4Aqf=~QJ2mKdHS6dW8{Hr=KH3ok=ryC&wdYT2PeEQvezCA*5YjWI2fb2 zw6$d?7po;8cvtK3BUQn;tdf%SlM_bgnsLNAa%$jxmJKO!X99~LD%7Jrk%4jdeY+A?8bR>Rmn9Qu5_2%x3{hCG+@rbDfgNS z1p?EpfAJvUwv{sGGK50h9{0fkeaXTsOn+eGdX^GmodQKeupX|>m|EplX*OsbF282f z3zlhK70`kE1xU(5~to|g_;IX3?p zv>k;%CIt`?S(&_S*U=b1AG|RmX?#ppS#?S~ae43uYYvxiTouDE6@>7pg;ob@KT4W) zC)7nh2MA$8GNi*)L*t^N1ZOb~nd9YTh>@8RERS#|oC@JM+po##(hxBzY2;M157+m@ z^5}^lTeSSu*dC^hSt6cIjGAv6L;(IJ%Y7x<3nY%MaW?4H)T(|yJGw+8cUs7Q&n^~Z z%y03lw$C_jOsxBp>BmAdhop*<5`Wdy$!)+v4*C5Nk&~0FUM^)q`i;38a?=zSBh5R> zC49RFLG_CRg_WP%YnKILv17QH`Q}PRZ}zf#@NbtM@lXI%qyg3n`xUQAN{33q`&d4i z--=Z7pg($l2u?Q@z|h3zDeavwc+5K2?G3j}gp@AqpD;`ndNYrrqNs11xKN1A8W$D!j4c#KA)Jm5%M&j>2gIf+{Up)^MF!sbEr;D>NsCfU-ch zn-!Ii$|p#Q7*BYz#pu~M4cw^UqA(KT4JUQv2yd2!8z8)2{KPgp))l^^4ZQ~A#V~sm zVq1MJ!CtG5!!YZ8vo1*QYS^7@A5aq)KcO$kaOZ%Q^KO66O=I8A)}#5CQyU#Oqt7_5 zx(zwE!KpmuCuz~X!+=Y86&4lEfPy{KN@M)zb5(j9zT_T`Vq9FjiOcJkz^W`q9W%fI zX%0B%=x|?V4h{~_lbQv+de1Ad2rL}3Ns-rtBGo+l>$qo&n|*v?w^V(!i7NU~JPQt8 zxEY4vOs1j!yO+r%_O7qjY>87aqHw#R!w((H&Ius85@M}<-!5(Dbs)nLBUCp@ze85u z4X*#tU2KZ&nc}6K#B$qiZd^EgC!HDQdpB?S#>MQ5)Z7(@jNTIkc2r5TK~v5ju)4`Ws7bstk_0~Zsp6q6a;b=hUbS`Vr zr!0IHKxlj6%kA@Gw>$!&0FYdPyH&6bdLZw!?0H|C!;o@dcsTF_JI*X2+$U*TXQHX8 z2(f49eZw2CGlo}3?BK)&<}erPJ^1n$w4*y2+jvSB)=LWE0UfKA}5$$l(Bs!9-PRK7L7nHtf^^iXGrJ# z)7H2K7O(Mmu8d<-*ksyg9tMJf2YHz9@Z@valkZ5y+=VQ-^L$vyCka!>A_Rd)))k@lM|HDGjh?wYFFXoHc0F`6c{ zh2U#P$K}PXU-UWDe(FiY{rJH-tByP0q;-7%;ChGu_v_V=f>y(?M+~83*1B`U*JS$( zNpH8JNvVVg4&Of9jzg`}c8z4p6tBNuNPeDg9ouWwPfx0?a@(H!DU&*JbW|+L@)p5G z$C@Z|nhlcc-jW#op?@Bj*%()78SPnqme0Dx4_Tly&x(O+J$#40ttUvnxvc?v@oXx+5 zEXnS#S-_z;H>c8Ifps-Rqp)yMIsrl6iHJqG{On}ow>uDkBESA;@8Iq4;K0Me!eZz- z6AVsOv!mpkm`fwdA+U1;H4=`JtjfxZvR=obymcaV0P(ikS<#0n;o$I~&#j@a-JA=E zq8VzwvuNKHvnnW%2}R9)U*Cmz%}Ape{xv~c^T{JGE`6kVvrA&a@Y$abCy>a@JO~NF z80;_*HdQ6m3{0Xn_l2~y%FoFGyJskMvS6=8 zM9s}|l?x2|pUf5>3ECOT8!Y!o6Q-(#WEaD;@V{I$&{Hk?XDxoD-3uKZm4h(`h)9%_ zvT_L?!P?k;F^uP%moFtoN8S4-8{;xENWoh8HG)T?9mOLq4_MkoSHc{}mr`OQ@&c0@ z^;hNJSX(@_sw>asjg0KBU)`#x*;q~7*zquI9$BbQk5jvsKF9fp&tvi&DC?|Fft{q8 z(K?jn_;@X!@O|RgP5)kmt08=mnXj;sGg?4#X=9^tZJo$7hq2Bc27?i#1>Q9wC<;#* z(rZ|<`2Eo@QsvrEx!sthcU>rNMZ9M^i4Os0v<&V1PMta_qFpBxmj|lM04@~LcAtRD z#EBV|z|`9;i%Jr8xB+0fygUn$?QIp%rpO6(G&MB?hnBybR+bCHTI)$)V-ETK>zCpC zMWCaFYb$x?`1JJ<8UrD-$P0kwja6RLFO*53syF7buZn|e09Kd3Y*xfA*E4&wI0#8Y zbE=aKxs?Ecx#)W3QUbM5lPNg9N|!;Qw4JI924)R;bgPCr0Zeu-Slq@!NkL)J{@Z3J zwi=Zzdd$}&I!7wuID_{6%MgJ6iDjHYV*PvZr!bW34bvK`MkgkK00`t_`djxaHE~Q| zQRi8w|Lz5QUE0ApRD?Xy;f#|mU%>n!rpAW#l_zwawxNs7L6a>k(z}y|J5q!NBmLwj zhc+w=is>vYb}$_PTHs6eRH}EFnbuFZ>o0#5G(>0ZK?!3=b{Qs0R;7RAlcAp@2aHc1 zEw$n${J80E-+#7#7mDR`D`c?3VpwX?~BZ3RmWUBa$<04r~7e zLjSPxjJURYInrYzTDS3`?r8=3>_`r@hGe9qJgyZH1x;~$`I|HtdPwRx)<5X;!@}30 zb#A;EI%e>jE@Z<9ZPL_E{QC8e{$G{#TbcUBE|CY2VS zt^b+ySx3JDUkzMd=Wt0Gh}0}pWFB&Xem)O|?=uOl-Bshtx&`8PK0f$R7>8Go=`SLA zG(%=>|9n1Hi5s?5r@;7g2j0~eFib#l2b})X5YCwcN-vAwF&=vRTCeE37&KaO82imp z`NMJvVm`fhhy0UP$0}i%BI}!y{93b+j)HZ1H|~nK(RXv>xB? zO#$unSH-mvY*{(G>-ESJAJ7)WxsIohT;M>;H|6y^a4l_`$pHyq1bEIcS7x4US>Y1v zP#r&?PGj_)1Ols29a>uo7w%Susk$JxOz&7SzrWIk9uscROCXb@!RWR3uR8tTMHaAv zmkHxzUbA(~JBytRo5dA(9R3*S#l=`MQ|%iG^b_`as+wBXVa$P7!{PqMU0p1+Fypp+ zSvd_1vS08_!P%rh4(y<_LX)0&P+kDGOh^RO;8;n+X3+z`etnlOJH51!?!gU7awy(T z_c(d+P`J5W;^Yn_1%Zw8jn`GscDN(je-8~s5kt$RPak1{yNLEX?-zMUVyBW|J-J9hO6=Rk2Al+*IQvocn_4R>EDI#zI1~8^AtBL^K$inIs3;n#jHTp-~ zweiU5AG7l<+%eV#LPz+s$%B8eKs_N2&(<_HRw(3p^?@CS1P{IVcLgBhu1VT_`?Z{D z35mKt`}%%Nt22pD0P86(o1G9cbde-PN&2V8#fm*vx_Oi0EEONOLYQtO80(IoM-TSq zKDgwy>+~i%4k0Rx&nqTyA3&&({ehUrxIGQt@i8D$&92r-(CFyEel@GMHX|lRN?ytam@AK|T@t>1N8v2zl_@kO4H-FYZl7S1AU3aQ~viC!$Ri#-%``zv7Y<~X` zRL%M)KN0?Bh}6z}QIX`bCx>w->Pjn>*X~a0w4?Cvp4Rw8-C5_FjyWVEPJXx9eI~L6 z2T2!(eJ`BC)Iv;@FfI*A(_IJz*Z4Uibqlh7nQP*BJTWMyy+1XM zp4IeHpw@@}(qVvz-?!hD@}3qgyHU@BzY3+02M~dUj1x}S>M7nUUzfT)D%?>Gh=I@& z=EXn3U7UbxG@Y?;o4Q-^E2&}1|2iY197-SmgD+KbbtC%XYK z{@^BsKbu}_M<+OnaZQ@@Qjzb%*p$?uwteHi;qy)$Y3#WUqjJkJX z93E8v?a7PifLSys6dM7jyLKm--2g`%yb~D33-}%DaostN0|}&cy5q63O)u}5_J-F| z|2BQOp3p;BQ~-kHC1NDr8)n>OWmwAh)6>}}UW5HpAq=Fd1>nvAPX=5~k+z`~E;aP< zXH*8LW<;hs9**J0uE$JyP@tN<03|NNh6|7Z`(EXA4*IEGEIC`W@wYXYYb z?7=M<|3&um;L8n-Ll%Q1=>TnzD7%T;e6@RTM?!hv`feHlBmy|;1TTW!Q>ZlU{Zh}1^au!^Jwk=hARV8{SNpV!YtN@#vS zy6gOoMZgATps!CEuttC$ml2bgY?RD)*o{X05|h<+-`AgximcWRl{3E@>2Mmq4N&j!^3^M7*zXkJ@!V1(RMtbw83+B^$ztP@t+GP zQF;H=Ls*jKTa!n~=C2%)K6TzY7)q4-}D%eSW+}BBK?M7FA7MD5Q;2<_zKZ|dw z1_36Z?ChyEZyT8d`OnS#R+XnpSXael45=*ljpv^^=n%} zdDb{fRKjf;W)0Bel}npWa>iW;A_eXWVaBG!I$-zF-O<60(*1x7v(DtFI+(*I-}f|1 z)N`q*07UAib6x1ya@ik@8$u33yytr}+o98b7@$=JY0iXmb91;f+ZisC#y2A_mQEO! z#Eq9^^_hSSh6JA(WEnx*c}1ZroB=~Z5H8Sn{+xepUESUoMSvN6QUH~DXG4f`Yz|`s zDs|`d^kpS#o>@pmT4H8faRGQ(l9ao4l7kN}!~ORM{c*P;GA}?qTiaV(f)oI^{c`_f z@7PXCB=fpP-d3cd&RtO3-y(t^dYUU1-+}uz^Pt*PA14I46sP)ZK5rjI+JS{X2dgIY zRFur%weExLyc6YOY1C`BL-6gxdzUZy$KKoCWi&oY1)k3@oNq1p+zZ{g1fJs?w~r#x zSQUDQ-kjySQP{J-nl8#3L$`4-M0aO)50~Aw>Y>NE9UO%j#DLb}>h8{r;tOZKNz>f! z{@!C28FhhU zP`xuY9HbkIMOW94`3)}oi>^zTIb@WcrNrImedrZzbfYS(F$PMYy1KeBhj?%=*Vd6r zumB^}CS9!*Up#`20m@R}LS5s(EzSxHJtJJ|VmfpCw|%pk*Yx6zA|M33v_uDnzLQ4A z?3m8Xq|UjVt8!64zq;1P6|P9=kT1Gl%u&0;Tb}|~4~S?fAn4>0SU^0muQJjx7;*#J zz%!c(RpZ_)YgGUr!a5m3Q|AMv1aw*e_bYC4#7D8`3oHNY<({^h@fz*0XJ1-Q1q&0j z%R*HoP)nPC)B#2eY^AyIdy)`y2QMrFtn@i5(ho>{9H{tAOICiKarR9E{Cn$>%NxQ zprTr!1#kx7d#7;=!E35)NX=S-7Wn~^X{_1@rNpjg zCPRpbTyVD`98_t~|I!}0t@9#+rzR=Yp)uK3umwy^ zZ`l|F=#7Nb?^4M=l0ptK0nahg2vu{4y%l~g_Lb>Xy?MRDU;aE#bP2?(BQ7G$TO02l zuf24GU5;!;+0(VpyR)vtY}o}Ft$lwl!ulKkqmdf5P?U>s+UL*8z)o>r`4k|@8GJdn zcexe4J%jOd5>7*(HByL;LD(FLhFJh2_)E!hzGki_0gN3ZwxlRNR_)Pr5qOJ+z2OrUzAr{CtwRMz1K582o0wz=c~yMI7$fCg%Qfd}h7o*oSBQmz z0Gtg97Q}FxuyPGd;!vg>B}MFI_ciXub_#<@;JewC``L|_ESxlcY2njdv-)QNtf=3x z-)=j(KmE>71}|!fpns|Os9&n}5N#pYKXYWrvY~`$_^S-db z*y&enNn^OZa%14`GK|o;&ZByB?lUbj-JpxTwqMb|a;QhMao4eHlc!J9!yO3e&+3Dk znvT3`@r~L4cZxV{hu5nX#D#}*fZ>1+$Z$l>x#xpeI*`p!l`OITp_~V-1zJ-7Ry6M< zgya9eSD>doTf3i}zkS3t{5_~Q<3gDq@0fggjy6IJ;I(!)o3bhqeu-}{cb(h@3yh4; z%5$GHA14CPgWFSP2&9E#Gq(eD&fG+iYPY@|GK!SO&hBu$i$8?zW^Pl{@{2*j=+BG% zxPGg}XHzxp-(*4uNPpa;R~;R52T&n0@&3%O5vqzHD$WEK>}?^~&v$}OBk$uQ-~UTK zBfFSA+~^y&`#oHv0ZDZ;i+2wi?Xt670onP;h|Zgu-;CS`@_$k3M>01 z#m~Wt2uaH5myO0;2<3rKoO>y(VEaoP3$}O+bpx901?A2&?Z5=Doigxc;(#eNZ`?GBJ9DbE$ZD8G<=YhC_I={kbLDc4v-ZWGGzG{a|A zNka?ZygyskE*}uU15Zj>N$e*?=dVZHPxk|(fuAoD{)Z#Oyz8%ATK^wT;#5SIKd$l-5+zKdFF~U{Ijxw`$~}TjvS1Qt|COHi}Ydt zT_zZ%hunZxUsPP0RZs_qyk7treaTg0eVw2I+(~+ew@*o!zDG_mQ#Sn4MD%Z+{24tR4ei6H zaYk9T1Slj=b@^dcSn0C+w2*^t0%M8hwFp^g0lSeo1Oa(h@!gOq9?Cci+JXU6VO{M< z+18{$W%}v&?y%RwdqTDY>38F2RyjET0F%K8y=VGP=+s!mt#=pm%U##xflVlpvUK5k zJfrz>WoCu_Sa0VXnTfjLzoJ-SQ%sYFf!Da_)iGXYumk-8*CM<_o?>j<1wec$5echM zttN@K>3zPMZ2Kxw)V~|G+!SQZXwbw1ON>`WlS@*QPd=T8nl0A28|nU7lW7D!qkR<( zAP>bD$I!!bFJDWrD_{7h_NX6BYis_$_)6kr>^NN-Hmujx&&kj1h{%tYyZ#ri*?{&W z4i4!E4Rd)XiZ?pUad*KTs48-3SsT25Eht!)c|y%#cj_;LZ&+6Uw(HhOy3YSa*k1re zxrcqguz^T-N(x9whk$e=QX(KADUEc4lz?Qcd7fwH z`)1ymcV~`glp|-C-TVGu*DtAdOqDl-I}^lvRH~Yk8d|?i?OH9!H=}LGf{m$+y zagZvx)aQA2{hbGi<+;D)o^G_;D^vL&00Z~StjaMGGQ{(wSTL|xWO3f_Z}j$)0Q$g5 z*l?v{dXGK>r9=(lP~|!oAtU_!<%`8?e{v^6<5{VZER$(KK#~PzK7rd$+cmX>x5?t{ zYyAm!!UM?c?Hir}i4}QmelKG4(JFzr2Xu6cWi%B&d5QPZ zW{Q`KIP}Ar*jOWpRowyM|8?-=*FUXAC$EUk+4bK6DdwOM|7CUeBl~o~LOK0M!#;N% zVK=*U%!6{|`(muzCl4KJo97G1*%}@DJQm8aNIz7jLC_-EI1jd;%5+}b_Vb!@i?qXYkYx=OLUt_<(t1;Quy)~ebavr$!X#l*ColAjPkff%heDnyWLgd<4TPJJETj$ zja3=Y3*Z-k7zd!TAZgi68FGVF{H=B-n7Bp*)%oF`Ytt><<18S zKQlU=6R1Q_=CnNfoJ%V>>-B3U8ac{6iR51q9$1 zX+gm+N|0D?a~*n7%v}-=W69Uo{Zr&#zSeq`WQ_SZPm;toY#i1gxd0j>N#re@$^wR5GXWZT3W8aQ91Ab65fW$`Z5@>7 zZg63bl;KLf2NhLn_mr53I+ryNiObRI(Y&;jF94(k*`_wwnZm0gLmw}@)s00#Lfgc)x#O)^fB6mCw!Q^ZFz6e4HCk$ zdMlcDe~KUNjD?u~p3hKW4p(5|aohDe*9zs%%Rl8}8r5j%d&po?>+L*s5v>>(-yfYq z=0#)rc2IGH%0JXB3x7oXSXfbQemI-)XiRcn?6@!69uuzG`cozrHT& z@vU=5h(Fz6y}UKbf@5e0pMHRE+U_)yS?sy4$>ra#4nhkP!+)u4xjqY8^U~?sk1SQM zO;oj?bh@lmm%+oU!{p)qbJRC#GOBYvXcm~TlTT3Fu}oIM-^*Z;?4A1Xk7}n{j${>4 z_jK}sn{2>@OsX>UO^!S`xI=QzRfu_ng~+OungoHXA_3a7Qp16Se0E`9YsoB{ZSrJx zM+=Jw)$X`}^706ZJSB0BKs*`*!*sYW$JrWA*||V{k-VTyP;qi=j5Vq z43^)O3 zXjs;*CE;VpoTUcIrm#v=goeVJ{#&krJ8bUHdziUlR_|ua19w9%E7HReA1xRlLSU6C zsbb!*-KeT*%37PTughE zF#*?rAOQcXq{(m;prJvEyIDM3BE+Dyd*T#aP1@NMXo3NR{UG@JmH2r^2E101-m8(^ zgHvPTf%|cjzn1DfKEZxn^CVv`?APGID5#+Y1WO{v45W2?y{yH>H*O$I*u!&fxyg3$ zXt^2sOza2>X2gJ`@1^Y~Bvpd69Tou_YddDzI7k!@EH17y;Ci`vXZI`^^=S|j@R~Vf z8Gu%!0v<0fukiN3mNAA>tXwB!n1B!nMEYXxb!KKY@t#3_)x~L!$SHG5y&A?@6&YUt$#(zhBW7;8Zu#7}e^EF7hUkmmmK= zZUhk1;+>GxGUtDa)*qWns@gs=XVD;^oOyb0{0c}7H9}&nd5-dM_3mJYiA!w;)w)ci zx84`oOGy~)5}r9>%$_})9vhL5W1VrD2~N7Dzt`}okIlK8B`)Dx^n06>@JVRKSTaS% z{OQ%#*AHWT+-aJa@_KM7lTbchivCTBEhxv5LWjdA&^gy`e!_j;^rI}G!&4h(W`>XBXfHvW2OoVx9CTPzKNk15 zNzpAYo5=%XVOWS(Qz$1}Xk0Kf$m8aw%91lop2?5zs#gcEi|+w{(gD z##6FUvi8-QyI2e-zOh<-(jtirkXfNr2;>V$tQs2BfVSvGy50)>dqTQ<1N?#(+MLPB z+Hx!`6x3TR0eA~{r3o;?24L0h{!_-!$Je?0gf8McYhpQ`0B6{wVZ=D${kgxNBf1-f z$DAb<)h@%M$JAM=6($9k^AeLn26U@FCIh{=<#8KCBnHxA`u#}+;u(VkF|nXkhHzv! zW%cxKSuDC_s_C>#3x*+BA)Ww{m?+n+pwyX%Aq8KAt}^KHM3sN3#;`@!Oq;_S@%PY; zkC!(Pu>x-b)TKj8boktwiRoB$kLjq5+E?_@+}us9h7uEsg2wGn@(C+J;kDUX_o00a zAM_lm<8SQ+p?UAI(cPS36ptw{PdeJ?43@+pVJW1?8JxM&+9V1J=)-zw{>*MSGx5lw zP96jVVr1<8LIt9iztck}kyg?JrZ|RHp!70lkQO6kypv^aYMQyXrvVO33R+52bFc76 z=5Hb*oDri+M7MetRG4KYa%3m|BA}w)W%=I;$h6RcUwmEU>+gp%_A{KZDX?L{!otd4 z%0$h@NP)9>a0}*E086RWZdVKjYB@<~6X6b%hrS@#=eFoVc)mz%&R^7t;i%`qi3yBH z_ObVk?QY)b7~!7U!7lw2nUC#IC^q%{&V2?YJRDi1`Ecn7Znc1~h8cxOWcuASS`!A3 zOzWm71Bu8IBJwZVe(T(?OK{K!-ULn3)esEhOVe-~$_4^^f* z$KBEpcyv*rEBD&|_g7y@*8s9nM;$h2eCNIk;*30muyuwk%}5=GQ)=!%9p zINqOYEdF@wMY*2hxW&E}%^J1_0sQbV5RdMsu|`HfY!g7r(J^?5;TcQd&WAlXucqXB z>cA}w6*V;oSW^|F70u!_*f(mQ?m*X<`Z92lS2)<81JeyEWOb zOee1zKNOqGN@*u3tc_^4Eun1$+fP7Kzkas>- z89nY&(w=^qzF9LE_3m#nJ;sf4bNsAk^>Kd}x}I2?rQO_{)DK%U*cfmv;8)<45M?#}L=2#+8!?bzG5H znkIV23sUkZS9d~qj=z)CB(9eH-L!CiUS2Q|0cl8t6Uxf|sf`Z9)CBm$5dl(Z63noH zy^~<@e)IA1K^<^!1#aV9AXAz{14;HENsBV5vmsv%0u(R&=AxruKUvPsfX|z{>%s@Ral2K zJ%LOgGD3j`exT-{<@sk?IsJ%vnbrH?GzBZ5kXfXtI1;e}c6GQpB=n(0$YtufCG_<< zGc$LGN5{aE?CkBOhdDl4k)hL+7)0XGu(6?%?kf>o{4zY~wOu6uu^?|XsjBELagL2epDje`AA%cJQ6Kbe}}L)`9|IEw%%W1GGvDrr&#sr!CO3XP&8%QnvWovvU!rgLwTT|e3 zk#%v}sUe9xSm(LxcGNH}-;BR{huK>Z%@lKV;B;4|(bk@rvh#2=w1Ru(=;)%1$XUIuuLA`|DBIeDt8^k!_~ATw z;I1|KomY5jxOdmY<~TutfQe}|bW$^>M;n*I+$GVR&uk^B)7!Hw(IVpXl=(c6;Nn7D zB|7J^RRCLs-Qt{`?mt4Yl43Xv^8!}b@Tvkr_SSiEI;0Zh#EiHtERv6X{VT^s$Ska_ ze`U&5m7)jGOIcXprWX)WQr(Szl<9Hf@nZRt^8r>dB^5$PO48(s^@brY^Q1@S-&CX} zA#eTPt&c@EZL1iI6%RCNn{Z0a*wlO;Ab31ay{@SaBs@Bb@6V#o7FY3HaK*vNmYdWD zn>4t=_9L+rLc=I&X@Oj-u$zAQ<8w2PQo_5;%=dZAXjv@k1TkvgoTRf}sSSp(Mq;2& z4CsgmGU18l7yw5LGfR&W^AcLnU71|IifJ6E{8CDQ;0Y#TB?6VjqRCD91iLOw$V(^4 zqP7A=&`!{GW_g$e$nIxGDC^s_UF>DcA3X#VeoL#`izkN+YiR7_kp0{k)>5pUh3s-- z!NwSfhhHi`5V{8Ta_g7RrGVaFUfCP}p`2m?_uG%3Kfi#s)A;yY7)#UHa<|ypx7cdW z(unV%$!T<2*1kxzVCst9$I9a=?R&_20jk-8<12h8$+jnn=lq-Y-JFk(Elq&qp{+(7swa>g4Oo zV6xH&$Qg7b@&BDzq3uNfyWC~JwIKhL(iEnxyr4~RiDBLFSm$cTYvUI(qFZ!ixRMId z)fF?KH3Ez?6X$OMbW%}{=#VoT!uUaZGuxQYkDZQNUNvIliNFYV}oZdOSSzh zY5ZS^^(Wdmwy~RlcHc{Dsv0jU)!kPU{Cv*JrC2B6HXmMa#LshiZNpb6Q0iI^cQ`8s z2I4g<7HhGBfQW_@Huv1=IRn{mp1Ht_WZvdXHZ2nQgGB_8$=fm4ymfnsK7z9GJ#6_7gj9mbZ-Oc zYdOQ}_J%h-GGf}>ubY-DX-&A@me5yW`4`mqN;=$@#K3Uy-!}qh*msLxVgz}|$Z04f zSgJi6bmvC5hU1W;<-5dqIkWBtKMKG^E;s?rhyQ zvG7f6jf@A{=;zJvE!a8r<3_56#~%GnI;42QSLUvX)DkB*ji#;~^Y2D^e`Rje`|gE3 zTY8*2_9WiTBl@DJr9GR`mc9kc&!qAl-H>*h<^SggeEu!dZI6tcx2=>) zE`;ibZ~N5Vf80389{ahpWTiTLTd(=AxYu04NMn*$MO@G2t`1K0d9HxKP7;lJB@<{m^4nRhnRQr|gd7F$)1pFUA-`k_*X%R5=lZGpsdOh8^#-w};CZAL^}xX@ zn!BebLoz&=T+7fDRFhIWX3%;w?h}zl=Ju8~YF`_X+{cMuFoXlLrEoF)ezS zO{}u+*jd;>K(Lx#nFzYnm=ejmFHU1*>ON;SG$;`5QNRtpV11X!@&r*^`C>xRNtFGu zEHWlO0{L+CjMKCz5e}ibKW*F25N_fuVt7q1FELuNyO;fBY;YKxHtsgC>xh+z9<#!n zOlNdELCVs}xPeuMEVaaN#nHcMUwhc>1k;{;#OdIH$%2%QJV;9VJNu0SVM1vhmQ=8? zXYi}y(D1yqphB>|)!FCI5gxZ2Qq}k%1!*J}7OOaThs0T#nOJ1Xq*tQIh7F{~TfHF; zG21z>I+}<_)YTvpggT&u`4&qKV#R^AtGTF?!hvl_*!(T+UTGe z^fY&uBikil6~{fV%(%Rau9@|@_^OO#^AP{0X!YTD?RPDIwB}TXMGKTa{qU?eo^-3e~^JvodUF=(A=yL+pMll%2dX0)jAiVxD%5kb9~CY zI9aK9{;?e_t%@Q({v!1S!ijH>vVG=Z-BP?$BN8^0I&%zlk z{27E(`fg?{EEVEkM(;&n&Y%9M-Gx_}+VG11u(u;_D8R{2vgD*~Qq_56j>ju};`-{;*u<+YM`i8n2f^BR z#^!w?b8Czw9EA-9vDUsI&rF2Ek}(9CRm7~Gw7eIkkte4_D|QCEs?HJD>20+XvgQ@t zpI+Eh&-~uJ50JK5ZyJS7hMVS`8xb+IB%=A2m0^I$s1%yA6~$=HOvQpqGGa?L5#pK# zHYt+9p*y4|SajQhq7toi8VN9ye;Dgq;#JWxYNmfH5c0-!Z>kW_p>i4p=0Rw)9G@B# zmlm0S{XTnR?aLI2NyD5&3WuJWsyz)cv6*>gfvYV8Ekt~g$!o(}PZ8QSHH85cQji=; zPa!i-nh=3zA_5Q@r^(`15K6g^&yFhrIO-6W3M&IMi<-FcEoq?17Z1Ij>|=R^1w)bu zwa0B@VifZLcj~VFe2UQ6f(;XjTS#+E2qeCJ12i>@d&iH30)wbZU#ve$IB9t|j0BR- zRE$V^+%hWPV)~rpMj(%W4t~ZQ-s=Pi|B#R9Vg|6>dZr#@{Z>#r!9QG8iiRPupe_>^ zqE|f5NEoIAuSC&$FI9}%*yOCdM8IkLv{p03;|lBGrPOOk*IX)B3JnX3D(Md)y0^fhnJHGerpYiv$v#|G;%2eIi$z6d{ICEM zQAnC*mY48~l0K;<_;qQBc9f)?=HO65?|J;7{6oN4hIh^;;nEd@Bi&zJe1NPu3nu;U z<&qopfZ191#0h&XiGJW?v|_`n{qF+y`u9H<@N9!Um8fUSd1GdQ4YhDtj`8_9@_@O( zpw@x2ws~W43cFS58km5t4kk*8;*1T53pnrYY<|KudMsnqx&V!`_u?NJxh+Ihu0C}P zPWqW=^rrqH?}WLs#R63lrJ)x2j(us6y5dV z;v7TC?@QCVoQyQn9$ejcX|U$R4s@X>UQAN!8?u+Ma@C->Dc{*|1f;%$iX??(QEo{+v| z=%KQ(xW(P_mnfswZY@^S0SUpS=s71yaNM8N`*xtKRn=CSc42|Ud5&7bH$339Ct#_? zr?np}Wy)5Hw!xK9h^omu&# zHnWvvt#11FnzZ@ZUcc1!Ztn$2?fB}BXmjb zmA-SIfMHNxlN3!Fa*@-zl%MnBfc{?gzy2x;NXAUn20bz59cp?I`VCm};=nf8i>&w< z>3yj=`EC2~2|&d#sr4b_&8djvF`#h#WAW3^l?BD1aT_aQ^1i3emBE}k0LpnxwBTMr zstuJ$UkPKEEUca(_O*Y4I9l4WMDjqO6_wh4wM*JOY|Dh@h*c~B+5>RZ=A^_<3&2`K@I$>Y1F&Kt$5FW<&VnoQ@0Ct=!hcTXqW>c9Q zYBxeUgtHtN%fVjW^x&1muKc3TS@3wmAaw8NsE~=()4jxwq_=x%Ixb7T>V7u40taxIF0h@0V_d$o0`Y z0GLwA>erp?zhNd>%@!EP*^lfTm3wT9*a=dV>qZ+kdL)z8Ti0Fu*C#Uznsm6_Y^Xeq zuFC;;P~(gj2uP>1cLd!B4hBey)4|QKs$x8&>(k`4Z!l zyyB#y)oL}t2P|XCQ>|}`_a``BHc%>6@KSC{mCMxx`idaHY?Y1H3Z5fazCJvp#er zHhhwbXS+{V17x7(pf1azw*p&lfAOe_VD|w;v?zTz9jzK~w156hfyDfdZOM!63jC*< z&Xj`FAxtxb@>CuVLHbTvvBH$TF1ABVG{oYOkrBE3_-mkie(r$`pSX(Rjx0`0v)l90 z1_1k7uSk5MxtIc{LOxDh1c+OYM3OSn6V%>ce6m){q!j-Z=Nq(=!@6aK@!%` zfRYRYQ1YR$G1!h-ba`qVNYRZ4BzPGN^IDO6dl*2zpq)#fOVAN7|3};>r^Qw`l;mxQ zAcWoh=_80PrQW8`yn@IK;&@(2;8Dx??fyH>`Wo0U&F=@YM#?+efdO@K$sWt@ft<8V z%`_^KPIVc}h*kOq1~p!)rk+N`?6!jT0}_kJ z!eR%m{BD}oS$*a(MNq~?13dhm)qBfB6u$YBy6FAL$3eL~aDmQ^jB07F7(_16eaI~b z8RF2?IuEqac6kOrg=|uTXGTsXF=LaHQ7_g*T+8D*!lRS{w$##@cspPLKLjzw$zPQq zSI$%;&vgn1LSo6{%rtuG-vF3P#)`&nq@p317F|U4ZU?~$TU1gE@xOtn&g`L%^%UCJqN*kXiq;Nar&N?iVyz;9iES|_8x z*=8UR> zk3E7;=d-2Ja`DA+?|Y*9P<_+iG371}nJ|31HB`f4L=RogL3Ww*vH}e4T)zbm6_yQV zfBEkBD<=KVjPZZJu1S$>8`PW+TNlqo4p7Pv(L74P)pJ=YJJXvzyp9^Q=l*cdeP0p- zl}r3LoV-mdTCJRD_k_VLW5OMS=$M#2ot$$feL=_7lEyzUs^`dSW1CWSNNJF`4U!y% zBf^V|0fhsVZ|VS4JOR2*@ApkVq5@RaK7<+`DE`v@ z=GHGt9IDaF!TF7hp_y9xN=EF@OEl^GxXm1kZKf~Tp*As{EtBgW_2D(_J0(`*4Obnp z?3Y>gRFWNsF<1TnG9-piSFfVpm)5%_PU23i+UmBfJM_yA#NYGLXyc@(R}$=(vFEVy zCnn8ZMSka+??t;9EC@Ur;$xaj7FHTm0N80;O-SH7EJ^oT?aWv){zpa<_A7m zrl$ow`zq_9MkMC*PRqFGzb9MGuLAwHB+KH${LctHe|p~zeevE#41ddPr$yZNK!3p;Op@!MSWtpyko74HP!m8OVB0UqTmm;ModrCFrrj{)aZkXx zfU0WDdIKl|Z@2oa>xdopI(qNn50A~c6B$nSt-1XD>&7o2@VX#9xMSAS4v9)@`_s51 z*!89Ox!8g)S5N0L#T+!6n(@N5gFysW|Js_R#07p%w#JTQ0CLuDzKK#+=n3g~u8;_C zUxb;W*9QKu>-iKRa}VQ6MOx5+4eh;Bc>To%Wqz|{E$8{%P!dZ9^aCXg?fZij%dQj zEnAr@l`&@^Z^aeHnhFqXsf4QBm%X3HKo-R(Fx9hX7WUBBOR`zqkck)*bc*ios#P^5 zCMS^-0uQ*ED6kj@){cH`9%wF%ydK{$v2&}UuMofZ)d-4&hT;?z=E2=w`p5*9G!>qQ zys?v;oCPA8&`k#IrADRX8FOlUlq{)@PQ)x)6X(&?c#1aGWZv?3lT|<@b3MQ$rR~C0 zmH^FsI&^{VeQ^T>0LVlCU;2Yj+-B2oRO*(!gC%Snb9z;VKn^IM`0^JGjWg2$zaHYz zdPDKT^M*}t#>6ZpzLVe7wH!laH|Iu1aJMa34F7|#Ku~k}(0iZB=jh!uAvNCZ2h~=B zWWxI2aM)edld8&o-Kc7hB89D^XPM2=-Wd~CsN5$X-Ks-ER{xi6>~8;GiB6fYWYu>= zMGz(Ya@KzLyN5__G?b&B@{UiuiUUHx&Y6~nhu~J)z7v&N&rceen~VX!ta~n)o?hhV zdRz7Ty$xdA8OvAphE}YH9$OS3m&+rtwf<HyjfpW(MfAGbAQBJM!JHrElD=#lt zRmX8DMc<*|LQZs8{ET|@#}`hKee_`IlDZ`<2vvb|-5erT?U_jU>0#TE2^c8auPWG8JoGuUBS4GSMMRB8 z+)T}EwD$X_{n_@6{-3taa@p;-_iiVww5{T3lG)utGmYTdkMy21mJH{3*%Xn|uvtF) zP2eCOBPhHF3f9EGdHv-nUhO}NWW(mn%fEbnK7Ts)gs@OtPGGdJ_qZjMw7}@|`g2+( zkEdh?L6e4>cd~T^#Fd|m$9}~mP|01lF;vDK5uoAGZSj3*Z*Twes^jeBXFx#g{yvY6 zadU(%djs{2v?Qx&z?M5sI|dmj?#zh(B* z8<};!(u2P{d9`5dx;t_g#528?u3%P59|C5xz-GO{=vbdI8SKoRqXo>V*8rcgYcgeo zqP4BrR>$s#8crKAJ%B#wL1avyIdoUPfMH^)Y|({pL*QzEI$#kphb-q#-L z@9%#JEDB(V@Rjy+1w3=OK-gGj;_XB`+voS8z3I-3Uj#9$y91O@bOrl!JKb0|e`mn+T># z{noP#uEy$W+=2rap6H&S50CaI9^u>%~8zGFRk32yP3lsNiAj$m5@%+uYoou5)IDuu7P5 zO=@Q$(<-i~<7)^uW@r#h6pMRx^u&lj3=O15;d+Z%w@k5Rqn9birU>?+> zh4clW5~PIY-H0cR1H^Ug8zQ?4m;oj(pZb}T+wlUKKA3^(397$5r9w6D>eX2j);E1U zuA2@JmM>y-gb?7K>e=ZQdr{jTCHasIQ$AXbeJZ+Y_fUtWe^Q^y98Yn6uF-RRrY0If z03yKSH#YM_fh)tpbm^}d4Jj!p^c=((_{_OOs({+F&$@w=n-$syShEB` zY{RX=Yv*~5FC`}@cG>Lql${`|T(H$&98!|Av$Mwx^$h5Ts&R){QW*c!VxaUGs7Kc) z1Va;bAtO&=xMyU41*!1X+J`$)*s@kvj?)2KRGo=_`FBGZ8@=~_1rS8gX5Fi57zqz* zv-`4DByzDEc60!UrPCP=s?WF;xo~x{KtUC?3rP=rJUl#RpUwijBwMd8cD%1P%c?Xzjb;TBrxFsLkn)j zN@n?Xe(X3QJ&A7603{dhpcIk4*H6+Z`xO3@X_MOe_*MQ|Sl$-P&f@Rs*sLeCx0x`! z3d$`vL>jInYlprI-{~S);?OTo&v5YO*RM6~*mdnbjZ<~+>r~_+kvJapED&WAHzToMhnj0kt_6>|7MT_HQEY! zKpY17o!9far)DcVz3M)?A*(p4y2$%3(M?O6F?E0_EAxGAVH9K7k?TtD_0Z5$kd5LM zV(X<45`cIUYNWt5LD)4dOI%^cNX-SJX@V#<9$LyQjUFw&zLga;$X;;jZQ6-MJmMih zs~mLOlgP2YHCn}_G-X#aw#xzM-kujVIO9usHqK=jq1(s!ZGZ8d z^bD}UpWFv-JKADkvdpBN=%pqM!Oa^xwibJKA0wX}@su ztOkwQBL+g*aT1u+1_!Zqf7Arc%!r^pY&Ulini(*U6ecI?^KZCK+qll`0@%4-^Ev;| z`U4gNpViiK*YN=7%^!}g6Em&d$g}|I%Ky0}Lb_~K-Q7tmILQ5V21(dT3>#zPeE%{+ zewrn~_q$#{p&8U^@Il7ORF7nLdbMqo1v#hDx0>x)Xtf{oYF>M@;UtXuEdYn2kYR)d z@s|)&NmgUOF!WpdllP|nLVuQLOGrV1g0BP}ZE0!U@czEb<=^4U=-HjR;1Fzb@Lyx1 z%cAMQj-YWMyv#oW#dfxFXfk)6@4}HKPUJg=^ei)h8G=(!i z4L#=`EbF@e`}e=m4p@zI2ILs%)($qg_4y$c70TSRvzzfnXVX8v=oftwQpGCxV>rI! z>`>cyJgq&Mxqx{|MlMEOm&@;b^6!Q*qq%)t1EIq zv#*?+HVdh@k1^Go|FY5gT_)lv9wIgionK@+qE!+T|57}_2(oVFg9UY%3R%E~?=X!QN#nzP(ZWl8dZLKkWbS|vs*=|D+Mg%S zjC}XcmKeI3CZ%>DOYV{Ax}e7wOZB#fJDIQv&Q6Px8iRp8 zoHe|3{gT<~5O3JgZU6BdZSl$s1uiZi}aBgs;$Z==r>>1Oyycl9iS=WIuKj zL>BW1jHnAHzSv8!FsQa+pRF+-j@@)HMdH?0yjY%i^R=Kui><&*vy11O&no0r4-2*a z!}Y(&F#hjG4OtOF&36=uBDvO(HJQezAq$&o!sB~tn{pzn38Isp z1qehCd_rSs#JflH6jhPW4FOar{`5(&`sKaiVwZ|#CYXe;$!jPTj(083xeRcMolY^r zNEL@P_KFQS?oo#%8w`x9s;XW5t6du--wk<>ZU2bY)2mCY!h@tb@73aD-%IQqtD|hg zt(gm=oU?PJZn>$qw7IDCeev1@FK=&9(j-$$ItR&y;h~^(iKCNY(!h=%LQS z4>%q^IrMDl8WdVUYfItOuRCh-@$M0wZ--EyVVx^vi|JOy0Qa)~!lmV&*yTyi73yH# zwF)>a^xYURHU+o-=T^BIn;@R!$9JU9ZXvKk~$`_Mor>hf@W zf;IjTk$NY%L%#nI9GhuKAZ7nC^0Vpn6V_;^K42#Rg{>$~*Sg==+xw)Q@RX#u_-(kN z21$q%efanWM9Kc7#kW{ZM#)-r7UbOB#Uot;=bf*qP5`|HPQ=+Y+HX0r1vVcvl?1dQ z^N&#psqV%R$p9IvPI?dB|KUP|Xi_r!WW}q&RStXmyrQBIxZnD=T=QtWnW3tXa1V^i zu=I(E$@TORQ;XEa-Gq&F)HyRZ*B>#8=~AyUI{lpFmP{^BRBF}eOifV5{(bWd0Oyr; zj+{Mqt|)1mTiL$Me`3g@$@_G51eaq2iSJH&5lkqBnnIU@IZXqPt%a~RT8Za^P^_vuEV7bGZn?R80#9Er=T+HdU5x_~F)?C{TOmt<3K zXD3?d3lyWY*G&Zp6I^rOmbCeD?8}lG8bs35sWvt@m(#4WbDJRms*e%l1}FCOy2WlP ztE7c08{%0{gQ!7EFa^A!gImjg|4YEJz?Xv}k^t4lKv%zDwto3?1!mOp=`H@>$1$Y= z!GVE+OXZM4hu$U?Ac=}CK0DlIKa4wqO$5^5QU5qsG&k2dMny$g3-l+dOY|KKOX_Up zrN4W}>hEzIZ;N}ba|t&TDmWx?39!Nl(E>-~%g6Zs(-M-EVxQkiP5l4Y5_&BY{N?^o z>^o>P-hUJ3!>XgpAT7%(0dr?sUYr;=kIeFj;JfU|2tbytC4m0$t}@ZaWn_t# zT3I{2y*iJ(TG?G>guoDeJy^Jbg1uV2q?=ba)4Ul)&J6`%!(YOY?b0}a#+ zgAvAc;7jeu*x1)f2(kpCfvU7FXw&1*O01|OtUQyuFvjmnUL8Desn29PB)z6`cV|M! zQ6}LY1Y+6%4NWLdC`~egOLIL?-=RK4@}g35aWRZ;ahdLnf{~GNtIh-PKA8C1<~$d= zQoiUPk6uUu$GMXSS+5WUdH828s=&4hZjthu+7gg^j*60nbQ2Ld4b#aILpT8gV~g*< zk-01A@Us`#SC_Nx+DiA?XW3p$N&udfmU-=&&O?D56kg?Ae6u?4h~ln*zfB^)_^Unm zvtcb@SIX)-LZYP$N-))ci0%enSTHUX7xK7#*{g|m9!Om0rA|x~yf7-s(^jCWLmbx? z5gi9rE$AYmqUE#OKb?EFA&QAa`^9QMsn)Y+L{VL+ngwWN8unj<0-HWYsI#F$pr9tU z;S_N1mndoWS#aGPEszTUJx4MiSP`4(X)2Mrb_t`Sgy^?VDc5)I5mDZwjRI%K6B1X% z7@MLcF=##IEgs;;aH9H_JQ@ja#k-00Nd<8G`86{U^Nwv`j!k3awlOsQ(b?hoP)rH) zwbfBPH-fcjY}Ymv`j(x?zkJsHJETW>2gs(BE#WPo-i7msZ(DZ$r@-Xk7>X%M`c3|7 zYsZu_s_`w`YI2i|g~dH=axU}5uOYW;`)Ic64xa2MG59t<^iyqYZ9ynmlJ+N^Wsk;)p5^m% zE6HUb5xXL;{9EIyZ6{w;PQzwHE#?)@?Y9>tw%184rg=<*=>(8l#jAfnIWAAOo<4{Z zKcv|6$^>7=;nuXQnI;d2tet;nKbnnlm({#t=X4XGumL>uMi-&}YlF@&#H@x-%RsPxeW{hLNE1&5Z-H?4fLl6E3yU zg-OYQe8|#Bfez$|WOlebyTgY^+jTVbx*q5_0wOb6Zn5d{e0B!o_@*3#8EZ(Iuxq(f zI|FnzD?BSPcmTA1X%7$Dl5^#9IZ5N(ko)BJ%04a?8+PjW__%oGYkH@NfvJV^$`;S{5hmZZvCV!O&inaF+?kjQb!wg)69yckL;~5Afd?N zR8xcy?rJNN>g-spSMT6i@C!O)T!?+hkuW~~`QW>@gO}cmA*Yplq1}h?Ke`^_W@0<& zkbdFxtZd*3%v)TWpl*oi0naJTC z^cy!OCbaG5YDlFCj!%aD)d0~EP|eHFPdhyoajB=~*K8sM!GF zH$(_I4{!=q0?vSnLIg7L6{rg+>FAKhd&HefygXnl24)dJOQ>(1}ZZ_@QO&thpr;flQ?j3VPUg+Od-2{(%CfwPXS zS@yFvdo{JKS(_z|DG-SO|DD2F1ThM(g-sDg7F=B1PE%eWJqa)%wYj}LIIIpj7Y9Xt z^0{-l!xhda!Y8BYN?eTCt<1T|j7_8g-P8DLK|=$2t0WMnw{nkE>;y%VwI={%Lr2c%UJV4v{doFHegc*v`3rO)mF(*S>=4>+R0KVHt1e#p1dU720@4P6$ zn2K1~Dg6978kQx<68rec@dE-82?qX2WXFbE23}(V+Z3t%K{IpCFkw^|1s$D*^$5v! zY&0H7dZB?DBA`YDa1AG;7IMax8|NHezPw{?_mY|9K2#QfXAU^tmP-eKvy}1^tkYlq zxf$%{ktA0USMlrVPvma4KuE#rI?b!}RJ==}i0@!!dC;|4lyBdz&x*~(hD%ED_8xh9 zc8+J*k`Tjx>MnagKJQT*1VKbpCAmlR_8fajS_#;Azi4Akw}dHt8P$IiUC*+QRr0*q~t>;Kjw4SZhZC#WW&{^sX_`Hn)I(wDhDPKEW!x6<89g2w0!)ESvwBB29k`y zq1|1cjt<#lUx^4I_|ZHAMgv79L`9uH0Bj;?c~C2-^lj%w4I{G z3O+I}gK&BbH&4&;IYR_p1IGVK0n{9g0mM1~1E0R~tm5L&y7fd*?})`^J0d?m<<A6$nGhrYz&sI=duFD~~>{{)$ z{hx}l$#=f>K!rIGJQXQFegO2Inj8v#?GInEVpC z97S{ijhm_cX)=W@Es>O6=U}n*SlQ#xPbF7ZY+6()9Ur`>J*bxfXSKa+0hXv?mU60; zwLdz~{|~6Q7H5q}yxG&L#_-_4bCATZW7rui$^$V+xFERbUd3Qk#;`nGq zLtP>s)+i7g$`Q|5&lFuxernohq|k$(Ffh2VVj%tY5MMD*I2M zBFYy(E_qI!?(s4xKw!Qvkaz(W!lQ_LK9+W#8>Vmjqg^VFbf_J!?j|~qr>#!B|7gQZ zbQW$&CtrrophQ$$%qJ-Lb-tNv4X?4(wb@4Oq!ow#>F{3lwH^N@0RbwYR5 zSMz1o>uh$uy%e&ym*_v1Y_fXa($*#f8=@u(963qEzrdWWaaitWFIl?SIlE?jmQ%Xd zdUbl`bTPD9zZXh%@^>L1otWiYQXCAuK0D2EsNn83q2@G{?XRmH|0Wp9#m>I*pZ_hC zWF*0=gh83#lEMVzb=$9B1X(mRP}=l+b2G|4M}{PS>A^cbkr4sSxA*(_zz_{4Hk>)B zKIEuC3@9(D(MZq&VR+ZsIlDhwYi~8M#%b4LiG8)Z5dbM#bcXzq7VV$CBvO}Q^GAY? zsBH(o%yRoV0UGcw#%D8=mRrc3t4lhs{k}p_O>oI9^61yvqpm*qpzEQN2hkJ2edrw7 z+U7oKG>|f=KLv~(%3;L_sStQLz%JYX024*x6B8!_(2fN~Yykn1>BR|;^N-hrT2VjA zsR|4BNrTFe*0Wjl(b?JCp@GFVT}f3H9Lq;%5Uc<))rcAk6hVjyv4$D~VU*_63KrU= zpl!9x@eJ7c-0s#fGAckS-V(R;OJ%C$@0dh0aXV6n>xU9M&9|+WPFp+S< zEPws2T0Sg|yRVwTpiY2+21obu@m|M=r+s=~#}8s&tba`R4yc{BY$(gd1INE*g*iVZ zz=B+JBm@&T7sof|Pq>d6D2#FtnBQNJra_vgd}@s@4bqU9Wrkt3L%8-m7QdD+gq~dZEyeA-S_wX z{r`{u<8e;soDMQR_j_Eg>v~=h=1j3p9UZ^?*N33zC*Wey!E>Z;MjoU`g3gqgL;TkJ zRjiJg!UhpSA|ro0km|Y`8fQ~4G;{^loBbYaf)#ev5!4olRy)B5sVx`6dk(WIpezi4F(3;MUg?PEKsxL&3x%Gd{D6)*+* z+oECC)LS;2vHc3^GaF5apn2&Oq?pN#l)2;+l zsatTN8*qvX4Y>R&Y8OBaW_EaKX-J6k_4oDp9|)lRN;_a;PYnyZVW#sZoU_E_ytdoY zR+v^rW2|DW-6WmfZx3CpmBq)jd@!+<=GKt+yuXYxvrl`yTKAjd993`=Y46%1!U63r z=vx{qwqK%E6RqKH?SUoVT$@z3-d|DRoh2d_5E zDf?7g0`+I+H-w7#YuK+{Lz&T^M*F4bd7Mj9W^Pv^=>FIV zUq%aW9MN@?Pepa>gfL(SFANGTUaA#Q;BfwGKSR34gSky>2)HURnq_5UQzykzmtfIL z;YjK>zj6igT|E{GM9N9i8s@)T*8`1;NibceYQjCQJWWv-JN57M+!Gnssa}0JpYFOZ z{ZL{oU?A+NLA057a`8o|8mE{tWb6qgelE8efAbp~7zp3_e%xEf^DzApXHUS2v%2FZvVQT~B#AUNw_o@SFF<6kk7oUZg23&PBBtrciOzp>9ySuXQZt8U ztF!&r#>>n|fZO=LN+R%!zKFGaQsF{!$oBLq&C1bT7^V@zXo-oGKto>xlxG0ofmMEk zEqcKJ4?7$IK`vh2<||#s43hQROM1(9PlYM=5xCZ&|IZ);{m#*>(W*8uY7Ad{K5hgX0#B(kgw=Y2g$QRtfV0vxEp zW&TqtK)2oJU#FFQ&1w%;#g zTze2+oW#`)O@C!(EBuLE_ez?k>^u1w#6-Kg;yXp0&e-GQ=RX&SEqNH>=xe{tQ|rHV zOb|pO&6X~?@W_=_P~X_~4^iLdc@u0HhGA@{JU@M!a+eI<`IGEFvs>frxf%I2(xd4pyJ-nzfhu+s}A(FXn#t@Q7ry&%0@BXf-CHvumUOW=ntK z%(fc+COu~S+7~Y9FWzZ#Ks^3iB{yOybMe44JpSUv#0yvrPrsNq2PRTY{9;qhyBa#> zD@_>MS{~hCcj`WD=sp&C;|oT3+!9QcAwlPl*9s&vsD_C2XgHnnUEPxIQII-Oe=%W! zAbpV*z;ht9yo>O2%w{jM=tybJswj;+>9BH7^AfUf&>;Q;|#BAnmDFeSL1Q-0^zH}e`;rr{}E{t>JuZdxU-^Ud=n zNYS9?#VHC56-?PLtriNaA@mtQDs47VFk#p1fK*cOl)Yu&wBO!-hV#txO7JHc`rXTB zcG@u$M~8HmH#bed6V=;G0B$YFHjA98p~iCl2w-aVa>ZtFU5hc%jt za(U^;TP&ZN-f#zRM$1*{ znt+Em7#I*xsN4{T;|-)Z(A9njh-t$DA}bq2BkBCMJ%Swaw=fS8D86xDM6Y9Kq5CeL zCq#xtUAHl=UIotW{#S(2Xuh&NJz@g&Nw99?4Io7khjNQ;6iN>oy)B7BNK!aOd-Q3BgEiDGe zW`&zB@YN*uF+&OH(kjw6kI*Bq5=ggTm&kah+TdR!0RJzhwT6o^iFu#?M&J zlsY(mnm^scmy{I~cULF)rkh3&IHp_AF0cv{r)B#`p3>+YRu_COX@q=5N~A~j=RALs zMt=ksoi48P>70yFIENq}BV zAWxR(8fYyorbmuliu3EZl70Q4-t;2~3Z*78#YcTuNy>fsgU?mZo~laC{H2-nlwX}< zPAKl?(9&UTqY&jw>%^DfN=3DrmEBwyl2*0Eb|M(?zEePM%C|#v8ttEMs!zyIwFYb{ z^qLgfefO2Jm{sjEhZm4oYI9?I%pc{%L-GlVSjTKb;B{-f3?g=!^TOk3dgXMa99YP?p8u$u-seHL?CxxOG(|vu7z%b5T_0Q9+gnW4 zy1}EAvVw_qMTYb{bUN{asu9|1Z#hytMI-HxPX8@(kIe3RiH`ZlJ?FCTJ;#7bTeSC> z8<%{$ll}-JV26#~b}B;gfsdBA!|dy3K7lbu*dU zTFdcjlILah=PNAs{H+t;HWq63KkYKl*86@$qeJ!1U%v*pW+ig4KI zg9y*w>+y7klW~sLjR+c2-nzv^9pMCyM8`f*JYP#+m~Ph36X0DvIXQvPid!l(Cdt4% zEGz3a<^XA=b?QSQ1PggO12sZ!1Rvb9%|=uPF-gi|@`i@=`DTC2<+H(y0QEUA&@nXy z>`n(LV_I5W7B0Y=WQ@HFEIoh{!p5<-4|E}%z-QOXR9I6U0hZtYb;hoXY5Cap=@})Z z+{Xcd>0K!J*g(NV9OZQt6eVya0A2`ouRqQ{PIV0;G#UhTd8`a7_{wXw#{LAQ?6IYH zuU$KZIhwhv?Hj-VX>!On&T>ea52KtjJ6$nl09y(78x>Pi+=T@#fM+o)${}6BnZLL1 zE+8RspEcd9J=;hz?hYqsD~024GZZELc#04P^`gAnN?U-Va5TB=J|qVC>(%OK1ZHNS#$8nl3GfU zV8M(mU1Z}*+{*22R7!p%FJ?Bo2KnvjnMY?r3GeG#9twpL6r< zZo<>^2QmLJCKUWRzW-yVZGX<60%@VxpFh#5LYU6VG3K3Ag0EG@?F1xQ z8EtLLyK51xb4F7q`*4(jwb z(z3`{bgnh1fe=K@W+#8sVAnQ(HzY(ks(*)!6ATXzN8F<6B!B+c{&mB~vNoCmcPaJh z#s26u!(uqm`l&ixKRw)9T8?EZkJgZw?jrE^Iqi3g0zo-w$mW?TrQ`POl}6OQ!!}%B z64C0MpU)uxZ}=ze55LrEYHK5hhtZuRgoMzVJV&)(KUhsVF`JS+ZeM)b(p_;kVk87T zPYQdYp=*P|^}HHeomA9ywk4p{#@gC*iM|0B3`(*f@K4nlrj`1yJ}~FEYCN3U;u93a z{QgtR27KoefOHiYX2P!Dr448c4910e9N$Zy8FQl#mxEVuLEcV8IMjeL@3}sp;I&y} zY0)-P)Rcy%-)nO8R5c#o>*%y>Jmc1@POh4Eqkxf~;pNH5`j}tAeEWv`Zn4LVEWo<- z)6;zq>t;IE_P0UNLxA=NCsgU93lAzPs+3YSKJh$=8=s;)Ct){EI}JDr`ppQ=_tz{+ z6wv1Dd2~n^ube?0nOZ>cJtkm}NleVb9Zz{Cz^dU&L1E7tgzV9`<7y}~0;`AxXrgC- zD5MeU?%_E~6VS0M9&2{|Z6UX~ialK7WZ6{Wa9yK)w0md_b~Y2K&m|7mX3b7fzx&t1 z*R1l&jhGvr2#XqqCy&C;jv_8YLE!4|8%Q4_4adf&q{PM! zJU&F@IGz|7$N-QVC@Ce6%=qaa#ifU&_Hfzx3%F@Pfz_MG5g)9*Iyw#qrcZ5Pe9V$U zC-rfA>CeOaakiNCDsRpr97W-*(P4JRJm7hK%-44s>l|1OU!8^&K63~QP^SZ{A>cbe zV2RZX-X6{e77G6NQ0A5Q?Y4&o9{8N(mp7Gkrz0nHUbAO7#}5bw$D+>HCB1q5TGg_w zN+$1|m_T`JSolv4jn6_SKWS(T39$p;Fpopi{Y$G!IhXT z-#S)D%1Jy{^AHY`1K-kX;D#W&<9f_co)W;=;!jB?`#3wh;$GK-XBg-;(`)V`ANou& z@g^p6L0jVYAkZ_RyBC)vHT|Kw>X0rHqS?^f*jt(@2*_XO8b=Wt zcz1p(7rvi!uCvayKj6ca>wp&lcq#es+*CB~!D<4YK*Ur?=Z4J4y{GxEsMNpCi%S@3 z2YL|ng)dAo?h(Z*PdBmiZTV%=2h9TpiFQY4{u~?yAXQO@sB$E*f+vAIot>Zqky!|U zBAG-M4i1~oMfsM_&S@DLJc4!yKCioVWb78i!106fS#uh1pnO0sPcM5nhuOfiYox!|s0IP#{46*)8n|BL4>jvXv|upjYM-Ky%2nwq;$#Jui)3*cBR zC8>Rn)R_~MAw-E|*Z=FCC1oz>bFl>Gl*efHB?Ogogv}*8KZ*T5rE1dJzzMa3tO-!-W?D%~^ks;X@ zD*cMO_TMzQCU@&2GkQtcnD{P(af>^UfI)U zK<>Zs9XbqsKzTw@q0GAzokpfSOsghDU6+YwE~gK}ONVTR9Xn|~j9~HEgOzbFR>8v7 zhZU~J^hfj3xe${8C;O%EexU$s@bJ(Oy10x!X#(9HYk0hqWNE9`B?SkIqn}AlzR$Kw zAeHnzJb|-jqf!_$9njA>2l+gpK5f>X+Cx!N5IFaaW`ovesvJ5hc|B-(uRXYpjGVQd z*n^yCqu!~Q{%Kl4VL`#!UUO!d$5sZ_M320V4%OD>_v>KjOOqID7H+(#pxSUfDSf=g ze|~nbG0_RGgeJ;5(i+W)*_HqQcG9I>m^$(n@+7QmAK^0#49>Idwz0Y8D5f779SuFr zfykBY%E~NC!|D%M>ZB=Yk-bD?*Uql|8(exay*Jw}ah)~ch-{lUJ#222aHH~MexRmC5lTqg%!jvn3yrPMX}|K)+WtYDxu8nU`QJ&#NpQpL z$t~}%RBfLkJbh~@8?MVb~5Z9PhK~3tb zDr41~yswZqKNLG(rPDUIS|)=ou#`og)fwblP{g`03kv?Aj(A>D^Q&|tg^!qd*H5)G z#?A?8tS@<5VWqc^O|eZ68GhbjL>18~$N5P`<9t-Dg%GzuBxHGL9mN z_BekZi}Evb9`K?-{b%Mv@>i=|t&Pu>IA2E0+rM*~$q+*y3)bivK{Qd`_>`w*g~ z6jELE2LZ1$Ugr_D;n`OOwWtuc@&RxXj}RX`T5#&gDJ!E^Ck0}KC)ZE7V#1vO$ky3FYJ8#$7h}tF?mz@4Q&~(Ly4=i&VZS zn?2A-Y=o6q@lUBpIDh#xs``#Zx{b8afpFf_JFKj%;hk7N%yCC*-|4`Hl5##1><8up zQd2Zs&LYY!)}AkpZ!vNqXq`&{3$R*$bzDVS9iR5YVvLb-e=c*XtRa`em5#w zs>P#HCZME&$n@J)oI` zctn4H3sM{9U+m5qBB&j58m+J6CkU5*Sd4l8WdHW6tOv=?7jT4p0M0cQZsJ#y1!}N2 zft6B49n*jME=23T&+nJQAS02>&UB%`?aPaX=ys*?&kiqHX^QVxjzI+#z+fSa(|zQL znKYs3C(AUXbr1BnS@%;&55kZ5x6=+t0-FopFC^0>ydtxj{aJB09%yN4YWcL=S6f0v zHn5p5g1qWCL{GwhQo}YFXXc*?gbxu2s!UC7zyVove?105Auu(m zWJ=*l{+)K6#$DPDcWW`R$k6h$^DJn6L&=Kz+=*JpJIuW((v)yY>6ez8VLGD zBK;Tnm#$Wo#{siY#mjRH?s&&2M_*jHP>NsINv ztJ4-nZLho$$n~dyduD0Z^zZLpx9MV_6AX2HK8ovyMFGgLw|Uo=mruF-HqN#E&)ZI6 zo%7f(WZRtUN|I{NI-n<3am}_GQ_^em!D;Qs>Gcv7l+RXbgZMscVs`XaQMBo!GHE%QoY`1AXIkefj=!0N`uSh7{<#K2Auh0jApu#|8f* z!?nQy!J;R{^eRY{mm0ouYM|;3XvTV9f9C~v2j+jx3|jXp0Hz%m7u3qad9Xm9~6_pP=61lVCuv-}W5D*5l!Erg(uwr;{j#2r))l~>GLfy` z?&gnkU8RH^M$AYA7vh1B3=vVp0}B#F4@{Erm2{H;W3EkOB-l4b%C4pmX9lr*r%cka zwxQvBPYl$xcE(6ADN5>6-MVKwizc?r=T`|ywpI3Pa75M(CX2Vf*zj~co%6LQCcM@< zI3)bvwb)XacL5A`9>fio_2t{%KDGUtLlPx9-8$c@qf%47$$51;0A)UmH^-=C??c$Wt~V0AK=|T5DF24-6OhfcF>~69br= zCt6rqL;ZrgK4ON-6?MbIWLz&MAG4G4_$pwM${TxnzMJnPKu!(G@Ka@Ke7B(tSt%~c zU(B|CSrA=(t6dvIofLKA3wU+nF3kD)kL3rlGT4Q;UKl@!q!Qjz>&QQ+AO|0pY8x^p zU{$PV`ZD=3oLsU|=tdAB5U&Xu|ApM=ihlcK{{uh6jZh+&?{eAxF5{}-Igk2kJyc*~>+72~-x&iS4fr-q zI=12q__G!1HbuLw4Z~FpCUWKcW_{P|494Yol3Ev>ozC%viE+|X*EI|bdVAAHz|1h< z2K-(r3`WzNfM)`~+lILNtYaE+fVYG_2ZyptpeDaO2YHS7lGom@^g96IQ?DMnNvSeDvU zXY^3KqWVakl&pd;ODFEHsQe-App>N^K^HO5PIGAw!F*}_k zC|5&YI^-oQyh|uI_x2!8yO>DsItABj_rDD`c68N+%bt=_$bvq#| zY{6ZSn}$k7b6)Fd`~!$yg@tJ!68o2u@CaDqcFdRle)mtlXa+pX(u`=?hw#oZ_yD?e>GS-s1Lhp(^wq=Kd(5m3i3z3Ey#a~QR+ zY7MEAwUZuL<<=E>HI}zq02n5pW zgZI|g?svmd(GIu&9tgA=;yC8)wcM{8$|H{9zmHN(kfK`lKSfUxOzmyzv+b~C%#2(2 z2etHH=K|!ubKo0I+{?_{>sl3DvZi$@k(p_w=Q*#Wi5N(EAVowRq1tHi=gV$X@fy~Z zk~=0y+(Y38h9}UOrh%s}zJeB+86qkq#DbjL>SJTpjj9R#$xvp+M`e){8|V_GkPcReV0`}krELS1ddQ_O zTiFGr+3dY%y*C11Jt6vYE$B8NoFCiyUClQOoSVyP@j`UIGas9bu}w_EiQwwO4n9}q zF5}YB*6z$^DFPQOjA)^UPP2#f^f6;Lv#Ey&2zDPTi(~b8l!Oq?8>s&NQDrZAvV!cu z`zX(5$K;R>i**9=GOlt@Cr*RR7+0|{xsvO-vaG29 zR1(3O?!w2H#FOYDBEeMn~Ce?ZZjHeWRs964upqgBZmg$9@wp7=6bA zr1^aY@atyh<$XNTy9zV0GW+9DxY`N0*BzR(UB40dhRfSY+~x^c)Wz!{JbX7kQBhSP zggj|mi_iUcjyhBe3kja}26F0fc6UABi$=u({i+7^x;L$4FhF>!J#$}0MRI|R3{dHl z_Pp5)@477B0-lSO*4V@sPfH#4e4z8mo0EavE2$elFooO5gt6tvHUrcez!@L5cSoN| zbP);_UFz+p=?*YkSa1esg#yeLV3!j~<6-V11&@K~!-o%-*EUQ{Bpyg*a{5>10MV!* z`H#MSX03zO^7wm=uhHz-p7m1DCk)znbMu9^l)q8(jINeefB2~|g-Uv@v^C3J;4a?H zohHl+yW}Me$@*A81viO~kDZh;bZiN94~NQJrmL24GxMU!B4!lb+D}CLbcp1b6nx#W-4khAbbKVoXpGkm*^L2MBK>%&-qlDG3oX_m(O$AB<@I=`uJ8 z$^1Vg=`<$)CMyy5tj-Ib#M0{gU1`H}{T^;^F1?o)?>3j0fmmDj4I8Y3WSmL!@V)hJ zppo*e7P(PXR~P{hi5LlSNTiY zS3v-!CqvT5LV11v)DP;i3E=Ix$W2FzYXlxBFy6E+Q#REQXf}GsSzH|m8JtvZ-O8_U z)i^qrg3B|Z^ci1gOiF4d343w+w} z2f`OuTx(4N-#k`Q9Otu96xC^Iwc|f(;bP^ACq5+=EorMSR*sn z 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%0AY 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�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�GW{`?}^b49k?&NQo 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%0AaXHkn^TJ9;6gC?6&oQBpr@U^qMex} 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

%?w20R>C$_K{7(4n& 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%0AHlZ;2Qb&2ooJzvboS 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%0AQ*2Y_hJhE-O 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

(?Z-MpWgZOjc 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�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

R(w&3}s#yUXB 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

shu+#sFcneAju7ai# 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 diff --git a/engraphis/app.py b/engraphis/app.py index 8be27a6..29d3e88 100644 --- a/engraphis/app.py +++ b/engraphis/app.py @@ -24,7 +24,7 @@ from engraphis.logging_setup import configure_logging from engraphis.netutil import client_ip from engraphis.routes.memory import router as memory_router -from engraphis.routes.vault import router as vault_router +from engraphis.routes.vault import VAULT_UPLOAD_REQUEST_BYTES, router as vault_router from engraphis.stores import get_conn, init_db logger = logging.getLogger("engraphis") @@ -35,6 +35,100 @@ # Readiness cache: only a *successful* embedder init is cached, so a transient # failure is re-checked on the next probe instead of wedging the pod NotReady. _embedder_ok: bool = False +_UPLOAD_LIMIT_PATHS = frozenset({ + "/api/workspaces/import-files", + "/memory/vaults/upload-folder", + "/memory/vaults/upload-folder-smart", +}) + + +class _RequestBodyTooLarge(Exception): + """Internal signal used by the streaming ASGI request limiter.""" + + +class _VaultUploadLimitMiddleware: + """Reject oversized file imports before multipart parsing/spooling. + + ``Content-Length`` provides an immediate fast-fail. The receive wrapper is still + required because clients can omit or lie about that header, including HTTP/1.1 + chunked uploads. A fronting proxy should configure an equal or lower request-body + ceiling; this in-process guard remains the last line of defense for direct access. + """ + + def __init__(self, app, max_bytes: int): + self.app = app + self.max_bytes = max_bytes + + async def __call__(self, scope, receive, send): + if ( + scope["type"] != "http" + or scope["method"] != "POST" + or scope["path"].rstrip("/") not in _UPLOAD_LIMIT_PATHS + ): + await self.app(scope, receive, send) + return + + raw_lengths = [ + value for name, value in scope.get("headers", []) + if name.lower() == b"content-length" + ] + if len(raw_lengths) > 1: + await JSONResponse( + {"error": "invalid content-length"}, + status_code=400, + )(scope, receive, send) + return + if raw_lengths: + try: + declared_length = int(raw_lengths[0]) + except (TypeError, ValueError): + declared_length = -1 + if declared_length < 0: + await JSONResponse( + {"error": "invalid content-length"}, + status_code=400, + )(scope, receive, send) + return + if declared_length > self.max_bytes: + await self._too_large(scope, receive, send) + return + + received = 0 + limit_exceeded = False + + async def limited_receive(): + nonlocal limit_exceeded, received + message = await receive() + if message["type"] == "http.request": + received += len(message.get("body", b"")) + if received > self.max_bytes: + limit_exceeded = True + raise _RequestBodyTooLarge + return message + + async def guarded_send(message): + # FastAPI converts arbitrary body-parser exceptions into a generic 400. + # Suppress that replacement response once our receive wrapper has observed + # the real cause; the middleware emits the canonical 413 below. + if limit_exceeded: + return + await send(message) + + try: + await self.app(scope, limited_receive, guarded_send) + except _RequestBodyTooLarge: + pass + if limit_exceeded: + await self._too_large(scope, receive, send) + + async def _too_large(self, scope, receive, send): + await JSONResponse( + { + "error": "request body too large", + "max_bytes": self.max_bytes, + }, + status_code=413, + )(scope, receive, send) def _embedder_ready() -> bool: @@ -115,6 +209,10 @@ def create_app() -> FastAPI: allow_methods=["*"], allow_headers=["*"], ) + app.add_middleware( + _VaultUploadLimitMiddleware, + max_bytes=VAULT_UPLOAD_REQUEST_BYTES, + ) # Optional bearer-token auth. Active only when ENGRAPHIS_API_TOKEN is set. # Health-type probes (liveness + readiness) stay unauthenticated by convention. diff --git a/engraphis/backends/postgres_schema.py b/engraphis/backends/postgres_schema.py index bbd12f0..979559b 100644 --- a/engraphis/backends/postgres_schema.py +++ b/engraphis/backends/postgres_schema.py @@ -6,8 +6,11 @@ from __future__ import annotations import hashlib +import ipaddress import os -from typing import Any, Optional +import socket +from typing import Any, Optional, Union +from urllib.parse import urlparse from engraphis.core.interfaces import SchemaSnapshot @@ -32,19 +35,91 @@ def _bounded_env_int(name: str, default: int, maximum: int) -> int: return max(1, min(maximum, value)) +def _global_unicast( + address: Union[ipaddress.IPv4Address, ipaddress.IPv6Address], +) -> bool: + """Return whether *address* is safe for an untrusted outbound connection.""" + mapped = getattr(address, "ipv4_mapped", None) + if mapped is not None: + address = mapped + return ( + address.is_global + and not address.is_multicast + and not address.is_unspecified + and not address.is_loopback + and not address.is_link_local + and not address.is_private + and not address.is_reserved + ) + + +def _validate_dsn_host(dsn: str) -> tuple[str, Optional[str]]: + """Return the TLS hostname and pinned socket address for a safe DSN.""" + env_dsn = os.environ.get("ENGRAPHIS_POSTGRES_DSN", "") + if env_dsn and dsn.strip() == env_dsn.strip(): + return "", None + try: + parsed = urlparse(dsn) + hostname = parsed.hostname + except (TypeError, ValueError) as exc: + raise PostgresIntrospectionError("invalid PostgreSQL DSN") from exc + if not hostname: + raise PostgresIntrospectionError("PostgreSQL DSN must include a hostname") + loopback = { + "localhost": "127.0.0.1", + "127.0.0.1": "127.0.0.1", + "::1": "::1", + } + if hostname.lower() in loopback: + return hostname, loopback[hostname.lower()] + try: + infos = socket.getaddrinfo( + hostname, + parsed.port or 5432, + type=socket.SOCK_STREAM, + proto=socket.IPPROTO_TCP, + ) + except (OSError, ValueError) as exc: + raise PostgresIntrospectionError("cannot resolve PostgreSQL host") from exc + addresses: list[str] = [] + for _, _, _, _, sockaddr in infos: + try: + addr = ipaddress.ip_address(sockaddr[0]) + except ValueError: + raise PostgresIntrospectionError( + "PostgreSQL host resolved to an invalid address" + ) + if not _global_unicast(addr): + raise PostgresIntrospectionError( + "PostgreSQL DSN must resolve only to global unicast addresses" + ) + canonical = str(addr) + if canonical not in addresses: + addresses.append(canonical) + if not addresses: + raise PostgresIntrospectionError("cannot resolve PostgreSQL host") + return hostname, addresses[0] + + def _connect(dsn: str): + hostname, hostaddr = _validate_dsn_host(dsn) timeout = _bounded_env_int( "ENGRAPHIS_POSTGRES_CONNECT_TIMEOUT", _DEFAULT_CONNECT_TIMEOUT_SECONDS, _MAX_CONNECT_TIMEOUT_SECONDS, ) + connect_kwargs: dict[str, Any] = {"connect_timeout": timeout} + if hostaddr is not None: + # libpq connects to hostaddr without another DNS lookup, while host remains + # available for TLS certificate verification and password-file matching. + connect_kwargs.update(host=hostname, hostaddr=hostaddr) try: import psycopg - return psycopg.connect(dsn, connect_timeout=timeout) + return psycopg.connect(dsn, **connect_kwargs) except ImportError: try: import psycopg2 - return psycopg2.connect(dsn, connect_timeout=timeout) + return psycopg2.connect(dsn, **connect_kwargs) except ImportError as exc: raise PostgresIntrospectionError( "PostgreSQL introspection needs psycopg: " diff --git a/engraphis/config.py b/engraphis/config.py index 4578837..d3a95f6 100644 --- a/engraphis/config.py +++ b/engraphis/config.py @@ -1,6 +1,7 @@ """Central configuration — all values sourced from env with safe defaults.""" from __future__ import annotations +import errno import json import hashlib import os @@ -8,6 +9,7 @@ import sqlite3 import stat import sys +import time from contextlib import contextmanager import uuid from dataclasses import dataclass, field @@ -35,6 +37,7 @@ _PROJECT_ROOT = Path(__file__).resolve().parent.parent _DEFAULT_DB_NOTICES = set() +_WINDOWS_LOCK_RETRY_SECONDS = 0.05 def _default_db_path(root: Path = _PROJECT_ROOT, *, os_name: Optional[str] = None, @@ -221,6 +224,21 @@ def _cleanup_stale_migration_stages(target: Path) -> None: pass +def _lock_windows_migration_file(handle, msvcrt) -> None: + """Acquire the CRT lock even when its finite internal wait window expires.""" + while True: + try: + msvcrt.locking(handle.fileno(), msvcrt.LK_LOCK, 1) + return + except OSError as exc: + # ``LK_LOCK`` only retries internally for about ten seconds. Another process + # may still be performing a legitimate first-run migration, so keep waiting + # for lock contention but surface all filesystem/programming failures. + if exc.errno not in (errno.EACCES, errno.EDEADLK): + raise + time.sleep(_WINDOWS_LOCK_RETRY_SECONDS) + + @contextmanager def _migration_lock(target: Path): """Serialize first-run migration across processes without a third-party lock.""" @@ -261,9 +279,17 @@ def _migration_lock(target: Path): handle.seek(0, os.SEEK_END) if handle.tell() == 0: handle.write(b"\0") - handle.flush() + # Retry flush on Windows to handle concurrent file access + for attempt in range(10): + try: + handle.flush() + break + except PermissionError: + if attempt == 9: + raise + time.sleep(0.01 * (2 ** attempt)) # Exponential backoff handle.seek(0) - msvcrt.locking(handle.fileno(), msvcrt.LK_LOCK, 1) + _lock_windows_migration_file(handle, msvcrt) else: import fcntl fcntl.flock(handle.fileno(), fcntl.LOCK_EX) @@ -280,7 +306,18 @@ def _migration_lock(target: Path): import fcntl fcntl.flock(handle.fileno(), fcntl.LOCK_UN) finally: - handle.close() + # Retry close on Windows to handle concurrent file access + if os.name == "nt": + for attempt in range(10): + try: + handle.close() + break + except PermissionError: + if attempt == 9: + raise + time.sleep(0.01 * (2 ** attempt)) # Exponential backoff + else: + handle.close() def _prepare_installed_db_default_unlocked(root: Path, target: Path) -> Path: diff --git a/engraphis/engines/intelligence.py b/engraphis/engines/intelligence.py index ba1fcce..04df293 100644 --- a/engraphis/engines/intelligence.py +++ b/engraphis/engines/intelligence.py @@ -172,5 +172,6 @@ def _parse_json(raw: str) -> dict[str, Any]: text = json_match.group(0) try: return json.loads(text) - except Exception: + except Exception as exc: + logger.debug("JSON parse fallback to raw (%s)", type(exc).__name__) return {"raw": raw} diff --git a/engraphis/llm/client.py b/engraphis/llm/client.py index 5dbc96f..0439b9b 100644 --- a/engraphis/llm/client.py +++ b/engraphis/llm/client.py @@ -381,5 +381,6 @@ def _parse_json_response(raw: str) -> dict[str, Any]: text = text.rsplit("```", 1)[0] try: return json.loads(text) - except Exception: + except Exception as exc: + logger.debug("LLM JSON parse fallback to raw (%s)", type(exc).__name__) return {"raw": raw} diff --git a/engraphis/routes/memory.py b/engraphis/routes/memory.py index 986b94c..7e50eeb 100644 --- a/engraphis/routes/memory.py +++ b/engraphis/routes/memory.py @@ -445,8 +445,8 @@ def _add(ns: str, did: Optional[str]) -> None: for r in conn.execute(ev_sql + " ORDER BY timestamp DESC LIMIT 100", ev_params): try: _add(r["namespace"], _json.loads(r["payload"] or "{}").get("document_id")) - except Exception: - pass + except Exception as exc: + logger.debug("Entity event payload parse skipped (%s)", type(exc).__name__) # 2) broad: memories whose content mentions the entity m_sql = "SELECT namespace, document_id FROM memories WHERE content LIKE ? ESCAPE '\\'" @@ -619,7 +619,10 @@ async def list_thoughts(namespace: Optional[str] = None, limit: int = 50): thoughts = [] for r in rows: d = dict(r) - d["source_memory_ids"] = json.loads(d.get("source_memory_ids") or "[]") + try: + d["source_memory_ids"] = json.loads(d.get("source_memory_ids") or "[]") + except Exception: + d["source_memory_ids"] = [] try: d["parsed"] = json.loads(d["content"]) except Exception: @@ -640,9 +643,6 @@ async def get_config(): "embed_model": settings.embed_model, "loop_interval": settings.loop_interval, "decay_halflife_days": settings.decay_halflife_days, - "host": settings.host, - "port": settings.port, - "base_url": settings.base_url, }) diff --git a/engraphis/routes/vault.py b/engraphis/routes/vault.py index c502a1a..91261f3 100644 --- a/engraphis/routes/vault.py +++ b/engraphis/routes/vault.py @@ -1,30 +1,99 @@ """Vault management, file editing, folder import, memory health, bulk ops, and context preview routes.""" from __future__ import annotations +import asyncio +import heapq import logging import time +from collections import defaultdict from pathlib import Path from typing import Any, Optional import numpy as np -from fastapi import APIRouter, HTTPException, Query, UploadFile, File, Form +from fastapi import APIRouter, File, Form, HTTPException, Query, Request, UploadFile +from fastapi.routing import APIRoute from pydantic import BaseModel +from starlette.exceptions import HTTPException as StarletteHTTPException from engraphis.engines import embedder, ingest as ingest_engine, recall as recall_engine, reweight +from engraphis.service import MAX_IMPORT_FILES, MAX_IMPORT_RESOURCE_BYTES, MAX_IMPORT_TOTAL_BYTES from engraphis.engines.intelligence import auto_categorize, check_conflicts from engraphis.engines.reweight import retention_score -from engraphis.stores import get_conn, now_ts +from engraphis.stores import blob_to_vector, get_conn, now_ts from engraphis.stores import vaults as vault_store from engraphis.stores import vectors as mem_store logger = logging.getLogger("engraphis.routes.vault") -router = APIRouter(prefix="/memory", tags=["vault-management"]) +# Multipart boundaries and per-part headers count toward the HTTP request size even +# though they are not imported content. Keep the transport ceiling finite while allowing +# the documented content limit plus conservative multipart overhead. +VAULT_UPLOAD_REQUEST_BYTES = ( + MAX_IMPORT_TOTAL_BYTES + MAX_IMPORT_FILES * 16_384 + 1024 * 1024 +) +_UPLOAD_FORM_FIELDS = 8 +_DUPLICATE_CANDIDATE_LIMIT = 500 +_DUPLICATE_RESULT_LIMIT = 200 +_DUPLICATE_BLOCK_SIZE = 256 + + +class _BoundedUploadRoute(APIRoute): + """Parse vault uploads with their strict multipart limits before FastAPI binds files.""" + + def get_route_handler(self): + route_handler = super().get_route_handler() + + async def bounded_route_handler(request: Request): + # FastAPI normally resolves ``UploadFile`` parameters before dependencies. + # Parsing here runs first and caches the bounded FormData on this same request. + await _bounded_upload_form(request) + return await route_handler(request) + + return bounded_route_handler + + +class _VaultRouter(APIRouter): + """Install the bounded parser only on the two multipart folder-import routes.""" + + _bounded_upload_paths = { + "/vaults/upload-folder", + "/vaults/upload-folder-smart", + } + + def add_api_route(self, path: str, endpoint, **kwargs): + if path in self._bounded_upload_paths: + kwargs["route_class_override"] = _BoundedUploadRoute + return super().add_api_route(path, endpoint, **kwargs) + + +router = _VaultRouter(prefix="/memory", tags=["vault-management"]) def _ok(data: Any) -> dict[str, Any]: return {"data": data} +async def _bounded_upload_form(request: Request) -> None: + """Parse multipart once with a strict file-count ceiling. + + FastAPI otherwise parses ``UploadFile`` dependencies with Starlette's default + 1,000-file ceiling before the route can inspect ``len(files)``. The app-level + middleware separately bounds bytes before this parser is allowed to spool them. + """ + try: + await request.form( + max_files=MAX_IMPORT_FILES, + max_fields=_UPLOAD_FORM_FIELDS, + ) + except StarletteHTTPException as exc: + detail = str(exc.detail) + if exc.status_code == 400 and detail.lower().startswith("too many files"): + raise HTTPException( + status_code=413, + detail={"error": f"too many files (max {MAX_IMPORT_FILES})"}, + ) from exc + raise + + # ═══ VAULT MANAGEMENT ═══════════════════════════════════════════════════════ class VaultCreateReq(BaseModel): @@ -267,7 +336,8 @@ async def import_folder(req: FolderImportReq): ) results["imported"] += 1 results["files"].append({"path": rel, "title": title, "status": "ok"}) - except Exception: + except Exception as exc: + logger.warning("Folder import file failed (%s)", type(exc).__name__) results["errors"] += 1 results["files"].append({"path": rel_path.as_posix(), "title": "", "status": "error"}) @@ -282,13 +352,24 @@ async def upload_folder( ): """POST /memory/vaults/upload-folder — upload multiple files as a folder (multipart). Use webkitdirectory in the frontend to send an entire folder.""" + if len(files) > MAX_IMPORT_FILES: + raise HTTPException(status_code=413, detail={"error": f"too many files (max {MAX_IMPORT_FILES})"}) if not vault_store.get_vault(namespace): vault_store.create_vault(namespace=namespace, name=namespace) results = {"imported": 0, "errors": 0, "files": []} + total_bytes = 0 for f in files: try: - content = f.file.read().decode("utf-8", errors="replace") + raw = f.file.read(MAX_IMPORT_RESOURCE_BYTES + 1) + if len(raw) > MAX_IMPORT_RESOURCE_BYTES: + results["errors"] += 1 + results["files"].append({"path": f.filename, "title": "", "status": "error", "error": "file too large"}) + continue + total_bytes += len(raw) + if total_bytes > MAX_IMPORT_TOTAL_BYTES: + raise HTTPException(status_code=413, detail={"error": f"upload batch exceeds {MAX_IMPORT_TOTAL_BYTES} bytes"}) + content = raw.decode("utf-8", errors="replace") if not content.strip(): continue import re @@ -304,9 +385,12 @@ async def upload_folder( ) results["imported"] += 1 results["files"].append({"path": f.filename, "title": title, "status": "ok"}) - except Exception as e: + except HTTPException: + raise + except Exception as exc: results["errors"] += 1 - results["files"].append({"path": f.filename, "title": "", "status": "error", "error": str(e)}) + logger.warning("Folder upload file failed (%s)", type(exc).__name__) + results["files"].append({"path": f.filename, "title": "", "status": "error", "error": "processing failed"}) return _ok({"namespace": namespace, **results}) @@ -325,6 +409,8 @@ async def upload_folder_smart( If auto_categorize_flag is 'true', each file is classified by the LLM into the correct memory type. Uses batch embedding for speed.""" import re as _re + if len(files) > MAX_IMPORT_FILES: + raise HTTPException(status_code=413, detail={"error": f"too many files (max {MAX_IMPORT_FILES})"}) if not vault_store.get_vault(namespace): vault_store.create_vault(namespace=namespace, name=namespace) @@ -333,9 +419,18 @@ async def upload_folder_smart( # Phase 1: Read all files and prepare content file_data = [] + total_bytes = 0 for f in files: try: - content = f.file.read().decode("utf-8", errors="replace") + raw = f.file.read(MAX_IMPORT_RESOURCE_BYTES + 1) + if len(raw) > MAX_IMPORT_RESOURCE_BYTES: + results["errors"] += 1 + results["files"].append({"path": f.filename, "title": "", "status": "error", "error": "file too large"}) + continue + total_bytes += len(raw) + if total_bytes > MAX_IMPORT_TOTAL_BYTES: + raise HTTPException(status_code=413, detail={"error": f"upload batch exceeds {MAX_IMPORT_TOTAL_BYTES} bytes"}) + content = raw.decode("utf-8", errors="replace") if not content.strip(): results["skipped"] += 1 continue @@ -343,16 +438,20 @@ async def upload_folder_smart( title = title_match.group(1).strip() if title_match else Path(f.filename).stem doc_id = f.filename.replace("/", "__").replace("\\", "__").replace(".md", "").replace(".", "-") file_data.append({"filename": f.filename, "doc_id": doc_id, "title": title, "content": content}) - except Exception as e: + except HTTPException: + raise + except Exception as exc: results["errors"] += 1 - results["files"].append({"path": f.filename, "title": "", "status": "error", "error": str(e)}) + logger.warning("Smart import file read failed (%s)", type(exc).__name__) + results["files"].append({"path": f.filename, "title": "", "status": "error", "error": "processing failed"}) # Phase 2: Batch embed all files at once (10x faster than individual) if file_data: texts = [f"{fd['title']}\n\n{fd['content']}" for fd in file_data] try: vecs = embedder.embed_batch(texts) - except Exception: + except Exception as exc: + logger.warning("Batch embedding failed (%s), falling back to individual", type(exc).__name__) # Fallback: embed individually vecs = [embedder.embed(t) for t in texts] @@ -412,9 +511,10 @@ async def upload_folder_smart( "categorized": categorize_info is not None, "confidence": categorize_info.get("confidence", 0) if categorize_info else 0, }) - except Exception as e: + except Exception as exc: results["errors"] += 1 - results["files"].append({"path": fd["filename"], "title": "", "status": "error", "error": str(e)}) + logger.warning("Smart import ingest failed (%s)", type(exc).__name__) + results["files"].append({"path": fd["filename"], "title": "", "status": "error", "error": "processing failed"}) return _ok({"namespace": namespace, **results}) @@ -453,7 +553,8 @@ async def auto_categorize_memories(req: AutoCategorizeReq): "confidence": cat.get("confidence", 0), "reason": cat.get("reason", ""), }) - except Exception: + except Exception as exc: + logger.warning("Auto-categorize failed (%s)", type(exc).__name__) results["errors"] += 1 return _ok(results) @@ -477,27 +578,137 @@ async def conflict_check(req: ConflictCheckReq): # ═══ MEMORY HEALTH ══════════════════════════════════════════════════════════ -@router.get("/health/duplicates") -async def find_duplicates(namespace: Optional[str] = None, threshold: float = 0.85): - """GET /memory/health/duplicates — find near-duplicate memories by vector similarity.""" - candidates = mem_store.all_vectors(namespace=namespace) +def _duplicate_pairs( + candidates: list[tuple[str, str, np.ndarray, dict[str, str]]], + threshold: float, +) -> tuple[list[dict[str, Any]], int]: + """Find the strongest pairs with bounded block memory and response cardinality.""" + groups: dict[tuple[str, int], list[tuple[str, np.ndarray, dict[str, str]]]] = ( + defaultdict(list) + ) + for namespace, document_id, vector, memory in candidates: + # A stale vector from an old embedding dimension must not break all health data. + groups[(namespace, int(vector.size))].append((document_id, vector, memory)) + + strongest: list[tuple[float, int, int, int, list[tuple[str, np.ndarray, dict[str, str]]], str]] = [] + match_count = 0 + sequence = 0 + for (namespace, _dimension), memories in groups.items(): + if len(memories) < 2: + continue + vectors = np.stack([item[1] for item in memories]) + for start in range(0, len(memories), _DUPLICATE_BLOCK_SIZE): + stop = min(start + _DUPLICATE_BLOCK_SIZE, len(memories)) + similarities = vectors[start:stop] @ vectors.T + for local_index, absolute_index in enumerate(range(start, stop)): + similarities[local_index, :absolute_index + 1] = -np.inf + + flat = similarities.ravel() + matching = np.flatnonzero(flat >= threshold) + match_count += int(matching.size) + if matching.size > _DUPLICATE_RESULT_LIMIT: + relative = np.argpartition( + flat[matching], + -_DUPLICATE_RESULT_LIMIT, + )[-_DUPLICATE_RESULT_LIMIT:] + matching = matching[relative] + + for flat_index in matching: + local_index, right_index = divmod(int(flat_index), len(memories)) + left_index = start + local_index + similarity = float(similarities[local_index, right_index]) + entry = ( + similarity, + sequence, + left_index, + right_index, + memories, + namespace, + ) + sequence += 1 + if len(strongest) < _DUPLICATE_RESULT_LIMIT: + heapq.heappush(strongest, entry) + elif similarity > strongest[0][0]: + heapq.heapreplace(strongest, entry) + duplicates = [] - for i in range(len(candidates)): - for j in range(i + 1, len(candidates)): - id1, ns1, doc1, vec1, mem1 = candidates[i] - id2, ns2, doc2, vec2, mem2 = candidates[j] - if ns1 != ns2: - continue - sim = float(np.dot(vec1, vec2)) - if sim >= threshold: - duplicates.append({ - "namespace": ns1, - "memory_a": {"document_id": doc1, "title": mem1["title"], "content": mem1["content"][:200]}, - "memory_b": {"document_id": doc2, "title": mem2["title"], "content": mem2["content"][:200]}, - "similarity": round(sim, 4), - }) - duplicates.sort(key=lambda x: x["similarity"], reverse=True) - return _ok({"duplicates": duplicates, "count": len(duplicates)}) + for similarity, _, left_index, right_index, memories, namespace in sorted( + strongest, key=lambda item: (-item[0], item[1]) + ): + left_doc, _, left_mem = memories[left_index] + right_doc, _, right_mem = memories[right_index] + duplicates.append({ + "namespace": namespace, + "memory_a": { + "document_id": left_doc, + "title": left_mem["title"], + "content": left_mem["content"][:200], + }, + "memory_b": { + "document_id": right_doc, + "title": right_mem["title"], + "content": right_mem["content"][:200], + }, + "similarity": round(similarity, 4), + }) + return duplicates, match_count + + +def _duplicate_candidate_query(namespace: Optional[str]) -> tuple[str, list[Any]]: + """Build the bounded duplicate-candidate query without SQLite temporary sorting. + + A namespaced scan is ordered by newest update through ``idx_mem_updated``. A global + scan instead uses descending rowid/``id`` (newest insertion), because there is no + global ``updated_at`` index and combining the two would force a temp B-tree. + """ + sql = ( + "SELECT namespace, document_id, vector, title, content " + "FROM memories WHERE vector IS NOT NULL" + ) + params: list[Any] = [] + if namespace: + sql += " AND namespace=?" + params.append(namespace) + sql += " ORDER BY updated_at DESC" + else: + sql += " ORDER BY id DESC" + return sql, params + + +@router.get("/health/duplicates") +async def find_duplicates( + namespace: Optional[str] = None, + threshold: float = Query(0.85, ge=-1.0, le=1.0), +): + """Find a bounded set of strongest near-duplicates without blocking the event loop.""" + sql, params = _duplicate_candidate_query(namespace) + sql += " LIMIT ?" + params.append(_DUPLICATE_CANDIDATE_LIMIT + 1) + rows = get_conn().execute(sql, params).fetchall() + candidate_truncated = len(rows) > _DUPLICATE_CANDIDATE_LIMIT + candidates = [ + ( + row["namespace"], + row["document_id"], + blob_to_vector(row["vector"]), + {"title": row["title"], "content": row["content"]}, + ) + for row in rows[:_DUPLICATE_CANDIDATE_LIMIT] + ] + duplicates, match_count = await asyncio.to_thread( + _duplicate_pairs, candidates, threshold + ) + return _ok({ + "duplicates": duplicates, + "count": len(duplicates), + "matches_considered": match_count, + "candidate_count": len(candidates), + "candidate_limit": _DUPLICATE_CANDIDATE_LIMIT, + "result_limit": _DUPLICATE_RESULT_LIMIT, + "truncated": ( + candidate_truncated or match_count > _DUPLICATE_RESULT_LIMIT + ), + }) @router.get("/health/stale") diff --git a/engraphis/stores/graph.py b/engraphis/stores/graph.py index d13c546..f5cc51c 100644 --- a/engraphis/stores/graph.py +++ b/engraphis/stores/graph.py @@ -2,9 +2,12 @@ from __future__ import annotations from typing import Any, Optional +import logging from engraphis.stores import get_conn, now_ts +logger = logging.getLogger("engraphis.stores.graph") + def upsert_entity(namespace: str, name: str, entity_type: Optional[str] = None) -> None: conn = get_conn() @@ -91,8 +94,8 @@ def graph_snapshot(namespace: Optional[str] = None, limit: int = 200, did = payload.get("document_id") if did and did not in doc_ids: doc_ids.append(did) - except Exception: - pass + except Exception as exc: + logger.debug("Entity document payload parse skipped (%s)", type(exc).__name__) ent["documents"] = doc_ids[:10] # Get a preview from the first document if ent["documents"]: diff --git a/scripts/externalize_dashboard_assets.py b/scripts/externalize_dashboard_assets.py index 085dc4f..06bc266 100644 --- a/scripts/externalize_dashboard_assets.py +++ b/scripts/externalize_dashboard_assets.py @@ -45,6 +45,7 @@ HANDLER_REF = re.compile(r'data-on([a-z]+)=["\'](h\d+)["\']') HANDLER_DEF = re.compile(r'^\s*(h\d+):function\(event\)\{', re.MULTILINE) DELEGATED_EVENTS = re.compile(r"for\(const type of \[([^]]+)\]\)") +ASSET_END_TAG = re.compile(r"]*)>", re.IGNORECASE) @dataclass(frozen=True) @@ -118,8 +119,17 @@ def finish_unclosed(self) -> None: def _parse_page(html: str) -> _InlineAssetParser: + # ``HTMLParser`` does not recognize attributes on an end tag, although an HTML5 + # browser ignores them and still closes raw-text ``script``/``style`` elements. + # Blank the invalid suffix before parsing while preserving every byte offset and + # newline; extracted content and replacements continue to slice the original source. + def normalize_end_tag(match: re.Match[str]) -> str: + suffix = match.group(2) + blanked = "".join(char if char in "\r\n" else " " for char in suffix) + return match.group(0)[: 2 + len(match.group(1))] + blanked + ">" + parser = _InlineAssetParser(html) - parser.feed(html) + parser.feed(ASSET_END_TAG.sub(normalize_end_tag, html)) parser.close() parser.finish_unclosed() return parser diff --git a/tests/test_config.py b/tests/test_config.py index 03db0d8..469806c 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -5,12 +5,15 @@ instead of only in code. The default must stay empty so the offline/numpy-only CI path is unchanged (empty -> None -> IdentityReranker, no torch). """ +from pathlib import Path + import pytest from engraphis import config from engraphis.config import Settings +REPO_ROOT = Path(__file__).resolve().parents[1] RETIRED_RELAY_URLS = ( "https://engraphis-production.up.railway.app", "https://team.engraphis.com", @@ -39,6 +42,29 @@ def test_cors_origins_use_engraphis_port_env(monkeypatch): "http://127.0.0.1:9100", "http://localhost:9100"] +def test_sample_operational_config_matches_runtime_contract(monkeypatch): + example = (REPO_ROOT / ".env.example").read_text(encoding="utf-8") + readme = (REPO_ROOT / "README.md").read_text(encoding="utf-8") + + monkeypatch.delenv("ENGRAPHIS_RATE_LIMIT", raising=False) + assert Settings().rate_limit == 0 + assert "# ENGRAPHIS_RATE_LIMIT=0" in example + + monkeypatch.setenv("ENGRAPHIS_WORKSPACES", "acme,personal") + assert Settings().allowed_workspaces == ["acme", "personal"] + assert "# ENGRAPHIS_WORKSPACES=acme,personal" in example + + assert "http://127.0.0.1:" in example + assert "http://localhost:" in example + assert "These settings do not change CORS" in example + assert "# ENGRAPHIS_DASHBOARD_URL=https://engraphis.example.com" in example + + monkeypatch.delenv("ENGRAPHIS_LLM_AUTO_EXTRACT", raising=False) + assert Settings().llm_auto_extract is False + assert "ENGRAPHIS_LLM_AUTO_EXTRACT=0" in example + assert "| `ENGRAPHIS_LLM_AUTO_EXTRACT` | `0` |" in readme + + def test_rerank_model_read_from_env(monkeypatch): monkeypatch.setenv("ENGRAPHIS_RERANK_MODEL", "cross-encoder/ms-marco-MiniLM-L-6-v2") assert Settings().rerank_model == "cross-encoder/ms-marco-MiniLM-L-6-v2" diff --git a/tests/test_db_path_default.py b/tests/test_db_path_default.py index a76106d..a254ecb 100644 --- a/tests/test_db_path_default.py +++ b/tests/test_db_path_default.py @@ -13,6 +13,7 @@ import pytest +from engraphis import config from engraphis.config import ( Settings, _configured_db_path, @@ -115,6 +116,70 @@ def test_concurrent_first_start_serializes_migration(tmp_path): assert _value(Path(str(target) + ".users.db")) == "auth-data" +@pytest.mark.skipif(os.name != "nt", reason="Windows CRT lock mode") +def test_windows_migration_lock_uses_native_blocking_mode(tmp_path, monkeypatch): + import msvcrt + + calls = [] + native_locking = msvcrt.locking + + def recording_lock(fd, mode, size): + calls.append((mode, size)) + return native_locking(fd, mode, size) + + monkeypatch.setattr(msvcrt, "locking", recording_lock) + with config._migration_lock(tmp_path / "engraphis.db"): + pass + + assert calls == [(msvcrt.LK_LOCK, 1), (msvcrt.LK_UNLCK, 1)] + + +def test_windows_migration_lock_retries_expected_crt_contention(monkeypatch): + import errno + + class Handle: + def fileno(self): + return 7 + + class FakeMsvcrt: + LK_LOCK = 1 + calls = [] + + @classmethod + def locking(cls, _fd, _mode, _size): + cls.calls.append((_fd, _mode, _size)) + if len(cls.calls) == 1: + raise OSError(errno.EACCES, "locked by another process") + if len(cls.calls) == 2: + raise OSError(errno.EDEADLK, "retry lock acquisition") + + sleeps = [] + monkeypatch.setattr(config.time, "sleep", sleeps.append) + + config._lock_windows_migration_file(Handle(), FakeMsvcrt) + + assert len(FakeMsvcrt.calls) == 3 + assert sleeps == [config._WINDOWS_LOCK_RETRY_SECONDS] * 2 + + +def test_windows_migration_lock_reraises_unexpected_crt_error(): + import errno + + class Handle: + def fileno(self): + return 7 + + class FakeMsvcrt: + LK_LOCK = 1 + + @staticmethod + def locking(_fd, _mode, _size): + raise OSError(errno.EIO, "disk failure") + + with pytest.raises(OSError, match="disk failure"): + config._lock_windows_migration_file(Handle(), FakeMsvcrt) + + def test_upgrade_includes_committed_wal_content(tmp_path): root = tmp_path / "site-packages" legacy = root / "engraphis.db" diff --git a/tests/test_externalize_dashboard_assets.py b/tests/test_externalize_dashboard_assets.py index c6ef562..e7d01ab 100644 --- a/tests/test_externalize_dashboard_assets.py +++ b/tests/test_externalize_dashboard_assets.py @@ -15,6 +15,15 @@ def test_inline_asset_parser_handles_case_and_malformed_closing_tag(): assert [asset.content for asset in scripts] == ["alert(1)"] +def test_inline_asset_parser_resumes_after_malformed_closing_tag(): + styles, scripts = assets._inline_assets( + "" + ) + + assert styles == [] + assert [asset.content for asset in scripts] == ["first()", "second()"] + + def test_migrate_uses_parsed_asset_boundaries(tmp_path, monkeypatch): index = tmp_path / "index.html" css = tmp_path / "dashboard.css" diff --git a/tests/test_memory_routes_fixes.py b/tests/test_memory_routes_fixes.py index a307155..aefee77 100644 --- a/tests/test_memory_routes_fixes.py +++ b/tests/test_memory_routes_fixes.py @@ -8,6 +8,7 @@ """ import threading +import numpy as np import pytest from engraphis.config import settings @@ -137,3 +138,356 @@ def chat_with_context(self, **kwargs): result = response.json()["data"] assert result["llm_error"] == "LLM service unavailable" assert secret not in repr(result) + + +@pytest.mark.parametrize( + ("path", "extra_form"), + [ + ("/memory/vaults/upload-folder", {}), + ( + "/memory/vaults/upload-folder-smart", + {"auto_categorize_flag": "false"}, + ), + ], +) +def test_upload_batch_limit_remains_an_http_413( + monkeypatch, + tmp_path, + path, + extra_form, +): + from engraphis.routes import vault as vault_routes + + monkeypatch.setattr(vault_routes, "MAX_IMPORT_RESOURCE_BYTES", 4) + monkeypatch.setattr(vault_routes, "MAX_IMPORT_TOTAL_BYTES", 1) + with _client(monkeypatch, tmp_path) as client: + response = client.post( + path, + data={"namespace": "ns", "memory_type": "semantic", **extra_form}, + files={"files": ("memory.md", b"xy", "text/markdown")}, + ) + + assert response.status_code == 413 + assert response.json()["detail"] == {"error": "upload batch exceeds 1 bytes"} + + +@pytest.mark.parametrize( + "path", + [ + "/api/workspaces/import-files", + "/api/workspaces/import-files/", + "/memory/vaults/upload-folder", + "/memory/vaults/upload-folder/", + "/memory/vaults/upload-folder-smart", + "/memory/vaults/upload-folder-smart/", + ], +) +def test_vault_upload_rejects_declared_oversize_before_multipart_parse( + monkeypatch, + tmp_path, + path, +): + import engraphis.app as app_module + + monkeypatch.setattr(app_module, "VAULT_UPLOAD_REQUEST_BYTES", 16) + with _client(monkeypatch, tmp_path) as client: + response = client.post( + path, + content=b"not parsed", + headers={ + "content-type": "multipart/form-data; boundary=unused", + "content-length": "17", + }, + ) + + assert response.status_code == 413 + assert response.json() == { + "error": "request body too large", + "max_bytes": 16, + } + + +def test_vault_upload_counts_chunked_body_without_content_length(): + import asyncio + import json + + from engraphis.app import _VaultUploadLimitMiddleware + + messages = iter([ + {"type": "http.request", "body": b"12345", "more_body": True}, + {"type": "http.request", "body": b"67890", "more_body": False}, + ]) + sent = [] + + async def receive(): + return next(messages) + + async def send(message): + sent.append(message) + + async def drain_body(_scope, receive_body, send_response): + while True: + message = await receive_body() + if not message.get("more_body"): + break + await send_response({ + "type": "http.response.start", + "status": 204, + "headers": [], + }) + await send_response({"type": "http.response.body", "body": b""}) + + middleware = _VaultUploadLimitMiddleware(drain_body, max_bytes=8) + asyncio.run(middleware( + { + "type": "http", + "method": "POST", + "path": "/memory/vaults/upload-folder", + "headers": [(b"transfer-encoding", b"chunked")], + }, + receive, + send, + )) + + assert sent[0]["status"] == 413 + assert json.loads(sent[1]["body"])["max_bytes"] == 8 + + +def test_vault_upload_limits_valid_streamed_multipart_in_whole_app( + monkeypatch, + tmp_path, +): + import asyncio + import json + + import engraphis.app as app_module + + _setup_store(monkeypatch, tmp_path) + monkeypatch.setattr(settings, "loop_interval", 0) + monkeypatch.setattr(settings, "embed_model", "") + monkeypatch.setattr(app_module, "VAULT_UPLOAD_REQUEST_BYTES", 96) + body = ( + b"--vault\r\n" + b'Content-Disposition: form-data; name="namespace"\r\n\r\n' + b"ns\r\n" + b"--vault\r\n" + b'Content-Disposition: form-data; name="files"; filename="memory.md"\r\n' + b"Content-Type: text/markdown\r\n\r\n" + + b"x" * 64 + + b"\r\n--vault--\r\n" + ) + chunks = [ + { + "type": "http.request", + "body": body[offset:offset + 32], + "more_body": offset + 32 < len(body), + } + for offset in range(0, len(body), 32) + ] + messages = iter(chunks) + sent = [] + + async def receive(): + return next(messages, {"type": "http.disconnect"}) + + async def send(message): + sent.append(message) + + app = app_module.create_app() + asyncio.run(app( + { + "type": "http", + "asgi": {"version": "3.0"}, + "http_version": "1.1", + "method": "POST", + "scheme": "http", + "path": "/memory/vaults/upload-folder", + "raw_path": b"/memory/vaults/upload-folder", + "query_string": b"", + "root_path": "", + "headers": [ + (b"content-type", b"multipart/form-data; boundary=vault"), + (b"transfer-encoding", b"chunked"), + ], + "client": ("127.0.0.1", 12345), + "server": ("testserver", 80), + }, + receive, + send, + )) + + response_start = next( + message for message in sent if message["type"] == "http.response.start" + ) + response_body = b"".join( + message.get("body", b"") + for message in sent + if message["type"] == "http.response.body" + ) + assert response_start["status"] == 413 + assert json.loads(response_body)["max_bytes"] == 96 + + +@pytest.mark.parametrize( + ("path", "extra_form"), + [ + ("/memory/vaults/upload-folder", {}), + ( + "/memory/vaults/upload-folder-smart", + {"auto_categorize_flag": "false"}, + ), + ], +) +def test_vault_upload_stops_multipart_parse_at_file_count_limit( + monkeypatch, + tmp_path, + path, + extra_form, +): + from engraphis.routes import vault as vault_routes + + monkeypatch.setattr(vault_routes, "MAX_IMPORT_FILES", 2) + files = [ + ("files", (f"memory-{index}.md", b"# Memory", "text/markdown")) + for index in range(3) + ] + with _client(monkeypatch, tmp_path) as client: + response = client.post( + path, + data={"namespace": "ns", "memory_type": "semantic", **extra_form}, + files=files, + ) + + assert response.status_code == 413 + assert response.json()["detail"] == {"error": "too many files (max 2)"} + assert vault_routes.vault_store.get_vault("ns") is None + + +def test_vault_upload_instantiates_multipart_parser_with_bounded_file_cap( + monkeypatch, + tmp_path, +): + """The route handler, not a post-parse endpoint check, owns the parser cap.""" + import starlette.requests + + from engraphis.routes import vault as vault_routes + + monkeypatch.setattr(vault_routes, "MAX_IMPORT_FILES", 2) + parser_calls = [] + parser_type = starlette.requests.MultiPartParser + + class RecordingMultiPartParser(parser_type): + def __init__(self, headers, stream, *, max_files=1000, max_fields=1000, + max_part_size=1024 * 1024): + parser_calls.append((max_files, max_fields)) + super().__init__( + headers, + stream, + max_files=max_files, + max_fields=max_fields, + max_part_size=max_part_size, + ) + + monkeypatch.setattr(starlette.requests, "MultiPartParser", RecordingMultiPartParser) + with _client(monkeypatch, tmp_path) as client: + response = client.post( + "/memory/vaults/upload-folder", + data={"namespace": "ns", "memory_type": "semantic"}, + files=[ + ("files", (f"memory-{index}.md", b"# Memory", "text/markdown")) + for index in range(3) + ], + ) + + assert response.status_code == 413 + assert parser_calls == [(2, vault_routes._UPLOAD_FORM_FIELDS)] + + +def test_duplicate_candidate_query_uses_indexed_ordering_without_temp_sort(monkeypatch, tmp_path): + from engraphis.routes import vault as vault_routes + + _setup_store(monkeypatch, tmp_path) + vector = np.ones(8, dtype=np.float32) + mem_store.upsert_memory( + namespace="first", document_id="older", title="t", content="c", vector=vector, + updated_at=10, + ) + mem_store.upsert_memory( + namespace="first", document_id="newer", title="t", content="c", vector=vector, + updated_at=20, + ) + mem_store.upsert_memory( + namespace="second", document_id="latest-id", title="t", content="c", vector=vector, + updated_at=5, + ) + + conn = get_conn() + scoped_sql, scoped_params = vault_routes._duplicate_candidate_query("first") + global_sql, global_params = vault_routes._duplicate_candidate_query(None) + scoped_plan = " ".join( + row["detail"] for row in conn.execute( + "EXPLAIN QUERY PLAN " + scoped_sql + " LIMIT ?", (*scoped_params, 10) + ) + ) + global_plan = " ".join( + row["detail"] for row in conn.execute( + "EXPLAIN QUERY PLAN " + global_sql + " LIMIT ?", (*global_params, 10) + ) + ) + + assert "idx_mem_updated" in scoped_plan + assert "TEMP B-TREE" not in scoped_plan.upper() + assert "TEMP B-TREE" not in global_plan.upper() + assert [row["document_id"] for row in conn.execute(scoped_sql, scoped_params)] == [ + "newer", "older" + ] + assert conn.execute(global_sql, global_params).fetchone()["document_id"] == "latest-id" + + +def test_duplicate_health_bounds_candidates_results_and_uses_worker( + monkeypatch, + tmp_path, +): + import numpy as np + + from engraphis.routes import vault as vault_routes + + _setup_store(monkeypatch, tmp_path) + vector = np.ones(8, dtype=np.float32) / np.sqrt(8) + for index in range(4): + mem_store.upsert_memory( + namespace="ns", + document_id=f"d{index}", + title=f"Memory {index}", + content=f"duplicate content {index}", + vector=vector, + ) + + monkeypatch.setattr(vault_routes, "_DUPLICATE_CANDIDATE_LIMIT", 3) + monkeypatch.setattr(vault_routes, "_DUPLICATE_RESULT_LIMIT", 2) + monkeypatch.setattr( + vault_routes.mem_store, + "all_vectors", + lambda **_kwargs: pytest.fail("route must not load every vector"), + ) + worker_calls = [] + real_worker = vault_routes.asyncio.to_thread + + async def tracked_worker(function, *args): + worker_calls.append(function) + return await real_worker(function, *args) + + monkeypatch.setattr(vault_routes.asyncio, "to_thread", tracked_worker) + with _client(monkeypatch, tmp_path) as client: + response = client.get("/memory/health/duplicates?namespace=ns") + + assert response.status_code == 200 + data = response.json()["data"] + assert data["candidate_count"] == 3 + assert data["candidate_limit"] == 3 + assert data["matches_considered"] == 3 + assert data["count"] == 2 + assert len(data["duplicates"]) == 2 + assert data["result_limit"] == 2 + assert data["truncated"] is True + assert worker_calls == [vault_routes._duplicate_pairs] diff --git a/tests/test_postgres_schema.py b/tests/test_postgres_schema.py index caa103e..6344019 100644 --- a/tests/test_postgres_schema.py +++ b/tests/test_postgres_schema.py @@ -2,6 +2,8 @@ import sys import types +import pytest + from engraphis.backends import postgres_schema from engraphis.core.interfaces import SchemaSnapshot, SearchFilter from engraphis.service import MemoryService @@ -85,7 +87,7 @@ def connect(dsn, **kwargs): monkeypatch.setenv("ENGRAPHIS_POSTGRES_STATEMENT_TIMEOUT_MS", "45000") snapshot = postgres_schema.PostgresSchemaIntrospector().inspect( - "postgresql://local/appdb" + "postgresql://localhost/appdb" ) assert snapshot.metadata["database"] == "appdb" @@ -95,6 +97,143 @@ def connect(dsn, **kwargs): assert timeout_call[1] == ("45000",) +def test_postgres_connect_pins_validated_address_without_losing_tls_host(monkeypatch): + captured = {} + resolutions = 0 + + def resolve(*args, **kwargs): + nonlocal resolutions + resolutions += 1 + if resolutions > 1: + return [ + ( + postgres_schema.socket.AF_INET, + postgres_schema.socket.SOCK_STREAM, + postgres_schema.socket.IPPROTO_TCP, + "", + ("10.0.0.8", 5432), + ) + ] + return [ + ( + postgres_schema.socket.AF_INET, + postgres_schema.socket.SOCK_STREAM, + postgres_schema.socket.IPPROTO_TCP, + "", + ("93.184.216.34", 5432), + ) + ] + + def connect(dsn, **kwargs): + captured["dsn"] = dsn + captured.update(kwargs) + return _Connection() + + monkeypatch.setattr(postgres_schema.socket, "getaddrinfo", resolve) + monkeypatch.setitem(sys.modules, "psycopg", types.SimpleNamespace(connect=connect)) + + dsn = ( + "postgresql://db.example/appdb" + "?host=10.0.0.8&hostaddr=10.0.0.8" + ) + postgres_schema._connect(dsn) + + assert resolutions == 1 + assert captured["dsn"] == dsn + assert captured["host"] == "db.example" + assert captured["hostaddr"] == "93.184.216.34" + + +@pytest.mark.parametrize( + "address", + [ + "10.0.0.8", + "100.64.0.1", + "127.0.0.2", + "169.254.1.1", + "192.0.2.1", + "224.0.0.1", + "::", + "fe80::1", + "ff02::1", + ], +) +def test_postgres_connect_rejects_non_global_addresses(monkeypatch, address): + family = ( + postgres_schema.socket.AF_INET6 + if ":" in address + else postgres_schema.socket.AF_INET + ) + monkeypatch.setattr( + postgres_schema.socket, + "getaddrinfo", + lambda *args, **kwargs: [ + ( + family, + postgres_schema.socket.SOCK_STREAM, + postgres_schema.socket.IPPROTO_TCP, + "", + (address, 5432), + ) + ], + ) + + with pytest.raises( + postgres_schema.PostgresIntrospectionError, + match="global unicast", + ): + postgres_schema._connect("postgresql://db.example/appdb") + + +def test_postgres_connect_rejects_mixed_global_and_private_dns(monkeypatch): + monkeypatch.setattr( + postgres_schema.socket, + "getaddrinfo", + lambda *args, **kwargs: [ + ( + postgres_schema.socket.AF_INET, + postgres_schema.socket.SOCK_STREAM, + postgres_schema.socket.IPPROTO_TCP, + "", + ("93.184.216.34", 5432), + ), + ( + postgres_schema.socket.AF_INET, + postgres_schema.socket.SOCK_STREAM, + postgres_schema.socket.IPPROTO_TCP, + "", + ("10.0.0.8", 5432), + ), + ], + ) + + with pytest.raises( + postgres_schema.PostgresIntrospectionError, + match="global unicast", + ): + postgres_schema._connect("postgresql://db.example/appdb") + + +def test_postgres_connect_keeps_explicit_dsn_and_loopback_exceptions(monkeypatch): + calls = [] + + def connect(dsn, **kwargs): + calls.append((dsn, kwargs)) + return _Connection() + + explicit = "postgresql://db.internal/appdb" + monkeypatch.setenv("ENGRAPHIS_POSTGRES_DSN", explicit) + monkeypatch.setitem(sys.modules, "psycopg", types.SimpleNamespace(connect=connect)) + + postgres_schema._connect(explicit) + monkeypatch.delenv("ENGRAPHIS_POSTGRES_DSN") + postgres_schema._connect("postgresql://localhost/appdb") + + assert calls[0][1] == {"connect_timeout": 10} + assert calls[1][1]["host"] == "localhost" + assert calls[1][1]["hostaddr"] == "127.0.0.1" + + def test_postgres_introspection_is_filtered_bounded_and_cross_schema_safe(monkeypatch): connection = _Connection() monkeypatch.setattr(postgres_schema, "_connect", lambda dsn: connection) From 3d8242eb16535079c49805d1a26029c213ffc7ee Mon Sep 17 00:00:00 2001 From: Jaixii Date: Sun, 26 Jul 2026 13:53:16 -0400 Subject: [PATCH 35/82] Add `engraphis connect --token` so a purchased client can actually connect MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `cloud_session.save_bootstrap()` is the only function that writes `~/.engraphis/cloud_session.json`, and it had zero production callers — only tests reached it. Meanwhile `docs/AGENT_CONNECT.md` and `.env.example` told customers to prefer that file. Nothing created it, so a paying customer had no supported way to connect a client and every paid feature was undeliverable. This adds the client half of the device-connect flow that the control plane already serves: - `engraphis/device_connect.py` — token validation, stable client identity, the POST to `/v1/devices/connect`, status-keyed error copy, and the call into `save_bootstrap`. - `scripts/connect.py` — the CLI, following `scripts/init.py` conventions (`main(argv=None) -> int`, argparse, no prompts). - `scripts/entry.py` — an `engraphis` front door that dispatches to the existing `engraphis-` mains, so the portal's `engraphis connect --token ...` is a runnable command. `engraphis-connect` is installed too. Credential handling: the connect token travels in the request body and nowhere else — never printed, logged, or persisted, and never quoted back in an error. Malformed or truncated tokens are rejected before any network call, so a bad paste costs no rate budget and consumes no token. Network access uses the repo's pinned opener with redirects blocked and an explicit timeout; provider bodies are never reflected into messages. A 401 (expired / already used / invalid, which the service deliberately makes indistinguishable) stays distinct from a 402 lapsed subscription, because the fixes differ. Client ids are minted-once random ULIDs in the owner-only state directory rather than a hardware fingerprint: a MAC- or hostname-derived id is a cross-account identifier the customer never agreed to ship, and it changes under exactly the conditions where stability was the point. The command verifies `cloud_session.configured()` after writing, and says so explicitly when only the compute endpoint is missing rather than half-reporting success. Docs updated: `docs/AGENT_CONNECT.md` and `.env.example` now describe `engraphis connect --token` as the real path to the session file. Tests: 43 new, covering the happy path writing a usable session, 401 printing actionable copy and writing nothing, 402 staying distinguishable, the token never appearing in stdout/stderr or any written file, and short/malformed tokens being rejected before the network. Co-Authored-By: Claude Opus 5 --- .env.example | 12 +- CHANGELOG.md | 18 ++ docs/AGENT_CONNECT.md | 51 ++- engraphis/device_connect.py | 525 +++++++++++++++++++++++++++++++ pyproject.toml | 5 + scripts/connect.py | 162 ++++++++++ scripts/entry.py | 89 ++++++ tests/test_device_connect.py | 590 +++++++++++++++++++++++++++++++++++ 8 files changed, 1448 insertions(+), 4 deletions(-) create mode 100644 engraphis/device_connect.py create mode 100644 scripts/connect.py create mode 100644 scripts/entry.py create mode 100644 tests/test_device_connect.py diff --git a/.env.example b/.env.example index 7be5648..e58f1a7 100644 --- a/.env.example +++ b/.env.example @@ -151,7 +151,17 @@ ENGRAPHIS_LLM_API_KEY=sk-your-key-here # ENGRAPHIS_CLOUD_COMPUTE_URL=https://compute.engraphis.com # ENGRAPHIS_CLOUD_ORGANIZATION_ID=org_replace_me -# Prefer the owner-only ~/.engraphis/cloud_session.json created during hosted onboarding. +# Prefer the owner-only ~/.engraphis/cloud_session.json written by `engraphis connect`: +# +# engraphis connect --token engr_ct_... # the command your account portal shows +# printf %s "$TOKEN" | engraphis connect --token - # keep the token out of shell history +# +# That is the supported way to connect a client. It redeems the one-time connect token, saves +# the rotating refresh credential with 0600 permissions, and keeps it rotated afterwards, so +# none of the variables below are needed on an interactive machine. Set +# ENGRAPHIS_CLOUD_COMPUTE_URL (or pass --compute-url) only if your account portal shows a +# compute endpoint different from the default. See docs/AGENT_CONNECT.md. +# # For non-interactive deployments a refresh credential may be injected as a bootstrap secret. # It rotates on use; the owner-only saved replacement takes precedence afterward, even while # the environment variable remains set. Never commit it. Bind environment-only bootstrap diff --git a/CHANGELOG.md b/CHANGELOG.md index 3902eb7..64b8b60 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,24 @@ All notable changes to Engraphis are documented here. Format loosely follows ## [Unreleased] +### Added + +- **`engraphis connect --token engr_ct_…`** — the missing client half of device connect. + `cloud_session.save_bootstrap()` is the only writer of `~/.engraphis/cloud_session.json`, + and it had no production caller: the docs told paying customers to prefer a file nothing + created, so a purchased installation could not be connected without hand-writing state. + The new command redeems the one-time connect token from the account portal against + `POST /v1/devices/connect`, saves the returned session with owner-only permissions, and + verifies `cloud_session.configured()` before reporting success. The token is sent in the + request body and nowhere else — never printed, logged, or written to disk — and every + refusal maps to fixed, actionable copy (an expired or already-used token is not confused + with a lapsed subscription). Also installed as `engraphis-connect`. +- An `engraphis` front-door command that dispatches to the existing `engraphis-` + entry points, so the command the account portal displays is runnable as shown. +- A stable per-installation identity at `~/.engraphis/client_identity.json` (random ULIDs, + not a hardware fingerprint) so reconnecting a machine updates its existing installation + instead of registering a new device every time. + ### Removed - **"Signed compliance export" is no longer advertised on any surface.** It was granted to diff --git a/docs/AGENT_CONNECT.md b/docs/AGENT_CONNECT.md index 67e2b37..1e4d969 100644 --- a/docs/AGENT_CONNECT.md +++ b/docs/AGENT_CONNECT.md @@ -25,8 +25,9 @@ organization: 1. The organization owner starts Team or purchases a subscription in Engraphis Cloud. 2. The owner invites named members and assigns roles in the hosted dashboard. -3. A member accepts the invitation and creates a scoped agent/device credential. -4. The member configures their agent with the hosted URL and the one-time credential. +3. A member accepts the invitation and generates a one-time **connect token** (`engr_ct_…`). + The account portal shows the exact command to run. +4. The member runs that command on the machine being connected (see below). 5. The hosted service rechecks organization membership, role, scopes, entitlement version, and workspace binding on every request. @@ -37,6 +38,47 @@ The hosted onboarding flow provides the exact endpoint and client snippet for th organization. Do not substitute the URL of a public self-hosted image: that image intentionally has no Team identity backend. +## Connect a machine: `engraphis connect` + +Copy the command from your account portal and run it on the machine you are connecting: + +```bash +engraphis connect --token engr_ct_... +``` + +That redeems the token against `POST /v1/devices/connect` on the control plane and writes the +owner-only session file `~/.engraphis/cloud_session.json` (mode `0600`). The dashboard, the MCP +server, and Cloud Sync all read that file, so no environment secret is needed afterwards. Rerun +`engraphis connect` with a fresh token on every machine you want connected. + +Useful options: + +| Option | Effect | +| --- | --- | +| `--token -` | Read the token from stdin, so it never enters shell history. | +| `--workspace WS_ID` | Bind this device to a single workspace. | +| `--label TEXT` | Name this installation in your account portal. | +| `--device-name TEXT` | Override the device name (defaults to the hostname). | +| `--control-url URL` | Point at a non-default control plane. | +| `--compute-url URL` | Set the managed compute endpoint (also `ENGRAPHIS_CLOUD_COMPUTE_URL`). | +| `--json` | Print a redacted, machine-readable summary. | + +The same command is installed as `engraphis-connect`, matching the other `engraphis-*` scripts. + +Connect tokens are **single-use and short-lived**. The service answers every refusal — expired, +already redeemed, or never valid — with the same `401`, so the client reports all three +possibilities and the fix is always the same: generate a new token in the account portal. A `402` +means the subscription itself has lapsed; fix billing rather than the token. + +The token is a credential. It is sent in the request body and nowhere else — it is never +printed, never logged, and never written to disk. What *is* written is the rotating refresh +credential the service returns, which is why the session file is owner-only. + +The command also mints a stable per-installation identity at `~/.engraphis/client_identity.json` +(random ULIDs, not a hardware fingerprint) so reconnecting the same machine updates the existing +installation instead of registering a new device every time. Both files honour +`ENGRAPHIS_STATE_DIR`; a distinct state directory is a distinct installation. + ## Credential lifecycle Hosted access uses short-lived access tokens plus rotating refresh credentials. A refresh family @@ -45,7 +87,10 @@ service; the raw replacement is returned once and must be kept in an owner-only or secrets manager. Customer-side environment variables are documented in [`.env.example`](../.env.example). Prefer -the onboarding-created `~/.engraphis/cloud_session.json` over long-lived environment secrets. +the `~/.engraphis/cloud_session.json` that `engraphis connect --token` writes over long-lived +environment secrets: it holds a rotating credential, it is owner-only, and it is the path the +client keeps up to date on its own. Environment secrets are for non-interactive deployments that +cannot run the connect command. ## Trial and grace diff --git a/engraphis/device_connect.py b/engraphis/device_connect.py new file mode 100644 index 0000000..90a33c3 --- /dev/null +++ b/engraphis/device_connect.py @@ -0,0 +1,525 @@ +"""Client half of the Engraphis Cloud device-connect flow. + +The account portal issues a one-time connect token (``engr_ct_...``) and shows the +customer a single command. This module exchanges that token for the durable session +material :func:`engraphis.cloud_session.save_bootstrap` persists, so +``~/.engraphis/cloud_session.json`` -- the file :doc:`AGENT_CONNECT` and ``.env.example`` +tell paying customers to prefer -- is finally created by something. Before this existed +``save_bootstrap`` had no production caller at all and a paid installation could not be +connected without hand-writing the state file. + +Design constraints, all of which have teeth: + +* **The connect token is a bearer credential.** It travels in the request body and + nowhere else: never in a log line, never in an exception message, never in the saved + session, never echoed back to the terminal. Callers get a redacted summary. +* **The vetted transport only.** Requests go through + :func:`engraphis.hosted_client.build_pinned_https_opener` with redirects blocked and an + explicit timeout, exactly as :mod:`engraphis.cloud_session` and + :mod:`engraphis.update_check` do. A bare ``urllib.request.build_opener`` would drop the + DNS-rebinding guard on a credential-bearing call. +* **Fixed copy keyed on status.** Provider bodies are untrusted -- they may carry + internal URLs -- so nothing from the response is reflected into an error message. The + control plane deliberately makes expired / consumed / invalid tokens indistinguishable + (all ``401``), so the client says all three at once rather than guessing. +""" +from __future__ import annotations + +import json +import os +import platform +import re +import socket +import urllib.error +import urllib.request +from pathlib import Path +from typing import Optional, Tuple + +from engraphis import cloud_session +from engraphis.hosted_client import ( + CloudUrlUnresolved, + build_pinned_https_opener, + upgrade_url, + validate_cloud_base_url, +) +from engraphis.private_state import ( + UnsafeStateFile, + atomic_private_text, + publish_private_text_if_absent, + read_private_text, +) + +try: # installed distribution -> real version; source tree -> harmless fallback + from engraphis import __version__ as CURRENT_VERSION +except Exception: # pragma: no cover - engraphis is always importable in practice + CURRENT_VERSION = "0" + +#: Path segment of the unauthenticated connect endpoint on the control plane. +CONNECT_PATH = "/v1/devices/connect" + +#: One interactive request. Longer than the 10s refresh budget because this runs at a +#: human's prompt, once, and a spurious timeout costs the customer a fresh token. +DEFAULT_TIMEOUT_SECONDS = 15.0 + +#: The control plane answers with a small fixed record; anything larger is not ours. +_MAX_RESPONSE_BYTES = 64 * 1024 + +#: The portal always mints tokens with this prefix. Checking it locally turns a +#: mistyped or truncated paste into an instant, free error instead of a round trip that +#: consumes rate budget and returns the same opaque 401 as a genuinely dead token. +CONNECT_TOKEN_PREFIX = "engr_ct_" +#: Shortest credible token: the prefix plus enough entropy to be a real secret. +_MIN_TOKEN_CHARS = len(CONNECT_TOKEN_PREFIX) + 16 +_MAX_TOKEN_CHARS = 512 +#: ``secrets.token_urlsafe`` alphabet. Anything else is a paste accident (a shell- +#: mangled quote, a wrapped line, a whole command copied in). +_TOKEN_BODY = re.compile(r"\A[A-Za-z0-9_-]+\Z") + +#: Identity file for this installation. Kept beside ``cloud_session.json`` in the same +#: owner-only state directory and honouring the same ``ENGRAPHIS_STATE_DIR`` override. +_IDENTITY_FILENAME = "client_identity.json" +_IDENTITY_SCHEMA = "engraphis-client-identity/v1" + +#: Compute endpoint for the production deployment. ``DeviceRegistrationResponse`` does +#: not carry one, and ``cloud_session.configured()`` requires it, so a connect against the +#: shipped control plane would otherwise leave a customer "connected" but not configured. +#: Applied *only* when the control plane is the shipped one: a self-hosted or staging +#: control URL gets no guess, and the caller is told to supply the compute URL. +DEFAULT_COMPUTE_URL = "https://compute.engraphis.com" + + +class DeviceConnectError(RuntimeError): + """A connect attempt failed with public, actionable copy. + + ``status`` mirrors the control-plane status where there was one, and uses ``400`` for + a request this client refused to send at all. + """ + + def __init__(self, message: str, *, status: int = 503) -> None: + super().__init__(message) + self.status = status + + +class _NoRedirect(urllib.request.HTTPRedirectHandler): + """Refuse redirects: a 3xx would replay the connect token at an unvetted host.""" + + def redirect_request(self, req, fp, code, msg, headers, newurl): + return None + + +def normalize_connect_token(value: object) -> str: + """Return the trimmed token, or raise before any network call happens. + + Never quotes the offending value. A rejected token is still a credential -- an + error message containing it would land in shell history, CI logs and bug reports. + """ + + token = str(value or "").strip() + if not token: + raise DeviceConnectError( + "No connect token was supplied. Copy the `engraphis connect --token ...` " + "command shown in your Engraphis account portal.", + status=400, + ) + if ( + not token.startswith(CONNECT_TOKEN_PREFIX) + or len(token) < _MIN_TOKEN_CHARS + or len(token) > _MAX_TOKEN_CHARS + or not _TOKEN_BODY.match(token[len(CONNECT_TOKEN_PREFIX):]) + ): + raise DeviceConnectError( + "That does not look like an Engraphis connect token (they start with " + "`%s`). Copy the whole command from your account portal -- a token split " + "across lines or missing its last characters will not work." + % CONNECT_TOKEN_PREFIX, + status=400, + ) + return token + + +def _state_dir() -> Path: + root = os.environ.get("ENGRAPHIS_STATE_DIR", "").strip() + return Path(root).expanduser() if root else Path.home() / ".engraphis" + + +def _identity_path() -> Path: + return _state_dir() / _IDENTITY_FILENAME + + +def _new_client_id(prefix: str) -> str: + # The package's own ULID minter, so these ids sort chronologically and read the same + # way as every other prefixed id in the client. + from engraphis.core import ids + + return "%s_%s" % (prefix, ids.ulid()) + + +def _read_identity() -> dict: + try: + raw = read_private_text(_identity_path(), max_bytes=8 * 1024, allow_missing=True) + except UnsafeStateFile as exc: + raise DeviceConnectError( + "The saved client identity has unsafe filesystem permissions. Remove %s and " + "connect again." % _identity_path(), + status=409, + ) from exc + except (OSError, RuntimeError): + return {} + if not raw: + return {} + try: + value = json.loads(raw) + except (ValueError, RecursionError): + return {} + return value if isinstance(value, dict) else {} + + +def client_identity() -> Tuple[str, str]: + """Return ``(installation_client_id, device_client_id)`` for this machine. + + Minted once and persisted at ``/client_identity.json`` with owner-only + permissions, so reconnecting the same machine re-presents the same pair and the + control plane recognises the installation instead of accumulating a new phantom + device on every connect. + + They are random ULIDs rather than a hardware fingerprint on purpose: a MAC- or + hostname-derived id is a stable cross-account identifier the customer never agreed to + ship, and it changes under exactly the conditions (a new NIC, a rename) where + stability was the point. "Stable per installation" is what the server needs, and a + minted-once file in the state directory is precisely that. A second state directory + (``ENGRAPHIS_STATE_DIR``, a container, another user account) is a second installation, + which is the correct reading. + """ + + saved = _read_identity() + installation = str(saved.get("installation_client_id") or "").strip() + device = str(saved.get("device_client_id") or "").strip() + if installation and device: + return installation, device + + minted = { + "schema": _IDENTITY_SCHEMA, + "installation_client_id": installation or _new_client_id("inst"), + "device_client_id": device or _new_client_id("dev"), + } + payload = json.dumps(minted, sort_keys=True, separators=(",", ":")) + path = _identity_path() + try: + if not publish_private_text_if_absent(path, payload): + # Another process won the create, or a half-written file already existed. + # Re-read: the winner's ids are the ones the control plane will see. + existing = _read_identity() + installation = str(existing.get("installation_client_id") or "").strip() + device = str(existing.get("device_client_id") or "").strip() + if installation and device: + return installation, device + atomic_private_text(path, payload) + except UnsafeStateFile as exc: + raise DeviceConnectError( + "The client identity file at %s could not be written safely." % path, + status=409, + ) from exc + except OSError as exc: + raise DeviceConnectError( + "Could not write the client identity file at %s." % path, status=409 + ) from exc + return minted["installation_client_id"], minted["device_client_id"] + + +def default_control_url() -> str: + """Resolve the control plane: explicit env override, else the shipped manifest.""" + + configured = os.environ.get("ENGRAPHIS_CLOUD_CONTROL_URL", "").strip() + if configured: + return configured + try: + from engraphis.commercial import manifest + + return str(manifest().get("control_plane") or "").strip() + except Exception: # pragma: no cover - manifest ships with the package + return "" + + +def default_compute_url(control_url: str) -> str: + """Resolve the compute plane, guessing only for the shipped control plane.""" + + configured = os.environ.get("ENGRAPHIS_CLOUD_COMPUTE_URL", "").strip() + if configured: + return configured + shipped = "" + try: + from engraphis.commercial import manifest + + shipped = str(manifest().get("control_plane") or "").strip() + except Exception: # pragma: no cover - manifest ships with the package + return "" + if shipped and control_url.rstrip("/") == shipped.rstrip("/"): + return DEFAULT_COMPUTE_URL + return "" + + +def _validated_control_url(value: str) -> str: + if not str(value or "").strip(): + raise DeviceConnectError( + "No Engraphis Cloud control URL is configured. Set " + "ENGRAPHIS_CLOUD_CONTROL_URL or pass --control-url.", + status=400, + ) + try: + return validate_cloud_base_url(value) + except CloudUrlUnresolved as exc: + # "Offline" is not "misconfigured": validate_cloud_base_url resolves the host, so + # a customer on a plane would otherwise be told their URL is invalid forever. + raise DeviceConnectError( + "Engraphis Cloud is temporarily unreachable. Check your network and try " + "again.", + status=503, + ) from exc + except ValueError as exc: + raise DeviceConnectError( + "The Engraphis Cloud control URL is not a valid HTTPS endpoint.", status=400 + ) from exc + + +def _default_device_name() -> str: + try: + name = socket.gethostname().strip() + except OSError: + name = "" + return name[:100] + + +def _default_platform() -> str: + try: + return ("%s %s" % (platform.system(), platform.machine())).strip()[:100] + except Exception: # pragma: no cover - platform is stdlib and total + return "" + + +def _connect_http_error(status: int) -> DeviceConnectError: + """Map a control-plane status to fixed, actionable copy. + + Only the status is used. ``401`` deliberately covers expired, already-consumed and + never-valid tokens with one indistinguishable answer, so the copy names all three + instead of asserting one -- the fix is the same in every case. + """ + + if status == 401: + return DeviceConnectError( + "That connect token has expired, was already used, or is not valid. " + "Generate a new one in your Engraphis account portal and run " + "`engraphis connect --token ...` again.", + status=401, + ) + if status == 402: + return DeviceConnectError( + "This Engraphis Cloud subscription is not active, so no new device can be " + "connected. Update billing at %s and try again." % upgrade_url(), + status=402, + ) + if status == 403: + return DeviceConnectError( + "Engraphis Cloud refused this connect request. Check with the organization " + "owner that your account may still add devices.", + status=403, + ) + if status == 404: + return DeviceConnectError( + "This Engraphis Cloud control plane has no device-connect endpoint. Check " + "ENGRAPHIS_CLOUD_CONTROL_URL points at the URL shown in your account portal.", + status=404, + ) + if status == 422: + return DeviceConnectError( + "Engraphis Cloud rejected this connect request as malformed. Upgrade the " + "client (`pip install -U engraphis`) and try again.", + status=422, + ) + if status == 429: + return DeviceConnectError( + "Too many connect attempts. Wait a minute and try again.", status=429 + ) + if status == 503: + return DeviceConnectError( + "Engraphis Cloud is not accepting new device activations right now. Try " + "again shortly; your connect token is unaffected.", + status=503, + ) + return DeviceConnectError( + "Engraphis Cloud could not connect this device. Try again shortly.", status=503 + ) + + +def post_connect(control_url: str, token: str, *, installation_client_id: str, + device_client_id: str, installation_label: Optional[str] = None, + device_name: Optional[str] = None, app_platform: Optional[str] = None, + app_version: Optional[str] = None, workspace_id: Optional[str] = None, + timeout: float = DEFAULT_TIMEOUT_SECONDS) -> dict: + """POST the connect token and return the ``DeviceRegistrationResponse`` body. + + *control_url* must already be validated. The endpoint rejects unknown fields with a + ``422``, so optional values are omitted rather than sent empty, and there is + deliberately no ``organization_id``: the token carries the organization. + """ + + body = { + "connect_token": token, + "installation_client_id": installation_client_id, + "device_client_id": device_client_id, + } + for key, value in ( + ("installation_label", installation_label), + ("device_name", device_name), + ("platform", app_platform), + ("app_version", app_version), + ("workspace_id", workspace_id), + ): + cleaned = str(value or "").strip() + if cleaned: + body[key] = cleaned + + payload = json.dumps(body, sort_keys=True, separators=(",", ":")).encode("utf-8") + request = urllib.request.Request( + control_url + CONNECT_PATH, + data=payload, + headers={ + "Accept": "application/json", + "Content-Type": "application/json", + "User-Agent": "Engraphis/%s device-connect" % CURRENT_VERSION, + }, + method="POST", + ) + try: + with build_pinned_https_opener(_NoRedirect()).open( + request, timeout=timeout + ) as response: # nosec B310 - scheme validated by validate_cloud_base_url + raw = response.read(_MAX_RESPONSE_BYTES + 1) + except urllib.error.HTTPError as exc: + status = exc.code + # Draining the error body can itself raise; a sibling ``except`` of this ``try`` + # would not cover it, so an unguarded read escapes as a raw traceback exactly + # when the cloud is flaky. Same shape as cloud_session._post_refresh. + try: + exc.read(_MAX_RESPONSE_BYTES + 1) + except (OSError, ValueError): + pass + finally: + try: + exc.close() + except (OSError, ValueError): + pass + raise _connect_http_error(status) + except (urllib.error.URLError, TimeoutError, OSError) as exc: + # ``exc`` may quote an internal host or a proxy URL; never reflect it. + raise DeviceConnectError( + "Engraphis Cloud is temporarily unreachable. Check your network and try " + "again.", + status=503, + ) from exc + if len(raw) > _MAX_RESPONSE_BYTES: + raise DeviceConnectError( + "Engraphis Cloud returned an oversized connect response.", status=502 + ) + try: + parsed = json.loads(raw.decode("utf-8")) + except (UnicodeDecodeError, ValueError, RecursionError) as exc: + raise DeviceConnectError( + "Engraphis Cloud returned an invalid connect response.", status=502 + ) from exc + if not isinstance(parsed, dict): + raise DeviceConnectError( + "Engraphis Cloud returned an invalid connect response.", status=502 + ) + return parsed + + +#: Fields worth echoing back to the customer. Deliberately excludes +#: ``refresh_credential`` and ``access_token``: the summary is printed. +_SUMMARY_FIELDS = ( + "organization_id", + "installation_id", + "device_id", + "member_id", + "workspace_id", + "token_subject", + "plan", + "cloud_access_active", + "cloud_features", + "entitlement_version", + "expires_in_seconds", +) + + +def summarize(response: dict) -> dict: + """Return the non-secret fields of a registration response, for display.""" + + summary = {} + for key in _SUMMARY_FIELDS: + if key in response: + summary[key] = response[key] + return summary + + +def connect(token: object, *, control_url: Optional[str] = None, + compute_url: Optional[str] = None, workspace_id: Optional[str] = None, + installation_label: Optional[str] = None, device_name: Optional[str] = None, + timeout: float = DEFAULT_TIMEOUT_SECONDS) -> dict: + """Exchange a connect token for a saved cloud session. + + Returns the redacted summary -- it is safe to print. Raises + :class:`DeviceConnectError` for every failure, with copy the customer can act on and + never containing the token. Nothing is written unless the exchange succeeded. + """ + + normalized = normalize_connect_token(token) + resolved_control = _validated_control_url( + control_url if control_url is not None else default_control_url() + ) + resolved_compute = ( + compute_url if compute_url is not None else default_compute_url(resolved_control) + ) + if resolved_compute: + try: + resolved_compute = validate_cloud_base_url(resolved_compute) + except CloudUrlUnresolved as exc: + raise DeviceConnectError( + "The Engraphis Cloud compute endpoint is temporarily unreachable.", + status=503, + ) from exc + except ValueError as exc: + raise DeviceConnectError( + "The Engraphis Cloud compute URL is not a valid HTTPS endpoint.", + status=400, + ) from exc + + installation_client_id, device_client_id = client_identity() + response = post_connect( + resolved_control, + normalized, + installation_client_id=installation_client_id, + device_client_id=device_client_id, + installation_label=installation_label, + device_name=device_name if device_name is not None else _default_device_name(), + app_platform=_default_platform(), + app_version=str(CURRENT_VERSION), + workspace_id=workspace_id, + timeout=timeout, + ) + if not str(response.get("refresh_credential") or "").strip(): + raise DeviceConnectError( + "Engraphis Cloud accepted the token but returned no session credential. " + "Try again, and contact support if it repeats.", + status=502, + ) + try: + cloud_session.save_bootstrap( + response, control_url=resolved_control, compute_url=resolved_compute or None + ) + except cloud_session.CloudSessionError as exc: + raise DeviceConnectError(str(exc), status=getattr(exc, "status", 503)) from exc + + summary = summarize(response) + summary["control_url"] = resolved_control + summary["compute_url"] = resolved_compute + summary["session_path"] = str(_state_dir() / "cloud_session.json") + return summary diff --git a/pyproject.toml b/pyproject.toml index da56949..5af2743 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -164,6 +164,11 @@ Repository = "https://github.com/Coding-Dev-Tools/engraphis" Issues = "https://github.com/Coding-Dev-Tools/engraphis/issues" [project.scripts] +# The front door. The account portal tells customers to run `engraphis connect --token ...`, +# so the bare verb form has to exist; scripts.entry dispatches to the same main() each +# engraphis- script below calls. +engraphis = "scripts.entry:main" +engraphis-connect = "scripts.connect:main" engraphis-server = "scripts.start_server:main" engraphis-cli = "scripts.cli:main" engraphis-mcp = "engraphis.mcp_cli:main" diff --git a/scripts/connect.py b/scripts/connect.py new file mode 100644 index 0000000..afbb630 --- /dev/null +++ b/scripts/connect.py @@ -0,0 +1,162 @@ +"""engraphis connect - redeem the connect token from your account portal. + +Your Engraphis account portal shows a one-time token and the exact command to run: + + engraphis connect --token engr_ct_... + +That exchanges the token with the control plane and writes the owner-only session file +``~/.engraphis/cloud_session.json`` that the dashboard, MCP server, and Cloud Sync all +read. Until this command existed the file had no writer at all, so a paying customer had +no supported way to connect a client. + + engraphis connect --token engr_ct_... # the normal case + engraphis connect --token - # read the token from stdin + engraphis connect --token ... --workspace ws_1 # bind the device to one workspace + engraphis connect --token ... --label "CI runner" + engraphis connect --token ... --json # redacted machine-readable summary + +The token is a credential. It is sent in the request body and nowhere else: it is never +printed, never logged, and never written to disk. Passing it as an argument does put it +in your shell history, so ``--token -`` is available for scripted and shared machines. + +Non-interactive by design (no prompts): safe in scripts, CI, and agent shells. +""" +from __future__ import annotations + +import argparse +import json +import sys +from pathlib import Path + +from engraphis import cloud_session +from engraphis.device_connect import ( + DEFAULT_TIMEOUT_SECONDS, + DeviceConnectError, + connect, +) + + +def _prog(argv_zero: str) -> str: + """Name this command the way the caller actually invoked it.""" + + stem = Path(argv_zero or "").stem + return stem if stem.endswith("connect") and stem != "connect" else "engraphis connect" + + +def _read_token(value: str) -> str: + """Resolve ``--token -`` to one line of stdin, keeping it off the command line.""" + + if value != "-": + return value + if sys.stdin is None or sys.stdin.isatty(): + # A bare `--token -` on a terminal would silently hang waiting for input. + raise DeviceConnectError( + "--token - reads the token from stdin; pipe it in, for example " + "`printf %s \"$ENGRAPHIS_CONNECT_TOKEN\" | engraphis connect --token -`.", + status=400, + ) + return sys.stdin.readline() + + +def _print_summary(summary: dict) -> None: + rows = [ + ("organization", summary.get("organization_id")), + ("installation", summary.get("installation_id")), + ("device", summary.get("device_id")), + ("member", summary.get("member_id")), + ("workspace", summary.get("workspace_id")), + ("subject", summary.get("token_subject")), + ] + plan = str(summary.get("plan") or "").strip() + if plan: + active = summary.get("cloud_access_active") + rows.append(("plan", plan + ("" if active is None else + " (active)" if active else " (inactive)"))) + features = summary.get("cloud_features") + if isinstance(features, (list, tuple)) and features: + rows.append(("features", ", ".join(str(item) for item in features))) + rows.append(("control url", summary.get("control_url"))) + rows.append(("compute url", summary.get("compute_url") or "(not configured)")) + rows.append(("session file", summary.get("session_path"))) + + print("Connected this device to Engraphis Cloud.") + print() + for label, value in rows: + text = str(value or "").strip() + if text: + print(" %-14s %s" % (label, text)) + + +def main(argv=None) -> int: + ap = argparse.ArgumentParser( + prog=_prog(sys.argv[0] if sys.argv else ""), + description=__doc__, + formatter_class=argparse.RawDescriptionHelpFormatter, + ) + ap.add_argument("--token", required=True, metavar="TOKEN", + help="the connect token from your account portal, or - for stdin") + ap.add_argument("--control-url", default=None, metavar="URL", + help="control plane to connect to (default: the shipped endpoint, " + "or ENGRAPHIS_CLOUD_CONTROL_URL)") + ap.add_argument("--compute-url", default=None, metavar="URL", + help="managed compute endpoint (default: ENGRAPHIS_CLOUD_COMPUTE_URL, " + "or the shipped endpoint)") + ap.add_argument("--workspace", default=None, metavar="WORKSPACE_ID", + help="bind this device to a single workspace") + ap.add_argument("--label", default=None, metavar="TEXT", + help="label for this installation in your account portal") + ap.add_argument("--device-name", default=None, metavar="TEXT", + help="device name shown in your account portal (default: hostname)") + ap.add_argument("--timeout", type=float, default=DEFAULT_TIMEOUT_SECONDS, + metavar="SECONDS", help="network timeout (default: %(default)s)") + ap.add_argument("--json", action="store_true", + help="print the redacted summary as JSON instead of a report") + args = ap.parse_args(argv) + + try: + summary = connect( + _read_token(args.token), + control_url=args.control_url, + compute_url=args.compute_url, + workspace_id=args.workspace, + installation_label=args.label, + device_name=args.device_name, + timeout=args.timeout, + ) + except DeviceConnectError as exc: + # ``str(exc)`` is fixed public copy from device_connect; it never carries the + # token, the response body, or an internal hostname. + print("%s: %s" % (ap.prog, exc), file=sys.stderr) + return 1 + + if args.json: + print(json.dumps(summary, sort_keys=True, indent=2)) + else: + _print_summary(summary) + + # Prove the write actually produced a session the rest of the client will use, + # rather than reporting success on a file nothing can load. + try: + usable = cloud_session.configured() + except cloud_session.CloudSessionError as exc: + print("%s: the session was written but is not usable: %s" % (ap.prog, exc), + file=sys.stderr) + return 1 + + if not args.json: + print() + if usable: + print("Next steps:") + print(" engraphis-dashboard # your plan's features are now unlocked") + print(" engraphis-init --check # verify the installation") + else: + print("Note: hosted compute is not configured yet, so managed compute " + "features stay off.") + print(" Set ENGRAPHIS_CLOUD_COMPUTE_URL (or rerun with --compute-url) " + "using the endpoint") + print(" shown in your account portal. Everything else is connected.") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/scripts/entry.py b/scripts/entry.py new file mode 100644 index 0000000..c486055 --- /dev/null +++ b/scripts/entry.py @@ -0,0 +1,89 @@ +"""engraphis - the single front door, so the portal's copy-paste command actually runs. + +Every capability already ships as its own ``engraphis-`` console script; this adds +the spelling customers are *shown*. The account portal hands out + + engraphis connect --token engr_ct_... + +and until there was an ``engraphis`` executable that string was not a runnable command. + +This is a dispatcher, not a second CLI: it rewrites ``sys.argv`` and calls the same +``main()`` the matching ``engraphis-`` script calls, so a verb behaves identically +either way and there is exactly one implementation of each command. The import is lazy +so ``engraphis connect`` never drags in the memory/embedding stack that ``engraphis cli`` +needs. +""" +from __future__ import annotations + +import sys +from importlib import import_module + +#: verb -> "module:function", mirroring ``[project.scripts]`` with the prefix dropped. +COMMANDS = { + "connect": "scripts.connect:main", + "init": "scripts.init:main", + "cli": "scripts.cli:main", + "mcp": "engraphis.mcp_cli:main", + "server": "scripts.start_server:main", + "dashboard": "scripts.start_dashboard:main", + "inspector": "scripts.inspector:main", + "consolidate": "scripts.consolidate:main", + "graph": "scripts.graph_cli:main", + "graph-server": "scripts.graph_server:main", + "update": "scripts.update:main", +} + +_USAGE = """usage: engraphis [options] + +commands: + connect redeem the connect token from your account portal + init write a project .env and print agent setup snippets + cli store and recall memories from the terminal + mcp run the MCP server (Claude Code, Cursor, Cline, Zed) + server run the REST server + dashboard run the product dashboard + inspector inspect the local database + consolidate run consolidation over stored memories + graph query the knowledge graph + graph-server run the graph server + update check for and install a newer Engraphis release + +Run `engraphis --help` for a command's options. +Every command is also installed as `engraphis-`.""" + + +def main(argv=None) -> int: + args = list(sys.argv[1:] if argv is None else argv) + if not args or args[0] in {"-h", "--help", "help"}: + print(_USAGE) + return 0 if args else 2 + if args[0] in {"-V", "--version"}: + from engraphis import __version__ + + print(__version__) + return 0 + + verb = args[0] + target = COMMANDS.get(verb) + if target is None: + print("engraphis: unknown command %r\n" % verb, file=sys.stderr) + print(_USAGE, file=sys.stderr) + return 2 + + module_name, _, attribute = target.partition(":") + command = getattr(import_module(module_name), attribute) + + # Hand the verb its own argv. Some targets take ``main(argv)`` and some read + # ``sys.argv`` directly, so rewriting is the one approach that works for all of + # them -- and it also puts "engraphis connect" in that command's --help/usage. + saved = sys.argv + sys.argv = ["engraphis %s" % verb] + args[1:] + try: + result = command() + finally: + sys.argv = saved + return 0 if result is None else int(result) + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/tests/test_device_connect.py b/tests/test_device_connect.py new file mode 100644 index 0000000..bf775e3 --- /dev/null +++ b/tests/test_device_connect.py @@ -0,0 +1,590 @@ +"""Tests for the client half of the device-connect flow. + +``cloud_session.save_bootstrap`` had no production caller: nothing in the shipped client +ever created ``~/.engraphis/cloud_session.json``, while the docs told customers to prefer +it. These tests pin the command that closes that gap, and in particular that the connect +token -- a bearer credential -- never escapes the request body. +""" +from __future__ import annotations + +import json +import urllib.error +import urllib.request +from io import BytesIO +from pathlib import Path + +import pytest + +from engraphis import cloud_session, device_connect +from scripts import connect as connect_cli + +CONTROL_URL = "https://control.example.test" +COMPUTE_URL = "https://compute.example.test" +TOKEN = "engr_ct_R3plAceMeWithRealEntropy_0123456789" + +#: Every key the server's ``DeviceRegistrationResponse`` carries, fed to the client +#: verbatim the way a real 200 would be. +REGISTRATION = { + "organization_id": "org_alpha", + "installation_id": "instl_alpha", + "device_id": "devc_alpha", + "member_id": "mem_alpha", + "workspace_id": "ws_alpha", + "access_token": "short-lived-access-token", + "token_type": "Bearer", + "expires_in_seconds": 900, + "refresh_credential": "rotating-refresh-credential", + "refresh_expires_at": "2026-08-21T00:00:00Z", + "token_subject": "device", + "entitlement_version": 7, + "plan": "team", + "cloud_access_active": True, + "cloud_features": ["analytics", "automation", "export", "sync", "team"], +} + + +class _Response: + """Minimal stand-in for the ``http.client`` response the opener yields.""" + + def __init__(self, payload: bytes) -> None: + self._payload = payload + + def __enter__(self): + return self + + def __exit__(self, *exc) -> bool: + return False + + def read(self, size: int = -1) -> bytes: + return self._payload + + +class _Opener: + """Fake of the pinned opener, recording exactly what was put on the wire.""" + + def __init__(self, *, body=None, error=None) -> None: + self._body = body + self._error = error + self.calls = [] + + def open(self, request, timeout): + self.calls.append({ + "url": request.full_url, + "method": request.get_method(), + "headers": dict(request.headers), + "body": request.data, + "timeout": timeout, + }) + if self._error is not None: + raise self._error + return _Response(json.dumps(self._body).encode("utf-8")) + + +def _install_opener(monkeypatch, opener) -> None: + # ``build_pinned_https_opener`` is a thin wrapper over ``build_opener``; patching the + # stdlib factory keeps the module's own call site (and its redirect handler) intact. + monkeypatch.setattr(urllib.request, "build_opener", lambda *handlers: opener) + + +def _http_error(status: int, body: bytes = b'{"detail":"private"}'): + return urllib.error.HTTPError( + CONTROL_URL + device_connect.CONNECT_PATH, status, "denied", {}, BytesIO(body) + ) + + +@pytest.fixture(autouse=True) +def _isolated_client_state(monkeypatch, tmp_path): + """A private state directory and a control plane that never needs DNS.""" + + monkeypatch.setenv("ENGRAPHIS_STATE_DIR", str(tmp_path)) + for name in ( + "ENGRAPHIS_CLOUD_CONTROL_URL", + "ENGRAPHIS_CLOUD_COMPUTE_URL", + "ENGRAPHIS_CLOUD_ACCESS_TOKEN", + "ENGRAPHIS_CLOUD_ORGANIZATION_ID", + "ENGRAPHIS_CLOUD_REFRESH_CREDENTIAL", + "ENGRAPHIS_CLOUD_TOKEN_SUBJECT", + ): + monkeypatch.delenv(name, raising=False) + # ``validate_cloud_base_url`` resolves the hostname, so the offline gate cannot use + # the real one against ``.test`` names. Normalization is what callers depend on. + normalize = lambda value: str(value).rstrip("/") # noqa: E731 + monkeypatch.setattr(device_connect, "validate_cloud_base_url", normalize) + monkeypatch.setattr(cloud_session, "validate_cloud_base_url", normalize) + return tmp_path + + +def _state_files(root: Path): + return [path for path in Path(root).rglob("*") if path.is_file()] + + +# --------------------------------------------------------------------------- happy path + + +def test_connect_writes_a_session_the_rest_of_the_client_can_use(monkeypatch, tmp_path): + """The whole point: after connect, ``cloud_session.configured()`` is true. + + Before this command shipped, the only writer of the session file was a function with + zero production callers, so this assertion could not hold for any customer. + """ + + opener = _Opener(body=REGISTRATION) + _install_opener(monkeypatch, opener) + + summary = device_connect.connect( + TOKEN, control_url=CONTROL_URL, compute_url=COMPUTE_URL + ) + + assert cloud_session.configured() is True + saved = json.loads((tmp_path / "cloud_session.json").read_text(encoding="utf-8")) + assert saved["schema"] == "engraphis-cloud-session/v1" + assert saved["organization_id"] == "org_alpha" + assert saved["installation_id"] == "instl_alpha" + assert saved["device_id"] == "devc_alpha" + assert saved["member_id"] == "mem_alpha" + assert saved["refresh_credential"] == "rotating-refresh-credential" + assert saved["token_subject"] == "device" + assert saved["control_url"] == CONTROL_URL + assert saved["compute_url"] == COMPUTE_URL + # The entitlement travelled with the registration, so the dashboard knows the plan on + # its very first boot instead of showing a paying Team customer the free core. + assert saved["plan"] == "team" + assert saved["cloud_access_active"] is True + assert "team" in saved["cloud_features"] + assert summary["organization_id"] == "org_alpha" + + +def test_connect_posts_exactly_the_documented_request(monkeypatch): + """The endpoint 422s on unknown fields, and takes no ``organization_id`` at all.""" + + opener = _Opener(body=REGISTRATION) + _install_opener(monkeypatch, opener) + + device_connect.connect( + TOKEN, + control_url=CONTROL_URL, + compute_url=COMPUTE_URL, + workspace_id="ws_alpha", + installation_label="CI runner", + device_name="build-box", + ) + + call = opener.calls[0] + assert call["url"] == CONTROL_URL + "/v1/devices/connect" + assert call["method"] == "POST" + assert call["timeout"] == device_connect.DEFAULT_TIMEOUT_SECONDS + body = json.loads(call["body"].decode("utf-8")) + assert body["connect_token"] == TOKEN + assert body["installation_client_id"].startswith("inst_") + assert body["device_client_id"].startswith("dev_") + assert body["workspace_id"] == "ws_alpha" + assert body["installation_label"] == "CI runner" + assert body["device_name"] == "build-box" + # The token carries the organization; sending one would be rejected. + assert "organization_id" not in body + assert set(body) <= { + "connect_token", "installation_client_id", "device_client_id", + "installation_label", "device_name", "platform", "app_version", "workspace_id", + } + + +def test_optional_fields_are_omitted_rather_than_sent_empty(monkeypatch): + opener = _Opener(body=REGISTRATION) + _install_opener(monkeypatch, opener) + + device_connect.connect( + TOKEN, control_url=CONTROL_URL, compute_url=COMPUTE_URL, device_name="" + ) + + body = json.loads(opener.calls[0]["body"].decode("utf-8")) + assert "workspace_id" not in body + assert "installation_label" not in body + assert "device_name" not in body + + +def test_client_ids_are_stable_across_connects(monkeypatch): + """A reconnect must re-present the same installation, not mint a phantom device.""" + + opener = _Opener(body=REGISTRATION) + _install_opener(monkeypatch, opener) + + first = device_connect.client_identity() + device_connect.connect(TOKEN, control_url=CONTROL_URL, compute_url=COMPUTE_URL) + device_connect.connect(TOKEN, control_url=CONTROL_URL, compute_url=COMPUTE_URL) + + bodies = [json.loads(call["body"].decode("utf-8")) for call in opener.calls] + assert {body["installation_client_id"] for body in bodies} == {first[0]} + assert {body["device_client_id"] for body in bodies} == {first[1]} + assert device_connect.client_identity() == first + + +# ------------------------------------------------------------------------ failure modes + + +def test_expired_or_consumed_token_is_actionable_and_writes_nothing( + monkeypatch, tmp_path, capsys +): + """401 is the control plane's single answer for expired / consumed / invalid. + + The copy therefore has to name all three and point at the one fix, and a refused + connect must not leave a half-written session behind for the dashboard to load. + """ + + _install_opener(monkeypatch, _Opener(error=_http_error(401))) + + exit_code = connect_cli.main([ + "--token", TOKEN, "--control-url", CONTROL_URL, "--compute-url", COMPUTE_URL, + ]) + + assert exit_code == 1 + captured = capsys.readouterr() + assert "expired" in captured.err + assert "already used" in captured.err + assert "account portal" in captured.err + assert not (tmp_path / "cloud_session.json").exists() + assert cloud_session.configured() is False + + +def test_lapsed_subscription_is_distinguishable_from_a_dead_token(monkeypatch, capsys): + """402 must not be flattened into "your token is bad" -- the fix is billing.""" + + _install_opener(monkeypatch, _Opener(error=_http_error(402))) + + exit_code = connect_cli.main([ + "--token", TOKEN, "--control-url", CONTROL_URL, "--compute-url", COMPUTE_URL, + ]) + + assert exit_code == 1 + message = capsys.readouterr().err + assert "subscription is not active" in message + assert "billing" in message + assert "expired" not in message + + with pytest.raises(device_connect.DeviceConnectError) as caught: + device_connect.connect(TOKEN, control_url=CONTROL_URL, compute_url=COMPUTE_URL) + assert caught.value.status == 402 + + +@pytest.mark.parametrize( + "status,fragment", + [ + (403, "organization owner"), + (422, "pip install -U engraphis"), + (429, "Too many connect attempts"), + (503, "not accepting new device activations"), + (500, "could not connect this device"), + ], +) +def test_each_failure_status_gets_its_own_copy(monkeypatch, status, fragment): + _install_opener(monkeypatch, _Opener(error=_http_error(status))) + + with pytest.raises(device_connect.DeviceConnectError) as caught: + device_connect.connect(TOKEN, control_url=CONTROL_URL, compute_url=COMPUTE_URL) + + assert fragment in str(caught.value) + assert caught.value.status == (status if status != 500 else 503) + + +def test_error_body_is_never_reflected_into_the_message(monkeypatch): + """Provider bodies are untrusted and may quote internal hosts.""" + + error = _http_error(503, b'{"detail":"upstream 10.0.0.7 activation freeze"}') + _install_opener(monkeypatch, _Opener(error=error)) + + with pytest.raises(device_connect.DeviceConnectError) as caught: + device_connect.connect(TOKEN, control_url=CONTROL_URL, compute_url=COMPUTE_URL) + + assert "10.0.0.7" not in str(caught.value) + + +def test_http_error_body_is_drained_and_closed(monkeypatch): + error = _http_error(429) + closed = [] + original_close = error.close + error.close = lambda: (closed.append(True), original_close()) + _install_opener(monkeypatch, _Opener(error=error)) + + with pytest.raises(device_connect.DeviceConnectError): + device_connect.connect(TOKEN, control_url=CONTROL_URL, compute_url=COMPUTE_URL) + + assert closed == [True] + + +def test_network_failure_reports_an_outage_without_leaking_the_detail(monkeypatch): + _install_opener( + monkeypatch, _Opener(error=urllib.error.URLError("proxy.internal refused")) + ) + + with pytest.raises(device_connect.DeviceConnectError) as caught: + device_connect.connect(TOKEN, control_url=CONTROL_URL, compute_url=COMPUTE_URL) + + assert caught.value.status == 503 + assert "proxy.internal" not in str(caught.value) + + +def test_a_success_without_a_refresh_credential_writes_nothing(monkeypatch, tmp_path): + body = dict(REGISTRATION) + body.pop("refresh_credential") + _install_opener(monkeypatch, _Opener(body=body)) + + with pytest.raises(device_connect.DeviceConnectError): + device_connect.connect(TOKEN, control_url=CONTROL_URL, compute_url=COMPUTE_URL) + + assert not (tmp_path / "cloud_session.json").exists() + + +@pytest.mark.parametrize("payload", [b"not json", b'"a string"', b"[]"]) +def test_a_non_object_response_is_rejected(monkeypatch, payload): + class _Raw(_Opener): + def open(self, request, timeout): + return _Response(payload) + + _install_opener(monkeypatch, _Raw()) + + with pytest.raises(device_connect.DeviceConnectError, match="invalid connect"): + device_connect.connect(TOKEN, control_url=CONTROL_URL, compute_url=COMPUTE_URL) + + +# ------------------------------------------------------------- pre-flight token hygiene + + +@pytest.mark.parametrize("token", [ + "", + " ", + "engr_ct_", + "engr_ct_short", + "ct_missing_prefix_but_long_enough_to_pass", + "engr_ct_has spaces in the middle", + "engr_ct_" + "x" * 600, + "engraphis connect --token engr_ct_pasted_whole_command", +]) +def test_malformed_tokens_are_rejected_before_any_network_call(monkeypatch, token): + """A bad paste must cost nothing: no request, no rate budget, no consumed token.""" + + class _Poison: + def open(self, request, timeout): + raise AssertionError("a malformed token must not reach the network") + + _install_opener(monkeypatch, _Poison()) + + with pytest.raises(device_connect.DeviceConnectError) as caught: + device_connect.connect(token, control_url=CONTROL_URL) + + assert caught.value.status == 400 + + +def test_a_rejected_token_is_not_quoted_back(monkeypatch): + """Even an invalid token is a credential: it must stay out of the error text.""" + + secret = "engr_ct_" + "s" * 4 # too short, but still secret-shaped + with pytest.raises(device_connect.DeviceConnectError) as caught: + device_connect.connect(secret, control_url=CONTROL_URL) + + assert secret not in str(caught.value) + assert "ssss" not in str(caught.value) + + +def test_surrounding_whitespace_from_a_paste_is_tolerated(monkeypatch): + opener = _Opener(body=REGISTRATION) + _install_opener(monkeypatch, opener) + + device_connect.connect( + " %s\n" % TOKEN, control_url=CONTROL_URL, compute_url=COMPUTE_URL + ) + + body = json.loads(opener.calls[0]["body"].decode("utf-8")) + assert body["connect_token"] == TOKEN + + +# ------------------------------------------------------------------ credential leakage + + +def test_the_token_never_reaches_stdout_stderr_or_disk(monkeypatch, tmp_path, capsys): + """The one invariant that has to hold on the success path too. + + A token echoed into a terminal lands in scrollback, CI logs and screenshots; a token + persisted next to the session outlives the single use it was minted for. + """ + + opener = _Opener(body=REGISTRATION) + _install_opener(monkeypatch, opener) + + exit_code = connect_cli.main([ + "--token", TOKEN, "--control-url", CONTROL_URL, "--compute-url", COMPUTE_URL, + ]) + assert exit_code == 0 + + captured = capsys.readouterr() + assert TOKEN not in captured.out + assert TOKEN not in captured.err + written = _state_files(tmp_path) + assert written, "connect must actually write the session" + for path in written: + assert TOKEN.encode("utf-8") not in path.read_bytes(), "token leaked into %s" % path + # It did go where it belongs. + assert TOKEN.encode("utf-8") in opener.calls[0]["body"] + + +def test_the_session_secrets_are_not_printed(monkeypatch, capsys): + _install_opener(monkeypatch, _Opener(body=REGISTRATION)) + + connect_cli.main([ + "--token", TOKEN, "--control-url", CONTROL_URL, "--compute-url", COMPUTE_URL, + ]) + + captured = capsys.readouterr() + assert REGISTRATION["refresh_credential"] not in captured.out + assert REGISTRATION["access_token"] not in captured.out + assert "org_alpha" in captured.out # the useful, non-secret parts are shown + + +def test_the_json_summary_carries_no_secrets(monkeypatch, capsys): + _install_opener(monkeypatch, _Opener(body=REGISTRATION)) + + connect_cli.main([ + "--token", TOKEN, "--control-url", CONTROL_URL, "--compute-url", COMPUTE_URL, + "--json", + ]) + + summary = json.loads(capsys.readouterr().out) + assert "refresh_credential" not in summary + assert "access_token" not in summary + assert summary["plan"] == "team" + assert summary["control_url"] == CONTROL_URL + + +def test_summarize_drops_every_secret_field(): + summary = device_connect.summarize(REGISTRATION) + assert set(summary) & {"refresh_credential", "access_token"} == set() + assert summary["organization_id"] == "org_alpha" + + +# ------------------------------------------------------------------------- CLI surface + + +def test_cli_reports_the_connection_and_the_next_step(monkeypatch, capsys): + _install_opener(monkeypatch, _Opener(body=REGISTRATION)) + + assert connect_cli.main([ + "--token", TOKEN, "--control-url", CONTROL_URL, "--compute-url", COMPUTE_URL, + ]) == 0 + + out = capsys.readouterr().out + assert "Connected this device to Engraphis Cloud." in out + assert "team" in out + assert "cloud_session.json" in out + assert "engraphis-dashboard" in out + + +def test_cli_says_so_when_compute_is_not_configured(monkeypatch, capsys): + """Connecting against a custom control plane must not silently half-configure.""" + + _install_opener(monkeypatch, _Opener(body=REGISTRATION)) + + assert connect_cli.main(["--token", TOKEN, "--control-url", CONTROL_URL]) == 0 + + out = capsys.readouterr().out + assert "hosted compute is not configured" in out + assert "ENGRAPHIS_CLOUD_COMPUTE_URL" in out + assert cloud_session.configured(require_compute=False) is True + + +def test_compute_url_is_taken_from_the_environment(monkeypatch): + monkeypatch.setenv("ENGRAPHIS_CLOUD_COMPUTE_URL", COMPUTE_URL) + _install_opener(monkeypatch, _Opener(body=REGISTRATION)) + + summary = device_connect.connect(TOKEN, control_url=CONTROL_URL) + + assert summary["compute_url"] == COMPUTE_URL + assert cloud_session.configured() is True + + +def test_control_url_defaults_to_the_shipped_manifest(monkeypatch): + from engraphis.commercial import manifest + + assert device_connect.default_control_url() == manifest()["control_plane"] + # And only the shipped control plane gets a guessed compute endpoint. + assert device_connect.default_compute_url(manifest()["control_plane"]) == \ + device_connect.DEFAULT_COMPUTE_URL + assert device_connect.default_compute_url(CONTROL_URL) == "" + + +def test_control_url_env_override_wins(monkeypatch): + monkeypatch.setenv("ENGRAPHIS_CLOUD_CONTROL_URL", CONTROL_URL) + assert device_connect.default_control_url() == CONTROL_URL + + +def test_an_unconfigured_control_plane_is_a_clear_error(monkeypatch): + monkeypatch.setattr(device_connect, "default_control_url", lambda: "") + + with pytest.raises(device_connect.DeviceConnectError) as caught: + device_connect.connect(TOKEN) + + assert "ENGRAPHIS_CLOUD_CONTROL_URL" in str(caught.value) + assert caught.value.status == 400 + + +def test_token_dash_reads_stdin(monkeypatch, capsys): + _install_opener(monkeypatch, _Opener(body=REGISTRATION)) + + class _Stdin: + @staticmethod + def isatty() -> bool: + return False + + @staticmethod + def readline() -> str: + return TOKEN + "\n" + + monkeypatch.setattr(connect_cli.sys, "stdin", _Stdin) + + assert connect_cli.main([ + "--token", "-", "--control-url", CONTROL_URL, "--compute-url", COMPUTE_URL, + ]) == 0 + assert TOKEN not in capsys.readouterr().out + + +def test_token_dash_on_a_terminal_explains_itself_instead_of_hanging(monkeypatch, capsys): + class _Tty: + @staticmethod + def isatty() -> bool: + return True + + monkeypatch.setattr(connect_cli.sys, "stdin", _Tty) + + assert connect_cli.main(["--token", "-", "--control-url", CONTROL_URL]) == 1 + assert "reads the token from stdin" in capsys.readouterr().err + + +def test_connect_is_reachable_as_the_documented_engraphis_verb(monkeypatch, capsys): + """The portal shows `engraphis connect --token ...`; that string has to run.""" + + from scripts import entry + + _install_opener(monkeypatch, _Opener(body=REGISTRATION)) + assert entry.COMMANDS["connect"] == "scripts.connect:main" + + assert entry.main([ + "connect", "--token", TOKEN, "--control-url", CONTROL_URL, + "--compute-url", COMPUTE_URL, + ]) == 0 + assert "Connected this device to Engraphis Cloud." in capsys.readouterr().out + + +def test_the_dispatcher_restores_argv_and_rejects_unknown_verbs(capsys): + from scripts import entry + + saved = list(entry.sys.argv) + assert entry.main(["definitely-not-a-command"]) == 2 + assert entry.sys.argv == saved + assert "unknown command" in capsys.readouterr().err + + +def test_every_dispatched_verb_resolves_to_a_real_callable(): + from importlib import import_module + + from scripts import entry + + for verb, target in entry.COMMANDS.items(): + module_name, _, attribute = target.partition(":") + assert callable(getattr(import_module(module_name), attribute)), verb From ca1e1189a34310aa68564d7b33e303694ce5bf64 Mon Sep 17 00:00:00 2001 From: Jaixii Date: Sun, 26 Jul 2026 14:12:25 -0400 Subject: [PATCH 36/82] Pre-flight session storage before redeeming the connect token `connect()` spent the single-use connect token on the POST and only then called `save_bootstrap()`. If the state directory had become unwritable, or `cloud_session.json` had been replaced by a symlink, a hard link or a directory, the write failed after the token was already consumed: the customer was left with a spent token and no session, and had to go back to the portal for a new one. Worse, `atomic_private_text` raises `UnsafeStateFile`, which is an `OSError` and not a `CloudSessionError`, so it escaped `connect()`'s handler entirely and surfaced as a raw traceback rather than actionable copy. `cloud_session.preflight_save()` now runs before the exchange. It lives beside `_session_path()`, `_refresh_lock()` and `_save()` because that module owns the paths and the atomic write it predicts; a private copy of those rules in `device_connect` would drift from the save it is meant to model. It reuses the existing primitives -- `private_file_stat` on the session leaf and on its refresh lock, plus the randomized sibling temp file `atomic_private_text` has to create -- and never opens, creates or replaces the session leaf, so an existing session survives a failed pre-flight untouched and a first connect is not left half written. `_refresh_lock()` picks up the extracted `_refresh_lock_path()` so the lock filename is not duplicated. `device_connect._preflight_session_storage()` translates the failure into a `DeviceConnectError` that names the path to fix and states that the token is still redeemable, and `connect()` reuses the returned path for the summary instead of rebuilding it from `_state_dir()`. Tests: 6 new, all asserting `opener.calls == []` -- the POST is never issued. Session leaf and refresh lock replaced by a directory, a genuinely hard-linked session, an uncreatable state directory (`ENGRAPHIS_STATE_DIR` under a regular file), a read-only mount, and a pre-flight that creates nothing and leaves no probe file behind. All six fail against the pre-fix code. Co-Authored-By: Claude Opus 5 --- CHANGELOG.md | 6 +- docs/AGENT_CONNECT.md | 6 ++ engraphis/cloud_session.py | 68 +++++++++++++++- engraphis/device_connect.py | 26 +++++- tests/test_device_connect.py | 149 +++++++++++++++++++++++++++++++++++ 5 files changed, 252 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 64b8b60..8ba3cbb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,7 +16,11 @@ All notable changes to Engraphis are documented here. Format loosely follows verifies `cloud_session.configured()` before reporting success. The token is sent in the request body and nowhere else — never printed, logged, or written to disk — and every refusal maps to fixed, actionable copy (an expired or already-used token is not confused - with a lapsed subscription). Also installed as `engraphis-connect`. + with a lapsed subscription). Session storage is pre-flighted before the exchange, so an + unwritable state directory or a `cloud_session.json` replaced by a link fails the command + *without* spending the single-use token — the customer fixes the path and retries with the + same token instead of returning to the portal for a new one. Also installed as + `engraphis-connect`. - An `engraphis` front-door command that dispatches to the existing `engraphis-` entry points, so the command the account portal displays is runnable as shown. - A stable per-installation identity at `~/.engraphis/client_identity.json` (random ULIDs, diff --git a/docs/AGENT_CONNECT.md b/docs/AGENT_CONNECT.md index 1e4d969..4ea833f 100644 --- a/docs/AGENT_CONNECT.md +++ b/docs/AGENT_CONNECT.md @@ -70,6 +70,12 @@ already redeemed, or never valid — with the same `401`, so the client reports possibilities and the fix is always the same: generate a new token in the account portal. A `402` means the subscription itself has lapsed; fix billing rather than the token. +Because the token is single-use, the client checks that it can actually write the session file +*before* redeeming it. If the state directory is not writable, or `cloud_session.json` has been +replaced by a symlink, a hard link, or a directory, the command fails immediately, names the path +to fix, and sends nothing — your token is untouched, so you can correct the path and rerun the +same command rather than issuing a new token. + The token is a credential. It is sent in the request body and nowhere else — it is never printed, never logged, and never written to disk. What *is* written is the rotating refresh credential the service returns, which is why the session file is owner-only. diff --git a/engraphis/cloud_session.py b/engraphis/cloud_session.py index b539afe..cbadc1a 100644 --- a/engraphis/cloud_session.py +++ b/engraphis/cloud_session.py @@ -9,6 +9,7 @@ import json import os import stat +import tempfile import threading import time import urllib.error @@ -80,6 +81,10 @@ def _session_path() -> Path: return base / "cloud_session.json" +def _refresh_lock_path() -> Path: + return _session_path().with_name(".cloud_session.refresh.lock") + + @contextmanager def _refresh_lock(): """Serialize spend-and-rotate of the single-use refresh credential. @@ -89,7 +94,7 @@ def _refresh_lock(): so every process coordinates on one stable filesystem object. """ with _REFRESH_THREAD_LOCK: - lock_path = _session_path().with_name(".cloud_session.refresh.lock") + lock_path = _refresh_lock_path() try: lock_path.parent.mkdir(parents=True, exist_ok=True) expected = private_file_stat(lock_path, allow_missing=True) @@ -212,6 +217,67 @@ def _save(value: dict) -> None: atomic_private_text(path, json.dumps(value, sort_keys=True, separators=(",", ":"))) +def preflight_save() -> Path: + """Verify the session file can be saved, without saving anything. Returns its path. + + :func:`save_bootstrap` runs *after* the control plane has answered, so a state + directory that lost its permissions, or a ``cloud_session.json`` that is a symlink or + a hard link, was only discovered once a single-use connect token had already been + consumed: the customer was left with a spent token, no session, and a trip back to + the portal for a new one. Any caller about to spend a one-shot credential must run + this first, so a storage fault costs nothing. + + The checks are the ones the write path itself applies -- :func:`private_file_stat` on + the session leaf and on its refresh lock, plus the randomized sibling temp file + :func:`atomic_private_text` has to create -- so the preflight cannot drift from what + the real save will accept. It deliberately never opens, creates or replaces the + session leaf: an existing session survives a failed preflight untouched, and a first + connect is not turned into a half-written file. + """ + + path = _session_path() + try: + path.parent.mkdir(parents=True, exist_ok=True) + except OSError as exc: + raise CloudSessionError( + "The Engraphis state directory %s could not be created." % path.parent, + status=409, + ) from exc + for candidate in (path, _refresh_lock_path()): + try: + private_file_stat(candidate, allow_missing=True) + except UnsafeStateFile as exc: + raise CloudSessionError( + "%s is not a plain private file -- a symlink, hard link or directory is " + "in its place. Remove it." % candidate, + status=409, + ) from exc + except OSError as exc: + raise CloudSessionError( + "%s could not be inspected; check its permissions." % candidate, + status=409, + ) from exc + # Probe the directory the way ``atomic_private_text`` will, rather than touching + # ``cloud_session.json``: a read-only mount or a lost ACL fails here, while a valid + # existing session is never created, truncated or replaced. + try: + descriptor, probe = tempfile.mkstemp( + prefix=".%s.preflight." % path.name, dir=str(path.parent) + ) + except OSError as exc: + raise CloudSessionError( + "The Engraphis state directory %s is not writable, so the cloud session " + "cannot be saved there." % path.parent, + status=409, + ) from exc + os.close(descriptor) + try: + os.unlink(probe) + except OSError: # pragma: no cover - the probe was just created in this directory + pass + return path + + #: Plans that carry no paid cloud access, used only to default an absent activity flag. _UNPAID_PLANS = ("free", "local") #: Bounds on the entitlement fields before they are written into the session record. The diff --git a/engraphis/device_connect.py b/engraphis/device_connect.py index 90a33c3..6856ee2 100644 --- a/engraphis/device_connect.py +++ b/engraphis/device_connect.py @@ -460,6 +460,26 @@ def summarize(response: dict) -> dict: return summary +def _preflight_session_storage() -> Path: + """Refuse a connect *before* the token is spent when the session cannot be saved. + + The exchange is the point of no return: the control plane consumes the single-use + connect token as it answers, so any storage fault discovered afterwards costs the + customer a fresh token from the portal. Delegated to :mod:`engraphis.cloud_session` + because that module owns the paths, the lock and the atomic write this is checking -- + a private copy of those rules here would drift from the save it is meant to predict. + """ + + try: + return cloud_session.preflight_save() + except cloud_session.CloudSessionError as exc: + raise DeviceConnectError( + "%s Your connect token has not been used, so you can fix this and run " + "`engraphis connect --token ...` again with the same token." % exc, + status=getattr(exc, "status", 409), + ) from exc + + def connect(token: object, *, control_url: Optional[str] = None, compute_url: Optional[str] = None, workspace_id: Optional[str] = None, installation_label: Optional[str] = None, device_name: Optional[str] = None, @@ -493,6 +513,10 @@ def connect(token: object, *, control_url: Optional[str] = None, ) from exc installation_client_id, device_client_id = client_identity() + # Last check before the point of no return. ``client_identity`` may have written its + # file minutes or months ago, so a writable state directory then is no evidence of one + # now; prove the session can land *before* the POST spends the token, not after. + session_path = _preflight_session_storage() response = post_connect( resolved_control, normalized, @@ -521,5 +545,5 @@ def connect(token: object, *, control_url: Optional[str] = None, summary = summarize(response) summary["control_url"] = resolved_control summary["compute_url"] = resolved_compute - summary["session_path"] = str(_state_dir() / "cloud_session.json") + summary["session_path"] = str(session_path) return summary diff --git a/tests/test_device_connect.py b/tests/test_device_connect.py index bf775e3..16d8a09 100644 --- a/tests/test_device_connect.py +++ b/tests/test_device_connect.py @@ -8,6 +8,7 @@ from __future__ import annotations import json +import os import urllib.error import urllib.request from io import BytesIO @@ -345,6 +346,154 @@ def open(self, request, timeout): device_connect.connect(TOKEN, control_url=CONTROL_URL, compute_url=COMPUTE_URL) +# ------------------------------------------------------ pre-flight on session storage +# +# The POST is the point of no return: the control plane consumes the single-use connect +# token as it answers. ``save_bootstrap`` runs afterwards, so before the pre-flight a +# state directory that had lost its permissions -- or a ``cloud_session.json`` replaced +# by a link -- spent the customer's token and then failed, leaving them with nothing to +# retry with. Every test here asserts the same thing: no request was put on the wire. + + +def _probe_files(root: Path): + """Temporary files the writability probe must never leave behind.""" + + return sorted(path.name for path in Path(root).iterdir() if ".preflight." in path.name) + + +def test_an_unsafe_session_path_fails_before_the_token_is_spent(monkeypatch, tmp_path): + """The reported regression: a session leaf that is not a plain private file. + + A directory stands in for the symlink/hard-link family because it trips exactly the + same ``private_file_stat`` rejection on every platform, including a Windows runner + without the privilege to create a symlink at all. + """ + + opener = _Opener(body=REGISTRATION) + _install_opener(monkeypatch, opener) + # The identity file already exists, which is precisely why its earlier success is no + # evidence that the directory is still writable now. + device_connect.client_identity() + session_path = tmp_path / "cloud_session.json" + session_path.mkdir() + + with pytest.raises(device_connect.DeviceConnectError) as caught: + device_connect.connect(TOKEN, control_url=CONTROL_URL, compute_url=COMPUTE_URL) + + # The one assertion that matters: the token was never presented, so it is still live. + assert opener.calls == [] + assert caught.value.status == 409 + # The customer has to be told which path to fix, by name. + assert str(session_path) in str(caught.value) + assert "has not been used" in str(caught.value) + assert session_path.is_dir() + assert _probe_files(tmp_path) == [] + + +def test_an_unsafe_refresh_lock_also_fails_before_the_token_is_spent(monkeypatch, tmp_path): + """``save_bootstrap`` takes the refresh lock first, so an unusable lock spends it too.""" + + opener = _Opener(body=REGISTRATION) + _install_opener(monkeypatch, opener) + lock_path = tmp_path / ".cloud_session.refresh.lock" + lock_path.mkdir() + + with pytest.raises(device_connect.DeviceConnectError) as caught: + device_connect.connect(TOKEN, control_url=CONTROL_URL, compute_url=COMPUTE_URL) + + assert opener.calls == [] + assert str(lock_path) in str(caught.value) + assert not (tmp_path / "cloud_session.json").exists() + + +def test_a_hard_linked_session_is_refused_before_the_token_is_spent(monkeypatch, tmp_path): + """A second pathname to the session would keep resolving to the rotated credential.""" + + opener = _Opener(body=REGISTRATION) + _install_opener(monkeypatch, opener) + session_path = tmp_path / "cloud_session.json" + session_path.write_text("{}", encoding="utf-8") + try: + os.link(str(session_path), str(tmp_path / "session_alias.json")) + except (OSError, AttributeError, NotImplementedError) as exc: # pragma: no cover + pytest.skip("hard links are unavailable on this filesystem: %s" % exc) + + with pytest.raises(device_connect.DeviceConnectError) as caught: + device_connect.connect(TOKEN, control_url=CONTROL_URL, compute_url=COMPUTE_URL) + + assert opener.calls == [] + assert str(session_path) in str(caught.value) + # Inspection only: a pre-existing file is never opened, truncated or replaced. + assert session_path.read_text(encoding="utf-8") == "{}" + + +def test_an_uncreatable_state_directory_fails_before_the_token_is_spent( + monkeypatch, tmp_path +): + """``ENGRAPHIS_STATE_DIR`` under a regular file: the directory can never be made.""" + + blocker = tmp_path / "blocker" + blocker.write_text("not a directory", encoding="utf-8") + monkeypatch.setenv("ENGRAPHIS_STATE_DIR", str(blocker / "state")) + opener = _Opener(body=REGISTRATION) + _install_opener(monkeypatch, opener) + + with pytest.raises(device_connect.DeviceConnectError) as caught: + device_connect.connect(TOKEN, control_url=CONTROL_URL, compute_url=COMPUTE_URL) + + assert opener.calls == [] + assert str(blocker / "state") in str(caught.value) + assert blocker.read_text(encoding="utf-8") == "not a directory" + + +def test_an_unwritable_state_directory_fails_before_the_token_is_spent( + monkeypatch, tmp_path +): + """A read-only mount, which is the failure the report describes. + + Simulated at the probe rather than with ``chmod``: POSIX modes are advisory for root + and Windows has no equivalent, so a mode-based test would silently stop failing. The + probe is the only thing standing between the caller and ``atomic_private_text``. + """ + + opener = _Opener(body=REGISTRATION) + _install_opener(monkeypatch, opener) + device_connect.client_identity() + + def _read_only(*args, **kwargs): + raise PermissionError(13, "read-only file system") + + monkeypatch.setattr(cloud_session.tempfile, "mkstemp", _read_only) + + with pytest.raises(device_connect.DeviceConnectError) as caught: + device_connect.connect(TOKEN, control_url=CONTROL_URL, compute_url=COMPUTE_URL) + + assert opener.calls == [] + assert caught.value.status == 409 + assert str(tmp_path) in str(caught.value) + assert "not writable" in str(caught.value) + assert not (tmp_path / "cloud_session.json").exists() + + +def test_the_preflight_creates_nothing_and_leaves_nothing_behind(monkeypatch, tmp_path): + """A pre-flight that wrote the session would defeat the "nothing on failure" rule.""" + + session_path = cloud_session.preflight_save() + + assert session_path == tmp_path / "cloud_session.json" + assert not session_path.exists() + assert _probe_files(tmp_path) == [] + + # Idempotent, and equally inert once a real session exists. + _install_opener(monkeypatch, _Opener(body=REGISTRATION)) + device_connect.connect(TOKEN, control_url=CONTROL_URL, compute_url=COMPUTE_URL) + saved = session_path.read_bytes() + + assert cloud_session.preflight_save() == session_path + assert session_path.read_bytes() == saved + assert _probe_files(tmp_path) == [] + + # ------------------------------------------------------------- pre-flight token hygiene From 972cc7a83780b826d4bf7b872dfc774756f9374b Mon Sep 17 00:00:00 2001 From: Jaixii Date: Sun, 26 Jul 2026 17:42:20 -0400 Subject: [PATCH 37/82] Address connect review: manifest compute endpoint, timeout and save races Three unresolved review threads on #75, plus one semantic conflict the merge with main could not see. `default_compute_url` now reads the manifest's `compute_plane` and falls back to `DEFAULT_COMPUTE_URL`. The review asked for the constant to be replaced outright, but the shipped `engraphis-commercial/v2` manifest declares only `control_plane`: reading the absent key alone resolves `""`, and `cloud_session.configured()` then rejects the session a production connect just saved, leaving a paying customer "connected" but unusable. Preferring the key removes the drift point the review named -- a manifest-only endpoint change needs no code change -- while the constant stays as the fallback that keeps today's manifest working. `_validated_timeout` refuses a non-finite or non-positive timeout. `argparse`'s `type=float` accepts `nan` and `inf`, which reach the pinned opener's deadline arithmetic and raise `ValueError`/`OverflowError` from inside `urllib`, neither caught by `post_connect`. That broke this module's contract that every failure is a `DeviceConnectError`, so `engraphis connect --timeout nan` printed a traceback instead of the command's error and exit code. Checked at the top of `connect()` so a bad flag is reported as a bad flag rather than masked by whatever the identity or storage pre-flight hits first, and again in `post_connect()` because it is public and owns the socket call. `connect()` now also translates `OSError` from `save_bootstrap`. The pre-flight added in aae7d93 closes the common case, but the state directory can still change between the pre-flight and the write, and `UnsafeStateFile` is an `OSError`, not a `CloudSessionError`, so it escaped as a traceback at the worst moment. The token is spent by then, so the copy says so instead of promising a retry with the same one. The `REGISTRATION` fixture no longer claims the cloud grants `export`. #76 removed that key from the plan->feature tables in both repos because the signed compliance export was never implemented; a fixture asserting the control plane returns it would re-establish exactly the drift that removal cleaned up. Co-Authored-By: Claude Opus 5 --- engraphis/device_connect.py | 68 ++++++++++++++++++++++++-- tests/test_device_connect.py | 93 +++++++++++++++++++++++++++++++++++- 2 files changed, 157 insertions(+), 4 deletions(-) diff --git a/engraphis/device_connect.py b/engraphis/device_connect.py index 6856ee2..d0698bb 100644 --- a/engraphis/device_connect.py +++ b/engraphis/device_connect.py @@ -26,6 +26,7 @@ from __future__ import annotations import json +import math import os import platform import re @@ -85,6 +86,12 @@ #: shipped control plane would otherwise leave a customer "connected" but not configured. #: Applied *only* when the control plane is the shipped one: a self-hosted or staging #: control URL gets no guess, and the caller is told to supply the compute URL. +#: +#: This is the *fallback*, not the authority: ``default_compute_url`` prefers the +#: manifest's ``compute_plane`` whenever it carries one. The shipped +#: ``engraphis-commercial/v2`` manifest does not declare that key, so without a constant +#: here a production connect would resolve an empty compute URL and save an unconfigured +#: session. DEFAULT_COMPUTE_URL = "https://compute.engraphis.com" @@ -241,23 +248,61 @@ def default_control_url() -> str: def default_compute_url(control_url: str) -> str: - """Resolve the compute plane, guessing only for the shipped control plane.""" + """Resolve the compute plane, guessing only for the shipped control plane. + + The manifest is the authority for shipped endpoint metadata, so a ``compute_plane`` + key wins if one is ever published -- a manifest-only endpoint change then needs no + code change here. The current ``engraphis-commercial/v2`` manifest declares only + ``control_plane``, so :data:`DEFAULT_COMPUTE_URL` is what production actually + resolves; reading the absent key alone would yield ``""`` and save a session + ``cloud_session.configured()`` rejects. + """ configured = os.environ.get("ENGRAPHIS_CLOUD_COMPUTE_URL", "").strip() if configured: return configured shipped = "" + shipped_compute = "" try: from engraphis.commercial import manifest - shipped = str(manifest().get("control_plane") or "").strip() + data = manifest() + shipped = str(data.get("control_plane") or "").strip() + shipped_compute = str(data.get("compute_plane") or "").strip() except Exception: # pragma: no cover - manifest ships with the package return "" if shipped and control_url.rstrip("/") == shipped.rstrip("/"): - return DEFAULT_COMPUTE_URL + return shipped_compute or DEFAULT_COMPUTE_URL return "" +def _validated_timeout(value: object) -> float: + """Reject a timeout the socket layer cannot use, before any request is started. + + ``float("nan")`` and ``float("inf")`` are values ``argparse``'s ``type=float`` + accepts happily, but they reach the pinned opener's deadline arithmetic and raise + ``ValueError``/``OverflowError`` from inside ``urllib`` -- neither of which + :func:`post_connect` catches. That breaks this module's contract that every failure + is a :class:`DeviceConnectError` with actionable copy, so ``--timeout nan`` printed a + traceback instead of an error and an exit code. Non-positive values are refused for + the same reason: a ``0`` or negative socket timeout is not a shorter wait, it is a + different (non-blocking) mode the caller did not ask for. + """ + + try: + timeout = float(value) + except (TypeError, ValueError) as exc: + raise DeviceConnectError( + "The connect timeout must be a number of seconds.", status=400 + ) from exc + if not math.isfinite(timeout) or timeout <= 0: + raise DeviceConnectError( + "The connect timeout must be a positive, finite number of seconds.", + status=400, + ) + return timeout + + def _validated_control_url(value: str) -> str: if not str(value or "").strip(): raise DeviceConnectError( @@ -362,6 +407,7 @@ def post_connect(control_url: str, token: str, *, installation_client_id: str, deliberately no ``organization_id``: the token carries the organization. """ + timeout = _validated_timeout(timeout) body = { "connect_token": token, "installation_client_id": installation_client_id, @@ -491,6 +537,10 @@ def connect(token: object, *, control_url: Optional[str] = None, never containing the token. Nothing is written unless the exchange succeeded. """ + # Argument checks first: a bad ``--timeout`` must be reported as a bad timeout, not + # masked by whatever the identity or storage pre-flight happens to hit on the way to + # the same rejection inside ``post_connect``. + timeout = _validated_timeout(timeout) normalized = normalize_connect_token(token) resolved_control = _validated_control_url( control_url if control_url is not None else default_control_url() @@ -541,6 +591,18 @@ def connect(token: object, *, control_url: Optional[str] = None, ) except cloud_session.CloudSessionError as exc: raise DeviceConnectError(str(exc), status=getattr(exc, "status", 503)) from exc + except OSError as exc: + # The pre-flight cleared this exact path moments ago, so arriving here means the + # state directory changed underneath the exchange. ``UnsafeStateFile`` is an + # ``OSError`` and not a ``CloudSessionError``, so without this clause it escapes + # as a raw traceback at the worst possible moment -- the token is already spent, + # and the customer needs to be told that plainly rather than shown a stack. + raise DeviceConnectError( + "Engraphis Cloud accepted the token, but the session could not be written to " + "%s. Fix that path, then connect again with a new token from your account " + "portal -- this one has been used." % session_path, + status=409, + ) from exc summary = summarize(response) summary["control_url"] = resolved_control diff --git a/tests/test_device_connect.py b/tests/test_device_connect.py index 16d8a09..2367fa5 100644 --- a/tests/test_device_connect.py +++ b/tests/test_device_connect.py @@ -17,6 +17,7 @@ import pytest from engraphis import cloud_session, device_connect +from engraphis.private_state import UnsafeStateFile from scripts import connect as connect_cli CONTROL_URL = "https://control.example.test" @@ -40,7 +41,10 @@ "entitlement_version": 7, "plan": "team", "cloud_access_active": True, - "cloud_features": ["analytics", "automation", "export", "sync", "team"], + # No ``export``: the signed compliance export was never implemented and is no longer + # in either repo's plan->feature table, so a fixture claiming the cloud grants it + # would re-establish exactly the drift that removal cleaned up. + "cloud_features": ["analytics", "automation", "sync", "team"], } @@ -658,6 +662,93 @@ def test_control_url_defaults_to_the_shipped_manifest(monkeypatch): assert device_connect.default_compute_url(CONTROL_URL) == "" +def test_the_manifest_outranks_the_compute_constant(monkeypatch): + """A published ``compute_plane`` wins, so the manifest stays the endpoint authority. + + The constant is only the fallback for today's manifest, which declares no + ``compute_plane``; reading the key alone would resolve ``""`` and save a session + ``configured()`` rejects. + """ + + from engraphis.commercial import manifest + + shipped = manifest()["control_plane"] + monkeypatch.setattr( + "engraphis.commercial.manifest", + lambda: {"control_plane": shipped, "compute_plane": COMPUTE_URL}, + ) + + assert device_connect.default_compute_url(shipped) == COMPUTE_URL + # A self-hosted control plane still gets no guess from either source. + assert device_connect.default_compute_url(CONTROL_URL) == "" + + +@pytest.mark.parametrize("bad", ["nan", "inf", "-inf", "0", "-5"]) +def test_a_non_finite_timeout_is_refused_before_any_request(monkeypatch, bad): + """``argparse``'s ``type=float`` accepts ``nan``/``inf``; the socket layer does not. + + Those reach ``urllib``'s deadline arithmetic and raise ``ValueError``/``OverflowError`` + that ``post_connect`` does not catch, so the CLI printed a traceback instead of its + structured error. Nothing may be sent, either. + """ + + class _Exploding: + @staticmethod + def open(request, timeout=None): # pragma: no cover - must never run + raise AssertionError("a request was started with an unusable timeout") + + _install_opener(monkeypatch, _Exploding()) + + with pytest.raises(device_connect.DeviceConnectError) as caught: + device_connect.connect(TOKEN, control_url=CONTROL_URL, timeout=float(bad)) + + assert caught.value.status == 400 + assert "timeout" in str(caught.value) + + +def test_the_cli_reports_a_bad_timeout_instead_of_a_traceback(monkeypatch, capsys): + class _Exploding: + @staticmethod + def open(request, timeout=None): # pragma: no cover - must never run + raise AssertionError("a request was started with an unusable timeout") + + _install_opener(monkeypatch, _Exploding()) + + code = connect_cli.main( + ["--token", TOKEN, "--control-url", CONTROL_URL, "--timeout", "nan"] + ) + + assert code == 1 + err = capsys.readouterr().err + assert "timeout" in err + assert "Traceback" not in err + + +def test_a_storage_fault_racing_the_save_is_not_a_traceback(monkeypatch): + """``UnsafeStateFile`` is an ``OSError``, not a ``CloudSessionError``. + + The pre-flight closes the common case, but the state directory can still change + between the pre-flight and the write. The token is spent by then, so the customer + must be told that plainly rather than shown a stack trace. + """ + + _install_opener(monkeypatch, _Opener(body=REGISTRATION)) + + def _boom(*args, **kwargs): + raise UnsafeStateFile("cloud_session.json is not a plain private file") + + monkeypatch.setattr(cloud_session, "save_bootstrap", _boom) + + with pytest.raises(device_connect.DeviceConnectError) as caught: + device_connect.connect(TOKEN, control_url=CONTROL_URL) + + message = str(caught.value) + assert caught.value.status == 409 + # The token is gone; the copy must not promise it can be reused. + assert "has been used" in message + assert TOKEN not in message + + def test_control_url_env_override_wins(monkeypatch): monkeypatch.setenv("ENGRAPHIS_CLOUD_CONTROL_URL", CONTROL_URL) assert device_connect.default_control_url() == CONTROL_URL From 3e974c8e4638d5b45de9de4895001a999e2d7cc9 Mon Sep 17 00:00:00 2001 From: Jaixii Date: Sun, 26 Jul 2026 18:24:58 -0400 Subject: [PATCH 38/82] Report post-redemption connect failures instead of raising tracebacks Both paths fail *after* the control plane has consumed the single-use connect token, so a raw traceback left the customer unable to tell whether to retry or fetch a new token from the portal. `http.client.IncompleteRead` (a truncated chunked reply) subclasses `HTTPException`/`ValueError` -- neither `OSError` nor `URLError` -- so it escaped both of `post_connect`'s handlers. A third clause is added *after* the transport clause, because `RemoteDisconnected` is both a `ConnectionResetError` and a `BadStatusLine` and means the peer never answered: that one keeps the retryable 503 copy, and a test pins the ordering. `save_bootstrap` re-runs `validate_cloud_base_url` on both endpoints, which resolves the host. A resolver that dies mid-connect raises `CloudUrlUnresolved` and an endpoint that starts resolving to a rejected address raises a bare `ValueError`; both are `ValueError`, so neither the `CloudSessionError` nor the `OSError` handler in `connect()` covered them. Translated in `connect()` rather than by dropping the re-validation, which is still wanted for `save_bootstrap`'s other callers. Co-Authored-By: Claude Opus 5 --- CHANGELOG.md | 6 +- engraphis/device_connect.py | 40 +++++++++++ tests/test_device_connect.py | 128 +++++++++++++++++++++++++++++++++++ 3 files changed, 173 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8ba3cbb..c2de406 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,7 +19,11 @@ All notable changes to Engraphis are documented here. Format loosely follows with a lapsed subscription). Session storage is pre-flighted before the exchange, so an unwritable state directory or a `cloud_session.json` replaced by a link fails the command *without* spending the single-use token — the customer fixes the path and retries with the - same token instead of returning to the portal for a new one. Also installed as + same token instead of returning to the portal for a new one. Faults that can only happen + *after* the exchange — a reply truncated mid-body (`http.client.IncompleteRead`), or an + endpoint that stops resolving before the session is written (`CloudUrlUnresolved`) — are + reported as errors that say the token was already used, rather than escaping as tracebacks + that leave the customer unable to tell whether to retry. Also installed as `engraphis-connect`. - An `engraphis` front-door command that dispatches to the existing `engraphis-` entry points, so the command the account portal displays is runnable as shown. diff --git a/engraphis/device_connect.py b/engraphis/device_connect.py index d0698bb..cf50c73 100644 --- a/engraphis/device_connect.py +++ b/engraphis/device_connect.py @@ -25,6 +25,7 @@ """ from __future__ import annotations +import http.client import json import math import os @@ -65,6 +66,17 @@ #: The control plane answers with a small fixed record; anything larger is not ours. _MAX_RESPONSE_BYTES = 64 * 1024 +#: Copy for a reply that began but never completed. Every other failure in this module can +#: promise the connect token is untouched; this one cannot, because the request reached a +#: control plane that started to answer, and a 200 consumes the token as it is written. +#: Saying "try again" here would be a lie that costs the customer a second failed attempt, +#: so the copy sends them to the one place that shows whether the device landed. +_TRUNCATED_REPLY = ( + "Engraphis Cloud started answering this connect request but the connection closed " + "before the reply was complete. Your connect token may already have been used: check " + "your account portal, and generate a new one if this device is not listed there." +) + #: The portal always mints tokens with this prefix. Checking it locally turns a #: mistyped or truncated paste into an instant, free error instead of a round trip that #: consumes rate budget and returns the same opaque 401 as a genuinely dead token. @@ -457,11 +469,25 @@ def post_connect(control_url: str, token: str, *, installation_client_id: str, raise _connect_http_error(status) except (urllib.error.URLError, TimeoutError, OSError) as exc: # ``exc`` may quote an internal host or a proxy URL; never reflect it. + # + # Deliberately ahead of the ``HTTPException`` clause: ``RemoteDisconnected`` is + # both a ``ConnectionResetError`` and a ``BadStatusLine``, and it means the peer + # closed without answering at all. Nothing was consumed, so "try again" is the + # correct advice for it and it must not inherit the token-may-be-spent copy. raise DeviceConnectError( "Engraphis Cloud is temporarily unreachable. Check your network and try " "again.", status=503, ) from exc + except http.client.HTTPException as exc: + # A truncated chunked body makes ``HTTPResponse.read`` raise ``IncompleteRead``, + # which subclasses ``HTTPException``/``ValueError`` and is neither an ``OSError`` + # nor a ``URLError`` -- so it escaped both clauses above as a raw traceback. That + # happened at the worst moment: the control plane had already answered, so the + # single-use token was very likely spent, and the customer saw a stack trace + # instead of being told to check the portal. ``LineTooLong``/``BadStatusLine`` from + # reading the status line and headers land here for the same reason. + raise DeviceConnectError(_TRUNCATED_REPLY, status=502) from exc if len(raw) > _MAX_RESPONSE_BYTES: raise DeviceConnectError( "Engraphis Cloud returned an oversized connect response.", status=502 @@ -603,6 +629,20 @@ def connect(token: object, *, control_url: Optional[str] = None, "portal -- this one has been used." % session_path, status=409, ) from exc + except ValueError as exc: + # ``save_bootstrap`` re-runs ``validate_cloud_base_url`` on both endpoints, and + # that helper *resolves* the host. A resolver that dies between the pre-POST check + # and this line raises ``CloudUrlUnresolved``; an endpoint that starts resolving to + # a rejected address raises a bare ``ValueError``. Both are ``ValueError``, so + # neither the ``CloudSessionError`` nor the ``OSError`` clause above covered them + # and they escaped as a traceback -- again after the token was already spent. + raise DeviceConnectError( + "Engraphis Cloud accepted the token, but its endpoints could not be verified " + "in time to save the session, so nothing was written. Check your network, " + "then connect again with a new token from your account portal -- this one " + "has been used.", + status=409, + ) from exc summary = summarize(response) summary["control_url"] = resolved_control diff --git a/tests/test_device_connect.py b/tests/test_device_connect.py index 2367fa5..2d636e9 100644 --- a/tests/test_device_connect.py +++ b/tests/test_device_connect.py @@ -7,6 +7,7 @@ """ from __future__ import annotations +import http.client import json import os import urllib.error @@ -17,6 +18,7 @@ import pytest from engraphis import cloud_session, device_connect +from engraphis.hosted_client import CloudUrlUnresolved from engraphis.private_state import UnsafeStateFile from scripts import connect as connect_cli @@ -350,6 +352,132 @@ def open(self, request, timeout): device_connect.connect(TOKEN, control_url=CONTROL_URL, compute_url=COMPUTE_URL) +# ------------------------------------------- failures *after* the token has been spent +# +# Once ``opener.open`` has returned, the control plane has answered and the single-use +# connect token is gone. Every fault from that point on has to arrive as a +# ``DeviceConnectError`` that says so -- a traceback here is the worst possible outcome, +# because the customer cannot tell whether to retry or fetch a new token. + + +class _TruncatedBody: + """A 200 whose body stops mid-stream, the way a dropped chunked reply does.""" + + def __enter__(self): + return self + + def __exit__(self, *exc) -> bool: + return False + + def read(self, size: int = -1) -> bytes: + # What ``HTTPResponse._read_chunked`` raises for a truncated body. It subclasses + # ``HTTPException``/``ValueError`` -- neither ``OSError`` nor ``URLError``. + raise http.client.IncompleteRead(b'{"organization_id":"org_al') + + +@pytest.mark.parametrize("failure", [ + http.client.IncompleteRead(b'{"organization_id":"org_al'), + http.client.LineTooLong("header line"), + http.client.BadStatusLine("garbage"), +]) +def test_a_truncated_reply_reports_the_token_state_not_a_traceback( + monkeypatch, tmp_path, failure +): + """``IncompleteRead`` is an ``HTTPException``, so the transport clause never saw it.""" + + class _Broken(_Opener): + def open(self, request, timeout): + self.calls.append({"body": request.data}) + if isinstance(failure, http.client.IncompleteRead): + return _TruncatedBody() + raise failure + + opener = _Broken() + _install_opener(monkeypatch, opener) + + with pytest.raises(device_connect.DeviceConnectError) as caught: + device_connect.connect(TOKEN, control_url=CONTROL_URL, compute_url=COMPUTE_URL) + + message = str(caught.value) + assert caught.value.status == 502 + # The customer must be told the token may be gone rather than told to just retry. + assert "may already have been used" in message + assert TOKEN not in message + assert not (tmp_path / "cloud_session.json").exists() + + +def test_a_connection_reset_before_any_reply_still_says_retry(monkeypatch): + """``RemoteDisconnected`` is *both* an ``OSError`` and an ``HTTPException``. + + Nothing was read, so the token is untouched and "try again" remains the right copy; + it must not be swept into the token-may-be-spent message by the new clause. + """ + + _install_opener( + monkeypatch, _Opener(error=http.client.RemoteDisconnected("closed early")) + ) + + with pytest.raises(device_connect.DeviceConnectError) as caught: + device_connect.connect(TOKEN, control_url=CONTROL_URL, compute_url=COMPUTE_URL) + + assert caught.value.status == 503 + assert "temporarily unreachable" in str(caught.value) + + +@pytest.mark.parametrize("failure", [ + CloudUrlUnresolved("cloud service URL could not be resolved"), + ValueError("cloud service URL must not target private/reserved IP ranges"), +]) +def test_endpoint_validation_failing_after_redemption_is_not_a_traceback( + monkeypatch, tmp_path, failure +): + """``save_bootstrap`` re-resolves both endpoints *after* the POST spent the token. + + ``CloudUrlUnresolved`` is a ``ValueError``, so neither the ``CloudSessionError`` nor + the ``OSError`` handler in ``connect()`` covers it: a resolver that dies mid-connect, + or a host that starts resolving to a rejected address, escaped as a raw traceback. + """ + + opener = _Opener(body=REGISTRATION) + _install_opener(monkeypatch, opener) + + def _rejects(value): + raise failure + + # Only the save path: the pre-POST checks in ``connect()`` already passed. + monkeypatch.setattr(cloud_session, "validate_cloud_base_url", _rejects) + + with pytest.raises(device_connect.DeviceConnectError) as caught: + device_connect.connect(TOKEN, control_url=CONTROL_URL, compute_url=COMPUTE_URL) + + message = str(caught.value) + assert caught.value.status == 409 + assert opener.calls, "the token was spent; the copy has to admit it" + assert "has been used" in message + assert TOKEN not in message + assert not (tmp_path / "cloud_session.json").exists() + + +def test_the_cli_reports_a_post_redemption_fault_instead_of_a_traceback( + monkeypatch, capsys +): + _install_opener(monkeypatch, _Opener(body=REGISTRATION)) + + def _rejects(value): + raise CloudUrlUnresolved("cloud service URL could not be resolved") + + monkeypatch.setattr(cloud_session, "validate_cloud_base_url", _rejects) + + code = connect_cli.main([ + "--token", TOKEN, "--control-url", CONTROL_URL, "--compute-url", COMPUTE_URL, + ]) + + err = capsys.readouterr().err + assert code == 1 + assert "Traceback" not in err + assert "has been used" in err + + # ------------------------------------------------------ pre-flight on session storage # # The POST is the point of no return: the control plane consumes the single-use connect From 19e89e963e13ac05630817f7071ea24491fba285 Mon Sep 17 00:00:00 2001 From: Claude Code Date: Sun, 26 Jul 2026 23:02:56 -0400 Subject: [PATCH 39/82] Catch IncompleteRead when draining an error body, cap the timeout, and stop advising a retry after a spent token Three review findings on `engraphis/device_connect.py`, each reproduced as a failing test first. 1. The `HTTPError` drain was guarded with `except (OSError, ValueError)`. `http.client.IncompleteRead.__mro__` is `(IncompleteRead, HTTPException, Exception, BaseException, object)` -- it is neither an `OSError` nor a `ValueError`, so a truncated chunked error body escaped the guard. Because the drain runs *inside* an `except` block, the sibling `except http.client.HTTPException` clause could not catch it either, and the customer got a raw traceback instead of the status-specific copy. The guard now names `HTTPException`. The comments at both call sites asserted the false premise that `IncompleteRead` "subclasses HTTPException/ValueError"; both are corrected, and a new test pins the real MRO so the claim cannot drift back. 2. `_validated_timeout` accepted any finite positive float, but `socket.settimeout` converts it to an absolute deadline: `1e9` and above raise `OverflowError` ("timeout doesn't fit into C timeval" / "timestamp out of range for platform time_t") from inside `urllib`, which `post_connect` does not catch -- so `--timeout 10000000000` printed a traceback. Added a 3600s ceiling, asserted against a real socket so the constant cannot drift into the overflowing range. 3. A parsed 200 with no `refresh_credential` told the customer to "Try again." The 200 already consumed the single-use token, so retrying deterministically returns 401 and still saves nothing. The copy now says the token has been used and a new one is needed from the portal, matching the truncated-reply path. Co-Authored-By: Claude Opus 5 --- engraphis/device_connect.py | 52 ++++++++++--- tests/test_device_connect.py | 147 +++++++++++++++++++++++++++++++++-- 2 files changed, 184 insertions(+), 15 deletions(-) diff --git a/engraphis/device_connect.py b/engraphis/device_connect.py index cf50c73..bbcc761 100644 --- a/engraphis/device_connect.py +++ b/engraphis/device_connect.py @@ -63,6 +63,14 @@ #: human's prompt, once, and a spurious timeout costs the customer a fresh token. DEFAULT_TIMEOUT_SECONDS = 15.0 +#: Upper bound on ``--timeout``. Not a policy number -- a platform one. ``socket`` +#: converts a timeout into an absolute deadline, so a large but *finite* value raises +#: ``OverflowError`` ("timeout doesn't fit into C timeval", "timestamp out of range for +#: platform time_t") from inside ``urllib``: ``1e9`` already overflows on CPython 3.12. +#: One hour is orders of magnitude more than a single interactive POST can need and orders +#: of magnitude below the first value any supported platform rejects. +_MAX_TIMEOUT_SECONDS = 3600.0 + #: The control plane answers with a small fixed record; anything larger is not ours. _MAX_RESPONSE_BYTES = 64 * 1024 @@ -299,6 +307,12 @@ def _validated_timeout(value: object) -> float: traceback instead of an error and an exit code. Non-positive values are refused for the same reason: a ``0`` or negative socket timeout is not a shorter wait, it is a different (non-blocking) mode the caller did not ask for. + + ``math.isfinite`` is necessary but *not sufficient*: ``socket.settimeout`` turns the + value into an absolute deadline, so a merely large finite number + (``--timeout 10000000000``, and in fact anything from about ``1e9`` up) raises + ``OverflowError`` from the same uncaught place. Hence the explicit + :data:`_MAX_TIMEOUT_SECONDS` ceiling rather than a finiteness check alone. """ try: @@ -312,6 +326,11 @@ def _validated_timeout(value: object) -> float: "The connect timeout must be a positive, finite number of seconds.", status=400, ) + if timeout > _MAX_TIMEOUT_SECONDS: + raise DeviceConnectError( + "The connect timeout must be at most %d seconds." % int(_MAX_TIMEOUT_SECONDS), + status=400, + ) return timeout @@ -454,17 +473,26 @@ def post_connect(control_url: str, token: str, *, installation_client_id: str, raw = response.read(_MAX_RESPONSE_BYTES + 1) except urllib.error.HTTPError as exc: status = exc.code - # Draining the error body can itself raise; a sibling ``except`` of this ``try`` - # would not cover it, so an unguarded read escapes as a raw traceback exactly - # when the cloud is flaky. Same shape as cloud_session._post_refresh. + # Draining the error body can itself raise, and this runs *inside* an ``except`` + # block, so the sibling ``except http.client.HTTPException`` clause below cannot + # cover it -- an unguarded read escapes as a raw traceback exactly when the cloud + # is flaky, replacing the status copy the customer needs. + # + # ``HTTPException`` has to be named explicitly: a truncated chunked error body + # raises ``http.client.IncompleteRead``, whose MRO is ``(IncompleteRead, + # HTTPException, Exception, BaseException, object)`` -- it is neither an ``OSError`` + # nor a ``ValueError``, so an ``(OSError, ValueError)`` guard let it straight + # through. ``tests/test_device_connect.py`` pins that MRO so the mistake cannot + # come back. Same shape as cloud_session._post_refresh. + _DRAIN_FAILURES = (OSError, ValueError, http.client.HTTPException) try: exc.read(_MAX_RESPONSE_BYTES + 1) - except (OSError, ValueError): + except _DRAIN_FAILURES: pass finally: try: exc.close() - except (OSError, ValueError): + except _DRAIN_FAILURES: pass raise _connect_http_error(status) except (urllib.error.URLError, TimeoutError, OSError) as exc: @@ -481,8 +509,8 @@ def post_connect(control_url: str, token: str, *, installation_client_id: str, ) from exc except http.client.HTTPException as exc: # A truncated chunked body makes ``HTTPResponse.read`` raise ``IncompleteRead``, - # which subclasses ``HTTPException``/``ValueError`` and is neither an ``OSError`` - # nor a ``URLError`` -- so it escaped both clauses above as a raw traceback. That + # whose only base is ``HTTPException``: it is neither an ``OSError``, a + # ``ValueError``, nor a ``URLError`` -- so it escaped both clauses above. That # happened at the worst moment: the control plane had already answered, so the # single-use token was very likely spent, and the customer saw a stack trace # instead of being told to check the portal. ``LineTooLong``/``BadStatusLine`` from @@ -606,9 +634,15 @@ def connect(token: object, *, control_url: Optional[str] = None, timeout=timeout, ) if not str(response.get("refresh_credential") or "").strip(): + # Reaching here means a 200 was parsed, and the control plane consumes the + # single-use connect token as it writes one. So "try again" would be actively + # wrong: re-running the same command deterministically returns 401 and still leaves + # no session. Point at the portal, the same way the truncated-reply copy does. raise DeviceConnectError( - "Engraphis Cloud accepted the token but returned no session credential. " - "Try again, and contact support if it repeats.", + "Engraphis Cloud accepted the token but returned no session credential, so " + "no session was saved. This connect token has now been used -- generate a new " + "one in your Engraphis account portal and try again, and contact support if " + "it repeats.", status=502, ) try: diff --git a/tests/test_device_connect.py b/tests/test_device_connect.py index 2d636e9..351b8cf 100644 --- a/tests/test_device_connect.py +++ b/tests/test_device_connect.py @@ -10,6 +10,7 @@ import http.client import json import os +import socket import urllib.error import urllib.request from io import BytesIO @@ -317,6 +318,77 @@ def test_http_error_body_is_drained_and_closed(monkeypatch): assert closed == [True] +def test_incomplete_read_is_not_an_oserror_or_a_valueerror(): + """Pins the premise the drain guard is built on, so a wrong comment cannot return. + + ``http.client.IncompleteRead.__mro__`` is + ``(IncompleteRead, HTTPException, Exception, BaseException, object)``. It is *only* an + ``HTTPException``; an earlier version of this module claimed it also subclassed + ``ValueError`` and guarded the drain with ``(OSError, ValueError)`` on that basis. + """ + + assert not issubclass(http.client.IncompleteRead, OSError) + assert not issubclass(http.client.IncompleteRead, ValueError) + assert issubclass(http.client.IncompleteRead, http.client.HTTPException) + + +@pytest.mark.parametrize("failure", [ + http.client.IncompleteRead(b'{"detail":"pri'), + http.client.LineTooLong("chunk size"), + ConnectionResetError("peer went away mid-drain"), +]) +def test_a_truncated_error_body_still_reports_the_status(monkeypatch, failure): + """A flaky drain must not replace the status copy with a traceback. + + ``exc.read()`` is called from *inside* the ``except HTTPError`` block, so the sibling + ``except http.client.HTTPException`` clause of the same ``try`` can never catch what it + raises -- the drain needs its own guard, and that guard has to name ``HTTPException`` + because ``IncompleteRead`` is neither an ``OSError`` nor a ``ValueError``. + """ + + error = _http_error(401) + + def _boom(*args, **kwargs): + raise failure + + error.read = _boom + error.close = _boom + _install_opener(monkeypatch, _Opener(error=error)) + + with pytest.raises(device_connect.DeviceConnectError) as caught: + device_connect.connect(TOKEN, control_url=CONTROL_URL, compute_url=COMPUTE_URL) + + # The customer gets the 401 copy they would have got from a well-behaved body. + assert caught.value.status == 401 + assert "Generate a new one" in str(caught.value) + assert TOKEN not in str(caught.value) + + +def test_the_cli_reports_a_truncated_error_body_instead_of_a_traceback( + monkeypatch, capsys +): + """End-to-end proof of the same path: exit 1 and clean copy, no stack trace.""" + + error = _http_error(401) + + def _boom(*args, **kwargs): + raise http.client.IncompleteRead(b'{"detail":"pri') + + error.read = _boom + error.close = _boom + _install_opener(monkeypatch, _Opener(error=error)) + + code = connect_cli.main( + ["--token", TOKEN, "--control-url", CONTROL_URL, "--compute-url", COMPUTE_URL] + ) + + assert code == 1 + err = capsys.readouterr().err + assert "Traceback" not in err + assert "IncompleteRead" not in err + assert "Generate a new one" in err + + def test_network_failure_reports_an_outage_without_leaking_the_detail(monkeypatch): _install_opener( monkeypatch, _Opener(error=urllib.error.URLError("proxy.internal refused")) @@ -329,14 +401,34 @@ def test_network_failure_reports_an_outage_without_leaking_the_detail(monkeypatc assert "proxy.internal" not in str(caught.value) -def test_a_success_without_a_refresh_credential_writes_nothing(monkeypatch, tmp_path): +@pytest.mark.parametrize("credential", [None, "", " "]) +def test_a_success_without_a_refresh_credential_writes_nothing( + monkeypatch, tmp_path, credential +): + """A 200 spends the token even when the body is unusable, so "try again" is wrong. + + The control plane consumes the single-use connect token as it writes a 200. Re-running + the same command therefore cannot succeed -- it deterministically produces a 401 -- so + the copy has to send the customer to the portal for a fresh token, exactly like the + truncated-reply path does. + """ + body = dict(REGISTRATION) - body.pop("refresh_credential") + if credential is None: + body.pop("refresh_credential") + else: + body["refresh_credential"] = credential _install_opener(monkeypatch, _Opener(body=body)) - with pytest.raises(device_connect.DeviceConnectError): + with pytest.raises(device_connect.DeviceConnectError) as caught: device_connect.connect(TOKEN, control_url=CONTROL_URL, compute_url=COMPUTE_URL) + message = str(caught.value) + assert caught.value.status == 502 + assert "generate a new one" in message.lower() + # The old copy sent the customer back into a guaranteed 401. + assert "Try again," not in message + assert TOKEN not in message assert not (tmp_path / "cloud_session.json").exists() @@ -370,8 +462,9 @@ def __exit__(self, *exc) -> bool: return False def read(self, size: int = -1) -> bytes: - # What ``HTTPResponse._read_chunked`` raises for a truncated body. It subclasses - # ``HTTPException``/``ValueError`` -- neither ``OSError`` nor ``URLError``. + # What ``HTTPResponse._read_chunked`` raises for a truncated body. Its only base + # is ``HTTPException`` -- it is neither an ``OSError``, a ``ValueError``, nor a + # ``URLError``. See ``test_incomplete_read_is_not_an_oserror_or_a_valueerror``. raise http.client.IncompleteRead(b'{"organization_id":"org_al') @@ -811,7 +904,7 @@ def test_the_manifest_outranks_the_compute_constant(monkeypatch): assert device_connect.default_compute_url(CONTROL_URL) == "" -@pytest.mark.parametrize("bad", ["nan", "inf", "-inf", "0", "-5"]) +@pytest.mark.parametrize("bad", ["nan", "inf", "-inf", "0", "-5", "1e9", "10000000000"]) def test_a_non_finite_timeout_is_refused_before_any_request(monkeypatch, bad): """``argparse``'s ``type=float`` accepts ``nan``/``inf``; the socket layer does not. @@ -834,6 +927,48 @@ def open(request, timeout=None): # pragma: no cover - must never run assert "timeout" in str(caught.value) +def test_a_huge_finite_timeout_is_refused_before_the_socket_overflows(): + """``math.isfinite`` is not the same test as "a socket can use this". + + ``socket.settimeout`` computes an absolute deadline, so a large but finite value raises + ``OverflowError`` ("timeout doesn't fit into C timeval" / "timestamp out of range for + platform time_t") -- an exception ``post_connect`` does not catch, so ``--timeout + 10000000000`` printed a traceback. The bound is checked against a real socket here so + the constant cannot drift into the range that overflows. + """ + + sock = socket.socket() + try: + sock.settimeout(device_connect._MAX_TIMEOUT_SECONDS) + assert sock.gettimeout() == device_connect._MAX_TIMEOUT_SECONDS + finally: + sock.close() + + with pytest.raises(device_connect.DeviceConnectError) as caught: + device_connect._validated_timeout(device_connect._MAX_TIMEOUT_SECONDS + 1) + + assert caught.value.status == 400 + assert "timeout" in str(caught.value) + + +def test_the_cli_reports_an_oversized_timeout_instead_of_a_traceback(monkeypatch, capsys): + class _Exploding: + @staticmethod + def open(request, timeout=None): # pragma: no cover - must never run + raise AssertionError("a request was started with an unusable timeout") + + _install_opener(monkeypatch, _Exploding()) + + code = connect_cli.main( + ["--token", TOKEN, "--control-url", CONTROL_URL, "--timeout", "10000000000"] + ) + + assert code == 1 + err = capsys.readouterr().err + assert "timeout" in err + assert "Traceback" not in err + + def test_the_cli_reports_a_bad_timeout_instead_of_a_traceback(monkeypatch, capsys): class _Exploding: @staticmethod From b7caeb4af869da9bfec16f11f7218ea72156da75 Mon Sep 17 00:00:00 2001 From: Jaixii Date: Sun, 26 Jul 2026 23:11:31 -0400 Subject: [PATCH 40/82] chore: declare version 1.1.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bump the five places the client version is written, all of which `tests/test_packaging.py` requires to agree: `pyproject.toml`, the `PackageNotFoundError` fallback in `engraphis/__init__.py`, the commercial manifest that `scripts/check_commercial_manifest.py` cross-checks against pyproject, and the plugin/marketplace pair under `.claude-plugin/`. Editing the two `.claude-plugin/*.json` files invalidates their entries in `.claude-plugin/skill-assets.sha256`, which `test_packaging.py` verifies by hashing the files on disk, so those two digests are regenerated here. All six files are LF, as `.gitattributes` requires. 1.1.0 rather than 1.0.2: the unreleased work adds commands and changes the managed-compute consent default, which is a minor bump. Note that 1.0.1 was declared and dated in the changelog but never tagged or published — PyPI's latest is 1.0.0 — so 1.1.0 is the first release to actually carry it. No tag is pushed by this commit; publishing stays a separate, deliberate step. Co-Authored-By: Claude Opus 5 --- .claude-plugin/marketplace.json | 2 +- .claude-plugin/plugin.json | 2 +- .claude-plugin/skill-assets.sha256 | 4 ++-- engraphis/__init__.py | 2 +- engraphis/commercial_manifest.json | 2 +- pyproject.toml | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index 66251cb..309e648 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -9,7 +9,7 @@ "name": "engraphis-memory", "source": "./", "description": "Discipline for giving agents durable, scoped, explainable memory across sessions and repos with the Engraphis MCP tools.", - "version": "1.0.1" + "version": "1.1.0" } ] } diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json index ed29620..5444c25 100644 --- a/.claude-plugin/plugin.json +++ b/.claude-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "engraphis-memory", - "version": "1.0.1", + "version": "1.1.0", "description": "Give agents durable, scoped, explainable memory across sessions and repos via the Engraphis MCP tools. Use when you learn something worth keeping, need prior context before acting, or ask why/how a fact changed. Covers remember/recall, why/timeline, forget/pin/correct, sessions, and code search.", "author": { "name": "The Engraphis Authors", diff --git a/.claude-plugin/skill-assets.sha256 b/.claude-plugin/skill-assets.sha256 index 5cbcced..2f197f0 100644 --- a/.claude-plugin/skill-assets.sha256 +++ b/.claude-plugin/skill-assets.sha256 @@ -1,5 +1,5 @@ -5c5336f5cc0e46c118dd13aace779555c07df1d5ec89828c02b1763a39bb637b .claude-plugin/marketplace.json -5dcc1fed4a7f2a527b1f756b90dc12d9b80fe393df0090e22a603f71c1b4faba .claude-plugin/plugin.json +f02c452829de41bae8ab81a6e74a3a9f89895c51dc9ba01cd3947c4baf0622e2 .claude-plugin/marketplace.json +a17b520f3c1f3002aeba29d9312f9091d5a281035996c2e9c90b0397f4fb9fb9 .claude-plugin/plugin.json 89bf2728e44a3c877e31982d387fcfab10fbe065eb6441b2792375ca5105c07c skills/engraphis-memory/SKILL.md a295b0448e2ff372ddd8ea4e0bc8dc53f3d4bd56ff1fbd0d88cf4b6179511ce1 skills/engraphis-memory/references/CONVENTIONS.md 45f4b4ad9dbfd39f2b377083d9b3eec5eed7cba7cb8fa139e3f420bdd6105343 skills/engraphis-memory/references/SCOPING.md diff --git a/engraphis/__init__.py b/engraphis/__init__.py index 2e9166c..90979c1 100644 --- a/engraphis/__init__.py +++ b/engraphis/__init__.py @@ -7,4 +7,4 @@ except PackageNotFoundError: # source tree without an installed distribution # Keep in step with [project] version in pyproject.toml — tests/test_packaging.py # pins the two together so a release cannot ship them out of sync. - __version__ = "1.0.1" + __version__ = "1.1.0" diff --git a/engraphis/commercial_manifest.json b/engraphis/commercial_manifest.json index 42c06ff..cbb4980 100644 --- a/engraphis/commercial_manifest.json +++ b/engraphis/commercial_manifest.json @@ -1,6 +1,6 @@ { "schema": "engraphis-commercial/v2", - "version": "1.0.1", + "version": "1.1.0", "control_plane": "https://api.engraphis.com", "managed_dashboard": "https://team.engraphis.com", "billing": { diff --git a/pyproject.toml b/pyproject.toml index da56949..26b32d9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,7 +10,7 @@ build-backend = "setuptools.build_meta" [project] name = "engraphis" -version = "1.0.1" +version = "1.1.0" description = "Local-first AI memory engine for agents — Ebbinghaus decay, interaction-aware recall, bi-temporal facts, hybrid retrieval, and an MCP server. You bring the LLM." readme = "README.md" license = "Apache-2.0" From b39ac839fc70f1782284ca82322110fc69bee597 Mon Sep 17 00:00:00 2001 From: Jaixii Date: Sun, 26 Jul 2026 13:04:01 -0400 Subject: [PATCH 41/82] feat(dashboard): opt-in canvas graph engine behind ?graph-engine=next A second knowledge-graph renderer wrapping the already-vendored force-graph, opt-in behind ?graph-engine=next. Classic stays the default and the rollback path; graphRender falls through to it on any failure. Four styles are applied CSP-safely through a data-graph-style attribute rather than inline style. Fixed while reviewing, before this shipped: - XSS. setData stamped name on every node, and force-graph's nodeLabel defaults to that accessor and renders through innerHTML. Node names are entity labels extracted from ingested memories. Classic never set name, so the sink did not exist until this feature added it. Both accessors are now explicit and escaped. - Recursive Tarjan overflowed the stack at roughly 29.6k nodes on a chain component; rewritten iteratively. - The rAF loop never stopped: a hidden canvas kept repainting for the whole session. Added pause/resume driven from selectView and a real destroy(). - Unbounded O(V*E) betweenness on the main thread with Array.shift queues, now lazy, pivot-sampled and budgeted: 60k nodes went 25s to 3s, and 0s in the default view. - prefers-reduced-motion was ignored, against an existing dashboard contract. The CSP drift gate never scanned this asset -- it only ever read index.html, dashboard.css and dashboard.js -- so "the gate passes" was vacuous for any new first-party script. Extended to hold them to the same contract and to check that every /static script index.html references actually exists. All four new rules were negative-tested. The original test asserted formatting strings. Replaced with 24 tests that execute the asset under Node with only a bare window in scope, which is itself the load-order proof, and mutation-tested: removing the escaping fails them. Co-Authored-By: Claude Opus 5 (1M context) --- engraphis/static/dashboard.css | 5 + engraphis/static/dashboard.js | 123 +++- engraphis/static/engraphis-graph.js | 833 ++++++++++++++++++++++++ engraphis/static/index.html | 2 + scripts/externalize_dashboard_assets.py | 48 +- tests/test_graph_engine_asset.py | 391 +++++++++++ 6 files changed, 1382 insertions(+), 20 deletions(-) create mode 100644 engraphis/static/engraphis-graph.js create mode 100644 tests/test_graph_engine_asset.py diff --git a/engraphis/static/dashboard.css b/engraphis/static/dashboard.css index fc2c328..59c4ec4 100644 --- a/engraphis/static/dashboard.css +++ b/engraphis/static/dashboard.css @@ -743,3 +743,8 @@ progress.graph-degree[data-graph-node-type="person_or_concept"]::-webkit-progres .gslider{display:flex;align-items:center;gap:8px;margin:6px 0}.gslider label{width:88px;flex-shrink:0;font-size:12px;color:var(--color-text-mute,var(--color-text-dim))}.gslider input[type=range]{flex:1;min-width:0;accent-color:var(--color-accent)} .gx-chip-full{width:100%;justify-content:flex-start;border-radius:7px;margin-bottom:2px} .gx-dot-dim{background:var(--color-text-dim,#888)} +#graph-net[data-graph-style="galaxy"]{background:radial-gradient(58% 50% at 24% 22%,rgba(126,64,208,.30),transparent 66%),radial-gradient(52% 58% at 82% 78%,rgba(220,72,164,.20),transparent 68%),radial-gradient(46% 52% at 62% 42%,rgba(58,120,224,.16),transparent 70%),#06040f} +#graph-net[data-graph-style="solar"]{background:radial-gradient(40% 48% at 50% 50%,rgba(255,184,92,.16),transparent 60%),radial-gradient(90% 90% at 50% 50%,rgba(18,32,64,.55),transparent 82%),#05070d} +#graph-net[data-graph-style="cyber"]{background:linear-gradient(rgba(34,224,255,.055) 1px,transparent 1px) 0 0/30px 30px,linear-gradient(90deg,rgba(34,224,255,.055) 1px,transparent 1px) 0 0/30px 30px,radial-gradient(72% 60% at 50% 0%,rgba(255,62,165,.12),transparent 72%),#050810} +#graph-net.engraphis-graph-node-hover{cursor:pointer} +#graph-net:not(.engraphis-graph-node-hover){cursor:grab} diff --git a/engraphis/static/dashboard.js b/engraphis/static/dashboard.js index d9da2e8..3cc941c 100644 --- a/engraphis/static/dashboard.js +++ b/engraphis/static/dashboard.js @@ -105,6 +105,9 @@ function selectView(v){ /* Plan pills live in the topbar; clear them on navigation so only the active view's loader can repopulate one. */ ['an-lock','au-lock'].forEach(id=>{const p=document.getElementById(id);if(p){p.textContent='';p.className='pill pill-muted topbar-lock'}}); + /* The graph canvas is the only view that owns an animation loop. Park it while it is not + on screen so navigating away does not leave a hidden canvas repainting forever. */ + if(v==='graph')graphEngineResume();else graphEnginePause(); closeMobileNav(); (LOADERS[v]||function(){})(); heading.tabIndex=-1; @@ -474,7 +477,7 @@ function renderSync(d){const el=document.getElementById('sync-body');if(!el)retu async function syncNow(){const b=document.getElementById('sync-btn')||document.getElementById('sync-retry-btn');const original=b&&b.textContent;const s=document.getElementById('sync-status');if(b){b.disabled=true;b.textContent='Syncing…'}if(s)s.textContent='Contacting the cloud…';try{const d=await api('/sync/run',{method:'POST',headers:{'Content-Type':'application/json'},body:'{}'});const su=d.summary||{};toast('Synced — pushed '+(su.exported||0)+', '+(su.added||0)+' new from other devices','ok');await loadSyncStatus()}catch(e){if(e.status===401||e.status===402||e.status===403){const el=document.getElementById('sync-body');if(el)el.innerHTML=syncRecoveryHtml();toast(e.status===402?'Cloud Sync requires an active Pro or Team entitlement — open Engraphis Cloud to upgrade or renew.':'Cloud Sync authorization is no longer active — reconnect in Engraphis Cloud.','err');return}toast('Sync failed: '+e.message,'err');if(b){b.disabled=false;b.textContent=original||'Sync now'}if(s)s.textContent='Sync failed — try again.'}} /* ─── knowledge graph (force-graph + d3-force: compact defaults and selectable layouts) ─── */ -let GRAPH=null, FG=null, GRESIZE=false, GRESIZEFRAME=0, GADJ={}, GCOMM_ADJ={}, GCOMPONENTS={}, GCOMPONENT_LAYOUT=null, GHILITE=null, GHOVERSET=null, GLABELRANK={}, GLABELBOXES=[], GDATA_CACHE=null, GACTIVE_DATA=null, GREDRAWFRAME=0, GPERF={large:false,dense:false}; +let GRAPH=null, FG=null, GRAPH_ENGINE=null, GRESIZE=false, GRESIZEFRAME=0, GADJ={}, GCOMM_ADJ={}, GCOMPONENTS={}, GCOMPONENT_LAYOUT=null, GHILITE=null, GHOVERSET=null, GLABELRANK={}, GLABELBOXES=[], GDATA_CACHE=null, GACTIVE_DATA=null, GREDRAWFRAME=0, GPERF={large:false,dense:false}; const GRAPH_PRESETS={ original:{label:'Original force',repel:120,link:30,gravity:14,font:13,size:3,linkw:1,labelDensity:40,curve:0,particles:0}, compact:{label:'Compact clusters',repel:42,link:20,gravity:26,font:12,size:3,linkw:.7,labelDensity:30,curve:.08,particles:0}, @@ -528,6 +531,7 @@ function graphSetTypeColor(type,color,persist){ if(!type||!graphValidColor(color))return; GCOLOR_OVERRIDES[type]=color.toLowerCase();GCOLOR_PALETTE='custom'; const picker=document.getElementById('graph-palette');if(picker)picker.value='custom'; + if(GRAPH_ENGINE){GRAPH_ENGINE.setTypeColor(type,color);if(persist)graphSaveColorPreferences();return} graphRefreshNodeColors(); if(persist)graphSaveColorPreferences(); } @@ -553,7 +557,85 @@ function graphUpdateHud(data){ if(count&&data)count.textContent=data.nodes.length.toLocaleString()+' entities · '+data.links.length.toLocaleString()+' relations'; if(badge)badge.textContent=GPERF.large?'Large graph mode':'Adaptive rendering'; } -function graphInvalidateData(){GDATA_CACHE=null;GACTIVE_DATA=null;GCOMPONENT_LAYOUT=null;GHILITE=null;GHOVERSET=null} +/* ── opt-in next-generation renderer (`?graph-engine=next`) ────────────────────────────── + The classic renderer stays the default and the rollback path. Everything below is written + so that any failure in the opt-in engine degrades to classic rather than taking the graph + view down: one throw sets GRAPH_ENGINE_FAILED and the flag is never honoured again for the + life of the page. */ +let GRAPH_ENGINE_FAILED=false; +function graphEngineEnabled(){ + if(GRAPH_ENGINE_FAILED)return false; + try{return new URLSearchParams(window.location.search).get('graph-engine')==='next'}catch(e){return false} +} +function graphEngineFallback(error){ + GRAPH_ENGINE_FAILED=true; + try{if(GRAPH_ENGINE)GRAPH_ENGINE.destroy()}catch(e){} + GRAPH_ENGINE=null; + /* The classic renderer skips seeding when GACTIVE_DATA still points at the current data, + so a failure *after* a successful engine render would hand it an empty canvas. Clearing + the marker makes the very next graphRender() a full classic build. */ + GACTIVE_DATA=null;GCOMPONENT_LAYOUT=null;GHILITE=null;GHOVERSET=null; + if(window.console&&console.warn)console.warn('graph-engine=next failed; falling back to the classic renderer',error); +} +function graphEngineEmptyMessage(){ + const total=(GRAPH&&GRAPH.nodes&&GRAPH.nodes.length)||0; + return total?('No connected entities — tick "Show unlinked" to see all '+total+'.'):'No entities in this workspace yet.'; +} +function graphRenderEngine(data,fit,reheat){ + const element=document.getElementById('graph-net'),empty=document.getElementById('graph-empty'); + if(!element||typeof EngraphisGraph==='undefined')return false; + try{ + if(!data.nodes.length){ + if(GRAPH_ENGINE)GRAPH_ENGINE.setData({nodes:[],links:[]}); + showAs(empty,true,'flex'); + if(empty)empty.textContent=graphEngineEmptyMessage(); + GACTIVE_DATA=null;graphSetLayoutStatus('No entities',false);return true; + } + showAs(empty,false);GPERF={large:data.nodes.length>600||data.links.length>2400,dense:data.links.length>1500}; + const created=!GRAPH_ENGINE; + if(created){ + GRAPH_ENGINE=EngraphisGraph.create(element,{ + reducedMotion:prefersReducedMotion, + onNodeClick:node=>{syncGraphExplorerSelection(node.id);graphNodeClick(node.label||node.name||node.id)}, + onBackgroundClick:()=>graphSetHighlight(null), + onStats:stats=>{const count=document.getElementById('graph-hud-count');if(count)count.textContent=stats.nodes.toLocaleString()+' entities · '+stats.links.toLocaleString()+' relations'} + }); + } + /* Re-seeding identical data would re-copy every node and throw its x/y away, restarting + the layout on each slider or preset change. The classic path guards the same way. */ + const dataChanged=created||GACTIVE_DATA!==data; + const layers={};document.querySelectorAll('#graph-layer-filters input').forEach(input=>{layers[input.value]=input.checked}); + GRAPH_ENGINE.apply(engine=>{ + engine.setSettings({...window.GSET}); + engine.setStyle(typeof GSTYLE!=='undefined'?GSTYLE:'cyber'); + engine.setColorBy(typeof GCOLORBY!=='undefined'?GCOLORBY:'community'); + engine.setPalette(typeof GCOLOR_PALETTE!=='undefined'?GCOLOR_PALETTE:'theme'); + engine.setTypeColors(GCOLOR_OVERRIDES||{}); + engine.setLayers(layers); + if(dataChanged)engine.setData(data); + },fit,reheat&&!prefersReducedMotion()); + /* Mirror the engine's clustering back onto the dashboard's own node objects, or the + cluster legend (which reads GACTIVE_DATA) reports one community for the whole store. */ + const communityMap=GRAPH_ENGINE.communityMap(); + data.nodes.forEach(node=>{node.community=communityMap[node.id]||0}); + GACTIVE_DATA=data;graphSyncReadouts();graphUpdateEditedBadge();graphUpdateHud(data);graphRenderLegend(GRAPH); + if(dataChanged)graphSetHighlight(null); + if(window.GSET.frozen)GRAPH_ENGINE.freeze(true); + graphSetSimulationStatus(prefersReducedMotion()?'Static layout':'Adaptive layout',false); + return true; + }catch(error){ + graphEngineFallback(error); + return false; + } +} +/* Nav away from the graph view: park the engine's animation frame. Without this the opt-in + renderer keeps repainting a hidden canvas for the rest of the session. */ +function graphEnginePause(){try{if(GRAPH_ENGINE)GRAPH_ENGINE.pause()}catch(e){}} +function graphEngineResume(){try{if(GRAPH_ENGINE)GRAPH_ENGINE.resume()}catch(e){}} +function graphInvalidateData(){ + if(GRAPH_ENGINE){try{GRAPH_ENGINE.destroy()}catch(e){}GRAPH_ENGINE=null} + GDATA_CACHE=null;GACTIVE_DATA=null;GCOMPONENT_LAYOUT=null;GHILITE=null;GHOVERSET=null +} async function loadLegacyGraph(){ graphInjectCss();graphInvalidateData();GRAPH=null; const empty=document.getElementById('graph-empty'),net=document.getElementById('graph-net'),nodesBox=document.getElementById('graph-entity-list'),edgesBox=document.getElementById('graph-relation-list'); @@ -563,8 +645,8 @@ async function loadLegacyGraph(){ if(!GRESIZE){ GRESIZE=true; window.addEventListener('resize',()=>{ - if(!FG||GRESIZEFRAME)return; - GRESIZEFRAME=requestAnimationFrame(()=>{GRESIZEFRAME=0;const element=document.getElementById('graph-net');if(FG&&element)FG.width(element.clientWidth).height(element.clientHeight)}); + if((!FG&&!GRAPH_ENGINE)||GRESIZEFRAME)return; + GRESIZEFRAME=requestAnimationFrame(()=>{GRESIZEFRAME=0;const element=document.getElementById('graph-net');if(GRAPH_ENGINE)GRAPH_ENGINE.resize();else if(FG&&element)FG.width(element.clientWidth).height(element.clientHeight)}); }); } const layerInputs=Array.from(document.querySelectorAll('#graph-layer-filters input')),selectedLayers=layerInputs.filter(input=>input.checked).map(input=>input.value),layerFilter=selectedLayers.length===layerInputs.length?'':'&layers='+encodeURIComponent(selectedLayers.join(',')),includeCode=document.getElementById('graph-include-code').checked,repo=(document.getElementById('graph-repo-filter').value||'').trim(); @@ -711,6 +793,7 @@ function graphSetStyle(name){ if(['classic','galaxy','solar','cyber'].indexOf(name)<0)name='cyber'; GSTYLE=name;try{localStorage.setItem('engraphis-graph-style',name)}catch(e){} graphApplyStyleChrome(); + if(GRAPH_ENGINE){GRAPH_ENGINE.setStyle(name);return} if(GRAPH&&FG){graphRefreshNodeColors();graphRenderLegend();graphRender(false,false);} } /* ─── colorful graphs even when every node is one entity type: color by community or connections ─── */ @@ -766,6 +849,7 @@ function graphSetColorBy(mode){ if(['type','community','connections'].indexOf(mode)<0)mode='community'; GCOLORBY=mode;try{localStorage.setItem('engraphis-graph-colorby',mode)}catch(e){} var sel=document.getElementById('graph-colorby');if(sel&&sel.value!==mode)sel.value=mode; + if(GRAPH_ENGINE){GRAPH_ENGINE.setColorBy(mode);graphRenderLegend();return} if(GRAPH&&FG&&GACTIVE_DATA){graphComputeCommunities(GACTIVE_DATA.nodes);GMAXDEG=GACTIVE_DATA.nodes.reduce(function(m,n){return Math.max(m,n.degree||0);},1);graphRefreshNodeColors();graphRenderLegend();} } function graphApplyForces(){ @@ -790,6 +874,9 @@ function graphApplyForces(){ function graphSetHighlight(id){ GHILITE=id||null; GHOVERSET=id?new Set([id,...(GADJ[id]||[])]):null; + /* graphRedraw() is a no-op without the classic FG instance, so the opt-in engine needs + telling directly — otherwise hovering the entity list highlights nothing on canvas. */ + if(GRAPH_ENGINE){try{GRAPH_ENGINE.setHighlight(GHILITE)}catch(e){}return} graphRedraw(); } function graphRefreshNodeMetrics(){ @@ -824,7 +911,11 @@ function graphRender(fit=true,reheat=true){ }); return; } - const element=document.getElementById('graph-net'),settings=window.GSET,mode=GRAPH_PRESETS[settings.mode]||GRAPH_PRESETS.compact,data=graphData(),dataChanged=GACTIVE_DATA!==data; + const element=document.getElementById('graph-net'),settings=window.GSET,mode=GRAPH_PRESETS[settings.mode]||GRAPH_PRESETS.compact,data=graphData(); + if(graphEngineEnabled()&&graphRenderEngine(data,fit,reheat))return; + /* Read AFTER the opt-in attempt: a failing engine resets GACTIVE_DATA precisely so the + classic renderer below rebuilds from scratch instead of assuming the canvas is current. */ + const dataChanged=GACTIVE_DATA!==data; GPERF={large:data.nodes.length>600||data.links.length>2400,dense:data.links.length>1500}; graphSyncReadouts();graphUpdateEditedBadge(); if(dataChanged){ @@ -924,6 +1015,7 @@ function graphSet(key,value){ const rd=document.querySelector('[data-graph-val="'+key+'"]'); if(rd)rd.textContent=key==='linkw'?Number(value).toFixed(1):(key==='size'?String(+Number(value).toFixed(1)):String(Math.round(value))); graphUpdateEditedBadge(); + if(GRAPH_ENGINE){GRAPH_ENGINE.setSettings({[key]:Number(value)});return} if(!FG)return; const layout=key==='repel'||key==='link'||key==='gravity'||key==='size'; if(key==='size')graphRefreshNodeMetrics(); @@ -953,7 +1045,7 @@ function graphApplyPreset(name){ const help=document.getElementById('graph-preset-help'),largeNote=GPERF.large?' Expensive animation, curves, and arrows stay off for this large graph.':''; if(help)help.textContent=notes[window.GSET.mode]+largeNote; graphRefreshNodeMetrics();graphSyncReadouts();graphUpdateEditedBadge(); - if(FG)graphRender(true,true); + if(FG||GRAPH_ENGINE)graphRender(true,true); } function graphSyncReadouts(){ ['repel','link','gravity','font','size','linkw','labelDensity'].forEach(k=>{const rd=document.querySelector('[data-graph-val="'+k+'"]');if(!rd)return;const v=window.GSET[k];rd.textContent=k==='linkw'?Number(v).toFixed(1):(k==='size'?String(+Number(v).toFixed(1)):String(Math.round(v)));const ctl=document.querySelector('[data-graph-setting="'+k+'"]');if(ctl)ctl.value=v*(Number(ctl.dataset.graphScale)||1);}); @@ -975,28 +1067,39 @@ function graphUpdateEditedBadge(){ showAs(btn,edited); } function graphResetPreset(){graphApplyPreset(window.GSET.mode==='custom'?'compact':window.GSET.mode);toast('Preset restored','ok')} -function graphToggleFlow(control){window.GSET.flow=control.checked;if(FG)graphRender(false,false)} +function graphToggleFlow(control){window.GSET.flow=control.checked;if(GRAPH_ENGINE)GRAPH_ENGINE.setSettings({flow:control.checked});else if(FG)graphRender(false,false)} function graphToggleFreeze(control){ - window.GSET.frozen=control.checked;if(!FG)return; + window.GSET.frozen=control.checked;if(GRAPH_ENGINE){GRAPH_ENGINE.freeze(control.checked);return}if(!FG)return; const ns=(FG.graphData().nodes)||[]; if(control.checked){ns.forEach(n=>{n.fx=n.x;n.fy=n.y});graphSetSimulationStatus('Layout frozen')} else{ns.forEach(n=>{n.fx=null;n.fy=null});if(!prefersReducedMotion())FG.d3ReheatSimulation()} } -function graphToggleLabels(control){window.GSET.labels=control.checked;if(FG)graphRender(false,false)} +function graphToggleLabels(control){window.GSET.labels=control.checked;if(GRAPH_ENGINE)GRAPH_ENGINE.setSettings({labels:control.checked});else if(FG)graphRender(false,false)} function graphRecolor(){ renderGraphColorControls(); + if(GRAPH_ENGINE){GRAPH_ENGINE.apply(engine=>{engine.setPalette(typeof GCOLOR_PALETTE!=='undefined'?GCOLOR_PALETTE:'theme');engine.setTypeColors(GCOLOR_OVERRIDES||{})},false,false);return} if(!FG)return; window.GCOL=graphReadThemeColors();graphRefreshNodeColors(); FG.linkColor(FG.linkColor());FG.linkWidth(FG.linkWidth());graphRedraw(); } -function graphFit(){if(FG)FG.zoomToFit(prefersReducedMotion()?0:500,72)} +function graphFit(){if(GRAPH_ENGINE)GRAPH_ENGINE.fit();else if(FG)FG.zoomToFit(prefersReducedMotion()?0:500,72)} function graphReheat(){ + if(GRAPH_ENGINE){if(prefersReducedMotion()){toast('Layout motion is off because reduced motion is enabled.','ok');return}GRAPH_ENGINE.reheat();return} if(!FG)return; if(prefersReducedMotion()){toast('Layout motion is off because reduced motion is enabled.','ok');return} graphSetSimulationStatus('Reheating layout',true);FG.d3ReheatSimulation(); } function graphFocus(name){ clearTimeout(window.__gfit); + if(GRAPH_ENGINE){ + /* Keep the classic contract: highlight, sync the explorer, and if the entity is filtered + out, offer the same "show unlinked" recovery instead of silently doing nothing. */ + if(GRAPH_ENGINE.zoomToNode(name)){graphSetHighlight(name);syncGraphExplorerSelection(name);return} + const isolated=document.getElementById('graph-show-iso'); + if(isolated&&!isolated.checked){isolated.checked=true;graphRender(false,true);setTimeout(()=>graphFocus(name),prefersReducedMotion()?0:500)} + else toast('Entity not in view','err'); + return; + } const node=FG&&(FG.graphData().nodes||[]).find(item=>item.id===name),duration=prefersReducedMotion()?0:550; if(node&&node.x!=null){graphSetHighlight(name);FG.centerAt(node.x,node.y,duration);FG.zoom(5,duration);syncGraphExplorerSelection(name)} else{const show=document.getElementById('graph-show-iso');if(show&&!show.checked){show.checked=true;graphRender(false,true);setTimeout(()=>graphFocus(name),duration?500:0)}else toast('Entity not in view','err')} diff --git a/engraphis/static/engraphis-graph.js b/engraphis/static/engraphis-graph.js new file mode 100644 index 0000000..6314077 --- /dev/null +++ b/engraphis/static/engraphis-graph.js @@ -0,0 +1,833 @@ +/* Engraphis knowledge graph — the dashboard's opt-in force-graph engine. + Restores the shipped behaviour: GRAPH_PRESETS, GSTYLE render modes (cyber/galaxy/solar/classic), + STYLE_PAL / STYLE_LAYERS / STYLE_BG, COMMUNITY_PALS, GRAPH_HEAT, colour-by community/type/connections, + GRAPH_PALETTES with per-entity-type overrides, d3 force wiring, directional particles, label ranking, + hover neighbourhood highlight, freeze, fit and reheat. Values copied from dashboard.js. + + The public graph endpoint calls its fields `label`, `from` and `to`; the engine also + accepts the renderer-friendly `name`, `source` and `target` aliases so it can be used + with both the dashboard adapter and standalone scene payloads. */ +(function () { + const PRESETS = { + original: { label: 'Original force', repel: 120, link: 30, gravity: 14, font: 13, size: 3, linkw: 1, labelDensity: 40, curve: 0, particles: 0 }, + compact: { label: 'Compact clusters', repel: 42, link: 20, gravity: 26, font: 12, size: 3, linkw: 0.7, labelDensity: 30, curve: 0.08, particles: 0 }, + communities: { label: 'Community islands', repel: 48, link: 16, gravity: 48, font: 12, size: 3, linkw: 0.72, labelDensity: 24, curve: 0.12, particles: 0 }, + radial: { label: 'Radial orbit', repel: 68, link: 26, gravity: 12, font: 13, size: 3, linkw: 0.75, labelDensity: 55, curve: 0.22, particles: 0 }, + constellation: { label: 'Constellation flow', repel: 34, link: 16, gravity: 38, font: 12, size: 3, linkw: 0.65, labelDensity: 35, curve: 0.32, particles: 2 }, + custom: { label: 'Custom tuning', curve: 0.1, particles: 0 } + }; + + const STYLE_PAL = { + galaxy: { person_or_concept: '#b789ff', mention: '#7bb4ff', hashtag: '#ffcf6b', email: '#8aa2ff', organization: '#66e0d0', location: '#ff7ea8' }, + solar: { person_or_concept: '#ffb454', mention: '#3fd2c7', hashtag: '#ffd68a', email: '#8ea8ff', organization: '#5b9bff', location: '#ff8f6b' }, + cyber: { person_or_concept: '#ff3ea5', mention: '#b6ff3c', hashtag: '#ffe14d', email: '#8b7bff', organization: '#22e0ff', location: '#ff5c7a' } + }; + const STYLE_LAYERS = { + classic: { temporal: '#6f9fd8', entity: '#5aafb3', causal: '#d7a84b', semantic: '#8c83e8' }, + galaxy: { temporal: '#7bb4ff', entity: '#66e0d0', causal: '#ffcf6b', semantic: '#b789ff' }, + solar: { temporal: '#5b9bff', entity: '#3fd2c7', causal: '#ffb454', semantic: '#ffd68a' }, + cyber: { temporal: '#22e0ff', entity: '#b6ff3c', causal: '#ffe14d', semantic: '#ff3ea5' } + }; + /* The per-style pane backgrounds are NOT defined here. `style-src-attr 'none'` forbids + writing them onto the element, so dashboard.css owns them behind + `#graph-net[data-graph-style="galaxy|solar|cyber"]` and this file only sets that + attribute. Keeping a second copy of the gradients in JS would be dead drift. */ + const PALETTES = { + theme: null, + aurora: { person_or_concept: '#8b7cf6', mention: '#2dd4bf', hashtag: '#fbbf24', email: '#60a5fa', organization: '#f472b6', location: '#a3e635' }, + ocean: { person_or_concept: '#38bdf8', mention: '#2dd4bf', hashtag: '#facc15', email: '#818cf8', organization: '#22d3ee', location: '#34d399' }, + ember: { person_or_concept: '#f97316', mention: '#fb7185', hashtag: '#facc15', email: '#a78bfa', organization: '#ef4444', location: '#84cc16' }, + contrast: { person_or_concept: '#0072b2', mention: '#009e73', hashtag: '#e69f00', email: '#56b4e9', organization: '#cc79a7', location: '#d55e00' } + }; + const THEME_ETYPE = { person_or_concept: '#8c83e8', mention: '#5aafb3', hashtag: '#d7a84b', email: '#6f9fd8', organization: '#58b882', location: '#df7478' }; + const COMMUNITY_PALS = { + classic: ['#8c83e8', '#5aafb3', '#d7a84b', '#6f9fd8', '#58b882', '#df7478', '#b07de0', '#4fb0a0', '#e0894a', '#7c9be0', '#e06a9a', '#9ac25a'], + galaxy: ['#b789ff', '#7bb4ff', '#66e0d0', '#ffcf6b', '#ff7ea8', '#8aa2ff', '#c98bff', '#5ad0e0', '#ffa0d0', '#9d7bff', '#6ad0b0', '#ffb060'], + solar: ['#ffb454', '#3fd2c7', '#ffd68a', '#5b9bff', '#ff8f6b', '#8ea8ff', '#ffc98a', '#4fc0b0', '#ff9f5b', '#7fb0ff', '#ffd0a0', '#5ad0c0'], + cyber: ['#ff3ea5', '#22e0ff', '#b6ff3c', '#ffe14d', '#8b7bff', '#ff5c7a', '#3cffd0', '#ff9ae0', '#5ce0ff', '#d0ff3c', '#ffb03c', '#a06bff'] + }; + const GRAPH_HEAT = ['#3f7bff', '#6a5cff', '#a24bff', '#e0479f', '#ff6b6b', '#ffc23d']; + + function idOf(value) { return value && typeof value === 'object' ? value.id : value; } + function nodeName(node) { return String(node.name || node.label || node.id || ''); } + function linkEndpoint(link, side) { + return idOf(link[side] !== undefined ? link[side] : link[side === 'source' ? 'from' : 'to']); + } + function asOfValue(value) { + if (value instanceof Date) return value.getTime(); + if (typeof value === 'number') return Number.isFinite(value) ? value * (value < 1e11 ? 1000 : 1) : null; + if (typeof value === 'string' && value.trim()) { + const numeric = Number(value); + if (Number.isFinite(numeric)) return asOfValue(numeric); + const parsed = Date.parse(value); + return Number.isFinite(parsed) ? parsed : null; + } + return null; + } + function temporalValue(item, key, fallback) { + const value = item[key] !== undefined ? item[key] : item[key === 'valid_from' ? 'born' : 'closed']; + if (value === undefined || value === null || value === '') return fallback; + return asOfValue(value); + } + + /* Node and link labels come from ingested memories, i.e. untrusted text. force-graph's + tooltip renders a string label through `innerHTML` (see float-tooltip in + vendor/force-graph.min.js), so every label handed to it must already be escaped. */ + function esc(value) { + if (value === undefined || value === null) return ''; + return String(value) + .replace(/&/g, '&').replace(//g, '>') + .replace(/"/g, '"').replace(/'/g, '''); + } + + function hexRgb(c) { + if (!c) return [140, 131, 232]; + if (c[0] === '#') { + const hex = c.length === 4 ? c[1] + c[1] + c[2] + c[2] + c[3] + c[3] : c.slice(1, 7); + const n = parseInt(hex, 16); + if (!Number.isFinite(n)) return [140, 131, 232]; + return [n >> 16 & 255, n >> 8 & 255, n & 255]; + } + const m = c.match(/\d+/g) || [140, 131, 232]; + return [+m[0], +m[1], +m[2]]; + } + function alpha(c, a) { const [r, g, b] = hexRgb(c); return 'rgba(' + r + ',' + g + ',' + b + ',' + a + ')'; } + function lighten(c, amt) { let [r, g, b] = hexRgb(c); r = Math.round(r + (255 - r) * amt); g = Math.round(g + (255 - g) * amt); b = Math.round(b + (255 - b) * amt); return 'rgb(' + r + ',' + g + ',' + b + ')'; } + function contrastOn(c) { const [r, g, b] = hexRgb(c); return (0.2126 * r + 0.7152 * g + 0.0722 * b) > 150 ? '#111827' : '#f8fafc'; } + + function makeStars() { + const a = [], c = ['#dfe6ff', '#dfe6ff', '#c9b6ff', '#a7c6ff', '#ffd9ef']; + for (let i = 0; i < 110; i++) a.push({ x: (Math.random() - 0.5) * 1200, y: (Math.random() - 0.5) * 1200, r: Math.random() * 1.1 + 0.25, a: Math.random() * 0.7 + 0.25, tw: Math.random() * 1.6 + 0.4, ph: Math.random() * 6.28, c: c[i % c.length] }); + return a; + } + const STARS = makeStars(); + + function communities(nodes, links) { + const adj = {}; + const nodesById = new Map(nodes.map(node => [node.id, node])); + nodes.forEach(n => { adj[n.id] = []; }); + links.forEach(l => { + const s = linkEndpoint(l, 'source'), t = linkEndpoint(l, 'target'); + if (adj[s]) adj[s].push(t); + if (adj[t]) adj[t].push(s); + }); + // Respect clusters supplied with the data (a store that already knows its topics); + // otherwise fall back to connected-component BFS, as the dashboard does. + if (nodes.length && nodes.every(n => typeof n.community === 'number')) return adj; + const seen = new Set(); + let group = 0; + nodes.forEach(n => { + if (seen.has(n.id)) return; + // Read head instead of Array#shift: shift() is O(n) per pop, which turns this BFS + // quadratic on the large stores the dashboard is expected to open. + const queue = [n.id]; + let head = 0; + seen.add(n.id); + while (head < queue.length) { + const id = queue[head++]; + const node = nodesById.get(id); + if (node) node.community = group; + (adj[id] || []).forEach(next => { if (!seen.has(next)) { seen.add(next); queue.push(next); } }); + } + group++; + }); + return adj; + } + + function maxOf(values, floor) { + // Math.max(...array) throws RangeError once the array outgrows the argument limit, + // which a real store reaches long before the renderer gets slow. + let best = floor; + for (let i = 0; i < values.length; i++) if (values[i] > best) best = values[i]; + return best; + } + + /* Brandes betweenness — which entity is the bridge whose loss would split a topic. + Brandes is O(V·E); on a large store that is seconds of blocked main thread, so above + BETWEENNESS_PIVOTS sources we run the standard pivot approximation over a deterministic, + evenly-spaced sample. The score is only ever used as a *relative* size/highlight signal + (it is normalised to the maximum), so a sampled estimate is fit for purpose. */ + const BETWEENNESS_PIVOTS = 220; + const BETWEENNESS_BUDGET = 1.5e6; + function betweenness(nodes, adj) { + const bc = {}; + nodes.forEach(n => { bc[n.id] = 0; }); + // Each pivot costs O(V) just to initialise its bookkeeping, so cap pivots by total work + // as well as by count: without the budget a 60k-entity store blocks the main thread for + // ~25s. This is a relative sizing signal, so fewer pivots degrades quality, not truth. + const pivots = Math.max(1, Math.min( + BETWEENNESS_PIVOTS, + Math.floor(BETWEENNESS_BUDGET / Math.max(1, nodes.length)) + )); + const stride = nodes.length > pivots ? Math.ceil(nodes.length / pivots) : 1; + for (let index = 0; index < nodes.length; index += stride) { + const src = nodes[index]; + const stack = [], pred = {}, sigma = {}, dist = {}, delta = {}; + nodes.forEach(n => { pred[n.id] = []; sigma[n.id] = 0; dist[n.id] = -1; delta[n.id] = 0; }); + sigma[src.id] = 1; dist[src.id] = 0; + const queue = [src.id]; + let head = 0; + while (head < queue.length) { + const v = queue[head++]; + stack.push(v); + (adj[v] || []).forEach(w => { + if (dist[w] < 0) { dist[w] = dist[v] + 1; queue.push(w); } + if (dist[w] === dist[v] + 1) { sigma[w] += sigma[v]; pred[w].push(v); } + }); + } + while (stack.length) { + const w = stack.pop(); + pred[w].forEach(v => { delta[v] += (sigma[v] / sigma[w]) * (1 + delta[w]); }); + if (w !== src.id) bc[w] += delta[w]; + } + } + const max = maxOf(Object.values(bc), 1); + nodes.forEach(n => { n.betweenness = bc[n.id] / max; }); + return bc; + } + + /* Bridge edges (Tarjan): removing one disconnects part of the store. */ + function findBridges(nodes, links, adj) { + const disc = {}, low = {}, parent = {}, bridges = new Set(); + const multiplicity = {}; + links.forEach(link => { + const s = linkEndpoint(link, 'source'), t = linkEndpoint(link, 'target'); + const key = s < t ? s + '|' + t : t + '|' + s; + multiplicity[key] = (multiplicity[key] || 0) + 1; + }); + let timer = 0; + // Iterative Tarjan. The recursive form recurses once per node along a path, so a + // chain-shaped component of a few thousand entities overflows the call stack and takes + // the whole render down with it — an explicit frame stack has no such ceiling. + const visit = root => { + const frames = [{ u: root, i: 0 }]; + disc[root] = low[root] = ++timer; + while (frames.length) { + const frame = frames[frames.length - 1]; + const u = frame.u, neighbors = adj[u] || []; + if (frame.i < neighbors.length) { + const v = neighbors[frame.i++]; + if (!disc[v]) { + parent[v] = u; + disc[v] = low[v] = ++timer; + frames.push({ u: v, i: 0 }); + } else if (v !== parent[u]) { + low[u] = Math.min(low[u], disc[v]); + } + continue; + } + frames.pop(); + const p = parent[u]; + if (p !== undefined) { + low[p] = Math.min(low[p], low[u]); + const key = p < u ? p + '|' + u : u + '|' + p; + if (low[u] > disc[p] && multiplicity[key] === 1) { + bridges.add(p + '|' + u); + bridges.add(u + '|' + p); + } + } + } + }; + nodes.forEach(n => { if (!disc[n.id]) visit(n.id); }); + links.forEach(l => { + const s = linkEndpoint(l, 'source'), t = linkEndpoint(l, 'target'); + l.bridge = bridges.has(s + '|' + t); + }); + return bridges; + } + + function create(el, options) { + if (typeof ForceGraph === 'undefined') throw new Error('force-graph not loaded'); + if (!el || typeof el.getAttribute !== 'function') throw new Error('graph container missing'); + const opts = options || {}; + const state = { + // Named `styleName`, not `style`: scripts/externalize_dashboard_assets.py scans this + // asset for runtime inline-style mutation with a text pattern, and a plain data field + // by the shorter name reads as one. The longer name keeps that gate honest. + styleName: 'cyber', colorBy: 'community', palette: 'theme', overrides: {}, + settings: Object.assign({}, PRESETS.communities, { mode: 'communities', labels: false, flow: true, frozen: false }), + minDegree: 1, showUnlinked: false, focusId: null, depth: 2, layers: { temporal: true, entity: true, causal: true, semantic: true, code: false }, + path: null, asOf: null, ghost: true, sizeBy: 'degree', bridges: false, suggestions: false, collapse: 'auto' + }; + let raw = { nodes: [], links: [], suggestions: [] }, adj = {}, hilite = null, hoverSet = null, maxDeg = 1; + let zoom = 1, collapsed = false; + let destroyed = false, running = true, fitTimer = 0, suspended = 0, pendingRender = null; + let betweennessReady = false; + const fg = ForceGraph()(el); + const api = {}; + + /* The dashboard already honours `prefers-reduced-motion` for the classic renderer; this + engine must not quietly reintroduce perpetual motion for the same user. */ + function reduced() { + if (typeof opts.reducedMotion === 'function') return !!opts.reducedMotion(); + try { + return !!(window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches); + } catch (e) { return false; } + } + /* force-graph already keeps redrawing while the simulation runs or any link still has + particles in flight, so `autoPauseRedraw(false)` is only needed for paint this engine + does behind its back: the galaxy starfield lives in onRenderFramePre and is invisible + to that change detection. Everywhere else, letting force-graph park the redraw is what + keeps a settled graph off the CPU. */ + function needsContinuousFrames() { + return !reduced() && state.styleName === 'galaxy'; + } + /* Betweenness is the one analysis that is superlinear in the store size, and nothing in + the default view consumes it — the bridge overlay and betweenness-sizing are both off. + Computing it lazily keeps opening the graph cheap; the first toggle pays for it once. */ + function ensureBetweenness() { + if (betweennessReady) return; + betweennessReady = true; + betweenness(raw.nodes, adj); + } + /* Apply a batch of setters with exactly one render at the end. Each public setter renders + on its own, so a single dashboard sync used to cost six full re-simulations (and six + zoom-to-fit timers). The caller also states the intent explicitly, because the merged + intent of the individual setters is not the caller's: `setSettings` always asks for a + reheat, which would reheat even on a `render(false, false)` refresh. */ + function batch(fn, fit, reheat) { + suspended++; + try { fn(api); } finally { + suspended--; + pendingRender = null; + render(!!fit, !!reheat); + } + } + + function etypeColor(type) { + if (state.overrides[type]) return state.overrides[type]; + if (state.styleName !== 'classic' && STYLE_PAL[state.styleName] && STYLE_PAL[state.styleName][type]) return STYLE_PAL[state.styleName][type]; + return THEME_ETYPE[type] || '#8c83e8'; + } + function commPal() { return COMMUNITY_PALS[state.styleName] || COMMUNITY_PALS.classic; } + function heatColor(node) { + const t = (node.rank || 0) / Math.max(1, raw.nodes.length - 1); + return GRAPH_HEAT[Math.min(GRAPH_HEAT.length - 1, Math.floor(t * GRAPH_HEAT.length))]; + } + function nodeColor(node) { + if (state.colorBy === 'community') { const p = commPal(); return p[(node.community || 0) % p.length]; } + if (state.colorBy === 'connections') return heatColor(node); + return etypeColor(node.etype); + } + function layerColor(layer) { return (STYLE_LAYERS[state.styleName] || STYLE_LAYERS.classic)[layer] || '#8c83e8'; } + + function born(item) { return temporalValue(item, 'valid_from', -Infinity); } + function closed(item) { return temporalValue(item, 'valid_to', null); } + function aliveAt(item, date) { + const start = born(item), end = closed(item); + return start <= date && (end === null || end > date); + } + + function collapsedData(nodes, links) { + const groups = {}; + nodes.forEach(n => { + const c = n.community || 0; + if (!groups[c]) groups[c] = { id: 'cluster-' + c, cluster: true, community: c, name: (n.topic || 'Cluster ' + (c + 1)), etype: n.etype, members: 0, degree: 0, betweenness: 0 }; + groups[c].members++; + groups[c].degree += n.degree || 0; + groups[c].betweenness = Math.max(groups[c].betweenness, n.betweenness || 0); + }); + const cnodes = Object.values(groups); + const seen = {}; + const clinks = []; + // Indexed lookup, not Array#find per endpoint: auto-collapse fires on every zoom-out, + // and the scan made that O(nodes x links) — a visible freeze on a real store. + const byId = new Map(raw.nodes.map(n => [n.id, n])); + links.forEach(l => { + const s = byId.get(linkEndpoint(l, 'source')); + const t = byId.get(linkEndpoint(l, 'target')); + if (!s || !t) return; + const a = 'cluster-' + (s.community || 0), b = 'cluster-' + (t.community || 0); + if (a === b) return; + const key = a < b ? a + '|' + b : b + '|' + a; + if (seen[key]) { seen[key].weight++; return; } + const link = { source: a, target: b, layer: l.layer, weight: 1, aggregate: true }; + seen[key] = link; + clinks.push(link); + }); + return { nodes: cnodes, links: clinks }; + } + + function visible() { + const keepLayer = l => state.layers[l.layer] !== false; + let nodes = raw.nodes.filter(n => (state.showUnlinked || n.degree > 0) && n.degree >= state.minDegree); + if (state.repo) nodes = nodes.filter(n => (n.repo || n.topic || '').toLowerCase().includes(state.repo) || nodeName(n).toLowerCase().includes(state.repo)); + if (state.asOf !== null) { + const live = nodes.filter(n => aliveAt(n, state.asOf)); + const ghosts = state.ghost ? nodes.filter(n => !aliveAt(n, state.asOf) && born(n) <= state.asOf).map(n => Object.assign(n, { ghost: true })) : []; + live.forEach(n => { n.ghost = false; }); + nodes = live.concat(ghosts); + } else { + nodes.forEach(n => { n.ghost = false; }); + } + if (state.focusId != null) { + const keep = new Set([state.focusId]); + let frontier = [state.focusId]; + for (let h = 0; h < state.depth; h++) { + const next = []; + frontier.forEach(id => (adj[id] || []).forEach(n => { if (!keep.has(n)) { keep.add(n); next.push(n); } })); + frontier = next; + } + nodes = nodes.filter(n => keep.has(n.id)); + } + const ids = new Set(nodes.map(n => n.id)); + let links = raw.links.filter(l => keepLayer(l) && ids.has(linkEndpoint(l, 'source')) && ids.has(linkEndpoint(l, 'target'))); + if (state.asOf !== null) { + links.forEach(l => { l.ghost = !aliveAt(l, state.asOf); }); + if (!state.ghost) links = links.filter(l => !l.ghost); + links = links.filter(l => born(l) <= state.asOf); + } else { + links.forEach(l => { l.ghost = false; }); + } + if (state.suggestions && raw.suggestions) { + raw.suggestions.forEach(s => { + const source = linkEndpoint(s, 'source'), target = linkEndpoint(s, 'target'); + if (ids.has(source) && ids.has(target)) links = links.concat([Object.assign({}, s, { source, target, layer: 'semantic', suggested: true })]); + }); + } + if (collapsed) return collapsedData(nodes, links.filter(l => !l.suggested)); + return { nodes, links }; + } + + function applyForces() { + const s = state.settings, mode = s.mode || 'compact'; + fg.d3Force('charge').strength(-s.repel); + fg.d3Force('link').distance(s.link); + if (typeof d3 === 'undefined') return; + fg.d3Force('radial', null); + if (mode === 'communities') { + const target = node => { + const c = node.community || 0; + const ring = 240 + (c % 3) * 90; + const a = (c * 2.399); + return { x: Math.cos(a) * ring, y: Math.sin(a) * ring * 0.62 }; + }; + fg.d3Force('x', d3.forceX(n => target(n).x).strength(s.gravity / 100)); + fg.d3Force('y', d3.forceY(n => target(n).y).strength(s.gravity / 100)); + } else { + const centering = mode === 'radial' ? Math.max(0.04, s.gravity / 300) : s.gravity / 100; + fg.d3Force('x', d3.forceX(0).strength(centering)); + fg.d3Force('y', d3.forceY(0).strength(centering)); + if (mode === 'radial' && d3.forceRadial) fg.d3Force('radial', d3.forceRadial(n => Math.max(0, 5 - Math.min(5, n.degree || 0)) * Math.max(8, s.link * 0.72)).strength(0.32)); + } + if (d3.forceCollide) fg.d3Force('collide', d3.forceCollide(n => n.radius + 1.5).iterations(2)); + } + + function styleBackground(ctx, scale) { + if (state.styleName === 'galaxy') { + const t = performance.now() / 1000; + ctx.save(); + ctx.globalCompositeOperation = 'lighter'; + for (let i = 0; i < STARS.length; i++) { + const s = STARS[i], al = s.a * (0.5 + 0.5 * Math.sin(t * s.tw + s.ph)); + if (al <= 0.02) continue; + ctx.globalAlpha = al; + ctx.beginPath(); + ctx.arc(s.x, s.y, s.r, 0, 6.2832); + ctx.fillStyle = s.c; + ctx.fill(); + } + ctx.restore(); + } else if (state.styleName === 'solar') { + ctx.save(); + const g = ctx.createRadialGradient(0, 0, 2, 0, 0, 130); + g.addColorStop(0, 'rgba(255,192,112,.20)'); + g.addColorStop(0.6, 'rgba(255,150,80,.05)'); + g.addColorStop(1, 'rgba(255,150,80,0)'); + ctx.fillStyle = g; + ctx.beginPath(); + ctx.arc(0, 0, 130, 0, 6.2832); + ctx.fill(); + ctx.strokeStyle = 'rgba(255,190,120,.10)'; + ctx.lineWidth = 1 / scale; + [72, 132, 200, 286, 384].forEach(r => { ctx.beginPath(); ctx.ellipse(0, 0, r, r * 0.66, 0, 0, 6.2832); ctx.stroke(); }); + ctx.restore(); + } + } + + function styleNode(node, ctx, scale) { + if (!Number.isFinite(node.x) || !Number.isFinite(node.y)) return; + const focus = hoverSet && hoverSet.size > 1, neighbor = focus && hoverSet.has(node.id), dim = focus && !neighbor; + let r = node.radius; + const col = node.color, rich = node.id === hilite || neighbor || node.hub || node.degree >= 3; + ctx.globalAlpha = node.ghost ? 0.22 : (dim ? 0.12 : 1); + if (node.ghost) { + ctx.lineWidth = 1.1 / scale; + ctx.strokeStyle = col; + ctx.beginPath(); ctx.arc(node.x, node.y, r, 0, 6.2832); ctx.stroke(); + ctx.globalAlpha = 1; + return; + } + if (node.cluster) { + const g = ctx.createRadialGradient(node.x, node.y, r * 0.2, node.x, node.y, r * 1.5); + g.addColorStop(0, alpha(col, 0.9)); + g.addColorStop(0.7, alpha(col, 0.35)); + g.addColorStop(1, alpha(col, 0)); + ctx.fillStyle = g; + ctx.beginPath(); ctx.arc(node.x, node.y, r * 1.5, 0, 6.2832); ctx.fill(); + ctx.fillStyle = contrastOn(col); + ctx.font = '600 ' + Math.max(3, r * 0.55) + 'px system-ui, sans-serif'; + ctx.textAlign = 'center'; + ctx.textBaseline = 'middle'; + ctx.fillText(String(node.members), node.x, node.y); + ctx.font = '500 ' + Math.max(2.6, r * 0.4) + 'px system-ui, sans-serif'; + ctx.fillStyle = 'rgba(232,236,245,.9)'; + ctx.fillText(nodeName(node), node.x, node.y + r * 1.5 + r * 0.5); + ctx.textAlign = 'left'; + ctx.globalAlpha = 1; + return; + } + if (state.bridges && node.betweenness > 0.35) { + ctx.save(); + ctx.strokeStyle = alpha('#ff5c7a', 0.75); + ctx.lineWidth = 1.2 / scale; + ctx.setLineDash([2 / scale, 2 / scale]); + ctx.beginPath(); ctx.arc(node.x, node.y, r + 3 / scale, 0, 6.2832); ctx.stroke(); + ctx.restore(); + } + if (state.styleName === 'galaxy') { + if (rich) { + ctx.save(); + ctx.globalCompositeOperation = 'lighter'; + const R = r * (node.id === hilite ? 4.4 : 3.0); + const g = ctx.createRadialGradient(node.x, node.y, 0, node.x, node.y, R); + g.addColorStop(0, alpha(col, dim ? 0.15 : 0.6)); + g.addColorStop(0.42, alpha(col, dim ? 0.05 : 0.16)); + g.addColorStop(1, alpha(col, 0)); + ctx.fillStyle = g; + ctx.beginPath(); + ctx.arc(node.x, node.y, R, 0, 6.2832); + ctx.fill(); + ctx.restore(); + } + ctx.beginPath(); ctx.arc(node.x, node.y, r, 0, 6.2832); ctx.fillStyle = col; ctx.fill(); + ctx.beginPath(); ctx.arc(node.x, node.y, Math.max(0.4, r * 0.4), 0, 6.2832); ctx.fillStyle = 'rgba(255,255,255,.9)'; ctx.fill(); + } else if (state.styleName === 'solar') { + const sun = node.rank === 0; + if (sun) r *= 1.7; + if (rich) { + ctx.save(); + ctx.globalCompositeOperation = 'lighter'; + const cc = sun ? '#ffcf6b' : col, R2 = r * (sun ? 3.4 : 2.1); + const g2 = ctx.createRadialGradient(node.x, node.y, 0, node.x, node.y, R2); + g2.addColorStop(0, alpha(cc, dim ? 0.1 : (sun ? 0.6 : 0.3))); + g2.addColorStop(1, alpha(cc, 0)); + ctx.fillStyle = g2; + ctx.beginPath(); ctx.arc(node.x, node.y, R2, 0, 6.2832); ctx.fill(); + ctx.restore(); + } + const sg = ctx.createRadialGradient(node.x - r * 0.4, node.y - r * 0.4, Math.max(0.1, r * 0.12), node.x, node.y, r); + sg.addColorStop(0, lighten(sun ? '#ffe4ad' : col, 0.5)); + sg.addColorStop(1, sun ? '#e08a25' : col); + ctx.fillStyle = sg; + ctx.beginPath(); ctx.arc(node.x, node.y, r, 0, 6.2832); ctx.fill(); + } else if (state.styleName === 'cyber') { + ctx.save(); + if (rich) { ctx.shadowColor = col; ctx.shadowBlur = dim ? 2 : r * 2.6; } + ctx.beginPath(); ctx.arc(node.x, node.y, r, 0, 6.2832); ctx.fillStyle = col; ctx.fill(); + ctx.restore(); + ctx.beginPath(); ctx.arc(node.x, node.y, Math.max(0.4, r * 0.42), 0, 6.2832); ctx.fillStyle = '#eafcff'; ctx.fill(); + } else { + ctx.beginPath(); ctx.arc(node.x, node.y, r, 0, 6.2832); ctx.fillStyle = col; ctx.fill(); + if (node.hub) { ctx.lineWidth = 0.8 / scale; ctx.strokeStyle = node.stroke; ctx.stroke(); } + } + if (node.id === hilite) { + ctx.lineWidth = 1.3 / scale; + ctx.strokeStyle = state.styleName === 'cyber' ? '#ffffff' : 'rgba(255,255,255,.9)'; + ctx.beginPath(); ctx.arc(node.x, node.y, r + 1.4 / scale, 0, 6.2832); ctx.stroke(); + } + const showLabel = (state.settings.labels && node.degree >= Math.max(1, 12 - state.settings.labelDensity / 6)) || node.id === hilite || neighbor; + if (showLabel && scale > 0.35) { + const size = Math.max(2, state.settings.font / scale / 3.4); + ctx.font = '500 ' + size + 'px system-ui, sans-serif'; + ctx.textBaseline = 'middle'; + ctx.fillStyle = 'rgba(0,0,0,.5)'; + ctx.fillText(nodeName(node), node.x + r + 1.6 + 0.3, node.y + 0.3); + ctx.fillStyle = node.id === hilite ? '#ffffff' : 'rgba(232,236,245,.86)'; + ctx.fillText(nodeName(node), node.x + r + 1.6, node.y); + } + ctx.globalAlpha = 1; + } + + function applyChrome() { + // Keep the asset compatible with `style-src-attr 'none'`: the CSP-safe dashboard + // stylesheet owns the visual backgrounds, while the canvas owns the data-driven paint. + el.setAttribute('data-graph-style', state.styleName); + } + + function refreshColors() { + const nodes = fg.graphData().nodes || []; + nodes.forEach(n => { n.color = nodeColor(n); n.stroke = contrastOn(n.color); }); + fg.nodeCanvasObject(fg.nodeCanvasObject()); + } + + function render(fit, reheat) { + if (destroyed) return; + if (suspended) { + pendingRender = pendingRender ? [pendingRender[0] || fit, pendingRender[1] || reheat] : [fit, reheat]; + return; + } + const motion = !reduced(); + const data = visible(); + const sizeMetric = n => state.sizeBy === 'betweenness' ? (n.betweenness || 0) : ((n.degree || 0) / Math.max(1, maxDeg)); + data.nodes.forEach(n => { + const base = (state.settings.size || 3); + n.radius = n.cluster + ? Math.max(3, base * (1.4 + Math.min(3, Math.sqrt(n.members || 1) * 0.7))) + : Math.max(0.8, base * (0.55 + Math.min(1.6, sizeMetric(n) * 1.9))); + n.color = nodeColor(n); + n.stroke = contrastOn(n.color); + }); + applyChrome(); + fg.graphData(data); + applyForces(); + fg.autoPauseRedraw(!needsContinuousFrames()); + if (fg.d3AlphaDecay) fg.d3AlphaDecay(0.035); + if (fg.d3VelocityDecay) fg.d3VelocityDecay(0.38); + if (fg.linkCurvature) fg.linkCurvature((PRESETS[state.settings.mode] || PRESETS.compact).curve || 0); + fg.linkDirectionalArrowLength(2.5).linkDirectionalArrowRelPos(1); + if (fg.linkDirectionalParticles) { + const particles = (state.settings.flow === false || !motion) + ? 0 + : (state.styleName === 'cyber' ? 3 : ((PRESETS[state.settings.mode] || {}).particles || 2)); + fg.linkDirectionalParticles(l => l.suggested || l.ghost ? 0 : particles) + .linkDirectionalParticleWidth(2) + .linkDirectionalParticleColor(l => alpha(layerColor(l.layer), 0.95)) + .linkDirectionalParticleSpeed(l => 0.002 + ((state.settings.flowSpeed || 45) / 100) * 0.008); + } + if (reheat && motion && !state.settings.frozen && fg.d3ReheatSimulation) fg.d3ReheatSimulation(); + if ((state.settings.frozen || !motion) && fg.d3AlphaDecay) { /* keep painting, stop layout */ fg.d3AlphaDecay(1); } + if (fit) { + clearTimeout(fitTimer); + fitTimer = setTimeout(() => { if (!destroyed) fg.zoomToFit(motion ? 600 : 0, 40); }, motion ? 320 : 0); + } + if (opts.onStats) opts.onStats({ nodes: data.nodes.length, links: data.links.length, total: raw.nodes.length, totalLinks: raw.links.length, preset: (PRESETS[state.settings.mode] || PRESETS.compact).label, collapsed: collapsed, ghosts: data.nodes.filter(n => n.ghost).length, bridges: data.links.filter(l => l.bridge).length, suggested: data.links.filter(l => l.suggested).length }); + } + + fg.backgroundColor('rgba(0,0,0,0)').nodeRelSize(1).autoPauseRedraw(true) + /* force-graph's default `nodeLabel`/`linkLabel` is the literal accessor "name", and its + tooltip renders a string label with innerHTML. Node names here are entity labels + extracted from ingested memories — untrusted input — so both accessors are set + explicitly and escaped rather than left on the vendor default. */ + .nodeLabel(node => esc(nodeName(node))) + .linkLabel(link => esc(link && link.label ? link.label : '')) + .onRenderFramePre((ctx, scale) => { try { styleBackground(ctx, scale); } catch (e) { } }) + .nodeCanvasObject((node, ctx, scale) => styleNode(node, ctx, scale)) + .nodePointerAreaPaint((node, color, ctx) => { ctx.fillStyle = color; ctx.beginPath(); ctx.arc(node.x, node.y, node.radius + 2, 0, 6.2832); ctx.fill(); }) + .linkColor(l => { + const focus = hoverSet && hoverSet.size > 1; + const s = linkEndpoint(l, 'source'), t = linkEndpoint(l, 'target'); + const active = !focus || s === hilite || t === hilite; + if (l.suggested) return alpha('#ffffff', active ? 0.34 : 0.1); + if (l.ghost) return alpha(layerColor(l.layer), 0.12); + if (state.bridges && l.bridge) return alpha('#ff5c7a', active ? 0.95 : 0.5); + const base = layerColor(l.layer); + return active ? alpha(base, focus ? 0.85 : 0.4) : alpha(base, 0.06); + }) + .linkLineDash(l => l.suggested ? [2, 2] : (l.ghost ? [1, 3] : null)) + .linkWidth(l => { + const w = state.settings.linkw || 1; + const focus = hoverSet && hoverSet.size > 1; + const s = linkEndpoint(l, 'source'), t = linkEndpoint(l, 'target'); + if (l.aggregate) return Math.min(6, 0.6 + Math.log2(1 + (l.weight || 1)) * 1.4) * w; + if (state.bridges && l.bridge) return 2.6 * w; + if (!focus) return 0.82 * w; + return (s === hilite || t === hilite) ? 2.4 * w : 0.4 * w; + }) + .onNodeHover(node => { + hilite = node ? node.id : null; + hoverSet = node ? new Set([node.id].concat(adj[node.id] || [])) : null; + el.classList.toggle('engraphis-graph-node-hover', !!node); + }) + .onNodeClick(node => { + if (node.cluster) { collapsed = false; state.collapse = false; render(false, true); setTimeout(() => { fg.centerAt(node.x, node.y, 500); fg.zoom(1.6, 500); }, 60); if (opts.onCollapseChange) opts.onCollapseChange(false); return; } + if (opts.onNodeClick) opts.onNodeClick(node); + }) + .onNodeDragEnd(node => { node.fx = node.x; node.fy = node.y; }) + .onBackgroundClick(() => { if (opts.onBackgroundClick) opts.onBackgroundClick(); }) + .onZoom(z => { + zoom = z.k || 1; + if (state.collapse !== 'auto') return; + const next = zoom < 0.55; + if (next !== collapsed) { + collapsed = next; + render(false, true); + if (opts.onCollapseChange) opts.onCollapseChange(collapsed); + } + }); + + api.setData = data => { + const inputNodes = Array.isArray(data && data.nodes) ? data.nodes : []; + const nodes = inputNodes + .filter(node => node && node.id != null) + .map(node => Object.assign({}, node, { name: nodeName(node) })); + const nodeIds = new Set(nodes.map(node => node.id)); + const links = (Array.isArray(data && (data.links || data.edges)) ? (data.links || data.edges) : []) + .map(link => { + const source = linkEndpoint(link, 'source'), target = linkEndpoint(link, 'target'); + return Object.assign({}, link, { source, target }); + }) + .filter(link => link.source != null && link.target != null && nodeIds.has(link.source) && nodeIds.has(link.target)); + const suggestions = (Array.isArray(data && data.suggestions) ? data.suggestions : []) + .map(link => Object.assign({}, link, { source: linkEndpoint(link, 'source'), target: linkEndpoint(link, 'target') })) + .filter(link => link.source != null && link.target != null); + raw = { nodes, links, suggestions }; + adj = communities(raw.nodes, raw.links); + const deg = {}; + raw.links.forEach(l => { const s = linkEndpoint(l, 'source'), t = linkEndpoint(l, 'target'); deg[s] = (deg[s] || 0) + 1; deg[t] = (deg[t] || 0) + 1; }); + raw.nodes.forEach(n => { n.degree = deg[n.id] || 0; n.betweenness = 0; }); + maxDeg = maxOf(raw.nodes.map(n => n.degree), 1); + const ranked = [...raw.nodes].sort((a, b) => b.degree - a.degree); + ranked.forEach((n, i) => { n.rank = i; n.hub = i < 6; }); + // Bridge *edges* are cheap (linear) and feed the stats readout, so they stay eager. + // Betweenness is not: see ensureBetweenness. + findBridges(raw.nodes, raw.links, adj); + betweennessReady = false; + if (state.bridges || state.sizeBy === 'betweenness') ensureBetweenness(); + render(true, true); + }; + api.setSettings = patch => { Object.assign(state.settings, patch); render(false, patch.mode !== undefined); }; + api.setPreset = name => { + const p = PRESETS[name] || PRESETS.compact; + state.settings.mode = PRESETS[name] ? name : 'compact'; + ['repel', 'link', 'gravity', 'font', 'size', 'linkw', 'labelDensity'].forEach(k => { if (p[k] !== undefined) state.settings[k] = p[k]; }); + render(true, true); + return { ...state.settings }; + }; + api.setStyle = name => { state.styleName = ['classic', 'galaxy', 'solar', 'cyber'].indexOf(name) < 0 ? 'cyber' : name; render(false, false); }; + api.setColorBy = name => { state.colorBy = name; refreshColors(); render(false, false); }; + api.setPalette = name => { state.palette = name; state.overrides = PALETTES[name] ? { ...PALETTES[name] } : {}; refreshColors(); }; + api.setTypeColor = (type, color) => { state.overrides[type] = color; state.palette = 'custom'; refreshColors(); }; + /* Rehydrating saved overrides is not a user edit, so it must not flip the palette + selector to "custom" behind the user's back the way setTypeColor deliberately does. */ + api.setTypeColors = map => { Object.assign(state.overrides, map || {}); refreshColors(); }; + /* One render for a whole batch of setters — see `batch`. */ + api.apply = (fn, fit, reheat) => { batch(fn, fit, reheat); }; + api.setHighlight = id => { + hilite = id == null ? null : id; + hoverSet = id == null ? null : new Set([id].concat(adj[id] || [])); + if (!destroyed) fg.nodeCanvasObject(fg.nodeCanvasObject()); + }; + api.setScope = patch => { Object.assign(state, patch); render(false, true); }; + api.setLayers = layers => { state.layers = layers; render(false, false); }; + api.focus = id => { state.focusId = id; render(true, true); }; + api.clearFocus = () => { state.focusId = null; render(true, true); }; + api.fit = () => { if (!destroyed) fg.zoomToFit(reduced() ? 0 : 500, 40); }; + api.reheat = () => { + if (destroyed || reduced()) return; + raw.nodes.forEach(n => { n.fx = undefined; n.fy = undefined; }); + if (fg.d3ReheatSimulation) { fg.d3AlphaDecay(0.035); fg.d3ReheatSimulation(); } + }; + api.freeze = on => { + state.settings.frozen = on; + if (on) { fg.d3Force('charge').strength(0); fg.d3AlphaDecay(1); return; } + applyForces(); + if (reduced()) return; + fg.d3AlphaDecay(0.035); + if (fg.d3ReheatSimulation) fg.d3ReheatSimulation(); + }; + api.zoomToNode = id => { + const n = raw.nodes.find(x => x.id === id); + if (!n || !Number.isFinite(n.x) || !Number.isFinite(n.y)) return false; + const duration = reduced() ? 0 : 500; + fg.centerAt(n.x, n.y, duration); + fg.zoom(3, duration); + return true; + }; + api.state = () => ({ ...state, collapsed }); + /* The engine clusters its own copies of the nodes, so a caller that renders a cluster + legend from the source data would otherwise report a single community. */ + api.communityMap = () => { + const map = {}; + raw.nodes.forEach(n => { map[n.id] = n.community || 0; }); + return map; + }; + api.setGhosts = on => { state.ghost = on; render(false, false); }; + api.setRepoFilter = repo => { state.repo = (repo || '').trim().toLowerCase(); render(false, true); }; + api.setAsOf = date => { state.asOf = asOfValue(date); render(false, true); }; + api.setSizeBy = metric => { + state.sizeBy = metric === 'betweenness' ? metric : 'degree'; + if (state.sizeBy === 'betweenness') ensureBetweenness(); + render(false, false); + }; + api.setBridges = on => { state.bridges = on; if (on) ensureBetweenness(); render(false, false); }; + /* Forces the lazy analysis; the dashboard does not display these yet, so nothing calls it + on the render path. Kept as the seam a "most load-bearing entity" panel would use. */ + api.metrics = () => { + ensureBetweenness(); + return { + top: [...raw.nodes].sort((a, b) => b.betweenness - a.betweenness).slice(0, 5) + .map(n => ({ id: n.id, name: nodeName(n), score: n.betweenness })), + bridges: raw.links.filter(l => l.bridge).length + }; + }; + api.setSuggestions = on => { state.suggestions = on; render(false, true); }; + api.setCollapse = mode => { + state.collapse = mode; + const next = mode === true || (mode === 'auto' && zoom < 0.55); + collapsed = next; + render(true, true); + }; + api.presets = PRESETS; + api.resize = () => { measure(); }; + /* Leaving the graph view must stop the simulation loop. force-graph keeps a rAF alive + for as long as it is resumed, so a hidden pane would otherwise repaint forever. */ + api.pause = () => { + if (destroyed || !running) return; + running = false; + if (fg.pauseAnimation) fg.pauseAnimation(); + }; + api.resume = () => { + if (destroyed || running) return; + running = true; + if (fg.resumeAnimation) fg.resumeAnimation(); + measure(); + }; + api.destroyed = () => destroyed; + api.destroy = () => { + if (destroyed) return; + destroyed = true; + clearTimeout(fitTimer); + try { + if (api._ro) { api._ro.disconnect(); api._ro = null; } + // `_destructor` pauses the rAF and drops the graph data; it does not detach the + // canvas, so clear the container too or a re-create leaves the old one attached. + if (fg._destructor) fg._destructor(); + el.removeAttribute('data-graph-style'); + el.classList.remove('engraphis-graph-node-hover'); + el.innerHTML = ''; + } catch (e) { /* teardown is best-effort: never let it block a view change */ } + raw = { nodes: [], links: [], suggestions: [] }; + adj = {}; + hilite = null; + hoverSet = null; + }; + + // A hidden pane measures 0x0; writing that into force-graph collapses the canvas and + // nothing restores it, so only a real box is ever applied. + const measure = () => { + if (destroyed) return; + const w = el.clientWidth, h = el.clientHeight; + if (w > 0 && h > 0) fg.width(w).height(h); + }; + measure(); + requestAnimationFrame(() => { if (destroyed) return; measure(); fg.zoomToFit(reduced() ? 0 : 400, 40); }); + if (typeof ResizeObserver !== 'undefined') { + api._ro = new ResizeObserver(() => measure()); + api._ro.observe(el); + } + applyChrome(); + return api; + } + + window.EngraphisGraph = { + create, PRESETS, PALETTES, STYLE_LAYERS, COMMUNITY_PALS, GRAPH_HEAT, THEME_ETYPE, STYLE_PAL, + /* Pure helpers, exported so the offline test suite can assert real behaviour (escaping, + component labelling, bridge detection, stack safety) without a browser or a bundler. + Nothing in the dashboard uses these; treat them as the engine's unit-test seam. */ + _internals: { + esc, hexRgb, alpha, contrastOn, communities, betweenness, findBridges, maxOf, + nodeName, linkEndpoint, asOfValue + } + }; +})(); diff --git a/engraphis/static/index.html b/engraphis/static/index.html index f92f8c5..4ce68af 100644 --- a/engraphis/static/index.html +++ b/engraphis/static/index.html @@ -323,6 +323,8 @@ + + diff --git a/scripts/externalize_dashboard_assets.py b/scripts/externalize_dashboard_assets.py index 4c27b2d..d34a9b6 100644 --- a/scripts/externalize_dashboard_assets.py +++ b/scripts/externalize_dashboard_assets.py @@ -19,6 +19,14 @@ CSS = STATIC / "dashboard.css" JS = STATIC / "dashboard.js" +#: First-party scripts the dashboard page loads besides ``dashboard.js``. They run under the +#: same strict CSP, so they are held to the same no-inline-style/no-inline-handler contract. +#: Vendored bundles under ``static/vendor`` are excluded: they are third-party artefacts we +#: do not rewrite, and pinning them is the job of the commercial-manifest check. +EXTRA_SCRIPTS = (STATIC / "engraphis-graph.js",) + +SCRIPT_SRC = re.compile(r']+src=["\'](/static/[^"\']+)["\']') + STYLE_ATTR = re.compile(r"\sstyle=(?:\"([^\"]*)\"|'([^']*)')") EVENT_ATTR = re.compile(r"\s(on[a-z]+)=(?:\"([^\"]*)\"|'([^']*)')") STYLE_REF = re.compile(r'data-csp-style=["\'](s\d+)["\']') @@ -208,24 +216,44 @@ def check() -> None: failures.append("inline event attribute") if not CSS.is_file() or not JS.is_file(): failures.append("missing external asset") - if STYLE_ATTR.search(js): - failures.append("inline style attribute in generated dashboard markup") - if EVENT_ATTR.search(js): - failures.append("inline event attribute in generated dashboard markup") - if re.search(r"\.(?:style|cssText)\b|(?:get|set)Attribute\([\"']style[\"']", js): - failures.append("runtime inline-style mutation") - if re.search(r"\[on[a-z]+|(?:get|set)Attribute\([\"']on[a-z]+[\"']", js): - failures.append("legacy inline-handler selector") + extra = {path.name: path.read_text(encoding="utf-8") for path in EXTRA_SCRIPTS if path.is_file()} + missing_scripts = sorted(path.name for path in EXTRA_SCRIPTS if not path.is_file()) + if missing_scripts: + failures.append("missing first-party script: " + ", ".join(missing_scripts)) + + # Every /static asset the page asks for must exist, or the dashboard 404s at load time + # and the strict CSP turns a typo into a silently broken view. + absent = sorted( + { + reference + for reference in SCRIPT_SRC.findall(html) + if not (ROOT / "engraphis" / reference.lstrip("/")).is_file() + } + ) + if absent: + failures.append("index.html loads missing script: " + ", ".join(absent)) + + for name, source in [("dashboard.js", js), *extra.items()]: + if STYLE_ATTR.search(source): + failures.append(f"inline style attribute in {name}") + if EVENT_ATTR.search(source): + failures.append(f"inline event attribute in {name}") + if re.search(r"\.(?:style|cssText)\b|(?:get|set)Attribute\([\"']style[\"']", source): + failures.append(f"runtime inline-style mutation in {name}") + if re.search(r"\[on[a-z]+|(?:get|set)Attribute\([\"']on[a-z]+[\"']", source): + failures.append(f"legacy inline-handler selector in {name}") if "${" in css or "'+" in css or "+'" in css: failures.append("unresolved JavaScript interpolation in CSS") - style_refs = set(STYLE_REF.findall(html + "\n" + js)) + style_refs = set(STYLE_REF.findall("\n".join([html, js, *extra.values()]))) style_rules = set(STYLE_RULE.findall(css)) missing_styles = sorted(style_refs - style_rules) if missing_styles: failures.append("missing CSP style rules: " + ", ".join(missing_styles)) - handler_refs = HANDLER_REF.findall(html + "\n" + js) + # Handler *definitions* only ever live in the generated dashboard.js registry, but any + # first-party script may reference one, so references are collected across all of them. + handler_refs = HANDLER_REF.findall("\n".join([html, js, *extra.values()])) handler_ids = {handler_id for _event, handler_id in handler_refs} handler_defs = set(HANDLER_DEF.findall(js)) missing_handlers = sorted(handler_ids - handler_defs) diff --git a/tests/test_graph_engine_asset.py b/tests/test_graph_engine_asset.py new file mode 100644 index 0000000..9194a78 --- /dev/null +++ b/tests/test_graph_engine_asset.py @@ -0,0 +1,391 @@ +"""Contract checks for the opt-in browser graph engine (``?graph-engine=next``). + +These tests intentionally stay dependency-light: the dashboard's offline CI floor does +not need a browser or a JavaScript package manager just to validate a shipped static +asset. Where Node is available the asset is *executed* rather than pattern-matched, so +the checks assert behaviour (escaping, bridge detection, stack safety, load-order +independence) instead of the presence of source substrings. + +The properties guarded here are the ones whose failure is silent in a browser: + +* the asset must define its global without touching ``ForceGraph``/``document``, so a + blocked or missing vendor bundle degrades instead of white-screening the dashboard; +* every label crossing into force-graph must be escaped, because force-graph's tooltip + is an ``innerHTML`` sink and entity labels come from ingested memories; +* the client-side graph analysis must not recurse per node or run unbounded work; +* the per-style pane backgrounds must stay in CSS, since the production CSP sets + ``style-src-attr 'none'``. +""" + +from __future__ import annotations + +import json +import re +import shutil +import subprocess +from pathlib import Path + +import pytest + +ROOT = Path(__file__).resolve().parents[1] +STATIC = ROOT / "engraphis" / "static" +ASSET = STATIC / "engraphis-graph.js" +INDEX = STATIC / "index.html" +CSS = STATIC / "dashboard.css" +DASHBOARD = STATIC / "dashboard.js" +VENDOR = STATIC / "vendor" / "force-graph.min.js" + +NODE = shutil.which("node") +requires_node = pytest.mark.skipif(NODE is None, reason="node is not installed") + +#: Evaluates the asset with nothing but a bare ``window`` object in scope. Any top-level +#: use of a browser or vendor global would raise here, which is the point. +PRELUDE = """ +const fs = require('fs'); +const source = fs.readFileSync(process.argv[1], 'utf8'); +const window = {}; +new Function('window', source)(window); +const G = window.EngraphisGraph; +const I = G._internals; +const emit = value => console.log(JSON.stringify(value)); +""" + + +def _run_node(script: str) -> object: + result = subprocess.run( + [NODE, "-e", PRELUDE + script, str(ASSET)], + cwd=ROOT, + capture_output=True, + text=True, + check=False, + ) + assert result.returncode == 0, result.stderr + return json.loads(result.stdout.strip().splitlines()[-1]) + + +# ── load order and failure isolation ──────────────────────────────────────────────── + + +def test_opt_in_graph_asset_is_loaded_after_its_dependencies() -> None: + html = INDEX.read_text(encoding="utf-8") + d3 = html.index("/static/vendor/d3.min.js") + force_graph = html.index("/static/vendor/force-graph.min.js") + engine = html.index("/static/engraphis-graph.js") + dashboard = html.index("/static/dashboard.js") + assert d3 < force_graph < engine < dashboard + + +@requires_node +def test_graph_asset_defines_its_global_without_touching_its_dependencies() -> None: + """Nothing may run at parse time except pure setup. + + ``PRELUDE`` supplies no ``ForceGraph``, no ``document`` and no ``requestAnimationFrame``. + If the asset reached for any of them at the top level this would throw, and in a browser + the same reach would abort the script and take ``window.EngraphisGraph`` with it. + """ + report = _run_node( + """ + emit({ + create: typeof G.create, + presets: Object.keys(G.PRESETS).sort(), + styles: Object.keys(G.STYLE_LAYERS).sort(), + }); + """ + ) + assert report["create"] == "function" + assert "communities" in report["presets"] + assert report["styles"] == ["classic", "cyber", "galaxy", "solar"] + + +@requires_node +def test_create_fails_loudly_when_force_graph_is_unavailable() -> None: + """A blocked vendor bundle must raise, not half-initialise a dead canvas.""" + report = _run_node( + """ + let message = null; + try { G.create({ getAttribute() { return null; } }, {}); } + catch (error) { message = error.message; } + emit({ message }); + """ + ) + assert report["message"] == "force-graph not loaded" + + +def test_dashboard_falls_back_to_the_classic_renderer_when_the_engine_throws() -> None: + source = DASHBOARD.read_text(encoding="utf-8") + # The opt-in flag must be latched off after a failure, and the render path must catch. + assert "GRAPH_ENGINE_FAILED" in source + assert "if(GRAPH_ENGINE_FAILED)return false" in source + assert "graphEngineFallback(error)" in source + engine_path = source[source.index("function graphRenderEngine"):] + engine_path = engine_path[: engine_path.index("\nfunction ")] + assert "try{" in engine_path and "}catch(error){" in engine_path + + +# ── XSS: untrusted entity labels reaching force-graph ─────────────────────────────── + + +def test_force_graph_tooltip_is_still_an_inner_html_sink() -> None: + """Guards the *reason* the engine sets its own label accessors. + + force-graph defaults ``nodeLabel``/``linkLabel`` to the accessor ``"name"`` and renders a + string label through ``innerHTML``. Node names here are entity labels extracted from + ingested memories, i.e. untrusted. If a vendor bump ever changes this, revisit whether + the explicit escaped accessors below are still the right shape. + """ + vendor = VENDOR.read_text(encoding="utf-8", errors="ignore") + assert 'nodeLabel:{default:"name"' in vendor + assert 'linkLabel:{default:"name"' in vendor + + +def test_engine_never_relies_on_the_default_label_accessor() -> None: + source = ASSET.read_text(encoding="utf-8") + assert ".nodeLabel(node => esc(nodeName(node)))" in source + assert ".linkLabel(" in source + assert "eval(" not in source + # The engine paints to canvas; the only markup sink it may use is clearing its own + # container on teardown. Anything else would be a route for an unescaped entity label. + writes = re.findall(r"\w+\.(?:inner|outer)HTML\s*=\s*[^;]+", source) + assert writes == ["el.innerHTML = ''"], writes + assert not re.search(r"insertAdjacentHTML|document\.write|createContextualFragment", source) + + +@requires_node +@pytest.mark.parametrize( + "payload", + [ + "", + "", + "\" onmouseover=\"alert(1)", + "", + ], +) +def test_entity_labels_are_escaped_before_they_can_reach_a_dom_sink(payload: str) -> None: + report = _run_node( + "emit({ escaped: I.esc(%s), named: I.nodeName({ label: %s }) });" + % (json.dumps(payload), json.dumps(payload)) + ) + escaped = report["escaped"] + assert "<" not in escaped and ">" not in escaped + assert '"' not in escaped and "'" not in escaped + assert "<" in escaped or """ in escaped + # nodeName is the raw value; escaping is the accessor's job, so this documents the split. + assert report["named"] == payload + + +# ── payload compatibility with the shipped /graph endpoint ────────────────────────── + + +@requires_node +def test_engine_accepts_both_the_api_and_renderer_link_shapes() -> None: + report = _run_node( + """ + const api = { from: 'a', to: 'b' }; + const renderer = { source: { id: 'c' }, target: 'd' }; + emit({ + apiSource: I.linkEndpoint(api, 'source'), + apiTarget: I.linkEndpoint(api, 'target'), + rendererSource: I.linkEndpoint(renderer, 'source'), + rendererTarget: I.linkEndpoint(renderer, 'target'), + label: I.nodeName({ label: 'Ada' }), + name: I.nodeName({ name: 'Grace' }), + fallback: I.nodeName({ id: 'ent_1' }), + }); + """ + ) + assert report["apiSource"] == "a" and report["apiTarget"] == "b" + assert report["rendererSource"] == "c" and report["rendererTarget"] == "d" + assert report["label"] == "Ada" + assert report["name"] == "Grace" + assert report["fallback"] == "ent_1" + + +@requires_node +def test_valid_time_accepts_seconds_milliseconds_and_iso_strings() -> None: + report = _run_node( + """ + emit({ + seconds: I.asOfValue(1700000000), + millis: I.asOfValue(1700000000000), + iso: I.asOfValue('2023-11-14T22:13:20Z'), + blank: I.asOfValue(''), + junk: I.asOfValue('not a date'), + }); + """ + ) + assert report["seconds"] == report["millis"] == 1700000000000 + assert report["iso"] == 1700000000000 + assert report["blank"] is None and report["junk"] is None + + +# ── client-side analysis: correctness and cost ────────────────────────────────────── + + +@requires_node +def test_bridge_detection_matches_a_known_graph() -> None: + """A triangle has no bridges; the tail hanging off it is all bridges.""" + report = _run_node( + """ + const nodes = ['a', 'b', 'c', 'd', 'e'].map(id => ({ id })); + const links = [['a','b'], ['b','c'], ['c','a'], ['c','d'], ['d','e']] + .map(([source, target]) => ({ source, target })); + const adj = I.communities(nodes, links); + I.findBridges(nodes, links, adj); + emit({ + bridges: links.filter(l => l.bridge).map(l => l.source + '-' + l.target), + communities: new Set(nodes.map(n => n.community)).size, + }); + """ + ) + assert report["bridges"] == ["c-d", "d-e"] + assert report["communities"] == 1 + + +@requires_node +def test_parallel_edges_are_not_reported_as_bridges() -> None: + report = _run_node( + """ + const nodes = [{ id: 'a' }, { id: 'b' }]; + const links = [{ source: 'a', target: 'b' }, { source: 'a', target: 'b' }]; + const adj = I.communities(nodes, links); + I.findBridges(nodes, links, adj); + emit({ bridges: links.filter(l => l.bridge).length }); + """ + ) + assert report["bridges"] == 0 + + +@requires_node +def test_disconnected_entities_are_labelled_as_separate_communities() -> None: + report = _run_node( + """ + const nodes = ['a', 'b', 'c', 'd'].map(id => ({ id })); + const links = [{ source: 'a', target: 'b' }, { source: 'c', target: 'd' }]; + const adj = I.communities(nodes, links); + emit({ groups: new Set(nodes.map(n => n.community)).size }); + """ + ) + assert report["groups"] == 2 + + +@requires_node +def test_graph_analysis_is_stack_safe_and_bounded_on_a_large_store() -> None: + """A long chain of entities is the worst case for both analyses. + + A recursive Tarjan overflows the call stack here, and exact Brandes betweenness is + O(V*E) — minutes of blocked main thread. Both are guarded, so this must finish well + inside the bound even on a slow machine. + """ + report = _run_node( + """ + const N = 40000; + const nodes = [], links = []; + for (let i = 0; i < N; i++) { + nodes.push({ id: 'n' + i }); + if (i) links.push({ source: 'n' + (i - 1), target: 'n' + i }); + } + const adj = I.communities(nodes, links); + const started = Date.now(); + I.findBridges(nodes, links, adj); + I.betweenness(nodes, adj); + const scores = nodes.map(n => n.betweenness); + emit({ + ms: Date.now() - started, + allBridges: links.every(l => l.bridge), + finite: scores.every(Number.isFinite), + peak: Math.max.apply(null, scores.slice(0, 1000).concat(scores.slice(-1000))), + }); + """ + ) + assert report["allBridges"] is True + assert report["finite"] is True + # Ends of a chain are never on a shortest path between others. + assert report["peak"] < 0.5 + assert report["ms"] < 30000, f"graph analysis took {report['ms']}ms on 40k entities" + + +@requires_node +def test_max_helper_survives_arrays_past_the_spread_limit() -> None: + """``Math.max(...array)`` throws RangeError long before a store is unrenderable.""" + report = _run_node("emit({ max: I.maxOf(new Array(400000).fill(7), 1) });") + assert report["max"] == 7 + + +@requires_node +def test_colour_helpers_handle_the_shorthand_hex_the_palettes_may_carry() -> None: + report = _run_node( + """ + emit({ + short: I.hexRgb('#abc'), + long: I.hexRgb('#8c83e8'), + empty: I.hexRgb(''), + light: I.contrastOn('#ffffff'), + dark: I.contrastOn('#000000'), + }); + """ + ) + assert report["short"] == [170, 187, 204] + assert report["long"] == [140, 131, 232] + assert report["empty"] == [140, 131, 232] + assert report["light"] == "#111827" + assert report["dark"] == "#f8fafc" + + +# ── CSP, styling and lifecycle ────────────────────────────────────────────────────── + + +def test_pane_backgrounds_are_owned_by_css_not_by_the_asset() -> None: + """``style-src-attr 'none'`` forbids writing these onto the element.""" + css = CSS.read_text(encoding="utf-8") + source = ASSET.read_text(encoding="utf-8") + for style in ("galaxy", "solar", "cyber"): + assert f'#graph-net[data-graph-style="{style}"]' in css + assert "data-graph-style" in source + # The gradients must exist in exactly one place, or the two copies drift. + assert "radial-gradient" not in source + assert "linear-gradient" not in source + + +def test_hover_cursor_class_the_asset_toggles_exists_in_css() -> None: + css = CSS.read_text(encoding="utf-8") + source = ASSET.read_text(encoding="utf-8") + assert "engraphis-graph-node-hover" in source + assert ".engraphis-graph-node-hover" in css + + +def test_csp_gate_covers_the_graph_asset() -> None: + from scripts.externalize_dashboard_assets import EXTRA_SCRIPTS, check + + assert ASSET in EXTRA_SCRIPTS, "the graph engine must be inside the CSP drift gate" + check() + + +def test_engine_exposes_a_teardown_and_the_dashboard_drives_it() -> None: + source = ASSET.read_text(encoding="utf-8") + dashboard = DASHBOARD.read_text(encoding="utf-8") + for member in ("api.destroy", "api.pause", "api.resume", "api.resize"): + assert member in source + # force-graph keeps a rAF alive while resumed; leaving the view must park it. + assert "if(v==='graph')graphEngineResume();else graphEnginePause()" in dashboard + assert "GRAPH_ENGINE.destroy()" in dashboard + + +def test_reduced_motion_is_honoured_by_the_opt_in_renderer() -> None: + source = ASSET.read_text(encoding="utf-8") + dashboard = DASHBOARD.read_text(encoding="utf-8") + assert "prefers-reduced-motion: reduce" in source + assert "opts.reducedMotion" in source + assert "reducedMotion:prefersReducedMotion" in dashboard + + +def test_graph_engine_is_syntactically_valid_when_node_is_installed() -> None: + if NODE is None: + pytest.skip("node is not installed") + result = subprocess.run( + [NODE, "--check", str(ASSET)], + cwd=ROOT, + capture_output=True, + text=True, + check=False, + ) + assert result.returncode == 0, result.stderr From 18b865ff5638f494941134aeafb277b17fa68d23 Mon Sep 17 00:00:00 2001 From: Jaixii Date: Sun, 26 Jul 2026 13:51:56 -0400 Subject: [PATCH 42/82] fix(dashboard): lazy-load the graph assets so the CSP stays clean Adding force-graph.min.js and engraphis-graph.js to index.html loaded them on every dashboard page, not just the graph view. force-graph applies inline styles at runtime, the production CSP is style-src 'self', so the browser blocked them and logged an error per attempt. Eleven pre-existing e2e tests assert a clean console and failed -- a regression this branch introduced. dashboard.js already had loadForceGraph() lazily fetching the vendor bundle for the Classic renderer, so neither script ever needed to be in index.html. Both tags are removed and engraphis-graph.js gets a matching memoized loader. The naive version of that would silently downgrade a ?graph-engine=next deep link to Classic, because graphRenderEngine's guard cannot tell "not fetched yet" from "unavailable". The engine fetch now starts alongside the vendor bundle -- one round trip, not two -- and graphRender waits on it and re-enters, so only a genuine load failure degrades, and that path warns. Proved by executing the real routing source under Node with a stub DOM: deep link renders the engine, a failing asset falls back and warns. Both are tests, and reverting to defer-without-await fails them. The "referenced scripts exist" gate rule became three, so removing the tags strengthens it rather than hollowing it out: lazy script.src references are existence-checked (their only reference is a JS string literal), neither asset may reappear as a parsed script src in index.html, and each must keep a lazy loader so deferring cannot orphan them. All negative-tested. Local gate: 1429 passed, 0 failed. The CSP fix itself cannot be proven locally -- Playwright needs node_modules, which is not installed here -- so CI is the real verification for the 11 e2e assertions. Co-Authored-By: Claude Opus 5 (1M context) --- engraphis/static/dashboard.js | 44 ++++++ engraphis/static/index.html | 8 +- scripts/externalize_dashboard_assets.py | 41 +++++- tests/test_externalize_dashboard_assets.py | 85 ++++++++++- tests/test_graph_engine_asset.py | 158 ++++++++++++++++++++- 5 files changed, 323 insertions(+), 13 deletions(-) diff --git a/engraphis/static/dashboard.js b/engraphis/static/dashboard.js index 3cc941c..aecba6f 100644 --- a/engraphis/static/dashboard.js +++ b/engraphis/static/dashboard.js @@ -887,6 +887,12 @@ function graphRedraw(){ if(!FG||GREDRAWFRAME)return; GREDRAWFRAME=requestAnimationFrame(()=>{GREDRAWFRAME=0;if(FG)FG.nodeCanvasObject(FG.nodeCanvasObject())}); } +/* ── on-demand graph assets ─────────────────────────────────────────────────────────────── + Neither script is in index.html. force-graph.min.js applies inline styles at runtime, and + under the production CSP (`style-src 'self'`) every one of those is blocked and reported; + loading it on a page that never opens the graph turns a plain dashboard view into a wall of + console errors. Both loaders are memoized, so a re-entrant graphRender() reuses the in-flight + fetch rather than appending a second " "" - "", + "", encoding="utf-8", ) monkeypatch.setattr(assets, "INDEX", index) @@ -52,3 +57,81 @@ def test_check_rejects_unclosed_inline_asset_at_eof(tmp_path, monkeypatch, tag): with pytest.raises(SystemExit, match=f"inline {tag} block"): assets.check() + + +# ── deferred graph assets ─────────────────────────────────────────────────────────────── +# force-graph.min.js applies inline styles at runtime, so under `style-src 'self'` loading it +# on every page reported a CSP violation per attempt. It and the opt-in engine are fetched on +# demand instead; these rules keep that true and keep the deferred references checked. + +_LOADERS = ( + "script.src='/static/vendor/force-graph.min.js';" + "script.src='/static/engraphis-graph.js';" +) + + +def _gate(tmp_path, monkeypatch, html: str, js: str) -> None: + index, css, script = ( + tmp_path / "index.html", + tmp_path / "dashboard.css", + tmp_path / "dashboard.js", + ) + index.write_text(html, encoding="utf-8") + css.write_text("", encoding="utf-8") + script.write_text(js, encoding="utf-8") + monkeypatch.setattr(assets, "INDEX", index) + monkeypatch.setattr(assets, "CSS", css) + monkeypatch.setattr(assets, "JS", script) + # Isolate these cases to the script-reference rules; the first-party CSP scan has its own. + monkeypatch.setattr(assets, "EXTRA_SCRIPTS", ()) + + +def test_check_rejects_an_eagerly_loaded_csp_hostile_script(tmp_path, monkeypatch): + """Putting the tag back in index.html is precisely the regression this rule catches.""" + _gate( + tmp_path, + monkeypatch, + '', + _LOADERS, + ) + + with pytest.raises(SystemExit, match="must not eagerly load: /static/vendor/force-graph"): + assets.check() + + +def test_check_allows_a_deferred_script_named_only_in_a_comment(tmp_path, monkeypatch): + """The rule reads parsed ``' + "" + '' + '' + "" + "" + "" + ) + + assert found == [ + "/static/vendor/force-graph.min.js", + "/static/engraphis-graph.js", + "/static/dashboard.js", + ] + + +def test_check_rejects_an_eagerly_loaded_script_in_any_tag_case(tmp_path, monkeypatch): + """The uppercase spelling is loaded by browsers, so it must fail the same rule.""" + _gate( + tmp_path, + monkeypatch, + '', + _LOADERS, + ) + + with pytest.raises(SystemExit, match="must not eagerly load: /static/vendor/force-graph"): + assets.check() + + +def test_check_rejects_a_mixed_case_reference_to_a_missing_file(tmp_path, monkeypatch): + """The existence check must not have a case-shaped hole either.""" + _gate( + tmp_path, + monkeypatch, + "", + _LOADERS, + ) + + with pytest.raises(SystemExit, match=r"referenced script is missing: .*renamed-bundle\.js"): + assets.check() + + +def test_uppercase_script_src_is_not_mistaken_for_an_inline_block(tmp_path, monkeypatch): + """The inline-block rule reads the same parse, so an external tag stays external.""" + _gate( + tmp_path, + monkeypatch, + '', + _LOADERS, + ) + + assets.check() diff --git a/tests/test_graph_engine_asset.py b/tests/test_graph_engine_asset.py index 629cb18..d1daa21 100644 --- a/tests/test_graph_engine_asset.py +++ b/tests/test_graph_engine_asset.py @@ -51,9 +51,51 @@ """ -def _run_node(script: str) -> object: +#: Same, plus a recording stand-in for force-graph so ``create()`` can be *driven*. Every +#: accessor is a chainable setter that returns the stored value when called with no arguments — +#: force-graph's own kapsule semantics — so the paint configuration the engine installs can be +#: read back and invoked instead of pattern-matched. ``calls`` counts the invalidations the +#: engine requests, which is the only observable form a "redraw now" takes. +ENGINE_PRELUDE = """ +const fs = require('fs'); +const source = fs.readFileSync(process.argv[1], 'utf8'); +const window = {}; +globalThis.requestAnimationFrame = () => {}; +const store = {}, calls = {}; +const fg = new Proxy({}, { + get: (_target, prop) => (...args) => { + if (!args.length) return store[prop]; + calls[prop] = (calls[prop] || 0) + 1; + store[prop] = args.length === 1 ? args[0] : args; + return fg; + }, +}); +globalThis.ForceGraph = () => () => fg; +const el = { + attrs: {}, innerHTML: '', clientWidth: 800, clientHeight: 600, + getAttribute(name) { return this.attrs[name] === undefined ? null : this.attrs[name]; }, + setAttribute(name, value) { this.attrs[name] = value; }, + removeAttribute(name) { delete this.attrs[name]; }, + classList: { toggle() {}, remove() {} }, +}; +const chain = count => { + const nodes = [], links = []; + for (let i = 0; i <= count; i++) nodes.push({ id: 'n' + i }); + for (let i = 0; i < count; i++) { + links.push({ source: 'n' + i, target: 'n' + (i + 1), layer: 'semantic' }); + } + return { nodes, links }; +}; +new Function('window', source)(window); +const G = window.EngraphisGraph; +const I = G._internals; +const emit = value => console.log(JSON.stringify(value)); +""" + + +def _run_node(script: str, prelude: str = PRELUDE) -> object: result = subprocess.run( - [NODE, "-e", PRELUDE + script, str(ASSET)], + [NODE, "-e", prelude + script, str(ASSET)], cwd=ROOT, capture_output=True, text=True, @@ -63,6 +105,10 @@ def _run_node(script: str) -> object: return json.loads(result.stdout.strip().splitlines()[-1]) +def _run_engine(script: str) -> object: + return _run_node(script, prelude=ENGINE_PRELUDE) + + # ── load order and failure isolation ──────────────────────────────────────────────── @@ -450,6 +496,41 @@ def test_graph_analysis_is_stack_safe_and_bounded_on_a_large_store() -> None: assert report["ms"] < 30000, f"graph analysis took {report['ms']}ms on 40k entities" +@requires_node +def test_influence_relations_do_not_merge_two_topics_into_one_community() -> None: + """Community Islands must not fuse two topics over a single cross-topic relation. + + ``influences`` edges routinely span otherwise separate bodies of work. The classic + renderer keeps them drawn and traversable but builds its clustering adjacency without + them (``GCOMM_ADJ``); adding every link to one adjacency gives both topics the same + colour and the same force centre. + """ + report = _run_node( + """ + const nodes = ['a', 'b', 'c', 'd'].map(id => ({ id })); + const links = [ + { source: 'a', target: 'b', label: 'mentions' }, + { source: 'c', target: 'd', label: 'mentions' }, + { source: 'b', target: 'c', label: 'influences' }, + ]; + const adj = I.communities(nodes, links); + I.findBridges(nodes, links, adj); + emit({ + groups: new Set(nodes.map(n => n.community)).size, + merged: nodes[1].community === nodes[2].community, + neighbours: (adj.b || []).slice().sort(), + bridges: links.filter(l => l.bridge).length, + }); + """ + ) + assert report["groups"] == 2 + assert report["merged"] is False + # The relation itself stays in the traversal adjacency: hover neighbourhood, focus depth + # and bridge detection all still see it. Only the clustering ignores it. + assert report["neighbours"] == ["a", "c"] + assert report["bridges"] == 3 + + @requires_node def test_max_helper_survives_arrays_past_the_spread_limit() -> None: """``Math.max(...array)`` throws RangeError long before a store is unrenderable.""" @@ -477,6 +558,206 @@ def test_colour_helpers_handle_the_shorthand_hex_the_palettes_may_carry() -> Non assert report["dark"] == "#f8fafc" +# ── render configuration: what the engine actually installs on force-graph ────────── + + +@requires_node +def test_flow_particles_are_capped_on_a_large_relation_set() -> None: + """Three animated particles per relation does not survive a real ``/graph`` response. + + force-graph advances every particle on every frame, so a few thousand relations is tens + of thousands of animated objects and an unusable canvas. The classic renderer refuses to + draw them past 800 links; the opt-in engine must use the same cutoff rather than trusting + that no store is big. + """ + report = _run_engine( + """ + const api = G.create(el, {}); + const particlesFor = link => store.linkDirectionalParticles(link || { layer: 'semantic' }); + api.setStyle('cyber'); + api.setSettings({ flow: true }); + api.setData(chain(40)); + const small = particlesFor(); + api.setData(chain(800)); + const atLimit = particlesFor(); + api.setData(chain(801)); + const overLimit = particlesFor(); + api.setData(chain(4000)); + emit({ small, atLimit, overLimit, realistic: particlesFor() * 4000 }); + """ + ) + assert report["small"] == 3 + assert report["atLimit"] == 3 + assert report["overLimit"] == 0 + # The number this guards: 4k relations x 3 particles was 12,000 animated objects a frame. + assert report["realistic"] == 0 + + +@requires_node +def test_hovering_a_node_asks_for_a_redraw() -> None: + """A highlight nobody repaints is invisible. + + ``onNodeHover`` mutates closure state the paint callbacks read. With reduced motion on, + flow disabled, or a settled simulation, force-graph's ``autoPauseRedraw`` loop has nothing + left to animate and will not repaint just because the callback fired. + """ + report = _run_engine( + """ + const api = G.create(el, { reducedMotion: () => true }); + api.setData({ nodes: [{ id: 'a' }, { id: 'b' }], links: [{ source: 'a', target: 'b' }] }); + const settled = calls.nodeCanvasObject; + store.onNodeHover({ id: 'a' }); + const hovered = calls.nodeCanvasObject; + store.onNodeHover(null); + emit({ + settled, hovered, cleared: calls.nodeCanvasObject, + particles: store.linkDirectionalParticles({ layer: 'semantic' }), + }); + """ + ) + # Reduced motion: nothing is in flight, so an unrequested redraw would never arrive. + assert report["particles"] == 0 + assert report["hovered"] > report["settled"] + assert report["cleared"] > report["hovered"] + + +@requires_node +def test_unlinked_entities_are_shown_only_when_the_engine_is_told_to() -> None: + """The lever the dashboard has to pull for its "Show unlinked nodes" checkbox.""" + report = _run_engine( + """ + const seen = []; + const api = G.create(el, { onStats: stats => seen.push(stats.nodes) }); + api.setData({ + nodes: [{ id: 'a' }, { id: 'b' }, { id: 'lonely' }], + links: [{ source: 'a', target: 'b' }], + }); + const hidden = seen[seen.length - 1]; + api.setScope({ showUnlinked: true, minDegree: 0 }); + emit({ hidden, shown: seen[seen.length - 1] }); + """ + ) + assert report["hidden"] == 2 + assert report["shown"] == 3 + + +#: Executes the *real* ``graphRenderEngine`` source against stubs. Only its collaborators are +#: faked; the function itself is a verbatim slice, so what it forwards to the engine — and when +#: it parks a freshly created renderer — is observed rather than asserted about the source text. +RENDER_HARNESS = """ +const fs = require('fs'); +const src = fs.readFileSync(process.argv.slice(1).find(a => a.endsWith('dashboard.js')), 'utf8'); +const scenario = JSON.parse(process.argv[process.argv.length - 1]); +const start = src.indexOf('function graphRenderEngine('); +const slice = src.slice(start, src.indexOf('/* Nav away from the graph view', start)); + +const log = { created: 0, paused: 0, seeded: 0, scope: null, error: null }; +const checkbox = { checked: scenario.showUnlinked }; +const element = { classList: { toggle() {} }, setAttribute() {}, set textContent(value) {} }; +globalThis.document = { + getElementById: id => (id === 'graph-show-iso' ? checkbox : element), + querySelectorAll: () => [], +}; +const engine = { + setSettings() {}, setStyle() {}, setColorBy() {}, setPalette() {}, setTypeColors() {}, + setLayers() {}, setScope(patch) { log.scope = patch; }, + setData(data) { log.seeded = data.nodes.length; }, +}; +const api = { + apply(fn) { fn(engine); }, communityMap: () => ({}), + freeze() {}, destroy() {}, resume() {}, pause() { log.paused += 1; }, +}; +globalThis.EngraphisGraph = { create() { log.created += 1; return api; } }; +globalThis.window = { GSET: { mode: 'compact', frozen: false } }; +globalThis.GRAPH = { nodes: [] }; +globalThis.GRAPH_ENGINE = null; +globalThis.GACTIVE_DATA = null; +globalThis.GCOLOR_OVERRIDES = {}; +/* The state the nav-away pause recorded while GRAPH_ENGINE was still null. */ +globalThis.GRAPH_ENGINE_PARKED = scenario.parked; +globalThis.showAs = () => {}; +globalThis.prefersReducedMotion = () => false; +for (const name of ['graphSetLayoutStatus', 'graphSyncReadouts', 'graphUpdateEditedBadge', + 'graphUpdateHud', 'graphRenderLegend', 'graphSetHighlight', + 'graphSetSimulationStatus', 'syncGraphExplorerSelection', 'graphNodeClick', + 'graphEngineEmptyMessage']) globalThis[name] = () => {}; +globalThis.graphEngineFallback = error => { + log.error = String((error && error.message) || error); +}; + +const graphRenderEngine = new Function(slice + '\\nreturn graphRenderEngine;')(); +const rendered = graphRenderEngine({ + nodes: [{ id: 'a' }, { id: 'b' }, { id: 'lonely' }], + links: [{ source: 'a', target: 'b' }], +}, true, true); +console.log(JSON.stringify(Object.assign({ rendered }, log))); +""" + + +def _run_render(*, show_unlinked: bool = False, parked: bool = False) -> dict: + source = DASHBOARD.read_text(encoding="utf-8") + # The harness slices real source; keep its landmarks honest. + assert "function graphRenderEngine(" in source + assert "/* Nav away from the graph view" in source + scenario = json.dumps({"showUnlinked": show_unlinked, "parked": parked}) + result = subprocess.run( + [NODE, "-e", RENDER_HARNESS, str(DASHBOARD), scenario], + cwd=ROOT, + capture_output=True, + text=True, + check=False, + ) + assert result.returncode == 0, result.stderr + report = json.loads(result.stdout.strip().splitlines()[-1]) + assert report["error"] is None, report["error"] + assert report["rendered"] is True + return report + + +@requires_node +@pytest.mark.parametrize("checked", [False, True]) +def test_dashboard_tells_the_engine_whether_to_show_unlinked_entities(checked: bool) -> None: + """"Show unlinked nodes" is filtered twice, and only one half was wired up. + + ``graphData()`` starts supplying degree-zero entities when the box is ticked, but the + engine re-filters on its own ``showUnlinked``/``minDegree`` state — which stays at the + defaults that drop exactly those entities — unless the dashboard says otherwise. + """ + report = _run_render(show_unlinked=checked) + + assert report["scope"] is not None, "the engine never learns the checkbox state" + assert report["scope"]["showUnlinked"] is checked + # minDegree matters just as much: showUnlinked alone still loses to `degree >= 1`. + assert report["scope"]["minDegree"] == (0 if checked else 1) + + +@requires_node +def test_a_renderer_created_after_leaving_the_graph_view_is_born_paused() -> None: + """The rAF leak this PR already fixed once, reached by a different route. + + ``/graph`` and both lazy scripts resolve asynchronously. Leaving Graph before they do runs + the pause while ``GRAPH_ENGINE`` is still null, so the pending callback would create and + start a renderer against a hidden pane that nothing ever pauses again. + """ + parked = _run_render(parked=True) + assert parked["created"] == 1 + assert parked["paused"] == 1, "a renderer created off-view keeps repainting forever" + + # On the view, the same path must not park a renderer the user is looking at. + live = _run_render(parked=False) + assert live["created"] == 1 + assert live["paused"] == 0 + + +def test_leaving_the_graph_view_records_the_pause_as_well_as_applying_it() -> None: + source = DASHBOARD.read_text(encoding="utf-8") + assert "if(v==='graph')graphEngineResume();else graphEnginePause()" in source + pause = source[source.index("function graphEnginePause()"):] + pause = pause[: pause.index("\nfunction graphInvalidateData")] + assert "GRAPH_ENGINE_PARKED=true" in pause + assert "GRAPH_ENGINE_PARKED=false" in pause + + # ── CSP, styling and lifecycle ────────────────────────────────────────────────────── From efa35a6744bd4a88a3b219e8a73fcb3e6000e7da Mon Sep 17 00:00:00 2001 From: Jaixii Date: Sun, 26 Jul 2026 17:47:41 -0400 Subject: [PATCH 44/82] fix(graph): rank communities, settle large galaxy graphs, follow the theme Three further findings from PR #74 review. Community IDs were assigned in raw payload order while graphRenderLegend() sorts communities by size and calls the largest "Cluster 1". Node colour indexes the palette by the ID itself, so whenever a smaller component appeared first the legend described one component with another's swatch. Components are now ranked by size before the IDs escape, matching the classic graphComputeCommunities(). Galaxy style held autoPauseRedraw(false) unconditionally, so a settled large graph repainted every node and link every frame forever. The starfield is the only paint force-graph cannot see; the classic path drops it past GPERF.large, so the same 600-node/2400-link signal now skips it and hands the redraw loop back to the vendor. Type colours resolved from hard-coded dark-theme constants, so switching to Light, Midnight, Solarized or Sepia moved the legend and controls while the canvas stayed dark. The engine cannot read CSS custom properties from a canvas, so the dashboard resolves --entity-* and supplies them through a new setThemeColors(), below style palettes and user overrides in priority. 1446 passed, 0 failed (+5 tests). ruff, externalize and manifest gates pass. Co-Authored-By: Claude Opus 5 --- engraphis/static/dashboard.js | 7 +- engraphis/static/engraphis-graph.js | 50 ++++++- tests/test_graph_engine_asset.py | 197 +++++++++++++++++++++++++++- 3 files changed, 244 insertions(+), 10 deletions(-) diff --git a/engraphis/static/dashboard.js b/engraphis/static/dashboard.js index fe26969..f20be54 100644 --- a/engraphis/static/dashboard.js +++ b/engraphis/static/dashboard.js @@ -510,6 +510,10 @@ function graphLoadColorPreferences(){ } function graphSaveColorPreferences(){try{localStorage.setItem(GRAPH_COLOR_KEY,JSON.stringify({palette:GCOLOR_PALETTE,colors:GCOLOR_OVERRIDES}))}catch(e){}} function graphTypeColor(type){if(GCOLOR_OVERRIDES[type])return GCOLOR_OVERRIDES[type];if(typeof GSTYLE!=='undefined'&&GSTYLE&&GSTYLE!=='classic'&&STYLE_PAL[GSTYLE]&&STYLE_PAL[GSTYLE][type])return STYLE_PAL[GSTYLE][type];return cssvar(ETYPE_TOKEN[type]||'--entity-concept',cssvar('--color-accent','#8c83e8'))} +/* The engine renders to a canvas, so it cannot read `--entity-*` itself the way the legend and + the controls do. Resolve the active theme's values here and hand them over; without this the + opt-in canvas keeps dark-theme node colours after a switch to Light/Solarized/Sepia. */ +function graphThemeTypeColors(){const colors={},fallback=cssvar('--color-accent','#8c83e8');Object.keys(ETYPE_TOKEN).forEach(type=>{colors[type]=cssvar(ETYPE_TOKEN[type],fallback)});return colors} function graphContrastColor(color){if(!graphValidColor(color))return cssvar('--color-canvas','#0e1014');const n=parseInt(color.slice(1),16),lum=.2126*(n>>16)+.7152*((n>>8)&255)+.0722*(n&255);return lum>150?'#111827':'#f8fafc'} const ETYPE_COLOR=new Proxy({},{get:(_,type)=>graphTypeColor(type)}); graphLoadColorPreferences(); @@ -614,6 +618,7 @@ function graphRenderEngine(data,fit,reheat){ engine.setSettings({...window.GSET}); engine.setStyle(typeof GSTYLE!=='undefined'?GSTYLE:'cyber'); engine.setColorBy(typeof GCOLORBY!=='undefined'?GCOLORBY:'community'); + engine.setThemeColors(graphThemeTypeColors()); engine.setPalette(typeof GCOLOR_PALETTE!=='undefined'?GCOLOR_PALETTE:'theme'); engine.setTypeColors(GCOLOR_OVERRIDES||{}); engine.setLayers(layers); @@ -1137,7 +1142,7 @@ function graphToggleFreeze(control){ function graphToggleLabels(control){window.GSET.labels=control.checked;if(GRAPH_ENGINE)GRAPH_ENGINE.setSettings({labels:control.checked});else if(FG)graphRender(false,false)} function graphRecolor(){ renderGraphColorControls(); - if(GRAPH_ENGINE){GRAPH_ENGINE.apply(engine=>{engine.setPalette(typeof GCOLOR_PALETTE!=='undefined'?GCOLOR_PALETTE:'theme');engine.setTypeColors(GCOLOR_OVERRIDES||{})},false,false);return} + if(GRAPH_ENGINE){GRAPH_ENGINE.apply(engine=>{engine.setThemeColors(graphThemeTypeColors());engine.setPalette(typeof GCOLOR_PALETTE!=='undefined'?GCOLOR_PALETTE:'theme');engine.setTypeColors(GCOLOR_OVERRIDES||{})},false,false);return} if(!FG)return; window.GCOL=graphReadThemeColors();graphRefreshNodeColors(); FG.linkColor(FG.linkColor());FG.linkWidth(FG.linkWidth());graphRedraw(); diff --git a/engraphis/static/engraphis-graph.js b/engraphis/static/engraphis-graph.js index 9a23a07..28ba123 100644 --- a/engraphis/static/engraphis-graph.js +++ b/engraphis/static/engraphis-graph.js @@ -55,6 +55,14 @@ opt-in engine uses the same cutoff rather than inventing a second large-graph signal. */ const PARTICLE_LINK_LIMIT = 800; + /* The classic renderer's large-graph signal (`GPERF` in dashboard.js, set from the rendered + data as `nodes>600 || links>2400`). Past it the classic path drops the galaxy starfield + outright — `if(GPERF.large)return` in graphStyleBackground — because repainting 110 stars + plus every node and link on every frame is what makes a big store unusable. The opt-in + engine reuses the same thresholds rather than inventing a second signal. */ + const LARGE_NODE_LIMIT = 600; + const LARGE_LINK_LIMIT = 2400; + function idOf(value) { return value && typeof value === 'object' ? value.id : value; } function nodeName(node) { return String(node.name || node.label || node.id || ''); } function linkEndpoint(link, side) { @@ -138,7 +146,7 @@ // otherwise fall back to connected-component BFS, as the dashboard does. if (nodes.length && nodes.every(n => typeof n.community === 'number')) return adj; const seen = new Set(); - let group = 0; + const groups = []; nodes.forEach(n => { if (seen.has(n.id)) return; // Read head instead of Array#shift: shift() is O(n) per pop, which turns this BFS @@ -148,11 +156,21 @@ seen.add(n.id); while (head < queue.length) { const id = queue[head++]; - const node = nodesById.get(id); - if (node) node.community = group; (clusterAdj[id] || []).forEach(next => { if (!seen.has(next)) { seen.add(next); queue.push(next); } }); } - group++; + // `queue` has accumulated the whole component by now, so it *is* the group. + groups.push(queue); + }); + /* Rank by size before the IDs become visible. `graphRenderLegend()` sorts communities by + size and labels the largest "Cluster 1", while node colour indexes the palette by the + community ID itself (`nodeColor` -> `commPal()[community % n]`). Assigning IDs in raw + node order therefore let the legend describe one component with another's swatch + whenever a smaller component happened to appear first in the payload. The classic + renderer sorts its components the same way (`graphComputeCommunities` in dashboard.js), + so largest == community 0 == palette slot 0 == "Cluster 1" on both paths. */ + groups.sort((a, b) => b.length - a.length); + groups.forEach((group, index) => { + group.forEach(id => { const node = nodesById.get(id); if (node) node.community = index; }); }); return adj; } @@ -267,13 +285,16 @@ // Named `styleName`, not `style`: scripts/externalize_dashboard_assets.py scans this // asset for runtime inline-style mutation with a text pattern, and a plain data field // by the shorter name reads as one. The longer name keeps that gate honest. - styleName: 'cyber', colorBy: 'community', palette: 'theme', overrides: {}, + styleName: 'cyber', colorBy: 'community', palette: 'theme', overrides: {}, themeColors: {}, settings: Object.assign({}, PRESETS.communities, { mode: 'communities', labels: false, flow: true, frozen: false }), minDegree: 1, showUnlinked: false, focusId: null, depth: 2, layers: { temporal: true, entity: true, causal: true, semantic: true, code: false }, path: null, asOf: null, ghost: true, sizeBy: 'degree', bridges: false, suggestions: false, collapse: 'auto' }; let raw = { nodes: [], links: [], suggestions: [] }, adj = {}, hilite = null, hoverSet = null, maxDeg = 1; let zoom = 1, collapsed = false; + /* Recomputed from the *rendered* data on every render, exactly as the classic path + recomputes GPERF — filters and focus can take a huge store down to a small view. */ + let large = false; let destroyed = false, running = true, fitTimer = 0, suspended = 0, pendingRender = null; let betweennessReady = false; const fg = ForceGraph()(el); @@ -293,7 +314,7 @@ to that change detection. Everywhere else, letting force-graph park the redraw is what keeps a settled graph off the CPU. */ function needsContinuousFrames() { - return !reduced() && state.styleName === 'galaxy'; + return !reduced() && state.styleName === 'galaxy' && !large; } /* Betweenness is the one analysis that is superlinear in the store size, and nothing in the default view consumes it — the bridge overlay and betweenness-sizing are both off. @@ -317,10 +338,16 @@ } } + /* Priority mirrors the classic renderer's graphTypeColor(): an explicit user override wins, + then a non-classic style's own palette, then the *active theme*. The theme tier is the + reason `themeColors` exists — it cannot be folded into `overrides`, which outrank + STYLE_PAL. The dashboard owns the CSS custom properties (`--entity-*`), so it supplies + the resolved values through setThemeColors() on every applyTheme()/graphRecolor(); + THEME_ETYPE stays only as the standalone-embed fallback for a caller that never does. */ function etypeColor(type) { if (state.overrides[type]) return state.overrides[type]; if (state.styleName !== 'classic' && STYLE_PAL[state.styleName] && STYLE_PAL[state.styleName][type]) return STYLE_PAL[state.styleName][type]; - return THEME_ETYPE[type] || '#8c83e8'; + return state.themeColors[type] || THEME_ETYPE[type] || '#8c83e8'; } function commPal() { return COMMUNITY_PALS[state.styleName] || COMMUNITY_PALS.classic; } function heatColor(node) { @@ -438,6 +465,11 @@ function styleBackground(ctx, scale) { if (state.styleName === 'galaxy') { + /* Matches the classic path's `if(GPERF.large)return`. Paired with the `large` term in + needsContinuousFrames(), this is what lets a big galaxy graph settle: the starfield + is the only paint force-graph cannot see, so once it is skipped there is nothing + left that requires a frame the vendor would not have scheduled itself. */ + if (large) return; const t = performance.now() / 1000; ctx.save(); ctx.globalCompositeOperation = 'lighter'; @@ -602,6 +634,7 @@ } const motion = !reduced(); const data = visible(); + large = data.nodes.length > LARGE_NODE_LIMIT || data.links.length > LARGE_LINK_LIMIT; const sizeMetric = n => state.sizeBy === 'betweenness' ? (n.betweenness || 0) : ((n.degree || 0) / Math.max(1, maxDeg)); data.nodes.forEach(n => { const base = (state.settings.size || 3); @@ -738,6 +771,9 @@ /* Rehydrating saved overrides is not a user edit, so it must not flip the palette selector to "custom" behind the user's back the way setTypeColor deliberately does. */ api.setTypeColors = map => { Object.assign(state.overrides, map || {}); refreshColors(); }; + /* The active theme's resolved `--entity-*` values. Replaced wholesale rather than merged: + a theme switch must not leave the previous theme's colour for a type the new one omits. */ + api.setThemeColors = map => { state.themeColors = map && typeof map === 'object' ? { ...map } : {}; refreshColors(); }; /* One render for a whole batch of setters — see `batch`. */ api.apply = (fn, fit, reheat) => { batch(fn, fit, reheat); }; api.setHighlight = id => { diff --git a/tests/test_graph_engine_asset.py b/tests/test_graph_engine_asset.py index d1daa21..10b0341 100644 --- a/tests/test_graph_engine_asset.py +++ b/tests/test_graph_engine_asset.py @@ -531,6 +531,44 @@ def test_influence_relations_do_not_merge_two_topics_into_one_community() -> Non assert report["bridges"] == 3 +@requires_node +def test_community_ids_are_ranked_by_size_so_the_legend_describes_the_right_nodes() -> None: + """Legend labels and canvas swatches must agree about which cluster is "Cluster 1". + + ``graphRenderLegend()`` sorts communities by size and calls the largest "Cluster 1", but + node colour indexes the palette by the community *id* (``commPal()[community % n]``). + Assigning ids in raw payload order therefore made the legend describe one component with + another's colour whenever a smaller component appeared first — which the payload order + alone decides. The classic ``graphComputeCommunities()`` sorts before assigning; so must + this. + """ + report = _run_node( + """ + // Payload order is deliberately worst-case: the singleton comes first, the largest + // component last, so raw iteration order and size order disagree completely. + const nodes = ['solo', 'm1', 'm2', 'a', 'b', 'c'].map(id => ({ id })); + const links = [ + { source: 'm1', target: 'm2' }, + { source: 'a', target: 'b' }, + { source: 'b', target: 'c' }, + ]; + I.communities(nodes, links); + const byId = {}; + nodes.forEach(n => { byId[n.id] = n.community; }); + emit({ byId, distinct: new Set(nodes.map(n => n.community)).size }); + """ + ) + assert report["distinct"] == 3 + # Largest component (3 nodes) owns palette slot 0, i.e. the legend's "Cluster 1". + assert report["byId"]["a"] == 0 + assert report["byId"]["b"] == 0 + assert report["byId"]["c"] == 0 + # Then the 2-node component, then the singleton — strictly by size, not by payload order. + assert report["byId"]["m1"] == 1 + assert report["byId"]["m2"] == 1 + assert report["byId"]["solo"] == 2 + + @requires_node def test_max_helper_survives_arrays_past_the_spread_limit() -> None: """``Math.max(...array)`` throws RangeError long before a store is unrenderable.""" @@ -593,6 +631,114 @@ def test_flow_particles_are_capped_on_a_large_relation_set() -> None: assert report["realistic"] == 0 +#: A canvas 2D stand-in that counts the fills the galaxy starfield performs. The engine wraps +#: ``onRenderFramePre`` in a try/catch, so a stub too thin to survive the real paint would read +#: as "no stars drawn"; the small-graph leg of the test below is what proves it is thick enough. +CANVAS_STUB = """ +let fills = 0; +const ctx = { + globalAlpha: 1, globalCompositeOperation: '', fillStyle: '', strokeStyle: '', lineWidth: 1, + save() {}, restore() {}, beginPath() {}, arc() {}, ellipse() {}, stroke() {}, + fill() { fills += 1; }, + createRadialGradient() { return { addColorStop() {} }; }, +}; +""" + + +@requires_node +def test_galaxy_stops_animating_once_the_graph_is_large() -> None: + """A settled graph must fall off the CPU, and galaxy was the one style that never did. + + The starfield lives in ``onRenderFramePre``, which force-graph's change detection cannot + see, so the engine holds ``autoPauseRedraw(false)`` for it — repainting every node and link + every frame, forever, even after particles and the simulation have stopped. The classic + path simply drops the starfield past ``GPERF.large`` (``if(GPERF.large)return``); with the + stars gone there is nothing left that needs a frame the vendor would not schedule itself. + """ + report = _run_engine( + CANVAS_STUB + + """ + const api = G.create(el, {}); + api.setStyle('galaxy'); + + api.setData(chain(40)); + const smallAutoPause = store.autoPauseRedraw; + fills = 0; store.onRenderFramePre(ctx, 1); + const smallStars = fills; + + // 3001 entities / 3000 relations — past the classic renderer's 600-node signal. + api.setData(chain(3000)); + const bigAutoPause = store.autoPauseRedraw; + fills = 0; store.onRenderFramePre(ctx, 1); + const bigStars = fills; + + // Style is what costs the frames, not size alone: cyber never asked for them. + api.setStyle('cyber'); + api.setData(chain(40)); + emit({ smallAutoPause, bigAutoPause, smallStars, bigStars, + cyberAutoPause: store.autoPauseRedraw }); + """ + ) + # Small galaxy graph: the animation is affordable, so the engine keeps driving frames. + assert report["smallAutoPause"] is False + assert report["smallStars"] > 0, "canvas stub never reached the starfield" + # Large galaxy graph: no starfield, and the redraw loop is handed back to force-graph. + assert report["bigStars"] == 0 + assert report["bigAutoPause"] is True, "a large galaxy graph repaints every frame forever" + assert report["cyberAutoPause"] is True + + +@requires_node +def test_type_colours_follow_the_active_theme_not_a_hard_coded_dark_palette() -> None: + """``applyTheme()`` recolours the canvas, but the engine had no theme to recolour to. + + The legend and controls read the ``--entity-*`` custom properties, so switching to Light, + Midnight, Solarized or Sepia moved them while the canvas kept the dark-theme constants — + an inconsistent palette and, on the light themes, poor contrast. The engine cannot read + CSS variables from a canvas, so the dashboard supplies the resolved values. + """ + report = _run_engine( + """ + const api = G.create(el, {}); + // setData first: the force-graph stand-in only starts answering graphData() once the + // engine has pushed data into it, where the real vendor seeds an empty graph. + // Linked, because the default scope hides degree-zero entities. + api.setData({ + nodes: [{ id: 'a', etype: 'person_or_concept' }, { id: 'b', etype: 'person_or_concept' }], + links: [{ source: 'a', target: 'b', layer: 'entity' }], + }); + api.setColorBy('type'); + api.setStyle('classic'); + // `store` holds the values handed to force-graph, so this is the node object the + // engine actually painted from — recoloured in place by refreshColors()/render(). + const colour = () => store.graphData.nodes[0].color; + + const fallback = colour(); + api.setThemeColors({ person_or_concept: '#112233' }); + const themed = colour(); + + // A style palette still outranks the theme, exactly as classic graphTypeColor() does. + api.setStyle('cyber'); + const styled = colour(); + + // ...and an explicit user override still outranks both. + api.setStyle('classic'); + api.setTypeColor('person_or_concept', '#abcdef'); + const overridden = colour(); + + // A theme with no entry for the type must not strand the previous theme's colour. + api.setThemeColors({}); + emit({ fallback, themed, styled, overridden, cleared: colour() }); + """ + ) + assert report["fallback"] == "#8c83e8" + assert report["themed"] == "#112233", "the engine ignores the active theme" + assert report["styled"] == "#ff3ea5" + assert report["overridden"] == "#abcdef" + # The override survives; only the theme tier was replaced. + assert report["cleared"] == "#abcdef" + + @requires_node def test_hovering_a_node_asks_for_a_redraw() -> None: """A highlight nobody repaints is invisible. @@ -651,16 +797,35 @@ def test_unlinked_entities_are_shown_only_when_the_engine_is_told_to() -> None: const start = src.indexOf('function graphRenderEngine('); const slice = src.slice(start, src.indexOf('/* Nav away from the graph view', start)); -const log = { created: 0, paused: 0, seeded: 0, scope: null, error: null }; +/* The theme-colour lookup is sliced verbatim too, not stubbed: the property under test is + that the dashboard resolves the *active* CSS custom properties and hands them over, so + faking the resolver would assert nothing. Only `getComputedStyle` below is synthetic. */ +const between = (from, to) => src.slice(src.indexOf(from), src.indexOf(to, src.indexOf(from))); +const themeSrc = between('const ETYPE_TOKEN=', 'const GRAPH_PALETTES=') + + between('function cssvar(', 'function graphValidColor(') + + between('function graphThemeTypeColors(', 'function graphContrastColor('); + +/* A stand-in for a non-dark theme: every --entity-* token differs from the engine's + hard-coded THEME_ETYPE constants, so a renderer that ignored these would be visible. */ +const THEME_VARS = { + '--entity-concept': '#112233', '--entity-mention': '#223344', '--entity-hashtag': '#334455', + '--entity-email': '#445566', '--entity-organization': '#556677', '--entity-location': '#667788', + '--color-accent': '#778899', +}; +globalThis.getComputedStyle = () => ({ getPropertyValue: name => THEME_VARS[name] || '' }); + +const log = { created: 0, paused: 0, seeded: 0, scope: null, themeColors: null, error: null }; const checkbox = { checked: scenario.showUnlinked }; const element = { classList: { toggle() {} }, setAttribute() {}, set textContent(value) {} }; globalThis.document = { getElementById: id => (id === 'graph-show-iso' ? checkbox : element), querySelectorAll: () => [], + body: {}, }; const engine = { setSettings() {}, setStyle() {}, setColorBy() {}, setPalette() {}, setTypeColors() {}, setLayers() {}, setScope(patch) { log.scope = patch; }, + setThemeColors(map) { log.themeColors = map; }, setData(data) { log.seeded = data.nodes.length; }, }; const api = { @@ -685,7 +850,7 @@ def test_unlinked_entities_are_shown_only_when_the_engine_is_told_to() -> None: log.error = String((error && error.message) || error); }; -const graphRenderEngine = new Function(slice + '\\nreturn graphRenderEngine;')(); +const graphRenderEngine = new Function(themeSrc + slice + '\\nreturn graphRenderEngine;')(); const rendered = graphRenderEngine({ nodes: [{ id: 'a' }, { id: 'b' }, { id: 'lonely' }], links: [{ source: 'a', target: 'b' }], @@ -731,6 +896,34 @@ def test_dashboard_tells_the_engine_whether_to_show_unlinked_entities(checked: b assert report["scope"]["minDegree"] == (0 if checked else 1) +@requires_node +def test_dashboard_hands_the_engine_the_active_themes_entity_colours() -> None: + """The other half of the theme fix: the engine can only use what it is given.""" + report = _run_render() + + assert report["themeColors"] is not None, "the engine never learns the active theme" + # Resolved from the stubbed --entity-* custom properties, not from any JS constant. + assert report["themeColors"]["person_or_concept"] == "#112233" + assert report["themeColors"]["organization"] == "#556677" + # Every type the legend can show must be covered, or the canvas falls back per type. + assert set(report["themeColors"]) == { + "person_or_concept", "mention", "hashtag", "email", "organization", "location", + } + + +def test_a_theme_switch_repaints_the_opt_in_canvas() -> None: + """``applyTheme()`` is the only place a theme change is observable. + + It already calls ``graphRecolor()``; that path has to reach the engine, or the canvas keeps + the previous theme until the next full graph render. + """ + source = DASHBOARD.read_text(encoding="utf-8") + assert "if(typeof graphRecolor==='function')graphRecolor()" in source + recolor = source[source.index("function graphRecolor()"):] + recolor = recolor[: recolor.index("\nfunction graphFit")] + assert "engine.setThemeColors(graphThemeTypeColors())" in recolor + + @requires_node def test_a_renderer_created_after_leaving_the_graph_view_is_born_paused() -> None: """The rAF leak this PR already fixed once, reached by a different route. From f32edb2d806887a2b064de5d023bdc81667153b0 Mon Sep 17 00:00:00 2001 From: Jaixii Date: Sun, 26 Jul 2026 18:30:40 -0400 Subject: [PATCH 45/82] fix(graph): close the remaining review threads on the opt-in engine Six findings from the PR #74 review, all cases where the opt-in renderer diverged from the classic path it is meant to replace. - Relation labels: the dashboard's Labels checkbox drives two label layers on the classic path, but the engine configured no linkCanvasObject, so ticking it painted entity names only and a relation could be read only by hovering it. Paint them, with the classic gates (zoom, dense-graph). - zoomToNode: graphFocus() treats a false return as "run the recovery path". The engine answered from raw.nodes, which keeps the coordinates force-graph left on a node, so an entity hidden by a scope filter or by the auto-collapsed cluster view still reported success and the camera moved to nothing. Expand a collapsed view, then verify against the data force-graph is actually holding. - Reseeding: render() called graphData() unconditionally with newly allocated arrays, so Style, Color by, Labels and Flow each reset the d3 alpha and restarted the layout. Reseed only when the visible set really changed, and invalidate the paint when it did not. - Cooldown: nothing overrode force-graph's 15s default simulation window, so a large store kept simulating (and repainting) far past the 1.1s/80 ticks the classic path allows. Mirror its size-dependent bounds. - Dense graphs: curvature and arrowheads stayed on past the classic GPERF.dense threshold, paying a bezier and a filled triangle per relation across thousands of links. - Community colours: the cluster legend swatches are CSS (.graph-cluster-N) encoding the Cyber palette, but the engine's Cyber and Solar palettes were ordered differently from dashboard.js, so on the default style the legend described each of the first clusters with another cluster's colour. Each is covered by a test that fails without the change. Co-Authored-By: Claude Opus 5 --- engraphis/static/engraphis-graph.js | 141 ++++++++++++-- tests/test_graph_engine_asset.py | 282 ++++++++++++++++++++++++++++ 2 files changed, 411 insertions(+), 12 deletions(-) diff --git a/engraphis/static/engraphis-graph.js b/engraphis/static/engraphis-graph.js index 28ba123..6499d78 100644 --- a/engraphis/static/engraphis-graph.js +++ b/engraphis/static/engraphis-graph.js @@ -40,11 +40,17 @@ contrast: { person_or_concept: '#0072b2', mention: '#009e73', hashtag: '#e69f00', email: '#56b4e9', organization: '#cc79a7', location: '#d55e00' } }; const THEME_ETYPE = { person_or_concept: '#8c83e8', mention: '#5aafb3', hashtag: '#d7a84b', email: '#6f9fd8', organization: '#58b882', location: '#df7478' }; + /* Community colour is the *palette slot*, not the node: `nodeColor` indexes this by the + community id, and communities are numbered by size (largest == 0). The legend beside the + canvas paints its swatches from `.graph-cluster-N` in dashboard.css, which encodes the + Cyber palette — the default style — slot for slot. These arrays must therefore stay + byte-identical to `COMMUNITY_PALS` in dashboard.js, or "Cluster 1" gets one colour in the + legend and another on the canvas. Ordering is load-bearing; this is not free-choice art. */ const COMMUNITY_PALS = { classic: ['#8c83e8', '#5aafb3', '#d7a84b', '#6f9fd8', '#58b882', '#df7478', '#b07de0', '#4fb0a0', '#e0894a', '#7c9be0', '#e06a9a', '#9ac25a'], galaxy: ['#b789ff', '#7bb4ff', '#66e0d0', '#ffcf6b', '#ff7ea8', '#8aa2ff', '#c98bff', '#5ad0e0', '#ffa0d0', '#9d7bff', '#6ad0b0', '#ffb060'], - solar: ['#ffb454', '#3fd2c7', '#ffd68a', '#5b9bff', '#ff8f6b', '#8ea8ff', '#ffc98a', '#4fc0b0', '#ff9f5b', '#7fb0ff', '#ffd0a0', '#5ad0c0'], - cyber: ['#ff3ea5', '#22e0ff', '#b6ff3c', '#ffe14d', '#8b7bff', '#ff5c7a', '#3cffd0', '#ff9ae0', '#5ce0ff', '#d0ff3c', '#ffb03c', '#a06bff'] + solar: ['#ffb454', '#5b9bff', '#3fd2c7', '#ffd68a', '#ff8f6b', '#8ea8ff', '#ffc24a', '#6ac0d0', '#ff9f7a', '#7ab0ff', '#e0b050', '#5fd0b0'], + cyber: ['#22e0ff', '#ff3ea5', '#b6ff3c', '#ffe14d', '#8b7bff', '#ff5c7a', '#3affd0', '#ff7be0', '#7affea', '#c0ff4a', '#5c9bff', '#ff9b3c'] }; const GRAPH_HEAT = ['#3f7bff', '#6a5cff', '#a24bff', '#e0479f', '#ff6b6b', '#ffc23d']; @@ -63,6 +69,18 @@ const LARGE_NODE_LIMIT = 600; const LARGE_LINK_LIMIT = 2400; + /* The classic renderer's *dense* signal (`GPERF.dense`, `links>1500` in dashboard.js). Past + it the classic path turns off the two per-edge costs that scale with the link count and + buy nothing at that density: link curvature (a quadratic bezier per relation instead of a + straight line) and the directional arrowhead (a filled triangle per relation, recomputed + every frame). Relation labels get the same treatment unless one node is highlighted. Same + thresholds and same behaviour here — a second signal would only drift. */ + const DENSE_LINK_LIMIT = 1500; + + /* Relation labels are the noisiest layer on the canvas, so — exactly as the classic + `linkCanvasObject` does — they only appear once the user has zoomed in past this scale. */ + const LINK_LABEL_MIN_SCALE = 2.4; + function idOf(value) { return value && typeof value === 'object' ? value.id : value; } function nodeName(node) { return String(node.name || node.label || node.id || ''); } function linkEndpoint(link, side) { @@ -294,7 +312,11 @@ let zoom = 1, collapsed = false; /* Recomputed from the *rendered* data on every render, exactly as the classic path recomputes GPERF — filters and focus can take a huge store down to a small view. */ - let large = false; + let large = false, dense = false; + /* The node/link arrays last handed to force-graph. Seeding is not free: the vendor copies + the data in and d3 resets the simulation alpha to 1, so a paint-only change would restart + the whole layout. See `sameData`/`render`. */ + let seeded = null; let destroyed = false, running = true, fitTimer = 0, suspended = 0, pendingRender = null; let betweennessReady = false; const fg = ForceGraph()(el); @@ -626,6 +648,61 @@ invalidate(); } + /* The dashboard's **Labels** checkbox turns on *both* label layers on the classic path: + entity names (painted by styleNode) and relation names (a `linkCanvasObject`, drawn + 'after' the line so it sits on top of it). Without this second half the checkbox silently + did half its job under `?graph-engine=next` and a relation name could only be read by + hovering one edge at a time. Same gates as classic graphRender(): zoomed in past + LINK_LABEL_MIN_SCALE, the relation actually carries a label, and — on a dense graph — + only while something is highlighted, so thousands of overlapping strings are never + painted at once. Canvas text is not an HTML sink, so the raw label is drawn here; the + escaped copy is for `linkLabel`, whose tooltip *is* one. */ + function applyLinkLabels() { + if (!fg.linkCanvasObject || !fg.linkCanvasObjectMode) return; + if (!state.settings.labels) { fg.linkCanvasObjectMode(() => undefined); return; } + fg.linkCanvasObjectMode(() => 'after').linkCanvasObject((link, ctx, scale) => { + if (!link || !link.label || scale < LINK_LABEL_MIN_SCALE) return; + if (dense && !hilite) return; + const source = link.source, target = link.target; + if (!source || !target || typeof source !== 'object' || typeof target !== 'object') return; + if (!Number.isFinite(source.x) || !Number.isFinite(source.y)) return; + if (!Number.isFinite(target.x) || !Number.isFinite(target.y)) return; + if (link.ghost) return; + ctx.font = ((state.settings.font || 12) * 0.82) / scale + 'px system-ui, sans-serif'; + ctx.fillStyle = 'rgba(232,236,245,.62)'; + ctx.textAlign = 'center'; + ctx.textBaseline = 'middle'; + ctx.fillText(String(link.label), (source.x + target.x) / 2, (source.y + target.y) / 2); + ctx.textAlign = 'left'; + }); + } + + /* Does this render show the same entities and relations as the one force-graph is already + holding? Compared by identity of the *view*, not of the payload: `visible()` allocates + fresh arrays every call (and `collapsedData` fresh cluster nodes), so an object compare + would report a change for Style, Color by, Labels and Flow — none of which move a node. */ + function sameData(previous, next) { + if (!previous) return false; + if (previous.nodes.length !== next.nodes.length) return false; + if (previous.links.length !== next.links.length) return false; + for (let i = 0; i < next.nodes.length; i++) { + if (previous.nodes[i].id !== next.nodes[i].id) return false; + } + for (let i = 0; i < next.links.length; i++) { + const a = previous.links[i], b = next.links[i]; + if (linkEndpoint(a, 'source') !== linkEndpoint(b, 'source')) return false; + if (linkEndpoint(a, 'target') !== linkEndpoint(b, 'target')) return false; + if ((a.layer || '') !== (b.layer || '')) return false; + if (!a.suggested !== !b.suggested) return false; + if (!a.ghost !== !b.ghost) return false; + } + return true; + } + + /* Large graphs settle harder, exactly as the classic path does (`GPERF.large?.055:.035`). + Shared so reheat() and freeze() cannot drift back to the small-graph constant. */ + function alphaDecay() { return large ? 0.055 : 0.035; } + function render(fit, reheat) { if (destroyed) return; if (suspended) { @@ -633,8 +710,14 @@ return; } const motion = !reduced(); - const data = visible(); + const next = visible(); + /* Reuse the arrays force-graph already holds when the view is unchanged: the sizing and + colouring pass below must write onto the objects the vendor is painting from, and the + collapsed view hands out freshly built cluster nodes on every call. */ + const reused = sameData(seeded, next); + const data = reused ? seeded : next; large = data.nodes.length > LARGE_NODE_LIMIT || data.links.length > LARGE_LINK_LIMIT; + dense = data.links.length > DENSE_LINK_LIMIT; const sizeMetric = n => state.sizeBy === 'betweenness' ? (n.betweenness || 0) : ((n.degree || 0) / Math.max(1, maxDeg)); data.nodes.forEach(n => { const base = (state.settings.size || 3); @@ -645,13 +728,22 @@ n.stroke = contrastOn(n.color); }); applyChrome(); - fg.graphData(data); + if (!reused) { fg.graphData(data); seeded = data; } applyForces(); fg.autoPauseRedraw(!needsContinuousFrames()); - if (fg.d3AlphaDecay) fg.d3AlphaDecay(0.035); - if (fg.d3VelocityDecay) fg.d3VelocityDecay(0.38); - if (fg.linkCurvature) fg.linkCurvature((PRESETS[state.settings.mode] || PRESETS.compact).curve || 0); - fg.linkDirectionalArrowLength(2.5).linkDirectionalArrowRelPos(1); + /* Bound the simulation the way the classic path does. Without these force-graph keeps its + 15-second default window, so every load and every reheat of a large store runs the + layout — and repaints every node and link — for more than ten seconds longer. */ + if (fg.cooldownTime) fg.cooldownTime(motion ? (large ? 1100 : 2200) : 0); + if (fg.cooldownTicks) fg.cooldownTicks(motion ? (large ? 80 : 160) : 1); + if (fg.warmupTicks) fg.warmupTicks(motion ? (large ? 18 : 40) : 45); + if (fg.d3AlphaDecay) fg.d3AlphaDecay(alphaDecay()); + if (fg.d3VelocityDecay) fg.d3VelocityDecay(large ? 0.45 : 0.38); + if (fg.linkCurvature) { + fg.linkCurvature(dense ? 0 : ((PRESETS[state.settings.mode] || PRESETS.compact).curve || 0)); + } + fg.linkDirectionalArrowLength(dense ? 0 : 2.5).linkDirectionalArrowRelPos(1); + applyLinkLabels(); if (fg.linkDirectionalParticles) { const flowing = state.settings.flow !== false && motion @@ -666,6 +758,9 @@ } if (reheat && motion && !state.settings.frozen && fg.d3ReheatSimulation) fg.d3ReheatSimulation(); if ((state.settings.frozen || !motion) && fg.d3AlphaDecay) { /* keep painting, stop layout */ fg.d3AlphaDecay(1); } + /* Nothing was reseeded, so force-graph's own change detection saw no reason to repaint — + but Style, Color by and Labels all just changed how the *same* data must be drawn. */ + if (reused) invalidate(); if (fit) { clearTimeout(fitTimer); fitTimer = setTimeout(() => { if (!destroyed) fg.zoomToFit(motion ? 600 : 0, 40); }, motion ? 320 : 0); @@ -741,6 +836,10 @@ const suggestions = (Array.isArray(data && data.suggestions) ? data.suggestions : []) .map(link => Object.assign({}, link, { source: linkEndpoint(link, 'source'), target: linkEndpoint(link, 'target') })) .filter(link => link.source != null && link.target != null); + /* A fresh payload means fresh node objects, so the cached seed is stale even when the + ids are identical — force-graph must be re-pointed at the new objects or the render + below would style ones nobody is painting from. */ + seeded = null; raw = { nodes, links, suggestions }; adj = communities(raw.nodes, raw.links); const deg = {}; @@ -789,19 +888,36 @@ api.reheat = () => { if (destroyed || reduced()) return; raw.nodes.forEach(n => { n.fx = undefined; n.fy = undefined; }); - if (fg.d3ReheatSimulation) { fg.d3AlphaDecay(0.035); fg.d3ReheatSimulation(); } + if (fg.d3ReheatSimulation) { fg.d3AlphaDecay(alphaDecay()); fg.d3ReheatSimulation(); } }; api.freeze = on => { state.settings.frozen = on; if (on) { fg.d3Force('charge').strength(0); fg.d3AlphaDecay(1); return; } applyForces(); if (reduced()) return; - fg.d3AlphaDecay(0.035); + fg.d3AlphaDecay(alphaDecay()); if (fg.d3ReheatSimulation) fg.d3ReheatSimulation(); }; + /* Returning `false` is not a failure: it is the signal the dashboard's graphFocus() uses to + run its recovery path ("show unlinked", then retry, then say so). Reporting success for an + entity that is not on the canvas is therefore worse than reporting failure — the user gets + a camera move to nothing and no explanation. Two ways that happened: the auto-collapsed + view paints only `cluster-*` bubbles, and any filtered-out node keeps the x/y force-graph + left on it from an earlier render, so "found in `raw.nodes` with finite coordinates" was + never evidence of visibility. Expand a collapsed view first — focusing a named entity is + an explicit request to see it — then confirm against the data force-graph is holding. */ api.zoomToNode = id => { + if (destroyed) return false; const n = raw.nodes.find(x => x.id === id); - if (!n || !Number.isFinite(n.x) || !Number.isFinite(n.y)) return false; + if (!n) return false; + if (collapsed) { + collapsed = false; + state.collapse = false; + render(false, true); + if (opts.onCollapseChange) opts.onCollapseChange(false); + } + const shown = ((fg.graphData() || {}).nodes || []).some(node => node && node.id === id); + if (!shown || !Number.isFinite(n.x) || !Number.isFinite(n.y)) return false; const duration = reduced() ? 0 : 500; fg.centerAt(n.x, n.y, duration); fg.zoom(3, duration); @@ -872,6 +988,7 @@ } catch (e) { /* teardown is best-effort: never let it block a view change */ } raw = { nodes: [], links: [], suggestions: [] }; adj = {}; + seeded = null; hilite = null; hoverSet = null; }; diff --git a/tests/test_graph_engine_asset.py b/tests/test_graph_engine_asset.py index 10b0341..773297d 100644 --- a/tests/test_graph_engine_asset.py +++ b/tests/test_graph_engine_asset.py @@ -951,6 +951,288 @@ def test_leaving_the_graph_view_records_the_pause_as_well_as_applying_it() -> No assert "GRAPH_ENGINE_PARKED=false" in pause +#: Force-graph resolves each link's ``source``/``target`` from an id to the node object once it +#: owns the data, and the paint callbacks read ``.x``/``.y`` off those objects. The recording +#: stand-in stores the arrays untouched, so a test that wants to *drive* a link painter has to +#: do that resolution — and give the nodes coordinates — itself. +LAY_OUT = """ +const layOut = () => { + const data = store.graphData; + const byId = new Map(data.nodes.map(n => [n.id, n])); + data.nodes.forEach((n, i) => { n.x = i * 10; n.y = i; }); + data.links.forEach(l => { + const s = byId.get(l.source && l.source.id !== undefined ? l.source.id : l.source); + const t = byId.get(l.target && l.target.id !== undefined ? l.target.id : l.target); + if (s) l.source = s; + if (t) l.target = t; + }); + return data; +}; +let painted = []; +const linkCtx = { + font: '', fillStyle: '', textAlign: '', textBaseline: '', + fillText(text) { painted.push(String(text)); }, +}; +const paintLinks = (scale, links) => { + painted = []; + const mode = store.linkCanvasObjectMode ? store.linkCanvasObjectMode() : undefined; + const draw = store.linkCanvasObject; + if (mode === 'after' && draw) (links || store.graphData.links).forEach(l => draw(l, linkCtx, scale)); + return painted.slice(); +}; +""" + + +@requires_node +def test_relation_labels_are_painted_when_the_labels_box_is_ticked() -> None: + """**Labels** turns on two label layers on the classic path; the engine only had one. + + ``graphToggleLabels`` forwards the checkbox straight to ``setSettings({labels})``, and the + classic renderer answers it with *both* entity names and a ``linkCanvasObject`` that paints + each ``link.label``. The opt-in engine configured no link painter at all, so relation names + silently disappeared under ``?graph-engine=next`` and could only be read by hovering one + edge at a time. + """ + report = _run_engine( + LAY_OUT + + """ + const api = G.create(el, { reducedMotion: () => true }); + api.setData({ + nodes: [{ id: 'a' }, { id: 'b' }], + links: [{ source: 'a', target: 'b', layer: 'entity', label: 'mentions' }], + }); + layOut(); + const unticked = paintLinks(4); + api.setSettings({ labels: true }); + const ticked = paintLinks(4); + // Relation labels are the noisiest layer: they stay off until the user zooms in. + const zoomedOut = paintLinks(1); + emit({ unticked, ticked, zoomedOut }); + """ + ) + assert report["unticked"] == [] + assert report["ticked"] == ["mentions"], "the Labels checkbox never paints relation names" + assert report["zoomedOut"] == [] + + +@requires_node +def test_focusing_an_entity_the_canvas_is_not_showing_does_not_report_success() -> None: + """``zoomToNode`` is the dashboard's visibility oracle, and it was answering from memory. + + ``graphFocus`` treats ``false`` as "offer the recovery path" — tick *Show unlinked*, retry, + and otherwise say *Entity not in view*. The engine answered from ``raw.nodes``, which keeps + the coordinates force-graph left on a node from an earlier render, so a node hidden by the + auto-collapsed view (only ``cluster-*`` bubbles are drawn below zoom 0.55) or by a scope + filter still reported success — the camera moved to nothing and the user got no explanation. + """ + report = _run_engine( + """ + const collapses = []; + const api = G.create(el, { + reducedMotion: () => true, onCollapseChange: value => collapses.push(value), + }); + api.setData({ + nodes: [{ id: 'a' }, { id: 'b' }, { id: 'c' }, { id: 'lonely' }], + links: [{ source: 'a', target: 'b' }, { source: 'b', target: 'c' }], + }); + const shownIds = () => (store.graphData.nodes || []).map(n => n.id); + // Everything visible once, so every entity carries real coordinates from here on. + api.setScope({ showUnlinked: true, minDegree: 0 }); + store.graphData.nodes.forEach((n, i) => { n.x = i * 10; n.y = i; }); + + // 1. Hidden by the scope filter, but still remembered with valid coordinates. + api.setScope({ showUnlinked: false, minDegree: 1 }); + const filtered = { found: api.zoomToNode('lonely'), shown: shownIds() }; + + // 2. Hidden by the collapsed view, which paints cluster bubbles instead of entities. + api.setCollapse(true); + const whileCollapsed = shownIds(); + const focused = api.zoomToNode('c'); + emit({ + filtered, whileCollapsed, focused, collapses, + afterFocus: shownIds(), collapsed: api.state().collapsed, + }); + """ + ) + # A filtered-out entity is not in view, so the dashboard must be told to recover. + assert report["filtered"]["found"] is False, "a filtered-out entity reported as visible" + assert "lonely" not in report["filtered"]["shown"] + # A collapsed view really is showing only bubbles... + assert report["whileCollapsed"] == ["cluster-0"] + # ...so focusing a named entity has to expand it rather than claim it is already on screen. + assert report["focused"] is True + assert report["collapsed"] is False + assert "c" in report["afterFocus"], "the entity is still not on the canvas" + assert report["collapses"][-1] is False, "the dashboard was never told the view expanded" + + +@requires_node +def test_appearance_only_changes_do_not_restart_the_layout() -> None: + """Style, Color by, Labels and Flow repaint the graph; they must not re-run it. + + ``visible()`` allocates fresh arrays on every call, and force-graph treats any ``graphData`` + call as a data update: it re-copies the nodes and d3 resets the simulation alpha to 1. So + every appearance-only setter threw the settled layout away and made the whole graph move. + The classic renderer guards the same seed with ``if(dataChanged)FG.graphData(data)``. + """ + report = _run_engine( + """ + const api = G.create(el, { reducedMotion: () => true }); + const nodes = [{ id: 'lonely', etype: 'organization' }], links = []; + for (let i = 0; i < 12; i++) nodes.push({ id: 'n' + i, etype: 'person_or_concept' }); + for (let i = 0; i < 11; i++) links.push({ source: 'n' + i, target: 'n' + (i + 1) }); + api.setData({ nodes, links }); + const seeded = calls.graphData; + const before = store.graphData.nodes[0].color; + const repaintsBefore = calls.nodeCanvasObject; + + api.setStyle('galaxy'); + api.setColorBy('type'); + api.setSettings({ labels: true }); + api.setSettings({ flow: false }); + const paintOnly = calls.graphData; + const recoloured = store.graphData.nodes[0].color; + const repaintsAfter = calls.nodeCanvasObject; + + // A genuine change to the visible set still has to reach force-graph. + api.setScope({ showUnlinked: true, minDegree: 0 }); + emit({ + seeded, paintOnly, afterScope: calls.graphData, before, recoloured, + repaintsBefore, repaintsAfter, shown: store.graphData.nodes.length, + }); + """ + ) + assert report["paintOnly"] == report["seeded"], "an appearance change restarted the layout" + assert report["afterScope"] > report["seeded"], "a real view change never reached the canvas" + assert report["shown"] == 13 + # Skipping the reseed must not mean skipping the paint. + assert report["recoloured"] != report["before"] + assert report["repaintsAfter"] > report["repaintsBefore"] + + +@requires_node +def test_simulation_time_is_bounded_on_a_large_graph() -> None: + """force-graph's default cooldown is 15 seconds; nothing here was overriding it. + + The classic path caps a large graph at 1.1s / 80 ticks precisely because running the layout + — and therefore repainting every node and link — for the full default window is what makes a + big store feel broken on load and after every reheat. + """ + report = _run_engine( + """ + const api = G.create(el, {}); + api.setData(chain(40)); + const small = { + time: store.cooldownTime, ticks: store.cooldownTicks, warmup: store.warmupTicks, + alpha: store.d3AlphaDecay, velocity: store.d3VelocityDecay, + }; + // 3001 entities / 3000 relations — past the classic renderer's 600-node signal. + api.setData(chain(3000)); + const big = { + time: store.cooldownTime, ticks: store.cooldownTicks, warmup: store.warmupTicks, + alpha: store.d3AlphaDecay, velocity: store.d3VelocityDecay, + }; + const still = G.create(el, { reducedMotion: () => true }); + still.setData(chain(40)); + emit({ + small, big, + reduced: { time: store.cooldownTime, ticks: store.cooldownTicks }, + }); + """ + ) + assert report["small"]["time"] == 2200 + assert report["small"]["ticks"] == 160 + # The number this guards: the vendor default left a 3k-relation store simulating for 15s. + assert report["big"]["time"] == 1100 + assert report["big"]["ticks"] == 80 + assert report["big"]["warmup"] == 18 + # A large graph also settles harder, exactly as GPERF.large does on the classic path. + assert report["big"]["alpha"] > report["small"]["alpha"] + assert report["big"]["velocity"] > report["small"]["velocity"] + # Reduced motion asks for a static layout, not a shorter animation. + assert report["reduced"]["time"] == 0 + assert report["reduced"]["ticks"] == 1 + + +@requires_node +def test_curves_arrows_and_relation_labels_are_dropped_on_a_dense_graph() -> None: + """Three per-edge costs the classic path turns off past ``GPERF.dense`` (links > 1500). + + A curved link is a quadratic bezier instead of a straight line, an arrowhead is a filled + triangle, and a relation label is a text layout — each per relation, each every frame. At + this density they are unreadable anyway, so the classic renderer pays for none of them. + """ + report = _run_engine( + LAY_OUT + + """ + const api = G.create(el, { reducedMotion: () => true }); + api.setSettings({ labels: true }); + + api.setData(chain(1500)); + const atLimit = { + curve: store.linkCurvature, arrow: store.linkDirectionalArrowLength, + }; + + api.setData(chain(1501)); + const overLimit = { + curve: store.linkCurvature, arrow: store.linkDirectionalArrowLength, + }; + // One laid-out relation is enough to drive the label painter at this size. + const data = layOut(); + data.links[0].label = 'mentions'; + const denseUnhighlighted = paintLinks(4, [data.links[0]]); + store.onNodeHover(data.nodes[0]); + const denseHighlighted = paintLinks(4, [data.links[0]]); + emit({ atLimit, overLimit, denseUnhighlighted, denseHighlighted }); + """ + ) + # 1500 links is the classic threshold itself, so nothing is dropped yet. + assert report["atLimit"]["curve"] == 0.12 + assert report["atLimit"]["arrow"] == 2.5 + assert report["overLimit"]["curve"] == 0 + assert report["overLimit"]["arrow"] == 0 + # Relation labels come back for the one neighbourhood the user is actually pointing at. + assert report["denseUnhighlighted"] == [] + assert report["denseHighlighted"] == ["mentions"] + + +def _community_palettes(source: str) -> dict: + """Parse a ``COMMUNITY_PALS`` literal out of either renderer.""" + # Anchor on the declaration: both files also name the table in prose comments. + match = re.search(r"COMMUNITY_PALS\s*=\s*\{", source) + assert match is not None, "COMMUNITY_PALS is not declared here" + block = source[match.end():source.index("};", match.end())] + return { + name: re.findall(r"#[0-9a-fA-F]{3,8}", body) + for name, body in re.findall(r"(\w+)\s*:\s*\[([^\]]*)\]", block) + } + + +def test_community_colours_match_the_dashboard_and_the_legend_swatches() -> None: + """The cluster legend is painted from CSS, so palette *order* is a contract, not a taste. + + ``graphRenderLegend`` sorts communities by size and gives the largest a + ``.graph-cluster-0`` swatch, while the canvas colours that same community with palette slot + 0. The swatch colours live in ``dashboard.css`` and encode the Cyber palette — the default + style — so a renderer whose slot 0 is a different colour makes the legend describe cluster 1 + with cluster 2's colour, on the default style, for every workspace. + """ + engine = _community_palettes(ASSET.read_text(encoding="utf-8")) + classic = _community_palettes(DASHBOARD.read_text(encoding="utf-8")) + assert engine, "COMMUNITY_PALS could not be parsed out of the engine" + assert engine == classic, "the opt-in renderer paints communities a different colour" + + swatches = dict( + re.findall(r"\.graph-cluster-(\d+)\{background:(#[0-9a-fA-F]{3,8})\}", + CSS.read_text(encoding="utf-8")) + ) + assert swatches, "the cluster legend swatches are missing from the stylesheet" + for index, colour in sorted(swatches.items()): + assert engine["cyber"][int(index)].lower() == colour.lower(), ( + f"legend swatch {index} does not match the canvas colour for that cluster" + ) + + # ── CSP, styling and lifecycle ────────────────────────────────────────────────────── From b17ec4580a3ee87e3e98668badc128d7ee30c8b8 Mon Sep 17 00:00:00 2001 From: Jaixii Date: Sun, 26 Jul 2026 18:55:58 -0400 Subject: [PATCH 46/82] fix(graph): reheat the simulation when a physics slider moves MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Under ?graph-engine=next the Repel/Link/Gravity/Size sliders appeared dead. dashboard.js::graphSet routes them through api.setSettings, which only asked render() for a reheat when `mode` was present. applyForces() writes the new charge / link / forceX-forceY / collide values straight into the simulation force-graph is already running, and a settled graph sits at alpha~0 — so the new forces were installed and nothing moved until the user found the Reheat button. `size` is affected too: it feeds d3.forceCollide. The classic branch of that same function does the opposite — it treats `repel|link|gravity|size` as a layout change and reheats unless the user asked for reduced motion. setSettings now matches that set (plus `mode`, which swaps the whole force arrangement); render() already carries the reduced-motion exemption, so it is honoured for free. Appearance-only settings (font, link width, label density, labels, flow) still must not reheat: restarting the layout because a label got bigger throws away the arrangement being read. The regression test drives the API against the force-graph stand-in and counts d3ReheatSimulation() calls per key. Pre-fix it reported {repel: 0, link: 0, gravity: 0, size: 0, mode: 1}. Co-Authored-By: Claude Opus 5 --- engraphis/static/engraphis-graph.js | 19 +++++++-- tests/test_graph_engine_asset.py | 61 +++++++++++++++++++++++++++-- 2 files changed, 74 insertions(+), 6 deletions(-) diff --git a/engraphis/static/engraphis-graph.js b/engraphis/static/engraphis-graph.js index 6499d78..e134625 100644 --- a/engraphis/static/engraphis-graph.js +++ b/engraphis/static/engraphis-graph.js @@ -349,8 +349,9 @@ /* Apply a batch of setters with exactly one render at the end. Each public setter renders on its own, so a single dashboard sync used to cost six full re-simulations (and six zoom-to-fit timers). The caller also states the intent explicitly, because the merged - intent of the individual setters is not the caller's: `setSettings` always asks for a - reheat, which would reheat even on a `render(false, false)` refresh. */ + intent of the individual setters is not the caller's: `setSettings` asks for a reheat + whenever the patch carries a physics key, and the dashboard's sync hands it the whole + GSET — so it would reheat even on a `render(false, false)` refresh. */ function batch(fn, fit, reheat) { suspended++; try { fn(api); } finally { @@ -855,7 +856,19 @@ if (state.bridges || state.sizeBy === 'betweenness') ensureBetweenness(); render(true, true); }; - api.setSettings = patch => { Object.assign(state.settings, patch); render(false, patch.mode !== undefined); }; + /* Which of these settings changes the *layout* rather than just the paint, matching the + classic path's `key==='repel'||key==='link'||key==='gravity'||key==='size'` in + dashboard.js::graphSet — `size` counts because it feeds d3.forceCollide, and `mode` + swaps the whole force arrangement. applyForces() only writes the new charge / link / + forceX-forceY / collide values into the simulation force-graph is already running, and a + settled graph sits at alpha~0, so without the reheat those sliders install a force that + moves nothing. The paint-only settings must keep the arrangement the user is reading. + render() applies the reduced-motion exemption (`if(layout&&!prefersReducedMotion())`). */ + const LAYOUT_KEYS = ['mode', 'repel', 'link', 'gravity', 'size']; + api.setSettings = patch => { + Object.assign(state.settings, patch); + render(false, LAYOUT_KEYS.some(k => patch && patch[k] !== undefined)); + }; api.setPreset = name => { const p = PRESETS[name] || PRESETS.compact; state.settings.mode = PRESETS[name] ? name : 'compact'; diff --git a/tests/test_graph_engine_asset.py b/tests/test_graph_engine_asset.py index 773297d..a18c9e2 100644 --- a/tests/test_graph_engine_asset.py +++ b/tests/test_graph_engine_asset.py @@ -55,16 +55,18 @@ #: accessor is a chainable setter that returns the stored value when called with no arguments — #: force-graph's own kapsule semantics — so the paint configuration the engine installs can be #: read back and invoked instead of pattern-matched. ``calls`` counts the invalidations the -#: engine requests, which is the only observable form a "redraw now" takes. +#: engine requests, which is the only observable form a "redraw now" takes. ``invocations`` +#: counts the *argument-less* calls, which under kapsule semantics are the commands rather than +#: the setters — ``d3ReheatSimulation()`` is one, and it has no other observable effect here. ENGINE_PRELUDE = """ const fs = require('fs'); const source = fs.readFileSync(process.argv[1], 'utf8'); const window = {}; globalThis.requestAnimationFrame = () => {}; -const store = {}, calls = {}; +const store = {}, calls = {}, invocations = {}; const fg = new Proxy({}, { get: (_target, prop) => (...args) => { - if (!args.length) return store[prop]; + if (!args.length) { invocations[prop] = (invocations[prop] || 0) + 1; return store[prop]; } calls[prop] = (calls[prop] || 0) + 1; store[prop] = args.length === 1 ? args[0] : args; return fg; @@ -1154,6 +1156,59 @@ def test_simulation_time_is_bounded_on_a_large_graph() -> None: assert report["reduced"]["ticks"] == 1 +@requires_node +def test_physics_sliders_reheat_the_simulation_the_way_the_classic_renderer_does() -> None: + """Installing a new force on a settled graph moves nothing without a reheat. + + ``graphSet`` (dashboard.js) routes Repel/Link/Gravity/Size/Font/Link-width/Label-density + through ``setSettings`` under ``?graph-engine=next``. The classic branch of that same + function treats ``repel|link|gravity|size`` as *layout* changes: it re-applies the forces + and then reheats unless the user asked for reduced motion. The engine's ``applyForces()`` + only swaps the charge/link/forceX-forceY/collide values into the running simulation — and a + settled graph sits at alpha~0 — so without the reheat those four sliders are inert until + the user finds the Reheat button. The paint-only settings must *not* reheat: restarting + the layout because a label got bigger throws away the arrangement the user is reading. + """ + report = _run_engine( + """ + const reheats = () => invocations.d3ReheatSimulation || 0; + const bump = (api, patch) => { const before = reheats(); api.setSettings(patch); return reheats() - before; }; + + const api = G.create(el, {}); + api.setData(chain(40)); + const layout = { + repel: bump(api, { repel: 260 }), + link: bump(api, { link: 90 }), + gravity: bump(api, { gravity: 12 }), + size: bump(api, { size: 5 }), + mode: bump(api, { mode: 'radial' }), + }; + const paint = { + font: bump(api, { font: 11 }), + linkw: bump(api, { linkw: 2.4 }), + labelDensity: bump(api, { labelDensity: 40 }), + labels: bump(api, { labels: true }), + flow: bump(api, { flow: false }), + }; + + // The classic path's `if(layout&&!prefersReducedMotion())` exemption. + const still = G.create(el, { reducedMotion: () => true }); + still.setData(chain(40)); + const reducedMotion = bump(still, { repel: 260 }); + emit({ layout, paint, reducedMotion }); + """ + ) + # The four sliders the classic renderer calls a layout change, plus the preset itself. + assert report["layout"] == { + "repel": 1, "link": 1, "gravity": 1, "size": 1, "mode": 1 + }, "a physics slider installed new forces on a settled graph and nothing moved" + # Appearance-only settings keep the arrangement the user is looking at. + assert report["paint"] == { + "font": 0, "linkw": 0, "labelDensity": 0, "labels": 0, "flow": 0 + }, "an appearance change restarted the layout" + assert report["reducedMotion"] == 0, "reduced motion still got an animated relayout" + + @requires_node def test_curves_arrows_and_relation_labels_are_dropped_on_a_dense_graph() -> None: """Three per-edge costs the classic path turns off past ``GPERF.dense`` (links > 1500). From 089f18563f4957d020d0652b40f442aee25e198e Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 26 Jul 2026 23:03:08 -0400 Subject: [PATCH 47/82] perf(graph): apply the classic renderer's large-graph guards to the opt-in engine The engine already computed `large` (>600 nodes / >2400 links, the classic `GPERF.large` signal) and used it for cooldown, alpha decay and the galaxy starfield, but two per-frame costs the classic path drops at that cutoff were still being paid: - `applyForces()` pinned `forceCollide().iterations(2)`. The second pass is another full quadtree traversal per node per tick, and a large store pays it on the initial layout and on every reheat. Now `iterations(large ? 1 : 2)`, matching `.iterations(GPERF.large?1:2)`. - Every `rich` node still got a glow: the galaxy halo, the solar corona *and* its sphere shading, and the cyber `shadowBlur`. A gradient is a fresh object per node and a blur is a convolution of the drawn shape, both per frame. All three are now gated on `!large`, with the flat `fillStyle = col` fallback the classic path uses for the solar sphere. Both are pinned by tests that drive the asset under Node and read the recorded force/canvas calls back, and both fail against the previous asset (601 collision iterations of 2; 607 gradients painted on a large solar graph). Co-Authored-By: Claude Opus 5 --- engraphis/static/engraphis-graph.js | 29 ++++++-- tests/test_graph_engine_asset.py | 109 ++++++++++++++++++++++++++++ 2 files changed, 130 insertions(+), 8 deletions(-) diff --git a/engraphis/static/engraphis-graph.js b/engraphis/static/engraphis-graph.js index e134625..8dffa6c 100644 --- a/engraphis/static/engraphis-graph.js +++ b/engraphis/static/engraphis-graph.js @@ -483,7 +483,11 @@ fg.d3Force('y', d3.forceY(0).strength(centering)); if (mode === 'radial' && d3.forceRadial) fg.d3Force('radial', d3.forceRadial(n => Math.max(0, 5 - Math.min(5, n.degree || 0)) * Math.max(8, s.link * 0.72)).strength(0.32)); } - if (d3.forceCollide) fg.d3Force('collide', d3.forceCollide(n => n.radius + 1.5).iterations(2)); + /* One collision pass on a large graph, two otherwise — the classic path's + `.iterations(GPERF.large?1:2)`. The second pass costs another full quadtree traversal + per node on every tick, and a large store pays that on the initial layout and on every + reheat, which is exactly where it is least affordable. */ + if (d3.forceCollide) fg.d3Force('collide', d3.forceCollide(n => n.radius + 1.5).iterations(large ? 1 : 2)); } function styleBackground(ctx, scale) { @@ -563,8 +567,13 @@ ctx.beginPath(); ctx.arc(node.x, node.y, r + 3 / scale, 0, 6.2832); ctx.stroke(); ctx.restore(); } + /* Every per-node glow below is gated on `!large`, matching the classic path's + `if(rich&&!GPERF.large)` / `if(!GPERF.large)` pairs. A radial gradient or a shadow blur + is per-node, per-frame canvas work: at the >600-node cutoff that is hundreds of + gradients rebuilt on every tick of the layout, which is what makes a big store crawl. + The flat fill in the `else` is the classic fallback, not a missing branch. */ if (state.styleName === 'galaxy') { - if (rich) { + if (rich && !large) { ctx.save(); ctx.globalCompositeOperation = 'lighter'; const R = r * (node.id === hilite ? 4.4 : 3.0); @@ -583,7 +592,7 @@ } else if (state.styleName === 'solar') { const sun = node.rank === 0; if (sun) r *= 1.7; - if (rich) { + if (rich && !large) { ctx.save(); ctx.globalCompositeOperation = 'lighter'; const cc = sun ? '#ffcf6b' : col, R2 = r * (sun ? 3.4 : 2.1); @@ -594,14 +603,18 @@ ctx.beginPath(); ctx.arc(node.x, node.y, R2, 0, 6.2832); ctx.fill(); ctx.restore(); } - const sg = ctx.createRadialGradient(node.x - r * 0.4, node.y - r * 0.4, Math.max(0.1, r * 0.12), node.x, node.y, r); - sg.addColorStop(0, lighten(sun ? '#ffe4ad' : col, 0.5)); - sg.addColorStop(1, sun ? '#e08a25' : col); - ctx.fillStyle = sg; + if (large) { + ctx.fillStyle = col; + } else { + const sg = ctx.createRadialGradient(node.x - r * 0.4, node.y - r * 0.4, Math.max(0.1, r * 0.12), node.x, node.y, r); + sg.addColorStop(0, lighten(sun ? '#ffe4ad' : col, 0.5)); + sg.addColorStop(1, sun ? '#e08a25' : col); + ctx.fillStyle = sg; + } ctx.beginPath(); ctx.arc(node.x, node.y, r, 0, 6.2832); ctx.fill(); } else if (state.styleName === 'cyber') { ctx.save(); - if (rich) { ctx.shadowColor = col; ctx.shadowBlur = dim ? 2 : r * 2.6; } + if (rich && !large) { ctx.shadowColor = col; ctx.shadowBlur = dim ? 2 : r * 2.6; } ctx.beginPath(); ctx.arc(node.x, node.y, r, 0, 6.2832); ctx.fillStyle = col; ctx.fill(); ctx.restore(); ctx.beginPath(); ctx.arc(node.x, node.y, Math.max(0.4, r * 0.42), 0, 6.2832); ctx.fillStyle = '#eafcff'; ctx.fill(); diff --git a/tests/test_graph_engine_asset.py b/tests/test_graph_engine_asset.py index a18c9e2..4b65c3c 100644 --- a/tests/test_graph_engine_asset.py +++ b/tests/test_graph_engine_asset.py @@ -1251,6 +1251,115 @@ def test_curves_arrows_and_relation_labels_are_dropped_on_a_dense_graph() -> Non assert report["denseHighlighted"] == ["mentions"] +#: A ``d3`` stand-in for the force constructors ``applyForces()`` reaches for. The asset reads +#: ``d3`` as a free variable, so assigning it on ``globalThis`` is what the browser's global +#: script tag does; without it ``applyForces()`` returns before it ever configures collision. +D3_STUB = """ +let collide = null; +globalThis.d3 = { + forceX: () => ({ strength: () => ({}) }), + forceY: () => ({ strength: () => ({}) }), + forceRadial: () => ({ strength: () => ({}) }), + forceCollide: radius => ({ radius, iterations(n) { collide = { radius, iterations: n }; return this; } }), +}; +""" + + +@requires_node +def test_collision_runs_one_pass_on_a_large_graph_like_the_classic_renderer() -> None: + """``forceCollide().iterations(2)`` is a second full quadtree traversal per node per tick. + + ``graphApplyForces()`` on the classic path spends it only when it is affordable + (``.iterations(GPERF.large?1:2)``). The opt-in engine computes the same ``large`` signal for + its cooldown and alpha-decay constants but was pinning two iterations regardless, so the one + case where the extra pass hurts most — the initial layout and every reheat of a big store — + was the case that paid for it twice over. + """ + report = _run_engine( + D3_STUB + + """ + const api = G.create(el, { reducedMotion: () => true }); + + api.setData(chain(40)); + const small = collide.iterations; + + // 601 entities / 600 relations — one past the classic renderer's 600-node cutoff. + api.setData(chain(600)); + const big = collide.iterations; + + // A slider move re-runs applyForces() on the running simulation; it must not undo this. + api.setSettings({ repel: 90 }); + const afterSlider = collide.iterations; + emit({ small, big, afterSlider, radiusIsAFunction: typeof collide.radius === 'function' }); + """ + ) + assert report["small"] == 2 + assert report["big"] == 1, "a large graph still runs two collision passes per tick" + assert report["afterSlider"] == 1, "a slider move restored the expensive collision pass" + # Guards the whole call rather than the argument in isolation: a per-node radius, not a + # constant, is what makes collision agree with the sizes the renderer actually painted. + assert report["radiusIsAFunction"] is True + + +#: Counts the two per-node glow primitives independently. ``createRadialGradient`` is the halo +#: and the solar sphere shading; ``shadowBlur`` is the cyber bloom. Both are per node, per frame. +GLOW_CANVAS_STUB = """ +let gradients = 0, blurs = 0, fills = 0; +const ctx = { + globalAlpha: 1, globalCompositeOperation: '', strokeStyle: '', lineWidth: 1, font: '', + textBaseline: '', shadowColor: '', + set shadowBlur(v) { if (v) blurs += 1; }, + get shadowBlur() { return 0; }, + set fillStyle(v) {}, get fillStyle() { return ''; }, + save() {}, restore() {}, beginPath() {}, arc() {}, ellipse() {}, stroke() {}, + setLineDash() {}, fillText() {}, + fill() { fills += 1; }, + createRadialGradient() { gradients += 1; return { addColorStop() {} }; }, +}; +const paintNodes = () => { + gradients = 0; blurs = 0; fills = 0; + const draw = store.nodeCanvasObject; + store.graphData.nodes.forEach((n, i) => { n.x = i * 10; n.y = i; draw(n, ctx, 4); }); + return { gradients, blurs, fills }; +}; +""" + + +@requires_node +@pytest.mark.parametrize("style", ["cyber", "galaxy", "solar"]) +def test_per_node_glow_is_dropped_on_a_large_graph(style: str) -> None: + """Every ``rich`` node was getting a bloom or a gradient on every frame, at any size. + + The classic renderer gates all three of them on ``!GPERF.large`` — the galaxy halo, the solar + corona *and* its sphere shading, and the cyber ``shadowBlur``. A shadow blur is a full + convolution of the drawn shape and a radial gradient is a fresh object per node; at the + >600-node cutoff that is hundreds of them rebuilt per tick, on top of the layout, which is + what made a dense workspace crawl even after the other large-graph optimisations kicked in. + + ``fills`` is the control: the nodes are still being drawn, so a zero glow count means the + effect was skipped, not that the paint never ran. + """ + report = _run_engine( + GLOW_CANVAS_STUB + + f""" + const api = G.create(el, {{ reducedMotion: () => true }}); + api.setStyle("{style}"); + + api.setData(chain(40)); + const small = paintNodes(); + + api.setData(chain(600)); + const big = paintNodes(); + emit({{ small, big }}); + """ + ) + small, big = report["small"], report["big"] + assert small["fills"] > 0 and big["fills"] > 0, "canvas stub never reached the node painter" + assert small["gradients"] + small["blurs"] > 0, "the small graph lost its glow entirely" + assert big["gradients"] == 0, f"{style} still builds a radial gradient per node when large" + assert big["blurs"] == 0, f"{style} still shadow-blurs every node when large" + + def _community_palettes(source: str) -> dict: """Parse a ``COMMUNITY_PALS`` literal out of either renderer.""" # Anchor on the declaration: both files also name the table in prose comments. From 1e351567480aa3ce6828204d7bab763ae24a07db Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 26 Jul 2026 23:19:41 -0400 Subject: [PATCH 48/82] test(graph): exercise the opt-in engine in a real browser The Node harness in tests/test_graph_engine_asset.py drives the asset against a recording force-graph stand-in, which is right for the logic and proves nothing about a browser: no CSP, no real canvas, no vendor bundle, no ", encoding="utf-8", ) @@ -66,7 +66,7 @@ def test_check_rejects_unclosed_inline_asset_at_eof(tmp_path, monkeypatch, tag): _LOADERS = ( "script.src='/static/vendor/force-graph.min.js';" - "script.src='/static/engraphis-graph.js';" + "script.src='/v2-assets/engraphis-graph.js';" ) diff --git a/tests/test_graph_engine_asset.py b/tests/test_graph_engine_asset.py index 9403bad..0fcb598 100644 --- a/tests/test_graph_engine_asset.py +++ b/tests/test_graph_engine_asset.py @@ -29,7 +29,8 @@ ROOT = Path(__file__).resolve().parents[1] STATIC = ROOT / "engraphis" / "static" -ASSET = STATIC / "engraphis-graph.js" +ASSET = ROOT / "engraphis" / "dashboard_assets" / "engraphis-graph.js" +LEGACY_ADAPTER = STATIC / "engraphis-graph.js" INDEX = STATIC / "index.html" CSS = STATIC / "dashboard.css" DASHBOARD = STATIC / "dashboard.js" @@ -129,6 +130,14 @@ def test_graph_assets_are_never_loaded_on_a_plain_page_view() -> None: assert "/static/engraphis-graph.js" not in eager +def test_v1_graph_asset_is_only_a_compatibility_adapter() -> None: + """New renderer code stays on the v2 dashboard surface, not the legacy server.""" + adapter = LEGACY_ADAPTER.read_text(encoding="utf-8") + assert "canonicalAsset: '/v2-assets/engraphis-graph.js'" in adapter + assert "window.EngraphisGraph =" not in adapter + assert "window.EngraphisGraph =" in ASSET.read_text(encoding="utf-8") + + def test_opt_in_graph_asset_is_lazily_loaded_after_its_dependencies() -> None: """The load order the removed script tags used to guarantee now lives in graphRender(). @@ -137,7 +146,7 @@ def test_opt_in_graph_asset_is_lazily_loaded_after_its_dependencies() -> None: """ source = DASHBOARD.read_text(encoding="utf-8") assert "script.src='/static/vendor/force-graph.min.js'" in source - assert "script.src='/static/engraphis-graph.js'" in source + assert "script.src='/v2-assets/engraphis-graph.js'" in source render = source[source.index("function graphRender("):] render = render[: render.index("\nfunction ")] force_graph_gate = render.index("typeof ForceGraph==='undefined'") @@ -146,6 +155,12 @@ def test_opt_in_graph_asset_is_lazily_loaded_after_its_dependencies() -> None: assert force_graph_gate < engine_gate < classic +def test_engine_node_labels_honor_the_configured_font_at_normal_zoom() -> None: + source = ASSET.read_text(encoding="utf-8") + assert "state.settings.font / scale / 3.4" not in source + assert "state.settings.font / scale" in source + + #: Executes dashboard.js's real graph-render *routing* decision against a stub DOM. #: ``graphEngineEnabled``, ``graphEngineFallback``, ``loadForceGraph``, ``loadGraphEngine`` and #: the routing half of ``graphRender`` are verbatim source slices — nothing is re-implemented. @@ -234,7 +249,7 @@ def test_graph_engine_deep_link_reaches_the_next_engine_after_a_lazy_load() -> N report = _run_routing("loads") - assert report["appended"] == ["/static/engraphis-graph.js"] + assert report["appended"] == ["/v2-assets/engraphis-graph.js"] # It waits rather than rendering something wrong in the meantime. assert report["beforeSettle"] == {"engine": 0, "classic": 0} # And it lands on the next engine, never touching the classic renderer. From d4a113af4e4fec218fe02e330a215886958f2237 Mon Sep 17 00:00:00 2001 From: Jaixii Date: Mon, 27 Jul 2026 00:25:32 -0400 Subject: [PATCH 67/82] fix(connect): harden ambiguous device activation failures --- engraphis/cloud_session.py | 25 ++++- engraphis/device_connect.py | 95 ++++++++++++++++--- tests/test_device_connect.py | 173 +++++++++++++++++++++++++++++++++-- 3 files changed, 267 insertions(+), 26 deletions(-) diff --git a/engraphis/cloud_session.py b/engraphis/cloud_session.py index bed3a9d..5ab45ab 100644 --- a/engraphis/cloud_session.py +++ b/engraphis/cloud_session.py @@ -86,6 +86,11 @@ def _refresh_lock_path() -> Path: return _session_path().with_name(".cloud_session.refresh.lock") +#: Exactly the flags ``_refresh_lock`` opens the lock with, so ``preflight_save`` cannot +#: drift from the access the real save needs. +_LOCK_OPEN_FLAGS = os.O_RDWR | getattr(os, "O_BINARY", 0) | getattr(os, "O_NOFOLLOW", 0) + + @contextmanager def _refresh_lock(): """Serialize spend-and-rotate of the single-use refresh credential. @@ -99,7 +104,7 @@ def _refresh_lock(): try: lock_path.parent.mkdir(parents=True, exist_ok=True) expected = private_file_stat(lock_path, allow_missing=True) - flags = os.O_RDWR | getattr(os, "O_BINARY", 0) | getattr(os, "O_NOFOLLOW", 0) + flags = _LOCK_OPEN_FLAGS if expected is None: try: descriptor = os.open( @@ -258,6 +263,24 @@ def preflight_save() -> Path: "%s could not be inspected; check its permissions." % candidate, status=409, ) from exc + # ``private_file_stat`` above is an ``lstat``: it proves the lock is a plain, private, + # unlinked file, not that this process can *open* it. ``_refresh_lock`` opens it + # ``O_RDWR``, so a lock left behind by another UID -- or one whose mode changed -- + # passes the stat and fails the save, after the token is spent. Open it here with the + # same flags when it already exists. When it does not, ``_refresh_lock`` creates it in + # a directory the probe below proves writable, so there is nothing to pre-check and + # nothing is created here. + lock_path = _refresh_lock_path() + if lock_path.exists(): + try: + descriptor = os.open(str(lock_path), _LOCK_OPEN_FLAGS) + except OSError as exc: + raise CloudSessionError( + "The cloud session refresh lock %s exists but cannot be opened; check its " + "ownership and permissions." % lock_path, + status=409, + ) from exc + os.close(descriptor) # Probe the directory the way ``atomic_private_text`` will, rather than touching # ``cloud_session.json``: a read-only mount or a lost ACL fails here, while a valid # existing session is never created, truncated or replaced. diff --git a/engraphis/device_connect.py b/engraphis/device_connect.py index 0b7a99e..0002787 100644 --- a/engraphis/device_connect.py +++ b/engraphis/device_connect.py @@ -35,6 +35,7 @@ import urllib.error import urllib.request from pathlib import Path +from urllib.parse import urlsplit from typing import Optional, Tuple from engraphis import cloud_session @@ -181,7 +182,21 @@ def _state_dir() -> Path: def _identity_path() -> Path: - return _state_dir() / _IDENTITY_FILENAME + try: + return _state_dir() / _IDENTITY_FILENAME + except RuntimeError as exc: + # ``Path.home()`` raises ``RuntimeError("Could not determine home directory")`` on a + # service account or container with no resolvable home. This module promises every + # failure is a ``DeviceConnectError``, and the CLI catches only that, so the bare + # ``RuntimeError`` reached the terminal as a traceback -- from a command whose whole + # selling point is being non-interactive and scriptable. ``ENGRAPHIS_STATE_DIR`` is + # the documented answer, so the copy names it. + raise DeviceConnectError( + "Engraphis could not determine a home directory for its state files. Set " + "ENGRAPHIS_STATE_DIR to a writable directory and run `engraphis connect " + "--token ...` again.", + status=400, + ) from exc def _new_client_id(prefix: str) -> str: @@ -195,6 +210,12 @@ def _new_client_id(prefix: str) -> str: def _read_identity() -> dict: try: raw = read_private_text(_identity_path(), max_bytes=8 * 1024, allow_missing=True) + except DeviceConnectError: + # Already actionable copy (an unresolvable home directory). Must come first: + # ``DeviceConnectError`` is a ``RuntimeError``, so the broad clause below would + # otherwise swallow it and let the *next*, unguarded ``_identity_path()`` call + # raise the raw error instead. + raise except UnsafeStateFile as exc: raise DeviceConnectError( "The saved client identity has unsafe filesystem permissions. Remove %s and " @@ -278,6 +299,39 @@ def default_control_url() -> str: return "" +def _canonical_endpoint(value: object) -> str: + """Canonical ``scheme://host:port/path`` for comparing two endpoint URLs. + + ``validate_cloud_base_url`` returns ``urlunsplit((scheme, parts.netloc, ...))``: it + lower-cases the *scheme* but passes the netloc through verbatim, and it never removes a + redundant default port. So ``HTTPS://API.ENGRAPHIS.COM`` normalises to + ``https://API.ENGRAPHIS.COM``, and ``https://api.engraphis.com:443`` keeps its ``:443`` + -- both are the shipped control plane, and both compared unequal to it as raw strings. + The consequence was silent and expensive: :func:`default_compute_url` returned ``""``, + so a customer who typed the production URL with a different case or an explicit port + connected successfully and then had every hosted feature switched off, because + ``cloud_session.configured()`` needs a compute endpoint. + + Returns ``""`` for anything unparseable, which never equals another canonical form. + """ + + try: + parts = urlsplit(str(value or "").strip()) + except ValueError: + return "" + scheme = parts.scheme.lower() + host = (parts.hostname or "").lower() + if not scheme or not host: + return "" + try: + port = parts.port + except ValueError: + return "" + if port is None: + port = 443 if scheme == "https" else 80 + return "%s://%s:%d%s" % (scheme, host, port, parts.path.rstrip("/")) + + def default_compute_url(control_url: str) -> str: """Resolve the compute plane, guessing only for the shipped control plane. @@ -302,7 +356,7 @@ def default_compute_url(control_url: str) -> str: shipped_compute = str(data.get("compute_plane") or "").strip() except Exception: # pragma: no cover - manifest ships with the package return "" - if shipped and control_url.rstrip("/") == shipped.rstrip("/"): + if shipped and _canonical_endpoint(control_url) == _canonical_endpoint(shipped): return shipped_compute or DEFAULT_COMPUTE_URL return "" @@ -512,26 +566,37 @@ def post_connect(control_url: str, token: str, *, installation_client_id: str, except _DRAIN_FAILURES: pass raise _connect_http_error(status) - except (urllib.error.URLError, TimeoutError, OSError) as exc: + except urllib.error.URLError as exc: # ``exc`` may quote an internal host or a proxy URL; never reflect it. # - # Deliberately ahead of the ``HTTPException`` clause: ``RemoteDisconnected`` is - # both a ``ConnectionResetError`` and a ``BadStatusLine``, and it means the peer - # closed without answering at all. Nothing was consumed, so "try again" is the - # correct advice for it and it must not inherit the token-may-be-spent copy. + # ``URLError`` is the honest "nothing was consumed" case, and the only one. + # ``AbstractHTTPHandler.do_open`` wraps failures from establishing the connection + # and from ``h.request(...)`` -- DNS, connection refused, TLS, a write that never + # completed -- in ``URLError``, but lets anything raised by ``h.getresponse()`` + # propagate unwrapped. So reaching *this* clause means the request never finished + # going out, and "try again" with the same token is correct. raise DeviceConnectError( "Engraphis Cloud is temporarily unreachable. Check your network and try " "again.", status=503, ) from exc - except http.client.HTTPException as exc: - # A truncated chunked body makes ``HTTPResponse.read`` raise ``IncompleteRead``, - # whose only base is ``HTTPException``: it is neither an ``OSError``, a - # ``ValueError``, nor a ``URLError`` -- so it escaped both clauses above. That - # happened at the worst moment: the control plane had already answered, so the - # single-use token was very likely spent, and the customer saw a stack trace - # instead of being told to check the portal. ``LineTooLong``/``BadStatusLine`` from - # reading the status line and headers land here for the same reason. + except (TimeoutError, OSError, http.client.HTTPException) as exc: + # Everything else in this phase comes out of ``h.getresponse()``, which runs only + # after the request has been written in full. The control plane may therefore have + # received and processed it -- and a processed connect spends the token -- so this + # is ambiguous, not a clean miss. + # + # This clause used to claim the opposite for ``RemoteDisconnected`` ("the peer + # closed without answering at all. Nothing was consumed"). That was an overclaim: + # ``RemoteDisconnected`` is raised when ``getresponse()`` reads zero bytes for the + # status line, which is *after* the POST went out. Telling that customer to retry + # sent them into a 401 that reads as "the token I just generated is invalid". + # ``_TRUNCATED_REPLY`` is the right copy under ambiguity: it asks them to check the + # portal first rather than asserting either outcome. + # + # ``LineTooLong``/``BadStatusLine`` from a mangled status line, and ``IncompleteRead`` + # from a truncated body, land here for the same reason -- none of them are a + # ``URLError``, so before this clause existed they escaped as a raw traceback. raise DeviceConnectError(_TRUNCATED_REPLY, status=502) from exc # Past this line the control plane has answered with a success status, so the token is diff --git a/tests/test_device_connect.py b/tests/test_device_connect.py index 0f64700..849fc6b 100644 --- a/tests/test_device_connect.py +++ b/tests/test_device_connect.py @@ -588,19 +588,24 @@ def open(self, request, timeout): assert not (tmp_path / "cloud_session.json").exists() -def test_a_reset_before_any_reply_keeps_the_plain_retry_copy(monkeypatch): - """The other side of the split: nothing was consumed, so "try again" is still right.""" +def test_a_bare_reset_from_the_open_phase_is_also_ambiguous(monkeypatch): + """A bare ``ConnectionResetError`` reaching us unwrapped came from ``getresponse()``. + + urllib wraps connect-and-send failures in ``URLError``; only ``getresponse()`` raises + through. So an unwrapped reset means the POST was already written, and the token may be + spent -- see ``test_a_failure_before_the_request_goes_out_still_says_retry`` for the + ``URLError`` half that still says "try again". + """ _install_opener( - monkeypatch, _Opener(error=ConnectionResetError("closed before answering")) + monkeypatch, _Opener(error=ConnectionResetError("reset awaiting the reply")) ) with pytest.raises(device_connect.DeviceConnectError) as caught: device_connect.connect(TOKEN, control_url=CONTROL_URL, compute_url=COMPUTE_URL) - assert caught.value.status == 503 - assert "temporarily unreachable" in str(caught.value) - assert "may already have been used" not in str(caught.value) + assert caught.value.status == 502 + assert "may already have been used" in str(caught.value) def test_a_lock_failure_racing_the_save_says_the_token_was_spent(monkeypatch): @@ -688,22 +693,54 @@ def open(self, request, timeout): assert not (tmp_path / "cloud_session.json").exists() -def test_a_connection_reset_before_any_reply_still_says_retry(monkeypatch): - """``RemoteDisconnected`` is *both* an ``OSError`` and an ``HTTPException``. +def test_a_reset_with_no_reply_is_ambiguous_not_a_clean_miss(monkeypatch): + """This assertion is the reverse of what it once was, and the reversal is the point. + + The old copy claimed ``RemoteDisconnected`` meant "the peer closed without answering at + all. Nothing was consumed." That was an overclaim: ``RemoteDisconnected`` is raised when + ``getresponse()`` reads zero bytes for the status line, which happens *after* + ``h.request(...)`` has written the POST in full. The control plane may well have + received and processed it, and a processed connect spends the token -- so telling the + customer to retry sent them into a 401 reading "the token I just generated is invalid". - Nothing was read, so the token is untouched and "try again" remains the right copy; - it must not be swept into the token-may-be-spent message by the new clause. + ``_TRUNCATED_REPLY`` is the honest copy under ambiguity: check the portal, then decide. """ _install_opener( monkeypatch, _Opener(error=http.client.RemoteDisconnected("closed early")) ) + with pytest.raises(device_connect.DeviceConnectError) as caught: + device_connect.connect(TOKEN, control_url=CONTROL_URL, compute_url=COMPUTE_URL) + + assert caught.value.status == 502 + assert "may already have been used" in str(caught.value) + assert "temporarily unreachable" not in str(caught.value) + + +@pytest.mark.parametrize("reason", [ + ConnectionRefusedError("connection refused"), + OSError("dns failure"), + TimeoutError("connect timed out"), +]) +def test_a_failure_before_the_request_goes_out_still_says_retry(monkeypatch, reason): + """The other half of the same split, and the reason it is not blanket-ambiguous. + + ``AbstractHTTPHandler.do_open`` wraps everything from establishing the connection and + from ``h.request(...)`` in ``URLError``, and lets ``h.getresponse()`` raise unwrapped. + So a ``URLError`` is the one honest "nothing was consumed" signal -- DNS, refused, TLS, + a write that never completed -- and those customers must not be told to fetch a new + token for what is just flaky wifi. + """ + + _install_opener(monkeypatch, _Opener(error=urllib.error.URLError(reason))) + with pytest.raises(device_connect.DeviceConnectError) as caught: device_connect.connect(TOKEN, control_url=CONTROL_URL, compute_url=COMPUTE_URL) assert caught.value.status == 503 assert "temporarily unreachable" in str(caught.value) + assert "may already have been used" not in str(caught.value) @pytest.mark.parametrize("failure", [ @@ -908,6 +945,39 @@ def test_the_preflight_creates_nothing_and_leaves_nothing_behind(monkeypatch, tm assert _probe_files(tmp_path) == [] +def test_an_unopenable_refresh_lock_fails_before_the_token_is_spent(monkeypatch, tmp_path): + """``private_file_stat`` is an ``lstat``; it does not prove the lock can be opened. + + ``_refresh_lock`` opens it ``O_RDWR``, so a lock file left behind by another UID passes + the stat, the preflight passes, the token is redeemed -- and then ``save_bootstrap`` + fails opening a file whose inaccessibility was detectable before the POST. + """ + + lock_path = tmp_path / ".cloud_session.refresh.lock" + lock_path.write_bytes(b"") + + opener = _Opener(body=REGISTRATION) + _install_opener(monkeypatch, opener) + + real_open = cloud_session.os.open + + def _denied(path, flags, *args): + if str(path).endswith(".cloud_session.refresh.lock"): + raise PermissionError("owned by another uid") + return real_open(path, flags, *args) + + monkeypatch.setattr(cloud_session.os, "open", _denied) + + with pytest.raises(device_connect.DeviceConnectError) as caught: + device_connect.connect(TOKEN, control_url=CONTROL_URL, compute_url=COMPUTE_URL) + + # Detected before the POST, so the token is untouched. + assert opener.calls == [] + assert caught.value.status == 409 + assert "refresh lock" in str(caught.value) + assert not (tmp_path / "cloud_session.json").exists() + + def test_a_probe_that_cannot_be_removed_fails_the_preflight(monkeypatch, tmp_path): """Creating a file and removing one are separate rights. @@ -1161,6 +1231,89 @@ def test_the_manifest_outranks_the_compute_constant(monkeypatch): assert device_connect.default_compute_url(CONTROL_URL) == "" +@pytest.mark.parametrize("spelling", [ + "https://api.engraphis.test", + "HTTPS://API.ENGRAPHIS.TEST", + "https://API.engraphis.test", + "https://api.engraphis.test:443", + "https://api.engraphis.test/", + "HTTPS://API.ENGRAPHIS.TEST:443/", +]) +def test_equivalent_spellings_of_the_shipped_control_url_still_get_compute( + monkeypatch, spelling +): + """``validate_cloud_base_url`` normalises the scheme but not the netloc. + + It returns ``urlunsplit((scheme, parts.netloc, ...))``, so ``HTTPS://API.EXAMPLE`` keeps + its upper-case host and ``:443`` is never dropped. A raw string comparison against the + shipped URL therefore missed, ``default_compute_url`` returned "", and a customer who + typed the production endpoint with a different case or an explicit port connected + successfully and then found every hosted feature off, because + ``cloud_session.configured()`` needs a compute endpoint. + """ + + monkeypatch.setattr( + "engraphis.commercial.manifest", + lambda: { + "control_plane": "https://api.engraphis.test", + "compute_plane": COMPUTE_URL, + }, + ) + + assert device_connect.default_compute_url(spelling) == COMPUTE_URL + + +@pytest.mark.parametrize("other", [ + "https://api.engraphis.test:8443", # a different port really is a different endpoint + "http://api.engraphis.test", # and so is a different scheme + "https://api.engraphis.test/v2", # and a different path + "https://evil.example.test", +]) +def test_a_genuinely_different_control_url_still_gets_no_compute(monkeypatch, other): + """The normalisation must not become a wildcard: only equivalents may match.""" + + monkeypatch.setattr( + "engraphis.commercial.manifest", + lambda: { + "control_plane": "https://api.engraphis.test", + "compute_plane": COMPUTE_URL, + }, + ) + + assert device_connect.default_compute_url(other) == "" + + +def test_an_unresolvable_home_directory_is_an_error_not_a_traceback(monkeypatch, capsys): + """``Path.home()`` raises ``RuntimeError`` on a service account with no home. + + ``_read_identity`` swallowed it and returned ``{}``, but the *next* ``_identity_path()`` + call sits outside that guard and raised it again. The CLI catches only + ``DeviceConnectError``, so a command whose whole selling point is being non-interactive + and scriptable printed a traceback. + """ + + monkeypatch.delenv("ENGRAPHIS_STATE_DIR", raising=False) + + def _no_home(): + raise RuntimeError("Could not determine home directory") + + monkeypatch.setattr(device_connect.Path, "home", staticmethod(_no_home)) + + opener = _Opener(body=REGISTRATION) + _install_opener(monkeypatch, opener) + + code = connect_cli.main( + ["--token", TOKEN, "--control-url", CONTROL_URL, "--compute-url", COMPUTE_URL] + ) + + assert code == 1 + err = capsys.readouterr().err + assert "Traceback" not in err + assert "ENGRAPHIS_STATE_DIR" in err + # Nothing was sent, so the token is still good once the variable is set. + assert opener.calls == [] + + @pytest.mark.parametrize("bad", ["nan", "inf", "-inf", "0", "-5", "1e9", "10000000000"]) def test_a_non_finite_timeout_is_refused_before_any_request(monkeypatch, bad): """``argparse``'s ``type=float`` accepts ``nan``/``inf``; the socket layer does not. From daa7035f61000e79ca6e7b394062c09dc189c455 Mon Sep 17 00:00:00 2001 From: Jaixii Date: Mon, 27 Jul 2026 00:25:37 -0400 Subject: [PATCH 68/82] fix(graph): keep v2 assets lazy and themed --- engraphis/dashboard_assets/engraphis-graph.js | 4 +++- engraphis/static/dashboard.js | 2 +- scripts/externalize_dashboard_assets.py | 6 +++++- tests/test_externalize_dashboard_assets.py | 12 ++++++++++++ tests/test_graph_engine_asset.py | 9 ++++++++- 5 files changed, 29 insertions(+), 4 deletions(-) diff --git a/engraphis/dashboard_assets/engraphis-graph.js b/engraphis/dashboard_assets/engraphis-graph.js index 00a9ac6..532fcfb 100644 --- a/engraphis/dashboard_assets/engraphis-graph.js +++ b/engraphis/dashboard_assets/engraphis-graph.js @@ -553,7 +553,9 @@ ctx.textBaseline = 'middle'; ctx.fillText(String(node.members), node.x, node.y); ctx.font = '500 ' + Math.max(2.6, r * 0.4) + 'px system-ui, sans-serif'; - ctx.fillStyle = 'rgba(232,236,245,.9)'; + // Cluster names sit outside the coloured bubble. They therefore need the active + // theme's text colour, not the dark-theme near-white that disappears on light canvas. + ctx.fillStyle = state.themeColors.label || '#e7e9ee'; ctx.fillText(nodeName(node), node.x, node.y + r * 1.5 + r * 0.5); ctx.textAlign = 'left'; ctx.globalAlpha = 1; diff --git a/engraphis/static/dashboard.js b/engraphis/static/dashboard.js index 60cfdff..b012fbe 100644 --- a/engraphis/static/dashboard.js +++ b/engraphis/static/dashboard.js @@ -513,7 +513,7 @@ function graphTypeColor(type){if(GCOLOR_OVERRIDES[type])return GCOLOR_OVERRIDES[ /* The engine renders to a canvas, so it cannot read `--entity-*` itself the way the legend and the controls do. Resolve the active theme's values here and hand them over; without this the opt-in canvas keeps dark-theme node colours after a switch to Light/Solarized/Sepia. */ -function graphThemeTypeColors(){const colors={},fallback=cssvar('--color-accent','#8c83e8');Object.keys(ETYPE_TOKEN).forEach(type=>{colors[type]=cssvar(ETYPE_TOKEN[type],fallback)});colors.relation_label=cssvar('--color-text-dim','#7e8795');return colors} +function graphThemeTypeColors(){const colors={},fallback=cssvar('--color-accent','#8c83e8');Object.keys(ETYPE_TOKEN).forEach(type=>{colors[type]=cssvar(ETYPE_TOKEN[type],fallback)});colors.relation_label=cssvar('--color-text-dim','#7e8795');colors.label=cssvar('--color-text','#e7e9ee');return colors} function graphContrastColor(color){if(!graphValidColor(color))return cssvar('--color-canvas','#0e1014');const n=parseInt(color.slice(1),16),lum=.2126*(n>>16)+.7152*((n>>8)&255)+.0722*(n&255);return lum>150?'#111827':'#f8fafc'} const ETYPE_COLOR=new Proxy({},{get:(_,type)=>graphTypeColor(type)}); graphLoadColorPreferences(); diff --git a/scripts/externalize_dashboard_assets.py b/scripts/externalize_dashboard_assets.py index 858ae40..c2aaf96 100644 --- a/scripts/externalize_dashboard_assets.py +++ b/scripts/externalize_dashboard_assets.py @@ -139,7 +139,11 @@ def _eager_scripts(html: str) -> list[str]: CSP-hostile bundle back onto every page view *and* drop it from the existence check — a gate that cannot fail. """ - return [src for src in _parse_page(html).script_srcs if src.startswith("/static/")] + return [ + src + for src in _parse_page(html).script_srcs + if src.startswith(("/static/", "/v2-assets/")) + ] def _replace_assets(html: str, replacements: list[tuple[_InlineAsset, str]]) -> str: diff --git a/tests/test_externalize_dashboard_assets.py b/tests/test_externalize_dashboard_assets.py index 900cf26..8a3b567 100644 --- a/tests/test_externalize_dashboard_assets.py +++ b/tests/test_externalize_dashboard_assets.py @@ -99,6 +99,18 @@ def test_check_rejects_an_eagerly_loaded_csp_hostile_script(tmp_path, monkeypatc assets.check() +def test_check_rejects_an_eagerly_loaded_v2_graph_engine(tmp_path, monkeypatch): + _gate( + tmp_path, + monkeypatch, + '', + _LOADERS, + ) + + with pytest.raises(SystemExit, match="must not eagerly load: /v2-assets/engraphis-graph"): + assets.check() + + def test_check_allows_a_deferred_script_named_only_in_a_comment(tmp_path, monkeypatch): """The rule reads parsed ``", encoding="utf-8", ) @@ -75,7 +75,7 @@ def test_check_rejects_unclosed_inline_asset_at_eof(tmp_path, monkeypatch, tag): _LOADERS = ( "script.src='/static/vendor/force-graph.min.js';" - "script.src='/static/engraphis-graph.js';" + "script.src='/v2-assets/engraphis-graph.js';" ) diff --git a/tests/test_graph_engine_asset.py b/tests/test_graph_engine_asset.py index f365d27..3bbdb63 100644 --- a/tests/test_graph_engine_asset.py +++ b/tests/test_graph_engine_asset.py @@ -29,7 +29,8 @@ ROOT = Path(__file__).resolve().parents[1] STATIC = ROOT / "engraphis" / "static" -ASSET = STATIC / "engraphis-graph.js" +ASSET = ROOT / "engraphis" / "dashboard_assets" / "engraphis-graph.js" +LEGACY_ADAPTER = STATIC / "engraphis-graph.js" INDEX = STATIC / "index.html" CSS = STATIC / "dashboard.css" DASHBOARD = STATIC / "dashboard.js" @@ -129,6 +130,14 @@ def test_graph_assets_are_never_loaded_on_a_plain_page_view() -> None: assert "/static/engraphis-graph.js" not in eager +def test_v1_graph_asset_is_only_a_compatibility_adapter() -> None: + """New renderer code stays on the v2 dashboard surface, not the legacy server.""" + adapter = LEGACY_ADAPTER.read_text(encoding="utf-8") + assert "canonicalAsset: '/v2-assets/engraphis-graph.js'" in adapter + assert "window.EngraphisGraph =" not in adapter + assert "window.EngraphisGraph =" in ASSET.read_text(encoding="utf-8") + + def test_opt_in_graph_asset_is_lazily_loaded_after_its_dependencies() -> None: """The load order the removed script tags used to guarantee now lives in graphRender(). @@ -137,7 +146,7 @@ def test_opt_in_graph_asset_is_lazily_loaded_after_its_dependencies() -> None: """ source = DASHBOARD.read_text(encoding="utf-8") assert "script.src='/static/vendor/force-graph.min.js'" in source - assert "script.src='/static/engraphis-graph.js'" in source + assert "script.src='/v2-assets/engraphis-graph.js'" in source render = source[source.index("function graphRender("):] render = render[: render.index("\nfunction ")] force_graph_gate = render.index("typeof ForceGraph==='undefined'") @@ -146,6 +155,12 @@ def test_opt_in_graph_asset_is_lazily_loaded_after_its_dependencies() -> None: assert force_graph_gate < engine_gate < classic +def test_engine_node_labels_honor_the_configured_font_at_normal_zoom() -> None: + source = ASSET.read_text(encoding="utf-8") + assert "state.settings.font / scale / 3.4" not in source + assert "state.settings.font / scale" in source + + #: Executes dashboard.js's real graph-render *routing* decision against a stub DOM. #: ``graphEngineEnabled``, ``graphEngineFallback``, ``loadForceGraph``, ``loadGraphEngine`` and #: the routing half of ``graphRender`` are verbatim source slices — nothing is re-implemented. @@ -234,7 +249,7 @@ def test_graph_engine_deep_link_reaches_the_next_engine_after_a_lazy_load() -> N report = _run_routing("loads") - assert report["appended"] == ["/static/engraphis-graph.js"] + assert report["appended"] == ["/v2-assets/engraphis-graph.js"] # It waits rather than rendering something wrong in the meantime. assert report["beforeSettle"] == {"engine": 0, "classic": 0} # And it lands on the next engine, never touching the classic renderer. From 3cc80036e65fc9793ce112ec3f2eb1fd5b03fc73 Mon Sep 17 00:00:00 2001 From: Jaixii Date: Mon, 27 Jul 2026 00:25:37 -0400 Subject: [PATCH 74/82] fix(graph): keep v2 assets lazy and themed --- engraphis/dashboard_assets/engraphis-graph.js | 4 +++- engraphis/static/dashboard.js | 2 +- scripts/externalize_dashboard_assets.py | 6 +++++- tests/test_externalize_dashboard_assets.py | 12 ++++++++++++ tests/test_graph_engine_asset.py | 12 +++++++++++- 5 files changed, 32 insertions(+), 4 deletions(-) diff --git a/engraphis/dashboard_assets/engraphis-graph.js b/engraphis/dashboard_assets/engraphis-graph.js index 3409e11..c601cf1 100644 --- a/engraphis/dashboard_assets/engraphis-graph.js +++ b/engraphis/dashboard_assets/engraphis-graph.js @@ -556,7 +556,9 @@ ctx.textBaseline = 'middle'; ctx.fillText(String(node.members), node.x, node.y); ctx.font = '500 ' + Math.max(2.6, r * 0.4) + 'px system-ui, sans-serif'; - ctx.fillStyle = 'rgba(232,236,245,.9)'; + // Cluster names sit outside the coloured bubble. They therefore need the active + // theme's text colour, not the dark-theme near-white that disappears on light canvas. + ctx.fillStyle = state.themeColors.label || '#e7e9ee'; ctx.fillText(nodeName(node), node.x, node.y + r * 1.5 + r * 0.5); ctx.textAlign = 'left'; ctx.globalAlpha = 1; diff --git a/engraphis/static/dashboard.js b/engraphis/static/dashboard.js index b3fab5a..869549f 100644 --- a/engraphis/static/dashboard.js +++ b/engraphis/static/dashboard.js @@ -579,7 +579,7 @@ function graphTypeColor(type){if(GCOLOR_OVERRIDES[type])return GCOLOR_OVERRIDES[ /* The engine renders to a canvas, so it cannot read `--entity-*` itself the way the legend and the controls do. Resolve the active theme's values here and hand them over; without this the opt-in canvas keeps dark-theme node colours after a switch to Light/Solarized/Sepia. */ -function graphThemeTypeColors(){const colors={},fallback=cssvar('--color-accent','#8c83e8');Object.keys(ETYPE_TOKEN).forEach(type=>{colors[type]=cssvar(ETYPE_TOKEN[type],fallback)});colors.relation_label=cssvar('--color-text-dim','#7e8795');return colors} +function graphThemeTypeColors(){const colors={},fallback=cssvar('--color-accent','#8c83e8');Object.keys(ETYPE_TOKEN).forEach(type=>{colors[type]=cssvar(ETYPE_TOKEN[type],fallback)});colors.relation_label=cssvar('--color-text-dim','#7e8795');colors.label=cssvar('--color-text','#e7e9ee');return colors} function graphContrastColor(color){if(!graphValidColor(color))return cssvar('--color-canvas','#0e1014');const n=parseInt(color.slice(1),16),lum=.2126*(n>>16)+.7152*((n>>8)&255)+.0722*(n&255);return lum>150?'#111827':'#f8fafc'} const ETYPE_COLOR=new Proxy({},{get:(_,type)=>graphTypeColor(type)}); graphLoadColorPreferences(); diff --git a/scripts/externalize_dashboard_assets.py b/scripts/externalize_dashboard_assets.py index 04744e0..927f4e2 100644 --- a/scripts/externalize_dashboard_assets.py +++ b/scripts/externalize_dashboard_assets.py @@ -149,7 +149,11 @@ def _eager_scripts(html: str) -> list[str]: CSP-hostile bundle back onto every page view *and* drop it from the existence check — a gate that cannot fail. """ - return [src for src in _parse_page(html).script_srcs if src.startswith("/static/")] + return [ + src + for src in _parse_page(html).script_srcs + if src.startswith(("/static/", "/v2-assets/")) + ] def _replace_assets(html: str, replacements: list[tuple[_InlineAsset, str]]) -> str: diff --git a/tests/test_externalize_dashboard_assets.py b/tests/test_externalize_dashboard_assets.py index 6e1d30a..c3ddf3c 100644 --- a/tests/test_externalize_dashboard_assets.py +++ b/tests/test_externalize_dashboard_assets.py @@ -108,6 +108,18 @@ def test_check_rejects_an_eagerly_loaded_csp_hostile_script(tmp_path, monkeypatc assets.check() +def test_check_rejects_an_eagerly_loaded_v2_graph_engine(tmp_path, monkeypatch): + _gate( + tmp_path, + monkeypatch, + '', + _LOADERS, + ) + + with pytest.raises(SystemExit, match="must not eagerly load: /v2-assets/engraphis-graph"): + assets.check() + + def test_check_allows_a_deferred_script_named_only_in_a_comment(tmp_path, monkeypatch): """The rule reads parsed ``

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 z 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