Skip to content

Use store auth sessions for theme commands#7783

Open
alfonso-noriega wants to merge 1 commit into
mainfrom
theme-preview-store-auth
Open

Use store auth sessions for theme commands#7783
alfonso-noriega wants to merge 1 commit into
mainfrom
theme-preview-store-auth

Conversation

@alfonso-noriega

@alfonso-noriega alfonso-noriega commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

WHY are these changes introduced?

Fixes https://github.com/shop/issues-develop/issues/22916.

Preview stores created by shopify store create preview persist an Admin API token in the store-auth cache. theme pull and theme push should be able to use that cached token when the user does not provide a Theme Access/Admin token via --password.

WHAT is this pull request doing?

  • Moves the store-auth session storage schema, sanitization, keying, listing, reading, writing, and clearing helpers into @shopify/cli-kit/node/store-auth-session.
  • Deletes packages/store's old auth/session-store module; store and theme now use the cli-kit boundary directly.
  • Updates store auth, store info, store execute, and preview store creation code/tests to import store-auth session helpers from cli-kit.
  • Removes the direct @shopify/theme@shopify/store package dependency.
  • Updates theme command session creation so explicit --password still wins, but missing --password can fall back to a matching cached store-auth Admin API token before normal theme authentication.
  • Allows multi-environment theme configs to omit password when the matching store-auth cache session satisfies auth.
  • Adds/expands focused tests for the shared cli-kit storage boundary, explicit password precedence, store-auth fallback, missing-cache fallback, and multi-environment validation.

How to test your changes?

pnpm vitest run packages/cli-kit/src/public/node/store-auth-session.test.ts packages/store/src/cli/services/store/auth/session-store.test.ts packages/store/src/cli/services/store/auth/session-lifecycle.test.ts packages/store/src/cli/services/store/auth/stored-auth.test.ts packages/store/src/cli/services/store/auth/index.test.ts packages/store/src/cli/services/store/auth/existing-scopes.test.ts packages/store/src/cli/services/store/info/index.test.ts packages/store/src/cli/services/store/execute/admin-transport.test.ts packages/store/src/cli/services/store/create/preview/index.test.ts packages/theme/src/cli/utilities/theme-command.test.ts
pnpm --filter @shopify/cli-kit lint
pnpm --filter @shopify/store lint
pnpm --filter @shopify/theme lint
pnpm --filter @shopify/cli-kit build
pnpm --filter @shopify/store build
pnpm --filter @shopify/theme build

Post-release steps

None.

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 — I've identified the correct bump type and added a changeset

alfonso-noriega commented Jun 11, 2026

Copy link
Copy Markdown
Contributor Author

@github-actions github-actions Bot added the Area: @shopify/cli @shopify/cli package issues label Jun 11, 2026
@alfonso-noriega alfonso-noriega force-pushed the productionize-preview-store-create-main branch from f0160e7 to 72f8f19 Compare June 11, 2026 09:32
@alfonso-noriega alfonso-noriega force-pushed the theme-preview-store-auth branch 3 times, most recently from 9bae25d to 58a57dd Compare June 11, 2026 11:34
@alfonso-noriega alfonso-noriega force-pushed the productionize-preview-store-create-main branch from 72f8f19 to b504c98 Compare June 11, 2026 12:24
@alfonso-noriega alfonso-noriega force-pushed the theme-preview-store-auth branch 2 times, most recently from 56a026b to ab54f9c Compare June 11, 2026 14:35
@alfonso-noriega alfonso-noriega force-pushed the productionize-preview-store-create-main branch from b504c98 to c3f7626 Compare June 11, 2026 14:35
@alfonso-noriega alfonso-noriega force-pushed the theme-preview-store-auth branch from ab54f9c to 3764131 Compare June 12, 2026 12:28
@alfonso-noriega alfonso-noriega force-pushed the productionize-preview-store-create-main branch 2 times, most recently from 07d1745 to f4ec45d Compare June 12, 2026 12:42
@alfonso-noriega alfonso-noriega force-pushed the theme-preview-store-auth branch from 3764131 to d2b96d9 Compare June 12, 2026 12:42
@alfonso-noriega alfonso-noriega changed the base branch from productionize-preview-store-create-main to graphite-base/7783 June 12, 2026 13:10
@alfonso-noriega alfonso-noriega force-pushed the theme-preview-store-auth branch from d2b96d9 to 2ad7d1f Compare June 12, 2026 13:10
@alfonso-noriega alfonso-noriega changed the base branch from graphite-base/7783 to preview-store-claim-url June 12, 2026 13:10
@alfonso-noriega alfonso-noriega force-pushed the theme-preview-store-auth branch from 2ad7d1f to 5000127 Compare June 12, 2026 13:25
@alfonso-noriega alfonso-noriega marked this pull request as ready for review June 12, 2026 15:07
@alfonso-noriega alfonso-noriega requested review from a team as code owners June 12, 2026 15:07

@dmerand dmerand 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.

'bot found one concern worth looking into.

Comment thread packages/theme/src/cli/utilities/theme-command.ts Outdated
@alfonso-noriega alfonso-noriega force-pushed the preview-store-claim-url branch from 7ba8de4 to d0a2320 Compare June 16, 2026 10:13
@alfonso-noriega alfonso-noriega force-pushed the theme-preview-store-auth branch from 5000127 to ded68ab Compare June 16, 2026 10:13
@alfonso-noriega alfonso-noriega changed the base branch from preview-store-claim-url to graphite-base/7783 June 17, 2026 12:56
@alfonso-noriega alfonso-noriega force-pushed the theme-preview-store-auth branch from ded68ab to 2999eeb Compare June 17, 2026 13:31
@alfonso-noriega alfonso-noriega changed the base branch from graphite-base/7783 to preview-store-claim-url June 17, 2026 13:31
Comment thread packages/store/src/cli/services/store/auth/admin-session.ts Outdated
@alfonso-noriega alfonso-noriega force-pushed the theme-preview-store-auth branch 3 times, most recently from 716a05c to 77cfe9f Compare June 19, 2026 17:02
@alfonso-noriega alfonso-noriega force-pushed the theme-preview-store-auth branch from 77cfe9f to f44e9de Compare June 19, 2026 17:48
Comment thread packages/cli-kit/src/public/node/store-auth-session.ts Fixed

Copy link
Copy Markdown
Contributor

​That is a good product question. In my opinion we shouldn't try to have specific preview store behavior if we can avoid it. The same problem is already live if you run store execute with a query that you do not have scopes for.

@alfonso-noriega I don't think this is the same thing. store execute will fail with an obvious error that triggers you to increase the permissions on the token. But for theme commands, for non-preview stores, usually the right thing to do would be to log in via organizations. Of course they can also request the write_themes permission, but that's not documented in these commands at the moment.

@nickwesselman what do you think?

@alfonso-noriega alfonso-noriega force-pushed the theme-preview-store-auth branch 3 times, most recently from bdd4ac8 to c2fe1bc Compare June 22, 2026 10:28
@alfonso-noriega

Copy link
Copy Markdown
Contributor Author

/snapit

@github-actions

Copy link
Copy Markdown
Contributor

🫰✨ Thanks @alfonso-noriega! Your snapshot has been published to npm.

Test the snapshot by installing your package globally:

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

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.

Copy link
Copy Markdown
Contributor

​That is a good product question. In my opinion we shouldn't try to have specific preview store behavior if we can avoid it. The same problem is already live if you run store execute with a query that you do not have scopes for.

@alfonso-noriega I don't think this is the same thing. store execute will fail with an obvious error that triggers you to increase the permissions on the token.

​What is the error message and why wouldn't it trigger the agent to store auth with the additional required scopes?

But for theme commands, for non-preview stores, usually the right thing to do would be to log in via organizations. Of course they can also request the write_themes permission, but that's not documented in these commands at the moment.

The goal is to have a solution here that works for store auth generally, not just for preview stores. We don't want this functionality to stop working after they claim/save the store, right?

@alfonso-noriega alfonso-noriega force-pushed the theme-preview-store-auth branch 2 times, most recently from 4b9f711 to 6e8b6b5 Compare June 23, 2026 12:01
Comment thread packages/cli-kit/src/public/node/store-auth-session.test.ts
Comment thread packages/cli-kit/src/public/node/store-auth-session.ts Outdated
Comment thread packages/theme/src/cli/utilities/theme-command.ts Outdated
Comment thread packages/theme/src/cli/utilities/theme-command.ts Outdated
Comment thread packages/theme/src/cli/utilities/theme-command.ts Outdated
Comment thread pnpm-lock.yaml Outdated
@alfonso-noriega alfonso-noriega force-pushed the theme-preview-store-auth branch 2 times, most recently from 42b992a to 3d69dd4 Compare June 24, 2026 14:00
@alfonso-noriega alfonso-noriega requested a review from amcaplan June 24, 2026 14:14
Comment thread packages/cli-kit/src/public/node/store-auth-session.ts Outdated
Comment thread packages/theme/src/cli/utilities/theme-command.ts Outdated
Comment thread packages/store/src/cli/services/store/execute/admin-context.test.ts
@alfonso-noriega alfonso-noriega force-pushed the theme-preview-store-auth branch from 3d69dd4 to c31a07d Compare June 24, 2026 16:10
@alfonso-noriega alfonso-noriega requested a review from amcaplan June 24, 2026 16:28
@alfonso-noriega alfonso-noriega added this pull request to the merge queue Jun 24, 2026
@alfonso-noriega alfonso-noriega removed this pull request from the merge queue due to a manual request Jun 24, 2026
Assisted-By: devx/2de967b4-f860-4a71-a205-2e8334cf528c
@alfonso-noriega alfonso-noriega force-pushed the theme-preview-store-auth branch from c31a07d to 551bccc Compare June 24, 2026 17:50
@github-actions

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

packages/cli-kit/dist/public/node/constants.d.ts
export declare const STORE_AUTH_APP_CLIENT_ID = "7e9cb568cfd431c538f36d1ad3f2b4f6";
packages/cli-kit/dist/public/node/store-auth-session.d.ts
import { LocalStorage } from './local-storage.js';
import type { AdminSession } from './session.js';
/**
 * Discriminator for a stored store auth session.
 *
 * - 'standard': created via `shopify store auth`.
 * - 'preview': created via `shopify store create preview`; backed by a server-issued Admin API token.
 *
 * Stored sessions written before this discriminator existed have no `kind` field and are
 * read back as 'standard'.
 */
export type StoredStoreSessionKind = 'standard' | 'preview';
export interface StoredPreviewStoreMetadata {
    /** Placeholder account UUID returned by the preview-store backend when available. */
    placeholderAccountUuid?: string;
    /** Numeric shop id returned by the preview-store backend. */
    shopId: string;
    /** Store name returned by the preview-store backend. */
    name: string;
    /** ISO country code requested for the store, when provided by the caller. */
    country?: string;
    /** ISO timestamp for when the preview store was created locally. */
    createdAt: string;
    /** Access URL returned by the preview-store backend. */
    accessUrl?: string;
}
export interface StoredStoreAppSession {
    store: string;
    clientId: string;
    userId: string;
    accessToken: string;
    refreshToken?: string;
    scopes: string[];
    acquiredAt: string;
    expiresAt?: string;
    refreshTokenExpiresAt?: string;
    associatedUser?: {
        id: number;
        email?: string;
        firstName?: string;
        lastName?: string;
        accountOwner?: boolean;
    };
    /**
     * Discriminator. Optional in storage for back-compat with sessions written before the
     * field existed; `sessionKind()` resolves missing values to 'standard'.
     */
    kind?: StoredStoreSessionKind;
    /** Preview-store-only metadata. Set iff `kind === 'preview'`. */
    preview?: StoredPreviewStoreMetadata;
}
interface StoredStoreAppSessionBucket {
    currentUserId: string;
    sessionsByUserId: {
        [userId: string]: StoredStoreAppSession;
    };
}
interface StoreAuthSessionSchema {
    [key: string]: StoredStoreAppSessionBucket;
}
/**
 * Build the local-storage key used for store-auth sessions.
 *
 * @param store - The normalized store FQDN.
 * @returns The store-auth session storage key.
 */
export declare function storeAuthSessionKey(store: string): string;
/**
 * Project the current session for every store that has locally stored store auth.
 *
 * @param storage - Optional storage override for tests.
 * @returns Current stored store auth sessions.
 */
export declare function listCurrentStoredStoreAppSessions(storage?: LocalStorage<StoreAuthSessionSchema>): StoredStoreAppSession[];
/**
 * Get the current stored store auth session for a store.
 *
 * @param store - The store FQDN or URL to load a store-auth session for.
 * @param storage - Optional storage override for tests.
 * @returns The current stored store auth session, or undefined when missing or malformed.
 */
export declare function getCurrentStoredStoreAppSession(store: string, storage?: LocalStorage<StoreAuthSessionSchema>): StoredStoreAppSession | undefined;
/**
 * Persist a store auth session and mark it as current for its store.
 *
 * @param session - The store auth session to persist.
 * @param storage - Optional storage override for tests.
 */
export declare function setStoredStoreAppSession(session: StoredStoreAppSession, storage?: LocalStorage<StoreAuthSessionSchema>): void;
/**
 * Clear stored store auth sessions for a store.
 *
 * @param store - The store FQDN or URL to clear sessions for.
 * @param userIdOrStorage - Optional user ID to clear, or storage override when clearing all users.
 * @param maybeStorage - Optional storage override when clearing one user.
 */
export declare function clearStoredStoreAppSession(store: string, userIdOrStorage?: string | LocalStorage<StoreAuthSessionSchema>, maybeStorage?: LocalStorage<StoreAuthSessionSchema>): void;
/**
 * Load an Admin API session from the local store-auth cache when one is currently usable.
 *
 * @param store - The store FQDN or URL to load a store-auth session for.
 * @param storage - Optional storage override for tests.
 * @returns An Admin session, or undefined when no usable session is cached.
 */
export declare function getStoreAuthAdminSession(store: string, storage?: LocalStorage<StoreAuthSessionSchema>): AdminSession | undefined;
/**
 * Check whether a stored store auth session is expired, including the refresh margin.
 *
 * @param session - The stored store auth session.
 * @returns True when the session is expired or has an invalid expiry timestamp.
 */
export declare function isSessionExpired(session: StoredStoreAppSession): boolean;
export {};

Existing type declarations

We found no diffs with existing type declarations

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Area: @shopify/cli @shopify/cli package issues

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants