fix(program)!: fixes for next release - #222
Merged
Merged
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Greptile SummaryThe PR strengthens plan-update freshness and sponsored plan-creation support.
Confidence Score: 4/5The implementation appears safe to merge, but the outstanding security documentation wording should be corrected. The plan-update freshness checks and client plumbing appear coherent; the remaining issue is that the cancellation replay documentation still excludes the reachable case where a transfer executes before the replayed cancellation. Files Needing Attention: README.md Important Files Changed
Sequence DiagramsequenceDiagram
participant App
participant SDK
participant Program
participant Plan
App->>SDK: updatePlan(new values)
SDK->>Plan: Fetch live plan snapshot
Plan-->>SDK: createdAt, endTs, pullers, metadataUri
SDK->>Program: UpdatePlan(new values + expected snapshot)
Program->>Plan: Compare expected and live fields
alt Snapshot matches
Program->>Plan: Apply update
else Snapshot differs
Program-->>App: StalePlanApproval
end
Reviews (15): Last reviewed commit: "test(fuzz): thread update_plan expected_..." | Re-trigger Greptile |
Compute Unit Report
🔺 increase · 🔻 decrease · – unchanged · 🆕 new · 🗑 removed (vs Generated: 2026-07-29 |
dev-jodee
force-pushed
the
docs/cancel-now-approval-granularity
branch
from
July 27, 2026 14:34
87bfc62 to
ef30668
Compare
dev-jodee
force-pushed
the
docs/cancel-now-approval-granularity
branch
from
July 27, 2026 14:40
ef30668 to
653dec5
Compare
dev-jodee
force-pushed
the
docs/cancel-now-approval-granularity
branch
from
July 27, 2026 15:09
eb2962c to
7ffef20
Compare
The on-chain handler accepts a trailing optional rent payer (writable signer), but the Codama definition listed only five accounts, so the IDL and generated clients could not express sponsored plan creation. Declare the payer with the omitted-account strategy, matching the other creation instructions, and regenerate the IDL. Adds a client test pinning the payer's position and writable-signer role.
UpdatePlanData carried only replacement values, so an owner-signed but unsubmitted update (durable nonce or reorder window) stayed valid after a later update changed the plan — notably restoring a puller the owner had removed, re-authorizing it to pull from every subscription under the plan. A stale update could likewise apply to a plan recreated at the same PDA after deletion. Add expected_created_at, expected_end_ts, expected_pullers and expected_metadata_uri to the instruction data and reject with the new StalePlanApproval error when any differs from the live plan, binding each signed update to the exact state the owner observed. The TS plugin client auto-fills the expected fields from the live plan; the overlay requires them explicitly, and the webapp passes the displayed plan state. BREAKING CHANGE: update_plan instruction data grows by 272 bytes of expected_* fields. Transactions built against the prior format fail with InvalidInstructionData.
Group the flat list under authority-lifecycle, signed-transaction freshness, and collectability headings, and state the init_id slot semantics once instead of restating them per bullet. Add a note that a held one-transaction init + sentinel subscribe/create bundle survives revokeSubscriptionAuthority: it re-creates the authority in its landing slot and the sentinel binds, restoring a spendable permission with no fresh signature. The existing wording only covered a standalone sentinel create needing a same-slot re-init, understating the self-contained-bundle case.
build.rs swallowed generate_idl errors into a cargo:warning and exited zero, so a change that still compiles but breaks IDL generation could pass generate-idl/check-generated and be released with stale generated clients. Return the Result from main so cargo exits nonzero on failure, propagating through every release and publish path that compiles the program.
The update_plan wire change added expected_created_at/end_ts/pullers/ metadata_uri, so the fuzz action_update_plan literal no longer matches UpdatePlanData. Populate the expected_* fields from the live plan so the harness compiles and its updates still pass the new StalePlanApproval check.
dev-jodee
force-pushed
the
docs/cancel-now-approval-granularity
branch
from
July 29, 2026 17:13
a3ba0ff to
903a7e2
Compare
amilz
approved these changes
Jul 29, 2026
dev-jodee
added a commit
that referenced
this pull request
Jul 30, 2026
* docs: add changelog entries for stale-approval guards Document the Unreleased breaking changes across the program and both client changelogs: resume_subscription expected_expires_at_ts (#214), cancel_subscription_now expected_current_period_start_ts (#221), update_plan expected_* plan-state binding (#222), the same-slot abandoned-recovery guard (#221), and the new StaleSubscriptionApproval (521) / StalePlanApproval (522) errors. * docs: fold cancel-now consent binding into its Added entries CancelSubscriptionNow landed after the 0.4.0 release and has never shipped, so binding its instruction data is part of the new feature, not a breaking change. Describe expected_current_period_start_ts in the existing Added bullets and drop the Breaking entries. * docs: note cancel-now emits SubscriptionCancelledEvent --------- Co-authored-by: Jo D <dev-jodee@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
expected_created_at,expected_end_ts,expected_pullers,expected_metadata_uritoUpdatePlanDataand reject with newStalePlanApproval(522) when any differs from the live plan. A withheld owner-signed update can no longer restore a puller removed by a later update, nor apply to a plan recreated at the same PDA. TS plugin client auto-fills the expected fields from the live plan; the standalone overlay requires them explicitly; the webapp passes the displayed plan stateinit_idslot semantics once, and document (a) thatcancel_subscription_nowapprovals bind to second-granularcurrent_period_start_ts, and (b) that a held one-tx init + sentinel subscribe/create bundle survivesrevokeSubscriptionAuthority— the reliable defense is to keep the held transaction from landingTest Plan
just integration-test— 274 passed, incl. newupdate_plan_rejects_stale_approval_that_restores_removed_pullerandupdate_plan_rejects_approval_from_previous_plan_lifecyclejust test-client— 66 + 1 offline passedpnpm vitest run test/create-plan-payer.test.tsBreaking Changes
update_planinstruction data grows by 272 bytes ofexpected_*fields; transactions built against the prior format fail withInvalidInstructionData. TS SDK plugin callers are unaffected (auto-fill); direct overlay/builder callers must supply the observed plan state.