RFP-002 docs: freeze-authority extension guide + builder-guide updates - #1
Conversation
End-to-end usage guide for the freeze-authority extension: auto vs manual mode, seven management instructions, lifecycle (including recoverable renounce), per-account freeze, PDA-as-authority via CPI, F3 carve-outs. Extends build-a-spel-extension-library.md with three sections motivated by shipping a second extension: attribute-order convention for libs that re-export the #[instruction] shim, the optional wrap_instructions metadata for module-wide gate application, and the hard-dep composition pattern (freeze on top of admin). SUMMARY.md picks up the new page.
freeze_initialize self-elects the admin and takes no candidate, every CLI block uses the real invocation form, the candidate enum moves to the transfer section where it applies, and the embedded mode section covers the shared-account layout, born-vacant slots, and splice-only writes.
The transfer commands now take --new-account and --candidate. Both CLI examples updated to match the shipped surface.
The struct shows #[admin_slot] and #[freeze_slot] and the notes cover the #[admin_initialize] bootstrap next door and the layout agreement check the markers add.
da9f2bd to
0cdaf67
Compare
9cb2b1a to
b4854e3
Compare
Frontmatter and admonitions, matching the admin and library pages.
The admin branch's M2.5 alignment and the freeze branch each carried an auto-wrap section, and the merge kept both. One section survives at the earlier position with the richer body, the activation walk-through, and the composition note.
British spellings, abbreviations spelled out, and the flagged anthropomorphism reworded on the freeze page.
1246972 to
ac952fb
Compare
danisharora099
left a comment
There was a problem hiding this comment.
Same execution treatment as logos-co#355, and it inherits the same dependency-pin blocker (three unpinned git deps; also pin admin-authority to the rev freeze pins, 2eaa511, or the consumer ends up with two admin revs in one graph, which is how my first build failed). Two content fixes: the import snippet needs use freeze_authority::FreezeCandidate; (the generated dispatcher references it), and FreezeCandidate::Pda { program_id: AccountId } should be ProgramId. Everything else checked out exactly against the m3 stack: the seven-instruction surface, the dual gate in the IDL, auto and manual modes, exempt semantics and the shared-account embedded mode.
FreezeCandidate joins both import snippets, the generated dispatcher references it. The Pda variant's program_id field is a ProgramId, not an AccountId.
The frozen-state callable list includes the per-account freeze edits and consumer exemptions, the consumer prerequisites match the admin guide (six crates, cargo fetch, no default fn main), and the two inits go back to back because a LEZ transaction carries a single instruction. The freeze-account target is documented as hex, releasing a target that is not frozen documents its refusal, Signer transfers walk the co-sign exchange, and the candidate Pda field says ProgramId.
|
Same as logos-co#355, the packet assumes the released end state and lands last. Both content fixes are in at 13edb8d: FreezeCandidate joins the import snippets, and the Pda variant's program_id field is a ProgramId. The branch also merges: the frozen-state callable list now includes the per-account edits and consumer exemptions, the two inits are documented as consecutive transactions because a LEZ transaction carries a single instruction, the freeze-account target is hex, the not-frozen release refusal is documented, and the consumer prerequisites match the admin guide. On the pin alignment: the snippets stay unpinned for the release they describe, and the m3-settle tags across the four repos are the reproducible line meanwhile, admin-authority at the same rev freeze pins. |
danisharora099
left a comment
There was a problem hiding this comment.
Re-checked at 13edb8d. The FreezeCandidate import, the ProgramId type fix, and the write_to removal are all in; content now matches the shipped m3 stack exactly. Same single remaining condition as logos-co#355: the dep snippets need the temporary tag pins (including admin at its settle rev, so a consumer doesn't end up with two admin revs in one graph) - or the merge waits for the Logos-side merges.
The dependency blocks pin the fork revision the libraries pin, a branch reference fails even at the same commit because cargo keys git sources by reference kind. The admin page pins the v0.1.0 tag like the freeze page. A prerequisites section lists the packages the dependency tree and the spel CLI need, and the CLI gains install instructions, the package is named spel, not spel-cli. Marker imports and use super::* leave the snippets, the scanner consumes markers during expansion. The embedded snippets import AdminConfig, FreezeConfig, and FreezeCandidate, the generated transfer instruction references the candidate type even when consumer code never names it. The gate section shows a real body and states the post-state contract, declared accounts in declaration order, injected gate accounts appended automatically. Build and IDL steps are verified on a clean Ubuntu 24.04 with rustc 1.98, the lifecycle commands stay behind the draft banner.
The refuses-loudly guarantee applies to scanner-carrying framework revisions, on upstream main the marker is ignored and the program builds silently, so a missing surface points at the framework pin first. The spel binary must be built from the pinned revision, a scanner-less CLI omits every extension instruction with a clean exit. The draft banners state that the pages track unreleased code on a fork. The consumer snippet pins the fork revision and drops the marker import. The runtime library snippet carries its dependency block and names the state parameter after the inject role, injection, wrap stamping, and embedded retargeting resolve accounts by that name and a mismatched name fails the consumer's compile in embedded mode. Library bodies return inner account values, not the wrappers consumer handlers return. The gate helpers are hand-written and the gate is re-exported next to the marker. The wrap covers the extension's own instructions, which dispatch cross-crate, so an own instruction either covers the inject roles or carries the self exempt marker, the way freeze-authority's release and transfer ops carry freeze_exempt.
|
Acknowledged: this merged into the packet branch on 2026-08-21 and the freeze guide is now reviewed as part of logos-co#355, where the pin condition is met. Nothing further needed here. |
Description
Why this PR lives on the fork. It is the freeze-vs-admin review surface: the base is the admin docs branch, so the diff shows exactly what freeze-authority adds on top of logos-co#355. The upstream PR is deliberately deferred until logos-co#355 merges. logos-docs squash-merges, so after logos-co#355 lands the freeze branch rebases onto main and a clean freeze-only PR opens upstream.
Branched on top of
docs/admin-authority-rfp-001. Adds an end-to-end usage guide for the freeze-authority extension and extends the generic "Build a SPEL extension library" guide with sections motivated by shipping a second extension on top of the framework hook.Changes
docs/lez/extensions/freeze-authority.md(new): end-to-end usage guide for app developers consuming freeze-authority.docs/lez/extensions/build-a-spel-extension-library.md(extended): author-guide sections for building on the same framework primitives, see below.freeze-authority.mdoutlineModeled on the admin-authority guide. Sections:
#[freeze_authority], manual mode with(manual)arg; admin-authority composition).#[freeze_exempt].FreezeCandidate::SignerandPdavariants).caller-pda-seeds).#[admin_slot]and#[freeze_slot]markers, and the#[admin_initialize]bootstrap next door.Cross-references the admin-authority guide as the admin layer freeze composes with.
build-a-spel-extension-library.mdextensionsSections motivated by patterns that surfaced while shipping freeze-authority as the second extension on the framework hook:
#[instruction]in the library's own source, because the shim strips#[account(...)]before a lower gate attribute would run. Consumer code is unaffected.wrap_instructionsmetadata table (wrapper,skip,self_exempt_marker,exempt), the consumer activation flow, and the opt-in note.exempt, and the path-dep dedup for the diamond case.Breaking changes
None. Purely additive.
Open questions for maintainers
docs/lez/extensions/alongsideadmin-authority.md. Same depth, same anchor pattern. Confirm naming/placement.Relates to