feat(foundry): add the missing Configure stage; make the wizard fail closed#102
Merged
Conversation
…closed
The Foundry advertised `mint -> provision -> configure -> harness`, but stage
3 of 4 was a single `say` line: `stages/configure.sh` did not exist. Several
other paths could also report success having done nothing.
Configure stage (new)
stages/configure.sh applies endpoint + auth settings under the two rules
Foundry.idr types as `configure : Artifact ds caps -> Artifact ds caps`:
PRESERVATION the `capabilities` block is compared before/after and must
be byte-identical — configure may never edit the grant.
NO ESCALATION a setting requiring a locked-down capability is refused.
Remote `--api-base` needs Net (loopback forms do not);
`--auth` != none needs Cred; `--auth-env`/`--auth-source`
need Cred unconditionally, since naming a secret is itself
credential authority. Deciding that from the manifest's
current `auth.method` would let credential wiring land in a
freshly-minted cartridge (method `none`) and be activated by
a later `--auth` — a two-step escalation.
Refuses a cartridge with no capabilities block: without a provisioned grant
there is nothing to check against, so it fails closed.
Fail-closed wizard (--strict, or FOUNDRY_STRICT=1)
A missing deno/idris2/jq is now a failure rather than a skip. Previously,
with deno absent, the wizard scaffolded nothing, skipped provision, configure
and harness, printed "Foundry - done." and exited 0. It now exits non-zero
and says what did not run.
Single source of path logic
foundry.sh called mint.ts directly and then re-derived the cartridge location
with `find -name`, duplicating stages/mint.sh. It now delegates to mint.sh and
consumes its stdout. mint.sh's `deno run ... 2>&1` folded Deno's diagnostics
into that stdout — the channel carrying the path — so any warning corrupted
it; that is now `>&2`.
Interactive wizard could never mint
The minter requires `protocols`, which the wizard never prompted for or wrote,
so every interactively-produced descriptor was rejected at Mint. Now prompted
(default `mcp`) and emitted as a TOML array.
Honest toolchain diagnostics
harness.sh reported a bare "zig build failed" when the real cause was a
toolchain mismatch. It now compares `zig version` against the repo pin and
names the mismatch, quoting the first error line.
No vacuous proof pass
scripts/typecheck-proofs.sh exited 0 when `find` matched nothing (PASS=0
FAIL=0) — a green run having verified nothing, the exact failure mode the
script exists to prevent. Zero proofs is now a failure.
Verified locally with the pinned toolchains present (deno 2.9.3, idris2, jq):
- test-foundry.sh: 25/25 pass (was 12; 13 new Configure cases)
- typecheck-proofs.sh: 116 proofs typecheck, FAIL=0
- vacuous-pass guard exits 1 on an empty tree
- full `foundry.sh --strict --from` run: proof check, mint, provision,
configure and harness all execute end-to-end
- the escalation path was exercised for real: a descriptor granting only Net
while requesting api-key auth was correctly refused at Configure
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
🔍 Hypatia Security ScanFindings: 282 issues detected
View findings[
{
"reason": "TypeScript file detected -- banned language",
"type": "banned_language_file",
"file": "/home/runner/work/boj-server-cartridges/boj-server-cartridges/tools/auth-method-batch-fix/main.ts",
"action": "flag",
"rule_module": "cicd_rules",
"severity": "critical"
},
{
"reason": "TypeScript file detected -- banned language",
"type": "banned_language_file",
"file": "/home/runner/work/boj-server-cartridges/boj-server-cartridges/tools/category-batch-fix/main.ts",
"action": "flag",
"rule_module": "cicd_rules",
"severity": "critical"
},
{
"reason": "TypeScript file detected -- banned language",
"type": "banned_language_file",
"file": "/home/runner/work/boj-server-cartridges/boj-server-cartridges/tools/missing-fields-batch-fix/main.ts",
"action": "flag",
"rule_module": "cicd_rules",
"severity": "critical"
},
{
"reason": "TypeScript file detected -- banned language",
"type": "banned_language_file",
"file": "/home/runner/work/boj-server-cartridges/boj-server-cartridges/tools/cartridge-minter/mint.ts",
"action": "flag",
"rule_module": "cicd_rules",
"severity": "critical"
},
{
"reason": "TypeScript file detected -- banned language",
"type": "banned_language_file",
"file": "/home/runner/work/boj-server-cartridges/boj-server-cartridges/tools/validate-cartridges/main.ts",
"action": "flag",
"rule_module": "cicd_rules",
"severity": "critical"
},
{
"reason": "TypeScript file detected -- banned language",
"type": "banned_language_file",
"file": "/home/runner/work/boj-server-cartridges/boj-server-cartridges/tools/validate-cartridges/main_test.ts",
"action": "flag",
"rule_module": "cicd_rules",
"severity": "critical"
},
{
"reason": "TypeScript file detected -- banned language",
"type": "banned_language_file",
"file": "/home/runner/work/boj-server-cartridges/boj-server-cartridges/cartridges/domains/code-quality/sanctify-mcp/adapter/mod.ts",
"action": "flag",
"rule_module": "cicd_rules",
"severity": "critical"
},
{
"reason": "TypeScript file detected -- banned language",
"type": "banned_language_file",
"file": "/home/runner/work/boj-server-cartridges/boj-server-cartridges/cartridges/domains/infrastructure/hesiod-mcp/adapter/mod.ts",
"action": "flag",
"rule_module": "cicd_rules",
"severity": "critical"
},
{
"reason": "TypeScript file detected -- banned language",
"type": "banned_language_file",
"file": "/home/runner/work/boj-server-cartridges/boj-server-cartridges/cartridges/domains/research/bofig-mcp/adapter/mod.ts",
"action": "flag",
"rule_module": "cicd_rules",
"severity": "critical"
},
{
"reason": "TypeScript file detected -- banned language",
"type": "banned_language_file",
"file": "/home/runner/work/boj-server-cartridges/boj-server-cartridges/cartridges/domains/research/academic-workflow-mcp/adapter/mod.ts",
"action": "flag",
"rule_module": "cicd_rules",
"severity": "critical"
}
]Powered by Hypatia Neurosymbolic CI/CD Intelligence |
hyperpolymath
marked this pull request as ready for review
July 21, 2026 12:05
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The gap
SPEC.adocspecifiesmint → provision → configure → harness, but stage 3 of 4in
foundry.shwas a singlesayline —stages/configure.shdid not exist.Several other paths could report success having done nothing.
What this adds
stages/configure.sh(new)Applies endpoint and auth settings under the two rules
Foundry.idrtypes asconfigure : Artifact ds caps -> Artifact ds caps:capabilitiesblock is compared before/after and must be byte-identical — configure may never edit the grantlocked_downcapability is refused--api-baseloopback (local://,127.0.0.1,localhost,[::1])--api-baseremoteNet--auth≠noneCred--auth-env/--auth-sourceCred, unconditionallyThat last row is deliberate. Deciding it from the manifest's current
auth.method— which is what I wrote first — lets credential wiring land in afreshly-minted cartridge (where
methodisnone) and be activated by a later--auth. A two-step escalation. The test suite caught it.Fail-closed wizard —
--strict/FOUNDRY_STRICT=1Missing
deno/idris2/jqis now a failure, not a skip. Previously, withdenoabsent, the wizard scaffolded nothing, skipped provision/configure/harness,printed "Foundry · done." and exited 0.
Four further defects found while wiring it up
foundry.shbypassedstages/mint.sh— it calledmint.tsdirectly thenre-derived the path with
find -name, a second copy of the logic.mint.shcorrupted its own output contract —deno run … 2>&1foldedDeno's diagnostics into stdout, the channel carrying the cartridge path. Now
>&2.protocols;the wizard never prompted for it or wrote it, so every interactively-produced
descriptor was rejected at Mint.
typecheck-proofs.shcould pass vacuously —PASS=0 FAIL=0exited 0, agreen run having verified nothing.
Honest toolchain diagnostics
harness.shreported a barezig build failedwhere the real cause was aversion mismatch. It now compares
zig versionagainst the repo pin:Verification (run locally, toolchains present)
test-foundry.sh— 25/25 pass (was 12; 13 new Configure cases). Still purebash+jq, so it runs anywhere CI has
jq.typecheck-proofs.sh— 116 proofs typecheck,FAIL=0, under real Idris2.1on an empty tree.foundry.sh --strict --from <toml>run executes all four stages end-to-end.Netwhile requesting
api-keyauth was correctly refused at Configure.Note
.tool-versionspins zig0.15.1whilezig-test.ymluses0.15.2. Notaddressed here, but worth reconciling.