docs: mark browser inbox domain binding complete
This commit is contained in:
parent
eac67d9417
commit
2564f6ca9d
|
|
@ -249,8 +249,10 @@ search.provider
|
||||||
sidebar view and a workspace item. Workspace tabs keep their own pending queue;
|
sidebar view and a workspace item. Workspace tabs keep their own pending queue;
|
||||||
the global sidebar view aggregates queues from all workspaces plus unscoped
|
the global sidebar view aggregates queues from all workspaces plus unscoped
|
||||||
global captures. The local receiver now has an opt-in paired mode that requires
|
global captures. The local receiver now has an opt-in paired mode that requires
|
||||||
`X-Verstak-Receiver-Token` before publishing browser capture events. Domain
|
`X-Verstak-Receiver-Token` before publishing browser capture events. Browser
|
||||||
binding and conversion into notes/links/files/activity are still future work.
|
Inbox stores plugin-owned `domainBindings` and routes unscoped captures with an
|
||||||
|
exact domain match into the bound workspace queue. Conversion into
|
||||||
|
notes/links/files/activity is still future work.
|
||||||
|
|
||||||
## 9. `official.search`
|
## 9. `official.search`
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -55,8 +55,9 @@ Known remaining gaps:
|
||||||
- File/image preview exists as a basic provider with bounded inline image
|
- File/image preview exists as a basic provider with bounded inline image
|
||||||
rendering through the public Files API.
|
rendering through the public Files API.
|
||||||
- Browser extension repository has protocol, queue, and Chromium/Firefox build
|
- Browser extension repository has protocol, queue, and Chromium/Firefox build
|
||||||
scaffold; desktop has a local receiver and mounted-view inbox plugin, but no
|
scaffold; desktop has a local receiver and mounted-view inbox plugin; receiver
|
||||||
pairing model, domain binding, or conversion workflow yet.
|
pairing and basic Browser Inbox domain binding are implemented, but no
|
||||||
|
conversion workflow yet.
|
||||||
- Packaging/update/release workflow is not product-grade yet.
|
- Packaging/update/release workflow is not product-grade yet.
|
||||||
|
|
||||||
## 4. Implementation Phases
|
## 4. Implementation Phases
|
||||||
|
|
@ -163,7 +164,7 @@ Tasks:
|
||||||
- [x] implement browser extension capture scaffold for URL, selected text,
|
- [x] implement browser extension capture scaffold for URL, selected text,
|
||||||
page title, and link captures;
|
page title, and link captures;
|
||||||
- [x] define local receiver permission/pairing model;
|
- [x] define local receiver permission/pairing model;
|
||||||
- add domain-to-workspace binding;
|
- [x] add domain-to-workspace binding;
|
||||||
- convert inbox entries into notes/links/files/activity events through public
|
- convert inbox entries into notes/links/files/activity events through public
|
||||||
plugin APIs.
|
plugin APIs.
|
||||||
|
|
||||||
|
|
@ -235,8 +236,7 @@ Verification:
|
||||||
4. [x] Notes trash/delete UX in `verstak-official-plugins`.
|
4. [x] Notes trash/delete UX in `verstak-official-plugins`.
|
||||||
5. [x] Sync hardening pass with expanded real two-vault smoke.
|
5. [x] Sync hardening pass with expanded real two-vault smoke.
|
||||||
6. [~] Browser inbox protocol design, extension scaffold, local receiver, and
|
6. [~] Browser inbox protocol design, extension scaffold, local receiver, and
|
||||||
minimal inbox plugin are implemented; pairing, domain binding, and conversion
|
minimal inbox plugin are implemented; conversion workflows remain.
|
||||||
workflows remain.
|
|
||||||
|
|
||||||
This order finishes generic platform surfaces before building product features
|
This order finishes generic platform surfaces before building product features
|
||||||
that depend on them.
|
that depend on them.
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,119 @@
|
||||||
|
# Browser Inbox Domain Binding Implementation Plan
|
||||||
|
|
||||||
|
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||||||
|
|
||||||
|
**Goal:** Route unscoped Browser Inbox captures into workspace queues through plugin-owned domain bindings.
|
||||||
|
|
||||||
|
**Architecture:** Keep domain binding in `verstak.browser-inbox`. The plugin reads `domainBindings` from its own settings namespace, annotates unscoped incoming captures before storage, and preserves desktop core as a capture-event publisher only.
|
||||||
|
|
||||||
|
**Tech Stack:** Plain JavaScript official plugin bundle, Node smoke test harness, Markdown docs.
|
||||||
|
|
||||||
|
## Global Constraints
|
||||||
|
|
||||||
|
- Do not move Browser Inbox queues or conversion workflows into desktop core.
|
||||||
|
- Do not import Notes, Files, Activity, or Journal from Browser Inbox.
|
||||||
|
- Route only captures that do not already include `workspaceRootPath`.
|
||||||
|
- Domain matching is exact and case-insensitive for this slice.
|
||||||
|
- Use TDD: write the failing smoke test first, run it red, then implement.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Task 1: Browser Inbox Domain Routing
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Modify: `/home/mirivlad/git/verstak2/verstak-official-plugins/scripts/smoke-browser-inbox-plugin.js`
|
||||||
|
- Modify: `/home/mirivlad/git/verstak2/verstak-official-plugins/plugins/browser-inbox/frontend/src/index.js`
|
||||||
|
|
||||||
|
**Interfaces:**
|
||||||
|
- Consumes: Browser Inbox plugin settings key `domainBindings`.
|
||||||
|
- Produces: unscoped captures annotated with `workspaceRootPath` and `workspaceName` when an exact domain binding exists.
|
||||||
|
|
||||||
|
- [ ] **Step 1: Write the failing smoke test**
|
||||||
|
|
||||||
|
Add a scenario to `scripts/smoke-browser-inbox-plugin.js`:
|
||||||
|
|
||||||
|
```js
|
||||||
|
const bindingApi = makeApi({
|
||||||
|
domainBindings: {
|
||||||
|
'client.example.com': 'ClientA',
|
||||||
|
'project.example.com': 'Project'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const bindingGlobal = await mountWithApi(bindingApi, {});
|
||||||
|
await bindingApi.handlers['browser.capture.page']({
|
||||||
|
name: 'browser.capture.page',
|
||||||
|
timestamp: '2026-06-29T00:00:00Z',
|
||||||
|
payload: {
|
||||||
|
captureId: 'bound-client-capture',
|
||||||
|
capturedAt: '2026-06-29T00:00:00.000Z',
|
||||||
|
kind: 'page',
|
||||||
|
url: 'https://client.example.com/page',
|
||||||
|
title: 'Bound Client Page',
|
||||||
|
domain: 'client.example.com'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
await flush();
|
||||||
|
if (bindingApi.getStoredCaptures('captures:workspace:ClientA').length !== 1) {
|
||||||
|
throw new Error('domain-bound capture was not stored under ClientA workspace key');
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Also prove explicit `workspaceRootPath: "Project"` wins over a binding for
|
||||||
|
`client.example.com`.
|
||||||
|
|
||||||
|
- [ ] **Step 2: Run RED**
|
||||||
|
|
||||||
|
Run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /home/mirivlad/git/verstak2/verstak-official-plugins
|
||||||
|
PATH=/tmp/verstak2-tools:/home/mirivlad/.lmstudio/.internal/utils:$PATH node scripts/smoke-browser-inbox-plugin.js
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: fails because domain-bound captures are still stored in the receiving
|
||||||
|
view scope.
|
||||||
|
|
||||||
|
- [ ] **Step 3: Implement minimal routing**
|
||||||
|
|
||||||
|
In `plugins/browser-inbox/frontend/src/index.js`, add helper functions to
|
||||||
|
normalize binding keys, derive a domain from capture fields, and annotate
|
||||||
|
captures without `workspaceRootPath` before storage.
|
||||||
|
|
||||||
|
- [ ] **Step 4: Run GREEN**
|
||||||
|
|
||||||
|
Run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /home/mirivlad/git/verstak2/verstak-official-plugins
|
||||||
|
PATH=/tmp/verstak2-tools:/home/mirivlad/.lmstudio/.internal/utils:$PATH node scripts/smoke-browser-inbox-plugin.js
|
||||||
|
PATH=/tmp/verstak2-tools/venv/bin:/tmp/verstak2-tools:/home/mirivlad/.lmstudio/.internal/utils:$PATH ./scripts/check.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: both commands exit 0.
|
||||||
|
|
||||||
|
### Task 2: Roadmap Documentation
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Modify: `/home/mirivlad/git/verstak2/verstak-docs/05_Official_Plugins.md`
|
||||||
|
- Modify: `/home/mirivlad/git/verstak2/verstak-docs/07_Full_Implementation_Roadmap.md`
|
||||||
|
|
||||||
|
**Interfaces:**
|
||||||
|
- Consumes verified plugin routing behavior.
|
||||||
|
- Produces docs that distinguish implemented domain binding from future conversion workflows.
|
||||||
|
|
||||||
|
- [ ] **Step 1: Update docs**
|
||||||
|
|
||||||
|
Mark domain binding as implemented in the Browser Inbox status text and roadmap
|
||||||
|
while leaving conversion workflow as future work.
|
||||||
|
|
||||||
|
- [ ] **Step 2: Verify docs**
|
||||||
|
|
||||||
|
Run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /home/mirivlad/git/verstak2/verstak-docs
|
||||||
|
git diff --check
|
||||||
|
rg -n "domain-to-workspace binding|Domain binding|conversion" 05_Official_Plugins.md 07_Full_Implementation_Roadmap.md
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: `git diff --check` exits 0 and `rg` shows the updated status lines.
|
||||||
|
|
@ -0,0 +1,74 @@
|
||||||
|
# Browser Inbox Domain Binding Design
|
||||||
|
|
||||||
|
## Purpose
|
||||||
|
|
||||||
|
Browser captures often arrive while the user is not focused on the workspace
|
||||||
|
that should receive them. Domain binding routes unscoped browser captures into a
|
||||||
|
workspace queue by matching the capture domain to a plugin-owned binding table.
|
||||||
|
|
||||||
|
This keeps Browser Inbox behavior in the official plugin. Desktop core still
|
||||||
|
only publishes browser capture events and may annotate the current workspace
|
||||||
|
when it knows one.
|
||||||
|
|
||||||
|
## Scope
|
||||||
|
|
||||||
|
This slice implements domain-to-workspace routing inside `verstak.browser-inbox`:
|
||||||
|
|
||||||
|
- store bindings in the Browser Inbox plugin settings namespace;
|
||||||
|
- match capture domains case-insensitively;
|
||||||
|
- route only captures that do not already include `workspaceRootPath`;
|
||||||
|
- preserve the global aggregate view;
|
||||||
|
- keep the binding model independent from Notes, Files, Activity, and Journal.
|
||||||
|
|
||||||
|
It does not implement conversion into notes/links/files/activity, browser UI for
|
||||||
|
editing bindings, or a desktop core domain binding API.
|
||||||
|
|
||||||
|
## Settings Contract
|
||||||
|
|
||||||
|
The plugin reads `domainBindings` from its settings object:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"domainBindings": {
|
||||||
|
"example.com": "Project",
|
||||||
|
"client.example.com": "ClientA"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Keys are hostnames. Values are top-level `workspaceRootPath` strings.
|
||||||
|
|
||||||
|
Normalization rules:
|
||||||
|
|
||||||
|
- trim whitespace around keys and values;
|
||||||
|
- lowercase domains for matching;
|
||||||
|
- strip one or more leading dots from binding keys;
|
||||||
|
- ignore empty domains and empty workspace roots.
|
||||||
|
|
||||||
|
## Routing Rules
|
||||||
|
|
||||||
|
For each incoming `browser.capture.page`, `browser.capture.selection`, or
|
||||||
|
`browser.capture.link` event:
|
||||||
|
|
||||||
|
1. If payload already has `workspaceRootPath`, keep it unchanged.
|
||||||
|
2. Otherwise, derive a domain from `payload.domain` or `payload.url`.
|
||||||
|
3. If an exact normalized domain binding exists, set `workspaceRootPath` and
|
||||||
|
`workspaceName` to the bound workspace root before storage.
|
||||||
|
4. If no binding exists, keep current behavior and store the capture in the
|
||||||
|
receiving view scope.
|
||||||
|
|
||||||
|
Subdomain fallback is intentionally out of scope for this first slice. A
|
||||||
|
binding for `example.com` does not match `docs.example.com` until a later design
|
||||||
|
adds explicit wildcard or suffix semantics.
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
`scripts/smoke-browser-inbox-plugin.js` must prove:
|
||||||
|
|
||||||
|
- an unscoped capture with `domain: "client.example.com"` and a
|
||||||
|
`domainBindings` entry for that domain is stored under
|
||||||
|
`captures:workspace:ClientA`;
|
||||||
|
- the routed capture appears in the ClientA workspace view;
|
||||||
|
- the global view still aggregates the routed capture;
|
||||||
|
- an event that already includes `workspaceRootPath: "Project"` is not
|
||||||
|
overwritten by a domain binding for another workspace.
|
||||||
Loading…
Reference in New Issue