Skip to content

Add configurable API key expiration - #29

Merged
VibeSWE merged 3 commits into
mainfrom
feat/api-key-expiration
Oct 12, 2026
Merged

VibeSWE merged 3 commits into
mainfrom
feat/api-key-expiration

Conversation

@VibeSWE

@VibeSWE VibeSWE commented Oct 12, 2026 •

Copy link
Copy Markdown

Description

API keys currently remain valid until deleted. Add an optional lifetime of 30 minutes through 90 days, or no expiration. For example, a collector key created with ttlSeconds: 1800 stops authenticating 30 minutes after creation through both X-API-KEY and Bearer headers.

  • Persist a UTC expiresAt; omitted/null TTL preserves existing nonexpiring API behavior and legacy records.
  • Enforce the deadline in authentication and key validation. Cap temporary sessions at the key deadline and prevent API-key session refresh, while preserving Basic-auth precedence for mixed headers.
  • Default new UI-created keys to 90 days, with presets, custom minutes/hours/days, and an explicit No expiration option. Keep expired keys visible and deletable, and update their status automatically.
  • Warn when an older backend ignores a requested finite lifetime. Preserve current role-based permissions and admin authority.

Rollout: upgrade every serving and metadata-writing node before creating expiring keys. Older versions ignore expiration and can strip expiresAt when rewriting metadata; rollback with finite keys in service is unsafe. Requests authorized before expiry may finish afterwards.

Review automation

Add the swamp post-pr-review workflow and comment-clanker-post model/script. Actionable findings use resolvable line or file review threads; parsed ordinary PR conversation comments are rejected by default. Review summaries and existing-thread replies are allowed, with allowConversationComments=true available for intentional general discussion. The wrapper validates the report before posting and revokes its repository-scoped App token afterwards.

Running the automation requires an initialized swamp repository, Node.js, gh-comment with typed review support, and the comment-clanker vault containing the App client ID and private key. Credentials and unrelated local automation are excluded from this PR. No review comments were posted during validation.

Validation: five policy tests, four installed-parser integration cases, Node syntax checks, and swamp model/workflow validation passed.

Validation

  • Production frontend build and TypeScript pass; 2,200 unit tests pass across 89 files (one existing skipped test).
  • 50 Chromium browser tests pass: 11 expiration regressions and 39 existing Team tests, including mobile accessibility.
  • Final Rust build and 20 unique focused Rust tests pass.
  • 49 live HTTP/persistence assertions pass against the final build on a disposable single-node server. Covers TTL bounds, invalid inputs, both authentication headers, validation, retained expired records and restart compatibility. Expiry was simulated by editing only temporary persisted metadata while the server was stopped; no real 30-minute wait or cluster upgrade test was performed.
  • Formatting/diff checks pass. Three Opus 5.5 review rounds completed; final review approved with no actionable findings.

Details: frontend/docs/validation-review.md and frontend/docs/api-contracts.md. Implementation is also recorded in the project's shared Mayfly wiki under Team → API key expiration. Nothing deployed.

This PR has:

  • been tested to ensure log ingestion and log query works (focused authentication checks passed; full ingestion/query smoke was not repeated).
  • added comments explaining the "why" and intent where needed.
  • added documentation for new or modified features and behaviors.

View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.

@comment-clanker comment-clanker Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Independent reviews by GPT-6.1-Sol (backend; frontend + automation) and Claude Opus 5.5 of commit 8acc2f6d9dde8e350d52beb34416c60c27786079, verified in a second Sol pass.

The core expiry enforcement looks correct. The API-key header lookup (find_api_key_user) and /apikeys/validate both call matches_active_key. Sessions created directly from API-key headers are capped at the key's deadline and excluded from refresh (the one exception is the first thread below). The ttlSeconds bounds are enforced at deserialization. expiresAt is serialized into persisted users and into cluster-sync payloads. No issues found in the frontend duration validation, the warning for backends that ignore the TTL, or the timer (capped at 2³¹−1 ms).

The reviewers reported passing runs of cargo check --locked --offline, 20 focused Rust tests, 147 frontend unit tests, 5 policy tests and the 11 expiration browser tests (these mock the server). No live cluster test was run.

Comment thread src/handlers/http/middleware.rs
Comment thread src/handlers/http/middleware.rs Outdated
Comment thread scripts/comment-clanker-post.mjs
Comment thread scripts/comment-clanker-post.mjs
Comment thread scripts/comment-clanker-post.mjs
Comment thread frontend/src/features/team/CredentialSheet.tsx Outdated
Intra-cluster requests created a 20-second session for any stored user,
so work forwarded on behalf of an expired API key was still authorized.
Reject expired API-key users there, and cap every session created through
`Users.new_session` at the key's deadline.

Exercise the real `Auth` and `IntraClusterRequest` middleware in tests:
both API key headers before and after expiry, a key expiring after its
session is registered, and forwarded Basic credentials alongside an
expired key. Each removed guard makes a test fail.

Derive the custom duration input's native min/max from the selected unit
so the range matches validation (30 minutes to 90 days).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@VibeSWE
VibeSWE merged commit 78676fb into main Oct 12, 2026
6 of 8 checks passed
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