From 2a70eb774cd16730c3388f92b30f0d34b3114de2 Mon Sep 17 00:00:00 2001 From: Hassan Abdel-Rahman Date: Sun, 11 Oct 2026 09:52:10 -0400 Subject: [PATCH 1/2] Prepare each grant expression once per compiled policy Co-Authored-By: Claude Opus 5.5 --- .../tests/anonymous-access-test.ts | 57 +++++++++++++++++++ .../tests/realm-policy-anonymous-read-test.ts | 33 +++++++++++ .../card-operations/grant-expressions.ts | 56 ++++++++++++++---- 3 files changed, 134 insertions(+), 12 deletions(-) diff --git a/packages/realm-server/tests/anonymous-access-test.ts b/packages/realm-server/tests/anonymous-access-test.ts index 889180f0a22..1a8bdd21d54 100644 --- a/packages/realm-server/tests/anonymous-access-test.ts +++ b/packages/realm-server/tests/anonymous-access-test.ts @@ -19,6 +19,7 @@ import { import { blocklistCloses, compileGrantExpression, + grantExpressionPreparations, readBlocklist, readRateLimitPart, settleTraffic, @@ -434,6 +435,62 @@ module(basename(import.meta.filename), function () { }); }); + test('a grant expression is prepared once, and reads its context afresh each time', async function (assert) { + let grant = { + blocklist: compiled('blocklist', 'realmConfig("blockedIps")'), + rateLimitRequests: compiled('rateLimitRequests', 'policy("requests")'), + rateLimitWindowSeconds: compiled('rateLimitWindowSeconds', '600'), + }; + let before = grantExpressionPreparations(); + let settled = []; + for (let requests of [5, 6, 7]) { + settled.push( + await settleTraffic( + grant, + { + realmConfig: { blockedIps: `192.0.2.${requests}` }, + policy: { requests }, + }, + PLATFORM, + ), + ); + } + assert.strictEqual( + grantExpressionPreparations() - before, + 3, + 'one preparation for each expression', + ); + assert.deepEqual( + settled.map((traffic) => traffic.limit.requests), + [5, 6, 7], + 'each settlement reads its own policy', + ); + assert.deepEqual( + settled.map((traffic) => blocksAddress(traffic, '192.0.2.6')), + [false, true, false], + 'and its own realm config', + ); + + let failing = compiled('blocklist', 'realmConfig("blockedIps")'); + let beforeFailing = grantExpressionPreparations(); + await settleTraffic( + { blocklist: failing }, + { realmConfig: {} }, + PLATFORM, + ); + let fixed = await settleTraffic( + { blocklist: failing }, + { realmConfig: { blockedIps: CALLER } }, + PLATFORM, + ); + assert.strictEqual( + grantExpressionPreparations() - beforeFailing, + 1, + 'an expression that throws on its values is still prepared once', + ); + assert.true(blocksAddress(fixed, CALLER), 'and settles once they change'); + }); + test('a rate-limit expression that produces no limit leaves that half to the platform', async function (assert) { let grant = { rateLimitRequests: compiled( diff --git a/packages/realm-server/tests/realm-policy-anonymous-read-test.ts b/packages/realm-server/tests/realm-policy-anonymous-read-test.ts index 9ac4442ad4d..daa541c51b0 100644 --- a/packages/realm-server/tests/realm-policy-anonymous-read-test.ts +++ b/packages/realm-server/tests/realm-policy-anonymous-read-test.ts @@ -16,6 +16,7 @@ import type { QueueRunner, Realm, } from '@cardstack/runtime-common'; +import { grantExpressionPreparations } from '@cardstack/runtime-common/card-operations/grant-expressions'; import { setAnonymousRequestSink, type AnonymousRequestEvent, @@ -437,6 +438,38 @@ module(basename(import.meta.filename), function (hooks) { ); }); + test("a grant's blocklist and limit are prepared once and settled for every request", async function (assert) { + await setNewsroomConfig(limitOf(50)); + assert.strictEqual((await readCard(PUBLISHED)).status, 200); + let before = grantExpressionPreparations(); + for (let i = 0; i < 3; i++) { + assert.strictEqual((await readCard(PUBLISHED)).status, 200); + } + assert.strictEqual( + grantExpressionPreparations() - before, + 0, + 'the later reads prepare nothing', + ); + assert.deepEqual( + articleRecords().map((r) => ({ + outcome: r.outcome, + limit: r.limit, + count: r.count, + })), + [1, 2, 3, 4].map((count) => ({ + outcome: 'admitted' as const, + limit: { + requests: 50, + windowSeconds: 600, + requestsFrom: 'grant' as const, + windowSecondsFrom: 'grant' as const, + }, + count, + })), + "every read is counted against the grant's own limit", + ); + }); + test('each grant counts the same address on its own, so one over its limit leaves the others alone', async function (assert) { await setNewsroomConfig(limitOf(1)); assert.strictEqual((await readCard(PUBLISHED)).status, 200); diff --git a/packages/runtime-common/card-operations/grant-expressions.ts b/packages/runtime-common/card-operations/grant-expressions.ts index 259bc8436e1..8323f306c02 100644 --- a/packages/runtime-common/card-operations/grant-expressions.ts +++ b/packages/runtime-common/card-operations/grant-expressions.ts @@ -4,7 +4,11 @@ import { type AddressRange, type AnonymousRateLimit, } from '../anonymous-access.ts'; -import { loadBxlTransform } from './transforms.ts'; +import { + loadBxlTransform, + type BxlTransformModule, + type PreparedTransformProgram, +} from './transforms.ts'; // ============================================================================ // The expressions a grant carries besides its `where`, which settle how it @@ -70,23 +74,51 @@ export async function evaluateGrantExpression( context: GrantExpressionContext, ): Promise { try { - let bxl = await loadBxlTransform(); - let value = bxl.runBxlTransform( - expression.canonical, - null, - { - ...(context.realmConfig ? { realmConfig: context.realmConfig } : {}), - ...(context.policy ? { policy: context.policy } : {}), - ...(context.instance ? { instance: context.instance } : {}), - }, - { syntax: 'solidified' }, - ); + let program = preparedExpression(await loadBxlTransform(), expression); + let value = program.run(null, { + ...(context.realmConfig ? { realmConfig: context.realmConfig } : {}), + ...(context.policy ? { policy: context.policy } : {}), + ...(context.instance ? { instance: context.instance } : {}), + }); return { value }; } catch (e: unknown) { return { failed: errorKind(e) }; } } +// Each expression's program, parsed and checked once and run for every +// request it settles. Keyed on the compiled expression, so a program lives +// exactly as long as the compiled policy that holds it, and a recompiled +// policy prepares its own. An expression that fails to prepare is not held, +// and fails again on its next evaluation. +const preparedExpressions = new WeakMap< + CompiledGrantExpression, + PreparedTransformProgram +>(); + +// How many grant expression programs this process has prepared. A steady +// policy prepares each expression once however many requests settle it. +let preparations = 0; + +export function grantExpressionPreparations(): number { + return preparations; +} + +function preparedExpression( + bxl: BxlTransformModule, + expression: CompiledGrantExpression, +): PreparedTransformProgram { + let program = preparedExpressions.get(expression); + if (!program) { + program = bxl.prepareBxlTransform(expression.canonical, { + syntax: 'solidified', + }); + preparedExpressions.set(expression, program); + preparations++; + } + return program; +} + function errorKind(e: unknown): string { if (!(e instanceof Error)) { return typeof e; From 0645e61db1c68048623a3678bb48ab670e68a60b Mon Sep 17 00:00:00 2001 From: Hassan Abdel-Rahman Date: Sun, 11 Oct 2026 09:57:37 -0400 Subject: [PATCH 2/2] Assert the failing grant expression actually throws when it runs Co-Authored-By: Claude Opus 5.5 --- packages/realm-server/tests/anonymous-access-test.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/realm-server/tests/anonymous-access-test.ts b/packages/realm-server/tests/anonymous-access-test.ts index 1a8bdd21d54..33aec28e304 100644 --- a/packages/realm-server/tests/anonymous-access-test.ts +++ b/packages/realm-server/tests/anonymous-access-test.ts @@ -473,11 +473,16 @@ module(basename(import.meta.filename), function () { let failing = compiled('blocklist', 'realmConfig("blockedIps")'); let beforeFailing = grantExpressionPreparations(); - await settleTraffic( + let unset = await settleTraffic( { blocklist: failing }, { realmConfig: {} }, PLATFORM, ); + assert.strictEqual( + unset.blocklist.failed, + 'BxlTransformError (evaluate)', + 'an absent setting throws when the expression runs', + ); let fixed = await settleTraffic( { blocklist: failing }, { realmConfig: { blockedIps: CALLER } },