feat(kanban): partition local queues by account

req: sync/020

req: auth/005

req: security/004

req: operations/002
This commit is contained in:
slhx agent
2026-07-13 19:00:04 +02:00
parent 6de4dcb73b
commit 3ef84e7331
7 changed files with 239 additions and 95 deletions
+13 -8
View File
@@ -288,7 +288,7 @@ async fn kanban_command_persists_before_projection_and_restores_after_reload() -
.await?;
wait_until(
&driver,
"return !window.__reloadPending && document.querySelector('[data-hemx-root]').hasAttribute('data-kanban-command-ready')",
"return !window.__reloadPending && document.querySelector('[data-hemx-root]')?.hasAttribute('data-kanban-command-ready') === true",
)
.await?;
let restored = driver
@@ -312,7 +312,7 @@ async fn kanban_command_persists_before_projection_and_restores_after_reload() -
request.onsuccess = () => {
const tx = request.result.transaction('commands', 'readwrite');
tx.objectStore('commands').add({
id: 'future:2', schemaVersion: 3, actor: 'future', session: 'future',
id: 'future:2', schemaVersion: 3, accountPartition: 'demo:demo', actor: 'future', session: 'future',
causal: 2, kind: 'reorder_card', cardId: '2', targetColumn: 'done', eventKind: 'click', key: null,
});
tx.oncomplete = () => { window.__futureCommandStored = true; };
@@ -328,7 +328,7 @@ async fn kanban_command_persists_before_projection_and_restores_after_reload() -
.await?;
wait_until(
&driver,
"return !window.__reloadPending && document.querySelector('[data-hemx-root]').hasAttribute('data-kanban-command-error')",
"return !window.__reloadPending && document.querySelector('[data-hemx-root]')?.hasAttribute('data-kanban-command-error') === true",
)
.await?;
let rejected = driver
@@ -1476,12 +1476,17 @@ fn serve(
fs::read(&app_assets.expect("checked app assets").service_worker)
.expect("read service worker"),
),
"/sync/context" if app_assets.is_some() => (
"application/json; charset=utf-8",
br#"{"accountPartition":"demo:demo"}"#.to_vec(),
),
_ => ("text/plain", b"not found".to_vec()),
};
let status = if path == "/"
|| path == "/hemx.js"
|| path == "/hemx.client.js"
|| ((path == "/app.js" || path == "/offline.js") && app_assets.is_some())
|| ((path == "/app.js" || path == "/offline.js" || path == "/sync/context")
&& app_assets.is_some())
|| path.starts_with(&format!("/{asset_stem}"))
{
"200 OK"
@@ -1511,7 +1516,7 @@ async fn hold_command_transaction(driver: &WebDriver) -> WebDriverResult<()> {
r#"
window.__releaseCommandTransaction = false;
window.__commandTransactionHeld = false;
const open = indexedDB.open('hemx-kanban-v1', 1);
const open = indexedDB.open('hemx-kanban-v1');
open.onsuccess = () => {
const tx = open.result.transaction('commands', 'readwrite');
const commands = tx.objectStore('commands');
@@ -1571,7 +1576,7 @@ async fn store_replay_commands(driver: &WebDriver, first: u64, last: u64) -> Web
const first = arguments[0];
const last = arguments[1];
const done = arguments[arguments.length - 1];
const open = indexedDB.open('hemx-kanban-v1', 1);
const open = indexedDB.open('hemx-kanban-v1');
open.onerror = () => done({ error: open.error && open.error.name });
open.onsuccess = () => {
const tx = open.result.transaction('commands', 'readwrite');
@@ -1611,7 +1616,7 @@ async fn store_malformed_command(driver: &WebDriver) -> WebDriverResult<()> {
.execute_async(
r#"
const done = arguments[arguments.length - 1];
const open = indexedDB.open('hemx-kanban-v1', 1);
const open = indexedDB.open('hemx-kanban-v1');
open.onerror = () => done({ error: open.error && open.error.name });
open.onsuccess = () => {
const tx = open.result.transaction('commands', 'readwrite');
@@ -1647,7 +1652,7 @@ async fn occupy_next_command_id(driver: &WebDriver) -> WebDriverResult<()> {
.execute_async(
r#"
const done = arguments[arguments.length - 1];
const open = indexedDB.open('hemx-kanban-v1', 1);
const open = indexedDB.open('hemx-kanban-v1');
open.onerror = () => done({ error: open.error && open.error.name });
open.onsuccess = () => {
const tx = open.result.transaction(['commands', 'meta'], 'readwrite');