Skip to content

feat(session): let a session share expire - #2987

Open
QuentinBisson wants to merge 3 commits into
kagent-dev:mainfrom
QuentinBisson:upstream/session-share-expiry
Open

QuentinBisson wants to merge 3 commits into
kagent-dev:mainfrom
QuentinBisson:upstream/session-share-expiry

Conversation

@QuentinBisson

@QuentinBisson QuentinBisson commented Sep 28, 2026 •

Copy link
Copy Markdown
Contributor

Problem

A session share's token grants access until the share is revoked or the session is deleted: CreateSessionShareRequest takes no lifetime, and GetSessionShareByTokenHash checks nothing but the hash and the session's state. A client that keeps one share per conversation, for the people the owner lets in, has no way to bound it once the conversation is abandoned. A READ_WRITE share can also rename, suspend and delete the session.

Change

  • CreateSessionShareRequest.ttl is optional and must be positive when set. The share records expires_at in a nullable session_share.expires_at column, added to the unreleased 000001 baseline.
  • Token resolution treats an expired share like an unknown token, so both A2A transports refuse it. ListSessionShares still returns an expired share, so the owner can revoke it.
  • KAGENT_SESSION_SHARE_MAX_TTL (controller.sessionShareMaxTTL) lets admins cap share lifetime. A longer ttl is refused with InvalidArgument, and a share created without ttl receives the maximum. The default 0 keeps shares unbounded, so a share created without ttl behaves as before.

The migration immutability check fails because the column is folded into 000001, as its header asks until release (same as #2970).

@github-actions github-actions Bot added the enhancement New feature or request label Sep 28, 2026
QuentinBisson added a commit to giantswarm/kagent-upstream that referenced this pull request Sep 28, 2026
Signed-off-by: QuentinBisson <quentin@giantswarm.io>
@QuentinBisson
QuentinBisson marked this pull request as ready for review September 29, 2026 09:22

@EItanya EItanya left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This feature is looking great! Do you think you can add a ceiling value to the server so that admins can set a maximum valid time

@QuentinBisson

Copy link
Copy Markdown
Contributor Author

I definitely can, thanks for the review :)

CreateSessionShareRequest takes an optional ttl. The share records
expires_at, and token resolution treats an expired share like an unknown
token. The owner still lists an expired share so it can be revoked.

Signed-off-by: QuentinBisson <quentin@giantswarm.io>
KAGENT_SESSION_SHARE_MAX_TTL (controller.sessionShareMaxTTL) sets the
longest ttl a share may request. A longer ttl is refused, and a share
created without one receives the maximum. Zero, the default, leaves
shares unbounded; a negative value fails controller startup.

Signed-off-by: QuentinBisson <quentin@giantswarm.io>
@QuentinBisson
QuentinBisson force-pushed the upstream/session-share-expiry branch from 59b1965 to fd8bcda Compare September 29, 2026 15:09
@github-actions github-actions Bot added enhancement New feature or request and removed enhancement New feature or request labels Sep 29, 2026
@QuentinBisson

Copy link
Copy Markdown
Contributor Author

I pushed the new maximum valid time :)

QuentinBisson added a commit to giantswarm/kagent-upstream that referenced this pull request Sep 29, 2026
Signed-off-by: QuentinBisson <quentin@giantswarm.io>
Comment thread go/core/internal/database/shares.go Outdated
Comment on lines +145 to +150
func sameExpiry(payload *timestamppb.Timestamp, column *time.Time) bool {
if payload == nil || column == nil {
return payload == nil && column == nil
}
return payload.AsTime().Equal(*column)
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we really need this? How could these get out of sync, we have many times we do something similar and we don't have this check

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right, this field is only set when we create a share and cannot be updated unless someone does it in the database. I'll simplify this

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The expiry is only stored in the column now, so sameExpiry and the truncation are gone.

Signed-off-by: QuentinBisson <quentin@giantswarm.io>
@github-actions github-actions Bot added enhancement New feature or request and removed enhancement New feature or request labels Sep 29, 2026
not_in: 0
}];
// How long the share's token grants access, from its creation. Unset means
// until the share is revoked or the session deleted.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unset gets the server max when one is configured

if ttl < 0 {
return nil, "", serviceerrors.NewInvalidArgument("share ttl must be positive", nil)
}
if s.shareMaxTTL > 0 {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

enabling the cap later leaves older no-ttl shares unbounded

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's ok, we're pre-alpha

@EItanya
EItanya enabled auto-merge September 29, 2026 21:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants