fix(server,ui): use relative expires_in for install key expiration - #6860
Conversation
|
Claude finished @luizhf42's task in 11m 22s —— View job Code Review CompleteReviewed 13 files across code quality, security, testing, language patterns, and architecture. 3 inline issues posted (2 high, 1 medium) — all in the frontend edit flow.
Additional notesThe Go/server side is clean: the If you've addressed the feedback and want a new review, tag |
336715d to
3750396
Compare
|
/review |
|
Claude finished @otavio's task in 3m 35s —— View job Code Review CompleteReviewed 13 files across code quality, security, testing, language patterns, and architecture. 1 inline issue posted (1 medium) — a residual edge case in the frontend expiry field.
Additional notesThe three issues from the prior review round are correctly resolved:
The Go/server side is clean: the If you've addressed the feedback and want a new review, tag |
3376ec3 to
0f68336
Compare
|
/review |
|
Claude finished @otavio's task in 8m 3s —— View job Code Review CompleteReviewed 14 files across code quality, security, testing, language patterns, and architecture. 1 inline issue posted (1 low) — a residual edge case in the expiry field.
Additional notes
The three issues from the prior rounds are correctly resolved: the Edit initializer derives The Go/server side is clean: the If you've addressed the feedback and want a new review, tag |
|
/review |
|
Claude finished @otavio's task in 2m 17s —— View job Code Review CompleteReviewed 14 files across code quality, security, testing, language patterns, and architecture — no new issues found. The code looks good as-is. The current HEAD is unchanged since the previous Two low-severity items remain open from prior rounds (already noted in earlier threads, not re-posted): the If you push additional changes and want a new review, tag |
4ca8f90 to
950fd3f
Compare
|
/review |
|
Claude finished @otavio's task in 13m 46s —— View job Code Review CompleteReviewed 15 files across code quality, security, testing, language patterns, and architecture. 2 inline issues posted (1 high, 1 medium) — both in the frontend edit/expiry flow.
Additional notesThe Go/server side remains clean: the If you've addressed the feedback and want a new review, tag |
e72f385 to
2328f56
Compare
|
/review |
|
Claude finished @gustavosbarreto's task in 7m 35s —— View job Code Review CompleteReviewed 11 files across code quality, security, testing, language patterns, and architecture. 1 inline issue posted (1 medium) — a client-side expiry-state inconsistency in the Edit drawer.
Additional notesThe rest of the change is clean and the prior review rounds are fully resolved:
Two lower-signal items were considered and not posted: a dormant If you've addressed the feedback and want a new review, tag |
2328f56 to
b75ed04
Compare
|
/review |
|
Claude finished @otavio's task in 14m 30s —— View job Code Review CompleteReviewed 11 files across code quality, security, testing, language patterns, and architecture. 1 inline issue posted (1 medium) — a missing upper bound on the new
Additional notesThe rest of the change is clean and prior review rounds are fully resolved:
One lower-signal UX observation (not posted inline): in the edit drawer, If you've addressed the feedback and want a new review, tag |
…es_in` Users west of UTC saw the wrong expiration date because the frontend built a midnight-UTC ISO string that `date-fns` rendered in local time, shifting it back a day. Instead of patching the timezone math, the API now accepts `expires_in` (days from now) and the server computes the absolute timestamp via `clock.Now().AddDate(0, 0, days)`. Server: `OptionalTime` renamed to `OptionalInt` (same RFC 7396 three-state semantics). `installKeyExpiry` replaces the old `validateInstallKeyExpiry`. Four new update-path tests cover set/clear/leave-unchanged/reject-invalid. UI: the calendar picker is kept but converts selections to day counts via `differenceInCalendarDays`. An `expiryTouched` flag in the edit drawer ensures `expires_in` is only sent when the user changes the field, preventing silent expiry drift on unrelated edits. An expired-key `Callout` warns the user and clears when they pick a new date.
b75ed04 to
0d70664
Compare
|
/review |
|
Claude finished @otavio's task in 7m 14s —— View job Code Review CompleteReviewed 11 files across code quality, security, testing, language patterns, and architecture — no new issues found. The code looks good as-is. The final commit ( All prior-round feedback remains correctly resolved: the Two lower-signal items were considered and not posted (both already weighed in earlier rounds): a dormant If you push additional changes and want a new review, tag |
What
Install key create/update API now accepts
expires_in(days from now) instead ofexpires_at(absolute ISO date-time). The server computes the absolute timestamp. The UI keeps the calendar day-picker but converts selections to relative days internally.Why
Users west of UTC saw the wrong expiration date — picking Sep 3 showed Sep 2. The frontend built a midnight-UTC ISO string and
date-fnsformat()rendered it in local time, shifting it back a day. Rather than patching the timezone math, the API was changed to accept relative days (matching the SSH identity and API key pattern), eliminating client-side date computation entirely.Changes
expires_at(string, date-time, nullable) replaced withexpires_in(integer, minimum 1, optional) on create and update. Responseexpires_atchanged fromformat: datetoformat: date-time.ExpiresAt *time.Time→ExpiresIn *inton create.OptionalTime→OptionalInton update (same RFC 7396 three-state semantics: omit = unchanged, null = never, value = days from now).validateInstallKeyExpiryreplaced withinstallKeyExpiry(days *int) *time.Time, mirroringsshIdentityExpiry. The server computes the absolute timestamp viaclock.Now().AddDate(0, 0, *days).ExpirationField: keeps the calendar day-picker but converts selections to day counts viadifferenceInCalendarDays. Presets (30d/60d/90d/1y) compare by day count instead of ISO strings.expires_inviakeyExpiryPayload(create) andkeyExpiryUpdatePayload(update). AnexpiryTouchedflag in the edit drawer ensuresexpires_inis only sent when the user changes the field, preventing silent expiry drift on unrelated edits. An expired-keyCalloutwarns the user and clears when they pick a new date.Testing
TZ=America/Sao_Paulo) — the displayed date should match what was chosen.