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
2 changes: 1 addition & 1 deletion .release-please-manifest.premain.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
".": "1.3.0-rc.2"
".": "1.4.0-rc"
}
18 changes: 18 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,23 @@
# Changelog

## [1.4.0-rc](https://github.com/theory-cloud/TableTheory/compare/v1.3.0...v1.4.0-rc) (2026-02-14)


### Features

* add FaceTheory ISR MetaStore helper ([0812a68](https://github.com/theory-cloud/TableTheory/commit/0812a68b1203f9179d987dd62eb3529e0332d705))
* TableTheory FaceTheory ISR MetaStore ([f57744d](https://github.com/theory-cloud/TableTheory/commit/f57744d5275744d6399563d29f920bcc045a2f68))


### Bug Fixes

* **deps:** resolve npm audit vulnerabilities ([83fadbd](https://github.com/theory-cloud/TableTheory/commit/83fadbd3a7d5e8f3bab0fa85f0da4250bbb1e27a))
* **deps:** update python deps for security ([712cfb5](https://github.com/theory-cloud/TableTheory/commit/712cfb5b08c410d57bbc28bd6664768b2c74b30b))
* pass SEC-2 dependency scans ([a3e0390](https://github.com/theory-cloud/TableTheory/commit/a3e0390d31d99435fd8c8aa7d48c2aeb7845d977))
* **release:** reset premain manifest baseline ([33cf3bc](https://github.com/theory-cloud/TableTheory/commit/33cf3bce6460db569f017c3127a1606a2414c432))
* **release:** reset premain manifest baseline ([69020e6](https://github.com/theory-cloud/TableTheory/commit/69020e6ab46a9358f0d50347e62a2895a63ff5a2))
* **security:** bump Go toolchain to go1.25.7 ([033b62c](https://github.com/theory-cloud/TableTheory/commit/033b62cdb9551482020293e4a006e29adb601dac))

## [1.3.0](https://github.com/theory-cloud/TableTheory/compare/v1.2.1...v1.3.0) (2026-01-29)


Expand Down
2 changes: 1 addition & 1 deletion contract-tests/runners/go/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ module github.com/theory-cloud/tabletheory-contract-tests/runners/go

go 1.25

toolchain go1.25.6
toolchain go1.25.7

require (
github.com/aws/aws-sdk-go-v2 v1.41.1
Expand Down
480 changes: 238 additions & 242 deletions contract-tests/runners/ts/package-lock.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docs/development/planning/theorydb-10of10-roadmap.md
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ Guardrails (no denominator games):

**Implementation (in repo)**
- Workflow: `.github/workflows/quality-gates.yml` runs `make rubric` on PRs to `premain` (and on pushes to `premain`).
- Tooling pins: `golangci-lint@v2.5.0`, `govulncheck@v1.1.4`, `gosec@v2.22.11` (plus `go.mod` toolchain `go1.25.6` via `go-version-file`).
- Tooling pins: `golangci-lint@v2.5.0`, `govulncheck@v1.1.4`, `gosec@v2.22.11` (plus `go.mod` toolchain `go1.25.7` via `go-version-file`).
- Integration infra pin: DynamoDB Local uses `amazon/dynamodb-local:3.1.0` (via `docker-compose.yml` and `DYNAMODB_LOCAL_IMAGE`).

---
Expand Down
8 changes: 7 additions & 1 deletion docs/facetheory/isr-cache-schema.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,13 @@ Lock rule (correctness boundary):
- write new metadata + release lease as one atomic step
- pointer-swap designs where you write a new version item and then update the “current” pointer

(See `docs/facetheory/isr-transaction-recipes.md` once FT-T2 lands.)
(See `docs/facetheory/isr-transaction-recipes.md`.)

## Environment variables (FaceTheory ISR)

- `FACETHEORY_CACHE_TABLE_NAME` is the canonical env var used by FaceTheory ISR cache metadata/lease models.
- If you are wiring this table via **AppTheory**, some constructs may provide `APPTHEORY_CACHE_TABLE_NAME` (and/or other
aliases). Ensure `FACETHEORY_CACHE_TABLE_NAME` is set so FaceTheory docs and examples work without guesswork.

## Runnable model definitions

Expand Down
85 changes: 54 additions & 31 deletions docs/facetheory/isr-transaction-recipes.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,11 @@ Use this when you only need one metadata record per cache key.
1. Acquire the lease (`LOCK`) for `pk`.
2. Regenerate the body and write it to S3.
3. Publish metadata and release the lock with a single DynamoDB transaction:
- `ConditionCheck` the lease row (`lease_token` matches AND `lease_expires_at > now`)
- `Put` the metadata row (`META`) with the new pointer (`s3_key`), timestamps, etag, ttl
- `Delete` the lease row (optionally conditioned on `lease_token`)
- `Delete` the lease row (`LOCK`) with a condition expression (`lease_token` matches AND `lease_expires_at > now`)

Note: DynamoDB transactions cannot include multiple operations on the same item. Prefer a conditional `Delete`/`Update`
on the lease row over a separate `ConditionCheck` + `Delete` on the same lease key.

### Why the transaction matters

Expand All @@ -46,10 +48,9 @@ Recommended item roles (same `pk`):

Transaction sketch:

1. `ConditionCheck` the lease row (token + not expired).
2. `Put` the new version row (`VER#...`) guarded with `attribute_not_exists(pk)` to avoid duplicate IDs.
3. `Update` the pointer row (`META`) to set `current_sk` to the new version (optionally guard with optimistic `version`).
4. `Delete` the lease row (optionally conditioned on token).
1. `Put` the new version row (`VER#...`) guarded with `attribute_not_exists(pk)` to avoid duplicate IDs.
2. `Update` the pointer row (`META`) to set `current_sk` to the new version (optionally guard with optimistic `version`).
3. `Delete` the lease row (`LOCK`) with a condition expression (token + not expired).

## Stale-writer protection options

Expand Down Expand Up @@ -96,16 +97,13 @@ metaItem := &models.FaceTheoryCacheMetadata{
}

err := db.TransactWrite(ctx, func(tx core.TransactionBuilder) error {
tx.ConditionCheck(
tx.Put(metaItem)

tx.Delete(
leaseItem,
tabletheory.Condition("lease_token", "=", leaseToken),
tabletheory.Condition("lease_expires_at", ">", nowUnix),
)

tx.Put(metaItem)

// Optional: make the delete conditional on the same token.
tx.Delete(leaseItem, tabletheory.Condition("lease_token", "=", leaseToken))
return nil
})
```
Expand All @@ -114,17 +112,6 @@ err := db.TransactWrite(ctx, func(tx core.TransactionBuilder) error {

```ts
await client.transactWrite([
{
kind: 'condition',
model: 'FaceTheoryCacheLease',
key: { pk, sk: 'LOCK' },
conditionExpression: '#tok = :tok AND #exp > :now',
expressionAttributeNames: { '#tok': 'lease_token', '#exp': 'lease_expires_at' },
expressionAttributeValues: {
':tok': { S: leaseToken },
':now': { N: String(nowUnix) },
},
},
{
kind: 'put',
model: 'FaceTheoryCacheMetadata',
Expand All @@ -134,22 +121,56 @@ await client.transactWrite([
kind: 'delete',
model: 'FaceTheoryCacheLease',
key: { pk, sk: 'LOCK' },
conditionExpression: '#tok = :tok AND #exp > :now',
expressionAttributeNames: { '#tok': 'lease_token', '#exp': 'lease_expires_at' },
expressionAttributeValues: {
':tok': { S: leaseToken },
':now': { N: String(nowUnix) },
},
},
]);
```

### TypeScript (TableTheory helper: `FaceTheoryIsrMetaStore`)

TableTheory exports a small helper that implements the FaceTheory ISR metadata + lease operations using:

- `LeaseManager` for acquiring/releasing `LOCK` rows
- `TheorydbClient.transactWrite()` for atomic “publish META + release LOCK” (Recipe A)

```ts
import { DynamoDBClient } from '@aws-sdk/client-dynamodb';
import { createFaceTheoryIsrMetaStore } from '@theory-cloud/tabletheory-ts';

const ddb = new DynamoDBClient({ region: process.env.AWS_REGION ?? 'us-east-1' });
const isr = createFaceTheoryIsrMetaStore({
ddb,
tableName: process.env.FACETHEORY_CACHE_TABLE_NAME!,
});

const lease = await isr.tryAcquireLease({
cacheKey,
leaseOwner: 'my-app-instance', // optional (for app logs)
leaseDurationMs: 30_000,
});
if (!lease) return; // another contender is regenerating

await isr.commitGeneration({
cacheKey,
leaseOwner: 'my-app-instance', // optional (for app logs)
leaseToken: lease.leaseToken,
htmlPointer: s3Key,
generatedAtMs: Date.now(),
revalidateSeconds: 60,
etag,
});
```

### Python (`Table.transact_write`)

```py
table.transact_write(
[
TransactConditionCheck(
pk=pk,
sk="LOCK",
condition_expression="#tok = :tok AND #exp > :now",
expression_attribute_names={"#tok": "lease_token", "#exp": "lease_expires_at"},
expression_attribute_values={":tok": lease_token, ":now": now_unix},
),
TransactPut(
item=FaceTheoryCacheMetadata(
pk=pk,
Expand All @@ -164,8 +185,10 @@ table.transact_write(
TransactDelete(
pk=pk,
sk="LOCK",
condition_expression="#tok = :tok AND #exp > :now",
expression_attribute_names={"#tok": "lease_token", "#exp": "lease_expires_at"},
expression_attribute_values={":tok": lease_token, ":now": now_unix},
),
]
)
```

2 changes: 2 additions & 0 deletions examples/basic/contacts/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ module github.com/theory-cloud/tabletheory/examples/basic/contacts

go 1.25

toolchain go1.25.7

require (
github.com/aws/aws-sdk-go-v2/config v1.32.7
github.com/aws/aws-sdk-go-v2/credentials v1.19.7
Expand Down
2 changes: 2 additions & 0 deletions examples/basic/notes/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ module github.com/theory-cloud/tabletheory/examples/basic/notes

go 1.25

toolchain go1.25.7

require (
github.com/aws/aws-sdk-go-v2/config v1.32.7
github.com/aws/aws-sdk-go-v2/credentials v1.19.7
Expand Down
2 changes: 2 additions & 0 deletions examples/basic/todo/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ module github.com/theory-cloud/tabletheory/examples/basic/todo

go 1.25

toolchain go1.25.7

require (
github.com/aws/aws-sdk-go-v2/config v1.32.7
github.com/aws/aws-sdk-go-v2/credentials v1.19.7
Expand Down
2 changes: 2 additions & 0 deletions examples/multi-tenant/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ module github.com/theory-cloud/tabletheory/examples/multi-tenant

go 1.25

toolchain go1.25.7

require (
github.com/google/uuid v1.6.0
github.com/gorilla/mux v1.8.1
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ module github.com/theory-cloud/tabletheory

go 1.25

toolchain go1.25.6
toolchain go1.25.7

require (
github.com/aws/aws-lambda-go v1.52.0
Expand Down
3 changes: 2 additions & 1 deletion py/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ classifiers = [
dynamic = ["version"]
dependencies = [
"boto3>=1.42.30",
"cryptography>=46.0.3",
"cryptography>=46.0.5",
"PyYAML>=6.0.3",
]

Expand All @@ -23,6 +23,7 @@ dev = [
"boto3-stubs[dynamodb]>=1.42.30",
"build>=1.2.2",
"mypy>=1.14.0",
"pip>=26.0",
"pip-audit>=2.8.0",
"pytest>=8.3.0",
"pytest-cov>=7.0.0",
Expand Down
2 changes: 1 addition & 1 deletion py/src/theorydb_py/version.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"version": "1.3.0"
"version": "1.4.0-rc"
}
Loading
Loading