Target: directus/directus
Issue: directus/directus#24029
PR: directus/directus#27899
Field Lab: directus-directus-24029 case record
Field test status: bounded repair submitted; upstream review pending.
The reported failure
The issue involved Directus permission presets that referenced fields on the signed-in user through $CURRENT_USER.*.
A user could edit and save their own relationship field, such as builder_tenant_id, and the updated value would be stored in the database. However, permission presets using $CURRENT_USER.builder_tenant_id could continue operating with stale user context until the session was refreshed or the user logged in again. citeturn303935view0
The visible symptoms included:
- the relationship value not appearing correctly after save
- permission-controlled content creation failing
- the updated user field becoming effective only after another login
The issue was not simply that the user record failed to save.
The database value changed.
The application’s permission context did not change with it.
Why this is a boundary problem
Directus already refreshed the user store after the signed-in user saved their own record.
However, the permissions store was not refreshed afterward.
That created a split state:
- the user store contained the updated current-user data
- the permissions store continued evaluating presets against older current-user context
The diagnostic question was therefore not:
“How should relationship dropdowns be refreshed?”
It was:
“When the signed-in user changes fields used by $CURRENT_USER.* permission presets, which application state must be rehydrated before those changes become authoritative?”
That is the boundary.
The current-user record and the permissions derived from it are related, but they are not the same state surface.
Refreshing one without the other allowed Directus to hold two different versions of the signed-in user’s effective identity.
The repair lane
The repair refreshes the permissions store after the current user has been saved and the user store has been rehydrated.
The sequence becomes:
- save the signed-in user
- refresh the user store
- refresh the permissions store
- continue with permission presets evaluated against the updated current-user context
The patch is deliberately scoped to the current-user save path.
It does not change generic relationship dropdown behavior.
It does not redesign Directus permission presets.
It does not alter the broader authentication or session model.
It reconnects permission state to the current-user state from which those permissions are derived. citeturn327329view0turn303935view1
What changed
The implementation updates the Directus user-item save flow so that permissions are rehydrated after the signed-in user is saved and refreshed.
The public patch changes:
.changeset/fresh-users-remember.md
app/src/modules/users/routes/item.test.ts
app/src/modules/users/routes/item.vue
The regression test covers the current-user save path and verifies that the permissions store is refreshed after the user store is rehydrated.
A patch changeset was also added for @directus/app. citeturn327329view0
Why this was not a relationship-field repair
The original report presented through a relationship field, but the deeper failure was not owned by the relationship interface.
The field value was being saved.
The stale behavior occurred because permission presets continued using an outdated $CURRENT_USER context.
Changing dropdown rendering or generic relationship handling would have targeted the symptom rather than the state boundary.
The narrower repair was to refresh the state responsible for interpreting the updated value.
That is the difference between fixing what appeared stale and fixing what remained stale.
The Scarab reading
This was a current-user authority propagation failure.
The signed-in user changed a field that participated in permission evaluation.
Directus refreshed the user state but did not refresh the permission state derived from that user.
The application therefore carried two incompatible claims at once:
- the current user has the new field value
- permissions should still be evaluated using the old field value
The repair restores the dependency between those claims.
That is the Scarab boundary:
When authoritative current-user data changes, all permission state derived from that data must be rehydrated before the application treats the updated identity as active.
Why this boundary matters
$CURRENT_USER.* is not merely a display convenience.
It can participate in permission filters that determine which records a user may create, read, update, or delete.
That means stale current-user context can become a functional and security-sensitive state error.
The problem is not necessarily that Directus grants broader access.
Depending on the preset, stale context may deny valid access, apply the wrong tenant boundary, or continue evaluating rules against an identity state that is no longer true.
Permission systems depend on more than correct rules.
They depend on those rules being evaluated against current authority data.
Validation
Focused validation passed for:
- 36 targeted application tests
- lint checks on touched application files
- formatting checks on touched files
- style checks
- changeset validation
- the new current-user save regression
At the time the Field Lab record was created, the public upstream checks for lint, formatting, style, unit tests, changeset validation, and Codecov patch coverage were passing.
The Codecov project check was still failing while patch coverage passed, and contributor action was initially required. The contributor entry was subsequently added to the PR branch. citeturn327329view0turn303935view1
The pull request remains open and is awaiting the required upstream review. This report does not claim merge or completed CI. citeturn303935view1
Field result
Result: bounded Directus current-user permission-context repair candidate.
Issue shape:
- the signed-in user updated a relationship field
- the value was saved to the database
- the user store was refreshed
- the permissions store retained stale
$CURRENT_USER.*context - permission presets did not reflect the new value until a later session refresh
Repair:
- preserve the existing current-user save flow
- refresh the user store after save
- refresh the permissions store immediately afterward
- add focused regression coverage
- add an
@directus/apppatch changeset
This patch does not redesign Directus permissions or relationship fields.
It repairs the state boundary between an updated current-user record and the permissions derived from that record.
Public claim
Scarab/SDS helped drive a bounded repair candidate for directus/directus#24029.
The issue allowed permission presets using $CURRENT_USER.* fields to retain stale current-user context after the signed-in user saved their own record. Directus refreshed the user store, but the permissions store was not rehydrated afterward.
The upstream PR refreshes permissions after the current user has been saved and reloaded, ensuring that permission presets are re-evaluated against the updated user state.
The repair includes a focused regression test and passed targeted application tests, lint, formatting, style, and changeset validation.
The claim is limited to the current-user save and permission-rehydration boundary. It does not claim to redesign Directus permission presets or generic relationship-field behavior.
Disclosure: This field report was prepared with AI-assisted editing from my own field-test notes, the public issue and PR records, validation results, and the Scarab Field Lab case record. The technical claims and final wording were reviewed before publication.
Top comments (0)