Skip to content

Add the ingot system + forge-mode e2e validation#10

Merged
frrist merged 1 commit into
mainfrom
add-ingot-system
Jul 14, 2026
Merged

Add the ingot system + forge-mode e2e validation#10
frrist merged 1 commit into
mainfrom
add-ingot-system

Conversation

@frrist

@frrist frrist commented Jun 25, 2026

Copy link
Copy Markdown
Member

Add the ingot system + forge-mode e2e validation

Runs ingot — the S3 gateway over Forge — as a first-class smelt system and validates it live against the real stack (sprue + piri + indexing-service + postgres).

All upstream dependencies have landed: fil-forge/ingot PR #9 is merged and ghcr.io/fil-forge/ingot:main / :main-dev are published by ingot's container workflow. The e2e suite below passes against the published images with no workspace setup.

What this adds

  • systems/ingot/compose.yml (ingot daemon ghcr.io/fil-forge/ingot:main + postgres:16-alpine; forge mode; goose migrations at startup on a fresh DB) and config/config.yaml (S3 IAM, Postgres DSN, sprue/indexer endpoints, mounted space key). INGOT_IMAGE overrides the image (documented in .env alongside the other services).
  • pkg/stack support — IngotEndpoint(), Exec(ctx, "ingot", …), Logs(ctx, "ingot"); pkg/workspace registers ingot; pkg/generate adds the ingot agent key.
  • github.com/fil-forge/ingot pinned in go.mod (v0.0.0, ingot's release tag at current main) — the e2e tests import ingot/testing and now compile from a plain checkout; the parent go.work is only needed to rebuild ingot from local source via SMELT_WORKSPACE=1.

Forge e2e tests (tests/e2e/ingot_*.go)

Test Validates
TestIngotNativeProvision ingot self-provisions its space (guppy-free: ingot login + space generate --provision-to), then runs the versity Smoke suite over forge mode
TestIngotVersityConformance the gate — runs the same group universe as ingot's own smoke_test.go partition (Smoke + CopyObject + DeleteObjects) plus Multipart against an in-process baseline and forge, and asserts exact two-sided per-case parity: forge-only failures are regressions, forge-only passes are build divergences (mirroring the suite's "unexpectedly passed; promote it" ratchet) — both fail by name; out-of-scope cases self-calibrate out, and the one load-sensitive case (CompleteMultipartUpload_racey_success) is logged, not gated. Last run vs published images: forge 158/262 vs in-process baseline 157/262 — parity modulo that one timing case
TestIngotForgeReadAfterEviction the appliance read tier — PUT, wipe /data/spool, GET re-fetches the body from piri via LocalLocator + /content/retrieve (512 KiB round-tripped)

These caught a real forge bug during development (a re-PUT 500 from re-adding an already-stored blob), fixed in ingot PR #9.

How to run

# no workspace needed — runs against the published images
go test -tags e2e ./tests/e2e -run TestIngot -v -timeout 3600s

# rebuild ingot from local source instead (parent go.work with ./smelt ./ingot)
SMELT_WORKSPACE=1 go test -tags e2e ./tests/e2e -run TestIngot -v -timeout 3600s

Scope note

The branch is a single commit rebased onto current main (including the attested-signatures ucantone bump from #7 — the sprue use_path_style fix and the multikey port of pkg/stack/proofs.go landed there independently, so this PR inherits rather than duplicates them). Reviewers should focus on systems/ingot/** and tests/e2e/ingot_*.go.

🤖 Generated with Claude Code

@frrist
frrist force-pushed the add-ingot-system branch from e93c1f7 to a2a4ea1 Compare June 25, 2026 00:47
@frrist frrist changed the title Add the ingot system + forge-mode e2e validation (draft: depends on ingot PR #9) Add the ingot system + forge-mode e2e validation Jul 13, 2026
@frrist
frrist marked this pull request as ready for review July 13, 2026 21:24
@frrist
frrist force-pushed the add-ingot-system branch from 5261e75 to 8999ba8 Compare July 13, 2026 21:58
Run ingot as a first-class smelt system and validate it live against the
real stack (sprue + piri + indexing-service + postgres).

systems/ingot/: compose.yml (ingot daemon ghcr.io/fil-forge/ingot:main +
postgres:16-alpine; forge mode; goose migrations at startup on a fresh
DB) and config/config.yaml (S3 IAM, Postgres DSN, sprue/indexer
endpoints, mounted space key). INGOT_IMAGE overrides the image;
documented in .env alongside the other services.

pkg/stack: IngotEndpoint(), Exec/Logs support; pkg/workspace registers
ingot for SMELT_WORKSPACE=1 local-source rebuilds; pkg/generate adds the
ingot agent key.

github.com/fil-forge/ingot is pinned in go.mod (v0.0.0, ingot's release
tag at current main), so the e2e tests' ingot/testing import compiles
from a plain checkout — the parent go.work is only needed to rebuild
ingot from local source.

Forge e2e tests (tests/e2e/ingot_*.go):

- TestIngotNativeProvision: ingot self-provisions its space (guppy-free:
  ingot login + space generate --provision-to), then runs the versity
  Smoke suite over forge mode.
- TestIngotVersityConformance: the gate — runs the same group universe
  as ingot's own smoke_test.go partition (Smoke + CopyObject +
  DeleteObjects) plus Multipart against an in-process baseline and
  forge, asserting exact two-sided per-case parity: forge-only failures
  are regressions, forge-only passes are build divergences (mirroring
  the suite's "unexpectedly passed; promote it" ratchet) — both fail by
  name. The load-sensitive CompleteMultipartUpload_racey_success is
  logged, never gated. Last run vs published images: forge 158/262 vs
  baseline 157/262.
- TestIngotForgeReadAfterEviction: the appliance read tier — PUT, wipe
  /data/spool, GET re-fetches the body from piri via LocalLocator +
  /content/retrieve (512 KiB round-tripped).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@frrist
frrist force-pushed the add-ingot-system branch from 8999ba8 to d5c5865 Compare July 13, 2026 22:10
@frrist
frrist requested a review from alanshaw July 13, 2026 22:21
@frrist frrist self-assigned this Jul 13, 2026
frrist added a commit that referenced this pull request Jul 14, 2026
…now (#18)

Stacked on #17 (which stacks on #10). **Hold merge until the ingot-side
e2e PR is green** — this is the final step of the test-dependency
inversion.

- Deletes `tests/e2e/ingot_{versity,native,eviction}_test.go` — ported
to ingot `testing/forge_*_test.go`, where the conformance baseline and
the binary under test are the same commit by construction.
- The upload/retrieve smoke now asserts ingot boots to **healthy** in
every storage permutation — smelt keeps guarding the *system definition*
(topology, config, keys), the ingot repo owns *behavior*.
- `go.mod` drops the `fil-forge/ingot` and `versity/versitygw` pins —
smelt no longer depends on any service repo.
- Docs: DEVELOPING.md gains a "Service repos own their e2e tests (smelt
as SDK)" section (the pattern for piri/sprue/etc. teams, with a
one-e2e-run-per-host caveat for `CleanupLeaked`); CLAUDE.md's stale "no
CI" section now describes the actual workflows.

Verified: `go vet -tags e2e ./...`, live `TestUploadAndRetrieve/default`
(ingot health guard exercised, PASS 78s).

🤖 Generated with [Claude Code](https://claude.com/claude-code)
@frrist
frrist merged commit d5c5865 into main Jul 14, 2026
5 checks passed
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.

1 participant