@ductape/mcp 0.3.5 → 0.3.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.
@@ -4,6 +4,7 @@ interface AnalyticsDecision {
4
4
  rationale?: string;
5
5
  autoCapture?: 'disabled' | 'reviewed';
6
6
  privacyReviewed?: boolean;
7
+ settingsContractsReviewed?: boolean;
7
8
  }
8
9
  export interface FrontendAnalyticsValidationResult {
9
10
  valid: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"frontend-analytics-validator.d.ts","sourceRoot":"","sources":["../src/frontend-analytics-validator.ts"],"names":[],"mappings":"AASA,MAAM,MAAM,uBAAuB,GAAG,SAAS,GAAG,UAAU,GAAG,YAAY,CAAC;AAE5E,UAAU,iBAAiB;IACzB,MAAM,CAAC,EAAE,uBAAuB,CAAC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,UAAU,GAAG,UAAU,CAAC;IACtC,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAMD,MAAM,WAAW,iCAAiC;IAChD,KAAK,EAAE,OAAO,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IACpE,YAAY,EAAE,KAAK,CAAC;QAClB,IAAI,EAAE,MAAM,CAAC;QACb,SAAS,EAAE,OAAO,GAAG,KAAK,GAAG,QAAQ,CAAC;QACtC,QAAQ,CAAC,EAAE,iBAAiB,CAAC;QAC7B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACjC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;QACnC,MAAM,EAAE,MAAM,EAAE,CAAC;QACjB,QAAQ,EAAE,MAAM,EAAE,CAAC;KACpB,CAAC,CAAC;IACH,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AA0DD,wBAAgB,gCAAgC,CAC9C,UAAU,EAAE,MAAM,GACjB,iCAAiC,CA2HnC"}
1
+ {"version":3,"file":"frontend-analytics-validator.d.ts","sourceRoot":"","sources":["../src/frontend-analytics-validator.ts"],"names":[],"mappings":"AASA,MAAM,MAAM,uBAAuB,GAAG,SAAS,GAAG,UAAU,GAAG,YAAY,CAAC;AAE5E,UAAU,iBAAiB;IACzB,MAAM,CAAC,EAAE,uBAAuB,CAAC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,UAAU,GAAG,UAAU,CAAC;IACtC,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,yBAAyB,CAAC,EAAE,OAAO,CAAC;CACrC;AAMD,MAAM,WAAW,iCAAiC;IAChD,KAAK,EAAE,OAAO,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IACpE,YAAY,EAAE,KAAK,CAAC;QAClB,IAAI,EAAE,MAAM,CAAC;QACb,SAAS,EAAE,OAAO,GAAG,KAAK,GAAG,QAAQ,CAAC;QACtC,QAAQ,CAAC,EAAE,iBAAiB,CAAC;QAC7B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACjC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;QACnC,MAAM,EAAE,MAAM,EAAE,CAAC;QACjB,QAAQ,EAAE,MAAM,EAAE,CAAC;KACpB,CAAC,CAAC;IACH,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AA0DD,wBAAgB,gCAAgC,CAC9C,UAAU,EAAE,MAAM,GACjB,iCAAiC,CAyInC"}
@@ -140,6 +140,12 @@ export function validateFrontendAnalyticsProject(projectDir) {
140
140
  clearSession: /(?:analytics\.)?clearSession\s*\(/, pageview: /(?:analytics\.)?pageview\s*\(/,
141
141
  namedEvents: /(?:analytics\.)?track\s*\(/, autoCapture: /enableAutoCapture\s*\(/,
142
142
  clientFailure: /client[_\-. ]error|frontend[_\-. ]error|error_boundary|unhandledrejection/i,
143
+ settingsSurface: /settings|preferences|notificationpreferences/i,
144
+ settingsLiveRead: /\b(?:get|load|fetch|request)\s*[:=(]|method\s*:\s*['"]GET['"]/i,
145
+ settingsLiveWrite: /\b(?:update|save|mutate|request)\s*[:=(]|method\s*:\s*['"](?:POST|PUT|PATCH)['"]/i,
146
+ settingsLoading: /\b(?:loading|isLoading|pending|isPending)\b/i,
147
+ settingsFailure: /\b(?:error|failure|failed)\b/i,
148
+ settingsRetry: /\b(?:retry|refetch|reload|tryAgain)\b/i,
143
149
  };
144
150
  const evidence = Object.fromEntries(Object.entries(patterns).map(([name, pattern]) => [name, files.filter((item) => pattern.test(item.source)).map((item) => item.file)]));
145
151
  const signals = Object.fromEntries(Object.entries(evidence).map(([name, matches]) => [name, matches.length > 0]));
@@ -177,6 +183,20 @@ export function validateFrontendAnalyticsProject(projectDir) {
177
183
  if (!signals.clientFailure) {
178
184
  warnings.push('No sanitized client-failure analytics signal was detected; review error boundaries and unhandled failures.');
179
185
  }
186
+ if (signals.settingsSurface) {
187
+ if (!signals.settingsLiveRead)
188
+ errors.push('A settings surface was found without a statically discoverable canonical read path.');
189
+ if (!signals.settingsLiveWrite)
190
+ errors.push('A settings surface was found without a statically discoverable persisted mutation path.');
191
+ if (!signals.settingsLoading)
192
+ errors.push('A settings surface was found without a loading/pending state.');
193
+ if (!signals.settingsFailure)
194
+ errors.push('A settings surface was found without a failure state.');
195
+ if (!signals.settingsRetry)
196
+ errors.push('A settings surface was found without a retry/refetch path.');
197
+ if (!decision.settingsContractsReviewed)
198
+ errors.push('Settings payload keys must be reviewed against the current registered Feature input schema; record settingsContractsReviewed: true after that review.');
199
+ }
180
200
  }
181
201
  return [{ path: applicationPath, framework, decision, signals, evidence, errors, warnings }];
182
202
  });
package/dist/index.js CHANGED
@@ -2391,6 +2391,23 @@ PRODUCT ANALYTICS
2391
2391
  failures, privacy masking, hidden-state safety, and trace correlation. Keep auto-capture off until
2392
2392
  consent, selectors, masking, and sensitive states have been reviewed.
2393
2393
 
2394
+ LIVE SETTINGS AND FEATURE CONTRACTS
2395
+ A settings screen is incomplete if it renders static/mock values, mutates only local state, or
2396
+ sends independently invented payload keys. Before declaring any persisted preference/settings
2397
+ requirement complete:
2398
+ 1. Identify the owning registered Feature and inspect its exact current input schema. Do not
2399
+ infer the schema from UI labels, old examples, TypeScript names, or domain expectations.
2400
+ 2. Generate or consume the frontend input type from that Feature contract. Literal payload keys
2401
+ must be a subset of declared properties and every required property must be supplied.
2402
+ 3. Use the session-aware Ductape client path (directly or through a reviewed application API),
2403
+ load canonical state on entry, persist every mutation, and render loading, failure, and retry.
2404
+ 4. Verify a real read-after-write round trip in the target environment. A successful animation,
2405
+ toast, local state change, mock response, or TypeScript compilation is not persistence proof.
2406
+ 5. For notification preferences, distinguish channel consent (email, sms, push) from event-category
2407
+ subscriptions. Never submit category labels where the Feature contract accepts channel keys.
2408
+ Completion review MUST reject static/mock settings, missing read or write paths, absent failure/retry
2409
+ states, and payload keys that were not checked against the registered Feature schema.
2410
+
2394
2411
  AUTHENTICATION AND SECURITY
2395
2412
  - Use publishableKey in browser applications. Never ship workspace private keys or privileged
2396
2413
  access keys in frontend bundles.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ductape/mcp",
3
- "version": "0.3.5",
3
+ "version": "0.3.6",
4
4
  "description": "MCP server that exposes Ductape SDK operations via the backend proxy",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",