Skip to content

Bind consumer verify to judged bytes on generate and load - #499

Merged
cursor[bot] merged 3 commits into
masterfrom
cursor/consumer-artifact-verify-e17e
Sep 4, 2026
Merged

cursor[bot] merged 3 commits into
masterfrom
cursor/consumer-artifact-verify-e17e

Conversation

@IanFrelinger

@IanFrelinger IanFrelinger commented Sep 4, 2026 •

Copy link
Copy Markdown
Owner

Summary

Follow-on to the compile-authority hardening now on master. Production consumers bind the certificate to judged bytes, and generate→certify mints gate-emitted-artifact the same way the disk loader does.

Operator requested the v0.1.2 tag. This PR is the release commit: PublicAPI Unshipped → Shipped, changelog cut to [0.1.2] - 2026-09-04. Local release-preflight-local.sh 0.1.2 passed.

Changes

  • GeneratedBrickBuilder compiles with GateEmittedArtifactCompiler and activates through CertifiedBrickActivator. GenerateAndCertifyService passes EmittedArtifact, so the record mints gate-emitted-artifact / execution-mode=gate-emitted.
  • Hot-swap verify uses CertificationVerifyOptions.Strict. When a supplied PE matches the record hash, it uses the artifact-bytes Verify overload. HMAC-era records without that input are refused.
  • Self-extend admission uses Strict (source + kind completeness; no PE on the write path).
  • Reuse sample / ProjectBTrustConsumer use Strict, with an optional DLL path for hash binding.
  • Release prep: stable-tier PublicAPI.Unshipped.txt promoted to Shipped.txt; changelog cut for v0.1.2.

Testing

  • Local bash scripts/run-cert-gate.sh at e94fc6f8: 444/444.
  • Focused generate/hot-swap/reuse: 38/38.
  • Autonomy campaign + watch + controls: 30/30.
  • SelfExtendInvariantACertGateTests: 5/5.
  • Local bash scripts/release-preflight-local.sh 0.1.2: OK (pack-graph alignment + StableSdkHostSample 0.1.2).

Testing strategy (blast radius)

Change type Minimum proof
Infrastructure certification / generate cert-gate 444/444
Self-extend admission SelfExtendInvariantACertGateTests 5/5
Release preflight release-preflight-local.sh 0.1.2 OK
  • Documentation updated
  • Versioned release — tag v0.1.2 after merge (release.yml)

Release

Tag v0.1.2 after this merges to master. ci/published-version stays 0.1.1 until nuget.org publish from release.yml completes. The 2-arg Verify(record, source) helper remains HMAC-era for callers that opt into it.

Remaining honest limits

  • Callers that still use 2-arg default verify are HMAC-era.
  • Self-extend cannot hash-check a PE (it admits source writes).
  • StateLogVerifier still uses 2-arg verify on behavior certs.
  • Write-floor / --allow-mock / import canary / OS isolation of witness legs are unchanged.
Open in Web Open in Cursor 

cursoragent and others added 3 commits September 4, 2026 10:48
Generate→certify now emits through GateEmittedArtifactCompiler and
CertifiedBrickActivator, so the record mints gate-emitted-artifact
instead of in-process-fixture.

Hot-swap and self-extend admission use Strict. When hot-swap is given
a PE that matches the certificate hash, the artifact-bytes Verify
overload binds those bytes. HMAC-era records without the artifact
input are refused at those hosts. The reuse sample takes an optional
DLL path for the same check.

Co-authored-by: icfrelinger <icfrelinger@gmail.com>
Move reviewed stable-tier Unshipped symbols into Shipped.txt so the
v0.1.2 tag freezes the promised surface.

Co-authored-by: icfrelinger <icfrelinger@gmail.com>
Cut Unreleased notes under [0.1.2] - 2026-09-04. ci/published-version
stays 0.1.1 until release.yml finishes the nuget.org push.

Co-authored-by: icfrelinger <icfrelinger@gmail.com>
@cursor
cursor Bot merged commit 33a26f2 into master Sep 4, 2026
35 of 38 checks passed
@cursor
cursor Bot deleted the cursor/consumer-artifact-verify-e17e branch September 4, 2026 11:23
IanFrelinger pushed a commit that referenced this pull request Oct 1, 2026
…and refuses an empty scan

Tier 9.2 asserts no [Experimental] type appears in any PublicAPI.Shipped.txt.
It built its list of experimental types by harvesting class names from every
.cs file under src/ that contains the text "[Experimental(" - test projects
included. DiagnosticSuppressionConventionTests (added earlier in this series)
polices that attribute, so it contains the text five times, and it declares a
fixture class named AshlarSdkBuilder. The check therefore reported the real
AshlarSdkBuilder - which is [Obsolete], not [Experimental], and has been in
Ashlar.Sdk's PublicAPI.Shipped.txt since #499 - as an experimental type leaked
into the stable promise. Both UAT jobs went red on it. Nothing leaked.

- The harvest now skips any directory whose name contains "Tests".
- A floor: 82 experimental types are declared in product code today; fewer than
  60 means the scan lost its lens, and "none leaked" from an empty list is a
  pass that proves nothing, so it fails instead.

Observed, running only the 9.2 block against the tree:
- unfixed tree: FAIL "experimental types in the stable promise: AshlarSdkBuilder"
  - the CI failure, reproduced;
- fixed tree: PASS, 82 types;
- a REAL leak (Ashlar.Core.Application.Autonomy.TouchSet appended to a Shipped
  file): FAIL naming TouchSet;
- an empty scan (the file pattern changed to match nothing; anchor count 1 -> 0):
  FAIL "the scan found only 0 [Experimental] types (floor 60)";
- restored: porcelain empty, PASS.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
IanFrelinger pushed a commit that referenced this pull request Oct 1, 2026
…and refuses an empty scan

Tier 9.2 asserts no [Experimental] type appears in any PublicAPI.Shipped.txt.
It built its list of experimental types by harvesting class names from every
.cs file under src/ that contains the text "[Experimental(" - test projects
included. DiagnosticSuppressionConventionTests (added earlier in this series)
polices that attribute, so it contains the text five times, and it declares a
fixture class named AshlarSdkBuilder. The check therefore reported the real
AshlarSdkBuilder - which is [Obsolete], not [Experimental], and has been in
Ashlar.Sdk's PublicAPI.Shipped.txt since #499 - as an experimental type leaked
into the stable promise. Both UAT jobs went red on it. Nothing leaked.

- The harvest now skips any directory whose name contains "Tests".
- A floor: 82 experimental types are declared in product code today; fewer than
  60 means the scan lost its lens, and "none leaked" from an empty list is a
  pass that proves nothing, so it fails instead.

Observed, running only the 9.2 block against the tree:
- unfixed tree: FAIL "experimental types in the stable promise: AshlarSdkBuilder"
  - the CI failure, reproduced;
- fixed tree: PASS, 82 types;
- a REAL leak (Ashlar.Core.Application.Autonomy.TouchSet appended to a Shipped
  file): FAIL naming TouchSet;
- an empty scan (the file pattern changed to match nothing; anchor count 1 -> 0):
  FAIL "the scan found only 0 [Experimental] types (floor 60)";
- restored: porcelain empty, PASS.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants