Skip to content

Cleave-surface audit: ABI/FFI/Ephapax/Groove drift + ranked-ownership cleave (forward plan) #82

Description

@hyperpolymath

Status — verified-audit correction (2026-07-01, follow-up to gossamer#96)

Re-audited against main after #96 (which de-conflated Groove from the shell ABI and restored the namespace symlinks). Every finding below was re-verified with the toolchain. Four of the five original findings STAND; one — the "Ephapax↔Zig groove-surface" HIGH — was factually wrong and is corrected here; one is refined. Evidence is inline so this issue is now an accurate work-list, not a stale snapshot.

Confirmed findings (severity-ranked, re-verified 2026-07-01)

  • CRITICAL — the Idris2 ABI describes a phantom template, not the real FFI. ✅ CONFIRMED. src/interface/abi/Foreign.idr declares 11 generic placeholder %foreign "C:…, libgossamer" symbols; only 3 of the 11 actually exist among the 155 export fn C symbols in src/interface/ffi/src/*.zig: gossamer_last_error, gossamer_version, gossamer_build_info. The other 8 have no Zig definition: gossamer_init, gossamer_free, gossamer_process, gossamer_free_string, gossamer_get_string, gossamer_process_array, gossamer_register_callback, gossamer_is_initialized. idris2 --typecheck does not check %foreign linkage, so "15 modules green" ≠ "ABI matches FFI". This remains the load-bearing item.

  • HIGH — the Ephapax core is not actually linear. ✅ CONFIRMED. grep -c 'let!' src/core/*.eph0 across all .eph files: zero let! bindings, the linear construct the whole value proposition rests on. The .eph files are still thin __ffi(...) passthroughs. "Handle leaks become compile errors" stays aspirational until the .eph bodies use let! and are compiled by ephapax.

  • HIGH — third disagreeing surface (Ephapax↔Zig). ❌ CORRECTED — this finding was WRONG. The original claim (that Groove.eph calls discover/status/manifest/find_capability/send/recv/summary/disconnect_all while Zig only exports connect_typed/disconnect_typed/query_type/dock/undock) does not hold. Verified: all 10 gossamer_groove_* symbols called by src/core/Groove.eph have matching export fn definitions in src/interface/ffi/src/groove.zigdiscover, status, manifest, find_capability, check_compat, send, recv, summary, disconnect, disconnect_all. The connect_typed/disconnect_typed/query_type/dock/undock symbols live in main.zig and are a complementary typed/panel-docking layer driven by the shell, not a competing surface. The groove discovery/messaging/teardown cleave is fully mapped. (Post-fix(abi): de-conflate Groove from the shell + restore namespace symlinks (gossamer#95) #96 the groove proofs also live in their own gossamer-groove.ipkg, one-way dependent on the shell.)

  • HIGH → MEDIUM — the soft-groove privacy-wipe teardown is not proof-covered. ⚠️ REFINED (original framing was imprecise). Correction: ResourceCleanup.idr is wired to gossamer_groove_disconnect — its DisconnectGroove cleanup action maps to the symbol Groove.eph calls and Zig exports, and GrooveLinearity.consumeForDisconnect proves the Active→Consumed linearity. What is not proof-covered is the soft-groove path gossamer_groove_disconnect_typed (main.zig), the flat state-zeroing wipe used for soft grooves: ResourceCleanup proves the plain disconnect residue→0 descent, not the typed wipe. This is the real RC-7/RC-8 gap — extend residue→0 to cover the soft-groove disconnect_typed wipe.

  • MEDIUM — doc/reality drift. ✅ CONFIRMED (partially addressed). README/TOPOLOGY historically referenced ffi/zig/ and a top-level src/ABI.idr that don't exist; the honest homes are src/interface/ffi/src/ and src/interface/abi/. The "173 integration tests" claim is stale — the honest count is 186 (test/integration_test.zig). Foreign.idr's own comment still admits a "latent error masked by the never-built module".

Correct proof-location map (unchanged — re-verified)

  • Groove.idr handshakeRank/transitionDecreases = the connect ranking function (flat Nat, a DAG).
  • GrooveTermination.idr = connect-handshake bounded-length (≤4), no measure — not teardown.
  • ResourceCleanup.idr = the teardown/residue→0 proof (flat-Nat structural recursion) — the host to upgrade.

The forward frame (the "cleave surface")

Re-attach spec + proofs + linearity to the true cleave (the 155 real Zig symbols — was ~141 at the 2026-06-15 audit), as B-layer membrane properties, not to the phantom template. Cleave-surface layering: A discovery · B1 admissibility · B2 live-governance + lifecycle/residue · C1 logical schema · C2 framing/transport. Single-source-of-truth + codegen decision is the key open architectural choice (see handoff).

Locked decision — rupture policy (owner, 2026-06-15)

Zero-residue-on-rupture: day-one ownership shape (a survivor of the rupture owns the wipe, never the dying party's cleanup) + phased coverage (process-death/conn-drop first → host-crash → power-loss → durable-secret). Constrains the Zig handle-ownership design: resource+secret lifetime keyed to handle liveness; nothing stashed outside OS-reclaimed resources; groove membrane carries liveness/heartbeat so a peer reaps its half on the other's death.

Next actions (updated to reflect the re-audit)

  • [CRITICAL] Replace Foreign.idr's 8 placeholder %foreign symbols with the real cleave, or codegen a mirror from the 155 Zig export fn — so the typechecked ABI is the real ABI.
  • Extend ResourceCleanup residue→0 to cover the soft-groove disconnect_typed wipe (the real RC-7/RC-8 gap).
  • Make the .eph core actually linear (let!) and compile it with ephapax; until then, reconcile/retract the linearity claim in README.
  • Decide single-source-of-truth for the 155-symbol cleave + codegen-or-hand-mirror (see handoff "way forward").
  • Wire gossamer_groove_disconnect_typedResourceCleanup descent → superseded: plain disconnect is wired; scope narrows to the typed wipe (see refined finding above).
  • Adopt the Groove Ranked-Ownership Cleave spec (companion standards issue) as the B-layer normative doc.

Suggested labels: abi, ephapax, design, audit.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions