@fabricorg/sdui-release 0.5.0 → 0.6.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,38 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.6.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 4780974: Close what a sixth review found in the previously unreviewed fix batch, and disclose a breaking change
8
+ that batch shipped under a minor.
9
+
10
+ **Disclosure, first.** `experience-runtime@0.2.0` changed `OfflineReplaySummary.parked` and
11
+ `expired` from counts to arrays of records. That is breaking for any consumer of 0.1.0 — `parked > 0`
12
+ becomes permanently false and `if (expired)` permanently true — and its changelog described the
13
+ counts as still present. This release adds `storeFailures` to the same summary; treat the shape as
14
+ having changed at 0.2.0.
15
+
16
+ **Offline replay.** An authority refusal on a _recovery_ re-execution lands after adapter steps
17
+ already committed, since the lease worker re-runs authorization but skips succeeded steps rather
18
+ than undoing them; it is now reported as `unknown`, not `refused`, using the `executionReason` the
19
+ platform persists. A store that throws mid-replay now degrades one record instead of rejecting the
20
+ batch and losing every entry already removed. An idempotency conflict is settled — the key was reused
21
+ for a different command and retrying yields the same conflict forever — so it reaches a person rather
22
+ than looping. An action-version mismatch is transient, since it fires mid-rollout. An adapter
23
+ returning nothing keeps the capture queued rather than draining the queue into `unknown`.
24
+
25
+ **Release validation.** A grant that no supplied capability publishes now fails validation instead of
26
+ dying at promotion with "route missing"; ambiguity was scoped to granted references and had covered
27
+ only the two-or-more case. A contract supplied twice yields exactly one finding — the previous fix
28
+ still reported each of its granted views as declared twice, and the changelog claimed otherwise. An
29
+ intent whose action the contract does not declare no longer counts toward ambiguity, matching what
30
+ promotion resolves.
31
+
32
+ **Ports.** `PORT_ID` accepts any segment shape a manifest permits after the first dot, so every
33
+ namespaced name a capability can declare is a name a port can define. Dotless names remain
34
+ undefinable by design.
35
+
3
36
  ## 0.5.0
4
37
 
5
38
  ### Minor Changes
package/dist/index.cjs CHANGED
@@ -454,7 +454,9 @@ function buildKnownActionIntents(contracts, add, grantedIntents) {
454
454
  const occurrences = /* @__PURE__ */ new Map();
455
455
  for (const contract of contracts) {
456
456
  const experience = contract.extensions?.["fabric.experience/v1"];
457
+ const declaredActions = new Set(contract.actions.map((action) => action.actionId));
457
458
  for (const intent of experience?.actionIntents ?? []) {
459
+ if (!declaredActions.has(intent.actionId)) continue;
458
460
  const shortName2 = intent.name.startsWith(`${contract.namespace}.`) ? intent.name.slice(contract.namespace.length + 1) : intent.name;
459
461
  const reference = `${contract.namespace}/${shortName2}`;
460
462
  if (grantedIntents === void 0 || grantedIntents.has(`capability://${reference}`)) {
@@ -787,18 +789,40 @@ function validateSduiRelease(input) {
787
789
  const knownViews = buildKnownViews(contracts);
788
790
  const grantedViews = buildGrantedReferences(input.grants.views, "grants.views");
789
791
  const grantedIntents = buildGrantedReferences(input.grants.intents, "grants.intents");
790
- const knownIntents = buildKnownActionIntents(contracts, add, grantedIntents);
791
- reportAmbiguousGrantedViews(contracts, grantedViews, add);
792
792
  const contractNamespaces = /* @__PURE__ */ new Set();
793
- for (const contract of contracts) {
793
+ const distinctContracts = contracts.filter((contract) => {
794
794
  if (contractNamespaces.has(contract.namespace)) {
795
795
  add(
796
796
  "ambiguous_capability_reference",
797
797
  `contracts.${contract.namespace}`,
798
798
  `contract for "${contract.namespace}" is supplied more than once`
799
799
  );
800
+ return false;
800
801
  }
801
802
  contractNamespaces.add(contract.namespace);
803
+ return true;
804
+ });
805
+ const knownIntents = buildKnownActionIntents(distinctContracts, add, grantedIntents);
806
+ reportAmbiguousGrantedViews(distinctContracts, grantedViews, add);
807
+ for (const reference of grantedViews) {
808
+ const parsed = parseCapabilityRef(reference);
809
+ if (parsed && !knownViews.has(`${parsed.namespace}/${parsed.name}`)) {
810
+ add(
811
+ "unauthorized_data_ref",
812
+ `grants.views.${reference}`,
813
+ `release grants "${reference}", which no supplied capability publishes; promotion would fail to route it`
814
+ );
815
+ }
816
+ }
817
+ for (const reference of grantedIntents) {
818
+ const parsed = parseCapabilityRef(reference);
819
+ if (parsed && !knownIntents.has(`${parsed.namespace}/${parsed.name}`)) {
820
+ add(
821
+ "mutation_bypass",
822
+ `grants.intents.${reference}`,
823
+ `release grants "${reference}", which no supplied capability declares as an intent; promotion would fail to route it`
824
+ );
825
+ }
802
826
  }
803
827
  validateIntentActionDeclarations(contracts, add);
804
828
  const fragmentGrants = /* @__PURE__ */ new Map();