Implement stale indicator for secrets
Related: #571232
What does this MR do and why?
This MR introduces a stale status indicator for project secrets using lifecycle timestamps (create_started_at, create_completed_at, update_started_at, update_completed_at). The system now derives a status field exposed via GraphQL to identify whether a secret is completed or stale.
Status logic
Status | Description |
---|---|
COMPLETED | Secret was recently created or updated, or no timestamps are present. |
UPDATE_STALE | Secret is potentially outdated, stuck, or has invalid/missing timestamps (e.g. update started long ago without completion). |
CREATE_STALE | Secret creation appears stale or invalid, possibly due to missing timestamps or a create operation that started long ago without completion. |
Purpose
-
Enables frontend/API consumers to detect stale secrets.
-
Lays the foundation for future features such as automatic cleanup or deletion of stale secrets.
Timestamp logic:
Timestamp Field | Purpose |
---|---|
create_started_at | Marks when secret creation began. |
create_completed_at | Marks when creation finished successfully. |
update_started_at | Marks when a rotation/update was initiated. |
update_completed_at | Marks when the update was confirmed complete. |
These timestamps allow the system to infer the health of a secret:
-
✅ Valid / Completed State-
Creation or update completed normally (start < finish, and finish is recent).
-
No timestamps present is treated as safe/default (completed).
-
-
⚠️ Stale / Invalid State-
An operation started but did not complete within a defined threshold.
-
Timestamps are reversed (completion before start → indicates failed or interrupted process).
-
Missing completion timestamp after significant time implies secret may be stuck or abandoned.
-
References
Screenshots or screen recordings
Before | After |
---|---|
![]() |
![]() |
How to set up and validate locally
How to set up and validate locally
- Start OpenBao in your GDK:
gdk openbao start
- Ensure your GDK is up to date and restart:
gdk update
gdk restart
- Enable the secrets management feature flag in Rails console:
Feature.enable(:secrets_management)
- Navigate to your test project in the browser:
http://127.0.0.1:3000/your-namespace/your-project
-
Enroll the project in secrets management via the UI:
- Go to Settings > CI/CD
- Expand the Secrets Management section
- Click Enable Secrets Management (or similar enrollment button)
- Complete the enrollment process
-
Navigate to the secrets management interface and create a new secret:
- Go to Settings > Secrets (or wherever secrets are managed in the UI)
- Click Create secret
- Fill in the form:
- Name:
TEST_SECRET
- Value:
test-value
- Description:
Test secret for status validation
- Environment:
production
- Branch:
main
- Name:
- Click Create secret
-
Verify via GraphQL API (optional):
query {
project(fullPath: "your-namespace/your-project") {
projectSecret(name: "TEST_SECRET") {
name
status
metadataVersion
}
}
}
- Run the test suite to ensure all tests pass:
bundle exec rspec ee/spec/models/secrets_management/project_secret_spec.rb
bundle exec rspec ee/spec/services/secrets_management/project_secrets/
bundle exec rspec ee/spec/requests/api/graphql/secrets_management/project_secrets/
Expected behavior
- Newly created secrets show
status: "COMPLETED"
andmetadataVersion: 2
- Updated secrets increment metadata version by 1 and maintain
status: "completed"
- Timestamps (
create_started_at
,create_completed_at
,update_started_at
,update_completed_at
) are tracked in the secret metadata - Status changes to
"UPDATE_STALE"
or"CREATE_STALE"
if operations take longer than 30 seconds without completion (edge case)
MR acceptance checklist
Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.