@porulle/core 0.8.0 → 0.9.0
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/dist/auth/middleware.d.ts.map +1 -1
- package/dist/auth/middleware.js +26 -7
- package/dist/auth/setup.d.ts.map +1 -1
- package/dist/auth/setup.js +7 -5
- package/dist/config/defaults.d.ts.map +1 -1
- package/dist/config/defaults.js +2 -0
- package/dist/config/types.d.ts +9 -0
- package/dist/config/types.d.ts.map +1 -1
- package/dist/hooks/checkout-completion.d.ts.map +1 -1
- package/dist/hooks/checkout-completion.js +2 -2
- package/dist/hooks/checkout.d.ts.map +1 -1
- package/dist/hooks/checkout.js +1 -1
- package/dist/interfaces/rest/routes/admin/staff.d.ts.map +1 -1
- package/dist/interfaces/rest/routes/admin/staff.js +37 -3
- package/dist/interfaces/rest/routes/checkout.d.ts +9 -0
- package/dist/interfaces/rest/routes/checkout.d.ts.map +1 -1
- package/dist/interfaces/rest/routes/checkout.js +81 -22
- package/dist/interfaces/rest/routes/inventory.d.ts.map +1 -1
- package/dist/interfaces/rest/routes/inventory.js +13 -0
- package/dist/interfaces/rest/routes/orders.d.ts.map +1 -1
- package/dist/interfaces/rest/routes/orders.js +13 -0
- package/dist/interfaces/rest/schemas/orders.js +2 -2
- package/dist/interfaces/rest/schemas/responses.d.ts +34 -0
- package/dist/interfaces/rest/schemas/responses.d.ts.map +1 -1
- package/dist/kernel/database/scoped-db.d.ts +2 -1
- package/dist/kernel/database/scoped-db.d.ts.map +1 -1
- package/dist/kernel/database/scoped-db.js +62 -1
- package/dist/kernel/plugin/manifest.d.ts +3 -0
- package/dist/kernel/plugin/manifest.d.ts.map +1 -1
- package/dist/modules/analytics/drizzle-adapter.d.ts.map +1 -1
- package/dist/modules/analytics/drizzle-adapter.js +16 -3
- package/dist/modules/cart/service.d.ts.map +1 -1
- package/dist/modules/cart/service.js +3 -2
- package/dist/modules/catalog/entity-service.d.ts.map +1 -1
- package/dist/modules/catalog/entity-service.js +34 -2
- package/dist/modules/customers/service.d.ts.map +1 -1
- package/dist/modules/customers/service.js +6 -0
- package/dist/modules/orders/schema.d.ts +17 -0
- package/dist/modules/orders/schema.d.ts.map +1 -1
- package/dist/modules/orders/schema.js +4 -0
- package/dist/modules/orders/service.d.ts +16 -2
- package/dist/modules/orders/service.d.ts.map +1 -1
- package/dist/modules/orders/service.js +223 -26
- package/dist/modules/orders/stale-order-cleanup.d.ts.map +1 -1
- package/dist/modules/orders/stale-order-cleanup.js +13 -1
- package/dist/modules/pricing/service.d.ts.map +1 -1
- package/dist/modules/pricing/service.js +5 -5
- package/dist/test-utils/create-test-config.d.ts.map +1 -1
- package/dist/test-utils/create-test-config.js +2 -0
- package/dist/test-utils/order-test-helpers.d.ts +12 -0
- package/dist/test-utils/order-test-helpers.d.ts.map +1 -0
- package/dist/test-utils/order-test-helpers.js +18 -0
- package/dist/test-utils/rest-api-test-utils.d.ts.map +1 -1
- package/dist/test-utils/rest-api-test-utils.js +1 -0
- package/dist/test-utils/test-actors.js +1 -1
- package/dist/testing.d.ts +1 -0
- package/dist/testing.d.ts.map +1 -1
- package/dist/testing.js +1 -0
- package/package.json +1 -1
- package/src/auth/middleware.ts +26 -7
- package/src/auth/setup.ts +10 -4
- package/src/config/defaults.ts +2 -0
- package/src/config/types.ts +9 -0
- package/src/hooks/checkout-completion.ts +22 -16
- package/src/hooks/checkout.ts +11 -8
- package/src/interfaces/rest/routes/admin/staff.ts +45 -3
- package/src/interfaces/rest/routes/checkout.ts +93 -28
- package/src/interfaces/rest/routes/inventory.ts +14 -0
- package/src/interfaces/rest/routes/orders.ts +11 -0
- package/src/interfaces/rest/schemas/orders.ts +2 -2
- package/src/kernel/database/scoped-db.ts +70 -1
- package/src/kernel/plugin/manifest.ts +3 -0
- package/src/modules/analytics/drizzle-adapter.ts +19 -3
- package/src/modules/cart/service.ts +3 -2
- package/src/modules/catalog/entity-service.ts +28 -1
- package/src/modules/customers/service.ts +6 -0
- package/src/modules/orders/schema.ts +4 -0
- package/src/modules/orders/service.ts +408 -64
- package/src/modules/orders/stale-order-cleanup.ts +18 -4
- package/src/modules/pricing/service.ts +5 -6
- package/src/test-utils/create-test-config.ts +2 -0
- package/src/test-utils/order-test-helpers.ts +26 -0
- package/src/test-utils/rest-api-test-utils.ts +1 -0
- package/src/test-utils/test-actors.ts +1 -1
- package/src/testing.ts +1 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../../src/auth/middleware.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,MAAM,CAAC;AAC9C,OAAO,KAAK,EAAmB,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAE1E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAkC/C,wBAAgB,cAAc,CAC5B,IAAI,EAAE,YAAY,EAClB,MAAM,EAAE,cAAc,GACrB,iBAAiB,
|
|
1
|
+
{"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../../src/auth/middleware.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,MAAM,CAAC;AAC9C,OAAO,KAAK,EAAmB,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAE1E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAkC/C,wBAAgB,cAAc,CAC5B,IAAI,EAAE,YAAY,EAClB,MAAM,EAAE,cAAc,GACrB,iBAAiB,CA4PnB"}
|
package/dist/auth/middleware.js
CHANGED
|
@@ -27,10 +27,10 @@ export function authMiddleware(auth, config) {
|
|
|
27
27
|
return async (c, next) => {
|
|
28
28
|
// Resolve the default org from config, falling back to deprecated constant
|
|
29
29
|
const defaultOrgId = config.auth?.defaultOrganizationId ?? DEFAULT_ORG_ID;
|
|
30
|
-
// Test-only actor injection: NODE_ENV === "test"
|
|
31
|
-
//
|
|
32
|
-
//
|
|
33
|
-
if (process.env.NODE_ENV === "test") {
|
|
30
|
+
// Test-only actor injection: requires NODE_ENV === "test" AND an explicit
|
|
31
|
+
// config opt-in so staging/preview deployments left as NODE_ENV=test do not
|
|
32
|
+
// silently become a full auth bypass.
|
|
33
|
+
if (process.env.NODE_ENV === "test" && config.auth?.allowTestActor) {
|
|
34
34
|
const testActorHeader = c.req.header("x-test-actor");
|
|
35
35
|
if (testActorHeader) {
|
|
36
36
|
try {
|
|
@@ -146,10 +146,29 @@ export function authMiddleware(auth, config) {
|
|
|
146
146
|
});
|
|
147
147
|
if (result?.valid && result.key) {
|
|
148
148
|
const apiKey = result.key;
|
|
149
|
-
// v1.5+ renamed userId → referenceId on the apikey table.
|
|
150
|
-
const userId = (apiKey.referenceId ?? "");
|
|
151
149
|
const name = (apiKey.name ?? "API Key");
|
|
152
|
-
|
|
150
|
+
// Read the org (and operator identity) from key metadata when present.
|
|
151
|
+
// POS shift keys carry { organizationId, operatorId } in metadata so the
|
|
152
|
+
// operator is scoped to their store WITHOUT any org membership/role
|
|
153
|
+
// (SEC-16 / R-01). Other keys fall back to the key's organizationId.
|
|
154
|
+
const rawMeta = apiKey.metadata;
|
|
155
|
+
const meta = rawMeta && typeof rawMeta === "object"
|
|
156
|
+
? rawMeta
|
|
157
|
+
: typeof rawMeta === "string"
|
|
158
|
+
? (() => {
|
|
159
|
+
try {
|
|
160
|
+
return JSON.parse(rawMeta);
|
|
161
|
+
}
|
|
162
|
+
catch {
|
|
163
|
+
return null;
|
|
164
|
+
}
|
|
165
|
+
})()
|
|
166
|
+
: null;
|
|
167
|
+
const metaOrg = typeof meta?.organizationId === "string" ? meta.organizationId : undefined;
|
|
168
|
+
const orgId = (metaOrg ?? apiKey.organizationId ?? defaultOrgId);
|
|
169
|
+
const userId = ((typeof meta?.operatorId === "string" ? meta.operatorId : undefined)
|
|
170
|
+
?? apiKey.referenceId
|
|
171
|
+
?? "");
|
|
153
172
|
// Better Auth stores permissions as Record<string, string[]>
|
|
154
173
|
// (e.g. {"catalog":["read","create"]}). Flatten to the
|
|
155
174
|
// "resource:action" string[] format the engine expects.
|
package/dist/auth/setup.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../src/auth/setup.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,WAAW,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AACxF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAiBrE;;;;;GAKG;AACH,KAAK,cAAc,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC;IACjD,OAAO,EAAE;QACP,UAAU,CAAC,OAAO,YAAY,CAAC;QAC/B,UAAU,CAAC,OAAO,MAAM,CAAC;QACzB,UAAU,CAAC,OAAO,GAAG,CAAC;QACtB,UAAU,CAAC,OAAO,SAAS,CAAC;QAC5B,UAAU,CAAC,OAAO,MAAM,CAAC;QACzB,UAAU,CAAC,OAAO,WAAW,CAAC;KAC/B,CAAC;CACH,CAAC,CAAC,CAAC;AAEJ;;;GAGG;AACH,MAAM,MAAM,YAAY,GAAG,cAAc,CAAC;AAE1C,wBAAgB,UAAU,CACxB,EAAE,EAAE,eAAe,EACnB,MAAM,EAAE,cAAc,GACrB,YAAY,
|
|
1
|
+
{"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../src/auth/setup.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,WAAW,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AACxF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAiBrE;;;;;GAKG;AACH,KAAK,cAAc,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC;IACjD,OAAO,EAAE;QACP,UAAU,CAAC,OAAO,YAAY,CAAC;QAC/B,UAAU,CAAC,OAAO,MAAM,CAAC;QACzB,UAAU,CAAC,OAAO,GAAG,CAAC;QACtB,UAAU,CAAC,OAAO,SAAS,CAAC;QAC5B,UAAU,CAAC,OAAO,MAAM,CAAC;QACzB,UAAU,CAAC,OAAO,WAAW,CAAC;KAC/B,CAAC;CACH,CAAC,CAAC,CAAC;AAEJ;;;GAGG;AACH,MAAM,MAAM,YAAY,GAAG,cAAc,CAAC;AAE1C,wBAAgB,UAAU,CACxB,EAAE,EAAE,eAAe,EACnB,MAAM,EAAE,cAAc,GACrB,YAAY,CAgJd"}
|
package/dist/auth/setup.js
CHANGED
|
@@ -6,11 +6,7 @@ import * as authSchema from "./auth-schema.js";
|
|
|
6
6
|
function resolveAuthDbProvider(provider) {
|
|
7
7
|
if (provider === "postgres" || provider === "postgresql" || provider === "pg")
|
|
8
8
|
return "pg";
|
|
9
|
-
|
|
10
|
-
return "mysql";
|
|
11
|
-
if (provider === "sqlite")
|
|
12
|
-
return "sqlite";
|
|
13
|
-
throw new Error(`Unsupported auth database provider "${provider}".`);
|
|
9
|
+
throw new Error(`Unsupported auth database provider "${provider}". Only PostgreSQL is supported.`);
|
|
14
10
|
}
|
|
15
11
|
export function createAuth(db, config) {
|
|
16
12
|
if (process.env.NODE_ENV === "production" &&
|
|
@@ -42,6 +38,12 @@ export function createAuth(db, config) {
|
|
|
42
38
|
}
|
|
43
39
|
: {}),
|
|
44
40
|
...(scope.keyExpiration ? { keyExpiration: scope.keyExpiration } : {}),
|
|
41
|
+
...("references" in scope && scope.references
|
|
42
|
+
? { references: scope.references }
|
|
43
|
+
: {}),
|
|
44
|
+
...(scope.enableMetadata || scope.references === "organization"
|
|
45
|
+
? { enableMetadata: true }
|
|
46
|
+
: {}),
|
|
45
47
|
}));
|
|
46
48
|
plugins.push(apiKey(apiKeyConfigs));
|
|
47
49
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"defaults.d.ts","sourceRoot":"","sources":["../../src/config/defaults.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,eAAO,MAAM,aAAa,EAAE,OAAO,CAAC,cAAc,
|
|
1
|
+
{"version":3,"file":"defaults.d.ts","sourceRoot":"","sources":["../../src/config/defaults.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,eAAO,MAAM,aAAa,EAAE,OAAO,CAAC,cAAc,CAyFjD,CAAC"}
|
package/dist/config/defaults.js
CHANGED
package/dist/config/types.d.ts
CHANGED
|
@@ -105,6 +105,10 @@ export interface ApiKeyScopeDefinition {
|
|
|
105
105
|
minExpiresIn?: number;
|
|
106
106
|
maxExpiresIn?: number;
|
|
107
107
|
};
|
|
108
|
+
/** Better Auth ownership model — POS shift keys bind to an organization. */
|
|
109
|
+
references?: "user" | "organization";
|
|
110
|
+
/** Allow metadata on keys minted under this scope (e.g. operatorId on POS shift keys). */
|
|
111
|
+
enableMetadata?: boolean;
|
|
108
112
|
}
|
|
109
113
|
export interface AuthConfig {
|
|
110
114
|
/**
|
|
@@ -219,6 +223,11 @@ export interface AuthConfig {
|
|
|
219
223
|
* Appended to the core plugin list (organization, bearer, jwt, etc.).
|
|
220
224
|
*/
|
|
221
225
|
extraAuthPlugins?: unknown[];
|
|
226
|
+
/**
|
|
227
|
+
* When true (and NODE_ENV === "test"), the `x-test-actor` header may inject
|
|
228
|
+
* a trusted actor for integration tests. Default false.
|
|
229
|
+
*/
|
|
230
|
+
allowTestActor?: boolean;
|
|
222
231
|
}
|
|
223
232
|
export interface CartConfig {
|
|
224
233
|
ttlMinutes?: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/config/types.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/config/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"checkout-completion.d.ts","sourceRoot":"","sources":["../../src/hooks/checkout-completion.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,iCAAiC,CAAC;AAC5D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAgDlD;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,oBAAoB,EAAE,IAAI,CACrC,YAAY,EACZ,oBAAoB,EAAE,
|
|
1
|
+
{"version":3,"file":"checkout-completion.d.ts","sourceRoot":"","sources":["../../src/hooks/checkout-completion.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,iCAAiC,CAAC;AAC5D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAgDlD;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,oBAAoB,EAAE,IAAI,CACrC,YAAY,EACZ,oBAAoB,EAAE,CAyDvB,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,kBAAkB,EAAE,IAAI,CACnC,YAAY,EACZ;IAAE,eAAe,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAsD5C,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,uBAAuB,EAAE,IAAI,CACxC,YAAY,EACZ;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,CAwBpB,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB,EAAE,IAAI,CACrC,YAAY,EACZ;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,CA+ClB,CAAC"}
|
|
@@ -23,7 +23,7 @@ export const reserveInventoryStep = {
|
|
|
23
23
|
quantity: item.quantity,
|
|
24
24
|
orderId: data.checkoutId,
|
|
25
25
|
performedBy,
|
|
26
|
-
});
|
|
26
|
+
}, ctx.hook.actor);
|
|
27
27
|
if (!result.ok) {
|
|
28
28
|
return Err(new CommerceValidationError(`Inventory reservation failed for ${item.title ?? item.entityId}: ${result.error?.message ?? "unknown"}`));
|
|
29
29
|
}
|
|
@@ -46,7 +46,7 @@ export const reserveInventoryStep = {
|
|
|
46
46
|
quantity: r.quantity,
|
|
47
47
|
orderId: r.orderId,
|
|
48
48
|
performedBy,
|
|
49
|
-
});
|
|
49
|
+
}, ctx.hook.actor);
|
|
50
50
|
}
|
|
51
51
|
},
|
|
52
52
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"checkout.d.ts","sourceRoot":"","sources":["../../src/hooks/checkout.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"checkout.d.ts","sourceRoot":"","sources":["../../src/hooks/checkout.ts"],"names":[],"mappings":"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"}
|
package/dist/hooks/checkout.js
CHANGED
|
@@ -243,7 +243,7 @@ export const reserveInventory = async ({ result, context }) => {
|
|
|
243
243
|
quantity: lineItem.quantity,
|
|
244
244
|
orderId: result.id,
|
|
245
245
|
performedBy: context.actor?.userId ?? "system",
|
|
246
|
-
});
|
|
246
|
+
}, context.actor);
|
|
247
247
|
}
|
|
248
248
|
};
|
|
249
249
|
export const initiateFulfillment = async ({ result, context, }) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"staff.d.ts","sourceRoot":"","sources":["../../../../../src/interfaces/rest/routes/admin/staff.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,+BAA+B,CAAC;AAe5D,OAAO,EAAE,KAAK,MAAM,EAAe,MAAM,gBAAgB,CAAC;AAE1D;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"staff.d.ts","sourceRoot":"","sources":["../../../../../src/interfaces/rest/routes/admin/staff.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,+BAA+B,CAAC;AAe5D,OAAO,EAAE,KAAK,MAAM,EAAe,MAAM,gBAAgB,CAAC;AAE1D;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,gCAyO9C"}
|
|
@@ -36,6 +36,25 @@ export function adminStaffRoutes(kernel) {
|
|
|
36
36
|
},
|
|
37
37
|
}, 422);
|
|
38
38
|
}
|
|
39
|
+
const BUILTIN_ROLE_RANK = {
|
|
40
|
+
owner: 3,
|
|
41
|
+
admin: 2,
|
|
42
|
+
};
|
|
43
|
+
const CUSTOM_ROLE_RANK = 1;
|
|
44
|
+
function roleRank(role) {
|
|
45
|
+
return BUILTIN_ROLE_RANK[role] ?? CUSTOM_ROLE_RANK;
|
|
46
|
+
}
|
|
47
|
+
function canGrantRole(actorRole, targetRole) {
|
|
48
|
+
return roleRank(actorRole) >= roleRank(targetRole);
|
|
49
|
+
}
|
|
50
|
+
function insufficientPrivilege(c, targetRole) {
|
|
51
|
+
return c.json({
|
|
52
|
+
error: {
|
|
53
|
+
code: "FORBIDDEN",
|
|
54
|
+
message: `Cannot assign role "${targetRole}": your role does not have sufficient privilege.`,
|
|
55
|
+
},
|
|
56
|
+
}, 403);
|
|
57
|
+
}
|
|
39
58
|
async function countOwners(orgId) {
|
|
40
59
|
const rows = await db
|
|
41
60
|
.select({ id: member.id })
|
|
@@ -62,9 +81,12 @@ export function adminStaffRoutes(kernel) {
|
|
|
62
81
|
// @ts-expect-error -- openapi handler union return type
|
|
63
82
|
router.openapi(createStaffRoute, async (c) => {
|
|
64
83
|
const body = c.req.valid("json");
|
|
65
|
-
const
|
|
84
|
+
const actor = c.get("actor");
|
|
85
|
+
const orgId = resolveOrgId(actor);
|
|
66
86
|
if (!validRoles().has(body.role))
|
|
67
87
|
return invalidRole(c, body.role);
|
|
88
|
+
if (!canGrantRole(actor.role, body.role))
|
|
89
|
+
return insufficientPrivilege(c, body.role);
|
|
68
90
|
const users = await db.select().from(user).where(eq(user.id, body.userId));
|
|
69
91
|
if (users.length === 0) {
|
|
70
92
|
return c.json({ error: { code: "NOT_FOUND", message: "User not found." } }, 404);
|
|
@@ -128,10 +150,13 @@ export function adminStaffRoutes(kernel) {
|
|
|
128
150
|
// @ts-expect-error -- openapi handler union return type
|
|
129
151
|
router.openapi(updateStaffRoleRoute, async (c) => {
|
|
130
152
|
const body = c.req.valid("json");
|
|
131
|
-
const
|
|
153
|
+
const actor = c.get("actor");
|
|
154
|
+
const orgId = resolveOrgId(actor);
|
|
132
155
|
const id = c.req.param("id");
|
|
133
156
|
if (!validRoles().has(body.role))
|
|
134
157
|
return invalidRole(c, body.role);
|
|
158
|
+
if (!canGrantRole(actor.role, body.role))
|
|
159
|
+
return insufficientPrivilege(c, body.role);
|
|
135
160
|
const rows = await db
|
|
136
161
|
.select()
|
|
137
162
|
.from(member)
|
|
@@ -140,6 +165,10 @@ export function adminStaffRoutes(kernel) {
|
|
|
140
165
|
if (!target) {
|
|
141
166
|
return c.json({ error: { code: "NOT_FOUND", message: "Staff member not found." } }, 404);
|
|
142
167
|
}
|
|
168
|
+
// SEC-18/R-02: the actor must also outrank (or equal) the target's CURRENT
|
|
169
|
+
// role, else an admin could demote an owner they do not outrank.
|
|
170
|
+
if (!canGrantRole(actor.role, target.role))
|
|
171
|
+
return insufficientPrivilege(c, target.role);
|
|
143
172
|
if (target.role === "owner" && body.role !== "owner" && (await countOwners(orgId)) <= 1) {
|
|
144
173
|
return c.json({ error: { code: "VALIDATION_FAILED", message: "Cannot demote the organization's last owner." } }, 422);
|
|
145
174
|
}
|
|
@@ -152,7 +181,8 @@ export function adminStaffRoutes(kernel) {
|
|
|
152
181
|
});
|
|
153
182
|
// @ts-expect-error -- openapi handler union return type
|
|
154
183
|
router.openapi(revokeStaffRoute, async (c) => {
|
|
155
|
-
const
|
|
184
|
+
const actor = c.get("actor");
|
|
185
|
+
const orgId = resolveOrgId(actor);
|
|
156
186
|
const id = c.req.param("id");
|
|
157
187
|
const rows = await db
|
|
158
188
|
.select()
|
|
@@ -162,6 +192,10 @@ export function adminStaffRoutes(kernel) {
|
|
|
162
192
|
if (!target) {
|
|
163
193
|
return c.json({ error: { code: "NOT_FOUND", message: "Staff member not found." } }, 404);
|
|
164
194
|
}
|
|
195
|
+
// SEC-18/R-02: the actor must outrank (or equal) the target's current role
|
|
196
|
+
// to revoke it — an admin cannot revoke an owner.
|
|
197
|
+
if (!canGrantRole(actor.role, target.role))
|
|
198
|
+
return insufficientPrivilege(c, target.role);
|
|
165
199
|
if (target.role === "owner" && (await countOwners(orgId)) <= 1) {
|
|
166
200
|
return c.json({ error: { code: "VALIDATION_FAILED", message: "Cannot revoke the organization's last owner." } }, 422);
|
|
167
201
|
}
|
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
import { OpenAPIHono } from "@hono/zod-openapi";
|
|
2
2
|
import type { Kernel } from "../../../runtime/kernel.js";
|
|
3
3
|
import { type AppEnv } from "../utils.js";
|
|
4
|
+
import type { Actor } from "../../../auth/types.js";
|
|
5
|
+
/**
|
|
6
|
+
* SEC-07 — resolve the customer profile a checkout order is attributed to.
|
|
7
|
+
* A self-service actor may ONLY attribute the order to its own customer
|
|
8
|
+
* profile; only actors with org-level `customers:read` (staff/clienteling) may
|
|
9
|
+
* name an arbitrary `customerId`. Returns undefined for guests / unresolved
|
|
10
|
+
* (guest checkout). Exported for unit testing.
|
|
11
|
+
*/
|
|
12
|
+
export declare function resolveCheckoutCustomerUuid(customers: Kernel["services"]["customers"], actor: Actor | null, customerId: string | undefined): Promise<string | undefined>;
|
|
4
13
|
export declare function checkoutRoutes(kernel: Kernel): OpenAPIHono<AppEnv, {}, "/">;
|
|
5
14
|
//# sourceMappingURL=checkout.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"checkout.d.ts","sourceRoot":"","sources":["../../../../src/interfaces/rest/routes/checkout.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAC;AAoBzD,OAAO,EAAE,KAAK,MAAM,EAAwC,MAAM,aAAa,CAAC;AAKhF,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"checkout.d.ts","sourceRoot":"","sources":["../../../../src/interfaces/rest/routes/checkout.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAC;AAoBzD,OAAO,EAAE,KAAK,MAAM,EAAwC,MAAM,aAAa,CAAC;AAKhF,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,wBAAwB,CAAC;AAEpD;;;;;;GAMG;AACH,wBAAsB,2BAA2B,CAC/C,SAAS,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC,WAAW,CAAC,EAC1C,KAAK,EAAE,KAAK,GAAG,IAAI,EACnB,UAAU,EAAE,MAAM,GAAG,SAAS,GAC7B,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAmC7B;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,gCA2S5C"}
|
|
@@ -5,7 +5,52 @@ import { runAfterHooks, runBeforeHooks } from "../../../kernel/hooks/executor.js
|
|
|
5
5
|
import { createHookContext } from "../../../kernel/hooks/create-context.js";
|
|
6
6
|
import { mapErrorToResponse, mapErrorToStatus } from "../utils.js";
|
|
7
7
|
import { isCommerceError } from "../../../kernel/errors.js";
|
|
8
|
+
import { assertPermission } from "../../../auth/permissions.js";
|
|
8
9
|
import { makeId } from "../../../utils/id.js";
|
|
10
|
+
/**
|
|
11
|
+
* SEC-07 — resolve the customer profile a checkout order is attributed to.
|
|
12
|
+
* A self-service actor may ONLY attribute the order to its own customer
|
|
13
|
+
* profile; only actors with org-level `customers:read` (staff/clienteling) may
|
|
14
|
+
* name an arbitrary `customerId`. Returns undefined for guests / unresolved
|
|
15
|
+
* (guest checkout). Exported for unit testing.
|
|
16
|
+
*/
|
|
17
|
+
export async function resolveCheckoutCustomerUuid(customers, actor, customerId) {
|
|
18
|
+
const actorUserId = actor?.userId;
|
|
19
|
+
let canActForOthers = false;
|
|
20
|
+
if (actorUserId) {
|
|
21
|
+
try {
|
|
22
|
+
assertPermission(actor, "customers:read");
|
|
23
|
+
canActForOthers = true;
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
canActForOthers = false;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
if (customerId) {
|
|
30
|
+
const uuidRe = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
31
|
+
if (uuidRe.test(customerId)) {
|
|
32
|
+
const byId = await customers.getById(customerId, actor);
|
|
33
|
+
// Honor a profile UUID only if it is the actor's own, or the actor may
|
|
34
|
+
// act for other customers.
|
|
35
|
+
if (byId.ok && (canActForOthers || byId.value.userId === actorUserId)) {
|
|
36
|
+
return byId.value.id;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
if (canActForOthers) {
|
|
40
|
+
// Staff may resolve/create a customer by a supplied user_id.
|
|
41
|
+
const byUser = await customers.getByUserId(customerId, actor);
|
|
42
|
+
if (byUser.ok)
|
|
43
|
+
return byUser.value.id;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
// Self-service default: the authenticated actor's own customer profile.
|
|
47
|
+
if (actorUserId && !canActForOthers) {
|
|
48
|
+
const own = await customers.getByUserId(actorUserId, actor);
|
|
49
|
+
if (own.ok)
|
|
50
|
+
return own.value.id;
|
|
51
|
+
}
|
|
52
|
+
return undefined;
|
|
53
|
+
}
|
|
9
54
|
export function checkoutRoutes(kernel) {
|
|
10
55
|
const router = new OpenAPIHono();
|
|
11
56
|
// @ts-expect-error -- openapi() enforces strict response typing but our handler
|
|
@@ -20,7 +65,32 @@ export function checkoutRoutes(kernel) {
|
|
|
20
65
|
if (body.idempotencyKey) {
|
|
21
66
|
const replay = await kernel.services.orders.getByIdempotencyKey(body.idempotencyKey, actor);
|
|
22
67
|
if (replay.ok && replay.value) {
|
|
23
|
-
|
|
68
|
+
// IDOR guard: an idempotency key must only replay the requester's OWN
|
|
69
|
+
// order. Without this, a same-org customer who supplies/guesses another
|
|
70
|
+
// customer's key would receive that customer's order (PII, totals, lines).
|
|
71
|
+
let canActForOthers = false;
|
|
72
|
+
try {
|
|
73
|
+
assertPermission(actor, "customers:read");
|
|
74
|
+
canActForOthers = true;
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
canActForOthers = false;
|
|
78
|
+
}
|
|
79
|
+
const ownCustomer = actor
|
|
80
|
+
? await resolveCheckoutCustomerUuid(kernel.services.customers, actor, undefined)
|
|
81
|
+
: undefined;
|
|
82
|
+
const replayCustomer = replay.value.customerId ?? null;
|
|
83
|
+
const ownsOrder = (replayCustomer !== null && replayCustomer === ownCustomer) ||
|
|
84
|
+
(replayCustomer === null && !ownCustomer);
|
|
85
|
+
if (canActForOthers || ownsOrder) {
|
|
86
|
+
return c.json({ data: replay.value }, 201);
|
|
87
|
+
}
|
|
88
|
+
return c.json({
|
|
89
|
+
error: {
|
|
90
|
+
code: "IDEMPOTENCY_CONFLICT",
|
|
91
|
+
message: "Idempotency key does not belong to this account.",
|
|
92
|
+
},
|
|
93
|
+
}, 409);
|
|
24
94
|
}
|
|
25
95
|
}
|
|
26
96
|
const checkoutData = {
|
|
@@ -93,26 +163,10 @@ export function checkoutRoutes(kernel) {
|
|
|
93
163
|
// If Stripe takes 5s, the DB connection pool is not affected.
|
|
94
164
|
context.tx = null;
|
|
95
165
|
const processed = await runBeforeHooks(paymentHooks, validated, "create", context);
|
|
96
|
-
//
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
if (uuidRe.test(processed.customerId)) {
|
|
101
|
-
// Looks like a profile UUID — try direct lookup (no auto-create)
|
|
102
|
-
const byIdResult = await kernel.services.customers.getById(processed.customerId, actor);
|
|
103
|
-
if (byIdResult.ok) {
|
|
104
|
-
customerUuid = byIdResult.value.id;
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
if (!customerUuid) {
|
|
108
|
-
// Fall back to user_id lookup (auto-creates customer profile if needed)
|
|
109
|
-
const byUserIdResult = await kernel.services.customers.getByUserId(processed.customerId, actor);
|
|
110
|
-
if (byUserIdResult.ok) {
|
|
111
|
-
customerUuid = byUserIdResult.value.id;
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
// If both lookups fail, we still allow guest checkout (customerUuid remains undefined)
|
|
115
|
-
}
|
|
166
|
+
// SEC-07: resolve the order's customer server-side. A self-service actor
|
|
167
|
+
// can only attribute the order to its own profile; a client-supplied
|
|
168
|
+
// foreign customerId is ignored unless the actor is staff.
|
|
169
|
+
const customerUuid = await resolveCheckoutCustomerUuid(kernel.services.customers, actor, processed.customerId);
|
|
116
170
|
const orderPayload = {
|
|
117
171
|
...(body.idempotencyKey !== undefined
|
|
118
172
|
? { idempotencyKey: body.idempotencyKey }
|
|
@@ -159,7 +213,12 @@ export function checkoutRoutes(kernel) {
|
|
|
159
213
|
? { customerId: customerUuid }
|
|
160
214
|
: {}),
|
|
161
215
|
};
|
|
162
|
-
|
|
216
|
+
// Checkout is a trusted, already-server-priced pipeline (resolveCurrentPrices
|
|
217
|
+
// + promotions/tax) and reserves stock in its own after-hooks — so it hands
|
|
218
|
+
// the order primitive precomputed totals rather than re-deriving them.
|
|
219
|
+
const order = await kernel.services.orders.create(orderPayload, actor, undefined, {
|
|
220
|
+
trustedPricing: true,
|
|
221
|
+
});
|
|
163
222
|
if (!order.ok) {
|
|
164
223
|
return c.json(mapErrorToResponse(order.error), mapErrorToStatus(order.error));
|
|
165
224
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inventory.d.ts","sourceRoot":"","sources":["../../../../src/interfaces/rest/routes/inventory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAC;AAUzD,OAAO,EAAE,KAAK,MAAM,EAAqD,MAAM,aAAa,CAAC;AAE7F,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"inventory.d.ts","sourceRoot":"","sources":["../../../../src/interfaces/rest/routes/inventory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAC;AAUzD,OAAO,EAAE,KAAK,MAAM,EAAqD,MAAM,aAAa,CAAC;AAE7F,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,gCA+F7C"}
|
|
@@ -5,6 +5,13 @@ export function inventoryRoutes(kernel) {
|
|
|
5
5
|
const router = new OpenAPIHono();
|
|
6
6
|
// Inventory levels listing requires inventory:read
|
|
7
7
|
router.use("/levels", requirePerm("inventory:read"));
|
|
8
|
+
// Warehouse config + reservation are staff operations, never public. Gate them
|
|
9
|
+
// at the route (reserve/release are also called internally by checkout with the
|
|
10
|
+
// customer's actor, so the service itself must stay callable — the boundary is
|
|
11
|
+
// the HTTP route). Blocks anonymous (401) and customers lacking the perm (403).
|
|
12
|
+
router.use("/warehouses", requirePerm("inventory:read"));
|
|
13
|
+
router.use("/reserve", requirePerm("inventory:adjust"));
|
|
14
|
+
router.use("/release", requirePerm("inventory:adjust"));
|
|
8
15
|
// @ts-expect-error -- openapi handler union return type
|
|
9
16
|
router.openapi(listInventoryLevelsRoute, async (c) => {
|
|
10
17
|
const actor = c.get("actor");
|
|
@@ -59,6 +66,12 @@ export function inventoryRoutes(kernel) {
|
|
|
59
66
|
router.openapi(createWarehouseRoute, async (c) => {
|
|
60
67
|
const body = c.req.valid("json");
|
|
61
68
|
const actor = c.get("actor");
|
|
69
|
+
// Creating a warehouse (write) needs the higher inventory:adjust perm; the
|
|
70
|
+
// router.use above already requires inventory:read for the /warehouses path.
|
|
71
|
+
const perms = actor?.permissions ?? [];
|
|
72
|
+
if (!(perms.includes("inventory:adjust") || perms.includes("inventory:*") || perms.includes("*:*"))) {
|
|
73
|
+
return c.json({ error: { code: "FORBIDDEN", message: "Permission 'inventory:adjust' is required." } }, 403);
|
|
74
|
+
}
|
|
62
75
|
const result = await kernel.services.inventory.createWarehouse(body, actor);
|
|
63
76
|
if (!result.ok)
|
|
64
77
|
return c.json(mapErrorToResponse(result.error), mapErrorToStatus(result.error));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"orders.d.ts","sourceRoot":"","sources":["../../../../src/interfaces/rest/routes/orders.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAC;AAEzD,OAAO,EAAE,KAAK,MAAM,EAAiE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"orders.d.ts","sourceRoot":"","sources":["../../../../src/interfaces/rest/routes/orders.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAC;AAEzD,OAAO,EAAE,KAAK,MAAM,EAAiE,MAAM,aAAa,CAAC;AAIzG,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,gCAgRzC"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { OpenAPIHono } from "@hono/zod-openapi";
|
|
2
2
|
import { changeOrderStatusRoute, listOrdersRoute, orderLookupRoute, getOrderRoute, getOrderFulfillmentsRoute, createOrderRoute, refundOrderRoute, captureOrderRoute, createOrderFulfillmentRoute, addOrderLineItemRoute, updateOrderLineItemRoute, removeOrderLineItemRoute, refundOrderLinesRoute, undoOrderRefundRoute, listOrderRefundsRoute, refundCapStatusRoute, createOrderNoteRoute, listOrderNotesRoute, deleteOrderNoteRoute, orderTimelineRoute } from "../schemas/orders.js";
|
|
3
3
|
import { isUUID, mapErrorToResponse, mapErrorToStatus, parsePagination } from "../utils.js";
|
|
4
|
+
import { assertPermission } from "../../../auth/permissions.js";
|
|
4
5
|
export function orderRoutes(kernel) {
|
|
5
6
|
const router = new OpenAPIHono();
|
|
6
7
|
// @ts-expect-error -- openapi handler union return type
|
|
@@ -55,6 +56,12 @@ export function orderRoutes(kernel) {
|
|
|
55
56
|
});
|
|
56
57
|
// @ts-expect-error -- openapi handler union return type
|
|
57
58
|
router.openapi(createOrderRoute, async (c) => {
|
|
59
|
+
try {
|
|
60
|
+
assertPermission(c.get("actor"), "orders:manage");
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
return c.json(mapErrorToResponse(error), mapErrorToStatus(error));
|
|
64
|
+
}
|
|
58
65
|
const body = c.req.valid("json");
|
|
59
66
|
const result = await kernel.services.orders.create(body, c.get("actor"));
|
|
60
67
|
if (!result.ok)
|
|
@@ -139,6 +146,12 @@ export function orderRoutes(kernel) {
|
|
|
139
146
|
});
|
|
140
147
|
// @ts-expect-error -- openapi handler union return type
|
|
141
148
|
router.openapi(addOrderLineItemRoute, async (c) => {
|
|
149
|
+
try {
|
|
150
|
+
assertPermission(c.get("actor"), "orders:manage");
|
|
151
|
+
}
|
|
152
|
+
catch (error) {
|
|
153
|
+
return c.json(mapErrorToResponse(error), mapErrorToStatus(error));
|
|
154
|
+
}
|
|
142
155
|
const body = c.req.valid("json");
|
|
143
156
|
const result = await kernel.services.orders.addLineItem(c.req.param("id"), body, c.get("actor"));
|
|
144
157
|
if (!result.ok)
|
|
@@ -166,7 +166,7 @@ export const createOrderRoute = createRoute({
|
|
|
166
166
|
path: "/",
|
|
167
167
|
tags: ["Orders"],
|
|
168
168
|
summary: "Create a draft / manual order",
|
|
169
|
-
description: "
|
|
169
|
+
description: "Requires `orders:manage`. Creates an operator-entered order (phone / POS / manual); supplied line prices are stored as audited manual overrides.",
|
|
170
170
|
request: {
|
|
171
171
|
body: {
|
|
172
172
|
content: { "application/json": { schema: CreateOrderBodySchema } },
|
|
@@ -248,7 +248,7 @@ export const addOrderLineItemRoute = createRoute({
|
|
|
248
248
|
path: "/{id}/line-items",
|
|
249
249
|
tags: ["Orders"],
|
|
250
250
|
summary: "Add a line item to a placed order",
|
|
251
|
-
description: "Adds a line item to a non-terminal order
|
|
251
|
+
description: "Requires `orders:manage`. Adds a line item to a non-terminal order, records its supplied price as a manual override, and recalculates totals.",
|
|
252
252
|
request: {
|
|
253
253
|
params: OrderIdParam,
|
|
254
254
|
body: {
|
|
@@ -507,6 +507,23 @@ export declare const OrderLineItemSchema: import("drizzle-zod").BuildSchema<"sel
|
|
|
507
507
|
identity: undefined;
|
|
508
508
|
generated: undefined;
|
|
509
509
|
}, {}, {}>;
|
|
510
|
+
isCustomPrice: import("drizzle-orm/pg-core").PgColumn<{
|
|
511
|
+
name: "is_custom_price";
|
|
512
|
+
tableName: "order_line_items";
|
|
513
|
+
dataType: "boolean";
|
|
514
|
+
columnType: "PgBoolean";
|
|
515
|
+
data: boolean;
|
|
516
|
+
driverParam: boolean;
|
|
517
|
+
notNull: true;
|
|
518
|
+
hasDefault: true;
|
|
519
|
+
isPrimaryKey: false;
|
|
520
|
+
isAutoincrement: false;
|
|
521
|
+
hasRuntimeDefault: false;
|
|
522
|
+
enumValues: undefined;
|
|
523
|
+
baseColumn: never;
|
|
524
|
+
identity: undefined;
|
|
525
|
+
generated: undefined;
|
|
526
|
+
}, {}, {}>;
|
|
510
527
|
taxAmount: import("drizzle-orm/pg-core").PgColumn<{
|
|
511
528
|
name: "tax_amount";
|
|
512
529
|
tableName: "order_line_items";
|
|
@@ -769,6 +786,23 @@ export declare const OrderWithItemsSchema: z.ZodObject<{
|
|
|
769
786
|
identity: undefined;
|
|
770
787
|
generated: undefined;
|
|
771
788
|
}, {}, {}>;
|
|
789
|
+
isCustomPrice: import("drizzle-orm/pg-core").PgColumn<{
|
|
790
|
+
name: "is_custom_price";
|
|
791
|
+
tableName: "order_line_items";
|
|
792
|
+
dataType: "boolean";
|
|
793
|
+
columnType: "PgBoolean";
|
|
794
|
+
data: boolean;
|
|
795
|
+
driverParam: boolean;
|
|
796
|
+
notNull: true;
|
|
797
|
+
hasDefault: true;
|
|
798
|
+
isPrimaryKey: false;
|
|
799
|
+
isAutoincrement: false;
|
|
800
|
+
hasRuntimeDefault: false;
|
|
801
|
+
enumValues: undefined;
|
|
802
|
+
baseColumn: never;
|
|
803
|
+
identity: undefined;
|
|
804
|
+
generated: undefined;
|
|
805
|
+
}, {}, {}>;
|
|
772
806
|
taxAmount: import("drizzle-orm/pg-core").PgColumn<{
|
|
773
807
|
name: "tax_amount";
|
|
774
808
|
tableName: "order_line_items";
|