Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 38 additions & 6 deletions docs/development/storage-and-history-boundary.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,38 @@ ownership statement here is a contract direction for a later implementation; the
(bitty-plugins-docs), `W-139` (bitty-plugin-sdk), and `W-146`
(bitty / `CTX-0939`).

## Erratum (2026-10-05)

This erratum amends the per-plugin KV ceiling contract to the implemented
values. Accepted status is kept; this is a correction, not a normative
weakening.

- Corrected ceilings: 64 KiB total per plugin
(`STORE_MAX_TOTAL_BYTES = 64 * 1024`), 8 KiB per value (unchanged,
`STORE_MAX_VALUE_BYTES = 8 * 1024`), JSON depth 16
(`JSON_MAX_DEPTH = 16`), 256 entries per plugin
(`STORE_MAX_ENTRIES = 256`); atomic commit with no partial write is
unchanged.
- Provenance: `bitty-storage` `src/ceiling.rs` ceiling constants,
byte-for-byte with the Core
`crates/bitty-runtime/src/plugin_runtime/store.rs` bounds, confirmed by
the `bitty-storage` CTX-0003/0004 parity evidence.
- Superseded prose: the budget table below previously stated 256 KiB total
per plugin, depth 8, and 1024 nodes. Read the corrected ceilings above
wherever that prose appears.
- Why this is not a weakening: the implemented size and entry bounds are
strictly tighter than the superseded prose. Depth 16 versus 8 is the one
documented exception: it carries Core's pre-existing JSON depth, already
enforced by Core.
- Dual-layer scope note (resolved 2026-10-05): the Lua marshalling layer
previously enforced the older 256 KiB / depth 8 / 1024-node ceilings; its
alignment to the ceilings above landed in bitty CTX-0970 (PR #1713,
`a3dbf9d`). Both layers now enforce 64 KiB total, 8 KiB per value, and
depth 16; the count bound is 256 in each layer's native unit (entries in
`bitty-runtime`, nodes in `bitty-lua`).
- No silent changes: any future bound change is a new security-reviewed
decision, not an edit to this erratum.

## Purpose and scope

This specification is the accepted reconciliation of the history and storage scope. It fixes one ownership and
Expand Down Expand Up @@ -159,12 +191,12 @@ sensitivities, and budgets. They must not be merged into one universal database
or one shared store, and none may become the default sink for raw terminal
output.

| Storage object | Owner (contract and policy) | Store mechanics | Lifecycle | Retention and deletion | Persists by default | Budget or bound |
| -------------------- | ------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| Segmented transcript | History plugin (`history`, candidate) under plugin-facing policy fixed by `W-137`; Core owns the event source | Proposed extracted `bitty-storage` mechanics under the accepted reconciliation | Created only while opt-in capture is enabled for a panel; segments seal and roll; active capture ends at purging or uninstalling the plugin or at panel close per policy, and retained history is not deleted merely by closing a panel | Retention by age and size with sealed-segment deletion; explicit purge is authoritative and must remove bytes; no resurrect from a derived index | No; raw stdout and PTY bytes are not persisted without explicit opt-in | Per-panel and per-store byte and age caps; bounded sealed-segment size; compression; no unbounded growth |
| Command history | History plugin under policy fixed by `W-137`; Core owns the event source, and `OSC 133` is advisory only | Proposed extracted `bitty-storage` mechanics for the bytes and rebuildable index | Appended per command boundary while capture is enabled; small and long-lived; external links may dangle after provider removal | Explicit purge or uninstall; age and count bounds; dangling external references surface as typed unavailability, never as silent gaps | No; capture is opt-in, and recording input is a separate opt-in | Command-count, age, and byte bounds; commands-only is the least sensitive tier; optional output tier stays bounded and separate |
| Session snapshots | Core, under the Restore/Persistence separation in ADR 0013 and the Panel Runtime save/restore rules | Core save/restore path; storage mechanics may move only if restore re-derivation stays Core | Written by Core on normal interactive exit; read on restore; volatile structure is re-derived on load and fails closed to a clean start | Replaced by the next exit save; deletion removes the session file; safe mode never reads it; restore never writes | Yes for bounded scrollback and cwd on normal interactive exit (open point below); never under safe or headless mode | Versioned whole-file bound; bounded per-pane scrollback and captured metadata; atomic temp-plus-rename |
| Per-plugin KV | `bitty-plugin-host` Lua host service (Core); SDK surface fixed by `W-139`, plugin-facing policy by `W-137` | Core host service today; mechanics may move to `bitty-storage` while the contract stays with the SDK | Plugin-scoped and generation-independent: values committed before a generation is disposed remain readable by the next generation | Deleted only by uninstall, an explicit `nil` write, or an explicit user purge; no expiry and no eviction by construction | Only plugin-authored writes; not a default sink for terminal output or secrets | Published plugin-store ceilings: 256 KiB total per plugin, 8 KiB per value, depth 8, 1024 nodes; atomic commit with no partial write |
| Storage object | Owner (contract and policy) | Store mechanics | Lifecycle | Retention and deletion | Persists by default | Budget or bound |
| -------------------- | ------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| Segmented transcript | History plugin (`history`, candidate) under plugin-facing policy fixed by `W-137`; Core owns the event source | Proposed extracted `bitty-storage` mechanics under the accepted reconciliation | Created only while opt-in capture is enabled for a panel; segments seal and roll; active capture ends at purging or uninstalling the plugin or at panel close per policy, and retained history is not deleted merely by closing a panel | Retention by age and size with sealed-segment deletion; explicit purge is authoritative and must remove bytes; no resurrect from a derived index | No; raw stdout and PTY bytes are not persisted without explicit opt-in | Per-panel and per-store byte and age caps; bounded sealed-segment size; compression; no unbounded growth |
| Command history | History plugin under policy fixed by `W-137`; Core owns the event source, and `OSC 133` is advisory only | Proposed extracted `bitty-storage` mechanics for the bytes and rebuildable index | Appended per command boundary while capture is enabled; small and long-lived; external links may dangle after provider removal | Explicit purge or uninstall; age and count bounds; dangling external references surface as typed unavailability, never as silent gaps | No; capture is opt-in, and recording input is a separate opt-in | Command-count, age, and byte bounds; commands-only is the least sensitive tier; optional output tier stays bounded and separate |
| Session snapshots | Core, under the Restore/Persistence separation in ADR 0013 and the Panel Runtime save/restore rules | Core save/restore path; storage mechanics may move only if restore re-derivation stays Core | Written by Core on normal interactive exit; read on restore; volatile structure is re-derived on load and fails closed to a clean start | Replaced by the next exit save; deletion removes the session file; safe mode never reads it; restore never writes | Yes for bounded scrollback and cwd on normal interactive exit (open point below); never under safe or headless mode | Versioned whole-file bound; bounded per-pane scrollback and captured metadata; atomic temp-plus-rename |
| Per-plugin KV | `bitty-plugin-host` Lua host service (Core); SDK surface fixed by `W-139`, plugin-facing policy by `W-137` | Core host service today; mechanics may move to `bitty-storage` while the contract stays with the SDK | Plugin-scoped and generation-independent: values committed before a generation is disposed remain readable by the next generation | Deleted only by uninstall, an explicit `nil` write, or an explicit user purge; no expiry and no eviction by construction | Only plugin-authored writes; not a default sink for terminal output or secrets | Published plugin-store ceilings: 64 KiB total per plugin, 8 KiB per value, depth 16, 256 entries; atomic commit with no partial write |

### Segmented transcript

Expand Down
Loading