Continue Tor-everywhere implementation from the current handoff #4

Open
opened 2026-09-25 17:04:16 -04:00 by ober · 0 comments
Owner

Continuation objective

Implement every requirement in Tor-everywhere.md for jerboa-tor, then run
all required builds, tests, live qualification, security/release checks, and
open exactly one Forgejo pull request at the very end. Do not claim completion
from a green unchanged suite. Preserve the jerboa-sqlite-only storage rule,
the no-C/C++ Tor invariant, authenticated IPC, typed Jerboa/Rust boundaries,
and all AGENTS.md workflow rules.

The next agent must read Tor-everywhere.md §78 first, then §70 and the rest
of the document. §78 is the researched unblock guide and contains source
anchors, corrected assumptions, implementation order, and acceptance tests.

Current checkout and important warning

Remote:

ssh://git@git.jerboa.sh:2222/ober/jerboa-tor.git

Local branch: feat/tor-everywhere-complete.

The local branch is ahead of origin/feat/tor-everywhere-complete; the commits
below are local work and have not been published in a PR. The working tree
currently also has these uncommitted changes:

  • Tor-everywhere.md: §78 research-only continuation instructions.
  • rust/jtor-engine/Cargo.toml: adds arti-client/restricted-discovery to
    the arti-onion-service feature; the feature-check was started but was
    interrupted, so rerun it and record the result.

Do not open a PR yet. Reconcile, test, commit, and push all final work only
after the complete acceptance audit succeeds.

Completed local work

The following commits are present locally and should be preserved/reviewed:

  • 9d51a8c and fc8bf1d: lifecycle state machine and multi-service registry
    with Created/Running/Stopping/Stopped/Failed, ownership, generation fencing,
    disconnect cleanup, and invalid-transition tests.
  • 10012a2: separate ONION_ADMIN, ONION_ACCEPT, and ONION_VIEW rights.
  • 6b09b4a: DNS resolver identity fails closed unless explicitly tor.
  • ea915f3: supervised startup/failure fixtures; they skip when the native
    argv spawn binding is unavailable.
  • 84af14a: bounded lossless typed-directory input ABI.
  • 434e431: typed restricted-discovery key projection into the Arti launch
    patch series.
  • 6ff8e04: bounded versioned onion create/authorize/revoke payload codecs,
    rejecting paths, private-key-like material, invalid ports/selectors, and
    trailing bytes; docs for onion opcodes and rights.
  • c44e1ea: corrected typed signature boundaries. Consensus includes the
    directory-signature keyword plus its required space; authcert includes the
    full dir-key-certification line and newline; missing markers fail; focused
    boundary tests were added. Recheck these tests before relying on the change.
  • d8dc654: authenticated onion IPC dispatch seam. Opcodes 20–26 are wired
    through lifecycle ownership and rights, with bounded accept/stop decoding,
    disconnect cleanup, cross-connection theft tests, and fail-closed behavior
    when no real adapter is attached. It deliberately does not fake Arti.

The Arti patch series also contains the external discovery hook, typed static
key builder helper, and launch-time SQLite snapshot projection. Verify with
./tools/apply-arti-patches --check; generated target/arti-patched files are
disposable and must not be edited as the source of truth.

Verification already observed

At the previous stable point, make test passed the Rust default/Arti/
arti-onion/RustCrypto suites, parser, policy, provenance, Jerboa IPC, storage,
supervised, sandbox, SBOM, and typed-route gates. Supervised fixtures reported
controlled skips on macOS because aproc-native-spawn-available? was false;
this is not successful supervised qualification.

The onion dispatch agent reported:

cargo test --locked -p jtor-engine --lib — 49 passed

cargo check --locked -p jtor-engine --features arti-onion-service — passed

The signed-prefix agent reported git diff --check clean and queued the
focused typed-document test behind concurrent builds. Verify independently.

Work remaining: implement, do not merely document

1. Real onion Arti adapter

Implement the OnionServiceAdapter boundary against the real async Arti
TorClient::launch_onion_service and RunningOnionService. Add the maintained
create-with-client-state helper in arti-client, using external SQLite state
and the durable identity. Implement bounded per-service command/accept tasks,
StreamRequest conversion into existing owned IPC streams, cancellation,
quotas, publication status, stop/reap behavior, and stable reopen identity.
Exercise the real dispatch paths in ipc.rs and arti_adapter.rs, not only
fake-adapter tests. Add real tests for owner/right/generation failures,
duplicate start, accept/stop races, queue exhaustion, disconnect, and restart.

2. SQLite-only restricted discovery

Make the arti-client/restricted-discovery feature active and verify the
resolved graph. Fix initial enabled-config construction: Arti rejects enabled
restricted discovery with no static keys or key directories, so project a
validated SQLite snapshot before config validation rather than using a fake
file/key. Apply complete replacement snapshots, track desired/applied
generations, and never resurrect deleted keys. Revoke-last-client must stop or
deny all while retaining identity; never turn discovery public. Test wrong key,
stale writer, crash, disk-full rollback, failed reconfigure, restart, and
identity-preserving restore. Document that an in-database counter cannot detect
whole-database rollback without an independent protected checkpoint.

3. Complete WASM directory construction

Use the corrected signed spans as immutable input. Implement maintained
authority-certificate and consensus constructors inside their owning Arti
modules, including PEM ownership, cross-cert/signature/time checks, trusted
authority quorum, and digest validation. Route download/cache/diff production
paths through the guest and constructors. Native parsing is permitted only as
a differential-test oracle. Replace negative marker grep gates with positive
production-route, malformed-output, signed-fixture, mutation, multi-signature,
offset, and resource-exhaustion tests.

4. Supervised client and warm restart

Diagnose _native-loaded and the exported jerboa_aproc_spawn symbol; the
current macOS skip is a missing native binding, not proof that macOS cannot
spawn. Run success/failure fixtures on ssh build@infra1, then add delayed
bind, authentication/storage failure, readiness timeout, child death, and
reaping cases. Prove meaningful encrypted SQLite state survives a fresh restart
with the same wrapping key and fails with a wrong key. Ensure secret ownership
matches the Rust-owned-key requirement.

5. DNS, TLS, bridges, transports

If general DNS is required, implement bounded DNS-over-TCP first through owned
Tor streams (MX/TXT, framing, matching, limits, timeouts), then DoT/DoH with
TLS identity and redirect policy. Never use the host resolver or ignore the
resolver argument. Add expired/not-yet-valid, timeout, EOF/close-notify,
negotiated-suite, and relay-identity TLS tests through the actual engine route.
Qualify plain bridges with identity failure/reconnect/no-public-fallback. For
each required pluggable transport, either implement and audit a Rust path or
record a concrete porting ticket with vectors, graph, and confinement contract.

6. Applications and confinement

Do the in-repo reference adapter and read-only inventories first. Separate
authorization is required before changing sibling repositories. On the five
canonical hosts (build@infra1, clockwork, netbased, biggus, stink),
run the appropriate Linux Podman/native BSD builds. Extend the namespace smoke
test into application/descendant egress enforcement with inherited-FD closure,
filesystem restrictions, IPv4/IPv6/UDP/DNS/local-proxy deny probes, allowed Tor
positive controls, captures, and crash/suspend checks.

7. Release and independent review

Prepare reproducible artifact/source/feature hashes, SBOM, advisory decisions,
migration/backup/restore drills, provenance checks including tampered fixtures,
threat model, IPC/storage/parser/FFI review packet, and rollback instructions.
Do not create signing credentials or self-review. Final external inputs are an
approved signing identity/authorized signer, an independent reviewer, controlled
canary/bridge endpoints, named sibling repositories, and any privileged host
configuration.

Rules for the batch agent

Use ~/work/jerboa-tor-* only; never edit /Users/user/mine/jerboa* or vendor
trees. Use Jerboa MCP balanced tools for every .ss edit and run balance checks.
Use jerboa-sqlite only for persistent production state. Run the required native
build on macOS and Linux Podman on Linux, then all relevant focused and full
tests. Update Tor-everywhere.md ledger entries with exact commands/results.
Do not call the goal complete until every requirement has authoritative evidence.
When finally ready, bump VERSION, commit the complete branch, push it, open
one Forgejo PR against master, check CI with fj -H git.jerboa.sh pr status ober/jerboa-tor#<number>, and leave merging to a human.

## Continuation objective Implement every requirement in `Tor-everywhere.md` for `jerboa-tor`, then run all required builds, tests, live qualification, security/release checks, and open exactly one Forgejo pull request at the very end. Do not claim completion from a green unchanged suite. Preserve the jerboa-sqlite-only storage rule, the no-C/C++ Tor invariant, authenticated IPC, typed Jerboa/Rust boundaries, and all AGENTS.md workflow rules. The next agent must read `Tor-everywhere.md` §78 first, then §70 and the rest of the document. §78 is the researched unblock guide and contains source anchors, corrected assumptions, implementation order, and acceptance tests. ## Current checkout and important warning Remote: `ssh://git@git.jerboa.sh:2222/ober/jerboa-tor.git` Local branch: `feat/tor-everywhere-complete`. The local branch is ahead of `origin/feat/tor-everywhere-complete`; the commits below are local work and have not been published in a PR. The working tree currently also has these uncommitted changes: * `Tor-everywhere.md`: §78 research-only continuation instructions. * `rust/jtor-engine/Cargo.toml`: adds `arti-client/restricted-discovery` to the `arti-onion-service` feature; the feature-check was started but was interrupted, so rerun it and record the result. Do not open a PR yet. Reconcile, test, commit, and push all final work only after the complete acceptance audit succeeds. ## Completed local work The following commits are present locally and should be preserved/reviewed: * `9d51a8c` and `fc8bf1d`: lifecycle state machine and multi-service registry with Created/Running/Stopping/Stopped/Failed, ownership, generation fencing, disconnect cleanup, and invalid-transition tests. * `10012a2`: separate `ONION_ADMIN`, `ONION_ACCEPT`, and `ONION_VIEW` rights. * `6b09b4a`: DNS resolver identity fails closed unless explicitly `tor`. * `ea915f3`: supervised startup/failure fixtures; they skip when the native argv spawn binding is unavailable. * `84af14a`: bounded lossless typed-directory input ABI. * `434e431`: typed restricted-discovery key projection into the Arti launch patch series. * `6ff8e04`: bounded versioned onion create/authorize/revoke payload codecs, rejecting paths, private-key-like material, invalid ports/selectors, and trailing bytes; docs for onion opcodes and rights. * `c44e1ea`: corrected typed signature boundaries. Consensus includes the `directory-signature` keyword plus its required space; authcert includes the full `dir-key-certification` line and newline; missing markers fail; focused boundary tests were added. Recheck these tests before relying on the change. * `d8dc654`: authenticated onion IPC dispatch seam. Opcodes 20–26 are wired through lifecycle ownership and rights, with bounded accept/stop decoding, disconnect cleanup, cross-connection theft tests, and fail-closed behavior when no real adapter is attached. It deliberately does not fake Arti. The Arti patch series also contains the external discovery hook, typed static key builder helper, and launch-time SQLite snapshot projection. Verify with `./tools/apply-arti-patches --check`; generated `target/arti-patched` files are disposable and must not be edited as the source of truth. ## Verification already observed At the previous stable point, `make test` passed the Rust default/Arti/ arti-onion/RustCrypto suites, parser, policy, provenance, Jerboa IPC, storage, supervised, sandbox, SBOM, and typed-route gates. Supervised fixtures reported controlled skips on macOS because `aproc-native-spawn-available?` was false; this is not successful supervised qualification. The onion dispatch agent reported: `cargo test --locked -p jtor-engine --lib` — 49 passed `cargo check --locked -p jtor-engine --features arti-onion-service` — passed The signed-prefix agent reported `git diff --check` clean and queued the focused typed-document test behind concurrent builds. Verify independently. ## Work remaining: implement, do not merely document ### 1. Real onion Arti adapter Implement the `OnionServiceAdapter` boundary against the real async Arti `TorClient::launch_onion_service` and `RunningOnionService`. Add the maintained create-with-client-state helper in `arti-client`, using external SQLite state and the durable identity. Implement bounded per-service command/accept tasks, `StreamRequest` conversion into existing owned IPC streams, cancellation, quotas, publication status, stop/reap behavior, and stable reopen identity. Exercise the real dispatch paths in `ipc.rs` and `arti_adapter.rs`, not only fake-adapter tests. Add real tests for owner/right/generation failures, duplicate start, accept/stop races, queue exhaustion, disconnect, and restart. ### 2. SQLite-only restricted discovery Make the `arti-client/restricted-discovery` feature active and verify the resolved graph. Fix initial enabled-config construction: Arti rejects enabled restricted discovery with no static keys or key directories, so project a validated SQLite snapshot before config validation rather than using a fake file/key. Apply complete replacement snapshots, track desired/applied generations, and never resurrect deleted keys. Revoke-last-client must stop or deny all while retaining identity; never turn discovery public. Test wrong key, stale writer, crash, disk-full rollback, failed reconfigure, restart, and identity-preserving restore. Document that an in-database counter cannot detect whole-database rollback without an independent protected checkpoint. ### 3. Complete WASM directory construction Use the corrected signed spans as immutable input. Implement maintained authority-certificate and consensus constructors inside their owning Arti modules, including PEM ownership, cross-cert/signature/time checks, trusted authority quorum, and digest validation. Route download/cache/diff production paths through the guest and constructors. Native parsing is permitted only as a differential-test oracle. Replace negative marker grep gates with positive production-route, malformed-output, signed-fixture, mutation, multi-signature, offset, and resource-exhaustion tests. ### 4. Supervised client and warm restart Diagnose `_native-loaded` and the exported `jerboa_aproc_spawn` symbol; the current macOS skip is a missing native binding, not proof that macOS cannot spawn. Run success/failure fixtures on `ssh build@infra1`, then add delayed bind, authentication/storage failure, readiness timeout, child death, and reaping cases. Prove meaningful encrypted SQLite state survives a fresh restart with the same wrapping key and fails with a wrong key. Ensure secret ownership matches the Rust-owned-key requirement. ### 5. DNS, TLS, bridges, transports If general DNS is required, implement bounded DNS-over-TCP first through owned Tor streams (MX/TXT, framing, matching, limits, timeouts), then DoT/DoH with TLS identity and redirect policy. Never use the host resolver or ignore the resolver argument. Add expired/not-yet-valid, timeout, EOF/close-notify, negotiated-suite, and relay-identity TLS tests through the actual engine route. Qualify plain bridges with identity failure/reconnect/no-public-fallback. For each required pluggable transport, either implement and audit a Rust path or record a concrete porting ticket with vectors, graph, and confinement contract. ### 6. Applications and confinement Do the in-repo reference adapter and read-only inventories first. Separate authorization is required before changing sibling repositories. On the five canonical hosts (`build@infra1`, `clockwork`, `netbased`, `biggus`, `stink`), run the appropriate Linux Podman/native BSD builds. Extend the namespace smoke test into application/descendant egress enforcement with inherited-FD closure, filesystem restrictions, IPv4/IPv6/UDP/DNS/local-proxy deny probes, allowed Tor positive controls, captures, and crash/suspend checks. ### 7. Release and independent review Prepare reproducible artifact/source/feature hashes, SBOM, advisory decisions, migration/backup/restore drills, provenance checks including tampered fixtures, threat model, IPC/storage/parser/FFI review packet, and rollback instructions. Do not create signing credentials or self-review. Final external inputs are an approved signing identity/authorized signer, an independent reviewer, controlled canary/bridge endpoints, named sibling repositories, and any privileged host configuration. ## Rules for the batch agent Use `~/work/jerboa-tor-*` only; never edit `/Users/user/mine/jerboa*` or vendor trees. Use Jerboa MCP balanced tools for every `.ss` edit and run balance checks. Use jerboa-sqlite only for persistent production state. Run the required native build on macOS and Linux Podman on Linux, then all relevant focused and full tests. Update `Tor-everywhere.md` ledger entries with exact commands/results. Do not call the goal complete until every requirement has authoritative evidence. When finally ready, bump `VERSION`, commit the complete branch, push it, open one Forgejo PR against `master`, check CI with `fj -H git.jerboa.sh pr status ober/jerboa-tor#<number>`, and leave merging to a human.
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
ober/jerboa-tor#4
No description provided.