Skip to content

Commit f58ad3a

Browse files
fix(ticket-client): preserve tokenRefreshedAt on inline token refresh (#1783)
## Summary - Adds `tokenRefreshedAt` (ISO 8601 timestamp) to the SM secret payload written by `OAuthCredentialManager#writeTokens()` on inline token refresh - Previously, auth-service wrote this field at OAuth callback time, but ticket-client's inline refresh overwrote the secret without it — the timestamp disappeared after the first inline refresh ## Context Found during alignment review of auth-service PR #595 against ticket-client PR #1701. The field is observability-only (not read by any code path), but ops tooling that inspects SM secrets to check token freshness loses the timestamp. ## Test plan - [x] Existing test updated to verify `tokenRefreshedAt` is present and recent in written SM payload - [x] 200 tests passing, 100% coverage 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 5a7be7d commit f58ad3a

2 files changed

Lines changed: 4 additions & 0 deletions

File tree

packages/spacecat-shared-ticket-client/src/credentials/oauth-credential-manager.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -449,7 +449,9 @@ export default class OAuthCredentialManager {
449449
SecretString: JSON.stringify({
450450
accessToken: refreshed.access_token,
451451
refreshToken: refreshed.refresh_token,
452+
// expiresAt: epoch ms (numeric comparisons); tokenRefreshedAt: ISO 8601 (audit/display)
452453
expiresAt: Date.now() + refreshed.expires_in * 1000,
454+
tokenRefreshedAt: new Date().toISOString(),
453455
requiresReauth: false,
454456
}),
455457
};

packages/spacecat-shared-ticket-client/test/oauth-credential-manager.test.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,8 @@ describe('OAuthCredentialManager', () => {
330330
expect(httpClient.fetch.calledOnce).to.be.true;
331331
const written = JSON.parse(smClient.putSecretValue.firstCall.args[0].SecretString);
332332
expect(written.requiresReauth).to.be.false;
333+
expect(written.tokenRefreshedAt).to.be.a('string');
334+
expect(new Date(written.tokenRefreshedAt).getTime()).to.be.closeTo(Date.now(), 5000);
333335
});
334336

335337
it('sends client_id, client_secret, grant_type, and refresh_token in Atlassian request', async () => {

0 commit comments

Comments
 (0)