|
5 | 5 | * |
6 | 6 | * Owns what `ObjectQLPlugin` historically assembled inline: the |
7 | 7 | * `ObjectStackProtocolImplementation` construction + `protocol` service |
8 | | - * registration, the metadata-storage platform objects, and the lightweight |
9 | | - * `analytics` fallback. Registering it NEXT TO `ObjectQLPlugin` (with |
| 8 | + * registration and the metadata-storage platform objects. (The lightweight |
| 9 | + * `analytics` fallback that used to ride here was retired in #3891 — see |
| 10 | + * {@link assembleMetadataProtocol}.) Registering it NEXT TO `ObjectQLPlugin` (with |
10 | 11 | * `registerProtocol: false` on the engine plugin) makes `@objectstack/objectql` |
11 | 12 | * effectively protocol-free at boot-assembly level — the engine plugin keeps |
12 | 13 | * only protocol CONSUMERS (DB hydration + authored hook/action rebind, both of |
|
22 | 23 | */ |
23 | 24 |
|
24 | 25 | import type { Plugin, PluginContext } from '@objectstack/core'; |
25 | | -import { SERVICE_SELF_INFO_KEY, type ServiceSelfInfo } from '@objectstack/spec/api'; |
26 | 26 | import { |
27 | 27 | SysMetadataObject, |
28 | 28 | SysMetadataHistoryObject, |
@@ -73,12 +73,19 @@ export function createMetadataProtocolPlugin(options: MetadataProtocolPluginOpti |
73 | 73 |
|
74 | 74 | /** |
75 | 75 | * The ONE protocol assembly (ADR-0076 Step 2 PR-C): metadata-storage platform |
76 | | - * objects + `ObjectStackProtocolImplementation` as the `protocol` service + |
77 | | - * the D12 `degraded` analytics fallback. Called by |
78 | | - * {@link createMetadataProtocolPlugin} (delegated mode) AND by |
| 76 | + * objects + `ObjectStackProtocolImplementation` as the `protocol` service. |
| 77 | + * Called by {@link createMetadataProtocolPlugin} (delegated mode) AND by |
79 | 78 | * `ObjectQLPlugin`'s built-in convenience mode (`registerProtocol !== false`) |
80 | 79 | * — single source, two mounts, identical result. |
81 | 80 | * |
| 81 | + * The `analytics` slot is deliberately NOT filled here (#3891 / #3878, |
| 82 | + * superseding the ADR-0076 D10/D12 "preserve the fallback" stance): the |
| 83 | + * degraded shim dropped the caller's ExecutionContext (no RLS/tenant |
| 84 | + * predicates) and ignored the contract `where` filter, returning full-table |
| 85 | + * aggregates with a 200. An empty slot degrades honestly instead — the |
| 86 | + * dispatcher's `/analytics` domain answers 404 and discovery reports |
| 87 | + * `unavailable` until `AnalyticsServicePlugin` registers the real engine. |
| 88 | + * |
82 | 89 | * @returns the protocol shim, so the engine-side caller can arm its |
83 | 90 | * mutation-rebind subscription synchronously. |
84 | 91 | */ |
@@ -119,42 +126,13 @@ export function assembleMetadataProtocol( |
119 | 126 | ctx.registerService('protocol', protocolShim); |
120 | 127 | ctx.logger.info('Protocol service registered (MetadataProtocolPlugin)'); |
121 | 128 |
|
122 | | - // Lightweight `analytics` fallback mapped onto the protocol shim's |
123 | | - // `analyticsQuery` — kept with the protocol assembly so `/analytics` |
124 | | - // keeps answering on installs without service-analytics. Honest |
125 | | - // capabilities (ADR-0076 D12): self-identifies as `degraded`; |
126 | | - // AnalyticsServicePlugin replaces it (ctx.replaceService) with the |
127 | | - // real engine. |
128 | | - ctx.registerService('analytics', { |
129 | | - [SERVICE_SELF_INFO_KEY]: { |
130 | | - status: 'degraded', |
131 | | - handlerReady: true, |
132 | | - message: 'Lightweight ObjectQL analytics fallback — install @objectstack/service-analytics for the full engine', |
133 | | - } satisfies ServiceSelfInfo, |
134 | | - // HttpDispatcher passes the raw POST body (AnalyticsQuery |
135 | | - // shape); the shim's `analyticsQuery` expects the wrapped |
136 | | - // `{ cube, query }` envelope and returns its own `{ success, |
137 | | - // data }` — reshape in, unwrap out (one level), exactly as the |
138 | | - // historical inline adapter did. |
139 | | - query: async (body: any) => { |
140 | | - const envelope = body && typeof body === 'object' && 'query' in body && 'cube' in body |
141 | | - ? body |
142 | | - : { cube: body?.cube, query: body }; |
143 | | - const result = await protocolShim.analyticsQuery(envelope); |
144 | | - if (result && typeof result === 'object' && 'success' in result && 'data' in result) { |
145 | | - return (result as any).data; |
146 | | - } |
147 | | - return result; |
148 | | - }, |
149 | | - getMeta: async () => ({ |
150 | | - cubes: [], |
151 | | - message: 'Analytics meta endpoint not implemented by ObjectQL adapter', |
152 | | - }), |
153 | | - generateSql: async (_body: any) => ({ |
154 | | - sql: null, |
155 | | - message: 'Analytics SQL generation not implemented by ObjectQL adapter', |
156 | | - }), |
157 | | - }); |
| 129 | + // NO `analytics` fallback rides here anymore (#3891 / #3878). The |
| 130 | + // degraded shim this assembly used to register dropped the request's |
| 131 | + // ExecutionContext (aggregates ran without RLS/tenant predicates) |
| 132 | + // and ignored the contract filter field `where` — a 200 with wrong |
| 133 | + // numbers. The slot now stays empty: `/analytics/*` answers 404 |
| 134 | + // (ROUTE_NOT_FOUND) and discovery reports the service unavailable |
| 135 | + // until @objectstack/service-analytics registers the real engine. |
158 | 136 |
|
159 | 137 | return protocolShim; |
160 | 138 | } |
0 commit comments