Skip to content

Commit 85cbe0d

Browse files
onspeedhpclaude
andcommitted
docs(audit): delta brief + diff bundle for Accretion follow-up
Prepares the consolidated state at audit-pending-v1 for Accretion's delta-audit review. Local-only artifacts; not published, not pushed. Deliverables under docs/audit/: - DELTA_BRIEF.md: structured summary by phase (P0-P5), audit asks per phase, byte-identity claims vs upstream lazorkit-protocol, slot-share strategy context, contact + reproducibility info - program-src.diff: full unified diff of program/ between audit-baseline-2026-02-accretion (d1eaaeb, the prior audited state) and audit-pending-v1 (9c97fe2, the new state) - program-src.diff.stat: per-file changed-line summary - upstream-parity.txt: byte-identity report — 13/19 changed files byte-identical with already-audited lazorkit-protocol; 6 differ only for fee-strip / cosmetic reasons (URLs, layout) Local git tags created (not pushed): - audit-baseline-2026-02-accretion → d1eaaeb (prior audit baseline) - audit-pending-v1 → 9c97fe2 (current consolidated state) Audit ask is explicit per phase: - P1 action enforcement engine: confirm no new vulnerabilities - P5 auth/processor port: confirm Accretion's prior review of byte-identical upstream files extends to program-v2 - Slot-share compatibility: confirm state account layouts forward-compatible for binary swap at LazorjRF… mainnet slot Per user direction, NOT publishing or pushing yet — awaiting explicit permission for those operational steps. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 9c97fe2 commit 85cbe0d

4 files changed

Lines changed: 5940 additions & 0 deletions

File tree

docs/audit/DELTA_BRIEF.md

Lines changed: 255 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,255 @@
1+
# Accretion Audit Delta Brief — `program-v2` `audit-baseline-2026-02-accretion``audit-pending-v1`
2+
3+
**Repository:** `lazor-kit/program-v2`
4+
**Previous audit:** Accretion Labs, Solana Foundation, February 2026, A26SFR1
5+
([audits/2026-accretion-solana-foundation-lazorkit-audit-A26SFR1.pdf](../../audits/2026-accretion-solana-foundation-lazorkit-audit-A26SFR1.pdf))
6+
**Previous baseline tag:** `audit-baseline-2026-02-accretion` → commit `d1eaaeb` (Merge PR #49 fix/audit-hardening, 17/17 findings resolved)
7+
**Delta tag:** `audit-pending-v1` → commit `9c97fe2`
8+
**Delta scope:** 21 files in `program/`, +4168 / −444 lines
9+
10+
This delta brief is for an **Accretion follow-up engagement** to confirm the
11+
changes between the two tags introduce no new vulnerabilities versus the prior
12+
audited state. Most of the new code is **byte-identical with the
13+
already-audited `lazorkit-protocol` repo** (commercial sibling under the same
14+
audit engagement); this is documented per-file in
15+
[upstream-parity.txt](./upstream-parity.txt).
16+
17+
---
18+
19+
## Strategic context (deploy plan)
20+
21+
`program-v2` ships at the **same mainnet program ID** as `lazorkit-protocol`
22+
(`LazorjRFNavitUaBu5m3WaNPjU1maipvSW2rZfAFAKi`). The foundation contract
23+
period uses the `program-v2` (no-fee) build at that slot; afterwards, the
24+
upgrade authority swaps the binary at the same slot to the `lazorkit-protocol`
25+
(commercial, with-fee) build.
26+
27+
**Implication for audit scope:** binary-swap compatibility requires that
28+
program-v2 and lazorkit-protocol share identical:
29+
- Account layouts (Wallet, Authority, Session, DeferredExec — verified
30+
byte-identical via `state/*.rs` ↔ upstream)
31+
- Instruction encoding (discriminators 0–9, account orderings — kept aligned
32+
via the IDL sync in P5.4)
33+
- Auth verification logic (auth/secp256r1/* — byte-identical with upstream
34+
after P5.1)
35+
36+
Audit confirmation of this delta therefore also benefits the slot-share
37+
strategy: any wallet/authority/session created on either binary remains
38+
verifiable by the other after swap.
39+
40+
---
41+
42+
## Delta by phase
43+
44+
The 23 commits between the two tags group into 5 phases:
45+
46+
### P0 — Cherry-pick guardrails (zero-audit, mechanical)
47+
48+
Tooling-only. Adds `scripts/strip-fee.sh`, `scripts/check-no-fee.sh`,
49+
`scripts/fee-paths.txt`, and `.github/workflows/check-no-fee.yml` to enforce
50+
that fee/admin/FeeRecord surface from `lazorkit-protocol` cannot leak into
51+
`program-v2` during cherry-picks. **No `program/` source changed.**
52+
53+
### P1 — Action types port + execute enforcement (delta-audit)
54+
55+
**Most security-relevant section of the delta.** New on-chain feature.
56+
57+
Files touched:
58+
- `program/src/state/action.rs` (NEW, 697 lines) — byte-identical with
59+
upstream `lazorkit-protocol/program/src/state/action.rs` (already audited).
60+
Defines 8 action types + parser + validator.
61+
- `program/src/state/session.rs` — minor (+23 lines) — adds
62+
`SESSION_HEADER_SIZE` const and `actions_slice()` helper. Byte-identical
63+
with upstream.
64+
- `program/src/state/mod.rs` — adds `pub mod action;`.
65+
- `program/src/processor/create_session.rs` — adopts variable-size session PDA
66+
for optional actions buffer + validation at creation. Byte-identical with
67+
upstream.
68+
- `program/src/processor/execute_actions.rs` (NEW, 1644 lines) —
69+
byte-identical with upstream `lazorkit-protocol/program/src/processor/execute/actions.rs`.
70+
Pre-CPI program whitelist/blacklist + token snapshots; post-CPI delta
71+
computation, SOL/token cap enforcement, recurring window resets, vault
72+
invariant defenses against System::Assign / SetAuthority escapes.
73+
- `program/src/processor/execute.rs` — wires pre/post action evaluation
74+
around the CPI loop, adds the L5 anti-CPI guard for sessions, gross SOL
75+
outflow tracking. Differs from upstream `processor/execute/immediate.rs`
76+
by **1 import-path line** (`processor::execute_actions::` vs
77+
`processor::execute::actions::`) due to flat vs nested processor layout.
78+
- `program/src/error.rs` — adds 13 error variants (3020–3032) for action
79+
validation, enforcement, and vault invariant defense.
80+
81+
**Audit ask (P1):** Confirm action enforcement engine + execute integration
82+
introduce no new vulnerabilities vs. the audited upstream version.
83+
84+
### P2 — Dual-cluster + security_txt (zero-audit, mechanical)
85+
86+
- `program/src/lib.rs` — embeds `security_txt!` with program-v2-specific URLs
87+
(only difference vs upstream is the URL strings — see `upstream-parity.txt`)
88+
- `assertions/src/lib.rs`, `assertions/Cargo.toml`, `program/Cargo.toml`
89+
Pattern D feature flags: `--features mainnet` embeds `LazorjRF…` (slot
90+
shared with upstream); `--features devnet` embeds `FLb7…`; no feature →
91+
`compile_error!` (prevents accidental cross-cluster deploy)
92+
93+
No on-chain logic change. Build-time configuration only.
94+
95+
### P3 — SDK consolidation (no audit)
96+
97+
Off-chain only. `program-v2/sdk/solita-client/` deleted; `program-v2/tests-sdk/`
98+
migrated to `@lazorkit/sdk-legacy` from npm (the same SDK
99+
`lazorkit-protocol` ships).
100+
101+
### P4 — Release infrastructure (no audit)
102+
103+
`CHANGELOG.md`, `docs/MAINNET_DEPLOY_RUNBOOK.md`, `.github/workflows/release.yml`.
104+
Documentation + CI only.
105+
106+
### P5 — Consolidate: auth + processor port + IDL sync (delta-audit)
107+
108+
**Aligns the remaining processor + auth files with upstream so the slot-share
109+
strategy works end-to-end.**
110+
111+
Files (all byte-identical with upstream after this phase, except where noted):
112+
- `program/src/auth/secp256r1/{mod,webauthn,introspection}.rs` — port from
113+
upstream. Replaces older typeAndFlags-format auth (which reconstructed
114+
clientDataJSON server-side) with the format that embeds full raw
115+
clientDataJSON in the auth payload. **Byte-identical with upstream.**
116+
- `program/src/processor/{create_wallet,manage_authority,transfer_ownership,
117+
execute_deferred,revoke_session}.rs` — port from upstream. Brings authority
118+
data layout to:
119+
`Secp256r1 authority = header(48) + cred_hash(32) + pubkey(33) + rpIdHash(32) = 145B`
120+
(previously variable-length raw rpId; now precomputed SHA256 digest at
121+
offset 113, saves one syscall per Execute). **Byte-identical with upstream.**
122+
- `program/src/instruction.rs` — Shank IDL declarations resynced from
123+
upstream (account metadata: writable modifiers, positions, descriptions);
124+
5 fee instruction variants (disc 10–14) stripped. Runtime not affected
125+
(sdk-legacy uses hand-written builders, not generated IDL).
126+
127+
**Audit ask (P5):** Since these files are byte-identical with upstream,
128+
confirm Accretion's prior review of the upstream files extends to this
129+
program. Specifically:
130+
- Auth payload format change (typeAndFlags → embedded clientDataJSON) — was
131+
this reviewed in the upstream audit? Any concerns specific to program-v2
132+
context?
133+
- Authority layout change (raw rpId → rpIdHash) — same question.
134+
135+
---
136+
137+
## Files NOT changed since baseline (sanity)
138+
139+
- `program/src/auth/ed25519.rs` — unchanged
140+
- `program/src/auth/mod.rs` — unchanged
141+
- `program/src/auth/traits.rs` — unchanged
142+
- `program/src/utils.rs` — unchanged
143+
- `program/src/state/wallet.rs` — unchanged (verified byte-identical with
144+
upstream — wallet account layout is the cross-binary contract for
145+
slot-share)
146+
- `program/src/state/authority.rs` — unchanged (same reasoning as wallet)
147+
- `program/src/state/deferred.rs` — unchanged
148+
- `program/src/processor/authorize.rs` — unchanged
149+
- `program/src/processor/reclaim_deferred.rs` — unchanged
150+
- `program/src/entrypoint.rs` — unchanged dispatch (still discs 0–9)
151+
152+
---
153+
154+
## Strip surface — what's NOT in `program-v2`
155+
156+
Per the slot-share strategy, the following are intentionally absent:
157+
158+
- `program/src/state/protocol_config.rs` — admin + fee config
159+
- `program/src/state/integrator_record.rs` — FeeRecord
160+
- `program/src/state/treasury_shard.rs` — treasury
161+
- `program/src/processor/protocol/{initialize_protocol,update_protocol,
162+
register_integrator,withdraw_treasury,initialize_treasury_shard}.rs`
163+
- Discriminators 10–14 in entrypoint dispatch
164+
- `try_collect_fee` function in entrypoint
165+
- `ProtocolError` enum (codes 4001–4007)
166+
- `ProtocolConfig` / `FeeRecord` / `TreasuryShard` discriminator slots (5/6/7)
167+
in `state/mod.rs::AccountDiscriminator`
168+
169+
`scripts/check-no-fee.sh` enforces this via `scripts/fee-paths.txt`. CI fails
170+
on any introduction. Verified clean at `audit-pending-v1`.
171+
172+
---
173+
174+
## What we want from this engagement
175+
176+
Specific questions for Accretion:
177+
178+
1. **P1 action enforcement** — is the `evaluate_pre_actions` /
179+
`evaluate_post_actions` engine + integration into `execute.rs` and
180+
`create_session.rs` introducing any new vulnerabilities the prior audit
181+
didn't cover? Action discriminator collision, integer overflow in
182+
recurring-limit window math, race conditions between snapshot/execute,
183+
vault invariant gaps?
184+
185+
2. **P5 auth port** — confirm the typeAndFlags → embedded-clientDataJSON
186+
format change is safe in this context. Particular attention to:
187+
- origin field validation (intentionally omitted — see [audit doc L1
188+
comment](../../program/src/auth/secp256r1/mod.rs))
189+
- challenge field base64url encoding/decoding round-trip
190+
- rpIdHash computation timing
191+
192+
3. **P5 authority layout change** — confirm the raw rpId → rpIdHash storage
193+
change preserves all binding properties. Specifically that the on-chain
194+
stored rpIdHash remains tied to the credential at registration.
195+
196+
4. **Slot-share compatibility** — given program-v2 will live at
197+
`LazorjRF…` mainnet slot and later be replaced in-place by
198+
`lazorkit-protocol`'s commercial binary, confirm:
199+
- State account layouts are forward-compatible (existing Wallet,
200+
Authority, Session, DeferredExec accounts created by program-v2 are
201+
readable + valid for the commercial binary)
202+
- Auth verification continues working for sessions/wallets created
203+
pre-swap
204+
205+
5. **Anything Accretion flagged in the prior audit that may have regressed**
206+
— full diff bundle at [program-src.diff](./program-src.diff) for
207+
line-by-line review.
208+
209+
---
210+
211+
## Deliverables included
212+
213+
- [DELTA_BRIEF.md](./DELTA_BRIEF.md) (this file)
214+
- [program-src.diff](./program-src.diff) — full unified diff of `program/`
215+
between the two tags (~5600 lines)
216+
- [program-src.diff.stat](./program-src.diff.stat) — per-file changed-line
217+
counts
218+
- [upstream-parity.txt](./upstream-parity.txt) — byte-identity report vs
219+
`lazorkit-protocol`
220+
- Git tags `audit-baseline-2026-02-accretion` (commit `d1eaaeb`) and
221+
`audit-pending-v1` (commit `9c97fe2`)
222+
- This brief is intended to be sent alongside the on-chain `security_txt!`
223+
pointer to the prior PDF.
224+
225+
## Out of scope for this brief
226+
227+
- `tests-sdk/`, `sdk/`, `docs/`, `scripts/`, `.github/`, `Cargo.toml`,
228+
`assertions/Cargo.toml` — non-program changes (test infrastructure, build
229+
config). Available in the full `git diff audit-baseline-2026-02-accretion..audit-pending-v1`
230+
if Accretion requests but not part of the on-chain audit ask.
231+
- Operational items (mainnet deploy, multisig setup, binary swap procedure)
232+
— handled in [docs/MAINNET_DEPLOY_RUNBOOK.md](../MAINNET_DEPLOY_RUNBOOK.md).
233+
234+
---
235+
236+
## Build reproducibility
237+
238+
```bash
239+
git checkout audit-pending-v1
240+
cd program && cargo build-sbf --features mainnet
241+
shasum -a 256 ../target/deploy/lazorkit_program.so
242+
# Hash should match the artifact in the eventual mainnet deploy.
243+
```
244+
245+
CI workflow at `.github/workflows/release.yml` reproduces and publishes the
246+
hash on each tag push.
247+
248+
---
249+
250+
## Contact
251+
252+
- Email: security@lazorkit.app
253+
- GitHub Security Advisories: https://github.com/lazor-kit/program-v2/security/advisories/new
254+
- On-chain pointer: `solana program show LazorjRFNavitUaBu5m3WaNPjU1maipvSW2rZfAFAKi`
255+
`security_txt!` block links to this repo + audit PDF.

0 commit comments

Comments
 (0)