Skip to content

feat(builder): govern OS-image builds through the capability membrane (closure #1) - #557

Merged
mdheller merged 1 commit into
masterfrom
feat/governed-build-admission
Aug 4, 2026
Merged

feat(builder): govern OS-image builds through the capability membrane (closure #1)#557
mdheller merged 1 commit into
masterfrom
feat/governed-build-admission

Conversation

@mdheller

@mdheller mdheller commented Aug 4, 2026

Copy link
Copy Markdown
Member

Summary

Closes the biggest governance gap the OS-build survey found: the image-build path is self-governed by sourceos-spec contracts but never passes through the estate's autonomy-governance fabric — a build could dispatch with no membrane decision on record. This admits every build through the authoritative capability membrane before dispatch and seals the decision into an AutonomyAdmissionReceipt (the same contract the membrane emits estate-wide).

Safe to land on a live pipeline

  • Advisory by default — every build gets a decision + a sealed receipt, but is never blocked unless BUILD_ADMISSION_ENFORCE=true. So wiring this cannot break the currently-shipped build loop. Flip enforcement on once the membrane transport is confirmed in the deploy.
  • Fail-closed when enforcing — an unreachable/unwired membrane denies, never opens.
  • Conform, don't invent — the membrane decision is called, not re-implemented; the receipt schema is vendored verbatim + hash-pinned from prophet-platform.

Changes

  • src/services/buildAdmission.ts — compose a membrane CapabilityRequest (surface sourceos.os-image-build, tier→autonomy level, spec→risk), call the authoritative membrane over a config-driven transport (MEMBRANE_GATE_URL HTTP / MEMBRANE_GATE_CMD CLI: JSON in, decision out, exit 0=allow/3=deny), seal an AutonomyAdmissionReceipt.v0.2.
  • routes/api/builds-route.ts — admit before dispatchBuild: validate the receipt against the vendored schema, persist it + emit srcos.builder.admission.decided, and on an enforced deny return 403 without dispatching.
  • contracts/schemas/AutonomyAdmissionReceipt.v0.2.json (+ PROVENANCE) — vendored from prophet-platform, registered in the contracts validator.
  • test/admission.test.mjs — advisory-admits / enforce-fails-closed / CLI allow+deny / advisory-records-deny-without-blocking / risk / receipt conformance + seal. Gated in builder-contract-tests.yml. Existing contract test stays green.

Follow-ups

  • Deploy: set MEMBRANE_GATE_URL|CMD in the builder env, confirm decisions, then BUILD_ADMISSION_ENFORCE=true to make governance binding.
  • Closure configure local databases for user registration and login #2 (separate): point ControlPlaneLifecycle.vue's evidence-gate view at the live GCS-emitted evidence bundles instead of fixtures.

Touches a workflow — flagged for human review; not auto-merging.


const cli = (name, body) => {
const p = path.join(os.tmpdir(), name);
fs.writeFileSync(p, `let d='';process.stdin.on('data',c=>d+=c);process.stdin.on('end',()=>{${body}});`);
… (closure #1)

The image-build path was self-governed by sourceos-spec contracts but never passed
through the estate's autonomy-governance fabric — a build could dispatch with no
membrane decision on record. This admits every build through the AUTHORITATIVE
capability membrane before dispatch and seals the decision into an
AutonomyAdmissionReceipt (the same contract the membrane emits estate-wide).

- src/services/buildAdmission.ts — composes a membrane CapabilityRequest for the
  build (surface=sourceos.os-image-build, tier→autonomy level, spec→risk), CALLS the
  authoritative membrane (never reinvents the decision) over a config-driven transport
  (MEMBRANE_GATE_URL http / MEMBRANE_GATE_CMD cli: JSON in, decision out, exit 0=allow
  /3=deny), and seals an AutonomyAdmissionReceipt.v0.2. Two safety properties:
    * ADVISORY BY DEFAULT — every build gets a decision + sealed receipt but is never
      blocked unless BUILD_ADMISSION_ENFORCE=true, so wiring this cannot break the live
      pipeline. Flip enforcement on once the membrane transport is confirmed in deploy.
    * FAIL-CLOSED WHEN ENFORCING — an unreachable/unwired membrane denies; never opens.
- routes/api/builds-route.ts — admit before dispatchBuild: validate the receipt against
  the vendored schema (our own receipt must conform), persist it + emit
  srcos.builder.admission.decided, and on an enforced deny return 403 without dispatch.
- contracts/schemas/AutonomyAdmissionReceipt.v0.2.json — vendored verbatim + hash-pinned
  from prophet-platform (authoritative), registered in the contracts validator.
- test/admission.test.mjs — advisory-admits / enforce-fails-closed / cli allow+deny /
  advisory-records-deny-without-blocking / risk classification / receipt conformance +
  seal. Gated in builder-contract-tests.yml. Existing contract test stays green.

Follow-up (deploy): set MEMBRANE_GATE_URL|CMD in the builder env, confirm decisions,
then set BUILD_ADMISSION_ENFORCE=true to make governance binding. Closure #2 (point
ControlPlaneLifecycle.vue at live evidence bundles) is separate.
@mdheller
mdheller force-pushed the feat/governed-build-admission branch from 4baa3b0 to a593695 Compare August 4, 2026 18:04
@mdheller
mdheller merged commit 4005170 into master Aug 4, 2026
16 checks passed
@mdheller
mdheller deleted the feat/governed-build-admission branch August 4, 2026 18:17
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