The direct answer
A changed session key does not make retained anonymous data trustworthy. Follow the framework’s documented login transition, retain only explicitly allowed harmless preferences, and rebuild user, workspace and action authority from authenticated application records. Treat logout, other sessions and in-flight work according to their separate evidence.
A successful login can preserve the wrong kind of state
A fictional AI console allows an anonymous visitor to choose a display language and prepare a proposed export. After the visitor signs in, the interface shows the preferred language and the old proposal. Preserving the first can be useful; inheriting authority to execute the second would be a different decision.
This original worksheet selects the standard server-side database session backend and built-in authentication functions documented in Django 6.0. Both source pages display documentation version 6.0; no patch release, installed framework, middleware or backend configuration was inspected. The positive path begins anonymous and signs in as the intended authenticated user U-A. It does not cover switching directly between two authenticated users.
Read the key and data operations separately
The Django sessions documentation says cycle_key creates a new session key while retaining current data, and login calls it to mitigate session fixation. It describes flush as deleting current session data and the session cookie. These are different operations.
The authentication documentation explicitly says anonymous-session data is retained after login. Its logout description says all session data for the current request is removed. Those statements support the selected ordinary transition; they do not establish every internal login branch, a cross-device revocation mechanism or concurrent-request safety.
Do not replace normal framework login with a custom cookie change or assume that another manual cycle_key call cleans application values. A server-side store can hold data derived from untrusted requests. Storage location and a new key do not change that data’s origin or grant an approval.
Divide pre-login state by purpose
Invent anonymous context S-ANON with language preference L-A and proposal reference P-A. These are inert labels, not session identifiers, cookie contents, real proposals or user records. U-A later has current membership in workspace W-A, established through trusted authenticated application state.
| Application-owned data | Proposed treatment at login |
|---|---|
| Display-language preference L-A | Validate against the small permitted language set; retain only for presentation |
| Anonymous proposal reference P-A | Discard from the executable workflow; do not promote it to an approved action |
| Workspace or user hint | Treat as an untrusted selection request; resolve identity and membership anew |
| Claimed approval, spending credit or privileged role | Never migrate as authority; consult the responsible trusted records |
| Unrecognized application key or nested metadata | Exclude under the explicit allowlist rather than copy wholesale |
Keeping L-A must not select a model provider, widen a budget or change document access. If a supposedly cosmetic setting changes an important workflow consequence, remove it from this harmless-preference category and review that consequence separately.
Define the permitted ordinary transition
For this proposed design, capture and validate only the allowed application preference while the request is still anonymous. Remove the application’s pre-login workflow values before they can be consumed as authenticated work. Continue through the configured normal authentication path and built-in login for successfully authenticated U-A, preserving framework-owned session handling.
After that transition, keep only validated L-A in the application preference slot, resolve W-A from current membership and create a new action A-A under current authorization and required review. P-A may be discarded as an execution reference without pretending that its separate stored draft or previously delivered copies were deleted. If retaining draft content is later wanted, specify an independently reviewed ownership-transfer workflow.
This allowlist and cleanup sequence is application policy, not automatic Django behavior. Apply it only to application-owned values. Django reserves underscore-prefixed session keys for internal use; do not sweep away authentication internals, override request.session or bypass framework security controls to implement the example.
Persistence also needs evidence. The sessions page documents that nested-object mutation alone does not mark a session modified and that a response with status 500 does not save the session. A future implementation must demonstrate its supported assignment/deletion and successful persistence path before reporting migration complete. No database transaction, save operation or race was exercised here.
Review eight inert transition cards
| Inert condition | Proposed decision |
|---|---|
| Ordinary intended login, allowed L-A and current U-A/W-A rights | Retain presentation preference; permit only newly authorized and reviewed A-A |
| Key changed but anonymous P-A remains in application data | Do not execute P-A; rotation did not grant approval |
| Inherited value claims U-B, W-B or approval granted | Reject authority migration; derive current identity, membership and review separately |
| An authenticated earlier-user context is present | Hold outside this anonymous-entry profile; require a separately supported transition, not a guessed login branch |
| Logout occurs, then an old initiation or action reference is presented | Enforce the reference’s original binding; never attach it to the next signed-in user |
| Only this browser session’s operation is evidenced | Report that scope; other devices, sessions and connector grants remain unverified |
| Old request, overlapping write or save outcome is unresolved | Hold the affected workflow outcome; no race or effect-recall claim |
| Login succeeds but W-A action permission is absent | Deny A-A independently of authentication success |
Keep logout and current action authority precise
For the chosen documented logout path, current-request session data is cleaned out. If the application intentionally starts a new anonymous preference afterward, make that a fresh narrow decision rather than restoring a prior user’s workflow bundle. Do not copy stale approval or OAuth-initiation references into the new context.
This guide makes no authentication-hash, password-change, other-user-switch, global logout or cross-device invalidation claim. An earlier request can already be in flight, and an external effect may already have been admitted. Key rotation and session cleanup cannot establish that those effects were undone. Unsupported backend and concurrent-write behavior stays unknown.
The separate browser action-admission contract and exact current object/approval checks still apply after login. A retained preference, an authenticated flag or an old workspace selection cannot replace them.
All cases remain unrun: no Django import, login, logout, session, cookie, database, configuration, browser, account, API/model or runtime fixture operation occurred. Boundary is prelaunch and does not claim a shipped session manager. Its synthetic policy, export and approval-status checks establish different behavior.
Primary sources
Official references supporting the guidance. Examples in this guide are synthetic and are not reports of a production incident.