fix(offline): address PR #120 review (cross-user leak, Yjs title dup, i18n, docs, guards)
Security: - Clear the offline IndexedDB cache on sign-in (not only logout) so a previous user's persisted query cache and Yjs page bodies cannot leak to the next user on a shared device when the prior session ended without an explicit logout. Regressions: - Remove the double Yjs title write from the AI title-generation path: the title editor is bound to the Yjs `title` fragment and the server REST update reseeds it, so the local setContent raced that reseed and doubled/garbled the title. Conventions / i18n / docs: - Remove the unused showAiMenuAtom. - Register the 3 offline-fallback strings in en-US and ru-RU. - Fix the 5 broken links to the nonexistent docs/offline-sync-plan.md. Stability / simplification: - warmInfiniteAll now reports truncation (returns false) when it hits maxPages with a cursor still pending instead of silently succeeding. - space-tree make-offline catch logs the raw error and surfaces the real cause. - Move the Offline/Mobile/CORS CHANGELOG entries from the released 0.93.0 section into [Unreleased] (CORS is a documented breaking change). - Drop the pass-through sync-flag forwarders in use-page-collab-providers; set the atoms directly. - Collapse the three isSwaggerEnabled true-cases into it.each. Tests / architecture: - Extract collabTokenNeedsRefresh (pure) and cover all four token states. - Extract shouldPropagateTitleChange and cover the collab-origin skip; add a TitleEditor render test for the static-h1 vs collaborative-editor switch. - Add a use-auth test asserting the sign-in cache purge runs before login. - Add an OFFLINE_PERSIST_ROOTS guard test asserting every persisted root maps to an exported query-key factory; route make-offline's currentUser warm through a new userKeys factory. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -60,22 +60,11 @@ describe('EnvironmentService', () => {
|
||||
});
|
||||
|
||||
describe('isSwaggerEnabled', () => {
|
||||
it('is true for "true"', () => {
|
||||
expect(makeService({ SWAGGER_ENABLED: 'true' }).isSwaggerEnabled()).toBe(
|
||||
true,
|
||||
);
|
||||
});
|
||||
|
||||
it('is true case-insensitively for "TRUE"', () => {
|
||||
expect(makeService({ SWAGGER_ENABLED: 'TRUE' }).isSwaggerEnabled()).toBe(
|
||||
true,
|
||||
);
|
||||
});
|
||||
|
||||
it('is true for mixed-case "True"', () => {
|
||||
expect(makeService({ SWAGGER_ENABLED: 'True' }).isSwaggerEnabled()).toBe(
|
||||
true,
|
||||
);
|
||||
// Case-insensitive: "true" in any casing enables Swagger.
|
||||
it.each(['true', 'TRUE', 'True'])('is true for "%s"', (value) => {
|
||||
expect(
|
||||
makeService({ SWAGGER_ENABLED: value }).isSwaggerEnabled(),
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it('defaults to false when absent', () => {
|
||||
|
||||
Reference in New Issue
Block a user