Skip to content

(Medium) ORG-E1.3 generated error-reference (docs/ERROR_CODES.md) #141

Description

@EmeditWeb

Summary

There is no machine-generated, single-source error-code reference for the six Soroban contracts. The only error documentation in the repo is docs/standards/error-handling.md, and it is stale in three concrete ways: it marks the CreditLine, Merchant-Registry, and Liquidity-Pool sections "(Planned)" (docs/standards/error-handling.md:28,43,53) though all three ship today; it documents only 5 of the reputation contract's 11 real variants (:19-25 against contracts/reputation-contract/src/errors.rs:8-18); and it lists variants that exist nowhere in code — InvalidMerchant, UnauthorizedRepayment, LowReputationScore (:32,37,41) and the "Merchant" naming that was dropped when merchant-registry-contract was renamed to vendor-registry-contract (context/progress-tracker.md:112-116). The canonical catalog the roadmap expects — "error-code catalog scaffolded" (docs/PRD.md:331) — is absent: docs/ERROR_CODES.md does not exist (verified). Hand-maintained tables drift the moment any enum changes; only generation from the enums themselves keeps the catalog truthful.

Why these together: both workstreams are faces of one property — the published error reference is a build product of contracts/*/src/errors.rs, so it can never disagree with the code, and the drifting hand-written table that pretends to be that reference is retired in the same change. A generator with the old doc still in place leaves two contradictory sources; deleting the old doc without a generator leaves none.

Labels

area: contracts type: documentation priority: medium


Workstream 1 — Generate docs/ERROR_CODES.md from the six error enums

Objective

Produce one committed reference file whose every row is derived from the #[contracterror] enums, with a CI check that fails when the committed file and the generated file diverge.

Problem

Every contract's error enum carries no machine-readable metadata and no doc comments — contracts/creditline-contract/src/errors.rs:7-41 (33 variants), contracts/liquidity-pool-contract/src/errors.rs:6-26 (19), contracts/parameters-contract/src/errors.rs:6-26 (19), contracts/reputation-contract/src/errors.rs:7-19 (11), contracts/vouching-contract/src/errors.rs:6-20 (13), contracts/vendor-registry-contract/src/errors.rs:6-20 (13) — so there is no source a generator could read, and nothing forces the reference to update when a variant is added. The only existing table (docs/standards/error-handling.md) was edited by hand and has already drifted (:28,32,37,41,43,53).

Scope

  • scripts/generate-error-codes.sh (new — walks the enums, emits the catalog)
  • docs/ERROR_CODES.md (new — generated, committed, do-not-edit header)
  • Makefile (edit — error-codes target that runs the generator)
  • .github/workflows/contracts-ci.yml (edit — drift-check step)

Implementation

  1. Add scripts/generate-error-codes.sh that, for each contract dir under contracts/*-contract, parses src/errors.rs, extracts the enum name, each Variant = <n> and its trailing /// doc comment (if any), and writes a table section per contract: | Code | Variant | Recoverable | When | Fix |.
  2. Emit a fixed header line <!-- generated by scripts/generate-error-codes.sh — do not edit by hand --> and an ERROR_CODES_OUT env override, default docs/ERROR_CODES.md.
  3. Add make error-codes invoking the script; the script exits non-zero if any contract's errors.rs is missing or contains an unparseable variant line (so a new variant can never be silently skipped).
  4. Add a contracts-ci.yml step error-codes-drift: run the generator into a temp path and diff against the committed docs/ERROR_CODES.md; fail the job when they differ, printing the diff.
  5. Seed the "Recoverable / When / Fix" columns from doc comments where present and TBD where a variant is undocumented, so the file is truthful about gaps until the per-contract error-model work lands.

Acceptance Criteria

  • make error-codes regenerates docs/ERROR_CODES.md with exactly 33 creditline + 19 liquidity-pool + 19 parameters + 11 reputation + 13 vouching + 13 vendor-registry rows.
  • Mock: append a fake NewError = 99 to a copy of errors.rs → generator emits a 34th row and the CI drift check fails against the stale committed file.
  • Removing a variant from a temp copy produces a file that differs from the committed one and fails the drift check.
  • Running the generator twice is idempotent (byte-identical output).

Testing

  • Unit: a fixture errors.rs with 3 variants → parser returns exactly 3 (code, name, doc) tuples; a malformed line → non-zero exit.
  • Integration: run the full generator over the real workspace; assert row counts per contract match the enum counts above; assert the docs/ERROR_CODES.md in the tree is up to date.

Workstream 2 — Retire the stale docs/standards/error-handling.md table

Objective

Remove the hand-written, drifted error table and replace the standards page with a pointer to the generated reference plus the retained patterns guidance.

Problem

docs/standards/error-handling.md duplicates error data it cannot keep in sync: "CreditLine Contract (Planned)" (:28), "Merchant Registry (Planned)" (:43), "Liquidity Pool (Planned)" (:53) are all shipped contracts; its tables name phantom variants (InvalidMerchant :32, UnauthorizedRepayment :37, LowReputationScore :41) and phantom "Merchant" codes (:48-51); its reputation table stops at 5 variants (:19-25). It is also linked from the standards index (docs/standards/README.md:7), so the stale table is what readers reach today. The retained content — the #[contracterror] pattern, panic_with_error! usage, and safe-arithmetic guidance (:65-105) — is useful and should stay.

Scope

  • docs/standards/error-handling.md (edit — delete the four drifted tables; keep patterns + link the generated reference)
  • docs/standards/README.md (edit — relabel the link as "Error Handling (patterns) → see docs/ERROR_CODES.md")

Implementation

  1. Delete the "Reputation Contract", "CreditLine Contract (Planned)", "Merchant Registry (Planned)", and "Liquidity Pool (Planned)" tables from error-handling.md.
  2. Add a top pointer: "Canonical error codes: docs/ERROR_CODES.md (generated). This page covers patterns only."
  3. Retarget the standards index link so no reader lands on a phantom table.

Acceptance Criteria

  • grep -n "Planned\|Merchant\|InvalidMerchant\|LowReputationScore" docs/standards/error-handling.md returns nothing.
  • docs/standards/error-handling.md links to docs/ERROR_CODES.md, which exists.
  • Patterns sections (:65-105 content) are preserved.

Testing

  • Unit: n/a (docs).
  • Integration: make error-codes drift check still green after the edit; link-check that every docs/standards/README.md link resolves.

Shared acceptance criteria (whole epic)

  • cargo fmt --all --check, cargo clippy --workspace --all-targets --locked -- -D warnings, and cargo build --locked --target wasm32-unknown-unknown --release all exit 0; test count does not drop.
  • docs/ERROR_CODES.md exists, is generated, and the CI drift check passes.
  • No contract source is modified (this is a docs/tooling change); the six errors.rs files are read-only inputs.
  • No secrets; no changes outside scripts/, docs/, Makefile, .github/workflows/contracts-ci.yml.

Security & compatibility considerations

  • The generator reads only errors.rs; it must never execute contract code or touch target/.
  • The drift gate must fail closed: an unparseable enum or a missing contract dir exits non-zero rather than emitting an empty section.
  • No public API, ABI code value, or Rust symbol changes — this is documentation and tooling only.

References

  • contracts/creditline-contract/src/errors.rs:7-41 — 33-variant CreditLineError (the largest source section).
  • contracts/liquidity-pool-contract/src/errors.rs:6-26 — 19-variant LiquidityPoolError.
  • contracts/parameters-contract/src/errors.rs:6-26 — 19-variant ParametersError.
  • contracts/reputation-contract/src/errors.rs:7-19 — 11-variant ReputationError.
  • contracts/vouching-contract/src/errors.rs:6-20 — 13-variant VouchingError.
  • contracts/vendor-registry-contract/src/errors.rs:6-20 — 13-variant bare Error.
  • docs/standards/error-handling.md:28,32,37,41,43,48-53 — the drifted tables to retire.
  • docs/standards/README.md:7 — link to the stale page.
  • docs/PRD.md:331 — roadmap expectation "error-code catalog scaffolded".
  • context/progress-tracker.md:112-116 — merchant-registry → vendor-registry rename (why "Merchant" codes are phantom).
  • Makefile — target host for error-codes.
  • .github/workflows/contracts-ci.yml — CI host for the drift check.
  • Fed by the per-contract error-model documentation work (creditline, liquidity-pool, parameters, reputation, vouching, vendor-registry) which supplies the Recoverable/When/Fix columns; the namespacing work that assigns non-colliding code ranges lands in the same catalog.

If you're solving this with AI

In scope: scripts/generate-error-codes.sh, docs/ERROR_CODES.md, Makefile, .github/workflows/contracts-ci.yml, docs/standards/error-handling.md, docs/standards/README.md — only.
Out of scope: any change to contracts/*/src/*.rs; other repos; new dependencies beyond POSIX shell + awk/sed (already available); renaming contracts or variants; reformatting untouched docs.
Must: follow the repo PR template exactly; keep CI green for real (build + clippy + fmt + tests); add the generator's unit fixtures and the CI drift check; a regression fixture that FAILS when a variant is added to the committed file without regenerating; reference this issue (Closes #<n>); no secrets.

Contribution requirements: Follow the repo PR template exactly — https://github.com/StepFi-app/StepFi-Contracts/blob/main/.github/pull_request_template.md. Reference this issue in your PR. CI must pass green (build + fmt + clippy + tests). No secrets; no out-of-scope changes.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions