One deposit creates one bundle commitment. That commitment is the public leaf stored by the pool; the child commitments and secrets remain inside the bundle and recovery data.

The objects

Spending requires both sides: the secret bundle and its matching pool commitment. The recovery data provides the secret side.

From deposit to root

1

Client prepares the bundle

The template, child secrets, parent amount, runtime context, and encrypted recovery payload are fixed before submission.
2

Pool validates the deposit

The pool checks the six public inputs, proof, ETH value, commitment uniqueness, and payload binding.
3

Pool inserts one leaf

CommitmentInserted assigns the bundle commitment a leaf index.
4

Pool accepts the new root

RootAccepted names the new root, previous root, and inserted bundle commitment.

What the withdrawal proves

The private witness connects the selected child to its bundle, then connects the bundle commitment to an accepted root.
One bundle creates one public tree leaf. Its two child notes share that membership path and keep separate nullifiers.

Expired roots

The pool keeps a bounded root history. RootExpired leaves the bundle intact and asks you to rebuild membership against a newer accepted root. Refresh membership against a newer root containing the same bundle commitment. Do not alter the recovery data or invent a replacement commitment.