Skip to content

feat(save/latest): expose payload format on latest-save responses#20

Open
terafin wants to merge 1 commit into
joeblack2k:mainfrom
intarweb:feat/latest-expose-format
Open

feat(save/latest): expose payload format on latest-save responses#20
terafin wants to merge 1 commit into
joeblack2k:mainfrom
intarweb:feat/latest-expose-format

Conversation

@terafin

@terafin terafin commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

What

Adds a bare lowercase format field (e.g. "srm", "rtc") to every exists: true response from GET /save/latest, derived from the canonical record's payload extension.

Why

/save/latest currently returns {exists, sha256, version, id} — enough to detect a newer revision, but not the payload's file type. A sync helper that keys "latest" on slotName + recency can mistake a small, newer companion file for a newer revision of a different component that shares the same slot.

The concrete data-loss case: Game Boy / GBC saves where a helper stores the battery save (.srm, ~32 KB) and the RTC save (.rtc, 8 bytes) under the same slotName. The .rtc is written later, so it wins "latest" — and a naive helper then treats it as the newest revision of the slot and clobbers the .srm.

Exposing format lets a helper compare the canonical record's extension against the local target file's extension and skip-on-mismatch, instead of round-tripping through GET /saves/{id} (whose response shape doesn't carry the extension either).

How

  • New saveRecordFormat(rec saveRecord) string helper: strings.TrimPrefix(strings.ToLower(filepath.Ext(rec.PayloadFile)), ".").
  • Added "format" to all three exists: true /save/latest responses (standard, PlayStation-projection, N64-controller-pak paths). The data is already in hand at each writeJSON site.
  • Additive + backward-compatible — existing fields unchanged; clients that ignore format are unaffected.

Tests

save_format_test.go — 6 cases (.srm/.rtc, uppercase normalization, no-extension, empty, multi-dot). go build ./..., go vet ./cmd/server/, and gofmt all clean.

GET /save/latest returns {exists, sha256, version, id} but not the
payload's file type. Sync helpers that key "latest" on slotName +
recency can mistake a small, newer companion file for a newer revision
of a different component sharing the same slot — notably Game Boy
battery saves (.srm) and RTC saves (.rtc), which a helper may store
under the same slotName. The newer 8-byte .rtc then wins "latest" and
clobbers the 32 KB .srm.

Add a bare lowercase `format` field (e.g. "srm", "rtc") to every
exists:true /save/latest response, derived from the canonical record's
payload extension, so helpers can compare it against the local target
file's extension and skip-on-mismatch. Additive + backward-compatible.

Signed-off-by: terafin <terafin@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant