mirror of
https://github.com/BetterSEQTA/BetterSEQTA-Plus.git
synced 2026-06-15 16:14:13 +00:00
add aden's requested changes
This commit is contained in:
@@ -47,11 +47,11 @@ Cloud settings sync is a **whole-snapshot backup** of extension local storage:
|
||||
│ │ menuitems… │ │ │ │ │ │
|
||||
│ └─────────────┘ └──────────────┘ └────────────────────────┘ │
|
||||
└────────────────────────────┬────────────────────────────────────┘
|
||||
│ buildUploadPayload()
|
||||
│ • filter exclusions
|
||||
│ • migrateLegacyToPluginSettings()
|
||||
│ buildUploadPatch()
|
||||
│ • ensureSyncableStorageDefaults (local)
|
||||
│ • normalize + diff vs last upload / defaults
|
||||
▼
|
||||
PUT /api/bsplus/settings/sync
|
||||
PUT /api/bsplus/settings/sync (sparse data patch)
|
||||
{ schemaVersion, themeId, data: { … } }
|
||||
│
|
||||
▼
|
||||
@@ -108,9 +108,9 @@ Download is skipped when server `schemaVersion` > client `CLOUD_SETTINGS_SYNC_SC
|
||||
|
||||
After download, if `themeId` / `selectedTheme` is non-empty, the service worker sets `bsplus_pending_theme_ensure_after_cloud` so the page `ThemeManager` can download missing theme assets from the store.
|
||||
|
||||
### Full schema before upload
|
||||
### Local schema before diff (upload)
|
||||
|
||||
`ensureSyncableStorageDefaults()` (`src/seqta/utils/ensureSyncableStorageDefaults.ts`) ensures every **cloud-syncable** key exists in `chrome.storage.local` with its default value if it was previously absent. This makes uploads and dev JSON exports contain a complete schema (e.g. `customshortcuts: []`, `shortcuts: [...]`, every `plugin.{id}.settings` object) instead of omitting keys the user never touched.
|
||||
`ensureSyncableStorageDefaults()` (`src/seqta/utils/ensureSyncableStorageDefaults.ts`) ensures every **cloud-syncable** key exists in `chrome.storage.local` with its default value if it was previously absent. This runs **locally only** so diffs against the last-uploaded snapshot (or schema defaults) are consistent. The PUT body is a **sparse patch** of changed keys only — defaults are not bulk-uploaded.
|
||||
|
||||
| When it runs | Context |
|
||||
|--------------|---------|
|
||||
@@ -118,6 +118,7 @@ After download, if `themeId` / `selectedTheme` is non-empty, the service worker
|
||||
| `browser.runtime.onStartup` | Service worker |
|
||||
| Service worker load | `background.ts` (once at startup) |
|
||||
| `initializeSettingsState()` | SEQTA content script + extension settings page (first init) |
|
||||
| Before each cloud upload | `putSettingsOnce()` in `cloudSettingsAutoSync.ts` |
|
||||
|
||||
Rules:
|
||||
|
||||
@@ -146,22 +147,14 @@ Content-Type: application/json
|
||||
"schemaVersion": 1,
|
||||
"themeId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
|
||||
"data": {
|
||||
"onoff": true,
|
||||
"DarkMode": true,
|
||||
"selectedTheme": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
|
||||
"selectedColor": "linear-gradient(40deg, rgba(201,61,0,1) 0%, RGBA(170, 5, 58, 1) 100%)",
|
||||
"plugin.global-search.settings": {
|
||||
"enabled": true,
|
||||
"searchHotkey": "ctrl+k",
|
||||
"showRecentFirst": true,
|
||||
"transparencyEffects": true,
|
||||
"runIndexingOnLoad": true,
|
||||
"passiveIndexing": true
|
||||
}
|
||||
"selectedTheme": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Only keys that changed since the last successful upload appear in `data`. The server merges this patch into stored JSON; omitted keys are not deleted. Dev JSON export (`getSnapshotForUpload`) still returns the full normalized map for debugging.
|
||||
|
||||
| Top-level field | JSON type | Rules |
|
||||
|-----------------|-----------|-------|
|
||||
| `schemaVersion` | `number` | Always `1` today (`CLOUD_SETTINGS_SYNC_SCHEMA_VERSION`) |
|
||||
@@ -238,6 +231,7 @@ Implemented in `shouldOmitKeyFromCloudPayload(key)`:
|
||||
| `plugin.assessments-average.storage.assessments` | object | Keep device value |
|
||||
| `plugin.assessments-average.storage.weightings` | object | Keep device value |
|
||||
| `bsplus_cloud_settings_known_remote_updated_at` | ISO `string` | Keep device value |
|
||||
| `bsplus_cloud_settings_last_uploaded_snapshot` | `object` (normalized syncable map) | Keep device value |
|
||||
| `bsplus_lastCloudPoll` | `number` (ms) | Keep device value |
|
||||
| `bsplus_pending_theme_ensure_after_cloud` | `string` (theme id) | Keep device value |
|
||||
|
||||
@@ -1061,7 +1055,7 @@ Any new `chrome.storage.local` key syncs automatically unless added to:
|
||||
2. At least one changed key passes `isKeyIncludedInCloudUploadPayload`
|
||||
3. `autoCloudSettingsSync !== false`
|
||||
4. Valid access token
|
||||
5. Not during restore → schedule 2 s debounce → `PUT` full snapshot
|
||||
5. Not during restore → schedule 2 s debounce → `PUT` sparse patch (skip if empty)
|
||||
|
||||
### Server storage suggestion
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ Use the same **access tokens** issued by the existing BetterSEQTA+ OAuth flows (
|
||||
|
||||
### `PUT /api/bsplus/settings/sync`
|
||||
|
||||
Upserts the caller’s settings backup.
|
||||
Upserts the caller’s settings backup. The server **merges** `data` into the stored JSON document; keys omitted from the patch are **not** deleted.
|
||||
|
||||
**Request body (JSON):**
|
||||
|
||||
@@ -37,12 +37,14 @@ Upserts the caller’s settings backup.
|
||||
"schemaVersion": 1,
|
||||
"themeId": "uuid-string-or-empty",
|
||||
"data": {
|
||||
"...": "flat key-value map mirroring extension storage (see Payload shape)",
|
||||
"DarkMode": true,
|
||||
"selectedTheme": "uuid-or-empty-string"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The extension sends a **sparse patch**: only keys that changed since the last successful upload (or, on first upload, keys that differ from schema defaults). A full snapshot is not required.
|
||||
|
||||
- **`schemaVersion`**: integer. The extension currently sends `1`. The server may reject unknown major versions or store it for future migrations.
|
||||
- **`themeId`**: optional but recommended duplicate of **`data.selectedTheme`**. Should be the UUID of the **installed** BetterSEQTA store theme (`selectedTheme`). This may be a normal theme id **or** a **flavour (slave) variant** id from themes with **`flavours[]`** — the extension uses it after restore to prefetch `theme.json` when missing locally (same **`GET …/themes/{id}/download`** as the store UI). Persist and return **`themeId`** in sync with **`data.selectedTheme`**.
|
||||
- **`data`**: object whose keys are storage keys (strings) and values are JSON-serializable values (same types as stored in `chrome.storage.local`).
|
||||
@@ -51,11 +53,12 @@ Upserts the caller’s settings backup.
|
||||
|
||||
```json
|
||||
{
|
||||
"updated_at": "2026-04-07T12:00:00.000Z"
|
||||
"updated_at": "2026-04-07T12:00:00.000Z",
|
||||
"patch": { "DarkMode": true }
|
||||
}
|
||||
```
|
||||
|
||||
`updated_at` should be an ISO 8601 timestamp of the save time. The extension displays success without requiring extra fields.
|
||||
`updated_at` should be an ISO 8601 timestamp of the save time. The extension displays success without requiring extra fields. Optional `patch` may echo the merged keys applied server-side.
|
||||
|
||||
**Error responses:** Standard JSON error body if applicable, e.g. `{ "error": "message" }`, with appropriate HTTP status (`401`, `413`, `422`, etc.).
|
||||
|
||||
@@ -103,7 +106,8 @@ Unique constraint on `user_id`.
|
||||
|
||||
## Semantics
|
||||
|
||||
- **Last write wins:** each `PUT` replaces the stored backup for that user.
|
||||
- **Merge on PUT:** each `PUT` deep-merges `data` into the stored backup for that user. Keys not present in the request body remain unchanged on the server.
|
||||
- **Full document on GET:** restore and poll download still receive the complete hydrated settings object.
|
||||
- **Optional later:** `If-Unmodified-Since` or a `revision` field for conflict detection (not required for v1).
|
||||
|
||||
## Security and privacy
|
||||
@@ -121,6 +125,7 @@ The backup is a flat JSON map of **`chrome.storage.local`** keys. It does **not*
|
||||
- **Assessment Averages caches** — `plugin.assessments-average.storage.assessments`, `plugin.assessments-average.storage.weightings` (school assessment data).
|
||||
- **Keys under** `plugin.global-search.storage.*` — reserved so any future plugin storage cache there is not synced.
|
||||
- **Grade Analytics** — keys under `bsplus.analytics.*` (synced assessment cache and per-school chart preferences).
|
||||
- **`bsplus_cloud_settings_last_uploaded_snapshot`** — client-only normalized map last acked by PUT; used to compute sparse upload patches (not part of the cloud backup blob).
|
||||
- **`bsplus_cloud_settings_known_remote_updated_at`** — client-only watermark for auto-sync (not part of the cloud backup blob).
|
||||
|
||||
On restore, those keys are **not** taken from the server; the device keeps its current local values.
|
||||
@@ -136,6 +141,6 @@ This uses standard **WebExtension** APIs (`browser.alarms`, `runtime` messages,
|
||||
|
||||
## Client reference (extension)
|
||||
|
||||
- Upload / dev export: `buildUploadPayload` / `getSnapshotForUpload` in `src/seqta/utils/cloudSettingsSync.ts` (strips OAuth-related keys, sensitive device keys, **`bsplus_pending_theme_ensure_after_cloud`**, and **`bsplus_cloud_settings_known_remote_updated_at`** — includes **`themeId`** aligned with **`selectedTheme`**).
|
||||
- Upload (sparse patch): `buildUploadPatch` / `putSettingsOnce` in `src/background/cloudSettingsAutoSync.ts`; baseline from `bsplus_cloud_settings_last_uploaded_snapshot` or schema defaults; dev full export via `getSnapshotForUpload` / `buildUploadPayload` in `src/seqta/utils/cloudSettingsSync.ts` (strips OAuth-related keys, sensitive device keys, client-only metadata — includes **`themeId`** aligned with **`selectedTheme`**).
|
||||
- Download: resolve id via **`resolveThemeIdForPostSyncDownload`** → **`applyDownloadedEnvelope`** after `GET` → prefetch theme blobs in page context if needed (**`prepareThemeAfterCloudSync`** in **`ThemeManager`**) → reload SEQTA tabs; local auth keys, sensitive device keys, client-only watermark, and **`bsplus_pending_theme_ensure_after_cloud`** semantics preserved as documented above.
|
||||
- Auto sync (summary, debounced upload, alarms): `src/background/cloudSettingsAutoSync.ts`; content script triggers a poll on each verified SEQTA Learn/Engage page load (top frame) via `cloudSettingsPoll`.
|
||||
|
||||
Reference in New Issue
Block a user