Releases: budget-buddy-org/budget-buddy-contracts
Release list
v6.1.2
v6.1.1
v6.1.0
v6.0.0
6.0.0 (2026-05-28)
⚠ BREAKING CHANGES
- PATCH endpoints removed. Clients must use PUT with the
full resource body; sendnullfor nullable fields to clear them.
Co-Authored-By: Claude Opus 4.7 noreply@anthropic.com
- refactor: clear via field omission instead of explicit null
Replaces the local Mustache template override with a schema-level fix
that uses only out-of-the-box openapi-generator behavior.
monthlyBudget and description (on Category, Transaction, CategorySpendingRow,
and their *Write counterparts) are no longer marked required and no longer
typed as nullable. Clients clear these fields by omitting them from the
PUT body; the server treats absence and the previous explicit-null as the
same state. This sidesteps the openapi-generator behavior where required +
nullable getters end up with @NotNull on a spec-legal null payload.
- Removed config/spring-server.yaml
templateDir - Removed templates/JavaSpring/beanValidation.mustache
- Updated CLAUDE.md: documented "optional clearable" convention, removed
template override from Architecture, simplified PATCH-policy rationale
Co-Authored-By: Claude Opus 4.7 noreply@anthropic.com
- fix(spec): restore type: [..., null] on clearable fields
The previous commit dropped nullable to avoid the @NotNull-on-nullable
generator bug, but that left the spec lying about runtime behavior — the
server still accepts JSON null for these fields even though the schema
declared them strictly typed. That's contract drift.
Dropping required alone is enough to dodge the generator bug; nullable
can stay. The combination nullable: true, required: false is the
industry-conventional shape for "clearable" fields (Stripe, GitHub, MS
REST guidelines) and is what the runtime actually accepts.
- monthlyBudget on Category, CategoryWrite, CategorySpendingRow: back to
type: [integer, "null"] - description on Transaction, TransactionWrite: back to
type: [string, "null"] - Field docs now say "Send null (or omit) to clear any existing X"
- Read schemas emit the field with
nullwhen unset, so clients
deserialize one shape (always-present), not two - CLAUDE.md convention bullet rewritten to call out the
required-AND-nullable combo as the antipattern, not nullable itself
Generated Java output is unchanged versus the previous commit (still
@Nullable Long / @Nullable String, no @NotNull, @Min/@Size
preserved). The only change is that the spec is now honest about what
the server accepts.
Co-Authored-By: Claude Opus 4.7 noreply@anthropic.com
- chore(spec): consistency polish
- Reorder transaction paths to match categories: collection first, then
/summary and /summary/trend, then the by-id route. Spec ordering matches
/v1/categories now. - Enrich info.description with a self-contained primer (auth, error
format, money representation, pagination, mutation semantics) so anyone
reading the generated docs doesn't have to cross-reference five pages. - Document the "clearable field" rule (and the two distinct generator
quirks that motivate it) in CLAUDE.md so future contributors don't
re-introduce required+nullable on either read or write schemas.
No client-visible schema or operation changes versus the previous commit.
Co-Authored-By: Claude Opus 4.7 noreply@anthropic.com
- chore(spec): final consistency polish
- Summary endpoints (/v1/categories/summary, /v1/transactions/summary,
/v1/transactions/summary/trend) now use imperativeGet …titles,
matching every other GET operation in the spec. - Add
examplevalues to TransactionWrite.date, TransactionWrite.description,
and CategorySpendingRow.categoryName — read-side counterparts already had
them, the write/derived schemas were missing. - Document the implicit sort order on
GET /v1/categories(by name asc) so
clients don't have to rely on undocumented behavior. - Rename
replaceCurrentUserClientSettings→upsertCurrentUserClientSettings.
The operation creates the resource when absent and replaces it when
present; the operationId now matches the documented semantic, and the
generated SDK method name reads correctly. Breaking for SDK consumers,
but the PR is already feat! so the cost is bundled into the v6.0.0
migration that consumers will have to do anyway.
Co-Authored-By: Claude Opus 4.7 noreply@anthropic.com
Features
v5.0.0
5.0.0 (2026-05-28)
⚠ BREAKING CHANGES
- read schemas no longer include
createdAt/updatedAt;
write/update schemas reject unknown fields and requiredescription/
monthlyBudgetexplicitly; transactiondescriptionis now nullable
across all variants.
Co-Authored-By: Claude Sonnet 4.6 noreply@anthropic.com
- refactor: tighten spec descriptions, DRY client settings payload
- Strip deployment-specific detail from server descriptions (Raspberry Pi,
nginx, gradle bootRun command) — keep the spec agnostic to how the API is
hosted or started locally. - Extract reusable ClientSettingsPayload schema; ClientSettings.settings and
ClientSettingsWrite.settings now $ref it instead of duplicating the inline
opaque-object shape. - Add additionalProperties: false to FieldError for parity with other strict
schemas. - Simplify Me.id description so it describes the value (stable owner id)
instead of leaking how the server derives it from the OIDC subject. - Drop "(PUT semantics)" parentheticals from replace operations and PUT
request schemas — the HTTP verb and "Replace X" summary already convey it. - Standardize null-clearing phrasing across Category/Transaction write and
update schemas to "Pass null to clear the {budget|note}." - Rewrite Problem.errors description to specify when the array is populated
rather than restating that it's optional.
Co-Authored-By: Claude Opus 4.7 noreply@anthropic.com
- chore: pin pnpm via packageManager, bump @hey-api/openapi-ts
- Pin pnpm@11.4.0 via Corepack's packageManager field so local dev and CI
stay on the same version instead of drifting to whatever pnpm/action-setup
resolves at run time. - Bump @hey-api/openapi-ts 0.97.2 → 0.97.3 from pnpm up; lockfile refreshed.
Co-Authored-By: Claude Opus 4.7 noreply@anthropic.com
- ci: drop pnpm version pin from workflows, defer to packageManager
The packageManager field added in 245f460 conflicts with the explicit
"version: 10" passed to pnpm/action-setup, which now errors out with
ERR_PNPM_BAD_PM_VERSION on every workflow run. Removing the explicit
pin so action-setup reads the version from package.json's packageManager
field — single source of truth, and CI matches local.
Co-Authored-By: Claude Opus 4.7 noreply@anthropic.com
- docs: fix stale README claims and trim obsolete prerequisites
- Frontend client is fetch-based (@hey-api/client-fetch), not Axios.
- Pagination uses page/size/total, not the previously documented
total/limit/offset. - All endpoints require Bearer JWT — there are no login/register
endpoints in the spec; remove the misleading exception. - Drop hardcoded "1.1.0" version from Swift/Maven snippets; point at
the release badge for the current version. - Drop OpenAPI Generator CLI and Spectral CLI from prerequisites — they
install transparently via "pnpm install". - pnpm prerequisite reworded to reflect the Corepack-pinned setup.
- Release workflow steps rewritten to match the PR + squash-merge flow
documented in CLAUDE.md.
Co-Authored-By: Claude Opus 4.7 noreply@anthropic.com
Code Refactoring
v4.1.0
v4.0.0
4.0.0 (2026-05-08)
⚠ BREAKING CHANGES
- GET /v1/transactions/summary no longer accepts the
monthquery parameter and now returns an array of MonthlySummary
instead of a single object. Callers must migrate tofrom/to.
Co-Authored-By: Claude Opus 4.7 noreply@anthropic.com
- feat: add getTransactionsSummaryTrend endpoint
Splits per-month bucket trends into a separate endpoint instead of
overloading getTransactionsSummary. The single-month endpoint stays
untouched (one MonthlySummary, no [0] unwrap on the client). The new
endpoint serves dashboard sparklines: from/to month range, returns
MonthlySummary[] oldest first, empty months zero-filled, max 24 months.
Each endpoint speaks its native shape; no consumer has to unwrap a
1-element array for the common case.
Co-Authored-By: Claude Opus 4.7 noreply@anthropic.com