@reventlessdev/reventless-aws 3.0.0-alpha.221 → 3.0.0-alpha.223

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -3,6 +3,37 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ # 3.0.0-alpha.223 (2026-07-22)
7
+
8
+ * refactor!: retire the stale "Admin" vocabulary for platform-owned resources ([2770bd9](https://github.com/ReventlessDev/reventless-core/commit/2770bd96f309142bdfc65b9f36bd1a3ef60641bd))
9
+
10
+ ### BREAKING CHANGES
11
+
12
+ * platform-owned resources are renamed Admin* -> Platform*
13
+ (PlatformDcbEventLog, PlatformDcbCmdTopic, PlatformEventColl). This replaces
14
+ a DynamoDB table, an SQS queue and an SNS topic — wipe and redeploy rather
15
+ than migrate. Both alpha AdminDcbEventLog tables held 0 items at the time of
16
+ the rename. MCP resource URI templates change from Admin/<field>/{id} to
17
+ Platform/<field>/{id}; MCP tool names are unaffected.
18
+
19
+
20
+
21
+ # 3.0.0-alpha.222 (2026-07-22)
22
+
23
+ * refactor!: retire the stale "core" vocabulary for platform things ([34e7480](https://github.com/ReventlessDev/reventless-core/commit/34e7480992bd58906a250b0a1ce6ff2c5ba45260))
24
+
25
+ ### BREAKING CHANGES
26
+
27
+ * the built-in extension point is renamed Core.Plugin ->
28
+ Platform.Plugin. This replaces the CorePluginExtPointCmdTopic SQS queue
29
+ with PlatformPluginExtPointCmdTopic (a replacement, not an update) and
30
+ breaks every already-deployed plugin's connection until redeployed.
31
+ Wipe the alpha stack and redeploy fresh rather than migrating.
32
+
33
+ Build clean; 1349 tests green (interop 50, core 518, local 501, aws 280).
34
+
35
+
36
+
6
37
  # 3.0.0-alpha.221 (2026-07-22)
7
38
 
8
39
  ### Features
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reventlessdev/reventless-aws",
3
- "version": "3.0.0-alpha.221",
3
+ "version": "3.0.0-alpha.223",
4
4
  "description": "AWS adapters for Reventless",
5
5
  "license": "Apache-2.0",
6
6
  "dependencies": {
@@ -8,17 +8,17 @@
8
8
  "@aws-sdk/client-cloudfront": "3.970.0",
9
9
  "sury": "11.0.0-alpha.4",
10
10
  "uuid": "^13.0.0",
11
- "@reventlessdev/rescript-effect": "0.1.0-alpha.30",
12
11
  "@reventlessdev/rescript-aws-sdk": "2.2.0-alpha.24",
12
+ "@reventlessdev/rescript-effect": "0.1.0-alpha.30",
13
13
  "@reventlessdev/rescript-jest": "1.0.0-alpha.9",
14
- "@reventlessdev/rescript-pulumi-aws": "2.4.0-alpha.57",
15
14
  "@reventlessdev/rescript-pulumi-pulumi": "2.3.0-alpha.17",
16
- "@reventlessdev/reventless-core": "3.0.0-alpha.175",
17
- "@reventlessdev/reventless-infra": "3.0.0-alpha.103",
18
- "@reventlessdev/reventless-postgres": "3.0.0-alpha.39",
19
- "@reventlessdev/reventless-spec": "3.0.0-alpha.80",
15
+ "@reventlessdev/rescript-pulumi-aws": "2.4.0-alpha.57",
20
16
  "@reventlessdev/rescript-uuid": "1.1.0-alpha.17",
21
- "@reventlessdev/reventless-interop": "3.0.0-alpha.28"
17
+ "@reventlessdev/reventless-core": "3.0.0-alpha.177",
18
+ "@reventlessdev/reventless-spec": "3.0.0-alpha.80",
19
+ "@reventlessdev/reventless-interop": "3.0.0-alpha.29",
20
+ "@reventlessdev/reventless-postgres": "3.0.0-alpha.41",
21
+ "@reventlessdev/reventless-infra": "3.0.0-alpha.104"
22
22
  },
23
23
  "devDependencies": {
24
24
  "rescript": "12.3.0",
package/src/Platform.res CHANGED
@@ -154,7 +154,7 @@ module MakeWithConfig = (
154
154
  let adminSourceSdl = (): string =>
155
155
  assembleCanonicalSourceSdl(
156
156
  ~baseFragment=AppSync_Adapter.injectAwsAuthAll(
157
- ReventlessCore.AdminApi.baseFragment(~cloner=Config.cloner),
157
+ ReventlessCore.Platform_AdminApi.baseFragment(~cloner=Config.cloner),
158
158
  ~group="Admin",
159
159
  ),
160
160
  )
@@ -234,7 +234,7 @@ module MakeWithConfig = (
234
234
 
235
235
  // Populate apiConfig with both domain and platform API references.
236
236
  // In platform/monolithic mode, platformApi starts as domainApi and is updated
237
- // by deployPlatform/makePlatform once the core API resource is created (split mode).
237
+ // by deployPlatform/makePlatform once the platform API resource is created (split mode).
238
238
  let () = apiConfigRef := Some({
239
239
  domainApi: domainApi,
240
240
  domainApiRole: domainApiRole,
@@ -850,7 +850,7 @@ module MakeWithConfig = (
850
850
  // admin-prefixed `Platform_Plugin` / `Platform_Plugins` SDL fields declared by
851
851
  // PluginBaseFragment.queryEntries. Field-name alignment is handled by the
852
852
  // queryFieldNamesRegistry entries that Platform_Admin.construct populates
853
- // from AdminApi.queryEntries before this builder runs.
853
+ // from Platform_AdminApi.queryEntries before this builder runs.
854
854
  module PluginReadModel = ReadModel_Builder_Single_Stream.Make(
855
855
  ReventlessCore.PluginsReadModelSpec,
856
856
  PluginReadModelMappings,
@@ -980,7 +980,7 @@ module MakeWithConfig = (
980
980
  }
981
981
  }
982
982
 
983
- // In split mode, create a dedicated core AppSync API and push the core schema.
983
+ // In split mode, create a dedicated platform AppSync API and push the platform schema.
984
984
  // In unified mode, makePlatform is a no-op (schema stitching handled by events).
985
985
  let makePlatform = (~version, ~plugins: array<module(PluginMaker)>) => {
986
986
  log.info(~comp="Platform", `v${version}`)
@@ -1124,7 +1124,7 @@ module MakeWithConfig = (
1124
1124
 
1125
1125
  module PluginExtensionPoint = Plugin_ExtensionPoint_Builder.MakeWithConfig({
1126
1126
  // Cross-plugin SNS subscription management runs in the bundled
1127
- // AdminEventCollector Lambda (AdminEventCollectorEntryPoint.mjs), not in
1127
+ // AdminEventCollector Lambda (EventCollectorEntryPoint.mjs), not in
1128
1128
  // this deploy-time EP Lambda — which only handles incoming commands
1129
1129
  // (Heartbeat, ForwardCommand). None here keeps the deploy-time path
1130
1130
  // unchanged; the .mjs entry point supplies a real implementation.
@@ -15,7 +15,6 @@ import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js
15
15
  import * as Plugin$ReventlessAws from "./components/Plugin.res.mjs";
16
16
  import * as Logger$ReventlessCore from "@reventlessdev/reventless-core/src/util/Logger.res.mjs";
17
17
  import * as Message$ReventlessCore from "@reventlessdev/reventless-core/src/Message.res.mjs";
18
- import * as AdminApi$ReventlessCore from "@reventlessdev/reventless-core/src/admin/AdminApi.res.mjs";
19
18
  import * as Scheduler$ReventlessAws from "./components/Scheduler.res.mjs";
20
19
  import * as Aggregate$ReventlessCore from "@reventlessdev/reventless-core/src/components/Aggregate/Aggregate.res.mjs";
21
20
  import * as Component$ReventlessCore from "@reventlessdev/reventless-core/src/components/Component.res.mjs";
@@ -44,6 +43,7 @@ import * as NoEventMappings$ReventlessInfra from "@reventlessdev/reventless-infr
44
43
  import * as Util_HostUiDomain$ReventlessAws from "./util/Util_HostUiDomain.res.mjs";
45
44
  import * as DcbEventLogStorage$ReventlessAws from "./adapter/DcbEventLog/DcbEventLogStorage.res.mjs";
46
45
  import * as ExtensionMapping$ReventlessInfra from "@reventlessdev/reventless-infra/src/types/ExtensionMapping.res.mjs";
46
+ import * as Platform_AdminApi$ReventlessCore from "@reventlessdev/reventless-core/src/admin/Platform_AdminApi.res.mjs";
47
47
  import * as PluginsProjection$ReventlessCore from "@reventlessdev/reventless-core/src/plugin/lifecycle/PluginsProjection.res.mjs";
48
48
  import * as StateTopic_AppSync$ReventlessAws from "./adapter/StateTopic/StateTopic_AppSync.res.mjs";
49
49
  import * as AppSync_SdlDecorate$ReventlessAws from "./components/Api/AppSync_SdlDecorate.res.mjs";
@@ -148,7 +148,7 @@ function MakeWithConfig(Config) {
148
148
  subscriptionSources: []
149
149
  });
150
150
  let adminSourceSdl = () => {
151
- let baseFragment = AppSync_Adapter$ReventlessAws.injectAwsAuthAll(AdminApi$ReventlessCore.baseFragment(Config.cloner), "Admin", undefined);
151
+ let baseFragment = AppSync_Adapter$ReventlessAws.injectAwsAuthAll(Platform_AdminApi$ReventlessCore.baseFragment(Config.cloner), "Admin", undefined);
152
152
  return AppSync_SdlDecorate$ReventlessAws.stampCanonicalTypes(AppSync_Adapter$ReventlessAws.stitchStandaloneWithAwsDirectives(baseFragment));
153
153
  };
154
154
  let match;
@@ -1123,7 +1123,7 @@ function Make($star) {
1123
1123
  subscriptionSources: []
1124
1124
  });
1125
1125
  let adminSourceSdl = () => {
1126
- let baseFragment = AppSync_Adapter$ReventlessAws.injectAwsAuthAll(AdminApi$ReventlessCore.baseFragment(false), "Admin", undefined);
1126
+ let baseFragment = AppSync_Adapter$ReventlessAws.injectAwsAuthAll(Platform_AdminApi$ReventlessCore.baseFragment(false), "Admin", undefined);
1127
1127
  return AppSync_SdlDecorate$ReventlessAws.stampCanonicalTypes(AppSync_Adapter$ReventlessAws.stitchStandaloneWithAwsDirectives(baseFragment));
1128
1128
  };
1129
1129
  let match;
@@ -190,7 +190,7 @@ let makeDcb = (
190
190
  ~fieldNames: array<string>,
191
191
  ~tags: array<string>,
192
192
  // Admin (onAdminApi) DCB slices expose ONLY their mutation fields (declared in the
193
- // static AdminApi.baseFragment). The static base does NOT declare their `on<Field>`
193
+ // static Platform_AdminApi.baseFragment). The static base does NOT declare their `on<Field>`
194
194
  // subscription counterparts, so creating Source-C subscription resolvers would fail
195
195
  // with CreateResolver NotFound. Suppress subscriptions for admin; plugins keep them
196
196
  // (their generated fragment declares the matching subscription fields).
@@ -102,11 +102,11 @@ let generateConfig = (
102
102
  {serverName, serverVersion, tools, resources, eventHistoryResources}
103
103
  }
104
104
 
105
- /** Generate the core-only MCP config for split mode.
106
- Contains only core administrative tools (Plugin_Activate, Plugin_Deactivate, Clone)
107
- and core resources (Plugin, Plugins). No plugin-contributed entries.
105
+ /** Generate the platform-only MCP config for split mode.
106
+ Contains only platform administrative tools (Plugin_Activate, Plugin_Deactivate, Clone)
107
+ and platform resources (Plugin, Plugins). No plugin-contributed entries.
108
108
 
109
- The commandTopicArns and queryDbTableNames must map core field names to their
109
+ The commandTopicArns and queryDbTableNames must map platform field names to their
110
110
  corresponding AWS resource ARNs/names. When Lambda Function URL deployment is
111
111
  available (Step 13), these will be wired from Pulumi stack outputs. */
112
112
  let generateAdminConfig = (
@@ -119,8 +119,10 @@ let generateAdminConfig = (
119
119
  generateConfig(
120
120
  ~serverName=`${serverName}-admin`,
121
121
  ~serverVersion,
122
- ~pluginName="Admin",
123
- ~mutationEntries=ReventlessCore.AdminApi.mutationEntries(~cloner),
122
+ // Must match what Platform_Admin.construct registers — it forms the resource URI
123
+ // templates (`<pluginName>/<field>/{id}`) that MCP clients address.
124
+ ~pluginName=ReventlessCore.Platform_Admin_Structure.pluginId,
125
+ ~mutationEntries=ReventlessCore.Platform_AdminApi.mutationEntries(~cloner),
124
126
  ~queryEntries=ReventlessCore.PluginBaseFragment.queryEntries,
125
127
  ~commandTopicArns,
126
128
  ~queryDbTableNames,
@@ -11,11 +11,12 @@ import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js
11
11
  import * as AWS$ReventlessAws from "../AWS.res.mjs";
12
12
  import * as Identity$Reventless from "@reventlessdev/reventless-spec/src/types/Identity.res.mjs";
13
13
  import * as Runtime$ReventlessCore from "@reventlessdev/reventless-core/src/adapter/Runtime/Runtime.res.mjs";
14
- import * as AdminApi$ReventlessCore from "@reventlessdev/reventless-core/src/admin/AdminApi.res.mjs";
15
14
  import * as DynamoDb_Error$ReventlessAws from "../../errors/DynamoDb_Error.res.mjs";
15
+ import * as Platform_AdminApi$ReventlessCore from "@reventlessdev/reventless-core/src/admin/Platform_AdminApi.res.mjs";
16
16
  import * as PluginBaseFragment$ReventlessCore from "@reventlessdev/reventless-core/src/plugin/api/PluginBaseFragment.res.mjs";
17
17
  import * as MCP_SchemaGenerator$ReventlessCore from "@reventlessdev/reventless-core/src/components/Api/MCP_SchemaGenerator.res.mjs";
18
18
  import * as Util_DynamoDb_Runtime$ReventlessAws from "../../util/Util_DynamoDb_Runtime.res.mjs";
19
+ import * as Platform_Admin_Structure$ReventlessCore from "@reventlessdev/reventless-core/src/admin/Platform_Admin_Structure.res.mjs";
19
20
  import * as DcbEventLogStorage_DynamoDb_Runtime$ReventlessAws from "../DcbEventLog/DcbEventLogStorage_DynamoDb_Runtime.res.mjs";
20
21
  import * as CommandTopicChannel_SQS_RuntimeResMjs from "@reventlessdev/reventless-aws/src/adapter/CommandTopic/CommandTopicChannel_SQS_Runtime.res.mjs";
21
22
  import * as CommandGenerator_CallbackResMjs from "@reventlessdev/reventless-core/src/components/CommandGenerator/CommandGenerator_Callback.res.mjs";
@@ -69,7 +70,7 @@ function generateAdminConfig(serverName, serverVersion, clonerOpt, commandTopicA
69
70
  let cloner = clonerOpt !== undefined ? clonerOpt : false;
70
71
  let commandTopicArns = commandTopicArnsOpt !== undefined ? commandTopicArnsOpt : ({});
71
72
  let queryDbTableNames = queryDbTableNamesOpt !== undefined ? queryDbTableNamesOpt : ({});
72
- return generateConfig(serverName + `-admin`, serverVersion, "Admin", AdminApi$ReventlessCore.mutationEntries(cloner), PluginBaseFragment$ReventlessCore.queryEntries, undefined, commandTopicArns, queryDbTableNames, undefined);
73
+ return generateConfig(serverName + `-admin`, serverVersion, Platform_Admin_Structure$ReventlessCore.pluginId, Platform_AdminApi$ReventlessCore.mutationEntries(cloner), PluginBaseFragment$ReventlessCore.queryEntries, undefined, commandTopicArns, queryDbTableNames, undefined);
73
74
  }
74
75
 
75
76
  function extractEntityId(uri) {
@@ -2,7 +2,7 @@
2
2
  //
3
3
  // Drains a Postgres DCB log via `PgChangeFeed` and pushes each event — transformed
4
4
  // into the `{id, meta, event}` shape the plugin EventCollector SQS handler
5
- // consumes — onto that queue. The plugin EventCollector (`AdminEventCollectorEntryPoint`)
5
+ // consumes — onto that queue. The plugin EventCollector (`EventCollectorEntryPoint`)
6
6
  // then drives the full fan-out: read-model projections, aggregate command topics,
7
7
  // and the cross-plugin SNS EventTopic. See
8
8
  // docs/plans/aws-postgres-change-feed-bridge.md.
@@ -1,12 +1,12 @@
1
- // Plugin EventCollector Lambda entry point — shared between the admin and every
2
- // per-plugin EventCollector Lambda. Despite the historical "Admin" filename, this
3
- // module is plugin-agnostic: behaviour is driven entirely by HANDLER_CONFIG.
1
+ // Plugin EventCollector Lambda entry point — shared between the platform and every
2
+ // per-plugin EventCollector Lambda. This module is plugin-agnostic: behaviour is
3
+ // driven entirely by HANDLER_CONFIG.
4
4
  //
5
5
  // HANDLER_CONFIG schema (JSON in env var "HANDLER_CONFIG"):
6
6
  //
7
7
  // {
8
8
  // "queueUrl": string // SQS URL of the EventCollector this Lambda drains
9
- // "pluginExtensionPointCmdTopicUrl":string // SQS URL of CorePluginExtPoint cmd topic (admin's Plugin EP)
9
+ // "pluginExtensionPointCmdTopicUrl":string // SQS URL of PlatformPluginExtPoint cmd topic (admin's Plugin EP)
10
10
  // "eventTopicArn": string // SNS ARN the EP's outgoing events publish to ("NOT_AVAILABLE" if none)
11
11
  // "pluginReadModelTableName": string // DynamoDB table for Plugin RM (used by QueryEngine.scan)
12
12
  // "pluginSchemaPersistenceTableName":string // DynamoDB table holding deploy-time SDL fragments
@@ -30,7 +30,7 @@
30
30
  // "connectExtension": { // The auto-included PluginConnectExtension entry; null for admin Lambda
31
31
  // "specModule": string,
32
32
  // "mappingsModule": string,
33
- // "extensionPointName": string // service key for incomingConnectExtensionEventHandlers (e.g. "Core.Plugin")
33
+ // "extensionPointName": string // service key for incomingConnectExtensionEventHandlers (e.g. "Platform.Plugin")
34
34
  // } | null,
35
35
  // "extensions": [ // User-declared extensions — wired into incoming/outgoing dicts at cold start
36
36
  // {
@@ -411,7 +411,7 @@ function loadUiFragments() {
411
411
  // Cross-plugin spec packages (e.g. "@reventlessdev/online-shop-hybrid-catalog-spec")
412
412
  // are bundled into the function asset under /var/task/node_modules/ by
413
413
  // PluginRuntime_Builder.forPluginEventCollector. This entry-point file, however,
414
- // lives in the Lambda LAYER at /opt/nodejs/node_modules/.../AdminEventCollectorEntryPoint.mjs,
414
+ // lives in the Lambda LAYER at /opt/nodejs/node_modules/.../EventCollectorEntryPoint.mjs,
415
415
  // so a bare `await import("@reventlessdev/online-shop-hybrid-catalog-spec/...")`
416
416
  // from here resolves through /opt/nodejs/node_modules/ and never reaches the
417
417
  // function asset. Anchoring createRequire at file:///var/task/index.mjs makes
@@ -585,7 +585,7 @@ async function buildHandler() {
585
585
  // it through ExtensionMapping.Make, and build per-extension Extension_Operations.
586
586
  const userExtensionHandlers = await Promise.all(config.extensions.map(async (ext) => {
587
587
  if (!ext.specModule || !ext.mappingsModule || !ext.delegateModule) {
588
- log.warn("extension '" + ext.name + "' missing module specifier(s); skipping. specModule=" + ext.specModule + ", mappingsModule=" + ext.mappingsModule + ", delegateModule=" + ext.delegateModule, { comp: "AdminEventCollectorEntryPoint" });
588
+ log.warn("extension '" + ext.name + "' missing module specifier(s); skipping. specModule=" + ext.specModule + ", mappingsModule=" + ext.mappingsModule + ", delegateModule=" + ext.delegateModule, { comp: "EventCollectorEntryPoint" });
589
589
  return null;
590
590
  }
591
591
  const epSpec = patchSpecId(await importFromAsset(ext.specModule));
@@ -7,7 +7,7 @@
7
7
  // STITCHED schema at push time — the additive counterpart of the neutral
8
8
  // emission, mirroring how `injectAwsAuthAll`/`stampSharedIamTypes` decorate
9
9
  // auth. Runtime-pure so the bundled Lambda entry points
10
- // (AdminEventCollectorEntryPoint.mjs) can import it without dragging
10
+ // (EventCollectorEntryPoint.mjs) can import it without dragging
11
11
  // deploy-time dependencies into the runtime module graph.
12
12
 
13
13
  /**
@@ -375,7 +375,7 @@ export function response(ctx) {
375
375
  }
376
376
  `->Pulumi.Input.make
377
377
 
378
- let field = ReventlessCore.AdminApi.cloneMutationEntry.fieldNames->Array.getUnsafe(0)
378
+ let field = ReventlessCore.Platform_AdminApi.cloneMutationEntry.fieldNames->Array.getUnsafe(0)
379
379
  let resolver = AppSync_Resolver_Retrying.makeUnitJsResolver(
380
380
  ~name=field,
381
381
  ~api,
@@ -11,11 +11,11 @@ import * as AWS$ReventlessAws from "../../adapter/AWS.res.mjs";
11
11
  import * as Cloner$ReventlessCore from "@reventlessdev/reventless-core/src/components/Cloner.res.mjs";
12
12
  import * as AWS_Tags$ReventlessAws from "../../adapter/AWS_Tags.res.mjs";
13
13
  import * as Util_Vpc$ReventlessAws from "../../util/Util_Vpc.res.mjs";
14
- import * as AdminApi$ReventlessCore from "@reventlessdev/reventless-core/src/admin/AdminApi.res.mjs";
15
14
  import * as PolicyDocument$PulumiAws from "@reventlessdev/rescript-pulumi-aws/src/IAM/PolicyDocument.res.mjs";
16
15
  import * as Util_Bundle$ReventlessAws from "../../util/Util_Bundle.res.mjs";
17
16
  import * as GetSecretVersion$PulumiAws from "@reventlessdev/rescript-pulumi-aws/src/SecretsManager/GetSecretVersion.res.mjs";
18
17
  import * as Util_AppSync$ReventlessAws from "../../util/Util_AppSync.res.mjs";
18
+ import * as Platform_AdminApi$ReventlessCore from "@reventlessdev/reventless-core/src/admin/Platform_AdminApi.res.mjs";
19
19
  import * as AppSync_Resolver_Retrying$ReventlessAws from "../../adapter/Api/AppSync_Resolver_Retrying.res.mjs";
20
20
 
21
21
  function make(name, api, fullQualifiedStackName, reventlessCiSecretUrn, secretUrns, opts) {
@@ -226,7 +226,7 @@ export const handler = async (event) => {
226
226
  },
227
227
  serviceRoleArn: dataSourceRole.arn
228
228
  }, opts);
229
- let field = AdminApi$ReventlessCore.cloneMutationEntry.fieldNames[0];
229
+ let field = Platform_AdminApi$ReventlessCore.cloneMutationEntry.fieldNames[0];
230
230
  let resolver = AppSync_Resolver_Retrying$ReventlessAws.makeUnitJsResolver(field, api, dataSource.name, "Mutation", field, `import { util } from '@aws-appsync/utils';
231
231
  export function request(ctx) {
232
232
  return {
@@ -14,7 +14,7 @@ let make: ReventlessCore.Heartbeat_Adapter.runnerMaker<runtimeParts> = (
14
14
  EventRule.make(
15
15
  ~name=Pulumi.Pulumi.getStackName() ++ ("-" ++ name),
16
16
  ~args={
17
- description: "Send a heartbeat to the Core Plugin ExtensionPoint"->Pulumi.Input.make,
17
+ description: "Send a heartbeat to the Platform Plugin ExtensionPoint"->Pulumi.Input.make,
18
18
  scheduleExpression: EventRule.ScheduleExpression.every(timeout->Minutes),
19
19
  tags: AWS.Tags.make(
20
20
  ~name=Pulumi.Pulumi.getStackName() ++ ("-" ++ name),
@@ -29,14 +29,14 @@ let make: ReventlessCore.Heartbeat_Adapter.runnerMaker<runtimeParts> = (
29
29
 
30
30
  let lambda = runtime.parts.lambda
31
31
  let lambdaRole = runtime.parts.lambdaRole
32
- let coreSqsQueue = remoteChannel.resources->Util_SQS.findResolvedResource
32
+ let platformSqsQueue = remoteChannel.resources->Util_SQS.findResolvedResource
33
33
 
34
- // Grant sqs:SendMessage on the Core Plugin ExtensionPoint command topic at
35
- // TOP LEVEL. Previously this RolePolicy was created inside the
34
+ // Grant sqs:SendMessage on the Platform Plugin ExtensionPoint command topic
35
+ // at TOP LEVEL. Previously this RolePolicy was created inside the
36
36
  // `Pulumi.Output.apply` below — and a resource created inside an apply
37
37
  // callback does not reliably register with the engine, which intermittently
38
- // left the heartbeat Lambda without this grant (IAM AccessDenied:
39
- // `sqs:sendmessage on CorePluginExtPointCmdTopic`). `coreSqsQueue.urn` is an
38
+ // left the heartbeat Lambda without this grant (IAM AccessDenied on the
39
+ // extension point's command-topic queue). `platformSqsQueue.urn` is an
40
40
  // already-resolved ARN string from the remote channel and `lambdaRole.id` an
41
41
  // Output, so neither needs an apply. Mirrors the EC `pta` grant fix — see
42
42
  // docs/analysis/ec-publish-to-aggregates-grant-broken.md.
@@ -48,7 +48,7 @@ let make: ReventlessCore.Heartbeat_Adapter.runnerMaker<runtimeParts> = (
48
48
  sid: "AllowLambdaToSendSQS",
49
49
  effect: Allow,
50
50
  actions: Action("sqs:SendMessage"),
51
- resources: Resource(coreSqsQueue.urn),
51
+ resources: Resource(platformSqsQueue.urn),
52
52
  },
53
53
  ],
54
54
  )
@@ -20,7 +20,7 @@ import * as Cloudwatch_EventTarget$PulumiAws from "@reventlessdev/rescript-pulum
20
20
  function make(name, remoteChannel, timeout, runtime, opts) {
21
21
  let opts$1 = Util_Pulumi$ReventlessCore.ComponentResourceOptions.toCustomResourceOptions(opts);
22
22
  let cloudwatchEventRule = new (Aws.cloudwatch.EventRule)(Pulumi.getStack() + ("-" + name), {
23
- description: "Send a heartbeat to the Core Plugin ExtensionPoint",
23
+ description: "Send a heartbeat to the Platform Plugin ExtensionPoint",
24
24
  scheduleExpression: Primitive_option.some(Cloudwatch_EventRule$PulumiAws.ScheduleExpression.every({
25
25
  TAG: "Minutes",
26
26
  _0: timeout
@@ -29,12 +29,12 @@ function make(name, remoteChannel, timeout, runtime, opts) {
29
29
  }, opts$1);
30
30
  let lambda = runtime.parts.lambda;
31
31
  let lambdaRole = runtime.parts.lambdaRole;
32
- let coreSqsQueue = Util_SQS$ReventlessAws.findResolvedResource(remoteChannel.resources);
32
+ let platformSqsQueue = Util_SQS$ReventlessAws.findResolvedResource(remoteChannel.resources);
33
33
  let heartbeatLambdaSendMessagePolicyDocument = PolicyDocument$PulumiAws.make(undefined, undefined, [{
34
34
  Sid: "AllowLambdaToSendSQS",
35
35
  Effect: "Allow",
36
36
  Action: "sqs:SendMessage",
37
- Resource: coreSqsQueue.urn
37
+ Resource: platformSqsQueue.urn
38
38
  }]);
39
39
  new (Aws.iam.RolePolicy)(name + "RolePolicy", {
40
40
  policy: PolicyDocument$PulumiAws.mergePolicyDocuments(name + "Policy", [
@@ -118,7 +118,7 @@ let registerConfig = (
118
118
 
119
119
  // PluginRuntime_Builder is a functor so that the caller can inject the EventCollectorChannel
120
120
  // implementation. All other runtime builders hardcode EventCollectorChannel.DynamoDbStream, but
121
- // the Plugin admin handler (AdminEventCollectorEntryPoint) is shared across DCB and aggregate
121
+ // the Plugin admin handler (EventCollectorEntryPoint) is shared across DCB and aggregate
122
122
  // plugins which may use different event log backends. The functor keeps the builder generic
123
123
  // while the concrete instantiation picks the right channel at the platform level.
124
124
  module Make = (
@@ -151,9 +151,11 @@ module Make = (
151
151
  let synthesizeAdminContext = (): ReventlessCore.Plugin_Helpers.eventCollectorContext => {
152
152
  let config = configRef.contents
153
153
  // Stable JSON literal — matches Reventless.Plugin.pluginDefinitionSchema
154
- // (optional fields encoded as null via js_nullable).
154
+ // (optional fields encoded as null via js_nullable). Must stay byte-aligned with
155
+ // the ReScript-built twin in `Platform_Admin.construct`'s `fakePluginDefinition`.
156
+ let platformId = ReventlessCore.Platform_Admin_Structure.pluginId
155
157
  let fakePluginDefinitionJson =
156
- `{"id":"Admin@INTERNAL","name":"Admin","version":"INTERNAL","extensionPoints":[],"extensions":[],"eventCollector":"NOT-SET","extensionProtocols":[],"apiSchemaFragment":null,"apiTarget":null,"structure":null}`->Pulumi.Output.make
158
+ `{"id":"${platformId}@INTERNAL","name":"${platformId}","version":"INTERNAL","extensionPoints":[],"extensions":[],"eventCollector":"NOT-SET","extensionProtocols":[],"apiSchemaFragment":null,"apiTarget":null,"structure":null}`->Pulumi.Output.make
157
159
  let adminEpEventTopicArn = switch config.eventTopicArn {
158
160
  | Some(arn) => arn
159
161
  | None => Pulumi.Output.make("NOT_AVAILABLE")
@@ -436,7 +438,7 @@ module Make = (
436
438
  [ext.specModule, ext.mappingsModule, ext.delegateModule]->Array.forEach(addPackageFor)
437
439
  })
438
440
  // Outgoing EPs: the entry point dynamic-imports ep.specModule and
439
- // ep.mappingsModule at cold start (AdminEventCollectorEntryPoint.mjs).
441
+ // ep.mappingsModule at cold start (EventCollectorEntryPoint.mjs).
440
442
  // Without this walk the EP spec package (e.g. <plugin>-spec) is missing
441
443
  // from the asset zip even though HANDLER_CONFIG references it, and the
442
444
  // Lambda crashes with MODULE_NOT_FOUND before any event is processed.
@@ -484,7 +486,9 @@ module Make = (
484
486
  // extension can emit RegisterUiFragment in the handshake answer.
485
487
  extraStringAssets->Dict.set("uiFragments.json", uiFragmentsJson)
486
488
  Util_Bundle.buildCodeArchive(
487
- ~entryPointModule="@reventlessdev/reventless-aws/src/adapter/Runtime/AdminEventCollectorEntryPoint.mjs",
489
+ // Path string, not a module reference — a rename that misses this stays green
490
+ // at build time and fails at bundle time or Lambda cold start.
491
+ ~entryPointModule="@reventlessdev/reventless-aws/src/adapter/Runtime/EventCollectorEntryPoint.mjs",
488
492
  ~packageDirs,
489
493
  ~extraStringAssets,
490
494
  )
@@ -608,7 +612,7 @@ module Make = (
608
612
 
609
613
  // Plugin EC sqs:SendMessage grants on the aggregate / StateChangeSlice
610
614
  // command-topic queues that user extensions publish to. The default
611
- // AllowLambdaSendSQS only covers CorePluginExtPointCmdTopic (added because
615
+ // AllowLambdaSendSQS only covers PlatformPluginExtPointCmdTopic (added because
612
616
  // the auto-included Connect extension publishes there), so without this
613
617
  // grant every cross-plugin extension's first command publish fails with
614
618
  // IAM AccessDenied (e.g. Catalog's Orders_Extension → RecordProductDemand).
@@ -15,6 +15,7 @@ import * as ComponentType$ReventlessCore from "@reventlessdev/reventless-core/sr
15
15
  import * as EventCollector$ReventlessCore from "@reventlessdev/reventless-core/src/components/EventCollector/EventCollector.res.mjs";
16
16
  import * as EventLogBackend$ReventlessAws from "../../adapter/EventLog/EventLogBackend.res.mjs";
17
17
  import * as Plugin_Helpers$ReventlessCore from "@reventlessdev/reventless-core/src/plugin/component/Plugin_Helpers.res.mjs";
18
+ import * as Platform_Admin_Structure$ReventlessCore from "@reventlessdev/reventless-core/src/admin/Platform_Admin_Structure.res.mjs";
18
19
  import * as RuntimeEnvironment_Lambda$ReventlessAws from "../../adapter/Runtime/RuntimeEnvironment_Lambda.res.mjs";
19
20
  import * as StateChangeSliceRuntime_Builder_Single$ReventlessAws from "../../adapter/Runtime/StateChangeSliceRuntime_Builder_Single.res.mjs";
20
21
 
@@ -132,7 +133,7 @@ function Make(EventCollectorChannel) {
132
133
  };
133
134
  let synthesizeAdminContext = () => {
134
135
  let config = configRef.contents;
135
- let fakePluginDefinitionJson = Pulumi.output(`{"id":"Admin@INTERNAL","name":"Admin","version":"INTERNAL","extensionPoints":[],"extensions":[],"eventCollector":"NOT-SET","extensionProtocols":[],"apiSchemaFragment":null,"apiTarget":null,"structure":null}`);
136
+ let fakePluginDefinitionJson = Pulumi.output(`{"id":"` + Platform_Admin_Structure$ReventlessCore.pluginId + `@INTERNAL","name":"` + Platform_Admin_Structure$ReventlessCore.pluginId + `","version":"INTERNAL","extensionPoints":[],"extensions":[],"eventCollector":"NOT-SET","extensionProtocols":[],"apiSchemaFragment":null,"apiTarget":null,"structure":null}`);
136
137
  let arn = config.eventTopicArn;
137
138
  let adminEpEventTopicArn = arn !== undefined ? arn : Pulumi.output("NOT_AVAILABLE");
138
139
  return {
@@ -306,7 +307,7 @@ function Make(EventCollectorChannel) {
306
307
  let extraStringAssets = {};
307
308
  extraStringAssets["pluginDefinition.json"] = param[0];
308
309
  extraStringAssets["uiFragments.json"] = param[1];
309
- return Util_Bundle$ReventlessAws.buildCodeArchive("@reventlessdev/reventless-aws/src/adapter/Runtime/AdminEventCollectorEntryPoint.mjs", packageDirs, extraStringAssets);
310
+ return Util_Bundle$ReventlessAws.buildCodeArchive("@reventlessdev/reventless-aws/src/adapter/Runtime/EventCollectorEntryPoint.mjs", packageDirs, extraStringAssets);
310
311
  });
311
312
  let codeOutput = bundleOutput.apply(b => b.code);
312
313
  let sourceCodeHashOutput = bundleOutput.apply(b => b.sourceCodeHash);
@@ -23,7 +23,7 @@ let decodeFragment = (fragment: Reventless.Plugin.apiSchemaFragment) =>
23
23
  ReventlessCore.GraphQL_Stitcher.decode(fragment)
24
24
 
25
25
  describe("AppSync_Adapter.injectAwsAuthAll", () => {
26
- let baseFragment = ReventlessCore.AdminApi.baseFragment(~cloner=true)
26
+ let baseFragment = ReventlessCore.Platform_AdminApi.baseFragment(~cloner=true)
27
27
 
28
28
  testSync("adds @aws_auth directive to all mutation fields", () => {
29
29
  let augmented = AppSync_Adapter.injectAwsAuthAll(baseFragment, ~group="Admin")
@@ -86,10 +86,10 @@ describe("AppSync_Adapter.injectAwsAuth", () => {
86
86
  testSync("injects auth only on entries with authorization", () => {
87
87
  // Build a fragment with known entries
88
88
  let mutationEntries: array<ReventlessInfra.Api.mutationSchemaEntry> =
89
- ReventlessCore.AdminApi.mutationEntries(~cloner=false)
89
+ ReventlessCore.Platform_AdminApi.mutationEntries(~cloner=false)
90
90
  let queryEntries = ReventlessCore.PluginBaseFragment.queryEntries
91
91
 
92
- let baseFragment = ReventlessCore.AdminApi.baseFragment(~cloner=false)
92
+ let baseFragment = ReventlessCore.Platform_AdminApi.baseFragment(~cloner=false)
93
93
  let augmented = AppSync_Adapter.injectAwsAuth(
94
94
  baseFragment,
95
95
  ~mutationEntries,
@@ -111,7 +111,7 @@ describe("AppSync_Adapter.injectAwsAuth", () => {
111
111
 
112
112
  describe("AppSync_Adapter.generateFragment", () => {
113
113
  testSync("produces fragment with auth directives from entries", () => {
114
- let mutationEntries = ReventlessCore.AdminApi.mutationEntries(~cloner=false)
114
+ let mutationEntries = ReventlessCore.Platform_AdminApi.mutationEntries(~cloner=false)
115
115
  let queryEntries = ReventlessCore.PluginBaseFragment.queryEntries
116
116
 
117
117
  let fragment = AppSync_Adapter.generateFragment(~mutationEntries, ~queryEntries)
@@ -570,7 +570,7 @@ describe("AppSync_Adapter — type-level dual-auth", () => {
570
570
  })
571
571
 
572
572
  describe("AppSync_Adapter.injectAwsAuthAll — ~iamFieldNames", () => {
573
- let baseFragment = ReventlessCore.AdminApi.baseFragment(~cloner=true)
573
+ let baseFragment = ReventlessCore.Platform_AdminApi.baseFragment(~cloner=true)
574
574
 
575
575
  testSync("marks only the named field dual-auth, leaving others single-mode", () => {
576
576
  // Pick a real mutation field name from the admin base fragment.
@@ -644,7 +644,7 @@ describe("Split mode — empty base fragment", () => {
644
644
  })
645
645
 
646
646
  testSync("stitching admin base without plugins produces only admin fields", () => {
647
- let adminBase = ReventlessCore.AdminApi.baseFragment(~cloner=false)
647
+ let adminBase = ReventlessCore.Platform_AdminApi.baseFragment(~cloner=false)
648
648
  let sdl = ReventlessCore.GraphQL_Stitcher.stitch(
649
649
  ~baseFragment=adminBase,
650
650
  ~pluginFragments=[],
@@ -678,7 +678,7 @@ describe("Merged mode — canonical source documents", () => {
678
678
 
679
679
  let adminSourceSdl = assembleCanonicalSourceSdl(
680
680
  ~baseFragment=AppSync_Adapter.injectAwsAuthAll(
681
- ReventlessCore.AdminApi.baseFragment(~cloner=false),
681
+ ReventlessCore.Platform_AdminApi.baseFragment(~cloner=false),
682
682
  ~group="Admin",
683
683
  ),
684
684
  )
@@ -5,9 +5,9 @@ import * as Stdlib_JsExn from "@rescript/runtime/lib/es6/Stdlib_JsExn.js";
5
5
  import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
6
6
  import * as Stdlib_JsError from "@rescript/runtime/lib/es6/Stdlib_JsError.js";
7
7
  import * as Primitive_exceptions from "@rescript/runtime/lib/es6/Primitive_exceptions.js";
8
- import * as AdminApi$ReventlessCore from "@reventlessdev/reventless-core/src/admin/AdminApi.res.mjs";
9
8
  import * as AppSync_Adapter$ReventlessAws from "../src/components/Api/AppSync_Adapter.res.mjs";
10
9
  import * as GraphQL_Stitcher$ReventlessCore from "@reventlessdev/reventless-core/src/components/Api/GraphQL_Stitcher.res.mjs";
10
+ import * as Platform_AdminApi$ReventlessCore from "@reventlessdev/reventless-core/src/admin/Platform_AdminApi.res.mjs";
11
11
  import * as AppSync_SdlDecorate$ReventlessAws from "../src/components/Api/AppSync_SdlDecorate.res.mjs";
12
12
  import * as PluginBaseFragment$ReventlessCore from "@reventlessdev/reventless-core/src/plugin/api/PluginBaseFragment.res.mjs";
13
13
 
@@ -28,7 +28,7 @@ globalThis.describe("AppSync_Adapter.sha256Hex", () => {
28
28
  let decodeFragment = GraphQL_Stitcher$ReventlessCore.decode;
29
29
 
30
30
  globalThis.describe("AppSync_Adapter.injectAwsAuthAll", () => {
31
- let baseFragment = AdminApi$ReventlessCore.baseFragment(true);
31
+ let baseFragment = Platform_AdminApi$ReventlessCore.baseFragment(true);
32
32
  globalThis.test("adds @aws_auth directive to all mutation fields", () => {
33
33
  let augmented = AppSync_Adapter$ReventlessAws.injectAwsAuthAll(baseFragment, "Admin", undefined);
34
34
  let parts = GraphQL_Stitcher$ReventlessCore.decode(augmented);
@@ -77,8 +77,8 @@ globalThis.describe("AppSync_Adapter.injectAwsAuthAll", () => {
77
77
 
78
78
  globalThis.describe("AppSync_Adapter.injectAwsAuth", () => {
79
79
  globalThis.test("injects auth only on entries with authorization", () => {
80
- let mutationEntries = AdminApi$ReventlessCore.mutationEntries(false);
81
- let baseFragment = AdminApi$ReventlessCore.baseFragment(false);
80
+ let mutationEntries = Platform_AdminApi$ReventlessCore.mutationEntries(false);
81
+ let baseFragment = Platform_AdminApi$ReventlessCore.baseFragment(false);
82
82
  let augmented = AppSync_Adapter$ReventlessAws.injectAwsAuth(baseFragment, mutationEntries, PluginBaseFragment$ReventlessCore.queryEntries);
83
83
  let parts = GraphQL_Stitcher$ReventlessCore.decode(augmented);
84
84
  let queryWithAuth = PluginBaseFragment$ReventlessCore.queryEntries.some(entry => Stdlib_Option.isSome(entry.authorization));
@@ -92,7 +92,7 @@ globalThis.describe("AppSync_Adapter.injectAwsAuth", () => {
92
92
 
93
93
  globalThis.describe("AppSync_Adapter.generateFragment", () => {
94
94
  globalThis.test("produces fragment with auth directives from entries", () => {
95
- let mutationEntries = AdminApi$ReventlessCore.mutationEntries(false);
95
+ let mutationEntries = Platform_AdminApi$ReventlessCore.mutationEntries(false);
96
96
  let fragment = AppSync_Adapter$ReventlessAws.generateFragment(mutationEntries, PluginBaseFragment$ReventlessCore.queryEntries);
97
97
  let parts = GraphQL_Stitcher$ReventlessCore.decode(fragment);
98
98
  globalThis.expect(parts.types.length).toBeGreaterThan(0);
@@ -536,7 +536,7 @@ globalThis.describe("AppSync_Adapter — type-level dual-auth", () => {
536
536
  });
537
537
 
538
538
  globalThis.describe("AppSync_Adapter.injectAwsAuthAll — ~iamFieldNames", () => {
539
- let baseFragment = AdminApi$ReventlessCore.baseFragment(true);
539
+ let baseFragment = Platform_AdminApi$ReventlessCore.baseFragment(true);
540
540
  globalThis.test("marks only the named field dual-auth, leaving others single-mode", () => {
541
541
  let firstMutationName = GraphQL_Stitcher$ReventlessCore.extractLeadingName(GraphQL_Stitcher$ReventlessCore.decode(baseFragment).mutations[0]);
542
542
  let augmented = AppSync_Adapter$ReventlessAws.injectAwsAuthAll(baseFragment, "Admin", [firstMutationName]);
@@ -600,7 +600,7 @@ globalThis.describe("Split mode — empty base fragment", () => {
600
600
  globalThis.expect(sdl).not.toContain("Platform_Plugin");
601
601
  });
602
602
  globalThis.test("stitching admin base without plugins produces only admin fields", () => {
603
- let adminBase = AdminApi$ReventlessCore.baseFragment(false);
603
+ let adminBase = Platform_AdminApi$ReventlessCore.baseFragment(false);
604
604
  let sdl = GraphQL_Stitcher$ReventlessCore.stitch(adminBase, []);
605
605
  globalThis.expect(sdl).toContain("Platform_Plugin");
606
606
  });
@@ -614,7 +614,7 @@ globalThis.describe("Merged mode — canonical source documents", () => {
614
614
  subscriptions: [],
615
615
  subscriptionSources: []
616
616
  });
617
- let baseFragment = AppSync_Adapter$ReventlessAws.injectAwsAuthAll(AdminApi$ReventlessCore.baseFragment(false), "Admin", undefined);
617
+ let baseFragment = AppSync_Adapter$ReventlessAws.injectAwsAuthAll(Platform_AdminApi$ReventlessCore.baseFragment(false), "Admin", undefined);
618
618
  let adminSourceSdl = AppSync_SdlDecorate$ReventlessAws.stampCanonicalTypes(AppSync_Adapter$ReventlessAws.stitchStandaloneWithAwsDirectives(baseFragment));
619
619
  let domainBaseSourceSdl = AppSync_SdlDecorate$ReventlessAws.stampCanonicalTypes(AppSync_Adapter$ReventlessAws.stitchStandaloneWithAwsDirectives(domainBaseFragment));
620
620
  globalThis.test("no AWS source document carries the global node query (dropped — see plan)", () => {
@@ -73,7 +73,7 @@ describe("MCP_Lambda.generateAdminConfig", () => {
73
73
  let arns = Dict.make()
74
74
  // Use a tool name that matches the first mutation field
75
75
  let firstEntry: ReventlessInfra.Api.mutationSchemaEntry =
76
- ReventlessCore.AdminApi.mutationEntries(~cloner=false)->Array.getUnsafe(0)
76
+ ReventlessCore.Platform_AdminApi.mutationEntries(~cloner=false)->Array.getUnsafe(0)
77
77
  let firstFieldName = firstEntry.fieldNames->Array.getUnsafe(0)
78
78
  arns->Dict.set(firstFieldName, "arn:aws:sqs:us-east-1:123:queue")
79
79
 
@@ -1,7 +1,7 @@
1
1
  // Generated by ReScript, PLEASE EDIT WITH CARE
2
2
 
3
- import * as AdminApi$ReventlessCore from "@reventlessdev/reventless-core/src/admin/AdminApi.res.mjs";
4
3
  import * as MCP_Lambda$ReventlessAws from "../src/adapter/Mcp/MCP_Lambda.res.mjs";
4
+ import * as Platform_AdminApi$ReventlessCore from "@reventlessdev/reventless-core/src/admin/Platform_AdminApi.res.mjs";
5
5
 
6
6
  globalThis.describe("MCP_Lambda.generateAdminConfig", () => {
7
7
  globalThis.test("produces tools from admin mutation entries (no cloner)", () => {
@@ -40,7 +40,7 @@ globalThis.describe("MCP_Lambda.generateAdminConfig", () => {
40
40
  });
41
41
  globalThis.test("commandTopicArns are mapped to tools", () => {
42
42
  let arns = {};
43
- let firstEntry = AdminApi$ReventlessCore.mutationEntries(false)[0];
43
+ let firstEntry = Platform_AdminApi$ReventlessCore.mutationEntries(false)[0];
44
44
  let firstFieldName = firstEntry.fieldNames[0];
45
45
  arns[firstFieldName] = "arn:aws:sqs:us-east-1:123:queue";
46
46
  let config = MCP_Lambda$ReventlessAws.generateAdminConfig("test", "1.0.0", undefined, arns, undefined);