diff --git a/CHANGELOG.md b/CHANGELOG.md index 09f4620..9966744 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,9 +2,16 @@ # Changelog -Sandwich Hime follows semantic versioning after v1. Compiler and nested runtime releases are listed separately. +Sandwich Hime follows semantic versioning after final v1. Compiler and nested +runtime releases are versioned independently and listed together when they form +one coordinated release. -## Unreleased — v1 proof +## v1.0.0-beta.1 — 2026-08-12 + +This is the first installable public beta: `sando/v1.0.0-beta.1` for the +Apache-2.0 runtime and `v1.0.0-beta.1` for the compiler and CLI. The beta is +for learning, classroom projects, evaluation, and compatibility feedback. It is +not a production-stability promise. ### Added @@ -12,15 +19,46 @@ Sandwich Hime follows semantic versioning after v1. Compiler and nested runtime - Context-annotated renderer IR with deterministic, atomic Go generation. - Read-only stale-output checking and structured diagnostics. - Independent Apache-2.0 `sando` component/runtime ABI. -- Loopback-only last-good development supervisor with SSE reload and diagnostic overlay. +- Loopback-only last-good development supervisor with SSE reload and diagnostic + overlay. - Compiler-owned deterministic golden fixture and standalone release gates. -- Multi-license, security, governance, trademark, AI contribution, and release policies. +- Multi-license, security, governance, trademark, AI contribution, and release + policies. +- Public beta support policy for evaluation and classroom use, including a + provisional macOS lane and a community compatibility-reporting path. -### Removed +### Pre-beta verification baseline -- Unpublished `.go.hime` syntax and 2025 generated API. -- Injected helper directories, nested demo modules, Go plugins, and manually repaired generated output. +Maintainer-run Linux and native Windows matrices passed on public commit +`113c95c21e57227b4675c9fda015ada59cc9e9a6` (tree +`a2aeb4dac22853cb3894e3e487b94bbeff5051e5`) with Go 1.25.12 and Go +1.26.5. The tested golden output had the same SHA-256 on each tested host: +`63fa75a3049a3a8a12d769d7f9b6b510dfe763baacf706775b75cef2c57a984f`. + +That commit is a pre-beta baseline, not evidence for the later Beta 1 commit. +The required matrix must be rerun from the exact candidate before its tags are +published. Native macOS execution remains pending and is explicitly provisional +for this beta. + +### Known limitations + +- Source syntax, generated format, CLI details, and runtime API may change + before final v1. +- Native macOS behavior has not yet been maintainer-validated. +- Prebuilt binary artifacts, checksums, SBOMs, reproducible archives, + key-recovery rehearsal, systematic browser differential, long fuzz, + benchmark, and final compatibility gates remain work toward the release + candidate and final v1. Beta 1 itself is a signed source/module release. +- The project has no independent security audit, certification, or formal + verification. + +### Removed since the private prototype + +- Unpublished `.go.hime` syntax and the 2025 generated API. +- Injected helper directories, nested demo modules, Go plugins, and manually + repaired generated output. - Repository-bundled application examples and deployment-specific evidence. - Placeholder novelty commands that did not perform project work. -Private prototype history is intentionally outside the sanitized public repository. The public changelog begins with the pre-1.0 source preview. +Private prototype history is intentionally outside the sanitized public +repository. The public changelog begins with Beta 1. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 5a717e4..849663c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -5,7 +5,7 @@ The canonical public project and only contribution venue is the [founder-controlled Gitea repository](https://gitea.speelman.ca/gamertan/sandwich-hime). Repository maintainers may temporarily disable issue or patch intake during the -pre-1.0 preview; do not route around a closed intake channel by sending +pre-1.0 period; do not route around a closed intake channel by sending unsolicited private patches. Public pre-1.0 contributions use Developer Certificate of Origin 1.1 sign-off. The proposed `CLA.md` is an inactive draft, is not a condition of contribution, and creates no contributor or project obligations. If a contribution agreement is ever activated after legal review, the project will announce its prospective terms rather than silently applying the draft. diff --git a/GOVERNANCE.md b/GOVERNANCE.md index bda215d..1f8b52f 100644 --- a/GOVERNANCE.md +++ b/GOVERNANCE.md @@ -2,9 +2,9 @@ # Founder-led governance -Sandwich Hime is founder-led. Cole Speelman is lead maintainer and has final authority over product direction, merges, releases, project identity, and security coordination. Authority is exercised through reviewable public releases, written rationale for material public decisions, and the published compatibility and release policies. Publishing a source preview does not create a promise of support or transfer stewardship. +Sandwich Hime is founder-led. Cole Speelman is lead maintainer and has final authority over product direction, merges, releases, project identity, and security coordination. Authority is exercised through reviewable public releases, written rationale for material public decisions, and the published compatibility and release policies. Publishing a prerelease creates only the support commitment stated for that version; it does not transfer stewardship. -Pre-1.0 contributions use the DCO process described in `CONTRIBUTING.md`; the CLA draft is inactive. Acceptance is never guaranteed. Maintainers may close work that expands the product beyond an HTML-first Go component compiler, weakens fail-closed safety, couples the runtime to a framework, or imposes unsustainable maintenance. +Pre-1.0 contributions use the DCO process described in `CONTRIBUTING.md`; the CLA draft is inactive. Acceptance is never guaranteed. Maintainers may close work that expands the product beyond an HTML-first, ahead-of-time Go template engine, weakens fail-closed safety, couples the runtime to a framework, or imposes unsustainable maintenance. Maintainers disclose relevant employment or financial conflicts and recuse when a conflict would compromise review. If the project reaches three maintainers, no single employer may control a majority of seats. diff --git a/LICENSES.md b/LICENSES.md index 1d470d4..23ff2bf 100644 --- a/LICENSES.md +++ b/LICENSES.md @@ -33,4 +33,4 @@ SPDX identifiers state the applicable license for comment-capable source and doc The snapshot exporter's `PUBLIC-SNAPSHOT.json` and `PUBLIC-SNAPSHOT.sha256` are generated factual provenance records and intentionally carry no inline SPDX comment. They do not change the license of any listed file. -These are practical project licensing terms, not legal advice or a prediction of how every jurisdiction will classify a particular work. The inactive CLA draft and pre-registration trademark policy say so explicitly. Qualified legal review remains prudent before changing these terms, activating a CLA, registering marks, or making a fact-specific licensing decision; it is not represented as a prerequisite to publishing the current unsupported source preview. +These are practical project licensing terms, not legal advice or a prediction of how every jurisdiction will classify a particular work. The inactive CLA draft and pre-registration trademark policy say so explicitly. Qualified legal review remains prudent before changing these terms, activating a CLA, registering marks, or making a fact-specific licensing decision; it is not represented as a prerequisite to publishing the current narrowly scoped public beta. diff --git a/PUBLIC-SNAPSHOT.json b/PUBLIC-SNAPSHOT.json index e9a7fa9..b4830e4 100644 --- a/PUBLIC-SNAPSHOT.json +++ b/PUBLIC-SNAPSHOT.json @@ -1 +1 @@ -{"schema_version":2,"project":"sandwich-hime","export_policy":"exact-allowlist-v1","export_mode":"release","file_count":80,"allowlist_sha256":"e40a56b3431efdd99b3a78c38c387722de347216640383fc849569a817edf5c6","manifest_sha256":"0b27ea55bc1f2083ac07ae777d20735e651c5026888b973bfe02ee764b9487dc"} +{"schema_version":2,"project":"sandwich-hime","export_policy":"exact-allowlist-v1","export_mode":"release","file_count":80,"allowlist_sha256":"e40a56b3431efdd99b3a78c38c387722de347216640383fc849569a817edf5c6","manifest_sha256":"93870a8c1e91602754de257c30249892821356ea9bf8d89e1b4502b62d769b06"} diff --git a/PUBLIC-SNAPSHOT.sha256 b/PUBLIC-SNAPSHOT.sha256 index 2715b9d..8033803 100644 --- a/PUBLIC-SNAPSHOT.sha256 +++ b/PUBLIC-SNAPSHOT.sha256 @@ -2,45 +2,45 @@ 658ba4b4645426f8c3249337f47669074ae9249a31703dcd9ea4c1afec45e20b ./.gitattributes d5ae411fb422b2388cac220f9655900eecbc49ece961b2bb2a6610347733b756 ./.gitignore 98f663ab0f376b4550094465ec2e06192d1e0b0707604ec6794f20b0d10952c1 ./AI_CONTRIBUTIONS.md -7f4414fed21e9578b8d1a0d109ba807cb79d28a9290d58df49cc75145d9d1068 ./CHANGELOG.md +8bc6c7586a58bdc648c7d3df2db33fa6db6381a111da9d8fc2d5817b5e0517ad ./CHANGELOG.md b696cab3cf482ff5737501371cca749369b119351383e698ced42bcdbcbfc8ae ./CLA.md -2d98826969cd492cc4dd10c595be21a608def5aacbec40ea5e25f1c3a617d8e6 ./CONTRIBUTING.md +797e884105738fc931b585b695424f43ec5f296d8ab9bba5191b096e87a9e2c2 ./CONTRIBUTING.md 86d7e49d5d90e0f98a4ad0f14b5d8b9f11ed09a1e29ecdf27388316b28e195e8 ./COPYRIGHT f7ac75b443f4ca16b503241344b41aeff9503b0c30bedc2b119551d83cb0fa90 ./DCO.txt 73cb1b092a40c56e522c5a0ebddf2b44f347cdb57bf6994cdb305d0e5697b55e ./GENERATED_CODE.md -048f96acecd3af84d6abc4f8c38108dff2171445417e5132318a1d18de4279fe ./GOVERNANCE.md +a4570d054f072d33b8f17b0c8b162a6ee0ca37d7df2b1aee7e4b728ab350a892 ./GOVERNANCE.md 0d96a4ff68ad6d4b6f1f30f713b18d5184912ba8dd389f86aa7710db079abcb0 ./LICENSE -6587e439cb3c39dce9aaa5b51facdbd78c0e86c24e9e3fb9537b944435a74410 ./LICENSES.md +47d857e49f89596bac9b09fc8ca57a668a33d01e2b51508acfc92ed321cdc27f ./LICENSES.md b6aa08e5ccaec3c5dccdc19d7cd7f54a70adae4d57966263c7aa353c7ba70e08 ./MAINTAINERS.md 6638db2f1fba831c79de835ce95c847a5b36c5b5c693b99a28655b2d096cc440 ./OUTPUT_EXCEPTION.md -327386b40ee9fb92a8568b6a51722578890393fa23051af632f3180385a4e739 ./README.md -ce32945cf5f16ab1a0202615bcf2053f46d421dcdd8ff2f1292f95bb5cf4493d ./RELEASE.md -419c334aeb20dc22ceba8d031aaa95314b77125bf3267fd9fdc003e3865f0327 ./ROADMAP.md -d70d89db6bf0142a42a95f45537be5a4562258646d36d56bd9a70096ec78ed91 ./SECURITY.md +dda0ffee17bc1586ac16cc9707999cde2909a116c98cd43aeab85e0d3da7b636 ./README.md +9895823f9f7ba88ddf048c53c23ed32298b151ab049a9c4470366389d9498ff4 ./RELEASE.md +6d1e49dd72ba9592a3fd0562fcca1857803a3dd86dc097b36043e20f5d5cd591 ./ROADMAP.md +50a24995b39a957e47e0e181f8771a87141302b4d308fa8d8bfdc2e70121c2b9 ./SECURITY.md 53bd6eda804d6b782bdb07115ec197c890813cf2d5d0125dfe8f47f5f92f75b0 ./SPEC.md -842beff8afa72d120fcad0ac73afb2049d580ff3000975f3b1786c4ade6a14d4 ./TRADEMARKS.md +3d9e680cdfe147df7cc9ff29ecf1d3e566e9cd559ae84db4880e559b9c7c7205 ./TRADEMARKS.md 136a6d82db842547b342f8b0c9ffdc7c04f7c9b473b4ef6dca9dbc940cb24b54 ./cmd/himesan/main.go 3011a435aaeb572d34e2d2b582865fd63268c92a9ae3f0ae1a56d1a59d83cd43 ./cmd/himesan/main_test.go 1ecbba46f8b1b2d548a01d7e98afae17b2dd17a814338ff1f88db885655d1c07 ./docs/ARCHITECTURE.md 9c598559a89fa4a9bdd2311bd1ed8330992d0a0f74ec8b29ac151fc0ff8fef16 ./docs/BENCHMARKS.md 5c3a62fed80ca28d56558b8c75e8b5be8ba7d2554127adf4609d96da314e85b0 ./docs/BRAND.md -35f5b4b7d195a7b5c071d4665505afef189c7b386d4e3079e9ce8a96ace07f3a ./docs/COMPATIBILITY.md +4f7b04b3f74a2e90fc69019cad78a1287f4806ae84e7207cfdf000971702395d ./docs/COMPATIBILITY.md 5f4ac209a16ab110baeaa64a40c19d9239c903e17550c3f05e1e1473ddcc33a3 ./docs/DEVELOPMENT_SERVER.md 51aa57a81131b64f76c45552122de842f22be92d81c8bba8f6fd38a18a7670d6 ./docs/DIAGNOSTICS.md -04c6b3f93588177a87edbca8f56af0e0f2a7c5ba31936f3174570c8282a1a7c2 ./docs/SECURITY_EVIDENCE.md +9bd43853d91b841c4879dac94dda5aafefa25bcdf4a02763445e2506fc618b03 ./docs/SECURITY_EVIDENCE.md d969c7b5486ee93e54232fd69d9db06f3b4dc1bba63001596ec48545073c2680 ./docs/THREAT_MODEL.md -76ac444771ac0a4f584ee0cf86ebfd34233412e6e511485f6cc90131a9a50387 ./docs/V1_RELEASE_PLAN.md +82107c57043af40b9e3ec03f4ed9efddcf3bcdda1765b99ec413f835be4a46e3 ./docs/V1_RELEASE_PLAN.md f27c46ca63707bb8cc570eab1ea521824e94bc59b1d153998a5e91c2c7340d16 ./go.mod ca0bf5051d356d2602f46201fb1637ce48b629ad42161877eec13f743f215dc5 ./internal/compiler/abi_test.go -0a624f76214afbed561a6f6490405c5083e49a53ae301c6ede763b78407ec0c7 ./internal/compiler/backend.go -7c96a4b31a34201cb9c48a7f0bac1c201865e4ecc7c080691af5ce68b3d7c207 ./internal/compiler/compiler_test.go +6ef6a0f15a5aca1c8708cbf24218372e1fca9c6fead1a5a75d261faa69651af7 ./internal/compiler/backend.go +4d309392a7739b26e41cd9d9db71b52077bb8198573634ddf793ad531acc81cf ./internal/compiler/compiler_test.go dbba23e360bd6dd1e8f42953a49a7cfcc241aa3ac76f5ce505ec8f8558833c84 ./internal/compiler/context.go b2a96ef1ad572ad9cd0e9247328ca261de6f9f3689da41e3f3e111d405a6dee6 ./internal/compiler/diagnostic.go 45562a41ef9ab1116746e4962ce8f93d4d8651e1e468a38122c626f8a34a2874 ./internal/compiler/discover.go -f5a6b31416027cb69a61d1a1421cba779ec3accae59c9ba9dd45d2c31b72149e ./internal/compiler/e2e_test.go +50a8bad11deea99faf0c7c9de1266bc086b7a1247ff9dd275ffedfc69a3be81d ./internal/compiler/e2e_test.go eefb05a35bd07660a293c8af97949cd6f69a22709728f3fe2cc9132b863b7d5a ./internal/compiler/fuzz_test.go d166096f185d76b2698aa3ab3251f00e58f84cdedc3af667e88ddd528ca0cb76 ./internal/compiler/model.go -0c7a7a4d6a51a8b58dfe7c12ecd8c608aff639fd6157a9657a0663ceb58c3c8c ./internal/compiler/operation.go +01516c0330b14a1970019690d8efcc9004d2dcfa59e82fef1b67f98005b67532 ./internal/compiler/operation.go d7d8181455d5f37ef9bcc6bdbf86e0630f20e8a5b3b81688d12742687b434c99 ./internal/compiler/parse.go 80cf170514a3b955d24440cb086d34e19f3a305510e3c5db95cb897be91f922a ./internal/compiler/replace_unix.go 0fff1c67447bf5353ed1df6e7dfc4b14581b67adc1bf02f7a4a7c1f2680c392f ./internal/compiler/replace_windows.go @@ -62,7 +62,7 @@ b94103cd4b582968cdb0b61b0164f57ade006fa4e5187fcaa05944274192526a ./internal/dev e0a682c0153bf4f2a1f26cc6095d7893ad96e6199cbe76d0150785fc996f1141 ./internal/devserver/watch.go b7a7fabf9a6c497f7ac2262628c5fb37a6bd00da676e1b7d5088d5f649c9f14c ./internal/devserver/watch_test.go d8c6f37c94ef426fc2d95c82331265f7d700d2e2a23100ad78c92849280ff6d8 ./internal/version/version.go -15cf04427c5239cf6985a24c62c888013137205b8159f8f24189a16c22ac6cf3 ./internal/version/version_test.go +9b615038a1178eedbcab299d90548e259ac34d2f5c51deadd79ed16f51ef6911 ./internal/version/version_test.go e8a3026ec920d7312f843e2001e50ae4e34fd1ba5f9b2ae25a6113de1fa88385 ./sando/COPYRIGHT c71d239df91726fc519c6eb72d318ec65820627232b2f796219e87dcf35d0ab4 ./sando/LICENSE b4a7bffe678a97209881e07989563a5085aa0ead9e1b67306087dac6b97bad70 ./sando/README.md @@ -72,9 +72,9 @@ ff76daee5b642ad84af31701833246d68b54d09580192312d750a7a2e893a692 ./sando/go.mod 80ff53787919e809b8085d6ad9c3e183c9c7c1d74cfeda73369ac5c4607c236f ./sando/trust.go 85621a44c730582f4410ac2c70418b739fb55e916f7e6b73a1a619982c459572 ./sando/write.go b188917e258890e6b6e4840a6fd946fc9a77cabc2068da3764f221e4a6a5df97 ./sando/write_test.go -ecae2e2938da982001eb1e10d7e9869e191669a776336b89f5cb181b18678701 ./scripts/README.md +504897b29686e0ea7adff8beb8ec91612df3ee169397309c3b6b69eb0393491b ./scripts/README.md 0bc796f71c863aa898674a26c56f055e3d81cf20629ca7b32fbae87d8841e0a8 ./scripts/check-licenses.sh -502da1760bc87f260d474d81fe8f015a6e198f8d1ebf96db6b3f460ce4ef3b02 ./scripts/release-check.sh -6be2fc6b8c3e0a7dd85437fa4089e75b772baa7556675081e6956a1b9f207fb4 ./scripts/verify-public-install.sh +6c73ad46beb642836ae4d462f40e7ecc8d86a3cc194e71a5d0859dac73af0410 ./scripts/release-check.sh +9cd43005a7d0f3659b11c5c14e4e0b9e7f675b695da185f4ee97c54edebf0dc6 ./scripts/verify-public-install.sh 24ed3c9a1d37e46a856cbbd68e5c58ae04c6c9852902b99ed675e1f428339a9f ./scripts/verify.ps1 f0cbd86759fa729064cb1c69991db2ac291792dadb6b1e1ba83794f2e390404d ./scripts/verify.sh diff --git a/README.md b/README.md index 13c35f9..6241b18 100644 --- a/README.md +++ b/README.md @@ -42,11 +42,44 @@ request object, or production server. ## Status -This repository is an unsupported public pre-1.0 source preview, not a -supported v1 release. V1 is gated only by repository-owned compiler, runtime, -security, compatibility, and release checks. Application-specific deployments, -examples, and case studies live in their own repositories and are not imported -as release evidence here. +`v1.0.0-beta.1` is the first installable public beta. It is supported for +learning, classroom projects, evaluation, and compatibility feedback. It is a +semantic-version prerelease: source syntax, generated output, the runtime API, +and CLI behavior may change before final v1, and this beta is not recommended +for production deployment. + +Maintainer-run testing has established a pre-beta baseline on native Windows +and on Linux with Go 1.25 and Go 1.26. That matrix must pass again on the exact +Beta 1 commit before its tags are published. Native macOS validation is still +pending, so macOS support is provisional in this beta. Mac learners and Go +developers are warmly invited to try it and share their macOS version, +architecture, Go version, command, and smallest useful reproduction. Community +reports broaden the evidence; maintainers remain responsible for security +review, triage, fixes, and release decisions. + +Install the beta compiler: + +```sh +go install gamertan.com/sandwich-hime/cmd/himesan@v1.0.0-beta.1 +``` + +Add the small runtime to an application module: + +```sh +go get gamertan.com/sandwich-hime/sando@v1.0.0-beta.1 +``` + +For a reproducible one-off or classroom invocation that does not depend on the +learner's `PATH`: + +```sh +go run gamertan.com/sandwich-hime/cmd/himesan@v1.0.0-beta.1 --help +``` + +The runtime is released first as `sando/v1.0.0-beta.1`; the compiler follows as +`v1.0.0-beta.1`. If a newly announced version is not immediately available +through a module proxy, retry after the proxy has discovered the immutable tag +or use the canonical Gitea release instructions. For repository development: @@ -64,14 +97,9 @@ and serves it through `http://127.0.0.1:7331` with local-only reload diagnostics. That is a Cole-shaped convenience, not a production server or a requirement. Take the paved path—or don't. -The eventual versioned installs are: - -```sh -go install gamertan.com/sandwich-hime/cmd/himesan@v1.0.0 -go get gamertan.com/sandwich-hime/sando@v1.0.0 -``` - -Those vanity paths must not be advertised as working until the corresponding signed releases and `gamertan.com` metadata exist. +Final-v1 installs will use the same paths with `@v1.0.0`. A version is +advertised as available only after its immutable tags, `gamertan.com` +metadata, and clean direct-fetch installation have been verified. ## The contract diff --git a/RELEASE.md b/RELEASE.md index 7bfb9c3..4b21742 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -2,41 +2,122 @@ # Release process -Sandwich Hime uses separate root and runtime version lines. Compiler tags are `vX.Y.Z`; runtime tags are `sando/vX.Y.Z`. Generated headers record both compiler version and runtime ABI. +Sandwich Hime uses separate root and runtime version lines. Compiler tags are +`vX.Y.Z`; runtime tags are `sando/vX.Y.Z`. Generated headers record both the +compiler version and runtime ABI. The runtime is always published before the +compiler that references it. -The public pre-1.0 source snapshot is not a supported release and does not imply that the v1 gates below have passed. +Every tag is immutable. A failed publication is corrected with a new version, +never by moving or replacing a tag. -No v1.0.0 release occurs until every gate in this repository is evidenced, -including cross-platform deterministic generation, temporary-module -compilation, fuzz/adversarial suites, race/vet/vulnerability/license checks on -the latest two supported Go lines, development-supervisor failure tests, and -reproducible repository-owned benchmark and security results. A deployment, -example, or case study in another repository is neither imported nor required -as release evidence. +## What the version stages mean -Release candidates require a clean canonical checkout, reviewed changelog, compatible vanity-import metadata, reproducible binaries, signed annotated tags, checksums, SBOMs, vulnerability results, and verification on Linux, macOS, and Windows. The runtime is tagged and published independently before the compiler that references its ABI. +### Beta + +A beta is an installable public evaluation release. The current +`v1.0.0-beta.1` scope is learning, classroom projects, prototypes, and +compatibility feedback. It receives best-effort security assessment and fixes +while it is the current prerelease, but it is not recommended or supported as a +production-stable dependency. Syntax, generated output, runtime APIs, CLI +behavior, and diagnostics may change in a later prerelease. + +Beta 1 may publish with native macOS validation pending when Windows and Linux +have passed the exact-candidate matrix and macOS is clearly marked provisional. +Community Mac results are valuable compatibility input; they do not transfer +security review, triage, remediation, or release responsibility away from the +maintainers. + +Beta tags are signed, annotated, and immutable. Beta 1 is a source/module +release installed through the Go toolchain; it does not promise downloadable +prebuilt binaries. Signed binary artifacts, checksums, SBOMs, reproducible +archives, and key-recovery rehearsal are mandatory for release candidates and +final v1. + +### Release candidate + +An RC means the intended v1 source, runtime, CLI, diagnostics, schemas, and +generated contract are frozen except for release-blocking fixes. An RC requires +maintainer-run native Linux, macOS, and Windows evidence, complete release +artifacts and provenance, signed tags, clean direct/proxy installs, and every RC +gate in this repository. Findings produce a new RC rather than a moved tag. + +### Final v1 + +Final v1 is the compatibility and support commitment. It requires the complete +repository-owned evidence campaign, resolution or explicit acceptance of every +published assurance gap, and the documented RC observation period. A +deployment, example, classroom project, or case study in another repository is +neither imported nor required as release evidence. + +## Beta 1 publication gates + +Before `sando/v1.0.0-beta.1` and `v1.0.0-beta.1` are created: + +1. Use a clean reviewed canonical public commit with no private identifiers, + paths, credentials, or history. +2. Run license, root/runtime test, vet, build, race, deterministic-generation, + and candidate-version freshness checks on supported Go 1.25 and Go 1.26 + lanes on Windows and Linux. +3. Confirm generated bytes match across those exact-candidate lanes and record + all skips or platform limitations. +4. Run the bounded fuzz and known-vulnerability checks from a clean release + host. +5. Review the changelog, security policy, compatibility policy, support scope, + provisional macOS wording, and vanity-import metadata. +6. Build the candidate compiler at its candidate version and prove its committed + generated fixtures are current under that exact binary. +7. Create signed annotated tags and publish the runtime tag first, then the + compiler tag, from the same reviewed commit. +8. Verify both documented installs from fresh `GOPROXY=direct` and public-proxy + caches. Record propagation delays as delays, not test passes. + +The passing public commit +`113c95c21e57227b4675c9fda015ada59cc9e9a6` (tree +`a2aeb4dac22853cb3894e3e487b94bbeff5051e5`) is only the pre-beta +platform baseline. Any documentation, versioning, or code change produces a new +candidate and requires the candidate matrix to run again before tagging. + +## RC and final gates + +No release candidate or v1.0.0 release occurs until every applicable gate in +this repository is evidenced, including cross-platform deterministic +generation, temporary-module compilation, fuzz/adversarial suites, +race/vet/vulnerability/license checks on the latest two supported Go lines, +development-supervisor failure tests, and reproducible repository-owned +benchmark and security results. + +Release candidates require a clean canonical checkout, reviewed changelog, +compatible vanity-import metadata, reproducible binaries, signed annotated +tags, checksums, SBOMs, vulnerability results, and verification on Linux, +macOS, and Windows. + +## Public source and artifacts Gitea is the only canonical public forge. Public source is exported into a -separate, sanitized Gitea repository with fresh history; private development -history and the private-to-public commit mapping are not published. A -sanitized GitHub discovery snapshot may copy reviewed public source, but it is -not an issue, contribution, release, or module origin and must never receive -private development refs or an indiscriminate Git mirror. Release binaries and -provenance are built from the reviewed canonical Gitea commit. Compiler -documentation, binaries, checksums, SBOMs, and the independently versioned -runtime tag form the coordinated v1 release. Example applications and product -sites keep their own history, deployment, and evidence. +separate, sanitized Gitea repository with fresh reviewed history. A sanitized +GitHub discovery snapshot may copy reviewed public source, but it is not an +issue, contribution, release, or module origin and must never receive private +development refs or an indiscriminate Git mirror. Release binaries and +provenance are built from the reviewed canonical Gitea commit. The hosting configuration must answer exact package discovery requests, not only module-root pages. In particular, `/sandwich-hime/cmd/himesan?go-get=1` returns compiler metadata and the -`/sandwich-hime/sando` subtree returns runtime metadata. After signed tags and -public metadata exist, run `scripts/verify-public-install.sh --version -vX.Y.Z`; it exercises the documented `go install` and `go get` commands from -fresh direct-fetch and public-proxy caches. This post-publication check is -separate from the pre-tag, read-only `scripts/release-check.sh`. +`/sandwich-hime/sando` subtree returns runtime metadata. After tags and public +metadata exist, run: -Release notes report hardware, commit, datasets, commands, `ns/op`, allocations, response latency, and methodology for performance claims. “Fastest” or equivalent language is prohibited without durable, reproducible evidence. +```sh +scripts/verify-public-install.sh --version vX.Y.Z +``` + +That check exercises the documented `go install` and `go get` commands from +fresh direct-fetch and public-proxy caches. It is separate from the pre-tag, +read-only `scripts/release-check.sh`. + +Release notes report hardware, commit, datasets, commands, `ns/op`, +allocations, response latency, and methodology for any performance claim. +“Fastest” or equivalent language is prohibited without durable, reproducible +evidence. Production applications compile and deploy their committed `.sando.go` files with the Apache-2.0 `sando` runtime. They do not need the AGPL compiler or the diff --git a/ROADMAP.md b/ROADMAP.md index adabf40..fb00664 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -2,41 +2,77 @@ # Proof-in-the-pudding roadmap -Unchecked items are release blockers, not aspirational marketing. +Unchecked items are release blockers for the milestone that contains them, not +necessarily blockers for an earlier prerelease. The ordered initiative, +repository topology, release-candidate sequence, and definition of confidence +are maintained in [docs/V1_RELEASE_PLAN.md](docs/V1_RELEASE_PLAN.md). -The ordered initiative, repository topology, release-candidate sequence, and -definition of confidence are maintained in -[docs/V1_RELEASE_PLAN.md](docs/V1_RELEASE_PLAN.md). +## Beta 1: public learning and evaluation -## Compiler and runtime +Beta 1 deliberately ships before the final-v1 compatibility and artifact gates. +Its scope is classroom use, learning, prototypes, and compatibility feedback; +it is not a production-stability promise. -- [ ] Compiler-owned deterministic golden output repeated across Linux, macOS, and Windows. -- [ ] Temporary consumer modules compile using committed Go and only the Apache runtime. -- [ ] Parser, delimiter, context, path, and source-map fuzz targets survive the release campaign. -- [ ] Adversarial escaping and filesystem cases are evidenced. -- [ ] Latest two Go lines pass test, race, vet, vulnerability, and license gates. -- [ ] Signed compiler/runtime release artifacts, checksums, and SBOMs reproduce. +- [x] Define beta versus RC/final support and compatibility policy. +- [x] Establish a public pre-beta Linux/Windows matrix on Go 1.25 and Go 1.26. +- [x] Document macOS as provisional and invite useful community reports while + retaining maintainer responsibility for security and releases. +- [ ] Rerun all required Windows/Linux checks and deterministic generation on + the exact Beta 1 candidate. +- [ ] Publish immutable `sando/v1.0.0-beta.1`, then + `v1.0.0-beta.1`, from the reviewed public commit. +- [ ] Verify clean direct and public-proxy installs after publication. +- [ ] Complete native macOS maintainer validation. This is an RC/final gate, + not a Beta 1 gate. -## Development supervisor +## Compiler and runtime for RC/final -- [ ] Generation/build/start/health failures keep the previous healthy server live. -- [ ] SSE reconnect/reload and mapped overlay diagnostics pass browser-level tests. -- [ ] CSP hash injection, fragment/API/download exclusion, and cache disabling pass. -- [ ] Replaced and interrupted child processes leave no descendants on supported systems. +- [ ] Freeze and machine-check the compiler, CLI, diagnostic, schema, generated, + and runtime compatibility contracts. +- [ ] Repeat compiler-owned deterministic golden output across Linux, macOS, + and Windows on the exact candidate. +- [ ] Compile temporary consumer modules using committed Go and only the Apache + runtime. +- [ ] Run the parser, delimiter, context, path, and source-map release fuzz + campaign. +- [ ] Evidence adversarial escaping and filesystem cases. +- [ ] Pass test, race, vet, vulnerability, and license gates on the latest two + supported Go lines. +- [ ] Reproduce signed compiler/runtime release artifacts, checksums, and SBOMs. + +## Development supervisor for RC/final + +- [ ] Generation/build/start/health failures keep the previous healthy server + live. +- [ ] SSE reconnect/reload and mapped overlay diagnostics pass browser-level + tests. +- [ ] CSP hash injection, fragment/API/download exclusion, and cache disabling + pass. +- [ ] Replaced and interrupted child processes leave no descendants on + supported systems. ## Repository-owned release evidence -- [ ] Contextual escaping is differentially tested against Go's documented `html/template` safety baseline. -- [ ] Repository-owned synthetic benchmark cases and methodology are reproducible from a clean checkout. -- [ ] Generated output is reviewed for stable provenance, source mappings, and absence of compiler-license headers. -- [ ] Production application boundaries are documented: committed generated Go plus the Apache runtime, with no compiler or development supervisor in the deployed binary. -- [ ] Unsupported or unmeasured performance and production claims are absent from release materials. +- [ ] Differentially test contextual escaping against Go's documented + `html/template` safety baseline. +- [ ] Reproduce repository-owned synthetic benchmark cases and methodology from + a clean checkout. +- [ ] Review generated output for stable provenance, source mappings, and + absence of compiler-license headers. +- [ ] Document the production boundary: committed generated Go plus the Apache + runtime, with no compiler or development supervisor in the deployed binary. +- [ ] Keep unsupported or unmeasured performance and production claims out of + release materials. -## Public launch +## Final public launch -- [ ] Ownership notices, output permission, DCO contribution process, and pre-registration trademark terms receive final human review. -- [ ] Name clearance, security mailbox, two-person credential recovery, and signing keys complete. -- [ ] `gamertan.com` vanity-import metadata and documented installs verified from a clean machine. -- [ ] Sanitized fresh-history public Gitea snapshot contains no private paths, identifiers, history, or unsupported release claims. -- [x] Canonical public Gitea source and project documentation launch, with any - secondary forge explicitly limited to a sanitized discovery snapshot. +- [ ] Complete final human review of ownership notices, output permission, DCO + contribution process, and pre-registration trademark terms. +- [ ] Complete name clearance, security-mailbox recovery, release signing, and + two-person credential recovery. +- [ ] Verify `gamertan.com` vanity metadata and documented installs from clean + machines. +- [ ] Confirm the sanitized public Gitea source contains no private paths, + identifiers, history, or unsupported claims. +- [ ] Publish and observe a signed RC on every supported native platform. +- [ ] Publish `sando/v1.0.0`, then `v1.0.0`, without moving either tag. diff --git a/SECURITY.md b/SECURITY.md index ae146af..939e278 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -2,21 +2,28 @@ # Security policy -Sandwich Hime is a public pre-1.0 source preview. Security reports are welcome -now, even though no version is currently designated as supported for production -use. The project would rather receive a careful early report than project -confidence it has not earned. +Sandwich Hime `v1.0.0-beta.1` is supported within a deliberately narrow +scope: learning, classroom projects, evaluation, and compatibility testing. +Security reports are welcome and receive best-effort maintainer assessment and +fixes while Beta 1 is the current prerelease. This is not production support, +an SLA, a fitness guarantee, or a promise that a fix will preserve beta APIs. + +The community is invited to help find compatibility gaps, especially on macOS. +That invitation does not outsource security assurance. Maintainers retain +responsibility for vulnerability review, triage, remediation decisions, +advisories, and release decisions. ## Supported versions | Version | Security status | | --- | --- | -| Public `main` source preview | Best-effort assessment and fixes; interfaces may change | -| Versioned releases | None published yet | +| `v1.0.0-beta.1` and `sando/v1.0.0-beta.1` | Current evaluation/classroom prerelease once published; best-effort security assessment and fixes; interfaces may change | +| Public `main` | Development source; reports welcome, but no compatibility or production-support promise | +| Older prereleases | Superseded when a newer prerelease or final version is published; reports are still triaged to determine affected versions | -This table will name supported release lines once immutable compiler and runtime -versions are published. A pre-1.0 release is not a promise of API stability or -fitness for a particular application. +Beta support lasts until it is superseded or explicitly withdrawn in the +supported-version table and release notes. Published tags are immutable. A +security fix is issued as a new version, never by silently replacing a tag. ## Report a vulnerability privately @@ -24,6 +31,12 @@ Email **security@sandwichhime.com**. Please do not put an undisclosed vulnerability, working exploit, credential, secret, or personal data in a public issue. +If that new mailbox rejects or bounces a message, retain the report and open a +canonical Gitea issue containing only the fact that the private security contact +failed. Do not include technical details or sensitive data. The maintainer will +publish a corrected private route. Ordinary usage, classroom, and macOS +compatibility reports that do not reveal a vulnerability may use a public issue. + Helpful reports include: - the affected compiler/runtime version or exact commit; @@ -40,7 +53,9 @@ ownership, backup, and recovery procedure have been tested. ## What to expect -These are best-effort targets for a founder-maintained project, not an SLA: +These are best-effort targets for a founder-maintained project, not an SLA. +They describe maintainer responsibilities; asking the community to test a beta +does not ask reporters to investigate or remediate it: - acknowledge a report within 7 calendar days; - provide an initial severity/scope assessment within 14 calendar days when a @@ -118,8 +133,11 @@ an independent security audit, certification, or formal verification. Coverage percentages, passing scanners, and a clean vulnerability database result are evidence of specific checks—not proof that no vulnerability exists. -Release artifacts and tags are intended to carry signatures, checksums, an -SBOM, and exact source/build provenance. Those controls are publication gates -until the first versioned release is actually available. +Beta 1 publication requires signed annotated source tags, but may precede the +complete prebuilt-artifact and key-recovery system. Signed binaries, checksums, +an SBOM, reproducible archives, and complete source/build provenance are +release-candidate and final-v1 gates. Their absence from a source-only beta must +not be read as evidence of artifact authenticity beyond the verified tag and +canonical source. This policy is practical project guidance, not legal advice. diff --git a/TRADEMARKS.md b/TRADEMARKS.md index 844aacc..1a2eb65 100644 --- a/TRADEMARKS.md +++ b/TRADEMARKS.md @@ -12,4 +12,4 @@ Community discussion, commentary, criticism, tutorials, and truthful nominative Trademark permission does not supply a copyright license for artwork. If the project publishes an official flag, mascot, or “Built with Sandwich Hime” badge, that asset must identify its own copyright holder and reuse license before others are asked to copy it. -This policy grants permission only to the extent the project steward controls the relevant rights. It is not a claim that a mark is registered, cleared in every territory, or legally exclusive, and it does not override uses permitted by applicable law. Professional clearance and qualified legal advice remain prudent before registration, enforcement, or material investment in a mark; they are not represented as prerequisites to publishing the unsupported source preview. +This policy grants permission only to the extent the project steward controls the relevant rights. It is not a claim that a mark is registered, cleared in every territory, or legally exclusive, and it does not override uses permitted by applicable law. Professional clearance and qualified legal advice remain prudent before registration, enforcement, or material investment in a mark; they are not represented as prerequisites to publishing the current narrowly scoped public beta. diff --git a/docs/COMPATIBILITY.md b/docs/COMPATIBILITY.md index 23075f7..6720131 100644 --- a/docs/COMPATIBILITY.md +++ b/docs/COMPATIBILITY.md @@ -2,10 +2,69 @@ # 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. +## Beta 1 contract -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. +`v1.0.0-beta.1` and `sando/v1.0.0-beta.1` are semantic-version +prereleases. They are supported for learning, classroom projects, evaluation, +and compatibility testing. Before final v1, source syntax, generated output, +the runtime API, CLI behavior, diagnostics, and configuration may change +without compatibility shims. Every public change must still be documented and +generation must remain deterministic. -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 beta is not a production-stability commitment. Maintainers accept and +triage security reports within the boundary described in +[SECURITY.md](../SECURITY.md), but cannot promise that a beta fix preserves its +public API. -The project makes no compatibility promise for internal packages, development SSE payloads before v1, or hand-edited generated files. +## Final-v1 contract + +At final 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. + +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 final v1, or hand-edited generated files. + +## Go and platform support + +Beta 1 targets Go 1.25 and Go 1.26. Support is based on point-in-time, +maintainer-run release matrices, not an implication of continuous CI coverage. +A Go support change is announced in release notes before it takes effect. + +The current public evidence is a **pre-beta baseline** on commit +`113c95c21e57227b4675c9fda015ada59cc9e9a6` (tree +`a2aeb4dac22853cb3894e3e487b94bbeff5051e5`): + +| Platform | Go lanes | Maintainer-run result | +| --- | --- | --- | +| Windows 11/amd64 on NTFS | 1.25.12, 1.26.5 | Native tests, race, vet, builds, generation, process cleanup, watcher boundaries, and temporary consumer compilation passed; privileged symlink and POSIX-only permission cases were not exercised | +| Linux/amd64 on WSL2 with an ext4 checkout | 1.25.12, 1.26.5 | Tests, race, vet, builds, generation, focused filesystem/development cases, and license checks passed | +| Linux/amd64 in isolated containers on a Linux server | 1.25.12, 1.26.5 | Tests, race, vet, builds, deterministic generation, and license checks passed | +| macOS | — | Native maintainer validation pending; provisional for Beta 1 | + +The golden generated file had SHA-256 +`63fa75a3049a3a8a12d769d7f9b6b510dfe763baacf706775b75cef2c57a984f` +on every tested Windows and Linux lane. + +Because the Beta 1 candidate contains changes after that public baseline, the +complete Windows/Linux matrix must be rerun on the exact candidate before the +tags are published. The baseline does not become beta evidence merely because +its code is nearby in history. + +## macOS feedback + +Mac learners, teachers, and Go developers are warmly invited to try the beta. +A useful compatibility report includes the macOS version, Intel or Apple +Silicon architecture, `go version`, the exact command, and a minimal +reproduction or diagnostic output. Ordinary compatibility reports belong on +the canonical Gitea project. Suspected vulnerabilities must use the private +route in [SECURITY.md](../SECURITY.md). + +Community reports can reveal gaps and help prioritize maintainer testing. They +do not constitute an independent audit or shift responsibility for security +review, triage, fixes, and release decisions to the community. diff --git a/docs/SECURITY_EVIDENCE.md b/docs/SECURITY_EVIDENCE.md index 1833ece..fda9a51 100644 --- a/docs/SECURITY_EVIDENCE.md +++ b/docs/SECURITY_EVIDENCE.md @@ -11,19 +11,30 @@ verification, or guarantee that no vulnerability exists. | Field | Value | | --- | --- | | Assessment date | 2026-08-12 | -| Public evidence identity | Exact file checksums in the co-published `PUBLIC-SNAPSHOT.sha256`; private/public commit mapping is retained only in the non-exported operational ledger | -| Assessment phases | Clean pre-remediation source followed by clean remediated source | -| Primary environment | Linux amd64 under WSL, Go 1.26.5 | +| Evidence sets | Clean security self-assessment plus an exact-commit pre-beta platform baseline; neither is evidence for the later Beta 1 candidate | +| Public commit | `113c95c21e57227b4675c9fda015ada59cc9e9a6` | +| Public tree | `a2aeb4dac22853cb3894e3e487b94bbeff5051e5` | +| Maintainer-run environments | Windows 11/amd64 on NTFS; Ubuntu 20.04/amd64 under WSL2 on ext4; Linux/amd64 server containers | +| Supported Go lanes exercised | Go 1.25.12 and Go 1.26.5 | | Declared minimum Go | Go 1.25 | | Assessor | Project maintainer with AI-assisted code review; human responsibility retained | -Security remediation discovered during this assessment was committed and the -named checks were rerun from a clean source state. Before this ledger can support -a versioned release, the complete campaign must be rerun from the exact -sanitized public release commit. Private-to-public commit mappings are retained -outside the exported source rather than being disclosed here. +The named platform runs used the exact public commit and tree above. Hostnames, +network addresses, account names, private paths, private repository identities, +and private commit mappings are intentionally absent from this public ledger. -## Observed evidence +Beta 1 necessarily changes the tree through versioning, provenance, +documentation, or source fixes. Therefore this baseline cannot be relabeled as +Beta 1 evidence. The required Windows/Linux campaign must pass again on the +exact Beta 1 candidate before either tag is published. Native macOS execution +remains pending and is provisional for the beta. + +## Observed security self-assessment evidence + +These commands were observed on clean remediated source during the dated +assessment. Except where the exact-commit platform matrix below says otherwise, +the table does not claim that every command was rerun on the named public +baseline commit. | Property examined | Enforcement or test surface | Result observed on 2026-08-12 | | --- | --- | --- | @@ -41,7 +52,7 @@ outside the exported source rather than being disclosed here. | URL scheme handling | ordinary/trusted URL test matrix | Pass for enumerated cases | | Filesystem boundaries | symlink, nested-module, VCS, ownership, stale-output tests | Pass for tested cases; see open findings | | Development proxy browser boundary | Host, Origin, Fetch Metadata, CSP, fragment and response tests | Pass for tested cases | -| Native platform behavior | Linux execution; Windows/macOS cross-compilation | Native Windows/macOS execution not yet evidenced | +| Platform behavior | Native Windows and executed Linux matrices; macOS cross-compilation | Windows/Linux pass for tested lanes; native macOS pending | Coverage measures statements executed by tests. It is not branch completeness and is not evidence that the executed behavior is secure. @@ -50,6 +61,31 @@ and is not evidence that the executed behavior is secure. and reachable through its analysis. A clean result cannot detect unknown flaws, design errors, or vulnerabilities outside its model. +## Pre-beta native compatibility matrix + +These are maintainer-run, point-in-time results, not continuous CI and not an +independent audit. + +| Environment | Go lanes | Commands and focused evidence | Result and limits | +| --- | --- | --- | --- | +| Windows 11/amd64, NTFS | 1.25.12, 1.26.5 | Native PowerShell verifier with race; root/runtime tests, vet, trimpath build, freshness, two generation passes, process-tree cleanup, watcher boundaries, and temporary consumer compilation | Pass. Symlink-output rejection skipped because the test account lacked symlink privilege; the read-only-directory case is POSIX-only | +| Ubuntu 20.04/amd64 under WSL2, native ext4 checkout | 1.25.12, 1.26.5 | Race-enabled verifier; root/runtime tests, vet, build, two generation passes, ten focused filesystem cases, five focused development-process/watcher cases, and license check | Pass. This is Linux execution under WSL2, not bare-metal or Linux/arm64 evidence | +| Linux/amd64 server containers | 1.25.12, 1.26.5 | Root/runtime tests, vet, builds, race, licensing, and deterministic generation in sequential isolated official Go containers | Pass. Container resources were capped at 1 CPU and 2 GiB; this is not Linux/arm64 evidence | +| macOS | — | Cross-compilation only | Native maintainer execution pending; provisional for Beta 1 | + +The generated golden `basic.sando.go` was 1,399 bytes and had SHA-256 +`63fa75a3049a3a8a12d769d7f9b6b510dfe763baacf706775b75cef2c57a984f` +on every tested Windows and Linux lane. Repeated generation also preserved its +timestamp. This demonstrates cross-host agreement for one compiler-owned +fixture, not equivalence for every possible template. + +Mac learners and Go developers are warmly invited to report ordinary +compatibility results with macOS version, architecture, `go version`, exact +command, and a minimal reproduction. Suspected vulnerabilities use the private +route in [SECURITY.md](../SECURITY.md). Community reports help find gaps; +maintainers remain responsible for reproducing security-relevant behavior, +triage, remediation, and release decisions. + ## Security-relevant design evidence ### Production boundary @@ -115,8 +151,8 @@ not yet prove semantic HTML safety. ## Assessment findings and remediation status -The 2026-08-12 assessment identified six concrete gaps. Their current -working-tree status is recorded here without rewriting the original baseline: +The 2026-08-12 assessment identified six concrete gaps. Their status in the +named public pre-beta baseline is recorded here: | Finding | Current remediation | Executable evidence | | --- | --- | --- | @@ -127,19 +163,26 @@ working-tree status is recorded here without rewriting the original baseline: | Trusted-value warnings were described more broadly than their analysis supports | Policy and threat-model copy now call them best-effort lexical audit hints rather than type or taint analysis | Documentation assertion and review | | Public copy implied a completed systematic `html/template` differential campaign | Policy and public security copy now describe fixed adversarial cases and list systematic differential work as open | Documentation assertion and review | -The remediated clean source passed the race-enabled repository verifier, -sanitized-snapshot tests, both bounded fuzz-smoke targets, compiler/runtime -known-vulnerability scans, and Windows/macOS cross-compilation on 2026-08-12. -Those results do not become release evidence until the changes are committed, -exported to the sanitized canonical public tree, and re-run from that exact -public commit. Native Windows/macOS execution and the other gaps below remain -separate release decisions. +The clean remediated assessment source passed the race-enabled repository +verifier, sanitized-snapshot tests, both bounded fuzz-smoke targets, +compiler/runtime known-vulnerability scans, and Windows/macOS cross-compilation +on 2026-08-12. Separately, the exact public pre-beta commit passed the native +Windows and executed Linux matrices recorded above. These results still do not +become Beta 1 evidence: both sets of required checks must run on the exact +candidate after all candidate changes. Native macOS and the other gaps below +remain separate release decisions. ## Open assurance gaps +- the exact Beta 1 candidate Windows/Linux matrix and post-tag install checks + must still run; - confidential mailbox delivery and response/recovery procedure must be tested; -- release signing, checksum, SBOM, and provenance rehearsal is incomplete; -- native Windows/macOS execution remains outstanding; +- SSH tag-signing rehearsal passed, but the candidate tags still require + post-publication verification; prebuilt-artifact signing, checksums, SBOM, + reproducible provenance, and key recovery remain incomplete; +- native macOS, Linux/arm64, and Windows/arm64 execution remain outstanding; +- Windows symlink rejection was not natively exercised because the test account + lacked symlink privilege; - browser-parser differential and semantic property testing need expansion; - compiler input size, CPU, and memory have no built-in hard budget; - filesystem checks do not defend against a hostile local actor racing path diff --git a/docs/V1_RELEASE_PLAN.md b/docs/V1_RELEASE_PLAN.md index ae7654e..b10311f 100644 --- a/docs/V1_RELEASE_PLAN.md +++ b/docs/V1_RELEASE_PLAN.md @@ -7,55 +7,83 @@ accumulate features. The intended product is already visible: an HTML-first, ahead-of-time template engine for Go, typed generated components, a small HTTP-independent runtime, and an optional opinionated local development loop. -The private development initiative lives on `codex/v1-launch` in -`sandwich-hime-dev`. Public releases never originate from that private history. +Development records may remain private, but their repository names, branch +names, paths, commit mappings, and history are not release provenance. Public +releases originate only from the reviewed canonical public tree. ## Repository and publication topology | Surface | Purpose | History and tags | | --- | --- | --- | -| Private Gitea `sandwich-hime-dev` | development, working branches, private review records, and historical context | normal private history; no public release tags | -| Public Gitea `sandwich-hime` | canonical sanitized source, contribution venue, module origin, releases, and signed tags | fresh reviewed publication history; authoritative `sando/vX.Y.Z` and `vX.Y.Z` tags | -| GitHub `gamertan/sandwich-hime` | discoverability and a convenient sanitized source snapshot | no private refs, force-mirrors, workflows, contribution authority, release artifacts, or semver tags | +| Private development storage | Working branches, private review records, and historical context | identities and history are not exported; no public release tags | +| Public Gitea `sandwich-hime` | Canonical sanitized source, contribution venue, module origin, and releases | fresh reviewed history; authoritative immutable `sando/vX.Y.Z` and `vX.Y.Z` tags | +| GitHub `gamertan/sandwich-hime` | Discoverability and a convenient sanitized source snapshot | no private refs, force-mirrors, workflows, contribution authority, release artifacts, or semver tags | Each public update is exported through the exact committed allowlist, inspected, committed as a fresh public snapshot, and compared byte-for-byte with the -reviewed export. GitHub receives that public tree only. It never receives the -private repository or an indiscriminate Git mirror. +reviewed export. GitHub receives that public tree only. It never receives +private history or an indiscriminate Git mirror. ## Current readiness -At the 2026-08-12 v1 initiative baseline, the project is a strong engineering -preview, but not yet a release candidate. Exact private/public commit mappings -remain in the non-exported operational ledger. +Beta 1 is deliberately earlier than a release candidate. It creates a real, +repeatable install for learners and evaluators without claiming that the final +v1 compatibility, native-platform, artifact, signing, or soak gates are +complete. -### Demonstrated now +### Demonstrated in the pre-beta public baseline -- race-enabled tests, vet, builds, deterministic generation, license checks, - and sanitized-export tests pass on Linux; -- the compiler module and nested `sando` runtime declare zero third-party Go - module requirements; -- generated/runtime compatibility uses a version-specific compile-time ABI - marker with an incompatible-runtime regression; -- owned-output, orphan, stale, symlink, nested-module, restrictive-permission, - last-good, writer-error, and enumerated contextual-output cases are tested; -- the development proxy is loopback-only, browser-origin hardened, and clears - a dead selected upstream immediately; and -- the security policy, threat model, and dated evidence ledger state both the - demonstrated controls and the unresolved limits. +Public commit `113c95c21e57227b4675c9fda015ada59cc9e9a6` (tree +`a2aeb4dac22853cb3894e3e487b94bbeff5051e5`) passed maintainer-run Go +1.25.12 and Go 1.26.5 matrices on native Windows/amd64, Linux/amd64 under WSL2, +and isolated Linux/amd64 server containers. The same generated golden SHA-256 +was observed across those lanes. + +That result is a pre-beta baseline only. The exact Beta 1 candidate must rerun +the required Windows/Linux matrix after all version, documentation, and source +changes and before tags are created. + +Other demonstrated controls include: + +- zero third-party Go module requirements in the compiler and nested `sando` + runtime; +- a version-specific compile-time runtime ABI marker; +- owned-output, orphan, stale, symlink, nested-module, permission, last-good, + writer-error, and enumerated contextual-output tests; +- loopback-only, browser-origin-hardened development proxy behavior; and +- a public threat model, security policy, and dated evidence ledger. ### Not demonstrated yet -- native Windows and macOS execution of the complete supported matrix; -- a stable public API/CLI/schema snapshot and compatibility test; +- native maintainer-run macOS execution; macOS is provisional for Beta 1; +- stable final-v1 API, CLI, schema, diagnostic, and generated snapshots; - systematic browser-parser and `html/template` differential testing; - a long semantic fuzz campaign beyond bounded no-panic smoke; -- committed, reproducible comparative benchmarks and a predefined regression - threshold; -- real-browser SSE/reload/overlay evidence for `himesan dev`; -- deterministic release artifacts, checksums, SBOMs, signatures, and tested - signing/recovery procedures; or -- clean direct and public-proxy installation of signed release tags. +- committed comparative benchmarks and predefined regression thresholds; +- complete real-browser development-supervisor evidence; +- deterministic prebuilt archives, checksums, SBOMs, signed binaries, and + tested signing/recovery procedures; or +- clean direct and public-proxy installation of the not-yet-published Beta 1 + tags. + +## Beta 1 publication lane + +Beta 1 is supported for learning, classroom projects, evaluation, prototypes, +and compatibility feedback. It is not recommended as a production-stable +dependency, and its interfaces may change. + +- [x] Define beta support, security, compatibility, and macOS-provisional + language. +- [x] Establish the named public pre-beta Linux/Windows baseline. +- [ ] Rerun the supported Go matrix and deterministic generation on the exact + Beta 1 candidate. +- [ ] Run the candidate-version freshness, bounded fuzz, vulnerability, and + license gates. +- [ ] Publish immutable `sando/v1.0.0-beta.1`, then + `v1.0.0-beta.1`, from the same reviewed public commit. +- [ ] Verify clean direct and public-proxy installs and record the result. +- [ ] Add native macOS maintainer evidence before RC; community reports inform + that work but do not replace maintainer responsibility. ## Milestone 1: contract freeze @@ -126,8 +154,8 @@ Required before security/platform release-candidate work is declared complete: 4. Run the complete evidence suite again from the exact public commit. 5. Operate the official Sandwich Hime website on the RC runtime for a 14-day observation period with no unresolved Hime render, security, accessibility, - or rollback regression. This is product dogfooding, not a dependency on EQL - or another application's private repository. + or rollback regression. This is product dogfooding, not a dependency on + another application's private repository. 6. Fix findings in a new RC; restart the observation period when the affected boundary warrants it. 7. Finalize the changelog, supported-version table, migration notes, release diff --git a/internal/compiler/backend.go b/internal/compiler/backend.go index 3c27e44..58e62f4 100644 --- a/internal/compiler/backend.go +++ b/internal/compiler/backend.go @@ -316,6 +316,28 @@ func auditTrustCalls(file *sourceFile) []Diagnostic { return diagnostics } -func bytesEqual(a, b []byte) bool { - return bytes.Equal(a, b) +// generatedCodeEqual compares the freshness-relevant portions of two +// generated files. The compiler release is informational provenance: changing +// only that line must not make otherwise identical output stale. Every other +// byte remains part of the generated-code contract. +func generatedCodeEqual(a, b []byte) bool { + if bytes.Equal(a, b) { + return true + } + aBody, aOK := generatedCodeWithoutCompilerVersion(a) + bBody, bOK := generatedCodeWithoutCompilerVersion(b) + return aOK && bOK && bytes.Equal(aBody, bBody) +} + +func generatedCodeWithoutCompilerVersion(code []byte) ([]byte, bool) { + prefix := []byte(generatedPrefix + "\n// himesan:compiler ") + if !bytes.HasPrefix(code, prefix) { + return nil, false + } + remainder := code[len(prefix):] + lineEnd := bytes.IndexByte(remainder, '\n') + if lineEnd <= 0 { + return nil, false + } + return remainder[lineEnd:], true } diff --git a/internal/compiler/compiler_test.go b/internal/compiler/compiler_test.go index 868d1f6..40e9e19 100644 --- a/internal/compiler/compiler_test.go +++ b/internal/compiler/compiler_test.go @@ -67,11 +67,42 @@ func TestCommittedGoldenOutput(t *testing.T) { wantPath := sourcePath + ".go" compiled, diagnostics := compileWithMapping(sourcePath, mustRead(t, sourcePath), "internal/compiler/testdata/golden/basic.sando") assertNoErrorDiagnostics(t, diagnostics) - if want := mustRead(t, wantPath); !bytes.Equal(compiled.Code, want) { + if want := mustRead(t, wantPath); !generatedCodeEqual(compiled.Code, want) { t.Fatalf("committed golden output is stale; run himesan generate\n--- got ---\n%s\n--- want ---\n%s", compiled.Code, want) } } +func TestGeneratedCodeEqualityIgnoresOnlyCompilerProvenance(t *testing.T) { + t.Parallel() + compiled, diagnostics := Compile("hello.sando", []byte(simpleSource("Hello", "hello"))) + assertNoErrorDiagnostics(t, diagnostics) + + beta := replaceGeneratedCompilerVersion(t, compiled.Code, "v1.0.0-beta.1") + if !generatedCodeEqual(compiled.Code, beta) { + t.Fatal("compiler provenance alone made generated output unequal") + } + + changes := map[string][]byte{ + "runtime ABI": bytes.Replace(beta, []byte("himesan:runtime-abi sando.v1"), []byte("himesan:runtime-abi sando.v2"), 1), + "source digest": bytes.Replace(beta, []byte("himesan:source-sha256"), []byte("himesan:source-sha257"), 1), + "generated semantics": bytes.Replace(beta, []byte(".WriteString("), []byte(".WriteText("), 1), + "missing provenance marker": bytes.Replace(beta, []byte("// himesan:compiler "), []byte("// compiler: "), 1), + "empty provenance": replaceGeneratedCompilerVersion(t, beta, ""), + } + for name, changed := range changes { + name, changed := name, changed + t.Run(name, func(t *testing.T) { + t.Parallel() + if bytes.Equal(beta, changed) { + t.Fatalf("test mutation %q did not change generated output", name) + } + if generatedCodeEqual(compiled.Code, changed) { + t.Fatalf("generatedCodeEqual ignored %s change", name) + } + }) + } +} + func TestHeaderAllowsBOMWhitespaceAndGoLexicalDelimiters(t *testing.T) { t.Parallel() source := "\xef\xbb\xbf \r\n\t\"` })\n?>\n

\" ?>

" @@ -580,6 +611,24 @@ func mustRead(t *testing.T, path string) []byte { return content } +func replaceGeneratedCompilerVersion(t *testing.T, code []byte, compilerVersion string) []byte { + t.Helper() + prefix := []byte(generatedPrefix + "\n// himesan:compiler ") + if !bytes.HasPrefix(code, prefix) { + t.Fatal("generated output has no compiler provenance line") + } + remainder := code[len(prefix):] + lineEnd := bytes.IndexByte(remainder, '\n') + if lineEnd < 0 { + t.Fatal("generated compiler provenance line has no terminator") + } + replaced := make([]byte, 0, len(code)-lineEnd+len(compilerVersion)) + replaced = append(replaced, prefix...) + replaced = append(replaced, compilerVersion...) + replaced = append(replaced, remainder[lineEnd:]...) + return replaced +} + func assertNoErrorDiagnostics(t *testing.T, diagnostics []Diagnostic) { t.Helper() if hasErrors(diagnostics) { diff --git a/internal/compiler/e2e_test.go b/internal/compiler/e2e_test.go index 6735d68..193fab0 100644 --- a/internal/compiler/e2e_test.go +++ b/internal/compiler/e2e_test.go @@ -3,7 +3,9 @@ package compiler import ( + "bytes" "context" + "encoding/json" "os" "os/exec" "path/filepath" @@ -12,6 +14,79 @@ import ( "testing" ) +func TestDevelopmentAndBetaBinariesShareGeneratedOutput(t *testing.T) { + if testing.Short() { + t.Skip("skipping compiler-binary integration in short mode") + } + t.Parallel() + + _, thisFile, _, ok := runtime.Caller(0) + if !ok { + t.Fatal("runtime.Caller failed") + } + repositoryRoot := filepath.Clean(filepath.Join(filepath.Dir(thisFile), "..", "..")) + developmentBinary := buildHimesanBinary(t, repositoryRoot, "himesan-development", "") + betaVersion := "v1.0.0-beta.1" + betaBinary := buildHimesanBinary(t, repositoryRoot, "himesan-beta", "-X gamertan.com/sandwich-hime/internal/version.Compiler="+betaVersion) + + if got := compilerVersionFromBinary(t, developmentBinary, repositoryRoot); got != "0.1.0-dev" { + t.Fatalf("development binary version = %q, want 0.1.0-dev", got) + } + if got := compilerVersionFromBinary(t, betaBinary, repositoryRoot); got != betaVersion { + t.Fatalf("beta binary version = %q, want %q", got, betaVersion) + } + + directory := resolvedTempDir(t) + mustWrite(t, filepath.Join(directory, "go.mod"), "module example.test/provenance\n\ngo 1.25\n") + sourcePath := filepath.Join(directory, "hello.sando") + mustWrite(t, sourcePath, ` +

Hello

+`) + runHimesanBinary(t, developmentBinary, directory, "generate", "hello.sando") + outputPath := sourcePath + ".go" + developmentOutput := mustRead(t, outputPath) + if !bytes.Contains(developmentOutput, []byte("// himesan:compiler 0.1.0-dev\n")) { + t.Fatalf("development compiler did not record honest provenance:\n%s", developmentOutput) + } + + runHimesanBinary(t, betaBinary, directory, "check", "hello.sando") + runHimesanBinary(t, betaBinary, directory, "generate", "hello.sando") + if after := mustRead(t, outputPath); !bytes.Equal(after, developmentOutput) { + t.Fatalf("beta compiler rewrote otherwise-current development provenance\n--- before ---\n%s\n--- after ---\n%s", developmentOutput, after) + } + + if err := os.Remove(outputPath); err != nil { + t.Fatal(err) + } + runHimesanBinary(t, betaBinary, directory, "generate", "hello.sando") + betaOutput := mustRead(t, outputPath) + if !bytes.Contains(betaOutput, []byte("// himesan:compiler "+betaVersion+"\n")) { + t.Fatalf("beta compiler did not record honest provenance:\n%s", betaOutput) + } + runHimesanBinary(t, developmentBinary, directory, "check", "hello.sando") + runHimesanBinary(t, developmentBinary, directory, "generate", "hello.sando") + if after := mustRead(t, outputPath); !bytes.Equal(after, betaOutput) { + t.Fatalf("development compiler rewrote otherwise-current beta provenance\n--- before ---\n%s\n--- after ---\n%s", betaOutput, after) + } + + tampered := bytes.Replace(betaOutput, []byte(".WriteText("), []byte(".WriteAttr("), 1) + if bytes.Equal(tampered, betaOutput) { + t.Fatal("semantic tamper did not find generated WriteText call") + } + if err := os.WriteFile(outputPath, tampered, 0o644); err != nil { + t.Fatal(err) + } + command := exec.Command(betaBinary, "check", "hello.sando") + command.Dir = directory + output, err := command.CombinedOutput() + if err == nil || !strings.Contains(string(output), "HIM2204") { + t.Fatalf("beta check accepted semantic generated-code tamper: err=%v\n%s", err, output) + } +} + func TestGeneratedOutputCompilesInTemporaryModule(t *testing.T) { if testing.Short() { t.Skip("skipping temporary-module compilation in short mode") @@ -81,3 +156,46 @@ func Page(view View) t.Fatal("generated output leaked the compiler checkout path") } } + +func buildHimesanBinary(t *testing.T, repositoryRoot, name, linkerFlags string) string { + t.Helper() + if runtime.GOOS == "windows" { + name += ".exe" + } + path := filepath.Join(t.TempDir(), name) + arguments := []string{"build", "-trimpath"} + if linkerFlags != "" { + arguments = append(arguments, "-ldflags", linkerFlags) + } + arguments = append(arguments, "-o", path, "./cmd/himesan") + command := exec.Command("go", arguments...) + command.Dir = repositoryRoot + command.Env = append(os.Environ(), "GOWORK=off") + if output, err := command.CombinedOutput(); err != nil { + t.Fatalf("build %s: %v\n%s", name, err, output) + } + return path +} + +func compilerVersionFromBinary(t *testing.T, binary, directory string) string { + t.Helper() + output := runHimesanBinary(t, binary, directory, "version", "--json") + var information struct { + Compiler string `json:"compiler"` + } + if err := json.Unmarshal(output, &information); err != nil { + t.Fatalf("decode compiler version from %s: %v\n%s", binary, err, output) + } + return information.Compiler +} + +func runHimesanBinary(t *testing.T, binary, directory string, arguments ...string) []byte { + t.Helper() + command := exec.Command(binary, arguments...) + command.Dir = directory + output, err := command.CombinedOutput() + if err != nil { + t.Fatalf("%s %s: %v\n%s", binary, strings.Join(arguments, " "), err, output) + } + return output +} diff --git a/internal/compiler/operation.go b/internal/compiler/operation.go index 99d61f1..4b0f7b1 100644 --- a/internal/compiler/operation.go +++ b/internal/compiler/operation.go @@ -56,7 +56,7 @@ func Generate(ctx context.Context, paths []string) (Result, error) { break } existing, readErr := os.ReadFile(file.OutputPath) - if readErr == nil && bytesEqual(existing, file.Code) { + if readErr == nil && generatedCodeEqual(existing, file.Code) { result.Files[index].Changed = false result.Unchanged++ continue @@ -112,7 +112,7 @@ func Check(ctx context.Context, paths []string) (Result, error) { } continue } - if bytesEqual(existing, file.Code) { + if generatedCodeEqual(existing, file.Code) { result.Unchanged++ continue } diff --git a/internal/version/version_test.go b/internal/version/version_test.go index 1f4ac65..7b542ef 100644 --- a/internal/version/version_test.go +++ b/internal/version/version_test.go @@ -16,6 +16,7 @@ func TestSelectCompilerVersion(t *testing.T) { {name: "local build", linkerValue: developmentCompilerVersion, moduleVersion: "(devel)", want: developmentCompilerVersion}, {name: "missing build info", linkerValue: developmentCompilerVersion, moduleVersion: "", want: developmentCompilerVersion}, {name: "versioned go install", linkerValue: developmentCompilerVersion, moduleVersion: "v1.0.0", want: "v1.0.0"}, + {name: "beta launch install", linkerValue: developmentCompilerVersion, moduleVersion: "v1.0.0-beta.1", want: "v1.0.0-beta.1"}, {name: "versioned prerelease install", linkerValue: developmentCompilerVersion, moduleVersion: "v1.0.0-rc.1", want: "v1.0.0-rc.1"}, {name: "hyphenated prerelease install", linkerValue: developmentCompilerVersion, moduleVersion: "v1.2.3-beta-2", want: "v1.2.3-beta-2"}, {name: "pseudo version", linkerValue: developmentCompilerVersion, moduleVersion: "v0.0.0-20260811120000-0123456789ab", want: developmentCompilerVersion}, @@ -26,6 +27,9 @@ func TestSelectCompilerVersion(t *testing.T) { {name: "build metadata", linkerValue: developmentCompilerVersion, moduleVersion: "v1.0.0+build.1", want: developmentCompilerVersion}, {name: "leading zero release", linkerValue: developmentCompilerVersion, moduleVersion: "v01.0.0", want: developmentCompilerVersion}, {name: "leading zero numeric prerelease", linkerValue: developmentCompilerVersion, moduleVersion: "v1.0.0-rc.01", want: developmentCompilerVersion}, + {name: "leading zero numeric beta identifier", linkerValue: developmentCompilerVersion, moduleVersion: "v1.0.0-beta.01", want: developmentCompilerVersion}, + {name: "empty beta identifier", linkerValue: developmentCompilerVersion, moduleVersion: "v1.0.0-beta..1", want: developmentCompilerVersion}, + {name: "beta linker override wins", linkerValue: "v1.0.0-beta.1", moduleVersion: "(devel)", want: "v1.0.0-beta.1"}, {name: "linker override wins", linkerValue: "v1.0.0-rc.1", moduleVersion: "v1.0.0", want: "v1.0.0-rc.1"}, } for _, test := range tests { diff --git a/scripts/README.md b/scripts/README.md index 0e89331..442bda2 100644 --- a/scripts/README.md +++ b/scripts/README.md @@ -7,7 +7,7 @@ These scripts are intentionally understandable shell and PowerShell rather than - `verify.sh` runs root and nested-module tests and vet, builds `himesan`, checks the compiler-owned golden output, and proves two generation passes leave the same bytes and unchanged modification times. Set `HIMESAN_RACE=1` for race tests. - `verify.ps1` provides the equivalent native Windows lane; pass `-Race` to include the race detector. - `check-licenses.sh` enforces the AGPL compiler / Apache runtime boundary and prevents generated application Go from inheriting an AGPL identifier. -- `release-check.sh --version vX.Y.Z` is a clean-checkout technical preflight. Add `--public` and point `HIMESAN_RELEASE_EVIDENCE_DIR` at a human-reviewed evidence bundle for the public-launch gate. It never tags, pushes, publishes, or deploys. +- `release-check.sh --version vX.Y.Z` is a clean-checkout technical preflight, including exact candidate-version and generated-provenance checks. Beta publication follows the narrower prerelease gates in `RELEASE.md`; release candidates and final v1 additionally use `--public` with a human-reviewed `HIMESAN_RELEASE_EVIDENCE_DIR`. The script never tags, pushes, publishes, or deploys. - `verify-public-install.sh --version vX.Y.Z` is a post-tag/publication check. It verifies exact `go-get=1` package routes and runs the documented compiler install and runtime get from fresh direct-fetch and public-proxy caches without interactive Git credentials. The canonical Linux CI and release preflight also run bounded fuzz sessions for the parser/context compiler and Go-aware delimiter scanner. Seed-corpus execution remains part of ordinary `go test`; the bounded sessions are extra evidence, not a substitute for longer scheduled fuzzing before v1. diff --git a/scripts/release-check.sh b/scripts/release-check.sh index c79774f..ca57a8e 100755 --- a/scripts/release-check.sh +++ b/scripts/release-check.sh @@ -15,8 +15,9 @@ artifacts in the repository, pushes, or deploys. --version Candidate compiler version. The corresponding runtime tag is sando/vX.Y.Z. - --public Additionally require the human-reviewed launch evidence bundle - named by HIMESAN_RELEASE_EVIDENCE_DIR. + --public Require the human-reviewed RC/final launch evidence bundle named + by HIMESAN_RELEASE_EVIDENCE_DIR. Canonical beta prereleases may + run their narrower publication preflight without this flag. EOF } @@ -45,8 +46,31 @@ while (( $# > 0 )); do esac done -if [[ ! "$version" =~ ^v(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)(-[0-9A-Za-z]+([.-][0-9A-Za-z]+)*)?(\+[0-9A-Za-z]+([.-][0-9A-Za-z]+)*)?$ ]]; then - printf 'error: --version must be a semantic version beginning with v\n' >&2 +if [[ ! "$version" =~ ^v(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)(-([0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*))?$ ]]; then + printf 'error: --version must be a canonical semantic version beginning with v (build metadata is not allowed)\n' >&2 + exit 2 +fi +prerelease=${BASH_REMATCH[5]:-} +if [[ "$prerelease" =~ (^|[.-])(0\.)?[0-9]{14}-[0-9a-f]{12,}$ ]]; then + printf 'error: --version must be a signed release tag, not a Go pseudo-version\n' >&2 + exit 2 +fi +if [[ -n "$prerelease" ]]; then + IFS=. read -r -a prerelease_identifiers <<<"$prerelease" + for identifier in "${prerelease_identifiers[@]}"; do + if [[ "$identifier" =~ ^[0-9]+$ && "$identifier" =~ ^0[0-9]+$ ]]; then + printf 'error: numeric prerelease identifiers must not contain leading zeroes: %s\n' "$identifier" >&2 + exit 2 + fi + done +fi + +beta_release=0 +if [[ "$prerelease" == beta || "$prerelease" == beta.* ]]; then + beta_release=1 +fi +if (( public_release == 0 && beta_release == 0 )); then + printf 'error: RC and final release preflights require --public and the human-reviewed evidence bundle\n' >&2 exit 2 fi @@ -90,6 +114,73 @@ for tag in "$version" "$runtime_tag"; do fi done +artifact_dir=$(mktemp -d "${TMPDIR:-/tmp}/himesan-release-check.XXXXXXXX") +cleanup() { + if [[ -n "${artifact_dir:-}" && -d "$artifact_dir" ]]; then + rm -rf -- "$artifact_dir" + fi +} +trap cleanup EXIT HUP INT TERM + +compiler_linker_flags="-X gamertan.com/sandwich-hime/internal/version.Compiler=$version" +candidate_binary="$artifact_dir/himesan-candidate" + +printf '\n==> exact release candidate identity\n' +go build -trimpath -ldflags "$compiler_linker_flags" -o "$candidate_binary" ./cmd/himesan +candidate_go_version=$(go env GOVERSION) +expected_human_version="himesan $version (runtime ABI sando.v1, $candidate_go_version)" +actual_human_version=$("$candidate_binary" version) +if [[ "$actual_human_version" != "$expected_human_version" ]]; then + printf 'error: candidate human version mismatch\nexpected: %s\nactual: %s\n' \ + "$expected_human_version" "$actual_human_version" >&2 + exit 1 +fi +expected_json_version=$(printf '{"compiler":"%s","runtime_abi":"sando.v1","go":"%s"}' "$version" "$candidate_go_version") +actual_json_version=$("$candidate_binary" version --json) +if [[ "$actual_json_version" != "$expected_json_version" ]]; then + printf 'error: candidate JSON version mismatch\nexpected: %s\nactual: %s\n' \ + "$expected_json_version" "$actual_json_version" >&2 + exit 1 +fi + +file_mtime() { + if stat --printf='%y' "$1" >/dev/null 2>&1; then + stat --printf='%y' "$1" + else + stat -f '%m' "$1" + fi +} + +printf '\n==> candidate generated-output provenance compatibility\n' +golden_source=internal/compiler/testdata/golden/basic.sando +golden_output="$golden_source.go" +if ! grep -Fqx '// himesan:compiler 0.1.0-dev' "$golden_output"; then + printf 'error: golden fixture no longer provides development-to-release provenance coverage: %s\n' "$golden_output" >&2 + exit 1 +fi +golden_hash_before=$(git hash-object "$golden_output") +golden_mtime_before=$(file_mtime "$golden_output") +check_summary=$("$candidate_binary" check "$golden_source") +if [[ "$check_summary" != 'checked 1 .sando files: 1 current' ]]; then + printf 'error: candidate did not consider the development-produced golden current: %s\n' "$check_summary" >&2 + exit 1 +fi +for pass in 1 2; do + generate_summary=$("$candidate_binary" generate "$golden_source") + if [[ "$generate_summary" != 'generated 0, unchanged 1 (1 .sando files)' ]]; then + printf 'error: candidate generation pass %d reported unexpected changes: %s\n' "$pass" "$generate_summary" >&2 + exit 1 + fi + if [[ "$(git hash-object "$golden_output")" != "$golden_hash_before" ]]; then + printf 'error: candidate generation pass %d changed golden bytes\n' "$pass" >&2 + exit 1 + fi + if [[ "$(file_mtime "$golden_output")" != "$golden_mtime_before" ]]; then + printf 'error: candidate generation pass %d changed the golden mtime\n' "$pass" >&2 + exit 1 + fi +done + ./scripts/check-licenses.sh HIMESAN_RACE=1 ./scripts/verify.sh @@ -104,14 +195,6 @@ go run golang.org/x/vuln/cmd/govulncheck@v1.6.0 ./... go run golang.org/x/vuln/cmd/govulncheck@v1.6.0 ./... ) -artifact_dir=$(mktemp -d "${TMPDIR:-/tmp}/himesan-release-check.XXXXXXXX") -cleanup() { - if [[ -n "${artifact_dir:-}" && -d "$artifact_dir" ]]; then - rm -rf -- "$artifact_dir" - fi -} -trap cleanup EXIT HUP INT TERM - printf '\n==> cross-compiling release binary smoke set\n' for target in \ linux/amd64 \ @@ -127,7 +210,8 @@ for target in \ extension='.exe' fi CGO_ENABLED=0 GOOS="$target_os" GOARCH="$target_arch" \ - go build -trimpath -o "$artifact_dir/himesan-$target_os-$target_arch$extension" ./cmd/himesan + go build -trimpath -ldflags "$compiler_linker_flags" \ + -o "$artifact_dir/himesan-$target_os-$target_arch$extension" ./cmd/himesan done for required in \ @@ -158,9 +242,18 @@ if (( public_release == 1 )); then exit 1 fi done +fi + +if [[ -n "$(git status --porcelain=v1 --untracked-files=all)" ]]; then + printf 'error: release preflight left tracked changes or untracked artifacts in the canonical checkout\n' >&2 + git status --short >&2 + exit 1 +fi + +if (( public_release == 1 )); then printf '\nHuman review is still required; evidence presence is not automatic approval.\n' else - printf '\nTechnical preflight passed. Public launch remains blocked until --public evidence review passes.\n' + printf '\nBeta technical publication preflight passed. This does not establish RC/final launch evidence or production stability.\n' fi printf 'No tag, push, publication, or deployment was performed for %s / %s.\n' "$version" "$runtime_tag" diff --git a/scripts/verify-public-install.sh b/scripts/verify-public-install.sh index 490d4ff..2e91fed 100755 --- a/scripts/verify-public-install.sh +++ b/scripts/verify-public-install.sh @@ -33,10 +33,24 @@ while (( $# > 0 )); do esac done -if [[ ! "$version" =~ ^v(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)(-[0-9A-Za-z]+([.-][0-9A-Za-z]+)*)?(\+[0-9A-Za-z]+([.-][0-9A-Za-z]+)*)?$ ]]; then - printf 'error: --version must be a semantic version beginning with v\n' >&2 +if [[ ! "$version" =~ ^v(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)(-([0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*))?$ ]]; then + printf 'error: --version must be a canonical semantic version beginning with v (build metadata is not allowed)\n' >&2 exit 2 fi +prerelease=${BASH_REMATCH[5]:-} +if [[ "$prerelease" =~ (^|[.-])(0\.)?[0-9]{14}-[0-9a-f]{12,}$ ]]; then + printf 'error: --version must identify a signed release tag, not a Go pseudo-version\n' >&2 + exit 2 +fi +if [[ -n "$prerelease" ]]; then + IFS=. read -r -a prerelease_identifiers <<<"$prerelease" + for identifier in "${prerelease_identifiers[@]}"; do + if [[ "$identifier" =~ ^0[0-9]+$ ]]; then + printf 'error: numeric prerelease identifiers must not contain leading zeroes: %s\n' "$identifier" >&2 + exit 2 + fi + done +fi for command_name in curl go git false; do command -v "$command_name" >/dev/null 2>&1 || {