Skip to content

feat(ffi+cli): implement jk_* C ABI and CLI lifecycle — both product-gap gates green (closes #61, #62)#63

Merged
hyperpolymath merged 4 commits into
mainfrom
claude/confident-shannon-xf0Td
Jun 12, 2026
Merged

feat(ffi+cli): implement jk_* C ABI and CLI lifecycle — both product-gap gates green (closes #61, #62)#63
hyperpolymath merged 4 commits into
mainfrom
claude/confident-shannon-xf0Td

Conversation

@hyperpolymath

Copy link
Copy Markdown
Owner

Summary

Makes januskey's two product-gap CI checks pass for real — the gaps left tracked when #55 merged (issues #61, #62). All three gates verified green locally with the actual Zig 0.13 + Cargo toolchains on a clean tree.

Closes #61. Closes #62.

Gate 1 — Zig FFI Build + Test

ffi/zig/src/main.zig was an old januskey_* scaffold that didn't satisfy the repo's own conformance suite. Rewrote it to implement the authoritative jk_* C ABI declared in ffi/zig/include/januskey.h (itself generated from src/abi/{Foreign,Types,Layout}.idr):

  • extern struct types ContentHash(32) / KeyId(16) / OblitProof(112, 8-aligned) with comptime @sizeOf/@alignOf/@offsetOf assertions pinning them to Layout.idr — the build fails loudly if the ABI ever drifts from the Idris spec.
  • Error enum(c_int) with the exact JK_OK/JK_ERR_* wire values; OpKind/Algorithm enums.
  • A sized, heap-allocated Handle (not opaque) tracking init state + the one-active-transaction invariant (TX_CONFLICT/TX_NOT_ACTIVE).
  • All 15 jk_* functions with correct return codes.
  • zig build 0, zig build test 0 (15/15 tests).
  • Cryptographic/on-disk internals are honestly stubbed with TODO(product): markers; the lifecycle/transaction/null-guard semantics the suite exercises are real.

Gate 2 — E2E Lifecycle

  • Fixed tests/e2e/lifecycle_e2e.sh: ((PASS++)) under set -e (old value 0 → exit 1) replaced with PASS=$((PASS+1)) — the script could never pass before.
  • crates/januskey-cli: init now takes a positional <dir>; added global -r/--repo; added obliterate <paths…> backed by a new obliteration::obliterate_file (hash → DoD multi-pass secure overwrite → unlink → proof). init/copy/undo use real reversible-core ops.
  • Safety: obliterate refuses destructive erasure when stdin isn't a TTY and no -y is given — it errors cleanly (never auto-confirms, never hangs), so the non-interactive e2e skips that one step rather than faking a wipe.
  • cargo build --release 0, jk init 0, cargo test --all 0, bash tests/e2e/lifecycle_e2e.sh 0 (PASS: 6 FAIL: 0 SKIP: 2).

Gate 3 — Aspect Tests (kept green)

  • bash tests/aspect/cross_cutting_test.sh 0 (PASS: 29 FAIL: 0). Hardened the Zig-SPDX check to prune .zig-cache//zig-out/ (a built tree drops a header-less generated dependencies.zig that would otherwise skew the count). Added .zig-cache/+zig-out/ to .gitignore.

🤖 Draft — opened for review.

https://claude.ai/code/session_01GJatEm2TVFSTBEkKXmserJ


Generated by Claude Code

claude added 3 commits June 12, 2026 22:53
Rewrite ffi/zig/src/main.zig from the old `januskey_*` scaffold to the
authoritative `jk_*` C ABI declared in ffi/zig/include/januskey.h
(generated from src/abi/{Foreign,Types,Layout}.idr), so that
ffi/zig/test/integration_test.zig passes.

- extern-struct value types ContentHash (32B), KeyId (16B) and
  OblitProof (112B, 8-aligned: content_hash 32 + nonce 32 +
  commitment 32 + overwrite_passes u64 + passes_valid u8), with
  comptime size/align/offset assertions pinning them to Layout.idr.
- Error enum(c_int) with the 12 JK_OK / JK_ERR_* wire values.
- Sized, heap-allocated Handle struct (not opaque-with-fields)
  tracking init state + the single in-flight transaction; pointer
  round-trips through ?*anyopaque at the C boundary.
- jk_init/jk_open/jk_close, jk_execute/jk_undo/jk_obliterate,
  jk_generate_key/jk_rotate_key/jk_revoke_key,
  jk_tx_begin/commit/rollback (one-active-tx invariant ->
  TX_CONFLICT; foreign/null token -> TX_NOT_ACTIVE), jk_version.
- jk_execute takes op as c_int (the C enum wire type the test passes)
  and jk_version returns [*c]const u8 (C nullable const char*) so the
  conformance suite's literal/null-check usages typecheck.

Crypto/CNO internals are honest scaffolds marked TODO(product:);
the lifecycle, transaction-state and null-guard semantics the suite
asserts are real.

Also gitignore Zig build artefacts (.zig-cache/, zig-out/).

https://claude.ai/code/session_01GJatEm2TVFSTBEkKXmserJ
Make the `jk` CLI satisfy the init->execute->undo->obliterate lifecycle
the E2E test drives.

- `init` now takes an optional positional path (`jk init <dir>`),
  initialising that directory (created if absent) and overriding
  --dir/--repo when given.
- Add a global `-r/--repo <dir>` flag (alias of --dir, takes
  precedence) so `jk -r <repo> <cmd>` selects the repository.
- Add an `obliterate <paths...>` subcommand implementing GDPR Art. 17
  erasure of concrete files via a new public
  `obliteration::obliterate_file`: hash, DoD-style multi-pass secure
  overwrite, unlink, and return a proof. Irreversible, so it refuses
  to run without --yes when stdin is not a TTY (never auto-confirms
  destructive erasure unattended) and prompts otherwise.

Scaffold-level where noted with TODO(product:) (repo-side scrub of
content-store copies and op-log pruning on obliterate).

https://claude.ai/code/session_01GJatEm2TVFSTBEkKXmserJ
- tests/e2e/lifecycle_e2e.sh: replace ((PASS++))/((FAIL++))/((SKIP++))
  with PASS=$((PASS+1)) etc. Under `set -euo pipefail` a post-increment
  of a 0-valued var returns exit 1 and aborted the script on the first
  check (same fix already present in the aspect test).
- tests/aspect/cross_cutting_test.sh: prune .zig-cache/ and zig-out/
  from the Zig SPDX `find` so a generated, header-less
  dependencies.zig left by `zig build` cannot skew the count when the
  test runs in an already-built tree.

https://claude.ai/code/session_01GJatEm2TVFSTBEkKXmserJ
@hyperpolymath hyperpolymath marked this pull request as ready for review June 12, 2026 23:12
@hyperpolymath hyperpolymath merged commit b70175f into main Jun 12, 2026
13 checks passed
@hyperpolymath hyperpolymath deleted the claude/confident-shannon-xf0Td branch June 12, 2026 23:12
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.

product: fix jk init failure (E2E Lifecycle gate) product: implement the jk_* FFI API in ffi/zig/src/main.zig to match the integration tests

2 participants