Skip to content

Expand app configuration through extension specifications - #8686

Merged
isaacroldan merged 11 commits into
mainfrom
isaac/specification-config-expansion
Oct 5, 2026
Merged

isaacroldan merged 11 commits into
mainfrom
isaac/specification-config-expansion

Conversation

@isaacroldan

@isaacroldan isaacroldan commented Sep 28, 2026 •

Copy link
Copy Markdown
Contributor

WHY are these changes introduced?

Alternative to #8426, built on #8425. Deploying one events module per subscription needs support for multiple modules from one app configuration section. The events contract and identity rules belong in its specification.

WHAT is this pull request doing?

Add optional specification hooks for configuration expansion, module identity, and module target. The loader creates and validates every result through the same path, while the events specification owns the subscription split.

Expand event subscriptions by default, without an organization flag lookup. Require valid, unique subscription handles and reject the reserved legacy handle events. Keep app branding handles out of events validation, preserve extra subscription fields, and return no modules for an empty subscription list.

Validated with 350 tests across eight files, app type checking, lint on changed files, and Knip for the app workspace. Includes deploy/config-link round trips, identity stability, and invalid configuration cases. A live deploy has not been tested. The server must support single-subscription events modules before this CLI change is released.

How to manually test your changes?

pnpm shopify app deploy --path /path/to/app
pnpm shopify app config link --path /path/to/app

Checklist

  • I've considered possible cross-platform impacts (Mac, Linux, Windows)
  • I've considered possible documentation changes
  • I've considered analytics changes to measure impact
  • The change is user-facing and includes a patch changeset

@github-actions github-actions Bot added the Area: @shopify/app @shopify/app package issues label Sep 28, 2026
@cdarne
cdarne marked this pull request as ready for review September 29, 2026 18:40
@cdarne
cdarne requested a review from a team as a code owner September 29, 2026 18:40
@isaacroldan
isaacroldan force-pushed the isaac/specification-config-expansion branch 3 times, most recently from a63015f to 6809ca7 Compare September 30, 2026 15:01
isaacroldan and others added 4 commits September 30, 2026 17:02
Keep event subscription expansion and identity in the events specification. Use the shared loader validation path for each expanded module and validate subscription handles before resolving identity.

Co-authored-by: Rezaan Syed <rezaan.syed@shopify.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@isaacroldan
isaacroldan force-pushed the isaac/specification-config-expansion branch from 6809ca7 to 2241ebd Compare September 30, 2026 15:02
@github-actions github-actions Bot added no-changelog This PR doesn't include a changeset entry. Is an internal only change not relevant to end users. and removed Area: @shopify/app @shopify/app package issues labels Sep 30, 2026
Rename the flag to f_single_subscription_events_modules and drop the
SHOPIFY_CLI_EVENTS_SUBSCRIPTION_FANOUT environment opt-in.
Business Platform resolves hashed client handles rather than readable
Verdict handles, so the readable name always evaluated to false.
Comment thread packages/app/src/cli/models/extensions/specifications/app_config_events.ts Outdated
The platform is removing the nested handle from the single-subscription
contract, so an expanded configuration that still carried it inside the
subscription failed validation before the deploy transform stripped it.
Expand each subscription into a module with its handle at the top level,
like every other module, and derive identity and target from there.
@rezaansyed
rezaansyed requested a review from dpeacock September 30, 2026 20:35
Base automatically changed from events-config-link-shape-tolerance to main October 1, 2026 09:25
@isaacroldan

Copy link
Copy Markdown
Contributor Author

/snapit

Comment on lines +27 to +30
const EventsSchema = BaseSchemaWithoutHandle.extend({
events: zod.any().optional(),
handle: ModuleHandleSchema.optional(),
events: EventsSectionSchema.optional(),
}).superRefine((config, context) => {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can't include handle here outside of events. This will receive the full app toml config, and handle is a field belonging to the branding module. We can only validate events and its children here.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rezaansyed this is a limitation of the expansion approach, i'm looking on ways to improve this.

@github-actions github-actions Bot added Area: @shopify/app @shopify/app package issues and removed no-changelog This PR doesn't include a changeset entry. Is an internal only change not relevant to end users. labels Oct 1, 2026
@github-actions

github-actions Bot commented Oct 2, 2026

Copy link
Copy Markdown
Contributor

Differences in type declarations

We detected differences in the type declarations generated by Typescript for this branch compared to the baseline ('main' branch). Please, review them to ensure they are backward-compatible. Here are some important things to keep in mind:

  • Some seemingly private modules might be re-exported through public modules.
  • If the branch is behind main you might see odd diffs, rebase main into this branch.

New type declarations

We found no new type declarations in this PR

Existing type declarations

packages/cli-kit/dist/public/node/cli.d.ts
@@ -35,7 +35,6 @@ export declare function runCreateCLI(options: RunCLIOptions, launchCLI?: (option
 export declare const globalFlags: {
     'no-color': import("@oclif/core/interfaces").BooleanFlag<boolean>;
     verbose: import("@oclif/core/interfaces").BooleanFlag<boolean>;
-    'no-input': import("@oclif/core/interfaces").BooleanFlag<boolean>;
 };
 export declare const jsonFlag: {
     json: import("@oclif/core/interfaces").BooleanFlag<boolean>;

@isaacroldan

Copy link
Copy Markdown
Contributor Author

/snapit

@github-actions github-actions Bot added no-changelog This PR doesn't include a changeset entry. Is an internal only change not relevant to end users. and removed Area: @shopify/app @shopify/app package issues labels Oct 2, 2026
@github-actions

github-actions Bot commented Oct 2, 2026

Copy link
Copy Markdown
Contributor

🫰✨ Thanks @isaacroldan! Your snapshot has been published to npm.

Built from 294f999fa5b79d6784960e5b55791cb5b7238e0d. Workflow run.

Test the snapshot by installing your package globally:

pnpm i -g --@shopify:registry=https://registry.npmjs.org @shopify/cli@0.0.0-snapshot-20261002155739

Caution

After installing, validate the version by running shopify version in your terminal.
If the versions don't match, you might have multiple global instances installed.
Use which shopify to find out which one you are running and uninstall it.

@gonzaloriestra gonzaloriestra left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've been playing around and everything looks good 👍

@isaacroldan
isaacroldan added this pull request to the merge queue Oct 5, 2026
Merged via the queue into main with commit 01568f6 Oct 5, 2026
30 checks passed
@isaacroldan
isaacroldan deleted the isaac/specification-config-expansion branch October 5, 2026 11:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

no-changelog This PR doesn't include a changeset entry. Is an internal only change not relevant to end users.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants