Enforce SX boundary contract via boundary.sx spec + runtime validation
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 2m33s

Add boundary.sx declaring all 34 I/O primitives, 32 page helpers, and 9
allowed boundary types. Runtime validation in boundary.py checks every
registration against the spec — undeclared primitives/helpers crash at
startup with SX_BOUNDARY_STRICT=1 (now set in both dev and prod).

Key changes:
- Move 5 I/O-in-disguise primitives (app-url, asset-url, config,
  jinja-global, relations-from) from primitives.py to primitives_io.py
- Remove duplicate url-for/route-prefix from primitives.py (already in IO)
- Fix parse-datetime to return ISO string instead of raw datetime
- Add datetime→isoformat conversion in _convert_result at the edge
- Wrap page helper return values with boundary type validation
- Replace all SxExpr(f"...") patterns with sx_call() or _sx_fragment()
- Add assert declaration to primitives.sx

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-05 23:50:02 +00:00
parent 54adc9c216
commit 04366990ec
21 changed files with 1342 additions and 415 deletions

View File

@@ -238,7 +238,7 @@ def _tokenize_bash(code: str) -> list[tuple[str, str]]:
def highlight(code: str, language: str = "lisp"):
"""Highlight code in the given language. Returns SxExpr for wire format."""
from shared.sx.parser import SxExpr
from shared.sx.parser import SxExpr, serialize
if language in ("lisp", "sx", "sexp"):
return SxExpr(highlight_sx(code))
elif language in ("python", "py"):
@@ -246,5 +246,4 @@ def highlight(code: str, language: str = "lisp"):
elif language in ("bash", "sh", "shell"):
return SxExpr(highlight_bash(code))
# Fallback: no highlighting, just escaped text
escaped = code.replace("\\", "\\\\").replace('"', '\\"')
return SxExpr(f'(span "{escaped}")')
return SxExpr("(span " + serialize(code) + ")")

View File

@@ -97,7 +97,8 @@
(define bootstrappers-nav-items (list
(dict :label "Overview" :href "/bootstrappers/")
(dict :label "JavaScript" :href "/bootstrappers/javascript")))
(dict :label "JavaScript" :href "/bootstrappers/javascript")
(dict :label "Python" :href "/bootstrappers/python")))
;; Spec file registry — canonical metadata for spec viewer pages.
;; Python only handles file I/O (read-spec-file); all metadata lives here.

View File

@@ -268,9 +268,11 @@ boot.sx depends on: cssx, orchestration, adapter-dom, render")))
(td :class "px-3 py-2 text-green-600" "Live"))
(tr :class "border-b border-stone-100"
(td :class "px-3 py-2 text-stone-700" "Python")
(td :class "px-3 py-2 font-mono text-sm text-stone-400" "bootstrap_py.py")
(td :class "px-3 py-2 font-mono text-sm text-stone-400" "shared/sx/")
(td :class "px-3 py-2 text-stone-400" "Planned"))
(td :class "px-3 py-2 font-mono text-sm text-violet-700"
(a :href "/bootstrappers/python" :class "hover:underline"
"bootstrap_py.py"))
(td :class "px-3 py-2 font-mono text-sm text-stone-500" "sx_ref.py")
(td :class "px-3 py-2 text-green-600" "Live"))
(tr :class "border-b border-stone-100"
(td :class "px-3 py-2 text-stone-700" "Rust")
(td :class "px-3 py-2 font-mono text-sm text-stone-400" "bootstrap_rs.py")
@@ -320,6 +322,47 @@ boot.sx depends on: cssx, orchestration, adapter-dom, render")))
(pre :class "text-xs leading-relaxed whitespace-pre-wrap break-words"
(code (highlight bootstrapped-output "javascript"))))))))
;; ---------------------------------------------------------------------------
;; Python bootstrapper detail
;; ---------------------------------------------------------------------------
(defcomp ~bootstrapper-py-content (&key bootstrapper-source bootstrapped-output)
(~doc-page :title "Python Bootstrapper"
(div :class "space-y-8"
(div :class "space-y-3"
(p :class "text-stone-600"
"This page reads the canonical " (code :class "text-violet-700 text-sm" ".sx")
" spec files, runs the Python bootstrapper, and displays both the compiler source and its generated Python output. "
"The generated code below is live — it was produced by the bootstrapper at page load time.")
(p :class "text-xs text-stone-400 italic"
"With SX_USE_REF=1, the server-side SX evaluator running this page IS the bootstrapped output. "
"This page re-runs the bootstrapper to display the source and result."))
(div :class "space-y-3"
(div :class "flex items-baseline gap-3"
(h2 :class "text-2xl font-semibold text-stone-800" "Bootstrapper")
(span :class "text-sm text-stone-400 font-mono" "bootstrap_py.py"))
(p :class "text-sm text-stone-500"
"The compiler reads " (code :class "text-violet-700 text-sm" ".sx")
" spec files (eval, primitives, render, adapter-html) "
"and emits a standalone Python module. Platform bridge functions (type constructors, environment ops) "
"are emitted as native Python implementations.")
(div :class "bg-stone-100 rounded-lg p-5 max-h-96 overflow-y-auto border border-stone-200"
(pre :class "text-xs leading-relaxed whitespace-pre-wrap break-words"
(code (highlight bootstrapper-source "python")))))
(div :class "space-y-3"
(div :class "flex items-baseline gap-3"
(h2 :class "text-2xl font-semibold text-stone-800" "Generated Output")
(span :class "text-sm text-stone-400 font-mono" "sx_ref.py"))
(p :class "text-sm text-stone-500"
"The Python below was generated by running the bootstrapper against the current spec files. "
"It is a complete server-side SX evaluator — eval, primitives, and HTML renderer.")
(div :class "bg-stone-100 rounded-lg p-5 max-h-96 overflow-y-auto border border-violet-300"
(pre :class "text-xs leading-relaxed whitespace-pre-wrap break-words"
(code (highlight bootstrapped-output "python"))))))))
;; ---------------------------------------------------------------------------
;; Not found
;; ---------------------------------------------------------------------------

View File

@@ -368,6 +368,10 @@
:data (bootstrapper-data slug)
:content (if bootstrapper-not-found
(~spec-not-found :slug slug)
(~bootstrapper-js-content
:bootstrapper-source bootstrapper-source
:bootstrapped-output bootstrapped-output)))
(if (= slug "python")
(~bootstrapper-py-content
:bootstrapper-source bootstrapper-source
:bootstrapped-output bootstrapped-output)
(~bootstrapper-js-content
:bootstrapper-source bootstrapper-source
:bootstrapped-output bootstrapped-output))))

View File

@@ -135,29 +135,44 @@ def _bootstrapper_data(target: str) -> dict:
"""
import os
if target != "javascript":
if target not in ("javascript", "python"):
return {"bootstrapper-not-found": True}
ref_dir = os.path.join(os.path.dirname(__file__), "..", "..", "shared", "sx", "ref")
if not os.path.isdir(ref_dir):
ref_dir = "/app/shared/sx/ref"
# Read bootstrapper source
bs_path = os.path.join(ref_dir, "bootstrap_js.py")
try:
with open(bs_path, encoding="utf-8") as f:
bootstrapper_source = f.read()
except FileNotFoundError:
bootstrapper_source = "# bootstrapper source not found"
if target == "javascript":
# Read bootstrapper source
bs_path = os.path.join(ref_dir, "bootstrap_js.py")
try:
with open(bs_path, encoding="utf-8") as f:
bootstrapper_source = f.read()
except FileNotFoundError:
bootstrapper_source = "# bootstrapper source not found"
# Run the bootstrap to generate JS
from shared.sx.ref.bootstrap_js import compile_ref_to_js
try:
bootstrapped_output = compile_ref_to_js(
adapters=["dom", "engine", "orchestration", "boot", "cssx"]
)
except Exception as e:
bootstrapped_output = f"// bootstrap error: {e}"
# Run the bootstrap to generate JS
from shared.sx.ref.bootstrap_js import compile_ref_to_js
try:
bootstrapped_output = compile_ref_to_js(
adapters=["dom", "engine", "orchestration", "boot", "cssx"]
)
except Exception as e:
bootstrapped_output = f"// bootstrap error: {e}"
elif target == "python":
bs_path = os.path.join(ref_dir, "bootstrap_py.py")
try:
with open(bs_path, encoding="utf-8") as f:
bootstrapper_source = f.read()
except FileNotFoundError:
bootstrapper_source = "# bootstrapper source not found"
from shared.sx.ref.bootstrap_py import compile_ref_to_py
try:
bootstrapped_output = compile_ref_to_py()
except Exception as e:
bootstrapped_output = f"# bootstrap error: {e}"
return {
"bootstrapper-not-found": None,
@@ -176,7 +191,7 @@ def _attr_detail_data(slug: str) -> dict:
- attr-not-found (truthy if not found)
"""
from content.pages import ATTR_DETAILS
from shared.sx.helpers import SxExpr
from shared.sx.helpers import sx_call
detail = ATTR_DETAILS.get(slug)
if not detail:
@@ -193,7 +208,7 @@ def _attr_detail_data(slug: str) -> dict:
"attr-description": detail["description"],
"attr-example": detail["example"],
"attr-handler": detail.get("handler"),
"attr-demo": SxExpr(f"(~{demo_name})") if demo_name else None,
"attr-demo": sx_call(demo_name) if demo_name else None,
"attr-wire-id": wire_id,
}
@@ -201,7 +216,7 @@ def _attr_detail_data(slug: str) -> dict:
def _header_detail_data(slug: str) -> dict:
"""Return header detail data for a specific header slug."""
from content.pages import HEADER_DETAILS
from shared.sx.helpers import SxExpr
from shared.sx.helpers import sx_call
detail = HEADER_DETAILS.get(slug)
if not detail:
@@ -214,14 +229,14 @@ def _header_detail_data(slug: str) -> dict:
"header-direction": detail["direction"],
"header-description": detail["description"],
"header-example": detail.get("example"),
"header-demo": SxExpr(f"(~{demo_name})") if demo_name else None,
"header-demo": sx_call(demo_name) if demo_name else None,
}
def _event_detail_data(slug: str) -> dict:
"""Return event detail data for a specific event slug."""
from content.pages import EVENT_DETAILS
from shared.sx.helpers import SxExpr
from shared.sx.helpers import sx_call
detail = EVENT_DETAILS.get(slug)
if not detail:
@@ -233,5 +248,5 @@ def _event_detail_data(slug: str) -> dict:
"event-title": slug,
"event-description": detail["description"],
"event-example": detail.get("example"),
"event-demo": SxExpr(f"(~{demo_name})") if demo_name else None,
"event-demo": sx_call(demo_name) if demo_name else None,
}