Skip to content

feat: add delete_account_metadata statement - #229

Draft
ascandone wants to merge 2 commits into
mainfrom
feat/delete-account-metadata
Draft

ascandone wants to merge 2 commits into
mainfrom
feat/delete-account-metadata

Conversation

@ascandone

@ascandone ascandone commented Nov 4, 2026 •

Copy link
Copy Markdown
Contributor

Adds a delete_account_metadata(account, key) statement.

delete_account_metadata(@alice, "status")
delete_account_metadata(scoped(@alice, "myscope"), "status")

Changes

  • Frontend: new builtin (account, string), gated behind the experimental-delete-account-metadata flag, requiring interpreter 0.1.4 when a version pragma is present. The LSP hover and diagnostics work through the analysis builtin table. StatementFnCallResolution now accepts VersionConstraints.
  • Store contract (breaking): interpreter.Store and vm.Store (numscript.Store / numscript.VMStore) both get DeleteAccountMetadata(ctx, account, scope, key string) error. The engine calls it during execution, in script order.
  • Bytecode: new opcode DELETE_ACCOUNT_META (0x26, one word: account, key, scope). The verifier rejects it inside a mark, as save is rejected, because a store delete cannot be undone. Exec checks the same. CurrentBytecodeVersion is now 0.2. 0.1 blobs are no longer readable, as for any 0.x bump.
  • Frozen corpus: an older 0.x freeze is now checked to be rejected and then run with its header changed to the current version. A freeze only adds programs that no earlier freeze already holds (ignoring the version bytes), so testdata/bytecode/0.2 holds only the 4 new programs instead of a ~950-file copy of 0.1. testdata/bytecode/0.1 is unchanged and still runs in full.
  • Errors: the interpreter returns a new DeleteMetadataError (exported). The VM wraps store failures in the existing VmStoreError.
  • Dependencies: ResolveDependencies reports the deleted key in MetaWrites.
  • Specs format: new expect.deletedMetadata (an ordered list of {account, key, scope?}) in the code and in v1.specs.schema.json. Fixtures are in experimental/delete-account-metadata/ and run on both engines.
  • builder: StmtDeleteAccountMetadata.

Semantics to review

  1. The store is called mid-run, even if the run fails later. The host must apply the deletions in the same transaction as the result, and discard them on error.

  2. Interaction with set_account_meta on the same key:

    • set, then delete: the earlier set is removed from AccountsMetadata.
    • delete, then set: the set is kept.

    The host must therefore apply the deletions before the result's metadata.

  3. Reading a key after deleting it is not defined yet. Today no engine reads metadata after a statement: the interpreter rejects a mid-script meta(), and the compiler compiles one in account position as scoped() (a separate bug on main). If mid-script meta() is supported, the VM would ask the store, so the result would depend on whether the store has applied the delete yet.

  4. The engine does not check whether the key exists. Deleting a missing key is up to the store, which can return nil or an error.

  5. StaticStore.DeleteAccountMetadata is a no-op, because a StaticStore is an immutable snapshot. As a result, numscript run/test and bytecode run do not show deletions in their output.

Not done

  • The difftest generator does not emit the new statement. The oracle (the old machine) has no equivalent, and SideResult does not capture store calls.
  • The frozen corpus checks postings and errors, not store calls.
  • The ledger has to implement DeleteAccountMetadata and bump its numscript pin.
  • Public docs on docs.formance.com are not updated.

Gated behind experimental-delete-account-metadata. Both engines call a new
Store.DeleteAccountMetadata method during execution and drop any earlier
set_account_meta of the same key from the result. Compiled to the new
DELETE_ACCOUNT_META opcode (0x26), which the verifier rejects inside a mark.
@NumaryBot NumaryBot added risk: high NumaryBot classified this pull request as high risk. bot-reviewed NumaryBot completed its review workflow for the current head. draft-reviewed NumaryBot reviewed this draft, but published no readiness signal. labels Nov 4, 2026
Older 0.x freezes keep running with their header re-stamped to the current
version, so a freeze only adds the programs no earlier freeze holds. The 0.2
freeze holds the four delete_account_metadata programs.
@ascandone
ascandone force-pushed the feat/delete-account-metadata branch from df1c77b to d096c68 Compare November 4, 2026 15:40
@NumaryBot

Copy link
Copy Markdown
Contributor

Warning

⛔ REVIEW BLOCKED — binary files were not reviewed

These changed binary/non-UTF8 files were excluded from the model input. Their contents have not been verified.

  • testdata/bytecode/0.2/experimental-delete-account-metadata-delete-then-set.numb
  • testdata/bytecode/0.2/experimental-delete-account-metadata-delete-then-set/keeps-a-write-made-after-the-delete/vars.nvar
  • testdata/bytecode/0.2/experimental-delete-account-metadata-delete.numb
  • testdata/bytecode/0.2/experimental-delete-account-metadata-delete/deletes-each-key-from-the-store-in-script-order/vars.nvar
  • testdata/bytecode/0.2/experimental-delete-account-metadata-scoped.numb
  • testdata/bytecode/0.2/experimental-delete-account-metadata-scoped/deletes-only-the-entry-of-the-account-s-scope/vars.nvar
  • testdata/bytecode/0.2/experimental-delete-account-metadata-set-then-delete.numb
  • testdata/bytecode/0.2/experimental-delete-account-metadata-set-then-delete/drops-an-earlier-write-to-the-deleted-key/vars.nvar
    Automated approval is blocked, even if the remaining text review succeeds. Remove these artifacts from the PR, provide reviewable sources, or address their exclusion explicitly in trusted review policy. Do not merge based on this automated review.

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

Labels

bot-reviewed NumaryBot completed its review workflow for the current head. draft-reviewed NumaryBot reviewed this draft, but published no readiness signal. risk: high NumaryBot classified this pull request as high risk.

Development

Successfully merging this pull request may close these issues.

2 participants