encryptPipeline (src/crypto/encrypt.ts:47) and sealRaw (src/crypto/encrypt.ts:182) each repeat the same setup block verbatim:
- resolve email attributes (
options.emailAttributes ?? DEFAULT_EMAIL_ATTRIBUTES)
Promise.all([fetchMPK(...), options.signingKeys ?? resolveSigningKeys(...)])
nowSeconds() + buildEncryptionPolicy(recipients, ts, emailAttrs)
- the
sign.type === 'yivi' && includeSender branch that adds the sender's own policy entry
- building
ISealOptions with the privSignKey conditional
Lines 49-81 and 184-210 are the same ~25 lines. The risk is divergence: a change to who ends up in the policy (the includeSender branch in particular decides whether the sender can decrypt their own file) has to be made twice, and there is no test that pins the two paths to the same policy.
Suggested shape: extract one async function prepareSeal(options): Promise<{ mpk, sealOptions }> and have both call it. Both paths already have coverage (tests/encrypt.test.ts, tests/api.test.ts), so the refactor should be behaviour-preserving; a test asserting encryptPipeline and sealRaw produce the same policy for the same inputs would lock it in.
Flagging for review rather than fixing directly — this is on the crypto path and the split may be deliberate.
encryptPipeline(src/crypto/encrypt.ts:47) andsealRaw(src/crypto/encrypt.ts:182) each repeat the same setup block verbatim:options.emailAttributes ?? DEFAULT_EMAIL_ATTRIBUTES)Promise.all([fetchMPK(...), options.signingKeys ?? resolveSigningKeys(...)])nowSeconds()+buildEncryptionPolicy(recipients, ts, emailAttrs)sign.type === 'yivi' && includeSenderbranch that adds the sender's own policy entryISealOptionswith theprivSignKeyconditionalLines 49-81 and 184-210 are the same ~25 lines. The risk is divergence: a change to who ends up in the policy (the
includeSenderbranch in particular decides whether the sender can decrypt their own file) has to be made twice, and there is no test that pins the two paths to the same policy.Suggested shape: extract one
async function prepareSeal(options): Promise<{ mpk, sealOptions }>and have both call it. Both paths already have coverage (tests/encrypt.test.ts,tests/api.test.ts), so the refactor should be behaviour-preserving; a test assertingencryptPipelineandsealRawproduce the same policy for the same inputs would lock it in.Flagging for review rather than fixing directly — this is on the crypto path and the split may be deliberate.