@varshylinc/onboarding-consent-engine 0.1.0 → 0.2.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.
Files changed (83) hide show
  1. package/README.md +27 -0
  2. package/dist/client/actions.d.ts +33 -0
  3. package/dist/client/actions.d.ts.map +1 -0
  4. package/dist/client/actions.js +47 -0
  5. package/dist/client/actions.js.map +1 -0
  6. package/dist/client/components/ConsentBlock.d.ts +13 -0
  7. package/dist/client/components/ConsentBlock.d.ts.map +1 -0
  8. package/dist/client/components/ConsentBlock.js +14 -0
  9. package/dist/client/components/ConsentBlock.js.map +1 -0
  10. package/dist/client/components/ConsentCheckbox.d.ts +11 -0
  11. package/dist/client/components/ConsentCheckbox.d.ts.map +1 -0
  12. package/dist/client/components/ConsentCheckbox.js +5 -0
  13. package/dist/client/components/ConsentCheckbox.js.map +1 -0
  14. package/dist/client/components/ConsentUpdateModal.d.ts +12 -0
  15. package/dist/client/components/ConsentUpdateModal.d.ts.map +1 -0
  16. package/dist/client/components/ConsentUpdateModal.js +9 -0
  17. package/dist/client/components/ConsentUpdateModal.js.map +1 -0
  18. package/dist/client/components/EmptyState.d.ts +8 -0
  19. package/dist/client/components/EmptyState.d.ts.map +1 -0
  20. package/dist/client/components/EmptyState.js +5 -0
  21. package/dist/client/components/EmptyState.js.map +1 -0
  22. package/dist/client/components/SignupConsentBlock.d.ts +15 -0
  23. package/dist/client/components/SignupConsentBlock.d.ts.map +1 -0
  24. package/dist/client/components/SignupConsentBlock.js +11 -0
  25. package/dist/client/components/SignupConsentBlock.js.map +1 -0
  26. package/dist/client/components/WelcomeScreen.d.ts +15 -0
  27. package/dist/client/components/WelcomeScreen.d.ts.map +1 -0
  28. package/dist/client/components/WelcomeScreen.js +7 -0
  29. package/dist/client/components/WelcomeScreen.js.map +1 -0
  30. package/{src/client/components/index.ts → dist/client/components/index.d.ts} +3 -0
  31. package/dist/client/components/index.d.ts.map +1 -0
  32. package/dist/client/components/index.js +7 -0
  33. package/dist/client/components/index.js.map +1 -0
  34. package/dist/client/index.d.ts +6 -0
  35. package/dist/client/index.d.ts.map +1 -0
  36. package/dist/client/index.js +3 -0
  37. package/dist/client/index.js.map +1 -0
  38. package/dist/index.d.ts +2 -0
  39. package/dist/index.d.ts.map +1 -1
  40. package/dist/index.js +1 -0
  41. package/dist/index.js.map +1 -1
  42. package/dist/shared/signupConsent.d.ts +27 -0
  43. package/dist/shared/signupConsent.d.ts.map +1 -0
  44. package/dist/shared/signupConsent.js +29 -0
  45. package/dist/shared/signupConsent.js.map +1 -0
  46. package/package.json +11 -6
  47. package/.eslintrc.cjs +0 -18
  48. package/CHANGELOG.md +0 -11
  49. package/MODULE.md +0 -130
  50. package/src/client/components/ConsentBlock.tsx +0 -73
  51. package/src/client/components/ConsentCheckbox.tsx +0 -53
  52. package/src/client/components/ConsentUpdateModal.tsx +0 -65
  53. package/src/client/components/EmptyState.tsx +0 -38
  54. package/src/client/components/WelcomeScreen.tsx +0 -64
  55. package/src/client/index.ts +0 -19
  56. package/src/index.ts +0 -20
  57. package/src/server/index.ts +0 -143
  58. package/src/server/lib/getAuditTrail.ts +0 -20
  59. package/src/server/lib/getCurrentConsents.ts +0 -25
  60. package/src/server/lib/getUserLatestConsents.ts +0 -27
  61. package/src/server/lib/hasUserConsented.ts +0 -18
  62. package/src/server/lib/index.ts +0 -7
  63. package/src/server/lib/needsConsentUpdate.ts +0 -28
  64. package/src/server/lib/recordConsent.ts +0 -13
  65. package/src/server/lib/recordSignupConsents.ts +0 -32
  66. package/src/server/migrations/0001_create_oce_schema_migrations.sql +0 -7
  67. package/src/server/migrations/0002_create_oce_consent_definitions.sql +0 -12
  68. package/src/server/migrations/0003_create_oce_user_consents.sql +0 -14
  69. package/src/server/migrations/0004_create_oce_consent_version_log.sql +0 -12
  70. package/src/server/templates/applyProductName.ts +0 -10
  71. package/src/server/templates/index.ts +0 -3
  72. package/src/server/templates/standardConsents.ts +0 -37
  73. package/src/shared/types.ts +0 -85
  74. package/tests/integration/integration.test.ts +0 -162
  75. package/tests/setup/global-setup.ts +0 -16
  76. package/tests/unit/applyProductName.test.ts +0 -20
  77. package/tests/unit/getAuditTrail.test.ts +0 -33
  78. package/tests/unit/hasUserConsented.test.ts +0 -24
  79. package/tests/unit/needsConsentUpdate.test.ts +0 -24
  80. package/tests/unit/recordConsent.test.ts +0 -41
  81. package/tsconfig.client.json +0 -15
  82. package/tsconfig.json +0 -19
  83. package/vitest.config.ts +0 -9
package/README.md CHANGED
@@ -38,6 +38,33 @@ const pending = await consent.needsConsentUpdate(String(user.id));
38
38
 
39
39
  ## Client usage
40
40
 
41
+ ### Signup consent (v0.2.0+)
42
+
43
+ ```tsx
44
+ import {
45
+ SignupConsentBlock,
46
+ buildSignupConsentsPayload,
47
+ } from '@varshylinc/onboarding-consent-engine/client';
48
+
49
+ const [aiTraining, setAiTraining] = useState(false);
50
+
51
+ <SignupConsentBlock
52
+ termsUrl="/legal/terms"
53
+ privacyUrl="/legal/privacy"
54
+ aiTrainingChecked={aiTraining}
55
+ onAiTrainingChange={setAiTraining}
56
+ learnMoreUrl="/legal/ai-data"
57
+ />
58
+
59
+ // On signup submit — ToS/Privacy implied granted; AI reflects checkbox
60
+ await consent.recordSignupConsents({
61
+ userId: String(user.id),
62
+ consents: buildSignupConsentsPayload({ aiTrainingGranted: aiTraining }),
63
+ });
64
+ ```
65
+
66
+ ### Welcome screen (first-run onboarding)
67
+
41
68
  ```tsx
42
69
  import { WelcomeScreen } from '@varshylinc/onboarding-consent-engine/client';
43
70
 
@@ -0,0 +1,33 @@
1
+ import type { UserConsent } from '../shared/types.js';
2
+ import { buildSignupConsentsPayload, type BuildSignupConsentsPayloadOptions } from '../shared/signupConsent.js';
3
+ export { buildSignupConsentsPayload, DEFAULT_AI_TRAINING_LABEL } from '../shared/signupConsent.js';
4
+ export type { BuildSignupConsentsPayloadOptions };
5
+ export interface RecordSignupConsentsActionInput {
6
+ userId: string;
7
+ aiTrainingGranted: boolean;
8
+ apiBaseUrl?: string;
9
+ ipAddress?: string;
10
+ userAgent?: string;
11
+ includeMarketing?: boolean;
12
+ marketingGranted?: boolean;
13
+ }
14
+ export type RecordSignupConsentsActionResult = {
15
+ ok: true;
16
+ records: UserConsent[];
17
+ } | {
18
+ ok: false;
19
+ error: string;
20
+ };
21
+ /** SOREN-callable: set explicit AI-training consent checkbox state. */
22
+ export declare function setAiTrainingConsent(checked: boolean): Promise<boolean>;
23
+ /** SOREN-callable: flip AI-training consent checkbox state. */
24
+ export declare function toggleAiTrainingConsent(current: boolean): Promise<boolean>;
25
+ /** POST signup consents built from hybrid signup UI state. */
26
+ export declare function recordSignupConsentsAction(input: RecordSignupConsentsActionInput): Promise<RecordSignupConsentsActionResult>;
27
+ export declare const consentActions: {
28
+ buildSignupConsentsPayload: typeof buildSignupConsentsPayload;
29
+ setAiTrainingConsent: typeof setAiTrainingConsent;
30
+ toggleAiTrainingConsent: typeof toggleAiTrainingConsent;
31
+ recordSignupConsents: typeof recordSignupConsentsAction;
32
+ };
33
+ //# sourceMappingURL=actions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../../src/client/actions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EACL,0BAA0B,EAC1B,KAAK,iCAAiC,EACvC,MAAM,4BAA4B,CAAC;AAEpC,OAAO,EAAE,0BAA0B,EAAE,yBAAyB,EAAE,MAAM,4BAA4B,CAAC;AACnG,YAAY,EAAE,iCAAiC,EAAE,CAAC;AAElD,MAAM,WAAW,+BAA+B;IAC9C,MAAM,EAAE,MAAM,CAAC;IACf,iBAAiB,EAAE,OAAO,CAAC;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED,MAAM,MAAM,gCAAgC,GACxC;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,WAAW,EAAE,CAAA;CAAE,GACpC;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEjC,uEAAuE;AACvE,wBAAsB,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAE7E;AAED,+DAA+D;AAC/D,wBAAsB,uBAAuB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAEhF;AAED,8DAA8D;AAC9D,wBAAsB,0BAA0B,CAC9C,KAAK,EAAE,+BAA+B,GACrC,OAAO,CAAC,gCAAgC,CAAC,CA4B3C;AAED,eAAO,MAAM,cAAc;;;;;CAK1B,CAAC"}
@@ -0,0 +1,47 @@
1
+ import { buildSignupConsentsPayload, } from '../shared/signupConsent.js';
2
+ export { buildSignupConsentsPayload, DEFAULT_AI_TRAINING_LABEL } from '../shared/signupConsent.js';
3
+ /** SOREN-callable: set explicit AI-training consent checkbox state. */
4
+ export async function setAiTrainingConsent(checked) {
5
+ return checked;
6
+ }
7
+ /** SOREN-callable: flip AI-training consent checkbox state. */
8
+ export async function toggleAiTrainingConsent(current) {
9
+ return !current;
10
+ }
11
+ /** POST signup consents built from hybrid signup UI state. */
12
+ export async function recordSignupConsentsAction(input) {
13
+ const base = input.apiBaseUrl ?? '';
14
+ const consents = buildSignupConsentsPayload({
15
+ aiTrainingGranted: input.aiTrainingGranted,
16
+ includeMarketing: input.includeMarketing,
17
+ marketingGranted: input.marketingGranted,
18
+ });
19
+ try {
20
+ const res = await fetch(`${base}/api/consent/signup`, {
21
+ method: 'POST',
22
+ headers: { 'Content-Type': 'application/json' },
23
+ credentials: 'include',
24
+ body: JSON.stringify({
25
+ userId: input.userId,
26
+ consents,
27
+ ipAddress: input.ipAddress,
28
+ userAgent: input.userAgent,
29
+ }),
30
+ });
31
+ const data = (await res.json());
32
+ if (!res.ok) {
33
+ return { ok: false, error: data.error ?? `Request failed (${res.status})` };
34
+ }
35
+ return { ok: true, records: data };
36
+ }
37
+ catch (e) {
38
+ return { ok: false, error: e.message };
39
+ }
40
+ }
41
+ export const consentActions = {
42
+ buildSignupConsentsPayload,
43
+ setAiTrainingConsent,
44
+ toggleAiTrainingConsent,
45
+ recordSignupConsents: recordSignupConsentsAction,
46
+ };
47
+ //# sourceMappingURL=actions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"actions.js","sourceRoot":"","sources":["../../src/client/actions.ts"],"names":[],"mappings":"AACA,OAAO,EACL,0BAA0B,GAE3B,MAAM,4BAA4B,CAAC;AAEpC,OAAO,EAAE,0BAA0B,EAAE,yBAAyB,EAAE,MAAM,4BAA4B,CAAC;AAiBnG,uEAAuE;AACvE,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,OAAgB;IACzD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,+DAA+D;AAC/D,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAAC,OAAgB;IAC5D,OAAO,CAAC,OAAO,CAAC;AAClB,CAAC;AAED,8DAA8D;AAC9D,MAAM,CAAC,KAAK,UAAU,0BAA0B,CAC9C,KAAsC;IAEtC,MAAM,IAAI,GAAG,KAAK,CAAC,UAAU,IAAI,EAAE,CAAC;IACpC,MAAM,QAAQ,GAAG,0BAA0B,CAAC;QAC1C,iBAAiB,EAAE,KAAK,CAAC,iBAAiB;QAC1C,gBAAgB,EAAE,KAAK,CAAC,gBAAgB;QACxC,gBAAgB,EAAE,KAAK,CAAC,gBAAgB;KACzC,CAAC,CAAC;IAEH,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,qBAAqB,EAAE;YACpD,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,WAAW,EAAE,SAAS;YACtB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gBACnB,MAAM,EAAE,KAAK,CAAC,MAAM;gBACpB,QAAQ;gBACR,SAAS,EAAE,KAAK,CAAC,SAAS;gBAC1B,SAAS,EAAE,KAAK,CAAC,SAAS;aAC3B,CAAC;SACH,CAAC,CAAC;QACH,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAuC,CAAC;QACtE,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,IAAI,mBAAmB,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC;QAC9E,CAAC;QACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IACrC,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAG,CAAW,CAAC,OAAO,EAAE,CAAC;IACpD,CAAC;AACH,CAAC;AAED,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,0BAA0B;IAC1B,oBAAoB;IACpB,uBAAuB;IACvB,oBAAoB,EAAE,0BAA0B;CACjD,CAAC"}
@@ -0,0 +1,13 @@
1
+ import type { ConsentDefinition } from '../../shared/types.js';
2
+ export interface ConsentBlockProps {
3
+ requiredConsents: ConsentDefinition[];
4
+ optionalConsents: ConsentDefinition[];
5
+ /** Array of definition keys the user has currently checked/granted */
6
+ value: string[];
7
+ onChange: (keys: string[]) => void;
8
+ productName: string;
9
+ legalLinks?: Record<string, string>;
10
+ disabled?: boolean;
11
+ }
12
+ export declare function ConsentBlock({ requiredConsents, optionalConsents, value, onChange, legalLinks, disabled, }: ConsentBlockProps): import("react/jsx-runtime").JSX.Element;
13
+ //# sourceMappingURL=ConsentBlock.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ConsentBlock.d.ts","sourceRoot":"","sources":["../../../src/client/components/ConsentBlock.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAG/D,MAAM,WAAW,iBAAiB;IAChC,gBAAgB,EAAE,iBAAiB,EAAE,CAAC;IACtC,gBAAgB,EAAE,iBAAiB,EAAE,CAAC;IACtC,sEAAsE;IACtE,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IACnC,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,wBAAgB,YAAY,CAAC,EAC3B,gBAAgB,EAChB,gBAAgB,EAChB,KAAK,EACL,QAAQ,EACR,UAAU,EACV,QAAQ,GACT,EAAE,iBAAiB,2CAkDnB"}
@@ -0,0 +1,14 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { ConsentCheckbox } from './ConsentCheckbox.js';
3
+ export function ConsentBlock({ requiredConsents, optionalConsents, value, onChange, legalLinks, disabled, }) {
4
+ const toggle = (key, checked) => {
5
+ if (checked) {
6
+ onChange([...value, key]);
7
+ }
8
+ else {
9
+ onChange(value.filter((k) => k !== key));
10
+ }
11
+ };
12
+ return (_jsxs("div", { className: "space-y-1", children: [requiredConsents.length > 0 && (_jsxs("div", { children: [_jsx("p", { className: "text-xs font-semibold uppercase tracking-wide text-gray-500 mb-1", children: "Required" }), requiredConsents.map((def) => (_jsx(ConsentCheckbox, { id: `consent-${def.key}`, checked: value.includes(def.key), onChange: (checked) => toggle(def.key, checked), label: def.display_text, required: true, legalUrl: legalLinks?.[def.key] ?? def.legal_url, disabled: disabled }, def.key)))] })), optionalConsents.length > 0 && (_jsxs("div", { className: "mt-3", children: [_jsx("p", { className: "text-xs font-semibold uppercase tracking-wide text-gray-500 mb-1", children: "Optional" }), optionalConsents.map((def) => (_jsx(ConsentCheckbox, { id: `consent-${def.key}`, checked: value.includes(def.key), onChange: (checked) => toggle(def.key, checked), label: def.display_text, legalUrl: legalLinks?.[def.key] ?? def.legal_url, disabled: disabled }, def.key)))] }))] }));
13
+ }
14
+ //# sourceMappingURL=ConsentBlock.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ConsentBlock.js","sourceRoot":"","sources":["../../../src/client/components/ConsentBlock.tsx"],"names":[],"mappings":";AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAavD,MAAM,UAAU,YAAY,CAAC,EAC3B,gBAAgB,EAChB,gBAAgB,EAChB,KAAK,EACL,QAAQ,EACR,UAAU,EACV,QAAQ,GACU;IAClB,MAAM,MAAM,GAAG,CAAC,GAAW,EAAE,OAAgB,EAAE,EAAE;QAC/C,IAAI,OAAO,EAAE,CAAC;YACZ,QAAQ,CAAC,CAAC,GAAG,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC;QAC5B,CAAC;aAAM,CAAC;YACN,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;QAC3C,CAAC;IACH,CAAC,CAAC;IAEF,OAAO,CACL,eAAK,SAAS,EAAC,WAAW,aACvB,gBAAgB,CAAC,MAAM,GAAG,CAAC,IAAI,CAC9B,0BACE,YAAG,SAAS,EAAC,kEAAkE,yBAE3E,EACH,gBAAgB,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAC7B,KAAC,eAAe,IAEd,EAAE,EAAE,WAAW,GAAG,CAAC,GAAG,EAAE,EACxB,OAAO,EAAE,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,EAChC,QAAQ,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,EAC/C,KAAK,EAAE,GAAG,CAAC,YAAY,EACvB,QAAQ,QACR,QAAQ,EAAE,UAAU,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,SAAS,EAChD,QAAQ,EAAE,QAAQ,IAPb,GAAG,CAAC,GAAG,CAQZ,CACH,CAAC,IACE,CACP,EACA,gBAAgB,CAAC,MAAM,GAAG,CAAC,IAAI,CAC9B,eAAK,SAAS,EAAC,MAAM,aACnB,YAAG,SAAS,EAAC,kEAAkE,yBAE3E,EACH,gBAAgB,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAC7B,KAAC,eAAe,IAEd,EAAE,EAAE,WAAW,GAAG,CAAC,GAAG,EAAE,EACxB,OAAO,EAAE,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,EAChC,QAAQ,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,EAC/C,KAAK,EAAE,GAAG,CAAC,YAAY,EACvB,QAAQ,EAAE,UAAU,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,SAAS,EAChD,QAAQ,EAAE,QAAQ,IANb,GAAG,CAAC,GAAG,CAOZ,CACH,CAAC,IACE,CACP,IACG,CACP,CAAC;AACJ,CAAC"}
@@ -0,0 +1,11 @@
1
+ export interface ConsentCheckboxProps {
2
+ id: string;
3
+ checked: boolean;
4
+ onChange: (checked: boolean) => void;
5
+ label: string;
6
+ required?: boolean;
7
+ legalUrl?: string | null;
8
+ disabled?: boolean;
9
+ }
10
+ export declare function ConsentCheckbox({ id, checked, onChange, label, required, legalUrl, disabled, }: ConsentCheckboxProps): import("react/jsx-runtime").JSX.Element;
11
+ //# sourceMappingURL=ConsentCheckbox.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ConsentCheckbox.d.ts","sourceRoot":"","sources":["../../../src/client/components/ConsentCheckbox.tsx"],"names":[],"mappings":"AAEA,MAAM,WAAW,oBAAoB;IACnC,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IACrC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,wBAAgB,eAAe,CAAC,EAC9B,EAAE,EACF,OAAO,EACP,QAAQ,EACR,KAAK,EACL,QAAQ,EACR,QAAQ,EACR,QAAQ,GACT,EAAE,oBAAoB,2CAgCtB"}
@@ -0,0 +1,5 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ export function ConsentCheckbox({ id, checked, onChange, label, required, legalUrl, disabled, }) {
3
+ return (_jsxs("div", { className: "flex items-start gap-3 py-2", children: [_jsx("input", { id: id, type: "checkbox", checked: checked, onChange: (e) => onChange(e.target.checked), disabled: disabled, "aria-required": required, className: "mt-1 h-4 w-4 rounded border-gray-300 text-blue-600 focus:ring-blue-500" }), _jsxs("label", { htmlFor: id, className: "text-sm text-gray-700 leading-snug", children: [label, required && (_jsx("span", { className: "ml-1 text-red-500", "aria-hidden": "true", children: "*" })), legalUrl && (_jsx("a", { href: legalUrl, target: "_blank", rel: "noopener noreferrer", className: "ml-1 text-blue-600 underline", children: "(view)" }))] })] }));
4
+ }
5
+ //# sourceMappingURL=ConsentCheckbox.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ConsentCheckbox.js","sourceRoot":"","sources":["../../../src/client/components/ConsentCheckbox.tsx"],"names":[],"mappings":";AAYA,MAAM,UAAU,eAAe,CAAC,EAC9B,EAAE,EACF,OAAO,EACP,QAAQ,EACR,KAAK,EACL,QAAQ,EACR,QAAQ,EACR,QAAQ,GACa;IACrB,OAAO,CACL,eAAK,SAAS,EAAC,6BAA6B,aAC1C,gBACE,EAAE,EAAE,EAAE,EACN,IAAI,EAAC,UAAU,EACf,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,EAC3C,QAAQ,EAAE,QAAQ,mBACH,QAAQ,EACvB,SAAS,EAAC,wEAAwE,GAClF,EACF,iBAAO,OAAO,EAAE,EAAE,EAAE,SAAS,EAAC,oCAAoC,aAC/D,KAAK,EACL,QAAQ,IAAI,CACX,eAAM,SAAS,EAAC,mBAAmB,iBAAa,MAAM,kBAE/C,CACR,EACA,QAAQ,IAAI,CACX,YACE,IAAI,EAAE,QAAQ,EACd,MAAM,EAAC,QAAQ,EACf,GAAG,EAAC,qBAAqB,EACzB,SAAS,EAAC,8BAA8B,uBAGtC,CACL,IACK,IACJ,CACP,CAAC;AACJ,CAAC"}
@@ -0,0 +1,12 @@
1
+ import type { ConsentDefinition } from '../../shared/types.js';
2
+ export interface ConsentUpdateModalProps {
3
+ productName: string;
4
+ updatedConsents: ConsentDefinition[];
5
+ value: string[];
6
+ onChange: (keys: string[]) => void;
7
+ onAccept: () => void;
8
+ loading?: boolean;
9
+ legalLinks?: Record<string, string>;
10
+ }
11
+ export declare function ConsentUpdateModal({ productName, updatedConsents, value, onChange, onAccept, loading, legalLinks, }: ConsentUpdateModalProps): import("react/jsx-runtime").JSX.Element;
12
+ //# sourceMappingURL=ConsentUpdateModal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ConsentUpdateModal.d.ts","sourceRoot":"","sources":["../../../src/client/components/ConsentUpdateModal.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAG/D,MAAM,WAAW,uBAAuB;IACtC,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,iBAAiB,EAAE,CAAC;IACrC,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IACnC,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACrC;AAED,wBAAgB,kBAAkB,CAAC,EACjC,WAAW,EACX,eAAe,EACf,KAAK,EACL,QAAQ,EACR,QAAQ,EACR,OAAO,EACP,UAAU,GACX,EAAE,uBAAuB,2CA0CzB"}
@@ -0,0 +1,9 @@
1
+ import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
+ import { ConsentBlock } from './ConsentBlock.js';
3
+ export function ConsentUpdateModal({ productName, updatedConsents, value, onChange, onAccept, loading, legalLinks, }) {
4
+ const required = updatedConsents.filter((d) => d.required);
5
+ const optional = updatedConsents.filter((d) => !d.required);
6
+ const allRequiredGranted = required.every((d) => value.includes(d.key));
7
+ return (_jsx("div", { className: "fixed inset-0 z-50 flex items-center justify-center bg-black/50 p-4", role: "dialog", "aria-modal": "true", children: _jsxs("div", { className: "w-full max-w-md bg-white rounded-2xl shadow-xl p-8", children: [_jsxs("h2", { className: "text-xl font-bold text-gray-900 mb-2", children: [productName, " has updated its policies"] }), _jsx("p", { className: "text-sm text-gray-500 mb-5", children: "Please review and accept the updated terms to continue." }), _jsx(ConsentBlock, { requiredConsents: required, optionalConsents: optional, value: value, onChange: onChange, productName: productName, legalLinks: legalLinks, disabled: loading }), _jsx("button", { onClick: onAccept, disabled: !allRequiredGranted || loading, className: "mt-6 w-full rounded-lg bg-blue-600 px-4 py-3 text-sm font-semibold text-white\n hover:bg-blue-700 disabled:opacity-40 disabled:cursor-not-allowed\n focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2\n transition-colors", children: loading ? 'Saving…' : 'Accept & Continue' })] }) }));
8
+ }
9
+ //# sourceMappingURL=ConsentUpdateModal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ConsentUpdateModal.js","sourceRoot":"","sources":["../../../src/client/components/ConsentUpdateModal.tsx"],"names":[],"mappings":";AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAYjD,MAAM,UAAU,kBAAkB,CAAC,EACjC,WAAW,EACX,eAAe,EACf,KAAK,EACL,QAAQ,EACR,QAAQ,EACR,OAAO,EACP,UAAU,GACc;IACxB,MAAM,QAAQ,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;IAC3D,MAAM,QAAQ,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;IAC5D,MAAM,kBAAkB,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAExE,OAAO,CACL,cACE,SAAS,EAAC,qEAAqE,EAC/E,IAAI,EAAC,QAAQ,gBACF,MAAM,YAEjB,eAAK,SAAS,EAAC,oDAAoD,aACjE,cAAI,SAAS,EAAC,sCAAsC,aACjD,WAAW,iCACT,EACL,YAAG,SAAS,EAAC,4BAA4B,wEAErC,EAEJ,KAAC,YAAY,IACX,gBAAgB,EAAE,QAAQ,EAC1B,gBAAgB,EAAE,QAAQ,EAC1B,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,QAAQ,EAClB,WAAW,EAAE,WAAW,EACxB,UAAU,EAAE,UAAU,EACtB,QAAQ,EAAE,OAAO,GACjB,EAEF,iBACE,OAAO,EAAE,QAAQ,EACjB,QAAQ,EAAE,CAAC,kBAAkB,IAAI,OAAO,EACxC,SAAS,EAAC,6SAGmB,YAE5B,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,mBAAmB,GACnC,IACL,GACF,CACP,CAAC;AACJ,CAAC"}
@@ -0,0 +1,8 @@
1
+ import React from 'react';
2
+ export interface EmptyStateProps {
3
+ title?: string;
4
+ description?: string;
5
+ action?: React.ReactNode;
6
+ }
7
+ export declare function EmptyState({ title, description, action, }: EmptyStateProps): import("react/jsx-runtime").JSX.Element;
8
+ //# sourceMappingURL=EmptyState.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EmptyState.d.ts","sourceRoot":"","sources":["../../../src/client/components/EmptyState.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,MAAM,WAAW,eAAe;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC1B;AAED,wBAAgB,UAAU,CAAC,EACzB,KAA0B,EAC1B,WAAqD,EACrD,MAAM,GACP,EAAE,eAAe,2CAyBjB"}
@@ -0,0 +1,5 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ export function EmptyState({ title = 'Nothing here yet', description = 'Data will appear here once available.', action, }) {
3
+ return (_jsxs("div", { className: "flex flex-col items-center justify-center py-16 px-4 text-center", children: [_jsx("div", { className: "mb-4 text-gray-300", children: _jsx("svg", { xmlns: "http://www.w3.org/2000/svg", className: "h-16 w-16", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 1.5, d: "M20 13V6a2 2 0 00-2-2H6a2 2 0 00-2 2v7m16 0v5a2 2 0 01-2 2H6a2 2 0 01-2-2v-5m16 0h-2.586a1 1 0 00-.707.293l-2.414 2.414a1 1 0 01-.707.293h-3.172a1 1 0 01-.707-.293l-2.414-2.414A1 1 0 006.586 13H4" }) }) }), _jsx("h3", { className: "text-lg font-semibold text-gray-700 mb-1", children: title }), _jsx("p", { className: "text-sm text-gray-500 max-w-xs", children: description }), action && _jsx("div", { className: "mt-4", children: action })] }));
4
+ }
5
+ //# sourceMappingURL=EmptyState.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EmptyState.js","sourceRoot":"","sources":["../../../src/client/components/EmptyState.tsx"],"names":[],"mappings":";AAQA,MAAM,UAAU,UAAU,CAAC,EACzB,KAAK,GAAG,kBAAkB,EAC1B,WAAW,GAAG,uCAAuC,EACrD,MAAM,GACU;IAChB,OAAO,CACL,eAAK,SAAS,EAAC,kEAAkE,aAC/E,cAAK,SAAS,EAAC,oBAAoB,YACjC,cACE,KAAK,EAAC,4BAA4B,EAClC,SAAS,EAAC,WAAW,EACrB,IAAI,EAAC,MAAM,EACX,OAAO,EAAC,WAAW,EACnB,MAAM,EAAC,cAAc,iBACT,MAAM,YAElB,eACE,aAAa,EAAC,OAAO,EACrB,cAAc,EAAC,OAAO,EACtB,WAAW,EAAE,GAAG,EAChB,CAAC,EAAC,qMAAqM,GACvM,GACE,GACF,EACN,aAAI,SAAS,EAAC,0CAA0C,YAAE,KAAK,GAAM,EACrE,YAAG,SAAS,EAAC,gCAAgC,YAAE,WAAW,GAAK,EAC9D,MAAM,IAAI,cAAK,SAAS,EAAC,MAAM,YAAE,MAAM,GAAO,IAC3C,CACP,CAAC;AACJ,CAAC"}
@@ -0,0 +1,15 @@
1
+ export interface SignupConsentBlockProps {
2
+ termsUrl: string;
3
+ privacyUrl: string;
4
+ /** Explicit AI-training consent — initialize to false (unchecked by default). */
5
+ aiTrainingChecked: boolean;
6
+ onAiTrainingChange: (checked: boolean) => void;
7
+ /** Override default owner-approved copy if needed. */
8
+ aiTrainingLabel?: string;
9
+ learnMoreUrl?: string;
10
+ /** Phrase after "By …" — default matches locked spec ("signing in"). */
11
+ actionPhrase?: string;
12
+ disabled?: boolean;
13
+ }
14
+ export declare function SignupConsentBlock({ termsUrl, privacyUrl, aiTrainingChecked, onAiTrainingChange, aiTrainingLabel, learnMoreUrl, actionPhrase, disabled, }: SignupConsentBlockProps): import("react/jsx-runtime").JSX.Element;
15
+ //# sourceMappingURL=SignupConsentBlock.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SignupConsentBlock.d.ts","sourceRoot":"","sources":["../../../src/client/components/SignupConsentBlock.tsx"],"names":[],"mappings":"AAIA,MAAM,WAAW,uBAAuB;IACtC,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,iFAAiF;IACjF,iBAAiB,EAAE,OAAO,CAAC;IAC3B,kBAAkB,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IAC/C,sDAAsD;IACtD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,wEAAwE;IACxE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,wBAAgB,kBAAkB,CAAC,EACjC,QAAQ,EACR,UAAU,EACV,iBAAiB,EACjB,kBAAkB,EAClB,eAA2C,EAC3C,YAAY,EACZ,YAA2B,EAC3B,QAAQ,GACT,EAAE,uBAAuB,2CA6DzB"}
@@ -0,0 +1,11 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { DEFAULT_AI_TRAINING_LABEL } from '../../shared/signupConsent.js';
3
+ import { setAiTrainingConsent } from '../actions.js';
4
+ export function SignupConsentBlock({ termsUrl, privacyUrl, aiTrainingChecked, onAiTrainingChange, aiTrainingLabel = DEFAULT_AI_TRAINING_LABEL, learnMoreUrl, actionPhrase = 'signing in', disabled, }) {
5
+ const handleAiTrainingChange = async (checked) => {
6
+ const next = await setAiTrainingConsent(checked);
7
+ onAiTrainingChange(next);
8
+ };
9
+ return (_jsxs("div", { className: "space-y-3", children: [_jsxs("p", { className: "text-sm text-gray-600 leading-snug", children: ["By ", actionPhrase, ", you agree to our", ' ', _jsx("a", { href: termsUrl, target: "_blank", rel: "noopener noreferrer", className: "text-blue-600 underline", children: "Terms of Service" }), ' ', "and", ' ', _jsx("a", { href: privacyUrl, target: "_blank", rel: "noopener noreferrer", className: "text-blue-600 underline", children: "Privacy Policy" }), "."] }), _jsxs("div", { className: "flex items-start gap-3", children: [_jsx("input", { id: "signup-consent-ai-training", type: "checkbox", checked: aiTrainingChecked, onChange: (e) => void handleAiTrainingChange(e.target.checked), disabled: disabled, className: "mt-1 h-4 w-4 rounded border-gray-300 text-blue-600 focus:ring-blue-500" }), _jsxs("label", { htmlFor: "signup-consent-ai-training", className: "text-sm text-gray-700 leading-snug", children: [aiTrainingLabel, learnMoreUrl && (_jsxs(_Fragment, { children: [' ', _jsx("a", { href: learnMoreUrl, target: "_blank", rel: "noopener noreferrer", className: "text-blue-600 underline", children: "Learn more" })] }))] })] })] }));
10
+ }
11
+ //# sourceMappingURL=SignupConsentBlock.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SignupConsentBlock.js","sourceRoot":"","sources":["../../../src/client/components/SignupConsentBlock.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,yBAAyB,EAAE,MAAM,+BAA+B,CAAC;AAC1E,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAgBrD,MAAM,UAAU,kBAAkB,CAAC,EACjC,QAAQ,EACR,UAAU,EACV,iBAAiB,EACjB,kBAAkB,EAClB,eAAe,GAAG,yBAAyB,EAC3C,YAAY,EACZ,YAAY,GAAG,YAAY,EAC3B,QAAQ,GACgB;IACxB,MAAM,sBAAsB,GAAG,KAAK,EAAE,OAAgB,EAAE,EAAE;QACxD,MAAM,IAAI,GAAG,MAAM,oBAAoB,CAAC,OAAO,CAAC,CAAC;QACjD,kBAAkB,CAAC,IAAI,CAAC,CAAC;IAC3B,CAAC,CAAC;IAEF,OAAO,CACL,eAAK,SAAS,EAAC,WAAW,aACxB,aAAG,SAAS,EAAC,oCAAoC,oBAC3C,YAAY,wBAAoB,GAAG,EACvC,YACE,IAAI,EAAE,QAAQ,EACd,MAAM,EAAC,QAAQ,EACf,GAAG,EAAC,qBAAqB,EACzB,SAAS,EAAC,yBAAyB,iCAGjC,EAAC,GAAG,SACJ,GAAG,EACP,YACE,IAAI,EAAE,UAAU,EAChB,MAAM,EAAC,QAAQ,EACf,GAAG,EAAC,qBAAqB,EACzB,SAAS,EAAC,yBAAyB,+BAGjC,SAEF,EAEJ,eAAK,SAAS,EAAC,wBAAwB,aACrC,gBACE,EAAE,EAAC,4BAA4B,EAC/B,IAAI,EAAC,UAAU,EACf,OAAO,EAAE,iBAAiB,EAC1B,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,sBAAsB,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,EAC9D,QAAQ,EAAE,QAAQ,EAClB,SAAS,EAAC,wEAAwE,GAClF,EACF,iBACE,OAAO,EAAC,4BAA4B,EACpC,SAAS,EAAC,oCAAoC,aAE7C,eAAe,EACf,YAAY,IAAI,CACf,8BACG,GAAG,EACJ,YACE,IAAI,EAAE,YAAY,EAClB,MAAM,EAAC,QAAQ,EACf,GAAG,EAAC,qBAAqB,EACzB,SAAS,EAAC,yBAAyB,2BAGjC,IACH,CACJ,IACK,IACJ,IACF,CACP,CAAC;AACJ,CAAC"}
@@ -0,0 +1,15 @@
1
+ import React from 'react';
2
+ import type { ConsentDefinition } from '../../shared/types.js';
3
+ export interface WelcomeScreenProps {
4
+ productName: string;
5
+ requiredConsents: ConsentDefinition[];
6
+ optionalConsents: ConsentDefinition[];
7
+ value: string[];
8
+ onChange: (keys: string[]) => void;
9
+ onContinue: () => void;
10
+ legalLinks?: Record<string, string>;
11
+ loading?: boolean;
12
+ logo?: React.ReactNode;
13
+ }
14
+ export declare function WelcomeScreen({ productName, requiredConsents, optionalConsents, value, onChange, onContinue, legalLinks, loading, logo, }: WelcomeScreenProps): import("react/jsx-runtime").JSX.Element;
15
+ //# sourceMappingURL=WelcomeScreen.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WelcomeScreen.d.ts","sourceRoot":"","sources":["../../../src/client/components/WelcomeScreen.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAG/D,MAAM,WAAW,kBAAkB;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,gBAAgB,EAAE,iBAAiB,EAAE,CAAC;IACtC,gBAAgB,EAAE,iBAAiB,EAAE,CAAC;IACtC,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IACnC,UAAU,EAAE,MAAM,IAAI,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CACxB;AAED,wBAAgB,aAAa,CAAC,EAC5B,WAAW,EACX,gBAAgB,EAChB,gBAAgB,EAChB,KAAK,EACL,QAAQ,EACR,UAAU,EACV,UAAU,EACV,OAAO,EACP,IAAI,GACL,EAAE,kBAAkB,2CAqCpB"}
@@ -0,0 +1,7 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { ConsentBlock } from './ConsentBlock.js';
3
+ export function WelcomeScreen({ productName, requiredConsents, optionalConsents, value, onChange, onContinue, legalLinks, loading, logo, }) {
4
+ const allRequiredGranted = requiredConsents.every((d) => value.includes(d.key));
5
+ return (_jsx("div", { className: "min-h-screen flex items-center justify-center bg-gray-50 p-4", children: _jsxs("div", { className: "w-full max-w-md bg-white rounded-2xl shadow-lg p-8", children: [logo && _jsx("div", { className: "flex justify-center mb-6", children: logo }), _jsxs("h1", { className: "text-2xl font-bold text-gray-900 text-center mb-2", children: ["Welcome to ", productName] }), _jsx("p", { className: "text-sm text-gray-500 text-center mb-6", children: "Before you get started, please review and accept the following." }), _jsx(ConsentBlock, { requiredConsents: requiredConsents, optionalConsents: optionalConsents, value: value, onChange: onChange, productName: productName, legalLinks: legalLinks, disabled: loading }), _jsx("button", { onClick: onContinue, disabled: !allRequiredGranted || loading, className: "mt-6 w-full rounded-lg bg-blue-600 px-4 py-3 text-sm font-semibold text-white\n hover:bg-blue-700 disabled:opacity-40 disabled:cursor-not-allowed\n focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2\n transition-colors", children: loading ? 'Saving…' : 'Continue' })] }) }));
6
+ }
7
+ //# sourceMappingURL=WelcomeScreen.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WelcomeScreen.js","sourceRoot":"","sources":["../../../src/client/components/WelcomeScreen.tsx"],"names":[],"mappings":";AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAcjD,MAAM,UAAU,aAAa,CAAC,EAC5B,WAAW,EACX,gBAAgB,EAChB,gBAAgB,EAChB,KAAK,EACL,QAAQ,EACR,UAAU,EACV,UAAU,EACV,OAAO,EACP,IAAI,GACe;IACnB,MAAM,kBAAkB,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAEhF,OAAO,CACL,cAAK,SAAS,EAAC,8DAA8D,YAC3E,eAAK,SAAS,EAAC,oDAAoD,aAChE,IAAI,IAAI,cAAK,SAAS,EAAC,0BAA0B,YAAE,IAAI,GAAO,EAC/D,cAAI,SAAS,EAAC,mDAAmD,4BACnD,WAAW,IACpB,EACL,YAAG,SAAS,EAAC,wCAAwC,gFAEjD,EAEJ,KAAC,YAAY,IACX,gBAAgB,EAAE,gBAAgB,EAClC,gBAAgB,EAAE,gBAAgB,EAClC,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,QAAQ,EAClB,WAAW,EAAE,WAAW,EACxB,UAAU,EAAE,UAAU,EACtB,QAAQ,EAAE,OAAO,GACjB,EAEF,iBACE,OAAO,EAAE,UAAU,EACnB,QAAQ,EAAE,CAAC,kBAAkB,IAAI,OAAO,EACxC,SAAS,EAAC,6SAGmB,YAE5B,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,UAAU,GAC1B,IACL,GACF,CACP,CAAC;AACJ,CAAC"}
@@ -8,3 +8,6 @@ export { EmptyState } from './EmptyState.js';
8
8
  export type { EmptyStateProps } from './EmptyState.js';
9
9
  export { ConsentUpdateModal } from './ConsentUpdateModal.js';
10
10
  export type { ConsentUpdateModalProps } from './ConsentUpdateModal.js';
11
+ export { SignupConsentBlock } from './SignupConsentBlock.js';
12
+ export type { SignupConsentBlockProps } from './SignupConsentBlock.js';
13
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/client/components/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,YAAY,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AACjE,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,YAAY,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAC3D,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,YAAY,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAC7D,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,YAAY,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,YAAY,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AACvE,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,YAAY,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC"}
@@ -0,0 +1,7 @@
1
+ export { ConsentCheckbox } from './ConsentCheckbox.js';
2
+ export { ConsentBlock } from './ConsentBlock.js';
3
+ export { WelcomeScreen } from './WelcomeScreen.js';
4
+ export { EmptyState } from './EmptyState.js';
5
+ export { ConsentUpdateModal } from './ConsentUpdateModal.js';
6
+ export { SignupConsentBlock } from './SignupConsentBlock.js';
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/client/components/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAEvD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEnD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAE7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC"}
@@ -0,0 +1,6 @@
1
+ export { ConsentCheckbox, ConsentBlock, WelcomeScreen, EmptyState, ConsentUpdateModal, SignupConsentBlock, } from './components/index.js';
2
+ export type { ConsentCheckboxProps, ConsentBlockProps, WelcomeScreenProps, EmptyStateProps, ConsentUpdateModalProps, SignupConsentBlockProps, } from './components/index.js';
3
+ export { consentActions, buildSignupConsentsPayload, setAiTrainingConsent, toggleAiTrainingConsent, recordSignupConsentsAction, DEFAULT_AI_TRAINING_LABEL, } from './actions.js';
4
+ export type { BuildSignupConsentsPayloadOptions, RecordSignupConsentsActionInput, RecordSignupConsentsActionResult, } from './actions.js';
5
+ export type { ConsentDefinition, ConsentStatus, AuditEntry, } from '../shared/types.js';
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,YAAY,EACZ,aAAa,EACb,UAAU,EACV,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,uBAAuB,CAAC;AAC/B,YAAY,EACV,oBAAoB,EACpB,iBAAiB,EACjB,kBAAkB,EAClB,eAAe,EACf,uBAAuB,EACvB,uBAAuB,GACxB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,cAAc,EACd,0BAA0B,EAC1B,oBAAoB,EACpB,uBAAuB,EACvB,0BAA0B,EAC1B,yBAAyB,GAC1B,MAAM,cAAc,CAAC;AACtB,YAAY,EACV,iCAAiC,EACjC,+BAA+B,EAC/B,gCAAgC,GACjC,MAAM,cAAc,CAAC;AACtB,YAAY,EACV,iBAAiB,EACjB,aAAa,EACb,UAAU,GACX,MAAM,oBAAoB,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { ConsentCheckbox, ConsentBlock, WelcomeScreen, EmptyState, ConsentUpdateModal, SignupConsentBlock, } from './components/index.js';
2
+ export { consentActions, buildSignupConsentsPayload, setAiTrainingConsent, toggleAiTrainingConsent, recordSignupConsentsAction, DEFAULT_AI_TRAINING_LABEL, } from './actions.js';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,YAAY,EACZ,aAAa,EACb,UAAU,EACV,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,uBAAuB,CAAC;AAS/B,OAAO,EACL,cAAc,EACd,0BAA0B,EAC1B,oBAAoB,EACpB,uBAAuB,EACvB,0BAA0B,EAC1B,yBAAyB,GAC1B,MAAM,cAAc,CAAC"}
package/dist/index.d.ts CHANGED
@@ -1,3 +1,5 @@
1
1
  export { runMigrations, seedStandardConsents, createConsentModule, STANDARD_CONSENTS, applyProductName, } from './server/index.js';
2
2
  export type { ConsentDefinition, UserConsent, ConsentVersionLog, RecordConsentInput, RecordSignupConsentsInput, ConsentStatus, AuditEntry, ConsentModuleAdapter, ConsentModuleConfig, ConsentModule, } from './shared/types.js';
3
+ export { buildSignupConsentsPayload, DEFAULT_AI_TRAINING_LABEL, IMPLIED_SIGNUP_CONSENT_KEYS, AI_TRAINING_CONSENT_KEY, } from './shared/signupConsent.js';
4
+ export type { BuildSignupConsentsPayloadOptions, SignupConsentEntry, } from './shared/signupConsent.js';
3
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EACb,oBAAoB,EACpB,mBAAmB,EACnB,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,mBAAmB,CAAC;AAE3B,YAAY,EACV,iBAAiB,EACjB,WAAW,EACX,iBAAiB,EACjB,kBAAkB,EAClB,yBAAyB,EACzB,aAAa,EACb,UAAU,EACV,oBAAoB,EACpB,mBAAmB,EACnB,aAAa,GACd,MAAM,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EACb,oBAAoB,EACpB,mBAAmB,EACnB,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,mBAAmB,CAAC;AAE3B,YAAY,EACV,iBAAiB,EACjB,WAAW,EACX,iBAAiB,EACjB,kBAAkB,EAClB,yBAAyB,EACzB,aAAa,EACb,UAAU,EACV,oBAAoB,EACpB,mBAAmB,EACnB,aAAa,GACd,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,0BAA0B,EAC1B,yBAAyB,EACzB,2BAA2B,EAC3B,uBAAuB,GACxB,MAAM,2BAA2B,CAAC;AACnC,YAAY,EACV,iCAAiC,EACjC,kBAAkB,GACnB,MAAM,2BAA2B,CAAC"}
package/dist/index.js CHANGED
@@ -1,2 +1,3 @@
1
1
  export { runMigrations, seedStandardConsents, createConsentModule, STANDARD_CONSENTS, applyProductName, } from './server/index.js';
2
+ export { buildSignupConsentsPayload, DEFAULT_AI_TRAINING_LABEL, IMPLIED_SIGNUP_CONSENT_KEYS, AI_TRAINING_CONSENT_KEY, } from './shared/signupConsent.js';
2
3
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EACb,oBAAoB,EACpB,mBAAmB,EACnB,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EACb,oBAAoB,EACpB,mBAAmB,EACnB,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,mBAAmB,CAAC;AAe3B,OAAO,EACL,0BAA0B,EAC1B,yBAAyB,EACzB,2BAA2B,EAC3B,uBAAuB,GACxB,MAAM,2BAA2B,CAAC"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Hybrid signup consent — implied ToS/Privacy + explicit optional AI training.
3
+ * See MODULE.md and product integration spec §6.1.
4
+ */
5
+ /** Owner-approved default copy for Job Site Intel.ai (products may override in UI). */
6
+ export declare const DEFAULT_AI_TRAINING_LABEL = "Help improve construction intelligence by sharing your anonymized project data.";
7
+ /** Consent keys recorded as implied-granted when the user completes signup. */
8
+ export declare const IMPLIED_SIGNUP_CONSENT_KEYS: readonly ["terms_of_service", "privacy_policy"];
9
+ export declare const AI_TRAINING_CONSENT_KEY: "ai_training";
10
+ export interface BuildSignupConsentsPayloadOptions {
11
+ /** Explicit AI-training checkbox value. Must default to false in signup UI. */
12
+ aiTrainingGranted: boolean;
13
+ /** Include marketing_emails in the payload (default false — not part of SignupConsentBlock). */
14
+ includeMarketing?: boolean;
15
+ marketingGranted?: boolean;
16
+ }
17
+ export type SignupConsentEntry = {
18
+ key: string;
19
+ granted: boolean;
20
+ };
21
+ /**
22
+ * Builds the consent array for recordSignupConsents after signup.
23
+ * ToS and Privacy are always granted (implied by signup action).
24
+ * AI training is separate and must reflect the unchecked-by-default checkbox.
25
+ */
26
+ export declare function buildSignupConsentsPayload(options: BuildSignupConsentsPayloadOptions): SignupConsentEntry[];
27
+ //# sourceMappingURL=signupConsent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signupConsent.d.ts","sourceRoot":"","sources":["../../src/shared/signupConsent.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,uFAAuF;AACvF,eAAO,MAAM,yBAAyB,oFAC6C,CAAC;AAEpF,+EAA+E;AAC/E,eAAO,MAAM,2BAA2B,iDAAkD,CAAC;AAE3F,eAAO,MAAM,uBAAuB,EAAG,aAAsB,CAAC;AAE9D,MAAM,WAAW,iCAAiC;IAChD,+EAA+E;IAC/E,iBAAiB,EAAE,OAAO,CAAC;IAC3B,gGAAgG;IAChG,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED,MAAM,MAAM,kBAAkB,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC;AAEnE;;;;GAIG;AACH,wBAAgB,0BAA0B,CACxC,OAAO,EAAE,iCAAiC,GACzC,kBAAkB,EAAE,CAatB"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Hybrid signup consent — implied ToS/Privacy + explicit optional AI training.
3
+ * See MODULE.md and product integration spec §6.1.
4
+ */
5
+ /** Owner-approved default copy for Job Site Intel.ai (products may override in UI). */
6
+ export const DEFAULT_AI_TRAINING_LABEL = 'Help improve construction intelligence by sharing your anonymized project data.';
7
+ /** Consent keys recorded as implied-granted when the user completes signup. */
8
+ export const IMPLIED_SIGNUP_CONSENT_KEYS = ['terms_of_service', 'privacy_policy'];
9
+ export const AI_TRAINING_CONSENT_KEY = 'ai_training';
10
+ /**
11
+ * Builds the consent array for recordSignupConsents after signup.
12
+ * ToS and Privacy are always granted (implied by signup action).
13
+ * AI training is separate and must reflect the unchecked-by-default checkbox.
14
+ */
15
+ export function buildSignupConsentsPayload(options) {
16
+ const consents = [
17
+ { key: 'terms_of_service', granted: true },
18
+ { key: 'privacy_policy', granted: true },
19
+ { key: AI_TRAINING_CONSENT_KEY, granted: options.aiTrainingGranted },
20
+ ];
21
+ if (options.includeMarketing) {
22
+ consents.push({
23
+ key: 'marketing_emails',
24
+ granted: options.marketingGranted ?? false,
25
+ });
26
+ }
27
+ return consents;
28
+ }
29
+ //# sourceMappingURL=signupConsent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signupConsent.js","sourceRoot":"","sources":["../../src/shared/signupConsent.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,uFAAuF;AACvF,MAAM,CAAC,MAAM,yBAAyB,GACpC,iFAAiF,CAAC;AAEpF,+EAA+E;AAC/E,MAAM,CAAC,MAAM,2BAA2B,GAAG,CAAC,kBAAkB,EAAE,gBAAgB,CAAU,CAAC;AAE3F,MAAM,CAAC,MAAM,uBAAuB,GAAG,aAAsB,CAAC;AAY9D;;;;GAIG;AACH,MAAM,UAAU,0BAA0B,CACxC,OAA0C;IAE1C,MAAM,QAAQ,GAAyB;QACrC,EAAE,GAAG,EAAE,kBAAkB,EAAE,OAAO,EAAE,IAAI,EAAE;QAC1C,EAAE,GAAG,EAAE,gBAAgB,EAAE,OAAO,EAAE,IAAI,EAAE;QACxC,EAAE,GAAG,EAAE,uBAAuB,EAAE,OAAO,EAAE,OAAO,CAAC,iBAAiB,EAAE;KACrE,CAAC;IACF,IAAI,OAAO,CAAC,gBAAgB,EAAE,CAAC;QAC7B,QAAQ,CAAC,IAAI,CAAC;YACZ,GAAG,EAAE,kBAAkB;YACvB,OAAO,EAAE,OAAO,CAAC,gBAAgB,IAAI,KAAK;SAC3C,CAAC,CAAC;IACL,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC"}
package/package.json CHANGED
@@ -1,16 +1,21 @@
1
1
  {
2
2
  "name": "@varshylinc/onboarding-consent-engine",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Consent collection, audit trail, welcome screen, and empty state for Varshyl products",
5
5
  "type": "module",
6
+ "files": [
7
+ "dist"
8
+ ],
6
9
  "exports": {
7
10
  ".": {
8
- "import": "./dist/index.js",
9
- "types": "./dist/index.d.ts"
11
+ "types": "./dist/index.d.ts",
12
+ "require": "./dist/index.js",
13
+ "import": "./dist/index.js"
10
14
  },
11
15
  "./client": {
12
- "import": "./dist/client/index.js",
13
- "types": "./dist/client/index.d.ts"
16
+ "types": "./dist/client/index.d.ts",
17
+ "require": "./dist/client/index.js",
18
+ "import": "./dist/client/index.js"
14
19
  }
15
20
  },
16
21
  "main": "./dist/index.js",
@@ -38,7 +43,7 @@
38
43
  "registry": "https://registry.npmjs.org/"
39
44
  },
40
45
  "scripts": {
41
- "build": "tsc -p tsconfig.json && mkdir -p dist/server/migrations && cp src/server/migrations/*.sql dist/server/migrations/",
46
+ "build": "tsc -p tsconfig.json && tsc -p tsconfig.client.build.json && mkdir -p dist/server/migrations && cp src/server/migrations/*.sql dist/server/migrations/",
42
47
  "typecheck": "tsc -p tsconfig.json --noEmit && tsc -p tsconfig.client.json --noEmit",
43
48
  "lint": "eslint src --ext .ts,.tsx --max-warnings 0",
44
49
  "test": "vitest run",
package/.eslintrc.cjs DELETED
@@ -1,18 +0,0 @@
1
- module.exports = {
2
- root: true,
3
- parser: '@typescript-eslint/parser',
4
- parserOptions: {
5
- project: ['./tsconfig.json', './tsconfig.client.json'],
6
- tsconfigRootDir: __dirname,
7
- },
8
- plugins: ['@typescript-eslint'],
9
- extends: [
10
- 'eslint:recommended',
11
- 'plugin:@typescript-eslint/recommended',
12
- ],
13
- rules: {
14
- '@typescript-eslint/no-explicit-any': 'warn',
15
- '@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
16
- },
17
- env: { node: true, browser: true, es2022: true },
18
- };
package/CHANGELOG.md DELETED
@@ -1,11 +0,0 @@
1
- # @varshylinc/onboarding-consent-engine
2
-
3
- ## 0.1.0
4
-
5
- ### Minor Changes
6
-
7
- - Initial release: consent collection, audit trail, welcome screen, empty state.
8
- - 4 SQL migrations (0001–0004) using `oce_` table prefix.
9
- - Server API: `runMigrations`, `createConsentModule`, `seedStandardConsents`.
10
- - Client components: `ConsentCheckbox`, `ConsentBlock`, `WelcomeScreen`, `EmptyState`, `ConsentUpdateModal`.
11
- - Shared types: `ConsentDefinition`, `UserConsent`, `ConsentStatus`, `AuditEntry`.