PageSourceSearch

https://sendwork.com/_next/static/chunks/3290-5cdd2b3701b3e7b8.js?dpl=dpl_5fjwdkv4JxUYccV6VLxrnLLeDnjE

js sendwork.com collected 2026-10-08 02:47:52 UTC 66,596 bytes, 1,840 lines download raw bytes

1"use strict";
2(self["webpackChunk_N_E"] = self["webpackChunk_N_E"] || []).push([[3290],{
3
4/***/ 17906:
5/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
6
7/* harmony export */ __webpack_require__.d(__webpack_exports__, {
8/* harmony export */   i1: () => (/* binding */ getCompanyForUser),
9/* harmony export */   p6: () => (/* binding */ getUserPrimaryCompany)
10/* harmony export */ });
11/* unused harmony export updateCompany */
12/* harmony import */ var _lib_supabase_v2_client__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(29326);
13/* harmony import */ var _lib_supabase_service_role_client__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(37314);
14/* harmony import */ var _lib_supabase_field_transformer__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(68762);
15/* harmony import */ var _lib_validation_api_schemas__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(83636);
16
17
18
19
20async function getUserPrimaryCompany() {
21    let client = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : _lib_supabase_v2_client__WEBPACK_IMPORTED_MODULE_0__/* .enhancedSupabase */ .XL;
22    const { data: authData, error: authError } = await client.auth.getUser();
23    if (authError) {
24        var _message_toLowerCase;
25        var _authError_status;
26        const status = (_authError_status = authError === null || authError === void 0 ? void 0 : authError.status) !== null && _authError_status !== void 0 ? _authError_status : authError === null || authError === void 0 ? void 0 : authError.code;
27        const message = (authError === null || authError === void 0 ? void 0 : authError.message) || "";
28        const isSessionMissing = status === 400 || ((_message_toLowerCase = message.toLowerCase) === null || _message_toLowerCase === void 0 ? void 0 : _message_toLowerCase.call(message).includes("auth session missing")) || authError.name === "AuthSessionMissingError";
29        if (isSessionMissing) {
30            // Expected on cold SSR refresh when cookies are missing; defer to client hydration
31            return null;
32        }
33        console.error("[getUserPrimaryCompany] auth error", authError);
34        return null;
35    }
36    const user = authData === null || authData === void 0 ? void 0 : authData.user;
37    if (!user) {
38        return null;
39    }
40    const { data: membership, error: membershipError } = await client.from("company_members").select("company_id").eq("user_id", user.id).limit(1).maybeSingle();
41    if (membershipError) {
42        console.error("[getUserPrimaryCompany] membership error", membershipError);
43        return null;
44    }
45    var _membership_companyId;
46    const membershipCompanyId = (_membership_companyId = membership === null || membership === void 0 ? void 0 : membership.companyId) !== null && _membership_companyId !== void 0 ? _membership_companyId : membership === null || membership === void 0 ? void 0 : membership.company_id;
47    if (!membershipCompanyId) {
48        return null;
49    }
50    const { data: company, error: companyError } = await client.from("companies").select("*").eq("id", membershipCompanyId).single();
51    if (companyError) {
52        console.error("[getUserPrimaryCompany] company error", companyError);
53        return null;
54    }
55    return company;
56}
57const getCompanyForUser = getUserPrimaryCompany;
58const normalizeLastKnownUpdatedAt = (value)=>{
59    if (value instanceof Date) {
60        const time = value.getTime();
61        return Number.isNaN(time) ? null : value.toISOString();
62    }
63    if (typeof value !== "string") {
64        return null;
65    }
66    const trimmed = value.trim();
67    if (!trimmed || Number.isNaN(Date.parse(trimmed))) {
68        return null;
69    }
70    return trimmed;
71};
72async function updateCompany(patch, idempotencyKey) {
73    const company = await getCompanyForUser();
74    if (!company) throw new Error("No company found");
75    const patchWithMetadata = patch;
76    const { lastKnownUpdatedAt, updatedAt: _updatedAt, ...patchWithoutCamelMetadata } = patchWithMetadata;
77    const normalizedLastKnownUpdatedAt = normalizeLastKnownUpdatedAt(lastKnownUpdatedAt);
78    const { ["updated_at"]: _updated_at, ...safePatch } = patchWithoutCamelMetadata;
79    const updateData = {
80        ...safePatch
81    };
82    // Prefer service role when available to avoid RLS update denials
83    const writeClient = serviceRoleClient !== null && serviceRoleClient !== void 0 ? serviceRoleClient : enhancedSupabase;
84    const dbUpdate = transformToDatabase(updateData);
85    const updateBaseQuery = writeClient.from("companies").update(dbUpdate).eq("id", company.id);
86    const updateQuery = normalizedLastKnownUpdatedAt ? updateBaseQuery.eq("updated_at", normalizedLastKnownUpdatedAt) : updateBaseQuery;
87    const { data: updated, error } = normalizedLastKnownUpdatedAt ? await updateQuery.select().maybeSingle() : await updateQuery.select().single();
88    if (error) {
89        // Preserve structured details from EnhancedSupabase normalization
90        const err = new Error("Failed to update company: ".concat(error.message || "unknown error"));
91        try {
92            err.code = error === null || error === void 0 ? void 0 : error.code;
93            err.details = error === null || error === void 0 ? void 0 : error.details;
94            err.hint = error === null || error === void 0 ? void 0 : error.hint;
95            err.raw = error;
96        } catch (e) {}
97        throw err;
98    }
99    if (normalizedLastKnownUpdatedAt && !updated) {
100        const { data: existingCompany, error: existenceError } = await writeClient.from("companies").select("id").eq("id", company.id).maybeSingle();
101        if (existenceError) {
102            throw new Error("Failed to verify company version: ".concat(existenceError.message || "unknown error"));
103        }
104        if (existingCompany) {
105            throw new SettingsVersionMismatchError();
106        }
107        throw new Error("Failed to update company: No rows found");
108    }
109    // Optionally refresh cached company data by returning success; callers may refetch.
110    try {
111        console.debug("updateCompany: updated row", updated);
112    } catch (e) {}
113    return {
114        success: true,
115        applied: true
116    };
117}
118
119
120/***/ }),
121
122/***/ 37314:
123/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
124
125/* unused harmony exports serviceRoleClient, isServiceRoleEnabled, classifyAuthVerificationFailure, getCurrentUserClassified, getCurrentUser, getUserCompanyRole, readActivePermissionMemberships, verifyPermission, createAuditLog, errorResponses */
126/* harmony import */ var _supabase_supabase_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(42367);
127/* harmony import */ var _lib_permissions__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(57791);
128/* harmony import */ var _lib_supabase_field_transformer__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(68762);
129/* provided dependency */ var process = __webpack_require__(44822);
130/* provided dependency */ var Buffer = __webpack_require__(44226)["hp"];
131
132
133
134// Service role client for server-side operations that bypass RLS
135// This should ONLY be used in API routes with proper permission checks
136const supabaseUrl = "https://api.sendwork.com" || 0;
137const supabaseServiceRoleKey = process.env.SUPABASE_SERVICE_ROLE_KEY;
138const supabaseAuthIssuer = process.env.SUPABASE_AUTH_ISSUER;
139// Validate required env var (dev-only to avoid noisy production builds)
140if (false) {}
141// Create service role client only if key is available
142const serviceRoleClient = supabaseServiceRoleKey && "https://api.sendwork.com" && hasTrustedIssuerConfiguration("".concat(supabaseUrl.replace(/\/$/, ""), "/auth/v1")) ? (0,_supabase_supabase_js__WEBPACK_IMPORTED_MODULE_2__/* .createClient */ .UU)(supabaseUrl, supabaseServiceRoleKey, {
143    auth: {
144        autoRefreshToken: false,
145        persistSession: false,
146        detectSessionInUrl: false
147    }
148}) : null;
149// Helper to check if service role is enabled
150const isServiceRoleEnabled = ()=>serviceRoleClient !== null;
151function isJwtClaimsRecord(value) {
152    return typeof value === "object" && value !== null && !Array.isArray(value);
153}
154function hasTrustedIssuerConfiguration(issuer) {
155    if (!issuer || issuer.trim() !== issuer) return false;
156    try {
157        const url = new URL(issuer);
158        const loopback = [
159            "localhost",
160            "127.0.0.1",
161            "[::1]"
162        ].includes(url.hostname);
163        return (url.protocol === "https:" || url.protocol === "http:" && loopback) && !url.username && !url.password && !url.search && !url.hash && url.pathname === "/auth/v1" && url.href === issuer;
164    } catch (e) {
165        return false;
166    }
167}
168function hasJwtStructure(token, issuer) {
169    if (!/^[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$/.test(token)) return false;
170    try {
171        const [headerSegment, payloadSegment] = token.split(".");
172        const header = JSON.parse(Buffer.from(headerSegment, "base64url").toString("utf8"));
173        const payload = JSON.parse(Buffer.from(payloadSegment, "base64url").toString("utf8"));
174        return isJwtClaimsRecord(header) && hasValidUserClaims(payload, issuer) && [
175            "HS256",
176            "ES256",
177            "RS256"
178        ].includes(String(header.alg));
179    } catch (e) {
180        return false;
181    }
182}
183// Signature verification belongs to the installed SDK. These checks constrain
184// already verified claims to this application's explicit user-token contract.
185function hasValidUserClaims(claims, issuer) {
186    if (!isJwtClaimsRecord(claims)) return false;
187    const now = Math.floor(Date.now() / 1000);
188    const numericDate = (value)=>typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
189    const audience = claims.aud;
190    return claims.iss === issuer && typeof claims.sub === "string" && /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(claims.sub) && claims.role === "authenticated" && (audience === "authenticated" || Array.isArray(audience) && audience.length === 1 && audience[0] === "authenticated") && numericDate(claims.iat) && claims.iat <= now && numericDate(claims.exp) && claims.exp > now && claims.exp > claims.iat && (claims.nbf === undefined || numericDate(claims.nbf) && claims.nbf <= now && claims.nbf < claims.exp);
191}
192function createAuthFailure(status, code, message) {
193    return {
194        status,
195        code,
196        message
197    };
198}
199function isInvalidAuthError(error) {
200    if (error instanceof AuthApiError) {
201        return error.status === 401 || error.status >= 400 && error.status < 500 && (error.code === "bad_jwt" || error.code === "invalid_jwt");
202    }
203    if (typeof error !== "object" || error === null) {
204        return false;
205    }
206    const candidate = error;
207    return candidate.status === 401 || candidate.code === "invalid_jwt" || candidate.name === "AuthInvalidJwtError" || typeof candidate.message === "string" && /^(Missing exp claim|JWT has expired|Invalid alg claim)$/.test(candidate.message);
208}
209function classifyAuthVerificationFailure(error) {
210    let options = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : {};
211    const { authHeader, serviceRoleConfigured = true, user = null } = options;
212    if (!serviceRoleConfigured) {
213        return createAuthFailure(503, "AUTH_UNAVAILABLE", "Authentication verification unavailable");
214    }
215    if (authHeader !== undefined && (!authHeader || !authHeader.startsWith("Bearer ") || authHeader.length <= "Bearer ".length)) {
216        return createAuthFailure(401, "AUTH_REQUIRED", "Unauthorized");
217    }
218    if (!error && !user) {
219        return createAuthFailure(401, "AUTH_REQUIRED", "Unauthorized");
220    }
221    if (isAuthSessionMissingError(error)) {
222        return createAuthFailure(401, "AUTH_REQUIRED", "Unauthorized");
223    }
224    if (isAuthRetryableFetchError(error)) {
225        return createAuthFailure(504, "AUTH_TIMEOUT", "Authentication verification timed out");
226    }
227    if (isInvalidAuthError(error)) {
228        return createAuthFailure(401, "AUTH_INVALID", "Unauthorized");
229    }
230    return createAuthFailure(502, "AUTH_UPSTREAM_ERROR", "Authentication verification failed");
231}
232async function getCurrentUserClassified(request) {
233    if (!serviceRoleClient || !hasTrustedIssuerConfiguration(supabaseAuthIssuer)) {
234        return {
235            user: null,
236            authFailure: classifyAuthVerificationFailure(null, {
237                serviceRoleConfigured: false
238            })
239        };
240    }
241    const authHeader = request.headers.get("authorization");
242    if (!authHeader || !authHeader.startsWith("Bearer ") || authHeader.length <= "Bearer ".length) {
243        return {
244            user: null,
245            authFailure: classifyAuthVerificationFailure(null, {
246                authHeader
247            })
248        };
249    }
250    const token = authHeader.slice("Bearer ".length);
251    const invalid = ()=>({
252            user: null,
253            authFailure: createAuthFailure(401, "AUTH_INVALID", "Unauthorized")
254        });
255    // Syntax rejection is not verification and never creates an identity.
256    if (!hasJwtStructure(token, supabaseAuthIssuer)) return invalid();
257    try {
258        const { data: verified, error: claimsError } = await serviceRoleClient.auth.getClaims(token);
259        if (claimsError) {
260            return {
261                user: null,
262                authFailure: classifyAuthVerificationFailure(claimsError, {
263                    authHeader
264                })
265            };
266        }
267        if (!hasValidUserClaims(verified === null || verified === void 0 ? void 0 : verified.claims, supabaseAuthIssuer)) return invalid();
268        const { data: { user }, error } = await serviceRoleClient.auth.getUser(token);
269        if (error || !user) {
270            return {
271                user: null,
272                authFailure: classifyAuthVerificationFailure(error, {
273                    authHeader,
274                    user
275                })
276            };
277        }
278        if (user.id !== verified.claims.sub || !hasValidUserClaims(verified.claims, supabaseAuthIssuer)) return invalid();
279        // Current Auth identity/metadata comes only from getUser, never the JWT.
280        return {
281            user,
282            authFailure: null
283        };
284    } catch (error) {
285        return {
286            user: null,
287            authFailure: classifyAuthVerificationFailure(error, {
288                authHeader
289            })
290        };
291    }
292}
293// Helper to get current user from request headers
294async function getCurrentUser(request) {
295    const { user } = await getCurrentUserClassified(request);
296    return user;
297}
298// Helper to get user's company and role
299async function getUserCompanyRole(userId) {
300    var _data_roles, _data_role;
301    if (!serviceRoleClient) {
302        return null;
303    }
304    // Fetch primary membership and join role name; avoid filtering on non-existent columns.
305    const { data, error } = await serviceRoleClient.from("company_members").select("company_id, role_id, roles(name)").eq("user_id", userId).eq("is_primary", true).maybeSingle();
306    if (error || !data) {
307        return null;
308    }
309    const companyId = data.company_id;
310    const roleId = data.role_id;
311    const roleName = (data === null || data === void 0 ? void 0 : (_data_roles = data.roles) === null || _data_roles === void 0 ? void 0 : _data_roles.name) || (data === null || data === void 0 ? void 0 : (_data_role = data.role) === null || _data_role === void 0 ? void 0 : _data_role.name);
312    return {
313        companyId,
314        roleId,
315        roleName
316    };
317}
318function readOwnDataProperty(value, property) {
319    const descriptor = Object.getOwnPropertyDescriptor(value, property);
320    if (!descriptor || !("value" in descriptor)) {
321        return {
322            ok: false
323        };
324    }
325    return {
326        ok: true,
327        value: descriptor.value
328    };
329}
330function hasExactEnumerableKeys(value, expected) {
331    const keys = Object.keys(value).sort();
332    return keys.length === expected.length && expected.every((key, index)=>keys[index] === key);
333}
334/**
335 * Reads the bounded active-membership authority shape used by the canonical
336 * permission resolver. The principal is already server-derived; this adapter
337 * never accepts a role, status, company, or capability claim from a client.
338 */ async function readActivePermissionMemberships(principal) {
339    let client = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : serviceRoleClient;
340    try {
341        if (typeof principal !== "object" || principal === null || !client) {
342            return {
343                ok: false
344            };
345        }
346        const userIdProperty = readOwnDataProperty(principal, "userId");
347        const companyIdProperty = readOwnDataProperty(principal, "companyId");
348        if (!userIdProperty.ok || typeof userIdProperty.value !== "string" || userIdProperty.value.length === 0 || userIdProperty.value.trim() !== userIdProperty.value || !companyIdProperty.ok || typeof companyIdProperty.value !== "string" || companyIdProperty.value.length === 0 || companyIdProperty.value.trim() !== companyIdProperty.value) {
349            return {
350                ok: false
351            };
352        }
353        const userId = userIdProperty.value;
354        const companyId = companyIdProperty.value;
355        const queryResult = await client.from("company_members").select("status, roles(name)").eq("user_id", userId).eq("company_id", companyId).limit(2);
356        if (typeof queryResult !== "object" || queryResult === null) {
357            return {
358                ok: false
359            };
360        }
361        const dataProperty = readOwnDataProperty(queryResult, "data");
362        const errorProperty = readOwnDataProperty(queryResult, "error");
363        if (!dataProperty.ok || !errorProperty.ok || errorProperty.value !== null || !Array.isArray(dataProperty.value)) {
364            return {
365                ok: false
366            };
367        }
368        const rows = dataProperty.value;
369        const lengthProperty = readOwnDataProperty(rows, "length");
370        if (!lengthProperty.ok || typeof lengthProperty.value !== "number" || !Number.isInteger(lengthProperty.value) || lengthProperty.value < 0 || lengthProperty.value > 2) {
371            return {
372                ok: false
373            };
374        }
375        const memberships = [];
376        for(let index = 0; index < lengthProperty.value; index += 1){
377            const rowProperty = readOwnDataProperty(rows, index);
378            if (!rowProperty.ok || typeof rowProperty.value !== "object" || rowProperty.value === null || Array.isArray(rowProperty.value) || !hasExactEnumerableKeys(rowProperty.value, [
379                "roles",
380                "status"
381            ])) {
382                return {
383                    ok: false
384                };
385            }
386            const statusProperty = readOwnDataProperty(rowProperty.value, "status");
387            const rolesProperty = readOwnDataProperty(rowProperty.value, "roles");
388            if (!statusProperty.ok || !rolesProperty.ok || typeof rolesProperty.value !== "object" || rolesProperty.value === null || Array.isArray(rolesProperty.value) || !hasExactEnumerableKeys(rolesProperty.value, [
389                "name"
390            ])) {
391                return {
392                    ok: false
393                };
394            }
395            const roleNameProperty = readOwnDataProperty(rolesProperty.value, "name");
396            if (!roleNameProperty.ok) {
397                return {
398                    ok: false
399                };
400            }
401            memberships.push({
402                status: statusProperty.value,
403                roleName: roleNameProperty.value
404            });
405        }
406        return {
407            ok: true,
408            memberships
409        };
410    } catch (e) {
411        return {
412            ok: false
413        };
414    }
415}
416async function verifyPermission(userId, companyId) {
417    let requiredPermission = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : [
418        "owner",
419        "admin",
420        "staff"
421    ];
422    var _data_roles, _data_role;
423    if (isPermissionCapability(requiredPermission)) {
424        return resolvePermission({
425            userId,
426            companyId
427        }, requiredPermission, readActivePermissionMemberships);
428    }
429    if (typeof requiredPermission === "string") {
430        return false;
431    }
432    if (!serviceRoleClient) {
433        return false;
434    }
435    const { data, error } = await serviceRoleClient.from("company_members").select("role_id, roles(name)").eq("user_id", userId).eq("company_id", companyId).maybeSingle();
436    if (error || !data) return false;
437    const roleNameRaw = (data === null || data === void 0 ? void 0 : (_data_roles = data.roles) === null || _data_roles === void 0 ? void 0 : _data_roles.name) || (data === null || data === void 0 ? void 0 : (_data_role = data.role) === null || _data_role === void 0 ? void 0 : _data_role.name);
438    const roleName = typeof roleNameRaw === "string" ? roleNameRaw.toLowerCase() : undefined;
439    if (!roleName) return false;
440    return requiredPermission.map((r)=>r.toLowerCase()).includes(roleName);
441}
442// Helper to create audit log entry
443async function createAuditLog(tableName, operation, userId, companyId, recordId, oldData, newData) {
444    if (!serviceRoleClient) {
445        console.warn("[createAuditLog] Service role client not available, skipping audit log");
446        return;
447    }
448    try {
449        const payload = transformToDatabase({
450            tableName,
451            operation,
452            userId,
453            companyId,
454            recordId,
455            oldData: oldData ? JSON.stringify(oldData) : null,
456            newData: newData ? JSON.stringify(newData) : null
457        });
458        await serviceRoleClient.from("audit_logs").insert(payload);
459    } catch (error) {
460        console.error("Failed to create audit log:", error);
461    // Don't throw - audit logging should not break the operation
462    }
463}
464// Standard error responses
465const errorResponses = {
466    unauthorized: ()=>Response.json({
467            error: "Unauthorized"
468        }, {
469            status: 401
470        }),
471    authRequired: ()=>Response.json({
472            error: "Unauthorized",
473            code: "AUTH_REQUIRED"
474        }, {
475            status: 401
476        }),
477    authInvalid: ()=>Response.json({
478            error: "Unauthorized",
479            code: "AUTH_INVALID"
480        }, {
481            status: 401
482        }),
483    authTimeout: ()=>Response.json({
484            error: "Authentication verification timed out",
485            code: "AUTH_TIMEOUT"
486        }, {
487            status: 504
488        }),
489    authUpstreamError: ()=>Response.json({
490            error: "Authentication verification failed",
491            code: "AUTH_UPSTREAM_ERROR"
492        }, {
493            status: 502
494        }),
495    authUnavailable: ()=>Response.json({
496            error: "Authentication verification unavailable",
497            code: "AUTH_UNAVAILABLE"
498        }, {
499            status: 503
500        }),
501    authFailure: (failure)=>{
502        switch(failure.code){
503            case "AUTH_REQUIRED":
504                return errorResponses.authRequired();
505            case "AUTH_INVALID":
506                return errorResponses.authInvalid();
507            case "AUTH_TIMEOUT":
508                return errorResponses.authTimeout();
509            case "AUTH_UNAVAILABLE":
510                return errorResponses.authUnavailable();
511            default:
512                return errorResponses.authUpstreamError();
513        }
514    },
515    forbidden: ()=>Response.json({
516            error: "Forbidden"
517        }, {
518            status: 403
519        }),
520    notFound: ()=>Response.json({
521            error: "Not found"
522        }, {
523            status: 404
524        }),
525    badRequest: (message)=>Response.json({
526            error: message
527        }, {
528            status: 400
529        }),
530    serverError: function() {
531        let message = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : "Internal server error";
532        return Response.json({
533            error: message
534        }, {
535            status: 500
536        });
537    }
538};
539
540
541/***/ }),
542
543/***/ 57791:
544/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
545
546/* harmony export */ __webpack_require__.d(__webpack_exports__, {
547/* harmony export */   pl: () => (/* binding */ hasDefaultPermission)
548/* harmony export */ });
549/* unused harmony exports PERMISSION_ROLES, DEFAULT_PERMISSION_MATRIX, PERMISSION_CAPABILITIES, isPermissionRole, isPermissionCapability, resolvePermission */
550const PERMISSION_ROLES = Object.freeze([
551    "owner",
552    "admin",
553    "manager",
554    "member",
555    "staff",
556    "viewer",
557    "customer"
558]);
559const freezeRoleDecisions = (decisions)=>Object.freeze(decisions);
560const permissionMatrix = {
561    "dashboard.access": freezeRoleDecisions({
562        owner: true,
563        admin: true,
564        manager: true,
565        member: true,
566        staff: true,
567        viewer: true,
568        customer: true
569    }),
570    "tasks.view": freezeRoleDecisions({
571        owner: true,
572        admin: true,
573        manager: true,
574        member: true,
575        staff: true,
576        viewer: true,
577        customer: false
578    }),
579    "tasks.create": freezeRoleDecisions({
580        owner: true,
581        admin: true,
582        manager: true,
583        member: true,
584        staff: true,
585        viewer: false,
586        customer: false
587    }),
588    "tasks.edit": freezeRoleDecisions({
589        owner: true,
590        admin: true,
591        manager: true,
592        member: true,
593        staff: true,
594        viewer: false,
595        customer: false
596    }),
597    "assignment.visibility": freezeRoleDecisions({
598        owner: true,
599        admin: true,
600        manager: true,
601        member: false,
602        staff: false,
603        viewer: true,
604        customer: false
605    }),
606    "scheduling.view": freezeRoleDecisions({
607        owner: true,
608        admin: true,
609        manager: true,
610        member: true,
611        staff: true,
612        viewer: true,
613        customer: false
614    }),
615    "timeline.view": freezeRoleDecisions({
616        owner: true,
617        admin: true,
618        manager: true,
619        member: true,
620        staff: true,
621        viewer: true,
622        customer: false
623    }),
624    "customers.view": freezeRoleDecisions({
625        owner: true,
626        admin: true,
627        manager: true,
628        member: true,
629        staff: true,
630        viewer: true,
631        customer: false
632    }),
633    "customers.viewContactDetails": freezeRoleDecisions({
634        owner: true,
635        admin: true,
636        manager: true,
637        member: true,
638        staff: true,
639        viewer: false,
640        customer: false
641    }),
642    "customers.create": freezeRoleDecisions({
643        owner: true,
644        admin: true,
645        manager: true,
646        member: true,
647        staff: true,
648        viewer: false,
649        customer: false
650    }),
651    "customers.edit": freezeRoleDecisions({
652        owner: true,
653        admin: true,
654        manager: true,
655        member: true,
656        staff: true,
657        viewer: false,
658        customer: false
659    }),
660    "team.viewRoster": freezeRoleDecisions({
661        owner: true,
662        admin: true,
663        manager: true,
664        member: true,
665        staff: true,
666        viewer: true,
667        customer: false
668    }),
669    "team.viewInvitationStatus": freezeRoleDecisions({
670        owner: true,
671        admin: true,
672        manager: false,
673        member: false,
674        staff: false,
675        viewer: false,
676        customer: false
677    }),
678    "team.viewFullCoworkerEmail": freezeRoleDecisions({
679        owner: true,
680        admin: true,
681        manager: false,
682        member: false,
683        staff: false,
684        viewer: false,
685        customer: false
686    }),
687    "team.viewMaskedCoworkerEmail": freezeRoleDecisions({
688        owner: false,
689        admin: false,
690        manager: true,
691        member: true,
692        staff: true,
693        viewer: true,
694        customer: false
695    }),
696    "team.manage": freezeRoleDecisions({
697        owner: true,
698        admin: true,
699        manager: false,
700        member: false,
701        staff: false,
702        viewer: false,
703        customer: false
704    }),
705    "team.manageRoles": freezeRoleDecisions({
706        owner: true,
707        admin: true,
708        manager: false,
709        member: false,
710        staff: false,
711        viewer: false,
712        customer: false
713    }),
714    "invoices.view": freezeRoleDecisions({
715        owner: true,
716        admin: true,
717        manager: true,
718        member: true,
719        staff: true,
720        viewer: true,
721        customer: false
722    }),
723    "invoices.create": freezeRoleDecisions({
724        owner: true,
725        admin: true,
726        manager: true,
727        member: true,
728        staff: true,
729        viewer: false,
730        customer: false
731    }),
732    "invoices.edit": freezeRoleDecisions({
733        owner: true,
734        admin: true,
735        manager: true,
736        member: true,
737        staff: true,
738        viewer: false,
739        customer: false
740    }),
741    "invoices.send": freezeRoleDecisions({
742        owner: true,
743        admin: true,
744        manager: false,
745        member: true,
746        staff: true,
747        viewer: false,
748        customer: false
749    }),
750    "quotes.view": freezeRoleDecisions({
751        owner: true,
752        admin: true,
753        manager: true,
754        member: true,
755        staff: true,
756        viewer: false,
757        customer: false
758    }),
759    "quotes.create": freezeRoleDecisions({
760        owner: true,
761        admin: true,
762        manager: true,
763        member: true,
764        staff: true,
765        viewer: false,
766        customer: false
767    }),
768    "quotes.edit": freezeRoleDecisions({
769        owner: true,
770        admin: true,
771        manager: true,
772        member: true,
773        staff: true,
774        viewer: false,
775        customer: false
776    }),
777    "quotes.send": freezeRoleDecisions({
778        owner: true,
779        admin: true,
780        manager: false,
781        member: false,
782        staff: true,
783        viewer: false,
784        customer: false
785    }),
786    "payments.view": freezeRoleDecisions({
787        owner: true,
788        admin: true,
789        manager: true,
790        member: true,
791        staff: true,
792        viewer: true,
793        customer: false
794    }),
795    "payments.record": freezeRoleDecisions({
796        owner: true,
797        admin: true,
798        manager: false,
799        member: false,
800        staff: true,
801        viewer: false,
802        customer: false
803    }),
804    "payments.collect": freezeRoleDecisions({
805        owner: true,
806        admin: true,
807        manager: false,
808        member: false,
809        staff: true,
810        viewer: false,
811        customer: false
812    }),
813    "ledger.export": freezeRoleDecisions({
814        owner: true,
815        admin: true,
816        manager: false,
817        member: false,
818        staff: true,
819        viewer: false,
820        customer: false
821    }),
822    "reports.view": freezeRoleDecisions({
823        owner: true,
824        admin: true,
825        manager: true,
826        member: false,
827        staff: false,
828        viewer: false,
829        customer: false
830    }),
831    "analytics.view": freezeRoleDecisions({
832        owner: true,
833        admin: true,
834        manager: false,
835        member: false,
836        staff: false,
837        viewer: false,
838        customer: false
839    }),
840    "settings.view": freezeRoleDecisions({
841        owner: true,
842        admin: true,
843        manager: false,
844        member: false,
845        staff: false,
846        viewer: false,
847        customer: false
848    }),
849    "settings.edit": freezeRoleDecisions({
850        owner: true,
851        admin: true,
852        manager: false,
853        member: false,
854        staff: false,
855        viewer: false,
856        customer: false
857    }),
858    "billing.manage": freezeRoleDecisions({
859        owner: true,
860        admin: true,
861        manager: false,
862        member: false,
863        staff: false,
864        viewer: false,
865        customer: false
866    }),
867    "aiCommandCenter.access": freezeRoleDecisions({
868        owner: true,
869        admin: true,
870        manager: true,
871        member: true,
872        staff: true,
873        viewer: true,
874        customer: false
875    }),
876    "aiCommandCenter.executeActions": freezeRoleDecisions({
877        owner: true,
878        admin: true,
879        manager: true,
880        member: true,
881        staff: true,
882        viewer: false,
883        customer: false
884    })
885};
886const DEFAULT_PERMISSION_MATRIX = Object.freeze(permissionMatrix);
887const PERMISSION_CAPABILITIES = Object.freeze(Object.keys(DEFAULT_PERMISSION_MATRIX));
888const permissionRoleSet = new Set(PERMISSION_ROLES);
889const permissionCapabilitySet = new Set(PERMISSION_CAPABILITIES);
890function isPermissionRole(value) {
891    return typeof value === "string" && permissionRoleSet.has(value);
892}
893function isPermissionCapability(value) {
894    return typeof value === "string" && permissionCapabilitySet.has(value);
895}
896function hasDefaultPermission(role, capability) {
897    if (!isPermissionRole(role) || !isPermissionCapability(capability)) {
898        return false;
899    }
900    return DEFAULT_PERMISSION_MATRIX[capability][role];
901}
902const isValidPrincipalIdentifier = (value)=>typeof value === "string" && value.length > 0 && value.trim() === value;
903const readOwnDataProperty = (value, property)=>{
904    const descriptor = Object.getOwnPropertyDescriptor(value, property);
905    if (!descriptor || !("value" in descriptor)) {
906        return {
907            ok: false
908        };
909    }
910    return {
911        ok: true,
912        value: descriptor.value
913    };
914};
915/**
916 * Resolves a capability for a principal whose identity and tenant were already
917 * derived by a trusted server boundary. This module deliberately has no live
918 * data client; consumers must inject the narrow membership reader.
919 */ async function resolvePermission(principal, capability, readMemberships) {
920    try {
921        if (typeof principal !== "object" || principal === null || Array.isArray(principal) || !isPermissionCapability(capability)) {
922            return false;
923        }
924        const userIdProperty = readOwnDataProperty(principal, "userId");
925        const companyIdProperty = readOwnDataProperty(principal, "companyId");
926        if (!userIdProperty.ok || !companyIdProperty.ok || !isValidPrincipalIdentifier(userIdProperty.value) || !isValidPrincipalIdentifier(companyIdProperty.value)) {
927            return false;
928        }
929        const userId = userIdProperty.value;
930        const companyId = companyIdProperty.value;
931        const readResult = await readMemberships({
932            userId,
933            companyId
934        });
935        if (typeof readResult !== "object" || readResult === null || Array.isArray(readResult)) {
936            return false;
937        }
938        const okProperty = readOwnDataProperty(readResult, "ok");
939        const membershipsProperty = readOwnDataProperty(readResult, "memberships");
940        if (!okProperty.ok || okProperty.value !== true || !membershipsProperty.ok || !Array.isArray(membershipsProperty.value)) {
941            return false;
942        }
943        const memberships = membershipsProperty.value;
944        const lengthProperty = readOwnDataProperty(memberships, "length");
945        const membershipProperty = readOwnDataProperty(memberships, 0);
946        if (!lengthProperty.ok || lengthProperty.value !== 1 || !membershipProperty.ok) {
947            return false;
948        }
949        const membership = membershipProperty.value;
950        if (typeof membership !== "object" || membership === null || Array.isArray(membership)) {
951            return false;
952        }
953        const statusProperty = readOwnDataProperty(membership, "status");
954        const roleNameProperty = readOwnDataProperty(membership, "roleName");
955        if (!statusProperty.ok || statusProperty.value !== "active" || !roleNameProperty.ok || !isPermissionRole(roleNameProperty.value)) {
956            return false;
957        }
958        const roleName = roleNameProperty.value;
959        return DEFAULT_PERMISSION_MATRIX[capability][roleName];
960    } catch (e) {
961        return false;
962    }
963}
964
965
966/***/ }),
967
968/***/ 68177:
969/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
970
971
972// EXPORTS
973__webpack_require__.d(__webpack_exports__, {
974  cn: () => (/* binding */ cn),
975  sg: () => (/* binding */ debounce),
976  z3: () => (/* binding */ formatBytes),
977  Yq: () => (/* reexport */ formatDate)
978});
979
980// UNUSED EXPORTS: COUNTRIES, INDUSTRIES, formatCurrency, formatDateTime, formatDateToLocal
981
982// EXTERNAL MODULE: ./node_modules/.pnpm/[email protected]/node_modules/clsx/dist/clsx.mjs
983var clsx = __webpack_require__(79533);
984// EXTERNAL MODULE: ./node_modules/.pnpm/[email protected]/node_modules/tailwind-merge/dist/bundle-mjs.mjs
985var bundle_mjs = __webpack_require__(50712);
986// EXTERNAL MODULE: ./lib/company/settings.ts
987var settings = __webpack_require__(92008);
988;// ./lib/utils/date-formatter.ts
989
990function formatDate(dateString) {
991    if (!dateString) return "—";
992    try {
993        const date = typeof dateString === "string" ? new Date(dateString) : dateString;
994        if (isNaN(date.getTime())) {
995            return "—";
996        }
997        return new Intl.DateTimeFormat((0,settings/* getCompanyLocale */.WG)(), {
998            year: "numeric",
999            month: "short",
1000            day: "numeric"
1001        }).format(date);
1002    } catch (error) {
1003        return "—";
1004    }
1005}
1006function formatPhoneNumber(phone) {
1007    if (!phone) return "—";
1008    // Remove all non-digits
1009    const cleaned = phone.replace(/\D/g, "");
1010    // Format based on length
1011    if (cleaned.length === 10) {
1012        return "(".concat(cleaned.slice(0, 3), ") ").concat(cleaned.slice(3, 6), "-").concat(cleaned.slice(6));
1013    } else if (cleaned.length === 11 && cleaned[0] === "1") {
1014        return "+1 (".concat(cleaned.slice(1, 4), ") ").concat(cleaned.slice(4, 7), "-").concat(cleaned.slice(7));
1015    }
1016    // Return original if it doesn't match expected formats
1017    return phone;
1018}
1019function formatAddress(address) {
1020    if (!address) return "—";
1021    const parts = [];
1022    if (address.street) parts.push(address.street);
1023    if (address.city) parts.push(address.city);
1024    if (address.state) parts.push(address.state);
1025    if (address.zip) parts.push(address.zip);
1026    return parts.length > 0 ? parts.join(", ") : "—";
1027}
1028function formatCurrency(amount, currency) {
1029    if (amount === null || amount === undefined) return "—";
1030    return new Intl.NumberFormat(getCompanyLocale(), {
1031        style: "currency",
1032        currency: currency || getCompanyCurrency(),
1033        minimumFractionDigits: 2,
1034        maximumFractionDigits: 2
1035    }).format(amount);
1036}
1037function formatDateTime(dateString) {
1038    if (!dateString) return "—";
1039    try {
1040        const date = typeof dateString === "string" ? new Date(dateString) : dateString;
1041        if (isNaN(date.getTime())) {
1042            return "—";
1043        }
1044        return new Intl.DateTimeFormat(getCompanyLocale(), {
1045            year: "numeric",
1046            month: "short",
1047            day: "numeric",
1048            hour: "numeric",
1049            minute: "2-digit",
1050            hour12: true
1051        }).format(date);
1052    } catch (error) {
1053        return "—";
1054    }
1055}
1056
1057;// ./lib/utils.ts
1058
1059
1060function cn() {
1061    for(var _len = arguments.length, inputs = new Array(_len), _key = 0; _key < _len; _key++){
1062        inputs[_key] = arguments[_key];
1063    }
1064    return (0,bundle_mjs/* twMerge */.QP)((0,clsx/* clsx */.$)(inputs));
1065}
1066// Static data for dropdown options
1067const COUNTRIES = [
1068    {
1069        value: "USA",
1070        label: "USA"
1071    },
1072    {
1073        value: "UK",
1074        label: "UK"
1075    },
1076    {
1077        value: "Canada",
1078        label: "Canada"
1079    },
1080    {
1081        value: "Colombia",
1082        label: "Colombia"
1083    },
1084    {
1085        value: "Chile",
1086        label: "Chile"
1087    },
1088    {
1089        value: "Argentina",
1090        label: "Argentina"
1091    },
1092    {
1093        value: "Brazil",
1094        label: "Brazil"
1095    },
1096    {
1097        value: "Mexico",
1098        label: "Mexico"
1099    },
1100    {
1101        value: "Spain",
1102        label: "Spain"
1103    },
1104    {
1105        value: "Portugal",
1106        label: "Portugal"
1107    },
1108    {
1109        value: "France",
1110        label: "France"
1111    },
1112    {
1113        value: "Ireland",
1114        label: "Ireland"
1115    },
1116    {
1117        value: "Australia",
1118        label: "Australia"
1119    },
1120    {
1121        value: "New Zealand",
1122        label: "New Zealand"
1123    }
1124];
1125const INDUSTRIES = [
1126    {
1127        value: "air-conditioning",
1128        label: "Air Conditioning"
1129    },
1130    {
1131        value: "child-elderly-services",
1132        label: "Child & Elderly Services"
1133    },
1134    {
1135        value: "cleaning-services",
1136        label: "Cleaning Services"
1137    },
1138    {
1139        value: "dog-grooming",
1140        label: "Dog Grooming"
1141    },
1142    {
1143        value: "gardening",
1144        label: "Gardening"
1145    },
1146    {
1147        value: "general-contractors",
1148        label: "General Contractors"
1149    },
1150    {
1151        value: "painting",
1152        label: "Painting"
1153    },
1154    {
1155        value: "pest-control",
1156        label: "Pest Control"
1157    },
1158    {
1159        value: "rentals",
1160        label: "Rentals"
1161    },
1162    {
1163        value: "spa-services",
1164        label: "Spa Services"
1165    },
1166    {
1167        value: "vacation-rentals",
1168        label: "Vacation Rentals"
1169    },
1170    {
1171        value: "window-services",
1172        label: "Window Services"
1173    },
1174    {
1175        value: "electrical-services",
1176        label: "Electrical Services"
1177    },
1178    {
1179        value: "locksmith",
1180        label: "Locksmith"
1181    },
1182    {
1183        value: "housekeeping",
1184        label: "Housekeeping"
1185    },
1186    {
1187        value: "moving-services",
1188        label: "Moving Services"
1189    },
1190    {
1191        value: "plumbing",
1192        label: "Plumbing"
1193    },
1194    {
1195        value: "pool-services",
1196        label: "Pool Services"
1197    },
1198    {
1199        value: "handyman-services",
1200        label: "Handyman Services"
1201    },
1202    {
1203        value: "roofing-contractors",
1204        label: "Roofing Contractors"
1205    },
1206    {
1207        value: "lawn-care-landscaping",
1208        label: "Lawn Care & Landscaping"
1209    },
1210    {
1211        value: "hvac",
1212        label: "HVAC (Heating, Ventilation, and Air Conditioning) Services"
1213    },
1214    {
1215        value: "appliance-repair",
1216        label: "Appliance Repair"
1217    },
1218    {
1219        value: "smart-home-installation",
1220        label: "Smart Home Installation"
1221    },
1222    {
1223        value: "security-system-installation",
1224        label: "Security System Installation"
1225    },
1226    {
1227        value: "gutter-cleaning-repair",
1228        label: "Gutter Cleaning & Repair"
1229    },
1230    {
1231        value: "junk-removal-hauling",
1232        label: "Junk Removal & Hauling"
1233    },
1234    {
1235        value: "solar-panel-installation",
1236        label: "Solar Panel Installation & Maintenance"
1237    },
1238    {
1239        value: "home-inspection",
1240        label: "Home Inspection Services"
1241    },
1242    {
1243        value: "garage-door-repair",
1244        label: "Garage Door Repair & Installation"
1245    },
1246    {
1247        value: "carpentry-woodworking",
1248        label: "Carpentry & Woodworking"
1249    },
1250    {
1251        value: "tile-flooring-installation",
1252        label: "Tile & Flooring Installation"
1253    },
1254    {
1255        value: "paving-concrete",
1256        label: "Paving & Concrete Services"
1257    },
1258    {
1259        value: "interior-design",
1260        label: "Interior Design & Home Staging"
1261    },
1262    {
1263        value: "home-organization",
1264        label: "Home Organization & Decluttering"
1265    },
1266    {
1267        value: "well-septic-services",
1268        label: "Well & Septic System Services"
1269    },
1270    {
1271        value: "pressure-washing",
1272        label: "Pressure Washing & Exterior Cleaning"
1273    },
1274    {
1275        value: "custom-cabinet-furniture",
1276        label: "Custom Cabinet & Furniture Making"
1277    },
1278    {
1279        value: "other",
1280        label: "Other"
1281    }
1282];
1283function formatDateToLocal(date) {
1284    let locale = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : "en-US";
1285    return new Date(date).toLocaleDateString(locale, {
1286        day: "numeric",
1287        month: "short",
1288        year: "numeric"
1289    });
1290}
1291// Re-export utility functions from date-formatter
1292
1293// Format bytes to human readable format
1294function formatBytes(bytes) {
1295    let decimals = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : 2;
1296    if (bytes === 0) return '0 Bytes';
1297    const k = 1024;
1298    const dm = decimals < 0 ? 0 : decimals;
1299    const sizes = [
1300        'Bytes',
1301        'KB',
1302        'MB',
1303        'GB',
1304        'TB',
1305        'PB',
1306        'EB',
1307        'ZB',
1308        'YB'
1309    ];
1310    const i = Math.floor(Math.log(bytes) / Math.log(k));
1311    return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
1312}
1313// Debounce utility function
1314function debounce(func, delay) {
1315    let timeoutId;
1316    function debounced() {
1317        for(var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++){
1318            args[_key] = arguments[_key];
1319        }
1320        clearTimeout(timeoutId);
1321        timeoutId = setTimeout(()=>{
1322            func(...args);
1323        }, delay);
1324    }
1325    debounced.cancel = ()=>clearTimeout(timeoutId);
1326    return debounced;
1327}
1328
1329
1330/***/ }),
1331
1332/***/ 68762:
1333/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
1334
1335/* harmony export */ __webpack_require__.d(__webpack_exports__, {
1336/* harmony export */   vQ: () => (/* binding */ transformToDatabase)
1337/* harmony export */ });
1338/* unused harmony exports FIELD_NAME_MAP, transformFromDatabase, TransformingSupabaseClient, createTransformingClient */
1339// Supabase Field Name Transformer
1340// Auto-transforms between database snake_case and TypeScript camel
1340Case
1341// Database field name mapping
1342const FIELD_NAME_MAP = {
1343    // Database (snake_case) → TypeScript (camelCase)
1344    "pricing_type": "pricingType",
1345    "hourly_rate": "hourlyRate",
1346    "estimated_hours": "estimatedHours",
1347    "actual_hours": "actualHours",
1348    "payment_status": "paymentStatus",
1349    "deposit_percentage": "depositPercent",
1350    "deposit_amount": "depositAmount",
1351    "customer_address": "customerAddress",
1352    "assigned_to": "assignedTo",
1353    "special_instructions": "specialInstructions",
1354    "customer_id": "customerId",
1355    "company_id": "companyId",
1356    "locked_country": "lockedCountry",
1357    "country_code": "countryCode",
1358    "country_dial_code": "countryDialCode",
1359    "scheduled_date": "scheduledDate",
1360    "scheduled_time": "scheduledTime",
1361    "cancel_reason": "cancelReason",
1362    "canceled_at": "canceledAt",
1363    "created_at": "createdAt",
1364    "total_tax_amount": "totalTaxAmount",
1365    "quote_id": "quoteId",
1366    "quote_status": "quoteStatus",
1367    "invoice_status": "invoiceStatus",
1368    "require_deposit": "requireDeposit",
1369    "has_deposit": "hasDeposit",
1370    "recurrence_end_date": "recurrenceEndDate",
1371    "recurrence_count": "recurrenceCount",
1372    "recurrence_end_type": "recurrenceEndType",
1373    // Keep these as-is only within DB objects; do not surface as TS identifiers
1374    "deposit_paid": "deposit_paid"
1375};
1376// Transform database record to TypeScript camelCase
1377function transformFromDatabase(dbRecord) {
1378    if (!dbRecord || typeof dbRecord !== "object") {
1379        return dbRecord;
1380    }
1381    const transformed = {};
1382    for (const [dbField, tsField] of Object.entries(FIELD_NAME_MAP)){
1383        if (dbRecord[dbField] !== undefined) {
1384            transformed[tsField] = dbRecord[dbField];
1385        }
1386    }
1387    // Copy any unmapped fields as-is
1388    for (const [key, value] of Object.entries(dbRecord)){
1389        if (!FIELD_NAME_MAP[key]) {
1390            transformed[key] = value;
1391        }
1392    }
1393    return transformed;
1394}
1395// ---
1396// Minimal transformToDatabase helper for strict DB boundary enforcement
1397function transformToDatabase(obj) {
1398    const snake = {};
1399    Object.keys(obj).forEach((key)=>{
1400        if (obj[key] === undefined) {
1401            return;
1402        }
1403        const snakeKey = key.replace(/[A-Z]/g, (letter)=>"_".concat(letter.toLowerCase()));
1404        snake[snakeKey] = obj[key];
1405    });
1406    return snake;
1407}
1408// ---
1409// Enhanced Supabase client wrapper with auto-transform
1410class TransformingSupabaseClient {
1411    // Simple delegation approach - just transform the data
1412    from(table) {
1413        const originalQuery = this.supabase.from(table);
1414        // Return a proxy that intercepts method calls
1415        return new Proxy(originalQuery, {
1416            get (target, prop) {
1417                if (prop === "select") {
1418                    return async function() {
1419                        let query = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : "*";
1420                        const { data, error } = await target.select(query);
1421                        if (error) return {
1422                            data: null,
1423                            error
1424                        };
1425                        const transformedData = Array.isArray(data) ? data.map(transformFromDatabase) : data ? transformFromDatabase(data) : null;
1426                        return {
1427                            data: transformedData,
1428                            error
1429                        };
1430                    };
1431                }
1432                if (prop === "insert") {
1433                    return async function(record) {
1434                        const dbRecord = transformToDatabase(record);
1435                        return await target.insert(dbRecord);
1436                    };
1437                }
1438                if (prop === "update") {
1439                    return async function(record) {
1440                        const dbRecord = transformToDatabase(record);
1441                        return await target.update(dbRecord);
1442                    };
1443                }
1444                if (prop === "upsert") {
1445                    return async function(record) {
1446                        const dbRecord = transformToDatabase(record);
1447                        return await target.upsert(dbRecord);
1448                    };
1449                }
1450                // Pass through all other methods
1451                const value = target[prop];
1452                return typeof value === "function" ? value.bind(target) : value;
1453            }
1454        });
1455    }
1456    constructor(supabase){
1457        this.supabase = supabase;
1458    }
1459}
1460// Helper to create transformed supabase client
1461function createTransformingClient(supabase) {
1462    return new TransformingSupabaseClient(supabase);
1463}
1464
1465
1466/***/ }),
1467
1468/***/ 83636:
1469/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
1470
1471/* harmony export */ __webpack_require__.d(__webpack_exports__, {
1472/* harmony export */   QE: () => (/* binding */ TaskVersionMismatchError),
1473/* harmony export */   Sr: () => (/* binding */ sanitizeTaskWriteInput)
1474/* harmony export */ });
1475/* unused harmony exports createTaskSchema, updateTaskSchema, deleteTaskSchema, stopRecurringTaskSeriesSchema, ProtectedTaskFieldError, CustomerVersionMismatchError, SettingsVersionMismatchError, assertNoProtectedTaskFields, sanitizeTaskUpdateInput, filterUuidArray */
1476/* harmony import */ var zod__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(36619);
1477
1478const taskStatusSchema = zod__WEBPACK_IMPORTED_MODULE_0__/* ["enum"] */ .k5([
1479    "pending",
1480    "active",
1481    "completed",
1482    "canceled",
1483    "quotePending"
1484]);
1485const paymentStatusSchema = zod__WEBPACK_IMPORTED_MODULE_0__/* ["enum"] */ .k5([
1486    "paid",
1487    "partial",
1488    "unpaid",
1489    "no-charge"
1490]);
1491const pricingTypeSchema = zod__WEBPACK_IMPORTED_MODULE_0__/* ["enum"] */ .k5([
1492    "fixed",
1493    "hourly"
1494]);
1495const recurrenceSchema = zod__WEBPACK_IMPORTED_MODULE_0__/* ["enum"] */ .k5([
1496    "none",
1497    "daily",
1498    "weekly",
1499    "biweekly",
1500    "monthly",
1501    "bimonthly",
1502    "quarterly",
1503    "semiannual",
1504    "custom"
1505]);
1506function snakeField() {
1507    for(var _len = arguments.length, parts = new Array(_len), _key = 0; _key < _len; _key++){
1508        parts[_key] = arguments[_key];
1509    }
1510    return parts.join("_");
1511}
1512const createTaskSchema = zod__WEBPACK_IMPORTED_MODULE_0__/* .object */ .Ik({
1513    title: zod__WEBPACK_IMPORTED_MODULE_0__/* .string */ .Yj().min(1).max(255),
1514    description: zod__WEBPACK_IMPORTED_MODULE_0__/* .string */ .Yj().optional(),
1515    customerId: zod__WEBPACK_IMPORTED_MODULE_0__/* .string */ .Yj().uuid(),
1516    customerAddressId: zod__WEBPACK_IMPORTED_MODULE_0__/* .string */ .Yj().uuid().optional().nullable(),
1517    customerEmail: zod__WEBPACK_IMPORTED_MODULE_0__/* .string */ .Yj().email().optional(),
1518    scheduledDate: zod__WEBPACK_IMPORTED_MODULE_0__/* .string */ .Yj().min(1),
1519    scheduledTime: zod__WEBPACK_IMPORTED_MODULE_0__/* .string */ .Yj().optional().nullable(),
1520    boardId: zod__WEBPACK_IMPORTED_MODULE_0__/* .string */ .Yj().uuid().optional(),
1521    columnId: zod__WEBPACK_IMPORTED_MODULE_0__/* .string */ .Yj().optional(),
1522    amount: zod__WEBPACK_IMPORTED_MODULE_0__/* .number */ .ai().nonnegative().optional(),
1523    priority: zod__WEBPACK_IMPORTED_MODULE_0__/* ["enum"] */ .k5([
1524        "low",
1525        "medium",
1526        "high",
1527        "urgent"
1528    ]).optional(),
1529    status: taskStatusSchema.optional(),
1530    paymentStatus: paymentStatusSchema.optional(),
1531    // Nullable/optional persistence plumbing for explicit fixed-base storage.
1532    fixedBaseAmount: zod__WEBPACK_IMPORTED_MODULE_0__/* .number */ .ai().nonnegative().optional().nullable(),
1533    pricingType: pricingTypeSchema.optional(),
1534    hourlyRate: zod__WEBPACK_IMPORTED_MODULE_0__/* .number */ .ai().nonnegative().optional().nullable(),
1535    estimatedHours: zod__WEBPACK_IMPORTED_MODULE_0__/* .number */ .ai().nonnegative().optional().nullable(),
1536    subtotal: zod__WEBPACK_IMPORTED_MODULE_0__/* .number */ .ai().optional().nullable(),
1537    taxAmount: zod__WEBPACK_IMPORTED_MODULE_0__/* .number */ .ai().optional().nullable(),
1538    totalTaxAmount: zod__WEBPACK_IMPORTED_MODULE_0__/* .number */ .ai().optional().nullable(),
1539    taxes: zod__WEBPACK_IMPORTED_MODULE_0__/* .unknown */ .L5().optional().nullable(),
1540    taxSelection: zod__WEBPACK_IMPORTED_MODULE_0__/* .unknown */ .L5().optional().nullable(),
1541    specialInstructions: zod__WEBPACK_IMPORTED_MODULE_0__/* .string */ .Yj().optional().nullable(),
1542    internalNotes: zod__WEBPACK_IMPORTED_MODULE_0__/* .string */ .Yj().optional().nullable(),
1543    hasDeposit: zod__WEBPACK_IMPORTED_MODULE_0__/* .boolean */ .zM().optional().nullable(),
1544    depositPercentage: zod__WEBPACK_IMPORTED_MODULE_0__/* .number */ .ai().nonnegative().optional().nullable(),
1545    depositAmount: zod__WEBPACK_IMPORTED_MODULE_0__/* .number */ .ai().nonnegative().optional().nullable(),
1546    depositPaid: zod__WEBPACK_IMPORTED_MODULE_0__/* .boolean */ .zM().optional().nullable(),
1547    assignedTo: zod__WEBPACK_IMPORTED_MODULE_0__/* .array */ .YO(zod__WEBPACK_IMPORTED_MODULE_0__/* .string */ .Yj()).optional().nullable(),
1548    quoteId: zod__WEBPACK_IMPORTED_MODULE_0__/* .string */ .Yj().uuid().optional().nullable(),
1549    quoteStatus: zod__WEBPACK_IMPORTED_MODULE_0__/* .string */ .Yj().optional().nullable(),
1550    invoiceId: zod__WEBPACK_IMPORTED_MODULE_0__/* .string */ .Yj().uuid().optional().nullable(),
1551    invoiceStatus: zod__WEBPACK_IMPORTED_MODULE_0__/* .string */ .Yj().optional().nullable(),
1552    sendEmail: zod__WEBPACK_IMPORTED_MODULE_0__/* .boolean */ .zM().optional(),
1553    createRequestKey: zod__WEBPACK_IMPORTED_MODULE_0__/* .string */ .Yj().min(1).max(200).optional(),
1554    recurrence: recurrenceSchema.optional(),
1555    recurrenceEndType: zod__WEBPACK_IMPORTED_MODULE_0__/* ["enum"] */ .k5([
1556        "date",
1557        "count",
1558        "never"
1559    ]).optional().nullable(),
1560    recurrenceEndDate: zod__WEBPACK_IMPORTED_MODULE_0__/* .string */ .Yj().optional().nullable(),
1561    recurrenceCount: zod__WEBPACK_IMPORTED_MODULE_0__/* .number */ .ai().int().min(1).max(365).optional().nullable(),
1562    occurrenceIds: zod__WEBPACK_IMPORTED_MODULE_0__/* .array */ .YO(zod__WEBPACK_IMPORTED_MODULE_0__/* .string */ .Yj().uuid()).optional(),
1563    recurrenceSeriesId: zod__WEBPACK_IMPORTED_MODULE_0__/* .string */ .Yj().uuid().optional()
1564}).passthrough();
1565const updateTaskSchema = zod__WEBPACK_IMPORTED_MODULE_0__/* .object */ .Ik({
1566    id: zod__WEBPACK_IMPORTED_MODULE_0__/* .string */ .Yj().uuid(),
1567    lastKnownUpdatedAt: zod__WEBPACK_IMPORTED_MODULE_0__/* .string */ .Yj().datetime().nullable().optional(),
1568    patch: zod__WEBPACK_IMPORTED_MODULE_0__/* .object */ .Ik({
1569        title: zod__WEBPACK_IMPORTED_MODULE_0__/* .string */ .Yj().min(1).max(255).optional(),
1570        description: zod__WEBPACK_IMPORTED_MODULE_0__/* .string */ .Yj().optional(),
1571        customerId: zod__WEBPACK_IMPORTED_MODULE_0__/* .string */ .Yj().uuid().optional(),
1572        customerAddressId: zod__WEBPACK_IMPORTED_MODULE_0__/* .string */ .Yj().uuid().optional().nullable(),
1573        scheduledDate: zod__WEBPACK_IMPORTED_MODULE_0__/* .string */ .Yj().optional(),
1574        scheduledTime: zod__WEBPACK_IMPORTED_MODULE_0__/* .string */ .Yj().optional().nullable(),
1575        priority: zod__WEBPACK_IMPORTED_MODULE_0__/* ["enum"] */ .k5([
1576            "low",
1577            "medium",
1578            "high",
1579            "urgent"
1580        ]).optional(),
1581        status: taskStatusSchema.optional(),
1582        cancelReason: zod__WEBPACK_IMPORTED_MODULE_0__/* .unknown */ .L5().optional(),
1583        canceledAt: zod__WEBPACK_IMPORTED_MODULE_0__/* .unknown */ .L5().optional(),
1584        [snakeField("cancel", "reason")]: zod__WEBPACK_IMPORTED_MODULE_0__/* .unknown */ .L5().optional(),
1585        [snakeField("canceled", "at")]: zod__WEBPACK_IMPORTED_MODULE_0__/* .unknown */ .L5().optional(),
1586        specialInstructions: zod__WEBPACK_IMPORTED_MODULE_0__/* .string */ .Yj().optional().nullable(),
1587        internalNotes: zod__WEBPACK_IMPORTED_MODULE_0__/* .string */ .Yj().optional().nullable(),
1588        assignedTo: zod__WEBPACK_IMPORTED_MODULE_0__/* .array */ .YO(zod__WEBPACK_IMPORTED_MODULE_0__/* .string */ .Yj()).optional().nullable(),
1589        boardId: zod__WEBPACK_IMPORTED_MODULE_0__/* .string */ .Yj().uuid().optional().nullable(),
1590        columnId: zod__WEBPACK_IMPORTED_MODULE_0__/* .string */ .Yj().uuid().optional().nullable(),
1591        position: zod__WEBPACK_IMPORTED_MODULE_0__/* .number */ .ai().int().nonnegative().optional(),
1592        recurrence: recurrenceSchema.optional(),
1593        recurrenceEndType: zod__WEBPACK_IMPORTED_MODULE_0__/* ["enum"] */ .k5([
1594            "date",
1595            "count",
1596            "never"
1597        ]).optional().nullable(),
1598        recurrenceEndDate: zod__WEBPACK_IMPORTED_MODULE_0__/* .string */ .Yj().optional().nullable(),
1599        recurrenceCount: zod__WEBPACK_IMPORTED_MODULE_0__/* .number */ .ai().int().min(1).max(365).optional().nullable()
1600    }).strict().refine((patch)=>Object.keys(patch).length > 0, {
1601        message: "At least one field required"
1602    })
1603});
1604const deleteTaskSchema = zod__WEBPACK_IMPORTED_MODULE_0__/* .object */ .Ik({
1605    id: zod__WEBPACK_IMPORTED_MODULE_0__/* .string */ .Yj().uuid()
1606});
1607const stopRecurringTaskSeriesSchema = zod__WEBPACK_IMPORTED_MODULE_0__/* .object */ .Ik({
1608    taskId: zod__WEBPACK_IMPORTED_MODULE_0__/* .string */ .Yj().uuid(),
1609    lastKnownUpdatedAt: zod__WEBPACK_IMPORTED_MODULE_0__/* .string */ .Yj().datetime(),
1610    recurrenceSeriesId: zod__WEBPACK_IMPORTED_MODULE_0__/* .string */ .Yj().uuid().optional(),
1611    cancelReason: zod__WEBPACK_IMPORTED_MODULE_0__/* .string */ .Yj().trim().min(1).max(2000).optional(),
1612    includeCancelReasonInEmail: zod__WEBPACK_IMPORTED_MODULE_0__/* .boolean */ .zM().optional(),
1613    canceledAt: zod__WEBPACK_IMPORTED_MODULE_0__/* .string */ .Yj().datetime().optional()
1614}
1614).strict();
1615const taskPhantomKeys = new Set([
1616    "id",
1617    "files",
1618    "customer",
1619    "customerAddress",
1620    "lineItems",
1621    "markAsQuote",
1622    "selectedAddressIndex",
1623    "companyId",
1624    "createdBy",
1625    "sendEmail",
1626    "customerEmail",
1627    "createRequestKey",
1628    "quoteProductionIntentId"
1629]);
1630const taskGenericUpdateBlockedKeys = new Set([
1631    "status",
1632    "cancelReason",
1633    "canceledAt",
1634    "cancel_reason",
1635    "canceled_at"
1636]);
1637const protectedTaskUpdateFields = new Set([
1638    "taxSelection",
1639    snakeField("tax", "selection"),
1640    "amount",
1641    "subtotal",
1642    "taxAmount",
1643    snakeField("tax", "amount"),
1644    "totalTaxAmount",
1645    snakeField("total", "tax", "amount"),
1646    "taxes",
1647    "fixedBaseAmount",
1648    snakeField("fixed", "base", "amount"),
1649    "lineItemsTotal",
1650    snakeField("line", "items", "total"),
1651    "hasLineItems",
1652    snakeField("has", "line", "items"),
1653    "pricingType",
1654    snakeField("pricing", "type"),
1655    "hourlyRate",
1656    snakeField("hourly", "rate"),
1657    "estimatedHours",
1658    snakeField("estimated", "hours"),
1659    "paymentStatus",
1660    snakeField("payment", "status"),
1661    "depositPaid",
1662    snakeField("deposit", "paid"),
1663    "depositPaidDate",
1664    snakeField("deposit", "paid", "date"),
1665    "hasDeposit",
1666    snakeField("has", "deposit"),
1667    "depositPercentage",
1668    snakeField("deposit", "percentage"),
1669    "depositPercent",
1670    snakeField("deposit", "percent"),
1671    "depositAmount",
1672    snakeField("deposit", "amount"),
1673    "depositRequired",
1674    snakeField("deposit", "required"),
1675    "requireDeposit",
1676    snakeField("require", "deposit"),
1677    "quoteId",
1678    snakeField("quote", "id"),
1679    "quoteStatus",
1680    snakeField("quote", "status"),
1681    "quoteSentAt",
1682    snakeField("quote", "sent", "at"),
1683    "invoiceId",
1684    snakeField("invoice", "id"),
1685    "invoiceStatus",
1686    snakeField("invoice", "status"),
1687    "invoiceSentAt",
1688    snakeField("invoice", "sent", "at"),
1689    "operationalEmailSentAt",
1690    snakeField("operational", "email", "sent", "at"),
1691    "sendEmailIntent",
1692    snakeField("send", "email", "intent")
1693]);
1694class ProtectedTaskFieldError extends Error {
1695    constructor(fields){
1696        super("Protected task update field".concat(fields.length === 1 ? "" : "s", ": ").concat(fields.join(", "))), this.fields = fields, this.code = "PROTECTED_FIELD";
1697        this.name = "ProtectedTaskFieldError";
1698    }
1699}
1700class TaskVersionMismatchError extends Error {
1701    constructor(){
1702        super("Task version mismatch"), this.code = "VERSION_MISMATCH";
1703        this.name = "TaskVersionMismatchError";
1704    }
1705}
1706class CustomerVersionMismatchError extends Error {
1707    constructor(){
1708        super("Customer version mismatch"), this.code = "VERSION_MISMATCH";
1709        this.name = "CustomerVersionMismatchError";
1710    }
1711}
1712class SettingsVersionMismatchError extends Error {
1713    constructor(){
1714        super("Settings version mismatch"), this.code = "VERSION_MISMATCH";
1715        this.name = "SettingsVersionMismatchError";
1716    }
1717}
1718function assertNoProtectedTaskFields(patch) {
1719    if (!patch || typeof patch !== "object" || Array.isArray(patch)) {
1720        return;
1721    }
1722    const fields = Object.keys(patch).filter((key)=>protectedTaskUpdateFields.has(key));
1723    if (fields.length > 0) {
1724        throw new ProtectedTaskFieldError(fields);
1725    }
1726}
1727function sanitizeTaskWriteInput(input) {
1728    const sanitized = {};
1729    for (const [key, value] of Object.entries(input)){
1730        if (taskPhantomKeys.has(key) || key === "requireDeposit" || key === "depositPercent") {
1731            continue;
1732        }
1733        sanitized[key] = value;
1734    }
1735    return sanitized;
1736}
1737function sanitizeTaskUpdateInput(input) {
1738    const sanitized = sanitizeTaskWriteInput(input);
1739    for (const key of taskGenericUpdateBlockedKeys){
1740        delete sanitized[key];
1741    }
1742    return sanitized;
1743}
1744function filterUuidArray(values) {
1745    if (!Array.isArray(values)) return undefined;
1746    const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
1747    const filtered = values.filter((value)=>typeof value === "string" && uuidRegex.test(value));
1748    return filtered;
1749}
1750
1751
1752/***/ }),
1753
1754/***/ 92008:
1755/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
1756
1757/* harmony export */ __webpack_require__.d(__webpack_exports__, {
1758/* harmony export */   E7: () => (/* binding */ getCompanyTimeFormat),
1759/* harmony export */   WG: () => (/* binding */ getCompanyLocale),
1760/* harmony export */   j7: () => (/* binding */ getCompanyDateFormat),
1761/* harmony export */   z5: () => (/* binding */ getCompanyCurrency)
1762/* harmony export */ });
1763/* unused harmony exports getCompanyCountry, getCompanyCountryKey, saveCompanyCountry, countryCurrencyMap */
1764// Company settings utilities
1765// This file provides helper functions to get company-specific settings
1766// These now come from Supabase via the useCompanySettings hook
1767// Note: These functions now serve as fallbacks when Supabase data isn't available
1768// The primary source should be the useCompanySettings hook
1769function getCompanyCountry() {
1770    // This is now a fallback - prefer using useCompanySettings hook
1771    // Default to USA (payment methods format)
1772    return "USA";
1773}
1774function getCompanyCountryKey() {
1775    // This is now a fallback - prefer using useCompanySettings hook
1776    // Default to united_states (settings format)
1777    return "united_states";
1778}
1779function normalizeCurrency(value) {
1780    if (typeof value !== "string") return null;
1781    const normalized = value.trim().toUpperCase();
1782    return /^[A-Z]{3}$/.test(normalized) ? normalized : null;
1783}
1784function readCompanyCurrency(input) {
1785    return typeof input === "object" && input !== null ? input.currency : input;
1786}
1787function readLegacyCurrency(input) {
1788    if (typeof input !== "object" || input === null) return input;
1789    var _input_defaultCurrency;
1790    return (_input_defaultCurrency = input["defaultCurrency"]) !== null && _input_defaultCurrency !== void 0 ? _input_defaultCurrency : input["default_currency"];
1791}
1792function getCompanyCurrency(company, settings) {
1793    var _normalizeCurrency, _ref;
1794    return (_ref = (_normalizeCurrency = normalizeCurrency(readCompanyCurrency(company))) !== null && _normalizeCurrency !== void 0 ? _normalizeCurrency : normalizeCurrency(readLegacyCurrency(settings))) !== null && _ref !== void 0 ? _ref : "USD";
1795}
1796function getCompanyLocale() {
1797    // This is now a fallback - prefer using useCompanySettings hook
1798    // Default to en
1799    return "en";
1800}
1801function getCompanyDateFormat() {
1802    // This is now a fallback - prefer using useCompanySettings hook
1803    // Default to MM/DD/YYYY for USA
1804    return "MM/DD/YYYY";
1805}
1806function getCompanyTimeFormat() {
1807    // This is now a fallback - prefer using useCompanySettings hook
1808    // Default to 12h for USA
1809    return "12h";
1810}
1811// Deprecated - kept for backward compatibility
1812function saveCompanyCountry(country) {
1813    console.warn('saveCompanyCountry is deprecated. Use useCompanySettings hook to update settings in Supabase.');
1814}
1815// Country to currency mappings (for reference)
1816const countryCurrencyMap = {
1817    "united_states": "USD",
1818    "united_kingdom": "GBP",
1819    "canada": "CAD",
1820    "colombia": "COP",
1821    "chile": "CLP",
1822    "argentina": "ARS",
1823    "brazil": "BRL",
1824    "france": "EUR",
1825    "germany": "EUR",
1826    "spain": "EUR",
1827    "netherlands": "EUR",
1828    "italy": "EUR",
1829    "australia": "AUD",
1830    "japan": "JPY",
1831    "mexico": "MXN",
1832    "india": "INR",
1833    "china": "CNY",
1834    "south_korea": "KRW"
1835};
1836
1837
1838/***/ })
1839
1840}]);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.