feat: publish the Sandwich Hime source preview

Signed-off-by: Cole Speelman <gamertan@noreply.localhost>
This commit is contained in:
2026-08-11 20:15:06 -04:00
commit 9b29b3d7f8
100 changed files with 10989 additions and 0 deletions
+26
View File
@@ -0,0 +1,26 @@
<!-- SPDX-License-Identifier: AGPL-3.0-only -->
# Architecture
Sandwich Hime is separated into three trust and deployment zones:
```text
trusted .sando source
|
v
AGPL himesan compiler: parse -> context-annotated renderer IR -> Go backend
|
v
committed .sando.go + Apache sando runtime
|
v
ordinary application/router/server chosen by the user
```
The compiler is globally installed for development. `generate` and `check` read source and emit or compare ordinary Go; they do not load plugins, fetch modules, run application code, or mutate module metadata. Generated output is the only bridge from compiler internals into an application.
The renderer IR records source spans and output context independently of Go syntax. The only v1 backend is `go`, selected explicitly in the source header. A future San backend may consume the same IR, but v1 contains no San parser, `.san` handling, or compatibility promise.
The nested `sando` module is a small ABI with no HTTP opinions. It owns component invocation, contextual writer helpers, and opaque trusted values. The application owns buffering, status codes, headers, routing, authentication, caching, CSP, and deployment.
`himesan dev` is a separate local-only supervisor. Its loopback proxy and browser client never enter generated output or a production binary. Candidate application processes become live only after generation, build, startup, and health checks pass; otherwise the last healthy process remains upstream.
+9
View File
@@ -0,0 +1,9 @@
<!-- SPDX-License-Identifier: AGPL-3.0-only -->
# Benchmark policy
Benchmarks compare equivalent typed views and output against Go's `html/template` baseline. Reports include hardware, operating system, Go version, repository commit, dataset identity, exact commands, warmup/run counts, `ns/op`, bytes and allocations per operation, end-to-end response latency where relevant, output size, and statistical method.
The v1 gate is no material regression for the selected EQL pages under the published method. Only reproduced improvements become marketing claims. Microbenchmarks do not justify claims about request throughput, database-heavy pages, or whole-application latency.
Benchmark fixtures must contain synthetic or approved public data. The EQL production database is never copied into this repository or a public artifact.
+9
View File
@@ -0,0 +1,9 @@
<!-- SPDX-License-Identifier: AGPL-3.0-only -->
# Brand vocabulary
Use **Sandwich Hime** for the project and **Hime-san** as its friendly short form. Use `himesan` for the command, `.sando` for source, `.sando.go` for generated Go, and `sando` for the runtime.
Never call the project bare “Hime,” which can be confused with an existing Go framework. Never use `.san`; it belongs exclusively to the separate San language project. “Sando” evokes a sandwich and keeps both projects unmistakable in editors, tooling, and search results.
The preferred truthful attribution is “Built with Sandwich Hime.” It is optional and governed by [TRADEMARKS.md](../TRADEMARKS.md).
+11
View File
@@ -0,0 +1,11 @@
<!-- SPDX-License-Identifier: AGPL-3.0-only -->
# Compatibility policy
Before v1.0.0, source syntax and generated ABI may change without compatibility shims, but each public change must be documented and deterministic. Private prototype history is intentionally outside the sanitized public repository and carries no public compatibility promise.
At v1, semantic versions apply independently to the compiler and `sando` runtime. Generated files record the exact compiler version and required runtime ABI. Patch releases do not intentionally change accepted source semantics or generated public signatures. Minor releases may add fail-closed syntax or API capabilities while continuing to render previously valid components. Major releases may remove or reinterpret behavior.
The compiler supports the latest two Go release lines validated in CI. A support change is announced before release. Generated files are source artifacts, not a stable interchange format across compiler versions; `himesan check` defines whether they are current.
The project makes no compatibility promise for internal packages, development SSE payloads before v1, or hand-edited generated files.
+34
View File
@@ -0,0 +1,34 @@
<!-- SPDX-License-Identifier: AGPL-3.0-only -->
# Local development supervisor
`himesan dev [package] [-- app-args...]` is an explicitly local convenience. It generates templates, builds the selected Go package into the user cache, starts a candidate on a random `127.0.0.1` address, health-checks it, and only then switches a stable loopback reverse proxy. Generation, build, startup, and health failures leave the previous healthy child serving.
The application must read its listen address from the configured environment variable and expose the configured health path. It remains an ordinary application server; no development proxy code appears in generated files or production binaries.
## `himesan.json` schema version 1
```json
{
"version": 1,
"sourceRoots": ["views"],
"goPackage": "./cmd/site",
"appArgs": ["--development"],
"listenAddressEnv": "HIMESAN_LISTEN_ADDR",
"healthPath": "/healthz",
"proxyAddress": "127.0.0.1:7331",
"additionalWatchRoots": ["assets"]
}
```
Unknown fields, non-loopback proxy addresses, invalid environment names, malformed health paths, NULs, and unsupported schema versions are rejected. Arguments are passed directly without a shell. The configuration contains no commands, secrets, credentials, or production bind address.
Simple projects can override the package and repeat `--source`/`--watch`, plus `--proxy`, `--listen-env`, and `--health`. When a config path is supplied, relative paths resolve from its directory.
## Browser behavior
The stable proxy reserves `/__himesan/events` for SSE. It injects a fixed reload/diagnostic client only into successful full HTML documents with positive document evidence. Fragments, APIs, encoded bodies, range responses, downloads, HEAD, and non-success responses are never injected. Development responses are non-cacheable.
When an existing CSP is present, the proxy adds the fixed script's SHA-256 source and same-origin SSE connection permission; it does not add `unsafe-inline` or `unsafe-eval`. The proxy and every candidate upstream are literal loopback addresses. Replaced process groups are terminated and waited for on Unix and Windows.
This is not a production proxy, TLS terminator, public preview server, process orchestrator, or deployment system. V1 refuses non-loopback binding.
+23
View File
@@ -0,0 +1,23 @@
<!-- SPDX-License-Identifier: AGPL-3.0-only -->
# Diagnostics
Human diagnostics use stable `path:line:column` locations and `HIM####` codes. `--json` emits one object containing the operation result and structured diagnostics. Error diagnostics make generation/check exit nonzero; audit warnings do not.
Code families are intentionally coarse compatibility surfaces:
| Range | Area |
| --- | --- |
| `HIM10xx` | Source encoding |
| `HIM11xx` | Component header and Go declaration |
| `HIM12xx` | Template tags and expressions |
| `HIM13xx` | HTML parser context and structure |
| `HIM14xx` | Generated Go/backend validation |
| `HIM15xx` | Component graph and package collisions |
| `HIM19xx` | Trusted-value audit warnings |
| `HIM20xx` | Discovery and cancellation |
| `HIM21xx` | Owned atomic generation |
| `HIM22xx` | Read-only freshness checking |
| `HIM29xx` | Boundary warnings |
Scripts should consume the JSON `code`, `severity`, and location fields, not parse English messages. Message wording may improve within a compatible release.
+39
View File
@@ -0,0 +1,39 @@
<!-- SPDX-License-Identifier: AGPL-3.0-only -->
# Threat model
## Trusted
- `.sando` files and embedded Go statements;
- handwritten application Go;
- explicit calls to `sando.TrustHTML`, `TrustURL`, `TrustJS`, and `TrustCSS`;
- the selected compiler binary and runtime module version.
## Untrusted
- values supplied to components unless deliberately wrapped in a trusted type;
- filenames and directory entries encountered during discovery;
- stale or manually modified generated output;
- browser requests reaching the development proxy;
- child process output and health failures.
## Guarantees sought by v1
- Context-sensitive escaping for supported HTML text, quoted attributes, URL attributes, and explicitly trusted script/style values.
- Compilation failure for unsupported or ambiguous output contexts.
- Dangerous normalized URL schemes fail rendering unless explicitly trusted.
- Component calls cannot change the surrounding HTML parser context.
- Dynamic `title` and `textarea` content uses a distinct RCDATA writer that escapes even `TrustedHTML`; trusted HTML cannot close those elements.
- Writer failures propagate and partial output is visible to the caller as an error; applications can buffer when atomic responses matter.
- Generation plans all outputs before atomic replacement, targets only owned files, preserves last-good output on failure, and follows neither symlinks nor nested-module traversal.
- `generate` and `check` do not execute project code, invoke Go tooling, fetch dependencies, or alter `go.mod`.
## Non-goals
Templates are not a sandbox. A malicious template author can write malicious Go in a statement tag. Sandwich Hime does not validate business authorization, prevent unsafe application logic, make an arbitrary `io.Writer` transactional, or secure an application router/server. Trusted constructors are intentionally sharp tools and must remain conspicuous in review and `himesan check` reporting. A `TrustedHTML` fragment must be balanced and context-neutral; `TrustedJS` and `TrustedCSS` authors are responsible for excluding container-closing HTML sequences.
The v1 HTML state machine is deliberately smaller than a browser parser. Any construct it cannot prove safe is rejected rather than guessed. Differential testing against Go `html/template` is a baseline, not a claim of byte-identical output or universal parser equivalence.
## Principal attack classes
Tests cover delimiter confusion, malformed HTML, quote/entity injection, event attributes, dangerous and obfuscated URLs, script/style termination, Unicode and NUL handling, component context breaks, import/source-map injection, CRLF and path behavior, symlinks, nested modules, stale outputs, interrupted/read-only writes, writer failures, component cycles, development-proxy exposure, CSP weakening, compression/content-length mistakes, and orphaned child processes.