Skip to content

fix(api): update token expiration format to include milliseconds#1821

Open
pg-nanjum wants to merge 1 commit into
rundeck:4.0.xfrom
pg-nanjum:fix/token-expiration-milliseconds-format
Open

fix(api): update token expiration format to include milliseconds#1821
pg-nanjum wants to merge 1 commit into
rundeck:4.0.xfrom
pg-nanjum:fix/token-expiration-milliseconds-format

Conversation

@pg-nanjum

@pg-nanjum pg-nanjum commented Jun 17, 2026

Copy link
Copy Markdown

Summary

The `expiration` field in the Token API endpoints currently shows timestamps without milliseconds in the docs (e.g. `2017-03-25T21:16:50Z`). The actual API response now includes milliseconds (e.g. `2017-03-25T21:16:50.403Z`), causing customer automation scripts that do strict timestamp parsing to break.

Verification

Verified against a live RBA staging environment:

  • List Tokens (`GET /api/47/tokens`) — confirmed, all non-null expiration values include milliseconds
  • Get a Token (`GET /api/47/token/[ID]`) — confirmed, e.g. `"2026-01-13T09:28:31.403Z"`
  • Create a Token (`POST /api/47/tokens`) — inferred from same underlying token serialization layer

Changes

Updated 7 `expiration` field examples across 3 sections in `docs/api/index.md`:

Section Lines
List Tokens 254, 266, 279, 290
Get a Token 344, 364
Create a Token 444

Format corrected: `YYYY-MM-DDTHH:MM:SSZ` → `YYYY-MM-DDTHH:MM:SS.mmmZ`

Note: `expirationDate` fields in other API sections were intentionally left unchanged as they are unrelated to token management.

Root Cause Analysis

This is an unintentional side effect of the Grails 7 migration — not a deliberate API change.

Detail
Build deployed `6.0-RBA-20260610-9b4775e-e87f288`, deployed ~June 15–16 JST
Key change Grails upgraded from 6 → Grails 7.1.1 (Spring Boot 3.x, Jackson 2.21.3), landed on `main` ~April 4 (commit `c9adfb1a`)
Why the format changed In Grails 7, `respond()` uses Jackson's `MappingJackson2HttpMessageConverter` instead of the old Grails-specific JSON converter. Jackson's default ISO 8601 serializer for `java.util.Date` always emits milliseconds when they are non-zero
Why there was no explicit format `Token.groovy` declares `Date expiration` with no `@JsonFormat` annotation, so the format is entirely dictated by the runtime serializer
Grails 6 behavior The old Grails JSON converter used `yyyy-MM-dd'T'HH:mm:ssX` — no milliseconds
Grails 7 behavior Jackson's `StdDateFormat` emits `yyyy-MM-dd'T'HH:mm:ss.SSSZ` — milliseconds included

The field in question is `rundeckapp/src/main/groovy/com/dtolabs/rundeck/app/api/tokens/Token.groovy`:

@Ignore(onlyIfNull = true)
@ApiVersion(19)
@Schema(description = "since: v19", implementation = String, format = 'iso')
Date expiration   // no @JsonFormat — format depends on runtime serializer

A permanent fix would be to pin the format explicitly:

@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ssX")
Date expiration

This would restore the previous no-milliseconds format. Alternatively, the current millisecond-inclusive format can be accepted as correct going forward — which is what this doc PR does.

🤖 Generated with Claude Code

@pg-nanjum pg-nanjum requested a review from a team June 17, 2026 06:49
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