Skip to content

Commit 29c4a18

Browse files
committed
test: ledger the bucket echo enumeration's producer calls and turn the runtime dry-run pin
The client envelope-caller census gains a NOT_SDK row for the two analytics.query sites in service-analytics' new bucket echo enumeration pin (section 2: 9 to 11 service sites; section 3: 9 to 11 not-SDK), and the file is declared by name in @objectstack/client#test's cross-package test inputs, beside the date-bucket echo pin. runtime's authored-cube pin asserted 200 and date_trunc from POST /analytics/sql on a host that wires no dateBucketSql hook. That dry run now answers the declared refusal, NOT_IMPLEMENTED / 501, whose kept message names the bucket (the declared month, the stated year) and the cause. Claude-Session: https://claude.ai/code/session_01DiCSbmJrkzNhuEAier4VoJ Co-authored-by: Claude <noreply@anthropic.com>
1 parent 0b10763 commit 29c4a18

4 files changed

Lines changed: 42 additions & 9 deletions

File tree

‎packages/client/src/envelope-caller-census.test.ts‎

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -493,6 +493,12 @@ const LEDGER: readonly LedgerRow[] = [
493493
method: 'analytics.query', receiver: 'service', count: 1, verdict: 'NOT_SDK',
494494
why: 'the real AnalyticsService that AnalyticsServicePlugin registers over a live engine, called directly (no HTTP, no dispatcher envelope) to read the ObjectQL face\'s rows and the echoed `sql` it runs against them',
495495
},
496+
// ── [#21647] the bucket echo's driver x timezone x granularity enumeration: producer reads only ──
497+
{
498+
file: 'packages/services/service-analytics/src/__tests__/objectql-echo-bucket-enumeration.test.ts',
499+
method: 'analytics.query', receiver: 'service', count: 2, verdict: 'NOT_SDK',
500+
why: 'the real AnalyticsService that AnalyticsServicePlugin registers over an ObjectQL engine with the driver\'s data doors spied, called directly (no HTTP, no dispatcher envelope) to read whether the ObjectQL face\'s answer carries an echoed `sql`, and its rows',
501+
},
496502
{
497503
file: 'packages/client/src/analytics-automation-json-erasure.test.ts',
498504
method: 'analytics.meta', receiver: 'sdk', count: 2, verdict: 'PAYLOAD_DEPENDENT',
@@ -699,11 +705,15 @@ describe('#13079 §2 — positive controls on the matcher itself', () => {
699705
// the real AnalyticsService that `AnalyticsServicePlugin` registers
700706
// over a live engine, to read the ObjectQL face's rows beside its
701707
// echoed `sql`. Its receiver is that service, not the client.
702-
expect(service.length, literalNote()).toBe(9);
708+
// [#21647] A fifth, two sites: the bucket echo's enumeration pin calls
709+
// the same plugin-registered AnalyticsService, over an engine with the
710+
// driver's data doors spied, to read whether the answer carries `sql`.
711+
expect(service.length, literalNote()).toBe(11);
703712
expect([...new Set(service.map((s) => s.file))].sort()).toEqual([
704713
'packages/client/src/analytics-automation-json-erasure.test.ts',
705714
'packages/drivers/driver-memory/src/memory-exists-non-boolean-refusal.test.ts',
706715
'packages/rest/src/analytics-nested-relation-filter.test.ts',
716+
'packages/services/service-analytics/src/__tests__/objectql-echo-bucket-enumeration.test.ts',
707717
'packages/services/service-analytics/src/__tests__/objectql-echo-date-bucket.test.ts',
708718
]);
709719
expect(service.every((s) => s.method === 'analytics.query')).toBe(true);
@@ -751,11 +761,12 @@ describe('#13079 §3 — every call site is classified', () => {
751761
expect(production, literalNote()).toEqual([]);
752762
});
753763

754-
it('records the split: 18 payload pins, 10 result-insensitive, 9 not-SDK', () => {
764+
it('records the split: 18 payload pins, 10 result-insensitive, 11 not-SDK', () => {
755765
expect(verdictTotal('PAYLOAD_DEPENDENT')).toBe(18);
756766
expect(verdictTotal('RESULT_INSENSITIVE')).toBe(10);
757767
// [#21441] 8 -> 9: the date-bucket echo pin's producer call (§2).
758-
expect(verdictTotal('NOT_SDK')).toBe(9);
768+
// [#21647] 9 -> 11: the bucket echo enumeration's two producer calls (§2).
769+
expect(verdictTotal('NOT_SDK')).toBe(11);
759770
// The three above are LEDGER sums and cannot move on a census reading;
760771
// this one is census-derived, so it carries the note. [#13874]
761772
expect(sdkSites.length, literalNote()).toBe(28);

‎packages/runtime/src/analytics-authored-cube-format-granularity.test.ts‎

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,19 @@ describe('an authored time dimension\'s single declared granularity is its defau
144144
expect(res.body.data.rows).toEqual([{ placed_at: '2026-07', count: 2 }]);
145145
});
146146

147-
it('POST /analytics/sql dry-runs the bucketed statement, and a stated granularity still wins', async () => {
147+
// [#21647] This case asserted 200 and `date_trunc('month'` / `date_trunc('year'`:
148+
// the representative bucket the SQL echo printed for a host with no
149+
// `dateBucketSql` hook, which no driver groups by. This host composes the
150+
// service directly, with no hook and no driver behind it, so the dry run now
151+
// answers the service's declared refusal (`NOT_IMPLEMENTED` / 501,
152+
// `refusal: true` at throw time). This exit reads that declaration to keep
153+
// the producer's message instead of withholding a 5xx as a fault, so the
154+
// message reaching the wire IS the declaration's effect: it names the bucket
155+
// it refused and the cause, the declared default for the first request and
156+
// the stated granularity for the second. Where a hook answers, the
157+
// service-level pin (`service-analytics` `cube-authored-format-granularity.test.ts`)
158+
// asserts the driver's expression.
159+
it('POST /analytics/sql dry-runs the bucket at the declared granularity, and a stated granularity still wins (no dateBucketSql hook: the declared refusal)', async () => {
148160
const declared = await post(analytics().service, 'sql', { cube: 'orders', measures: ['count'], dimensions: ['placed_at'] });
149161
const stated = await post(analytics().service, 'sql', {
150162
cube: 'orders',
@@ -153,9 +165,12 @@ describe('an authored time dimension\'s single declared granularity is its defau
153165
timeDimensions: [{ dimension: 'placed_at', granularity: 'year' }],
154166
});
155167

156-
expect(declared.statusCode).toBe(200);
157-
expect(declared.body.data.sql).toMatch(/date_trunc\('month'/i);
158-
expect(stated.statusCode).toBe(200);
159-
expect(stated.body.data.sql).toMatch(/date_trunc\('year'/i);
168+
for (const [res, granularity] of [[declared, 'month'], [stated, 'year']] as const) {
169+
expect(res.statusCode, granularity).toBe(501);
170+
expect(res.body.success, granularity).toBe(false);
171+
expect(res.body.error.code, granularity).toBe('NOT_IMPLEMENTED');
172+
expect(res.body.error.message, granularity).toContain(`"${granularity}" bucket of "placed_at"`);
173+
expect(res.body.error.message, granularity).toContain('dateBucketSql');
174+
}
160175
});
161176
});

‎scripts/cross-package-test-inputs.mjs‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -765,6 +765,12 @@ export const CROSS_PACKAGE_TEST_INPUTS = {
765765
// `service`). A call added to or removed from that file moves the census
766766
// verdict, so a change to it has to re-run this suite.
767767
'packages/services/service-analytics/src/__tests__/objectql-echo-date-bucket.test.ts',
768+
// [#21647] Declared by name for the same reason: the census LEDGER
769+
// carries a NOT_SDK row for service-analytics' bucket echo enumeration
770+
// pin, which calls `analytics.query(` twice on the real AnalyticsService
771+
// (receiver `service`). A call added to or removed from that file moves
772+
// the census verdict, so a change to it has to re-run this suite.
773+
'packages/services/service-analytics/src/__tests__/objectql-echo-bucket-enumeration.test.ts',
768774
],
769775
heldBy: {
770776
// `scripts/**` is rostered TODAY through the census's own

‎turbo.json‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,8 @@
262262
"$TURBO_ROOT$/scripts/**",
263263
"$TURBO_ROOT$/packages/rest/src/analytics-nested-relation-filter.test.ts",
264264
"$TURBO_ROOT$/packages/drivers/driver-memory/src/memory-exists-non-boolean-refusal.test.ts",
265-
"$TURBO_ROOT$/packages/services/service-analytics/src/__tests__/objectql-echo-date-bucket.test.ts"
265+
"$TURBO_ROOT$/packages/services/service-analytics/src/__tests__/objectql-echo-date-bucket.test.ts",
266+
"$TURBO_ROOT$/packages/services/service-analytics/src/__tests__/objectql-echo-bucket-enumeration.test.ts"
266267
]
267268
},
268269
"@objectstack/lint#test": {

0 commit comments

Comments
 (0)