NewInstructionsProposalRequest
NewInstructionsProposalRequest builds the GovDAO proposal that rewrites this realm's instructions. It replaces the previously exported NewInstructionsProposalCallback.
SECURITY: the privileged closure must never leave this package.
The VM mints a crossing frame's `cur` from the CALLEE's declaring package, so a closure declared here always runs with valopers' identity no matter who invokes it — and whoever holds the closure chooses its Previous() by wrapping it in an executor of their own. Handing such a closure to a caller therefore hands out the ability to satisfy this realm's gate whichever principal it is pointed at: the handler in init.gno runs the action and `instructions` is rewritten with no proposal and no vote. That is what the exported callback did.
Returning a dao.ProposalRequest instead seals the capability: the executor is an unexported field with no accessor (dao.ProposalRequest exposes only Title/Description/Filter), so the only way to reach the closure is for GovDAO to execute the proposal that contains it.
Note this is deliberately stronger than returning a dao.Executor — even a dao.NewSafeExecutor-wrapped one. Executor.Execute is an exported method, so a returned Executor stays directly invocable by its holder, and SafeExecutor's only gate (InAllowedDAOs) FAILS OPEN while the allowedDAOs list is empty, which is the documented bootstrap state (see r/gov/dao/loader/v0). A sealed request has no such conditional.
The rule for this realm: no exported function may return a crossing closure, a dao.Executor, or anything else that carries valopers' frame identity — and no exported function may itself BE such a thing, i.e. have a signature assignable to dao's `func(realm) error` callback type, since the proxy would then invoke it on an attacker's behalf. filetests/z_foreign_realm_capability_filetest.gno pins the first; filetests/z_govdao_only_principal_filetest.gno pins the second.
Command
# WARNING: This command is running in an INSECURE mode.
# It is strongly recommended to use a hardware device for signing
# and avoid trusting any computer connected to the internet,
# as your private keys could be exposed.
gnokey maketx call -pkgpath "gno.land/r/gnops/valopers" -func "NewInstructionsProposalRequest" -args $'' -gas-fee 1000000ugnot -gas-wanted 1_000_000_000 -send "" -chainid "gnoland-1" -remote "https://rpc.gno.land" ADDRESSgnokey query -remote "https://rpc.gno.land" auth/accounts/ADDRESS
gnokey maketx call -pkgpath "gno.land/r/gnops/valopers" -func "NewInstructionsProposalRequest" -args $'' -gas-fee 1000000ugnot -gas-wanted 1_000_000_000 -send "" -broadcast=false ADDRESS > call.tx
gnokey sign -tx-path call.tx -chainid "gnoland-1" -account-number ACCOUNTNUMBER -account-sequence SEQUENCENUMBER ADDRESS
gnokey broadcast -remote "https://rpc.gno.land" call.tx