@unifiedcommerce/core 0.5.4 → 0.5.5

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.
@@ -1,24 +1,27 @@
1
1
  /**
2
- * @deprecated Use `config.auth.defaultOrganizationId` instead.
3
- * This constant will be removed in the next major version.
4
- * See RFC-060 for migration details.
2
+ * @deprecated Will be removed. Use `config.auth.defaultOrganizationId` instead.
3
+ * Kept only for test utilities and backwards compatibility.
5
4
  */
6
5
  export declare const DEFAULT_ORG_ID = "org_default";
6
+ /**
7
+ * Called once at boot by createCommerce/createServer to register
8
+ * the config-driven default org ID. This bridges the gap between
9
+ * config (available at boot) and services (which don't have config access).
10
+ */
11
+ export declare function setBootDefaultOrgId(orgId: string): void;
7
12
  /**
8
13
  * Extracts the organization ID from an actor.
9
14
  *
10
15
  * Resolution order:
11
- * 1. Actor's organizationId (set by middleware from session/API key)
12
- * 2. Explicit defaultOrgId parameter (from config.auth.defaultOrganizationId)
13
- * 3. Deprecated fallback to "org_default" (logs warning once)
16
+ * 1. Actor's organizationId (set by middleware from session/API key/storeResolver)
17
+ * 2. Explicit defaultOrgId parameter (caller override)
18
+ * 3. Boot-time default (from config.auth.defaultOrganizationId via setBootDefaultOrgId)
19
+ * 4. Deprecated fallback to DEFAULT_ORG_ID (will be removed)
14
20
  */
15
21
  export declare function resolveOrgId(actor: unknown, defaultOrgId?: string): string;
16
22
  /**
17
23
  * @deprecated Use seed script with `auth.api.createOrganization()` instead.
18
- * This function will be removed in the next major version. See RFC-060.
19
- *
20
- * Ensures the default organization row exists in the database.
21
- * Idempotent — safe to call multiple times.
24
+ * Kept for backwards compatibility during migration. Will be removed.
22
25
  */
23
26
  export declare function ensureDefaultOrg(db: unknown, storeName?: string): Promise<void>;
24
27
  //# sourceMappingURL=org.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"org.d.ts","sourceRoot":"","sources":["../../src/auth/org.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,eAAO,MAAM,cAAc,gBAAgB,CAAC;AAI5C;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,CAiB1E;AAED;;;;;;GAMG;AACH,wBAAsB,gBAAgB,CACpC,EAAE,EAAE,OAAO,EACX,SAAS,SAAkB,GAC1B,OAAO,CAAC,IAAI,CAAC,CAOf"}
1
+ {"version":3,"file":"org.d.ts","sourceRoot":"","sources":["../../src/auth/org.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,eAAO,MAAM,cAAc,gBAAgB,CAAC;AAS5C;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAEvD;AAED;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,CAQ1E;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,CACpC,EAAE,EAAE,OAAO,EACX,SAAS,SAAkB,GAC1B,OAAO,CAAC,IAAI,CAAC,CAOf"}
package/dist/auth/org.js CHANGED
@@ -1,18 +1,31 @@
1
1
  import { OrganizationService } from "../modules/organization/service.js";
2
2
  /**
3
- * @deprecated Use `config.auth.defaultOrganizationId` instead.
4
- * This constant will be removed in the next major version.
5
- * See RFC-060 for migration details.
3
+ * @deprecated Will be removed. Use `config.auth.defaultOrganizationId` instead.
4
+ * Kept only for test utilities and backwards compatibility.
6
5
  */
7
6
  export const DEFAULT_ORG_ID = "org_default";
8
- let hasLoggedDeprecation = false;
7
+ /**
8
+ * Module-level default set once at boot by `setBootDefaultOrgId()`.
9
+ * Allows resolveOrgId to use the config value without requiring
10
+ * every service caller to pass it explicitly.
11
+ */
12
+ let _bootDefaultOrgId;
13
+ /**
14
+ * Called once at boot by createCommerce/createServer to register
15
+ * the config-driven default org ID. This bridges the gap between
16
+ * config (available at boot) and services (which don't have config access).
17
+ */
18
+ export function setBootDefaultOrgId(orgId) {
19
+ _bootDefaultOrgId = orgId;
20
+ }
9
21
  /**
10
22
  * Extracts the organization ID from an actor.
11
23
  *
12
24
  * Resolution order:
13
- * 1. Actor's organizationId (set by middleware from session/API key)
14
- * 2. Explicit defaultOrgId parameter (from config.auth.defaultOrganizationId)
15
- * 3. Deprecated fallback to "org_default" (logs warning once)
25
+ * 1. Actor's organizationId (set by middleware from session/API key/storeResolver)
26
+ * 2. Explicit defaultOrgId parameter (caller override)
27
+ * 3. Boot-time default (from config.auth.defaultOrganizationId via setBootDefaultOrgId)
28
+ * 4. Deprecated fallback to DEFAULT_ORG_ID (will be removed)
16
29
  */
17
30
  export function resolveOrgId(actor, defaultOrgId) {
18
31
  if (actor != null && typeof actor === "object" && "organizationId" in actor) {
@@ -22,21 +35,13 @@ export function resolveOrgId(actor, defaultOrgId) {
22
35
  }
23
36
  if (defaultOrgId)
24
37
  return defaultOrgId;
25
- // Deprecated fallback — will become an error in next major version
26
- if (!hasLoggedDeprecation) {
27
- hasLoggedDeprecation = true;
28
- console.warn("[UC DEPRECATION] resolveOrgId() fell back to 'org_default'. " +
29
- "Set auth.defaultOrganizationId in your commerce config. " +
30
- "This fallback will be removed in the next major version. See RFC-060.");
31
- }
38
+ if (_bootDefaultOrgId)
39
+ return _bootDefaultOrgId;
32
40
  return DEFAULT_ORG_ID;
33
41
  }
34
42
  /**
35
43
  * @deprecated Use seed script with `auth.api.createOrganization()` instead.
36
- * This function will be removed in the next major version. See RFC-060.
37
- *
38
- * Ensures the default organization row exists in the database.
39
- * Idempotent — safe to call multiple times.
44
+ * Kept for backwards compatibility during migration. Will be removed.
40
45
  */
41
46
  export async function ensureDefaultOrg(db, storeName = "Default Store") {
42
47
  const orgService = new OrganizationService(db);
@@ -1 +1 @@
1
- {"version":3,"file":"commerce.d.ts","sourceRoot":"","sources":["../../src/runtime/commerce.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAG1C,OAAO,EAAc,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACjE,OAAO,EAAgB,KAAK,MAAM,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EAAkB,KAAK,gBAAgB,EAAwB,MAAM,wBAAwB,CAAC;AAErG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoDG;AACH,MAAM,WAAW,gBAAgB;IAC/B,0EAA0E;IAC1E,GAAG,EAAE,gBAAgB,CAAC;IAEtB,8DAA8D;IAC9D,MAAM,EAAE,MAAM,CAAC;IAEf,mDAAmD;IACnD,EAAE,EAAE,OAAO,CAAC;IAEZ,yDAAyD;IACzD,IAAI,EAAE,YAAY,CAAC;IAEnB,aAAa;IACb,MAAM,EAAE,MAAM,CAAC;IAEf;;;;;;;;;;;;OAYG;IACH,SAAS,CAAC,KAAK,EAAE,KAAK,GAAG,gBAAgB,CAAC;IAE1C;;;;;;;;;;OAUG;IACH,eAAe,CAAC,EAAE,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE,KAAK,GAAG,IAAI,GAAG,gBAAgB,CAAC;CACtE;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,cAAc,CAClC,MAAM,EAAE,cAAc,GACrB,OAAO,CAAC,gBAAgB,CAAC,CA+B3B"}
1
+ {"version":3,"file":"commerce.d.ts","sourceRoot":"","sources":["../../src/runtime/commerce.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAG1C,OAAO,EAAc,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACjE,OAAO,EAAgB,KAAK,MAAM,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EAAkB,KAAK,gBAAgB,EAAwB,MAAM,wBAAwB,CAAC;AAErG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoDG;AACH,MAAM,WAAW,gBAAgB;IAC/B,0EAA0E;IAC1E,GAAG,EAAE,gBAAgB,CAAC;IAEtB,8DAA8D;IAC9D,MAAM,EAAE,MAAM,CAAC;IAEf,mDAAmD;IACnD,EAAE,EAAE,OAAO,CAAC;IAEZ,yDAAyD;IACzD,IAAI,EAAE,YAAY,CAAC;IAEnB,aAAa;IACb,MAAM,EAAE,MAAM,CAAC;IAEf;;;;;;;;;;;;OAYG;IACH,SAAS,CAAC,KAAK,EAAE,KAAK,GAAG,gBAAgB,CAAC;IAE1C;;;;;;;;;;OAUG;IACH,eAAe,CAAC,EAAE,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE,KAAK,GAAG,IAAI,GAAG,gBAAgB,CAAC;CACtE;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,cAAc,CAClC,MAAM,EAAE,cAAc,GACrB,OAAO,CAAC,gBAAgB,CAAC,CAkC3B"}
@@ -1,5 +1,5 @@
1
1
  import { createKernel } from "./kernel.js";
2
- import { ensureDefaultOrg } from "../auth/org.js";
2
+ import { ensureDefaultOrg, setBootDefaultOrgId } from "../auth/org.js";
3
3
  import { createAuth } from "../auth/setup.js";
4
4
  import { createLogger } from "./logger.js";
5
5
  import { createLocalAPI } from "../kernel/local-api.js";
@@ -16,10 +16,14 @@ import { createLocalAPI } from "../kernel/local-api.js";
16
16
  */
17
17
  export async function createCommerce(config) {
18
18
  const kernel = createKernel(config);
19
- // If no explicit org ID is configured, fall back to legacy ensureDefaultOrg behavior
20
- // with a deprecation warning. New deployments should use seed scripts with
21
- // auth.api.createOrganization() and set config.auth.defaultOrganizationId.
22
- if (!config.auth?.defaultOrganizationId) {
19
+ // Register the config-driven org ID so resolveOrgId() can use it
20
+ // without requiring every service to have config access.
21
+ if (config.auth?.defaultOrganizationId) {
22
+ setBootDefaultOrgId(config.auth.defaultOrganizationId);
23
+ }
24
+ else {
25
+ // Legacy fallback: auto-create org_default for deployments
26
+ // that haven't migrated to seed-based org creation yet.
23
27
  await ensureDefaultOrg(kernel.database.db, config.storeName);
24
28
  }
25
29
  const auth = createAuth(kernel.database, config);
@@ -1 +1 @@
1
- {"version":3,"file":"create-test-config.d.ts","sourceRoot":"","sources":["../../src/test-utils/create-test-config.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAgDzD,wBAAsB,gBAAgB,CACpC,SAAS,GAAE,OAAO,CAAC,cAAc,CAAM,GACtC,OAAO,CAAC,cAAc,CAAC,CA+GzB;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,sBAAsB,CAC1C,SAAS,GAAE,OAAO,CAAC,cAAc,CAAM,GACtC,OAAO,CAAC;IAAE,MAAM,EAAE,cAAc,CAAC;IAAC,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAAE,CAAC,CAUnE"}
1
+ {"version":3,"file":"create-test-config.d.ts","sourceRoot":"","sources":["../../src/test-utils/create-test-config.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAgDzD,wBAAsB,gBAAgB,CACpC,SAAS,GAAE,OAAO,CAAC,cAAc,CAAM,GACtC,OAAO,CAAC,cAAc,CAAC,CAgHzB;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,sBAAsB,CAC1C,SAAS,GAAE,OAAO,CAAC,cAAc,CAAM,GACtC,OAAO,CAAC;IAAE,MAAM,EAAE,cAAc,CAAC;IAAC,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAAE,CAAC,CAUnE"}
@@ -53,6 +53,7 @@ export async function createTestConfig(overrides = {}) {
53
53
  provider: "postgresql",
54
54
  },
55
55
  auth: {
56
+ defaultOrganizationId: "org_default",
56
57
  requireEmailVerification: false,
57
58
  apiKeys: { enabled: true, defaultPermissions: ["catalog:read"] },
58
59
  posPin: { enabled: true },
@@ -1,4 +1,10 @@
1
1
  import type { Actor } from "../auth/types.js";
2
+ /**
3
+ * Organization ID used in test fixtures. Tests use the deprecated DEFAULT_ORG_ID
4
+ * because ensureDefaultOrg() creates this org in test setup. When RFC-060 Phase 6
5
+ * removes DEFAULT_ORG_ID, test setup will create a real org via Better Auth API.
6
+ */
7
+ export declare const TEST_ORG_ID = "org_default";
2
8
  /** Admin with wildcard permissions. Use for setup operations in beforeAll. */
3
9
  export declare const testAdminActor: Actor;
4
10
  /** Staff with common operational permissions. */
@@ -1 +1 @@
1
- {"version":3,"file":"test-actors.d.ts","sourceRoot":"","sources":["../../src/test-utils/test-actors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAE9C,8EAA8E;AAC9E,eAAO,MAAM,cAAc,EAAE,KAS5B,CAAC;AAEF,iDAAiD;AACjD,eAAO,MAAM,cAAc,EAAE,KAY5B,CAAC;AAEF,wDAAwD;AACxD,eAAO,MAAM,iBAAiB,EAAE,KAS/B,CAAC;AAEF,qEAAqE;AACrE,eAAO,MAAM,eAAe,EAAE,KAS7B,CAAC;AAEF;;;GAGG;AACH,wBAAgB,WAAW,CAAC,KAAK,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAIjE"}
1
+ {"version":3,"file":"test-actors.d.ts","sourceRoot":"","sources":["../../src/test-utils/test-actors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAG9C;;;;GAIG;AACH,eAAO,MAAM,WAAW,gBAAiB,CAAC;AAE1C,8EAA8E;AAC9E,eAAO,MAAM,cAAc,EAAE,KAS5B,CAAC;AAEF,iDAAiD;AACjD,eAAO,MAAM,cAAc,EAAE,KAY5B,CAAC;AAEF,wDAAwD;AACxD,eAAO,MAAM,iBAAiB,EAAE,KAS/B,CAAC;AAEF,qEAAqE;AACrE,eAAO,MAAM,eAAe,EAAE,KAS7B,CAAC;AAEF;;;GAGG;AACH,wBAAgB,WAAW,CAAC,KAAK,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAIjE"}
@@ -1,3 +1,10 @@
1
+ import { DEFAULT_ORG_ID } from "../auth/org.js";
2
+ /**
3
+ * Organization ID used in test fixtures. Tests use the deprecated DEFAULT_ORG_ID
4
+ * because ensureDefaultOrg() creates this org in test setup. When RFC-060 Phase 6
5
+ * removes DEFAULT_ORG_ID, test setup will create a real org via Better Auth API.
6
+ */
7
+ export const TEST_ORG_ID = DEFAULT_ORG_ID;
1
8
  /** Admin with wildcard permissions. Use for setup operations in beforeAll. */
2
9
  export const testAdminActor = {
3
10
  type: "user",
@@ -5,7 +12,7 @@ export const testAdminActor = {
5
12
  email: "admin@test.local",
6
13
  name: "Test Admin",
7
14
  vendorId: null,
8
- organizationId: "org_default",
15
+ organizationId: TEST_ORG_ID,
9
16
  role: "admin",
10
17
  permissions: ["*:*"],
11
18
  };
@@ -16,7 +23,7 @@ export const testStaffActor = {
16
23
  email: "staff@test.local",
17
24
  name: "Test Staff",
18
25
  vendorId: null,
19
- organizationId: "org_default",
26
+ organizationId: TEST_ORG_ID,
20
27
  role: "staff",
21
28
  permissions: [
22
29
  "catalog:read", "catalog:create", "catalog:update",
@@ -30,7 +37,7 @@ export const testCustomerActor = {
30
37
  email: "customer@test.local",
31
38
  name: "Test Customer",
32
39
  vendorId: null,
33
- organizationId: "org_default",
40
+ organizationId: TEST_ORG_ID,
34
41
  role: "customer",
35
42
  permissions: ["catalog:read", "cart:create", "cart:read", "orders:read:own"],
36
43
  };
@@ -41,7 +48,7 @@ export const testNoPermActor = {
41
48
  email: "noperm@test.local",
42
49
  name: "No Permissions",
43
50
  vendorId: null,
44
- organizationId: "org_default",
51
+ organizationId: TEST_ORG_ID,
45
52
  role: "customer",
46
53
  permissions: [],
47
54
  };
package/dist/testing.d.ts CHANGED
@@ -9,6 +9,6 @@ export { createTestKernel } from "./test-utils/create-test-kernel.js";
9
9
  export { createTestPluginContext } from "./test-utils/create-test-plugin-context.js";
10
10
  export { createRepositoryTestHarness } from "./test-utils/create-repository-test-harness.js";
11
11
  export { createPluginTestApp, type PluginTestApp, type TestAppEnv } from "./test-utils/create-plugin-test-app.js";
12
- export { testAdminActor, testStaffActor, testCustomerActor, testNoPermActor, jsonHeaders, } from "./test-utils/test-actors.js";
12
+ export { TEST_ORG_ID, testAdminActor, testStaffActor, testCustomerActor, testNoPermActor, jsonHeaders, } from "./test-utils/test-actors.js";
13
13
  export { beforeHook, afterHook } from "./test-utils/typed-hooks.js";
14
14
  //# sourceMappingURL=testing.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["../src/testing.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AACtE,OAAO,EAAE,uBAAuB,EAAE,MAAM,4CAA4C,CAAC;AACrF,OAAO,EAAE,2BAA2B,EAAE,MAAM,gDAAgD,CAAC;AAC7F,OAAO,EAAE,mBAAmB,EAAE,KAAK,aAAa,EAAE,KAAK,UAAU,EAAE,MAAM,wCAAwC,CAAC;AAClH,OAAO,EACL,cAAc,EAAE,cAAc,EAAE,iBAAiB,EAAE,eAAe,EAClE,WAAW,GACZ,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC"}
1
+ {"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["../src/testing.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AACtE,OAAO,EAAE,uBAAuB,EAAE,MAAM,4CAA4C,CAAC;AACrF,OAAO,EAAE,2BAA2B,EAAE,MAAM,gDAAgD,CAAC;AAC7F,OAAO,EAAE,mBAAmB,EAAE,KAAK,aAAa,EAAE,KAAK,UAAU,EAAE,MAAM,wCAAwC,CAAC;AAClH,OAAO,EACL,WAAW,EACX,cAAc,EAAE,cAAc,EAAE,iBAAiB,EAAE,eAAe,EAClE,WAAW,GACZ,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC"}
package/dist/testing.js CHANGED
@@ -9,5 +9,5 @@ export { createTestKernel } from "./test-utils/create-test-kernel.js";
9
9
  export { createTestPluginContext } from "./test-utils/create-test-plugin-context.js";
10
10
  export { createRepositoryTestHarness } from "./test-utils/create-repository-test-harness.js";
11
11
  export { createPluginTestApp } from "./test-utils/create-plugin-test-app.js";
12
- export { testAdminActor, testStaffActor, testCustomerActor, testNoPermActor, jsonHeaders, } from "./test-utils/test-actors.js";
12
+ export { TEST_ORG_ID, testAdminActor, testStaffActor, testCustomerActor, testNoPermActor, jsonHeaders, } from "./test-utils/test-actors.js";
13
13
  export { beforeHook, afterHook } from "./test-utils/typed-hooks.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unifiedcommerce/core",
3
- "version": "0.5.4",
3
+ "version": "0.5.5",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {
package/src/auth/org.ts CHANGED
@@ -1,21 +1,35 @@
1
1
  import { OrganizationService } from "../modules/organization/service.js";
2
2
 
3
3
  /**
4
- * @deprecated Use `config.auth.defaultOrganizationId` instead.
5
- * This constant will be removed in the next major version.
6
- * See RFC-060 for migration details.
4
+ * @deprecated Will be removed. Use `config.auth.defaultOrganizationId` instead.
5
+ * Kept only for test utilities and backwards compatibility.
7
6
  */
8
7
  export const DEFAULT_ORG_ID = "org_default";
9
8
 
10
- let hasLoggedDeprecation = false;
9
+ /**
10
+ * Module-level default set once at boot by `setBootDefaultOrgId()`.
11
+ * Allows resolveOrgId to use the config value without requiring
12
+ * every service caller to pass it explicitly.
13
+ */
14
+ let _bootDefaultOrgId: string | undefined;
15
+
16
+ /**
17
+ * Called once at boot by createCommerce/createServer to register
18
+ * the config-driven default org ID. This bridges the gap between
19
+ * config (available at boot) and services (which don't have config access).
20
+ */
21
+ export function setBootDefaultOrgId(orgId: string): void {
22
+ _bootDefaultOrgId = orgId;
23
+ }
11
24
 
12
25
  /**
13
26
  * Extracts the organization ID from an actor.
14
27
  *
15
28
  * Resolution order:
16
- * 1. Actor's organizationId (set by middleware from session/API key)
17
- * 2. Explicit defaultOrgId parameter (from config.auth.defaultOrganizationId)
18
- * 3. Deprecated fallback to "org_default" (logs warning once)
29
+ * 1. Actor's organizationId (set by middleware from session/API key/storeResolver)
30
+ * 2. Explicit defaultOrgId parameter (caller override)
31
+ * 3. Boot-time default (from config.auth.defaultOrganizationId via setBootDefaultOrgId)
32
+ * 4. Deprecated fallback to DEFAULT_ORG_ID (will be removed)
19
33
  */
20
34
  export function resolveOrgId(actor: unknown, defaultOrgId?: string): string {
21
35
  if (actor != null && typeof actor === "object" && "organizationId" in actor) {
@@ -23,25 +37,13 @@ export function resolveOrgId(actor: unknown, defaultOrgId?: string): string {
23
37
  if (typeof orgId === "string") return orgId;
24
38
  }
25
39
  if (defaultOrgId) return defaultOrgId;
26
-
27
- // Deprecated fallback — will become an error in next major version
28
- if (!hasLoggedDeprecation) {
29
- hasLoggedDeprecation = true;
30
- console.warn(
31
- "[UC DEPRECATION] resolveOrgId() fell back to 'org_default'. " +
32
- "Set auth.defaultOrganizationId in your commerce config. " +
33
- "This fallback will be removed in the next major version. See RFC-060.",
34
- );
35
- }
40
+ if (_bootDefaultOrgId) return _bootDefaultOrgId;
36
41
  return DEFAULT_ORG_ID;
37
42
  }
38
43
 
39
44
  /**
40
45
  * @deprecated Use seed script with `auth.api.createOrganization()` instead.
41
- * This function will be removed in the next major version. See RFC-060.
42
- *
43
- * Ensures the default organization row exists in the database.
44
- * Idempotent — safe to call multiple times.
46
+ * Kept for backwards compatibility during migration. Will be removed.
45
47
  */
46
48
  export async function ensureDefaultOrg(
47
49
  db: unknown,
@@ -2,7 +2,7 @@ import type { Actor } from "../auth/types.js";
2
2
  import type { CommerceConfig } from "../config/types.js";
3
3
  import type { Kernel } from "./kernel.js";
4
4
  import { createKernel } from "./kernel.js";
5
- import { ensureDefaultOrg } from "../auth/org.js";
5
+ import { ensureDefaultOrg, setBootDefaultOrgId } from "../auth/org.js";
6
6
  import { createAuth, type AuthInstance } from "../auth/setup.js";
7
7
  import { createLogger, type Logger } from "./logger.js";
8
8
  import { createLocalAPI, type CommerceLocalAPI, type LocalAPIOptions } from "../kernel/local-api.js";
@@ -121,10 +121,13 @@ export async function createCommerce(
121
121
  ): Promise<CommerceInstance> {
122
122
  const kernel = createKernel(config);
123
123
 
124
- // If no explicit org ID is configured, fall back to legacy ensureDefaultOrg behavior
125
- // with a deprecation warning. New deployments should use seed scripts with
126
- // auth.api.createOrganization() and set config.auth.defaultOrganizationId.
127
- if (!config.auth?.defaultOrganizationId) {
124
+ // Register the config-driven org ID so resolveOrgId() can use it
125
+ // without requiring every service to have config access.
126
+ if (config.auth?.defaultOrganizationId) {
127
+ setBootDefaultOrgId(config.auth.defaultOrganizationId);
128
+ } else {
129
+ // Legacy fallback: auto-create org_default for deployments
130
+ // that haven't migrated to seed-based org creation yet.
128
131
  await ensureDefaultOrg(kernel.database.db, config.storeName);
129
132
  }
130
133
 
@@ -64,6 +64,7 @@ export async function createTestConfig(
64
64
  provider: "postgresql",
65
65
  },
66
66
  auth: {
67
+ defaultOrganizationId: "org_default",
67
68
  requireEmailVerification: false,
68
69
  apiKeys: { enabled: true, defaultPermissions: ["catalog:read"] },
69
70
  posPin: { enabled: true },
@@ -1,4 +1,12 @@
1
1
  import type { Actor } from "../auth/types.js";
2
+ import { DEFAULT_ORG_ID } from "../auth/org.js";
3
+
4
+ /**
5
+ * Organization ID used in test fixtures. Tests use the deprecated DEFAULT_ORG_ID
6
+ * because ensureDefaultOrg() creates this org in test setup. When RFC-060 Phase 6
7
+ * removes DEFAULT_ORG_ID, test setup will create a real org via Better Auth API.
8
+ */
9
+ export const TEST_ORG_ID = DEFAULT_ORG_ID;
2
10
 
3
11
  /** Admin with wildcard permissions. Use for setup operations in beforeAll. */
4
12
  export const testAdminActor: Actor = {
@@ -7,7 +15,7 @@ export const testAdminActor: Actor = {
7
15
  email: "admin@test.local",
8
16
  name: "Test Admin",
9
17
  vendorId: null,
10
- organizationId: "org_default",
18
+ organizationId: TEST_ORG_ID,
11
19
  role: "admin",
12
20
  permissions: ["*:*"],
13
21
  };
@@ -19,7 +27,7 @@ export const testStaffActor: Actor = {
19
27
  email: "staff@test.local",
20
28
  name: "Test Staff",
21
29
  vendorId: null,
22
- organizationId: "org_default",
30
+ organizationId: TEST_ORG_ID,
23
31
  role: "staff",
24
32
  permissions: [
25
33
  "catalog:read", "catalog:create", "catalog:update",
@@ -34,7 +42,7 @@ export const testCustomerActor: Actor = {
34
42
  email: "customer@test.local",
35
43
  name: "Test Customer",
36
44
  vendorId: null,
37
- organizationId: "org_default",
45
+ organizationId: TEST_ORG_ID,
38
46
  role: "customer",
39
47
  permissions: ["catalog:read", "cart:create", "cart:read", "orders:read:own"],
40
48
  };
@@ -46,7 +54,7 @@ export const testNoPermActor: Actor = {
46
54
  email: "noperm@test.local",
47
55
  name: "No Permissions",
48
56
  vendorId: null,
49
- organizationId: "org_default",
57
+ organizationId: TEST_ORG_ID,
50
58
  role: "customer",
51
59
  permissions: [],
52
60
  };
package/src/testing.ts CHANGED
@@ -11,6 +11,7 @@ export { createTestPluginContext } from "./test-utils/create-test-plugin-context
11
11
  export { createRepositoryTestHarness } from "./test-utils/create-repository-test-harness.js";
12
12
  export { createPluginTestApp, type PluginTestApp, type TestAppEnv } from "./test-utils/create-plugin-test-app.js";
13
13
  export {
14
+ TEST_ORG_ID,
14
15
  testAdminActor, testStaffActor, testCustomerActor, testNoPermActor,
15
16
  jsonHeaders,
16
17
  } from "./test-utils/test-actors.js";