@explorer02/cfm-survey-sdk 0.2.4 → 0.2.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.js +45 -44
- package/dist/cli/index.mjs +43 -42
- package/package.json +1 -6
- package/postinstall.js +2 -1
- package/templates/AGENT.md +3 -3
- package/templates/docs/00-integration/agent-execution-flow.md +46 -27
- package/templates/docs/00-integration/agent-operating-contract.md +13 -5
- package/templates/docs/00-integration/apply-ui-config.md +35 -10
- package/templates/docs/00-integration/aws-deploy.md +117 -3
- package/templates/docs/00-integration/component-checklist.md +8 -4
- package/templates/docs/00-integration/constraints.md +3 -2
- package/templates/docs/00-integration/custom-field-logic-and-navigation.md +1 -1
- package/templates/docs/00-integration/mockup-ui-extraction.md +113 -0
- package/templates/docs/00-integration/placeholders-and-custom-fields-wiring.md +192 -0
- package/templates/docs/00-integration/placeholders-and-tokens.md +2 -1
- package/templates/docs/00-integration/ui-customization-wizard.md +83 -104
- package/templates/docs/00-integration/wizard-api.md +74 -82
- package/templates/docs/00-integration/wizard-chrome-contract.md +210 -0
- package/templates/docs/00-integration/wizard-config-handoff.md +57 -9
- package/templates/docs/00-integration/wizard-preview-build-guide.md +30 -11
- package/templates/docs/00-integration/wizard-question-type-styling.md +4 -2
- package/templates/docs/00-integration/wizard-troubleshooting.md +80 -0
- package/templates/docs/01-components/10-header-footer.md +3 -3
- package/templates/docs/01-components/19-survey-sticky-chrome.md +16 -55
- package/templates/docs/MANIFEST.json +34 -13
- package/templates/docs/index.md +9 -11
- package/templates/docs/templates/Footer.tsx +72 -0
- package/templates/docs/templates/Header.tsx +84 -0
- package/templates/docs/templates/LanguageSelector.tsx +40 -0
- package/templates/docs/templates/PreviewBridgeInit.tsx +13 -0
- package/templates/docs/templates/ProgressBar.tsx +33 -0
- package/templates/docs/templates/Question.tsx +50 -7
- package/templates/docs/templates/SurveyStickyChrome.tsx +19 -5
- package/templates/docs/templates/deploy-to-aws.sh +74 -0
- package/templates/docs/templates/implementation_plan.md +19 -12
- package/templates/docs/templates/verify-agent-build.sh +25 -1
- package/templates/preview-harness/preview-bridge.inline.js +1 -1
- package/templates/previewBridge.ts +131 -38
- package/templates/wizard-dist/assets/{PreviewMock-DgHfrVeb.js → PreviewMock-7peNZK-z.js} +1 -1
- package/templates/wizard-dist/assets/{TypePanel-CFVC3Ptn.js → TypePanel-BxHnE3cm.js} +1 -1
- package/templates/wizard-dist/assets/index-DtZhNwPS.js +34 -0
- package/templates/wizard-dist/index.html +1 -1
- package/templates/wizard-dist/assets/index-DYK3X1e5.js +0 -34
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
# Placeholders & Custom Fields — Precise SDK Wiring
|
|
2
|
+
|
|
3
|
+
> **Read in Phase 4–5** after survey fetch. Companion: [`placeholders-and-tokens.md`](placeholders-and-tokens.md), [`custom-field-logic-and-navigation.md`](custom-field-logic-and-navigation.md), [`mockup-ui-extraction.md`](mockup-ui-extraction.md).
|
|
4
|
+
|
|
5
|
+
Agents must pass **exact keys** from the fetched survey and CRM context into `useSurveySDK` — not guesses from mockup text.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Two different maps (do not conflate)
|
|
10
|
+
|
|
11
|
+
| Map | Key format | Purpose | Value source |
|
|
12
|
+
|-----|------------|---------|----------------|
|
|
13
|
+
| **`placeholders`** | `FIRST_NAME`, `COMPANY` (no braces) | Replace `{{FIRST_NAME}}` in question copy at map time | CRM / marketing context or wizard `placeholders.*` |
|
|
14
|
+
| **`customFieldValues`** | `_c_…` ids from logic rules | Skip, display, answer, end, progress evaluation | CRM / transaction API — **not** respondent UI |
|
|
15
|
+
|
|
16
|
+
Mockup images do **not** define either map. Discover keys from **fetched survey JSON**.
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Step 1 — Discover placeholder keys (after fetch)
|
|
21
|
+
|
|
22
|
+
Scan all `questionText`, `questionDescription`, display variant bodies, intro/end copy for tokens:
|
|
23
|
+
|
|
24
|
+
```
|
|
25
|
+
{{FIRST_NAME}}
|
|
26
|
+
{{COMPANY}}
|
|
27
|
+
{{SURVEY_QUESTION-:-<questionId>}}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
**CRM placeholders** — add to `SURVEY_PLACEHOLDERS`:
|
|
31
|
+
|
|
32
|
+
```typescript
|
|
33
|
+
// src/lib/placeholders.ts (or module scope in SurveyPage.tsx)
|
|
34
|
+
export const SURVEY_PLACEHOLDERS = {
|
|
35
|
+
FIRST_NAME: 'Alex', // key = token name without {{ }}
|
|
36
|
+
COMPANY: 'Acme Corp',
|
|
37
|
+
} as const;
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Rules:
|
|
41
|
+
|
|
42
|
+
- Key must match token name **exactly** (case-sensitive per survey).
|
|
43
|
+
- Values are **display strings** for CRM/marketing — not survey answers.
|
|
44
|
+
- Omit keys not present in fetched text (do not copy example lists from docs blindly).
|
|
45
|
+
- **Answer tokens** `{{SURVEY_QUESTION-:-id}}` are **not** in `placeholders` — resolved at render via `resolveSurveyQuestionPlaceholders`.
|
|
46
|
+
|
|
47
|
+
Record discovered keys in `implementation_plan.md`:
|
|
48
|
+
|
|
49
|
+
```markdown
|
|
50
|
+
## Placeholder inventory (from fetch)
|
|
51
|
+
| Token | Key in SURVEY_PLACEHOLDERS | Example value | Found in question ids |
|
|
52
|
+
| {{FIRST_NAME}} | FIRST_NAME | … | q1, q3 |
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## Step 2 — Wire placeholders (stable ref + hook)
|
|
58
|
+
|
|
59
|
+
```typescript
|
|
60
|
+
import { useMemo } from 'react';
|
|
61
|
+
import { useSurveySDK } from '@explorer02/cfm-survey-sdk';
|
|
62
|
+
import { SURVEY_PLACEHOLDERS } from '@/lib/placeholders';
|
|
63
|
+
import { CUSTOM_FIELD_VALUES } from '@/lib/customFieldValues';
|
|
64
|
+
|
|
65
|
+
const surveyOptions = useMemo(
|
|
66
|
+
() => ({
|
|
67
|
+
instanceId: SURVEY_INSTANCE_ID,
|
|
68
|
+
language: selectedLanguage,
|
|
69
|
+
placeholders: SURVEY_PLACEHOLDERS,
|
|
70
|
+
customFieldValues: CUSTOM_FIELD_VALUES,
|
|
71
|
+
}),
|
|
72
|
+
[selectedLanguage],
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
const { state, onAction, surveyQueryResults } = useSurveySDK({ options: surveyOptions });
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
**Failure modes:**
|
|
79
|
+
|
|
80
|
+
| Mistake | Symptom |
|
|
81
|
+
|---------|---------|
|
|
82
|
+
| Inline `placeholders={{ ... }}` in component | Infinite re-fetch |
|
|
83
|
+
| Key missing from map | Literal `{{FIRST_NAME}}` in UI |
|
|
84
|
+
| Mockup name instead of token key | Wrong or missing substitution |
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## Step 3 — Discover custom field ids (after fetch)
|
|
89
|
+
|
|
90
|
+
Scan `survey.pages[].skipLogics`, `displayLogic`, `answerLogic`, and `endPages` for:
|
|
91
|
+
|
|
92
|
+
```json
|
|
93
|
+
"conditionEntity": { "entityType": "CUSTOM_FIELD", "id": "_c_67199096d294be011a2b4773", "fieldType": "TEXT" }
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Collect **every** `_c_…` id. Fill `implementation_plan.md` §3d.
|
|
97
|
+
|
|
98
|
+
Copy template → `src/lib/customFieldValues.ts`:
|
|
99
|
+
|
|
100
|
+
```typescript
|
|
101
|
+
import type { CustomFieldValueMap } from '@explorer02/cfm-survey-sdk';
|
|
102
|
+
|
|
103
|
+
export const CUSTOM_FIELD_VALUES: CustomFieldValueMap = {
|
|
104
|
+
'_c_67199096d294be011a2b4773': 'abc', // TEXT — exact id from fetch
|
|
105
|
+
// '_c_…': 2, // NUMBER
|
|
106
|
+
// '_c_…': 'picklist-option-uuid', // PICKLIST
|
|
107
|
+
};
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### Value shape by `fieldType` (must match SDK evaluator)
|
|
111
|
+
|
|
112
|
+
| fieldType | Pass |
|
|
113
|
+
|-----------|------|
|
|
114
|
+
| `TEXT`, `TEXT_MULTI`, `TEXTAREA` | `string` |
|
|
115
|
+
| `NUMBER` | `number` or numeric `string` |
|
|
116
|
+
| `PICKLIST` | option **id** string |
|
|
117
|
+
| `PICKLIST_MULTISELECT` | `string[]` of option ids |
|
|
118
|
+
| `DATETIME` | epoch ms (`number` or numeric string) |
|
|
119
|
+
|
|
120
|
+
Missing keys → treated as empty for logic. Wrong shape → rule may never match.
|
|
121
|
+
|
|
122
|
+
**Values come from CRM/transaction** — ask client or integration spec when not in prompt. Do **not** invent ids or values from mockup.
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
## Step 4 — Wire custom fields (two places — same map)
|
|
127
|
+
|
|
128
|
+
### A. Hook
|
|
129
|
+
|
|
130
|
+
```typescript
|
|
131
|
+
customFieldValues: CUSTOM_FIELD_VALUES, // inside useMemo surveyOptions
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### B. Question + visibility helpers
|
|
135
|
+
|
|
136
|
+
```tsx
|
|
137
|
+
<Question
|
|
138
|
+
customFieldValues={CUSTOM_FIELD_VALUES}
|
|
139
|
+
allAnswers={state.answers}
|
|
140
|
+
allQuestions={allQuestions}
|
|
141
|
+
...
|
|
142
|
+
/>
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Inside `Question.tsx` (from template):
|
|
146
|
+
|
|
147
|
+
```typescript
|
|
148
|
+
getVisibleMcqOptionsForAnswers(question, allAnswers, allQuestions, customFieldValues);
|
|
149
|
+
getVisibleMatrixItemsForAnswers(question, allAnswers, allQuestions, customFieldValues);
|
|
150
|
+
getVisibleRankOrderOptionsForAnswers(question, allAnswers, allQuestions, customFieldValues);
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
**Fourth argument must be the same map** as hook options whenever logic references `CUSTOM_FIELD`.
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
## Step 5 — Wizard overrides (Phase 6c)
|
|
158
|
+
|
|
159
|
+
When client uses wizard, `survey-ui-config.json` may include:
|
|
160
|
+
|
|
161
|
+
| Config path | Code update |
|
|
162
|
+
|-------------|-------------|
|
|
163
|
+
| `placeholders.firstName` etc. | Merge into `SURVEY_PLACEHOLDERS` (wizard keys → SDK token keys per [`apply-ui-config.md`](apply-ui-config.md)) |
|
|
164
|
+
| `customFields._c_…` | Merge into `CUSTOM_FIELD_VALUES` |
|
|
165
|
+
|
|
166
|
+
Wizard **Testing & Tokens** step edits config only — you still wire stable refs in code after `confirm-ui-config`.
|
|
167
|
+
|
|
168
|
+
---
|
|
169
|
+
|
|
170
|
+
## Verification checklist
|
|
171
|
+
|
|
172
|
+
- [ ] Placeholder keys discovered by **scanning fetched survey text**, not mockup
|
|
173
|
+
- [ ] `SURVEY_PLACEHOLDERS` at module scope; keys match `{{TOKEN}}` names
|
|
174
|
+
- [ ] Every `_c_…` id in logic appears in `CUSTOM_FIELD_VALUES`
|
|
175
|
+
- [ ] Value shapes match `fieldType` from fetch
|
|
176
|
+
- [ ] `useMemo` wraps hook `options`
|
|
177
|
+
- [ ] `customFieldValues` passed to hook **and** `Question`
|
|
178
|
+
- [ ] `getVisible*ForAnswers` receives 4th arg when CRM logic exists
|
|
179
|
+
- [ ] `resolveSurveyQuestionPlaceholders` used for answer tokens in question shell
|
|
180
|
+
- [ ] No placeholder or custom-field keys invented from mockup image
|
|
181
|
+
|
|
182
|
+
---
|
|
183
|
+
|
|
184
|
+
## Related
|
|
185
|
+
|
|
186
|
+
| Doc | Role |
|
|
187
|
+
|-----|------|
|
|
188
|
+
| [`mockup-ui-extraction.md`](mockup-ui-extraction.md) | UI-only vs fetch |
|
|
189
|
+
| [`placeholders-and-tokens.md`](placeholders-and-tokens.md) | Token resolution stages |
|
|
190
|
+
| [`custom-field-logic-and-navigation.md`](custom-field-logic-and-navigation.md) | Logic evaluation contract |
|
|
191
|
+
| [`client-lib-folder.md`](client-lib-folder.md) | File layout |
|
|
192
|
+
| [`templates/customFieldValues.ts`](../templates/customFieldValues.ts) | Copy template |
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# Placeholders and Tokens
|
|
2
2
|
|
|
3
|
-
> Covers `sdkFeatures.placeholderResolution` — how CRM and dynamic answer tokens resolve in question text.
|
|
3
|
+
> Covers `sdkFeatures.placeholderResolution` — how CRM and dynamic answer tokens resolve in question text.
|
|
4
|
+
> **Agent wiring (discover keys from fetch):** [`placeholders-and-custom-fields-wiring.md`](placeholders-and-custom-fields-wiring.md)
|
|
4
5
|
|
|
5
6
|
---
|
|
6
7
|
|
|
@@ -1,144 +1,123 @@
|
|
|
1
1
|
# UI Customization Wizard
|
|
2
2
|
|
|
3
|
-
> Optional **run** after Phase 6 verify. **Wizard-ready build** is mandatory in Phase 5 — see [`agent-execution-flow.md`](agent-execution-flow.md).
|
|
4
|
-
> **Wait + apply protocol:** [`wizard-config-handoff.md`](wizard-config-handoff.md).
|
|
3
|
+
> Optional **run** after Phase 6 verify. **Wizard-ready build** is mandatory in Phase 5 — see [`agent-execution-flow.md`](agent-execution-flow.md).
|
|
5
4
|
|
|
6
|
-
|
|
5
|
+
## Default: local wizard (`customize`)
|
|
7
6
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
After **Phase 6** (verify + `npm run dev`), ask the client:
|
|
11
|
-
|
|
12
|
-
> *"Your survey is running locally. Would you like to customize the UI through the web wizard?"*
|
|
13
|
-
|
|
14
|
-
- **Yes** → Phase 6b: run `npx cfm-sdk customize-ui` (AWS) or `customize` (local)
|
|
15
|
-
- **No** → proceed to Phase 7 deploy
|
|
16
|
-
|
|
17
|
-
## AWS flow (production) — agent waits for client
|
|
7
|
+
When the client says **yes** to customization in agent chat, **always run:**
|
|
18
8
|
|
|
19
9
|
```bash
|
|
20
|
-
|
|
21
|
-
npx cfm-sdk customize-ui
|
|
10
|
+
npx cfm-sdk customize
|
|
22
11
|
```
|
|
23
12
|
|
|
24
|
-
|
|
13
|
+
This is the **recommended default** because it:
|
|
25
14
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
6. Writes review artifacts — **does not auto-apply to codebase**
|
|
15
|
+
- Serves wizard + component previews from **one local server** (`localhost:4200`)
|
|
16
|
+
- Auto-exports all **11** question-type previews from agent components
|
|
17
|
+
- Writes `survey-ui-config.json` **directly** on save — no S3, no session polling
|
|
18
|
+
- Cleans up local `out/previews/` when client quits without saving (`POST /api/wizard-quit`) or when CLI exits (Ctrl+C)
|
|
19
|
+
- Updates live previews via the same iframe + preview bridge as production
|
|
32
20
|
|
|
33
|
-
|
|
21
|
+
**Agent script after client says yes:**
|
|
34
22
|
|
|
35
|
-
|
|
23
|
+
> *"I'll open the customization wizard in your browser. Complete all steps and click **Review & Build** when done — I'll apply your changes automatically."*
|
|
24
|
+
|
|
25
|
+
The CLI **blocks** until the client saves. Wait for:
|
|
36
26
|
|
|
37
27
|
```
|
|
38
|
-
✅
|
|
39
|
-
🔗 Client wizard link — share with the client:
|
|
40
|
-
http://43.204.26.213:3000/wizard-app/index.html?session=<uuid>&secret=<hex>
|
|
28
|
+
✅ UI configuration saved to survey-ui-config.json
|
|
41
29
|
```
|
|
42
30
|
|
|
43
|
-
|
|
44
|
-
|-----|------|
|
|
45
|
-
| **Client** | Opens the **deployed EC2 wizard link** only — customizes branding, colors, question-type tokens; previews update live from S3-backed component pages |
|
|
46
|
-
| **Agent** | Keeps `customize-ui` running (polls API); does **not** ask client to use localhost |
|
|
31
|
+
Then apply per [`apply-ui-config.md`](apply-ui-config.md).
|
|
47
32
|
|
|
48
|
-
|
|
33
|
+
### Who can use it
|
|
49
34
|
|
|
50
|
-
|
|
35
|
+
| User | Can use `customize`? |
|
|
36
|
+
|------|---------------------|
|
|
37
|
+
| Client on **same machine** as agent (Cursor chat on dev laptop) | **Yes — default** |
|
|
38
|
+
| Client on **another device** | **No** — use EC2 fallback below |
|
|
51
39
|
|
|
52
|
-
|
|
40
|
+
`localhost:4200` is only reachable on the machine running the CLI.
|
|
53
41
|
|
|
54
|
-
|
|
42
|
+
---
|
|
55
43
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
44
|
+
## EC2 fallback (`customize-ui`) — remote clients only
|
|
45
|
+
|
|
46
|
+
Use **only** when the client must customize from another PC/tablet/network:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
export CFM_INSTANCE_ID="..." CFM_DEPLOY_API_BASE="http://43.204.26.213:3000"
|
|
50
|
+
npx cfm-sdk customize-ui
|
|
62
51
|
```
|
|
63
52
|
|
|
64
|
-
|
|
65
|
-
-
|
|
66
|
-
-
|
|
67
|
-
-
|
|
68
|
-
- [ ] Read `survey-ui-config.diff.md` before Phase 6c
|
|
69
|
-
- [ ] Apply codebase per [`apply-ui-config.md`](apply-ui-config.md) from **`.final.json`**
|
|
70
|
-
- [ ] Run `npx cfm-sdk confirm-ui-config` after codebase apply
|
|
53
|
+
- Uploads previews to EC2 disk (local-server model on remote host)
|
|
54
|
+
- Prints EC2 wizard link — agent sends link to client
|
|
55
|
+
- CLI **polls** until client submits → writes `.final.json` + `.diff.md`
|
|
56
|
+
- Requires deploy-api on EC2 + `CFM_INSTANCE_ID`
|
|
71
57
|
|
|
72
|
-
See [`wizard-config-handoff.md`](wizard-config-handoff.md)
|
|
58
|
+
See [`wizard-api.md`](wizard-api.md) and [`wizard-config-handoff.md`](wizard-config-handoff.md).
|
|
73
59
|
|
|
74
|
-
|
|
60
|
+
**Do not** use `customize-ui` when client and agent share the same machine — `customize` is simpler and more reliable.
|
|
75
61
|
|
|
76
|
-
|
|
77
|
-
npx cfm-sdk customize-ui --apply
|
|
78
|
-
```
|
|
62
|
+
---
|
|
79
63
|
|
|
80
|
-
|
|
64
|
+
## When to ask (INPUT 3)
|
|
81
65
|
|
|
82
|
-
|
|
66
|
+
After Phase 6 verify + dev server:
|
|
83
67
|
|
|
84
|
-
|
|
85
|
-
npx cfm-sdk customize-ui --no-wait
|
|
86
|
-
# Later, when client done:
|
|
87
|
-
export CFM_WIZARD_SESSION_ID="..."
|
|
88
|
-
npx cfm-sdk fetch-ui-config
|
|
89
|
-
```
|
|
68
|
+
> *"Your survey is running locally. Would you like to customize the UI through the web wizard?"*
|
|
90
69
|
|
|
91
|
-
|
|
70
|
+
- **Yes** → `npx cfm-sdk customize` (default)
|
|
71
|
+
- **Yes, but I'm on a different device** → `npx cfm-sdk customize-ui`
|
|
72
|
+
- **No** → Phase 7 deploy ask
|
|
92
73
|
|
|
93
|
-
|
|
94
|
-
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## How local wizard works
|
|
77
|
+
|
|
78
|
+
```mermaid
|
|
79
|
+
sequenceDiagram
|
|
80
|
+
participant Agent as Agent CLI
|
|
81
|
+
participant Srv as localhost:4200
|
|
82
|
+
participant Wizard as Wizard SPA
|
|
83
|
+
participant Prev as out/previews/
|
|
84
|
+
|
|
85
|
+
Agent->>Agent: export-previews (all 11 types)
|
|
86
|
+
Agent->>Srv: customize serves wizard + previews
|
|
87
|
+
Wizard->>Srv: GET /api/inventory
|
|
88
|
+
Wizard->>Prev: iframe /previews/MCQ_single/...
|
|
89
|
+
Wizard->>Srv: POST /api/save-config
|
|
90
|
+
Srv->>Agent: survey-ui-config.json written, CLI exits
|
|
95
91
|
```
|
|
96
92
|
|
|
97
|
-
|
|
93
|
+
| Route | Purpose |
|
|
94
|
+
|-------|---------|
|
|
95
|
+
| `/api/inventory` | Preview manifest + seed config |
|
|
96
|
+
| `/previews/{key}/index.html` | Component-wise live preview |
|
|
97
|
+
| `/api/save-config` | Client submit → JSON on disk |
|
|
98
|
+
| `/api/upload-logo` | Logo → `public/` |
|
|
99
|
+
|
|
100
|
+
---
|
|
98
101
|
|
|
99
102
|
## Seed config
|
|
100
103
|
|
|
101
104
|
| Priority | Source |
|
|
102
105
|
|----------|--------|
|
|
103
106
|
| 1 | `./survey-ui-config.json` (draft) |
|
|
104
|
-
| 2 | `src/styles/survey-theme.css`
|
|
105
|
-
| 3 | `implementation_plan.md`
|
|
106
|
-
| 4 | `Header.tsx`
|
|
107
|
+
| 2 | `src/styles/survey-theme.css` |
|
|
108
|
+
| 3 | `implementation_plan.md` |
|
|
109
|
+
| 4 | `Header.tsx` logo contract |
|
|
107
110
|
| 5 | SDK defaults |
|
|
108
111
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
##
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
| Testing & Tokens | Placeholders, custom fields, debug |
|
|
122
|
-
| Deploy | AWS or Vercel target |
|
|
123
|
-
| Review & Build | **Client submits** — triggers CLI poll success |
|
|
124
|
-
|
|
125
|
-
## Output artifacts
|
|
126
|
-
|
|
127
|
-
| File | When |
|
|
128
|
-
|------|------|
|
|
129
|
-
| `survey-ui-config.final.json` | AWS — client's submitted config (apply source) |
|
|
130
|
-
| `survey-ui-config.diff.md` | AWS — every changed path (audit before apply) |
|
|
131
|
-
| `survey-ui-config.json` | Active config (seed until `confirm-ui-config`; or final for local/`--apply`) |
|
|
132
|
-
|
|
133
|
-
Apply tokens per [`apply-ui-config.md`](apply-ui-config.md).
|
|
134
|
-
|
|
135
|
-
## Agent Checklist
|
|
136
|
-
|
|
137
|
-
- [ ] Phase 5: components wired per [`wizard-preview-build-guide.md`](wizard-preview-build-guide.md)
|
|
138
|
-
- [ ] Client opted in after localhost preview (INPUT 3)
|
|
139
|
-
- [ ] Ran `customize-ui` or `customize` and **waited** for CLI exit 0
|
|
140
|
-
- [ ] Read `survey-ui-config.diff.md` (AWS review mode)
|
|
141
|
-
- [ ] Phase 6c: applied **all** diff paths per [`apply-ui-config.md`](apply-ui-config.md)
|
|
142
|
-
- [ ] AWS: ran `confirm-ui-config` after codebase apply
|
|
143
|
-
- [ ] Re-ran verify script + build
|
|
144
|
-
- [ ] Did not modify SDK integration (`onAction`, dispatch logic)
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
## Agent checklist
|
|
115
|
+
|
|
116
|
+
- [ ] Phase 5: wizard-preview artifacts wired
|
|
117
|
+
- [ ] Client opted in (INPUT 3)
|
|
118
|
+
- [ ] Ran **`npx cfm-sdk customize`** (default) and waited for CLI exit 0
|
|
119
|
+
- [ ] Read `survey-ui-config.json` (or `.diff.md` if used EC2 fallback)
|
|
120
|
+
- [ ] Phase 6c: applied per [`apply-ui-config.md`](apply-ui-config.md)
|
|
121
|
+
- [ ] Re-ran verify + build
|
|
122
|
+
|
|
123
|
+
See [`wizard-troubleshooting.md`](wizard-troubleshooting.md) if previews show mock UI.
|
|
@@ -1,134 +1,126 @@
|
|
|
1
|
-
# Wizard API (
|
|
1
|
+
# Wizard API — EC2 fallback (`customize-ui` only)
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> **Default wizard is `npx cfm-sdk customize` on localhost** — no EC2 API needed.
|
|
4
|
+
> This doc applies **only** when the client customizes from another device.
|
|
4
5
|
|
|
5
|
-
Base URL: `CFM_DEPLOY_API_BASE` —
|
|
6
|
+
Base URL: `CFM_DEPLOY_API_BASE` — default: `http://43.204.26.213:3000`
|
|
6
7
|
|
|
7
|
-
##
|
|
8
|
+
## Architecture
|
|
8
9
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
```mermaid
|
|
11
|
+
flowchart LR
|
|
12
|
+
CLI[customize-ui CLI] -->|PUT preview files| Disk[EC2 disk data/wizard-sessions/]
|
|
13
|
+
Client[Client browser] --> SPA[wizard-app SPA]
|
|
14
|
+
SPA -->|GET /api/inventory| API[deploy-api]
|
|
15
|
+
SPA -->|iframe /previews/...| Disk
|
|
16
|
+
SPA -->|POST /api/save-config| API
|
|
17
|
+
API -->|final config + logo| S3[S3 hosting bucket]
|
|
18
|
+
CLI -->|poll GET /wizard/config| API
|
|
13
19
|
```
|
|
14
20
|
|
|
15
|
-
|
|
21
|
+
| During session | Storage |
|
|
22
|
+
|----------------|---------|
|
|
23
|
+
| Preview HTML | EC2 disk (`WIZARD_DATA_DIR/{sessionId}/previews/`) |
|
|
24
|
+
| Seed config | EC2 disk (`seed-config.json`) |
|
|
25
|
+
| Temp logo | EC2 disk (`assets/`) |
|
|
26
|
+
| **On submit** | Final JSON + permanent logo → S3 |
|
|
27
|
+
|
|
28
|
+
Previews are **not** loaded from S3 during customization — avoids "Storage service unavailable" on preview iframes.
|
|
29
|
+
|
|
30
|
+
## Client wizard link
|
|
16
31
|
|
|
17
32
|
```
|
|
18
|
-
|
|
33
|
+
{CFM_DEPLOY_API_BASE}/wizard-app/index.html?session={sessionId}&secret={sessionSecret}
|
|
19
34
|
```
|
|
20
35
|
|
|
21
|
-
|
|
|
36
|
+
| Route | Role |
|
|
22
37
|
|-------|------|
|
|
23
|
-
| `/wizard-app/` | Wizard SPA
|
|
24
|
-
| `
|
|
25
|
-
|
|
|
26
|
-
|
|
27
|
-
**Agent:** copy link from CLI → send to client. **Client:** opens link only (no localhost). **Agent:** keeps CLI polling until submit.
|
|
28
|
-
|
|
29
|
-
`wizardUrl` in `POST /wizard/session/start` response is this full URL (built by `getWizardPublicUrl` in deploy-api).
|
|
30
|
-
|
|
31
|
-
## Auth
|
|
32
|
-
|
|
33
|
-
| Caller | Header |
|
|
34
|
-
|--------|--------|
|
|
35
|
-
| CLI | `Authorization: Bearer {CFM_INSTANCE_ID}` |
|
|
36
|
-
| Wizard SPA | `X-Wizard-Session: {secret}` + `X-Wizard-Session-Id: {sessionId}` |
|
|
37
|
-
|
|
38
|
-
## Endpoints
|
|
38
|
+
| `/wizard-app/` | Wizard SPA |
|
|
39
|
+
| `/api/inventory` | Session metadata + `previewManifest` (local-server API) |
|
|
40
|
+
| `/previews/{sessionId}/{key}/index.html` | Component preview iframes |
|
|
41
|
+
| `/api/save-config` | Client submit (same as local `customize`) |
|
|
39
42
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
Starts session; returns presigned PUT URLs for preview HTML files.
|
|
43
|
-
|
|
44
|
-
**Body:** `{ "files": [...], "surveyTypes": ["MCQ", "NPS_SCALE"], "initialConfig": { ... } }`
|
|
43
|
+
## Local-server routes (`/api/*`, `/previews/*`)
|
|
45
44
|
|
|
46
|
-
|
|
45
|
+
Same contract as `packages/sdk/src/cli/customize.ts`:
|
|
47
46
|
|
|
48
|
-
|
|
47
|
+
### `GET /api/inventory?session=&secret=`
|
|
49
48
|
|
|
50
|
-
|
|
49
|
+
Returns `{ surveyTypes, instanceId, previewUrl, previewManifest, initialConfig, localServer: true }`.
|
|
51
50
|
|
|
52
|
-
|
|
51
|
+
### `GET /api/preview-url`
|
|
53
52
|
|
|
54
|
-
|
|
53
|
+
Health check for preview availability indicator.
|
|
55
54
|
|
|
56
|
-
### `
|
|
55
|
+
### `POST /api/upload-logo?session=&secret=`
|
|
57
56
|
|
|
58
|
-
|
|
57
|
+
Body: `{ filename, base64 }` — stores logo on EC2 disk for session.
|
|
59
58
|
|
|
60
|
-
### `
|
|
59
|
+
### `POST /api/save-config?session=&secret=`
|
|
61
60
|
|
|
62
|
-
|
|
61
|
+
Body: full `survey-ui-config.json`. Persists final config + logo to S3, cleans session disk.
|
|
63
62
|
|
|
64
|
-
|
|
63
|
+
## Session management (`/wizard/*`)
|
|
65
64
|
|
|
66
|
-
|
|
65
|
+
### `POST /wizard/session/start`
|
|
67
66
|
|
|
68
|
-
|
|
67
|
+
**Auth:** `Authorization: Bearer {JWT}`
|
|
69
68
|
|
|
70
|
-
**Body:** `{
|
|
69
|
+
**Body:** `{ files, surveyTypes, initialConfig }`
|
|
71
70
|
|
|
72
|
-
|
|
71
|
+
**Response:** `{ sessionId, sessionSecret, wizardUrl, uploads[], localServer: true }`
|
|
73
72
|
|
|
74
|
-
|
|
73
|
+
`uploads[].uploadUrl` → `PUT /wizard/session/:sessionId/preview-file?path=previews/...` (EC2 disk, not S3 presign).
|
|
75
74
|
|
|
76
|
-
|
|
75
|
+
### `PUT /wizard/session/:sessionId/preview-file?path=...`
|
|
77
76
|
|
|
78
|
-
|
|
77
|
+
**Auth:** `X-Wizard-Session` + `X-Wizard-Session-Id`
|
|
79
78
|
|
|
80
|
-
|
|
81
|
-
2. Saves final config to `sites/{surveyId}/wizard/config.json` (with `logoKey` + `logoUrl` metadata)
|
|
82
|
-
3. **Deletes** entire wizard session folder `sites/{surveyId}/wizard-sessions/{sessionId}/` (previews, seed-config, temp logo)
|
|
83
|
-
4. Returns public logo URL: `{ logoUrl, logoKey, logoFileName }`
|
|
79
|
+
Raw file body → written to session disk.
|
|
84
80
|
|
|
85
|
-
|
|
81
|
+
### `POST /wizard/previews/upload/complete`
|
|
86
82
|
|
|
87
|
-
|
|
83
|
+
**Auth:** JWT. Verifies all files on disk; activates session; builds manifest with `/previews/{sessionId}/…` URLs.
|
|
88
84
|
|
|
89
|
-
|
|
85
|
+
### `POST /wizard/session/quit`
|
|
90
86
|
|
|
91
|
-
|
|
92
|
-
**Ready:** `{ "status": "ready", "config": { ... }, "logoUrl": "...", "logoKey": "...", "sessionId": "..." }`
|
|
87
|
+
Deletes session disk folder + in-memory session. CLI poll returns `status: abandoned`.
|
|
93
88
|
|
|
94
|
-
`config
|
|
89
|
+
### `GET /wizard/config/:surveyId?sessionId=`
|
|
95
90
|
|
|
96
|
-
|
|
91
|
+
CLI poll after client submit.
|
|
97
92
|
|
|
98
|
-
|
|
93
|
+
- **pending** — waiting
|
|
94
|
+
- **abandoned** — client quit
|
|
95
|
+
- **ready** — `{ config, logoUrl, … }`
|
|
99
96
|
|
|
100
97
|
## Env (deploy-api)
|
|
101
98
|
|
|
102
99
|
```bash
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
100
|
+
WIZARD_DATA_DIR=./data/wizard-sessions # preview + seed + temp logo on disk
|
|
101
|
+
WIZARD_SESSION_TTL_MS=7200000
|
|
102
|
+
HOSTING_BUCKET=... # final config + permanent logo only
|
|
103
|
+
CLOUDFRONT_BASE_URL=...
|
|
106
104
|
```
|
|
107
105
|
|
|
108
|
-
##
|
|
106
|
+
## IAM (EC2 instance role)
|
|
109
107
|
|
|
110
|
-
|
|
108
|
+
Required for **submit** (not previews):
|
|
111
109
|
|
|
112
|
-
|
|
110
|
+
- `s3:PutObject`, `s3:GetObject` on hosting bucket
|
|
111
|
+
- `cloudfront:CreateInvalidation` (logo cache bust)
|
|
113
112
|
|
|
114
|
-
|
|
115
|
-
2. **Origin access** → OAC/OAI allows CloudFront to read the bucket (bucket policy blocks public access)
|
|
116
|
-
3. **Behavior** → default or `sites/*` path serves objects from the bucket
|
|
117
|
-
|
|
118
|
-
No extra bucket policy for public read is required. The public URL is:
|
|
119
|
-
|
|
120
|
-
`https://{CLOUDFRONT_DOMAIN}/sites/{surveyId}/assets/{logoFileName}`
|
|
121
|
-
|
|
122
|
-
**IAM (EC2 instance role)** must allow: `s3:PutObject`, `s3:GetObject`, `s3:DeleteObject`, `s3:ListBucket` on the hosting bucket, plus `cloudfront:CreateInvalidation` on the distribution.
|
|
123
|
-
|
|
124
|
-
## CLI flow (review mode — default)
|
|
113
|
+
## CLI flow
|
|
125
114
|
|
|
126
115
|
```bash
|
|
127
116
|
export CFM_INSTANCE_ID="..." CFM_DEPLOY_API_BASE="http://43.204.26.213:3000"
|
|
128
117
|
npx cfm-sdk customize-ui
|
|
129
|
-
# export-previews → upload component previews to S3 → print client wizard link →
|
|
130
|
-
# POLL until client submits → survey-ui-config.final.json + .diff.md
|
|
131
|
-
# Agent applies codebase → npx cfm-sdk confirm-ui-config
|
|
132
118
|
```
|
|
133
119
|
|
|
134
|
-
|
|
120
|
+
1. `export-previews` on agent machine
|
|
121
|
+
2. Upload preview files to EC2 disk
|
|
122
|
+
3. Print client wizard link
|
|
123
|
+
4. Poll until `status: ready`
|
|
124
|
+
5. Write `.final.json` + `.diff.md`
|
|
125
|
+
|
|
126
|
+
See [`wizard-config-handoff.md`](wizard-config-handoff.md), [`ui-customization-wizard.md`](ui-customization-wizard.md).
|