@brandlab-digital/conformance 1.0.0-rc.18 → 1.0.0-rc.20

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.
@@ -1,6 +1,7 @@
1
1
  export declare const BRANDLAB_CONFIG_V3_RULESET_ID = "project-config-v3@1.0.0-rc.2";
2
2
  export declare const BRANDLAB_CONFIG_V4_RULESET_ID = "project-config-v4@1.0.0-rc.12";
3
- export type BrandlabInspectableConfigurationContract = "project-config-v3" | "project-config-v4";
3
+ export declare const BRANDLAB_CONFIG_V5_RULESET_ID = "project-config-v5@1.0.0-rc.19";
4
+ export type BrandlabInspectableConfigurationContract = "project-config-v3" | "project-config-v4" | "project-config-v5";
4
5
  export declare const BRANDLAB_CONFIG_V3_PROFILES: readonly ["next-local-service", "next-root-level", "next-static-legacy", "legacy-php"];
5
6
  export interface InspectedBrandlabProjectConfig {
6
7
  projectId: string;
@@ -1 +1 @@
1
- {"version":3,"file":"project-config-v3.d.ts","sourceRoot":"","sources":["../src/project-config-v3.ts"],"names":[],"mappings":"AASA,eAAO,MAAM,6BAA6B,iCAAiC,CAAC;AAC5E,eAAO,MAAM,6BAA6B,kCAAkC,CAAC;AAC7E,MAAM,MAAM,wCAAwC,GAChD,mBAAmB,GACnB,mBAAmB,CAAC;AAExB,eAAO,MAAM,2BAA2B,wFAK9B,CAAC;AA+CX,MAAM,WAAW,8BAA8B;IAC7C,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,CAAC,OAAO,2BAA2B,CAAC,CAAC,MAAM,CAAC,CAAC;IACtD,MAAM,EAAE;QACN,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;KAC7B,CAAC;IACF,mBAAmB,EAAE;QACnB,oBAAoB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;KACxD,CAAC;IACF,YAAY,EAAE;QACZ,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;QAC3B,cAAc,EAAE,OAAO,CAAC;QACxB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;QAChC,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;QAC/B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;QAC3B,eAAe,EAAE,SAAS,MAAM,EAAE,CAAC;QACnC,0BAA0B,EAAE,MAAM,GAAG,IAAI,CAAC;KAC3C,CAAC;CACH;AAED,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,SAAS,GAAG,SAAS,GAAG,MAAM,CAAC;IACzC,YAAY,EAAE,QAAQ,GAAG,aAAa,GAAG,SAAS,CAAC;IACnD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,0BAA0B;IACzC,MAAM,EAAE,8BAA8B,GAAG,IAAI,CAAC;IAC9C,OAAO,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC7B,iBAAiB,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACvC,kBAAkB,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACxC,iBAAiB,EAAE,WAAW,CAAC,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC;IAC5D,kBAAkB,EAAE,WAAW,CAAC,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC;IAC7D,qBAAqB,EAAE,WAAW,CAAC,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC;IAChE,MAAM,EAAE,qBAAqB,EAAE,CAAC;CACjC;AAuLD,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE;IAAE,eAAe,CAAC,EAAE,wCAAwC,CAAA;CAAO,GAC3E,0BAA0B,CA6G5B;AA6/FD,sFAAsF;AACtF,wBAAgB,2CAA2C,CAAC,UAAU,EAAE,MAAM,UAe7E"}
1
+ {"version":3,"file":"project-config-v3.d.ts","sourceRoot":"","sources":["../src/project-config-v3.ts"],"names":[],"mappings":"AASA,eAAO,MAAM,6BAA6B,iCAAiC,CAAC;AAC5E,eAAO,MAAM,6BAA6B,kCAAkC,CAAC;AAC7E,eAAO,MAAM,6BAA6B,kCAAkC,CAAC;AAC7E,MAAM,MAAM,wCAAwC,GAChD,mBAAmB,GACnB,mBAAmB,GACnB,mBAAmB,CAAC;AAExB,eAAO,MAAM,2BAA2B,wFAK9B,CAAC;AA+CX,MAAM,WAAW,8BAA8B;IAC7C,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,CAAC,OAAO,2BAA2B,CAAC,CAAC,MAAM,CAAC,CAAC;IACtD,MAAM,EAAE;QACN,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;KAC7B,CAAC;IACF,mBAAmB,EAAE;QACnB,oBAAoB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;KACxD,CAAC;IACF,YAAY,EAAE;QACZ,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;QAC3B,cAAc,EAAE,OAAO,CAAC;QACxB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;QAChC,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;QAC/B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;QAC3B,eAAe,EAAE,SAAS,MAAM,EAAE,CAAC;QACnC,0BAA0B,EAAE,MAAM,GAAG,IAAI,CAAC;KAC3C,CAAC;CACH;AAED,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,SAAS,GAAG,SAAS,GAAG,MAAM,CAAC;IACzC,YAAY,EAAE,QAAQ,GAAG,aAAa,GAAG,SAAS,CAAC;IACnD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,0BAA0B;IACzC,MAAM,EAAE,8BAA8B,GAAG,IAAI,CAAC;IAC9C,OAAO,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC7B,iBAAiB,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACvC,kBAAkB,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACxC,iBAAiB,EAAE,WAAW,CAAC,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC;IAC5D,kBAAkB,EAAE,WAAW,CAAC,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC;IAC7D,qBAAqB,EAAE,WAAW,CAAC,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC;IAChE,MAAM,EAAE,qBAAqB,EAAE,CAAC;CACjC;AAuOD,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE;IAAE,eAAe,CAAC,EAAE,wCAAwC,CAAA;CAAO,GAC3E,0BAA0B,CA6G5B;AA0gGD,sFAAsF;AACtF,wBAAgB,2CAA2C,CAAC,UAAU,EAAE,MAAM,UAe7E"}
@@ -8,6 +8,7 @@ import { extname, join, relative } from "node:path";
8
8
  import * as ts from "typescript";
9
9
  export const BRANDLAB_CONFIG_V3_RULESET_ID = "project-config-v3@1.0.0-rc.2";
10
10
  export const BRANDLAB_CONFIG_V4_RULESET_ID = "project-config-v4@1.0.0-rc.12";
11
+ export const BRANDLAB_CONFIG_V5_RULESET_ID = "project-config-v5@1.0.0-rc.19";
11
12
  export const BRANDLAB_CONFIG_V3_PROFILES = [
12
13
  "next-local-service",
13
14
  "next-root-level",
@@ -184,6 +185,54 @@ const FORBIDDEN_CANDIDATE_EXPORTS = [
184
185
  },
185
186
  ];
186
187
  const PROTECTED_LOCAL_PATTERNS = [
188
+ {
189
+ ruleId: "brandlab-config-v3-circular-business-evidence",
190
+ minimumContract: "project-config-v5",
191
+ surface: "business",
192
+ pattern: /\b(?:existing-production-config|repository-config|source-code):/i,
193
+ expected: "Verified business facts cite independent evidence, not the repository value being verified.",
194
+ remediation: "Use structured official-registry, GBP, client-document, first-party-record or public-authority evidence; otherwise mark the fact unknown.",
195
+ },
196
+ {
197
+ ruleId: "brandlab-config-v3-service-area-public-address",
198
+ minimumContract: "project-config-v5",
199
+ surface: "business",
200
+ pattern: /\bmodel\s*:\s*["']service-area["'][\s\S]{0,1200}\baddressVisibility\s*:\s*["']public["']|\baddressVisibility\s*:\s*["']public["'][\s\S]{0,1200}\bmodel\s*:\s*["']service-area["']/i,
201
+ expected: "Customer-location-only service-area businesses keep address facts hidden.",
202
+ remediation: "Use model service-area, addressVisibility hidden and an unknown or not-applicable address fact.",
203
+ },
204
+ {
205
+ ruleId: "brandlab-config-v3-synthetic-review-proof",
206
+ minimumContract: "project-config-v5",
207
+ surface: "location-proof",
208
+ pattern: /\bregion-review:[^"'`\n]*[\s\S]{0,2400}\b(?:review\?\.\w+\s*\|\||trust\s+\w+|customer feedback across)\b/i,
209
+ expected: "Review proof exists only when an approved review record is bound to business.proof.",
210
+ remediation: "Remove fallback review proof and use verified review evidence or no review proof.",
211
+ },
212
+ {
213
+ ruleId: "brandlab-config-v3-local-programmatic-proof-derivation",
214
+ minimumContract: "project-config-v5",
215
+ surface: "location-proof",
216
+ pattern: /\bfunction\s+getProofLevelFromAssetIds\s*\(/,
217
+ expected: "Programmatic proof levels are derived by @brandlab-digital/site-core/locations.",
218
+ remediation: "Remove the project-local proof classifier and call defineLocationRouteQuality with business.proof.",
219
+ },
220
+ {
221
+ ruleId: "brandlab-config-v3-hardcoded-search-demand",
222
+ minimumContract: "project-config-v5",
223
+ surface: "location-quality",
224
+ pattern: /\bsearchDemand\s*:\s*["']medium["']/,
225
+ expected: "Search demand is observed from evidence or explicitly unknown.",
226
+ remediation: "Replace the assumed medium value with unknown or an evidence-backed observed record.",
227
+ },
228
+ {
229
+ ruleId: "brandlab-config-v3-hidden-focusable-content",
230
+ minimumContract: "project-config-v5",
231
+ surface: "accessibility",
232
+ pattern: /\baria-hidden\s*=\s*(?:\{\s*true\s*\}|["']true["'])[\s\S]{0,1200}<\s*(?:a|button|input|select|textarea)\b/i,
233
+ expected: "Collapsed or aria-hidden content contains no focusable controls.",
234
+ remediation: "Remove collapsed controls from the DOM or make every descendant unfocusable until the content is visible.",
235
+ },
187
236
  {
188
237
  ruleId: "brandlab-config-v3-local-contact-transport",
189
238
  surface: "contact",
@@ -239,7 +288,7 @@ const PROTECTED_LOCAL_PATTERNS = [
239
288
  },
240
289
  ];
241
290
  export function inspectBrandlabConfigV3(root, options = {}) {
242
- const contractVersion = options.contractVersion ?? "project-config-v4";
291
+ const contractVersion = options.contractVersion ?? "project-config-v5";
243
292
  const issues = [];
244
293
  const configPath = join(root, "brandlab.config.ts");
245
294
  const usage = collectProjectImports(root, issues);
@@ -760,7 +809,7 @@ function validateCapabilities(capabilities, issues, contractVersion) {
760
809
  }
761
810
  else {
762
811
  addUnknownKeyIssues(capabilities.reviews, capabilities.reviews.provider === "google-places" &&
763
- contractVersion === "project-config-v4"
812
+ contractVersion !== "project-config-v3"
764
813
  ? new Set(["provider", "mode", "routeIds", "monthlyRequestLimit"])
765
814
  : new Set(["provider"]), new Set(), "capabilities.reviews", issues);
766
815
  if (typeof capabilities.reviews.provider !== "string" ||
@@ -774,7 +823,7 @@ function validateCapabilities(capabilities, issues, contractVersion) {
774
823
  }));
775
824
  }
776
825
  if (capabilities.reviews.provider === "google-places" &&
777
- contractVersion === "project-config-v4") {
826
+ contractVersion !== "project-config-v3") {
778
827
  if (typeof capabilities.reviews.mode !== "string" ||
779
828
  !GOOGLE_REVIEWS_MODES.has(capabilities.reviews.mode)) {
780
829
  issues.push(configIssue({
@@ -2882,8 +2931,7 @@ function addProtectedImplementationIssues(root, issues, contractVersion) {
2882
2931
  const source = readFileSync(file, "utf8");
2883
2932
  for (const rule of PROTECTED_LOCAL_PATTERNS) {
2884
2933
  if ("minimumContract" in rule &&
2885
- rule.minimumContract === "project-config-v4" &&
2886
- contractVersion !== "project-config-v4")
2934
+ !configurationContractIncludes(contractVersion, rule.minimumContract))
2887
2935
  continue;
2888
2936
  const match = rule.pattern.exec(source);
2889
2937
  if (!match || match.index === undefined)
@@ -2894,9 +2942,11 @@ function addProtectedImplementationIssues(root, issues, contractVersion) {
2894
2942
  surface: rule.surface,
2895
2943
  expected: rule.expected,
2896
2944
  actual: `A protected local implementation was found in ${relativePath}.`,
2897
- remediation: rule.ruleId === "brandlab-config-v3-url-derived-breadcrumbs"
2898
- ? "Use BrandlabRouteBreadcrumbs with the typed route catalog; keep path labels only as a development fallback."
2899
- : "Keep only the thin project binding and consume the shared runtime.",
2945
+ remediation: "remediation" in rule
2946
+ ? rule.remediation
2947
+ : rule.ruleId === "brandlab-config-v3-url-derived-breadcrumbs"
2948
+ ? "Use BrandlabRouteBreadcrumbs with the typed route catalog; keep path labels only as a development fallback."
2949
+ : "Keep only the thin project binding and consume the shared runtime.",
2900
2950
  severity: "severity" in rule ? rule.severity : "blocker",
2901
2951
  path: relativePath,
2902
2952
  line,
@@ -2904,6 +2954,14 @@ function addProtectedImplementationIssues(root, issues, contractVersion) {
2904
2954
  }
2905
2955
  }
2906
2956
  }
2957
+ function configurationContractIncludes(actual, minimum) {
2958
+ const order = {
2959
+ "project-config-v3": 3,
2960
+ "project-config-v4": 4,
2961
+ "project-config-v5": 5,
2962
+ };
2963
+ return order[actual] >= order[minimum];
2964
+ }
2907
2965
  function walkSourceFiles(root) {
2908
2966
  if (!existsSync(root))
2909
2967
  return [];