Skip to content

[CTX-0003] Implement search Lua policy over the public host API - #8

Merged
Xuepoo merged 1 commit into
mainfrom
ctx-0003/feat-search-policy
Oct 4, 2026
Merged

Xuepoo merged 1 commit into
mainfrom
ctx-0003/feat-search-policy

Conversation

@Xuepoo

@Xuepoo Xuepoo commented Oct 4, 2026

Copy link
Copy Markdown
Contributor

Priority: P1 | Area: architecture | Labels: chore,P1,area:architecture | Milestone: v0.1.0 | Task: CTX-0003 | Plan: W-135

Closes #2.

W-135 S-3 plugin package (search repo only): manifest, Lua policy, behavior + parity suites, README synchronized.

Public-API-only statement: the plugin consumes exactly one additive v2 capability (history.transcript.read) and no private surface. No commands history, no KV, no clipboard, no filesystem/process-spawn/network/overlay/terminal authority; export through bitty.selection.copy needs the separate clipboard.write grant and fails closed without it. Record bodies are untrusted observation text, displayed or copied verbatim, never executed. Snapshot queries are point-in-time with no subscriptions and no streaming; the query state is extension-side presentation state and never mutates Terminal Truth. No Core changes, no registry onboarding, no release.

Derivation (strict, read-only): W-135 search-selection contract accepted (bitty-terminal-docs b0514e6); W-131 storage-and-history boundary accepted (bitty-docs 21d63dc); W-137 history-and-storage policy accepted (bitty-plugins-docs 002c7ce); Core host W-143 merged (bitty 0d50b436) + C1-C3 (bitty PR #1664) + history-read host merged (bitty 76fa42d6); spellings verified read-only against bitty main (history.transcript.read / bitty.history.transcript.query / bitty.selection.copy under existing clipboard.write; no terminal.* use, no bitty.search / bitty.selection.get handles which stay Core-owned deferred pending W-01 + W-138). Never wrote in bitty/.

SDK-pin note: package.json pins bitty-plugin-sdk to 0a9487f6c6f47ea0e3cadc9b710e7b1150485822, the head of PR #144 (CTX-0066, W-139 history/search/selection surface), which is OPEN. The pin tracks that PR head rather than a merged release so the history.transcript.query gate shape, the history.transcript.read head, and the 8-category denial taxonomy match the reviewed surface. Re-pin to the #144 merge commit when it lands.

Lifecycle evidence: scoped search finds rows with untrusted-observation labels; foreign-panel rows never cross; next/prev clamp at cached ends; clear drops; refresh replaces (never appends); empty results report EMPTY; denied refresh keeps the previous page; export without clipboard.write denies E_CAPABILITY_DENIED with the page kept.

Denial evidence (all 8 host categories typed): E_HISTORY_MISSING_GRANT, E_HISTORY_REVOKED_GRANT, E_HISTORY_SCOPE_MISMATCH, E_DEF_INVALID (wildcard), E_HISTORY_OVER_BOUND (rows/bytes/needle/window), E_HISTORY_CAPTURE_DISABLED, E_HISTORY_SAFE_MODE, E_HISTORY_TRUST_DENIED, E_HISTORY_UNAVAILABLE (purged list; purged-only search is an empty page, never an existence oracle).

Parity evidence: ungranted/safe-mode/trust denials identical under the shipped vs a foreign commands-only manifest; commands grant never implies transcript reads and vice versa (source isolation); export-variant manifest copies verbatim with truncation flags while the shipped manifest denies even a runtime-granted clipboard.write (declaration required); manifest declares exactly the one head; Lua touches only api_version/commands/history/selection/settings with surfaces history.transcript.query + selection.copy; mismatch/safe-mode/uninstall match the no-plugin baseline.

Gates: just check green (fmt, markdownlint, metadata, hygiene, portable-path, manifest lint 0 errors + 1 high-risk consent warning for the transcript grant, luaparse, lua-control, bun test 30 pass / 128 expects); just workflows green (actionlint, act -n); gitleaks clean.

S-3 of W-135: manifest (id bitty-terminal.search 0.0.1, compat bitty >=0.5,<1.0 + plugin-api ^1.0, exactly history.transcript.read, lazy search/next/prev/clear/copy + no events), lua/search/init.lua (snapshot query state, explicit-scope search/list/tail over bitty.history.transcript.query, pure cursor navigation, grant-gated export via bitty.selection.copy, fail-closed typed denials, mismatch disable), bun+wasmoon suite against the SDK MockHost (search lifecycle/untrusted labels/navigation clamps, 8-category denial taxonomy, window budgets, export gating, mismatch/fallback/safe mode, denial parity vs foreign manifest, no-weakening proof: 30 tests), README scope/rules/non-goals/compat + SDK-pin note synchronized. No Core changes, no registry onboarding, no release.
@Xuepoo Xuepoo added this to the v0.1.0 milestone Oct 4, 2026
@Xuepoo
Xuepoo merged commit 74feb27 into main Oct 4, 2026
7 checks passed
@Xuepoo
Xuepoo deleted the ctx-0003/feat-search-policy branch October 4, 2026 13:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Implement accepted standalone component without private host bypass

1 participant