docs: plan browser receiver pairing
This commit is contained in:
parent
adb85f8a00
commit
f74b45a37c
|
|
@ -0,0 +1,171 @@
|
||||||
|
# Browser Receiver Pairing 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:** Add a token-based pairing gate to the local browser capture receiver.
|
||||||
|
|
||||||
|
**Architecture:** Keep Browser Inbox as a plugin. Add a transport-level token option to `internal/core/browserreceiver`, preserve the open constructor for current development behavior, and document the extension header contract.
|
||||||
|
|
||||||
|
**Tech Stack:** Go desktop core package tests, browser extension protocol docs, Markdown docs.
|
||||||
|
|
||||||
|
## Global Constraints
|
||||||
|
|
||||||
|
- Do not move Browser Inbox queues or conversion workflows into desktop core.
|
||||||
|
- Preserve existing receiver behavior when no token is configured.
|
||||||
|
- Paired mode must not publish capture events for missing or wrong tokens.
|
||||||
|
- Use TDD: write the failing Go receiver test first, run it red, then implement.
|
||||||
|
- Commit and push each affected repository after meaningful changes.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Task 1: Document The Pairing Contract
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Create: `/home/mirivlad/git/verstak2/verstak-docs/docs/superpowers/specs/2026-06-29-browser-receiver-pairing-design.md`
|
||||||
|
- Create: `/home/mirivlad/git/verstak2/verstak-docs/docs/superpowers/plans/2026-06-29-browser-receiver-pairing.md`
|
||||||
|
|
||||||
|
**Interfaces:**
|
||||||
|
- Produces documented `X-Verstak-Receiver-Token` pairing contract.
|
||||||
|
|
||||||
|
- [ ] **Step 1: Write spec and plan**
|
||||||
|
|
||||||
|
Write the design and this implementation plan.
|
||||||
|
|
||||||
|
- [ ] **Step 2: Verify docs**
|
||||||
|
|
||||||
|
Run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /home/mirivlad/git/verstak2/verstak-docs
|
||||||
|
git diff --check
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: exits 0.
|
||||||
|
|
||||||
|
- [ ] **Step 3: Commit and push docs**
|
||||||
|
|
||||||
|
Run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /home/mirivlad/git/verstak2/verstak-docs
|
||||||
|
git add docs/superpowers/specs/2026-06-29-browser-receiver-pairing-design.md docs/superpowers/plans/2026-06-29-browser-receiver-pairing.md
|
||||||
|
git commit -m "docs: plan browser receiver pairing"
|
||||||
|
git push
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: docs `main` is clean and pushed.
|
||||||
|
|
||||||
|
### Task 2: Desktop Receiver Token Gate
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Modify: `/home/mirivlad/git/verstak2/verstak-desktop/internal/core/browserreceiver/receiver_test.go`
|
||||||
|
- Modify: `/home/mirivlad/git/verstak2/verstak-desktop/internal/core/browserreceiver/receiver.go`
|
||||||
|
|
||||||
|
**Interfaces:**
|
||||||
|
- Produces:
|
||||||
|
- `type Options struct { RequireToken bool; ReceiverToken string }`
|
||||||
|
- `func NewWithOptions(bus *events.Bus, options Options, providers ...WorkspaceProvider) *Receiver`
|
||||||
|
|
||||||
|
- [ ] **Step 1: Write the failing tests**
|
||||||
|
|
||||||
|
Add tests proving missing/wrong token rejection and correct token acceptance.
|
||||||
|
|
||||||
|
- [ ] **Step 2: Run RED**
|
||||||
|
|
||||||
|
Run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /home/mirivlad/git/verstak2/verstak-desktop
|
||||||
|
go test ./internal/core/browserreceiver
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: fails because `Options` / `NewWithOptions` do not exist.
|
||||||
|
|
||||||
|
- [ ] **Step 3: Implement token gate**
|
||||||
|
|
||||||
|
Add `Options`, `NewWithOptions`, header validation, and constant-time token
|
||||||
|
comparison. Keep `New` behavior unchanged.
|
||||||
|
|
||||||
|
- [ ] **Step 4: Run GREEN**
|
||||||
|
|
||||||
|
Run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /home/mirivlad/git/verstak2/verstak-desktop
|
||||||
|
go test ./internal/core/browserreceiver
|
||||||
|
go test ./internal/core/...
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: both commands exit 0.
|
||||||
|
|
||||||
|
- [ ] **Step 5: Commit and push desktop**
|
||||||
|
|
||||||
|
Run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /home/mirivlad/git/verstak2/verstak-desktop
|
||||||
|
git add internal/core/browserreceiver/receiver.go internal/core/browserreceiver/receiver_test.go
|
||||||
|
git commit -m "feat: require token for paired browser receiver"
|
||||||
|
git push
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: commit is pushed. Existing unrelated `frontend/wailsjs/go/models.ts`
|
||||||
|
remains unstaged.
|
||||||
|
|
||||||
|
### Task 3: Extension And Roadmap Docs
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Modify: `/home/mirivlad/git/verstak2/verstak-browser-extension/README.md`
|
||||||
|
- 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 receiver token gate.
|
||||||
|
- Produces docs matching implemented pairing behavior.
|
||||||
|
|
||||||
|
- [ ] **Step 1: Update extension README**
|
||||||
|
|
||||||
|
Change the receiver token header description from optional future work to:
|
||||||
|
|
||||||
|
```md
|
||||||
|
- `X-Verstak-Receiver-Token: <token>` required when the desktop receiver is in paired mode
|
||||||
|
```
|
||||||
|
|
||||||
|
- [ ] **Step 2: Verify and commit extension docs**
|
||||||
|
|
||||||
|
Run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /home/mirivlad/git/verstak2/verstak-browser-extension
|
||||||
|
git diff --check
|
||||||
|
git add README.md
|
||||||
|
git commit -m "docs: describe receiver token pairing"
|
||||||
|
git push
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: extension `main` is clean and pushed.
|
||||||
|
|
||||||
|
- [ ] **Step 3: Update platform docs**
|
||||||
|
|
||||||
|
In `05_Official_Plugins.md`, describe that Browser Inbox receives captures
|
||||||
|
through the local receiver token pairing model. In
|
||||||
|
`07_Full_Implementation_Roadmap.md`, mark:
|
||||||
|
|
||||||
|
```md
|
||||||
|
- [x] define local receiver permission/pairing model;
|
||||||
|
```
|
||||||
|
|
||||||
|
- [ ] **Step 4: Verify and commit docs**
|
||||||
|
|
||||||
|
Run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /home/mirivlad/git/verstak2/verstak-docs
|
||||||
|
git diff --check
|
||||||
|
rg -n "define local receiver permission/pairing model|X-Verstak-Receiver-Token" 05_Official_Plugins.md 07_Full_Implementation_Roadmap.md
|
||||||
|
git add 05_Official_Plugins.md 07_Full_Implementation_Roadmap.md
|
||||||
|
git commit -m "docs: mark browser receiver pairing complete"
|
||||||
|
git push
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: docs `main` is clean and pushed.
|
||||||
|
|
@ -0,0 +1,103 @@
|
||||||
|
# Browser Receiver Pairing Design
|
||||||
|
|
||||||
|
## Purpose
|
||||||
|
|
||||||
|
The browser extension already sends captures to the desktop local receiver and
|
||||||
|
can include `X-Verstak-Receiver-Token`. The desktop receiver currently accepts
|
||||||
|
captures without a pairing model. This slice defines and implements the local
|
||||||
|
receiver token gate without moving Browser Inbox behavior into desktop core.
|
||||||
|
|
||||||
|
## Scope
|
||||||
|
|
||||||
|
This slice covers only the local receiver permission/pairing model:
|
||||||
|
|
||||||
|
- receiver token validation;
|
||||||
|
- clear HTTP responses for paired/unpaired requests;
|
||||||
|
- documentation of how the extension presents the token.
|
||||||
|
|
||||||
|
It does not implement domain-to-workspace binding, inbox conversion to
|
||||||
|
notes/files/activity, browser UI for pairing QR codes, or encrypted token
|
||||||
|
storage. Those remain later Phase 5 work.
|
||||||
|
|
||||||
|
## Model
|
||||||
|
|
||||||
|
The receiver has two modes:
|
||||||
|
|
||||||
|
- **Open legacy mode:** no receiver token is configured. This preserves current
|
||||||
|
development behavior and accepts captures without the token header.
|
||||||
|
- **Paired mode:** a receiver token is configured and enabled. Every capture
|
||||||
|
request must include:
|
||||||
|
|
||||||
|
```text
|
||||||
|
X-Verstak-Receiver-Token: <token>
|
||||||
|
```
|
||||||
|
|
||||||
|
The receiver compares the supplied token to the configured token using a
|
||||||
|
constant-time comparison. It does not publish browser capture events when the
|
||||||
|
token is missing or wrong.
|
||||||
|
|
||||||
|
## HTTP Contract
|
||||||
|
|
||||||
|
Endpoint:
|
||||||
|
|
||||||
|
```text
|
||||||
|
POST /api/browser-inbox/v1/captures
|
||||||
|
```
|
||||||
|
|
||||||
|
Successful capture:
|
||||||
|
|
||||||
|
```http
|
||||||
|
202 Accepted
|
||||||
|
```
|
||||||
|
|
||||||
|
```json
|
||||||
|
{ "status": "accepted", "captureId": "capture-id" }
|
||||||
|
```
|
||||||
|
|
||||||
|
Missing token in paired mode:
|
||||||
|
|
||||||
|
```http
|
||||||
|
401 Unauthorized
|
||||||
|
```
|
||||||
|
|
||||||
|
```json
|
||||||
|
{ "error": "receiver token required" }
|
||||||
|
```
|
||||||
|
|
||||||
|
Wrong token in paired mode:
|
||||||
|
|
||||||
|
```http
|
||||||
|
401 Unauthorized
|
||||||
|
```
|
||||||
|
|
||||||
|
```json
|
||||||
|
{ "error": "receiver token invalid" }
|
||||||
|
```
|
||||||
|
|
||||||
|
Other validation behavior remains unchanged: invalid payloads return `400`,
|
||||||
|
missing Browser Inbox consumers return `503`, and non-POST methods return
|
||||||
|
`405`.
|
||||||
|
|
||||||
|
## Runtime API
|
||||||
|
|
||||||
|
Desktop core exposes the model inside `internal/core/browserreceiver`:
|
||||||
|
|
||||||
|
```go
|
||||||
|
type Options struct {
|
||||||
|
RequireToken bool
|
||||||
|
ReceiverToken string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewWithOptions(bus *events.Bus, options Options, providers ...WorkspaceProvider) *Receiver
|
||||||
|
```
|
||||||
|
|
||||||
|
`New(bus, providers...)` remains the open legacy constructor.
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
`internal/core/browserreceiver/receiver_test.go` must prove:
|
||||||
|
|
||||||
|
- paired receivers reject missing tokens with `401`;
|
||||||
|
- paired receivers reject wrong tokens with `401`;
|
||||||
|
- paired receivers accept correct tokens and publish the capture event;
|
||||||
|
- open legacy receivers still accept captures without a token.
|
||||||
Loading…
Reference in New Issue