Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
3c21148
perf(entitlements): cache enforcement plan lookups
cursoragent Jul 31, 2026
7d5d777
style(docs): format entitlement cache notes
cursoragent Jul 31, 2026
0cd468d
Merge remote-tracking branch 'origin/main' into cursor/meter-do-38c8
cursoragent Jul 31, 2026
59a8238
feat(entitlements): add per-user quota meter
cursoragent Aug 1, 2026
8ebf663
feat(account): inventory UserMeter lifecycle
cursoragent Aug 1, 2026
4a60dd9
test(entitlements): provide UserMeter fixtures
cursoragent Aug 1, 2026
73a8e37
test(entitlements): clean meter test imports
cursoragent Aug 1, 2026
8b001bf
style(mcp): format meter gateway tests
cursoragent Aug 1, 2026
df32168
fix(email): read daily usage from UserMeter
cursoragent Aug 1, 2026
ae07b85
Merge remote-tracking branch 'origin/main' into cursor/meter-do-38c8
cursoragent Aug 1, 2026
e6622a4
docs(entitlements): clarify meter cutover semantics
cursoragent Aug 1, 2026
7628aaf
fix(entitlements): address UserMeter review feedback
cursoragent Aug 1, 2026
468ee51
Merge remote-tracking branch 'origin/main' into cursor/meter-do-38c8
cursoragent Aug 1, 2026
a8cba2b
test(entitlements): add RunLog admin fixture
cursoragent Aug 1, 2026
edfd973
test(run-log): isolate usage counts per user
cursoragent Aug 1, 2026
2307d37
Merge remote-tracking branch 'origin/main' into cursor/meter-do-38c8
cursoragent Aug 1, 2026
b18246f
feat(entitlements): shadow storage bytes in UserMeter
cursoragent Aug 1, 2026
eaaa509
docs(entitlements): inventory storage shadow
cursoragent Aug 1, 2026
3c13b53
fix(entitlements): make storage reserves fail closed
cursoragent Aug 1, 2026
68256ea
Merge remote-tracking branch 'origin/main' into cursor/meter-do-38c8
cursoragent Aug 1, 2026
e454e76
feat(services): shadow liveness in UserMeter
cursoragent Aug 1, 2026
9f7be03
docs(services): inventory liveness shadow
cursoragent Aug 1, 2026
581b896
perf(services): defer liveness shadow writes
cursoragent Aug 1, 2026
393b2a4
Merge remote-tracking branch 'origin/main' into cursor/meter-do-38c8
cursoragent Aug 1, 2026
12e7c02
fix(services): serialize liveness shadows
cursoragent Aug 1, 2026
3a0d41d
Merge remote-tracking branch 'origin/main' into cursor/meter-do-38c8
cursoragent Aug 1, 2026
194d5b5
Merge remote-tracking branch 'origin/main' into cursor/meter-do-38c8
cursoragent Aug 1, 2026
5e8d1b9
feat(account): shadow deletion leases in UserMeter
cursoragent Aug 1, 2026
2e92f03
docs(account): inventory deletion shadow
cursoragent Aug 1, 2026
c566c54
Merge remote-tracking branch 'origin/main' into cursor/meter-do-38c8
cursoragent Aug 1, 2026
62f6078
fix(account): reconcile and sanitize deletion shadows
cursoragent Aug 1, 2026
1116e07
Merge remote-tracking branch 'origin/main' into cursor/meter-do-38c8
cursoragent Aug 1, 2026
d20696d
feat(account): move write leases into UserMeter
cursoragent Aug 1, 2026
6c2effd
docs(account): describe UserMeter lease authority
cursoragent Aug 1, 2026
afe0bb2
test(account): provide authoritative meter fixtures
cursoragent Aug 1, 2026
29dc257
test(account): wire meter into workers fixtures
cursoragent Aug 1, 2026
11814af
fix(account): clean partial lease mirrors
cursoragent Aug 1, 2026
7e88800
Merge remote-tracking branch 'origin/main' into cursor/meter-do-38c8
cursoragent Aug 1, 2026
8d368eb
Merge remote-tracking branch 'origin/main' into cursor/meter-do-38c8
cursoragent Aug 1, 2026
4c0aa23
feat(admin): add UserMeter parity report
cursoragent Aug 1, 2026
c44a518
docs(entitlements): define production parity gates
cursoragent Aug 1, 2026
a6180fc
fix(admin): bound parity page walks
cursoragent Aug 1, 2026
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
34 changes: 34 additions & 0 deletions docs/contributing/architecture/entitlements.md
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,40 @@ soak/parity review.
waits until reporting-off-D1 work merges and mirror parity is verified in
production.

### Admin UserMeter parity gates (`admin_user_meter_parity`)

Production verification for mirror retirement and authority flips uses the
admin-only read-only capability `admin_user_meter_parity` (input:
`stable_user_id`). It compares production-shaped D1 rows for one account against
direct UserMeter RPCs and never bootstraps or writes parity state. Opening a
cold UserMeter stub may still run Durable Object constructor schema maintenance
and opportunistic stale daily-counter pruning. Cold meter rows surface as
`needsBootstrap` with `meterCount`/`meterBytes` null.

Interpret the structured report as independent gates:

| Gate | Pass condition |
| -------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Daily counters (current UTC day) | Each of the four daily resources has `parity: true` (`d1Count === meterCount`); aggregate `daily.mismatchCount === 0`. |
| Storage bytes | `storage.parity` — D1 `users.d1_storage_bytes` equals UserMeter `readStorageBytes` (not `needsBootstrap`). |
| Package services | `packageServices.parity` — inventory mismatch category counts are all zero (`d1Only` / `meterOnly` / `statusMismatch` / `startedAtMismatch` / `sourceUpdatedAtMismatch`), fresh-running counts match under the shared 24h stale window, and the meter page walk is not `truncated`. |
| Deletion tombstone | `deletion.deletingAtParity` — D1 `users.deleting_at` matches the meter tombstone. |
| Temporary D1 lease mirror | `deletion.mirrorLeaseParity` — `doOnly === 0`, `legacyWithoutD1 === 0`, inventory not truncated, and `d1ActiveLeaseCount >= doAuthorityLeaseCount` (same-token mirror coverage). `tokenSetMismatches.d1Only` is reported but does **not** fail this gate. |

**D1-only leases:** email and other transition paths that omit `env` still take
exact D1 leases, so `d1Only > 0` is expected until that handoff. Mirror-removal
readiness therefore ignores `d1Only`. Operators separately confirm those rows
are known email/transition holders via `admin_account_write_lease_list` and
holder classification before retiring the temporary D1 mirror inventory.

**Threshold:** treat unexplained mismatches as blocking for the corresponding
cutover (daily mirror retirement, storage authority flip, package-service
authority flip, or temporary D1 lease-mirror removal). Expected cold accounts
may report `needsBootstrap` until live traffic or an intentional bootstrap path
seeds the DO; that is a bootstrap gap, not a silent pass. Truncated inventories
fail closed (`parity` / `mirrorLeaseParity` false) so operators re-run or raise
the bounded page cap rather than approve a partial compare.

Module wiring: `consumeDailyEntitlement`, `refundDailyEntitlement`, and
`readDailyEntitlementResourceUsage` require `env.USER_METER` and fail closed
when the binding is missing. Storage-byte helpers (`readUserD1StorageBytes`,
Expand Down
Loading
Loading