Skip to content
Merged
Show file tree
Hide file tree
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
7 changes: 5 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,12 @@ The format follows Keep a Changelog and the package uses semantic versioning.

## Unreleased

## 3.2.0 - 2026-09-28

- Added opt-in bounded mutation batches for up to 20 documents and 1 MiB of
JSON, with one atomic collection revision, HEAD-last durability, and browser
cache updates.
JSON through typed `putMany()` APIs, with one atomic collection revision,
HEAD-last durability, bounded browser cache updates, and no silent fallback
to separate writes.
- Published a post-merge 1,008-write scaling matrix across seven regions,
three collection sizes, and zero, one, and two indexes, including three
retained R2 failures and the historical comparison.
Expand Down
1 change: 1 addition & 0 deletions deploy/cloudflare/wrangler.example.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"THIMBLE_READ_KEY_VERSIONS": "",
"THIMBLE_HEAD_TTL_MS": "1000",
"THIMBLE_READ_BUNDLES": "false",
"THIMBLE_MUTATION_BATCHES": "false",
"THIMBLE_COLLECTION_LAYOUTS": "",
"THIMBLE_COLLECTION_INDEXES": "{}",
"THIMBLE_COLLECTIONS": "",
Expand Down
9 changes: 5 additions & 4 deletions docs/DEPLOYMENT-AWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,11 @@ expose:
- `THIMBLE_READ_BUNDLES`
- `THIMBLE_MUTATION_BATCHES`

The supplied deployment therefore leaves Studio, covering indexes, and read
bundles disabled. Use a reviewed derived template or another Node deployment
configuration when those optional features are required. Setting variables
only in the deployment shell does not pass them into the Lambda function.
The supplied deployment therefore leaves Studio, covering indexes, read
bundles, and mutation batches disabled. Use a reviewed derived template or
another Node deployment configuration when those optional features are
required. Setting variables only in the deployment shell does not pass them
into the Lambda function.

The template still passes its legacy `RetiredCollectionLayouts` value into
the Lambda environment. The authority runtime does not perform retired-layout
Expand Down
9 changes: 5 additions & 4 deletions docs/DEPLOYMENT-AZURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,10 +96,11 @@ collection-layout, and retention settings. It does not currently expose:
- `THIMBLE_READ_BUNDLES`
- `THIMBLE_MUTATION_BATCHES`

The supplied deployment therefore leaves Studio, covering indexes, and read
bundles disabled. Use a reviewed derived template or another Container Apps
configuration when those optional features are required. Setting variables
only in the deployment shell does not add them to the Container App.
The supplied deployment therefore leaves Studio, covering indexes, read
bundles, and mutation batches disabled. Use a reviewed derived template or
another Container Apps configuration when those optional features are
required. Setting variables only in the deployment shell does not add them to
the Container App.

For key rotation, set `keyVersion` to the current write version and
`readKeyVersions` to the comma-separated historical versions that remain
Expand Down
10 changes: 10 additions & 0 deletions docs/EVALUATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,16 @@ Enable the opt-in cold point-read bundle path with:
$env:THIMBLE_READ_BUNDLES = "true"
```

Enable the opt-in bounded mutation-batch path with:

```powershell
$env:THIMBLE_MUTATION_BATCHES = "true"
```

The browser harness does not automatically coalesce writes. Use
`ThimbleCollection.putMany()` or `ThimbleClient.writeBatch()` to exercise one
explicit group.

For a compiled local run:

```powershell
Expand Down
16 changes: 16 additions & 0 deletions docs/OPERATIONS.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,13 +136,29 @@ Backups require the matching master key version.
Logical exports are portable plaintext migrations, not encrypted backups. See
[Logical migration](MIGRATION.md).

## Mutation batches

Enable mutation batching only for applications that intentionally call
`putMany()`. Ordinary writes are not delayed or coalesced automatically.

Monitor complete batch duration rather than only amortized per-document
latency. A batch remains one conflict and retry unit, so repeated CAS failures
can repeat more work than one ordinary mutation. Keep an immediate single-write
fallback for user actions that should not wait for a group.

The initial supported limits are 20 unique documents and 1 MiB of JSON. Do not
raise them without measuring authority memory, provider request limits, and
contention with representative payloads.

## Observability

Record:

- read source: memory, IndexedDB, or remote
- remote object bytes
- read-bundle requests, bytes, object counts, and fallbacks
- mutation-batch document count, request bytes, total duration, revision,
`cacheComplete`, failures, and CAS retries
- compression ratio
- envelope encode/decode duration
- HEAD conditional-write retries
Expand Down
18 changes: 18 additions & 0 deletions docs/SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,24 @@ maintenance, key rotation, and migration. A deployment that does not trust the
authority runtime with plaintext is outside the current ThimbleDB threat
model.

## Mutation batch boundary

Mutation batching is disabled by default. When enabled, it uses the same
authenticated session, exact origin, CSRF token, scope write grant, and layout
generation checks as an ordinary write.

The complete request is limited to 20 unique document IDs and 1 MiB of JSON.
Validation finishes before candidate immutable objects are uploaded. Success
is returned only after one conditional collection HEAD publication. A
validation failure publishes nothing, and a HEAD conflict applies to the
complete batch rather than hidden per-document commits.

The batch response is `no-store` and may contain decoded changed document-path
cache values over HTTPS. Response cache values are bounded to 42 objects and
16 MiB. The authority already processes the same plaintext during writes.
Applications that do not accept this response boundary should leave mutation
batching disabled and use ordinary writes.

## Secret handling

Never commit:
Expand Down
29 changes: 19 additions & 10 deletions docs/VERSIONING.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,6 @@ Package version `1.0.0` freezes the documented exports in
[Public package API](PUBLIC-API.md). Semantic versioning applies to the root,
auth, authority, and provider subpaths.

## Unreleased compatible capabilities

- authorities may explicitly advertise bounded mutation batches
- clients can publish 1-20 documents in one collection revision through
`putMany()`
- authorities that do not enable the capability retain existing single-write
behavior and do not advertise the endpoint
- the stored TDB1, Snapshot HEAD, Trie HEAD, and secondary-index formats are
unchanged

## Version 1.0

Version 1.0 provides:
Expand Down Expand Up @@ -114,6 +104,25 @@ optional definition and projection fields that older readers ignore. Upgrade
every writing authority before enabling covering fields, then rebuild the
affected indexes while writes are quiescent.

## Version 3.2

Version 3.2 adds compatible bounded write and performance improvements:

- authorities may explicitly advertise bounded mutation batches
- clients can publish 1-20 unique documents and at most 1 MiB of JSON in one
collection revision through `putMany()`
- authorities that do not enable the capability retain existing single-write
behavior and do not advertise the endpoint
- range planning applies every supported bound before loading candidates
- bounded immutable commits overlap independent Snapshot, Trie, and index
uploads while preserving final HEAD publication
- normal decoded object reads and writes fail closed above 16 MiB by default
- mutable HEAD freshness begins when revalidation completes

The stored TDB1, Snapshot HEAD, Trie HEAD, and secondary-index formats are
unchanged. Mutation batching is an optional authority and browser capability,
so older clients continue using ordinary single writes.

## Object protocol version

`TDB1` is stored in every object envelope. Protocol compatibility is separate
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "thimbledb",
"version": "3.1.0",
"version": "3.2.0",
"description": "Encrypted browser-first JSON database for small web apps, backed by object storage with in-app or separate Cloudflare and Node authorities.",
"private": false,
"license": "Apache-2.0",
Expand Down
5 changes: 4 additions & 1 deletion site/src/pages/index.astro
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,9 @@ const websiteSchema = {
</div>
<p>
The authority owns credentials, identity, keys, and conditional
writes. Application code works with documents and collections.
writes. Applications can explicitly group an existing burst into one
bounded collection revision. Application code works with documents
and collections.
</p>
</div>

Expand Down Expand Up @@ -277,6 +279,7 @@ const websiteSchema = {
<li>Records belong to one user, tenant, role, or public scope</li>
<li>ID reads, declared indexes, or bounded scans cover the workflow</li>
<li>Writes are modest compared with reads</li>
<li>Existing import or autosave bursts can use bounded batches</li>
<li>The hot working set fits in browser storage</li>
<li>External OIDC already handles account security</li>
</ul>
Expand Down
2 changes: 1 addition & 1 deletion site/tests/site.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ test("AI discovery routes publish explicit access and decision content", async (
expect(fullText).toContain("# System diagrams");
expect(fullText).toContain("# Configuration reference");
expect(fullText).toContain("# Website privacy");
expect(fullText).toContain("## 3.1.0");
expect(fullText).toContain("## 3.2.0");

await page.goto("/vibe-coded-apps/");
await expect(
Expand Down
Loading