Skip to content

RFP-002 docs: freeze-authority extension guide + builder-guide updates - #1

Merged
mmlado merged 14 commits into
docs/admin-authority-rfp-001from
docs/freeze-authority-rfp-002
Aug 21, 2026
Merged

RFP-002 docs: freeze-authority extension guide + builder-guide updates#1
mmlado merged 14 commits into
docs/admin-authority-rfp-001from
docs/freeze-authority-rfp-002

Conversation

@mmlado

@mmlado mmlado commented Jun 30, 2026

Copy link
Copy Markdown
Owner

Description

Note on RFP-002 deliverables. This PR adds the developer documentation for the freeze-authority extension shipping under RFP-002, awarded to @mmlado. The runtime library + sample programs live in the companion repository mmlado/spel-freeze-authority. The framework side is tracked from logos-co/spel#233, with the M2.5/M3 milestone work on the mmlado/spel milestone branches.

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.md outline

Modeled on the admin-authority guide. Sections:

  • When to use it (circuit-breaker pause + per-account blocklist).
  • Add the dependency (Cargo lines).
  • Annotate the module (auto mode with bare #[freeze_authority], manual mode with (manual) arg; admin-authority composition).
  • Seven management instructions table.
  • Initialization window (closed by admin-signature requirement per ADR-0006).
  • Gate an instruction (both modes).
  • Exempt with #[freeze_exempt].
  • Choose an initial freeze authority (FreezeCandidate::Signer and Pda variants).
  • Freeze and unfreeze the program.
  • Freeze and unfreeze a specific account.
  • Transfer freeze authority.
  • Use a program (PDA) as freeze authority (CPI via caller-pda-seeds).
  • Renounce freeze authority (vacates, recoverable by admin per ADR-0007, distinct from admin's terminal renounce).
  • Embedded mode: the freeze slot inside the consumer's own account, shared with admin at distinct offsets, #[admin_slot] and #[freeze_slot] markers, and the #[admin_initialize] bootstrap next door.
  • Verify your integration (IDL check).
  • Security notes (init order, recoverable renounce, exempt is shallow, auto-mode covers admin via metadata exempt, per-account PDAs persist).
  • Reference (link to companion repo for ADRs + lifecycle).

Cross-references the admin-authority guide as the admin layer freeze composes with.

build-a-spel-extension-library.md extensions

Sections motivated by patterns that surfaced while shipping freeze-authority as the second extension on the framework hook:

  • Attribute-order convention (subsection under "Per-instruction gate attributes"): gate attributes that do shape validation must sit above #[instruction] in the library's own source, because the shim strips #[account(...)] before a lower gate attribute would run. Consumer code is unaffected.
  • Auto-wrap every instruction (consolidated): the base branch carried a compact auto-wrap summary from the M2.5 alignment. This branch replaces it with the full treatment: the wrap_instructions metadata table (wrapper, skip, self_exempt_marker, exempt), the consumer activation flow, and the opt-in note.
  • Composing with another extension (hard dep): the freeze-on-top-of-admin pattern. Cargo dep, dual markers, importing gate attributes from the dep, listing the dep's instructions in exempt, and the path-dep dedup for the diamond case.

Breaking changes

None. Purely additive.

Open questions for maintainers

  1. Page placement. Placed under docs/lez/extensions/ alongside admin-authority.md. Same depth, same anchor pattern. Confirm naming/placement.
  2. Style consistency. Mirrored admin-authority's section structure to keep both extension guides discoverable. Open to consolidating shared sections into a shared explainer if the docs site prefers that pattern.

Relates to

mmlado added 4 commits August 4, 2026 06:51
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.
@mmlado
mmlado force-pushed the docs/freeze-authority-rfp-002 branch from da9f2bd to 0cdaf67 Compare August 4, 2026 04:54
@mmlado
mmlado force-pushed the docs/admin-authority-rfp-001 branch from 9cb2b1a to b4854e3 Compare August 4, 2026 07:16
mmlado added 4 commits August 4, 2026 09:18
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.
@mmlado
mmlado force-pushed the docs/freeze-authority-rfp-002 branch from 1246972 to ac952fb Compare August 4, 2026 08:24

@danisharora099 danisharora099 left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

mmlado added 4 commits August 10, 2026 12:13
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.
@mmlado

mmlado commented Aug 10, 2026

Copy link
Copy Markdown
Owner Author

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.

@mmlado
mmlado requested a review from danisharora099 August 10, 2026 11:56

@danisharora099 danisharora099 left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

mmlado added 2 commits August 21, 2026 10:57
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.
@mmlado
mmlado merged commit 8c42514 into docs/admin-authority-rfp-001 Aug 21, 2026
2 checks passed
@danisharora099

Copy link
Copy Markdown

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants