@fabricorg/sdui-release 0.5.0 → 0.7.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 +67 -0
- package/dist/index.cjs +44 -12
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +44 -12
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,72 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.7.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 8436c64: Close what a seventh review found in the previous follow-up, two of them regressions it introduced.
|
|
8
|
+
|
|
9
|
+
**An idempotency conflict is settled, but which way depends on why.** The previous release treated
|
|
10
|
+
every conflict as "never applied" and reported it refused. Only a `parameters` or `actor` conflict
|
|
11
|
+
means that. An `authority_binding` or `action_version` conflict means the _original_ invocation
|
|
12
|
+
exists and may well have applied — the capture-authority adapter mints a fresh binding on every
|
|
13
|
+
attempt, so a first attempt whose response was lost conflicts with itself on the second. Deleting that
|
|
14
|
+
capture and calling it refused was the worst available answer; it is now surfaced as `unknown` under
|
|
15
|
+
status `conflict_prior_invocation`.
|
|
16
|
+
|
|
17
|
+
**A policy block or validation failure is now `unknown`, not `refused`.** Within one attempt both are
|
|
18
|
+
decided before any effect. On a recovery re-execution the worker skips adapter steps that already
|
|
19
|
+
succeeded, then re-evaluates policy with a fresh clock and re-parses parameters against a possibly
|
|
20
|
+
newer action, and either can flip after effects committed. Unlike the authority path, the host
|
|
21
|
+
persists no execution reason for these, so the client cannot tell first delivery from recovery; it
|
|
22
|
+
errs toward a person checking. The precise fix is for the host to persist `executionReason` on failed
|
|
23
|
+
invocations, which is a store change and is recorded rather than attempted here.
|
|
24
|
+
|
|
25
|
+
**`failed` means "never delivered" again.** A store fault after a successful delivery was being counted
|
|
26
|
+
in it; it now lives only in `storeFailures`. The 0.3.0 changelog's disclosure misdescribed what 0.2.0
|
|
27
|
+
had changed — `parked` never shipped as a count; only `expired` did — and it is corrected in place.
|
|
28
|
+
|
|
29
|
+
Every validation pass now sees a duplicated contract once, so one root cause produces one finding
|
|
30
|
+
rather than one per copy. `deriveAuthorizationGrants` no longer emits a reference for an intent whose
|
|
31
|
+
action the contract does not declare, matching what promotion resolves. A superseded comment above
|
|
32
|
+
`PORT_ID` that asserted the claim the fix retracted is removed.
|
|
33
|
+
|
|
34
|
+
## 0.6.0
|
|
35
|
+
|
|
36
|
+
### Minor Changes
|
|
37
|
+
|
|
38
|
+
- 4780974: Close what a sixth review found in the previously unreviewed fix batch, and disclose a breaking change
|
|
39
|
+
that batch shipped under a minor.
|
|
40
|
+
|
|
41
|
+
**Disclosure, first.** `experience-runtime@0.2.0` changed `OfflineReplaySummary.expired` from a
|
|
42
|
+
count to an array of records — breaking for a 0.1.0 consumer, for whom `if (summary.expired)` becomes
|
|
43
|
+
permanently true. (`parked` was introduced and reshaped inside the 0.2.0 window and never shipped as
|
|
44
|
+
a count, so no published consumer could have depended on it.) The 0.2.0 changelog did disclose the
|
|
45
|
+
change, but one of its four aggregated entries still described counts. This release adds
|
|
46
|
+
`storeFailures`, a **required** field on the returned summary: source-breaking for anything that
|
|
47
|
+
constructs an `OfflineReplaySummary` or implements the exported `OfflineCaptureQueue`, which a test
|
|
48
|
+
double may. Treat the shape as changed.
|
|
49
|
+
|
|
50
|
+
**Offline replay.** An authority refusal on a _recovery_ re-execution lands after adapter steps
|
|
51
|
+
already committed, since the lease worker re-runs authorization but skips succeeded steps rather
|
|
52
|
+
than undoing them; it is now reported as `unknown`, not `refused`, using the `executionReason` the
|
|
53
|
+
platform persists. A store that throws mid-replay now degrades one record instead of rejecting the
|
|
54
|
+
batch and losing every entry already removed. An idempotency conflict is settled — the key was reused
|
|
55
|
+
for a different command and retrying yields the same conflict forever — so it reaches a person rather
|
|
56
|
+
than looping. An action-version mismatch is transient, since it fires mid-rollout. An adapter
|
|
57
|
+
returning nothing keeps the capture queued rather than draining the queue into `unknown`.
|
|
58
|
+
|
|
59
|
+
**Release validation.** A grant that no supplied capability publishes now fails validation instead of
|
|
60
|
+
dying at promotion with "route missing"; ambiguity was scoped to granted references and had covered
|
|
61
|
+
only the two-or-more case. A contract supplied twice yields exactly one finding — the previous fix
|
|
62
|
+
still reported each of its granted views as declared twice, and the changelog claimed otherwise. An
|
|
63
|
+
intent whose action the contract does not declare no longer counts toward ambiguity, matching what
|
|
64
|
+
promotion resolves.
|
|
65
|
+
|
|
66
|
+
**Ports.** `PORT_ID` accepts any segment shape a manifest permits after the first dot, so every
|
|
67
|
+
namespaced name a capability can declare is a name a port can define. Dotless names remain
|
|
68
|
+
undefinable by design.
|
|
69
|
+
|
|
3
70
|
## 0.5.0
|
|
4
71
|
|
|
5
72
|
### 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}`)) {
|
|
@@ -713,6 +715,25 @@ function validateSduiRelease(input) {
|
|
|
713
715
|
...resolved.remote ? { remote: resolved.remote } : {}
|
|
714
716
|
});
|
|
715
717
|
}
|
|
718
|
+
const contractNamespaces = /* @__PURE__ */ new Set();
|
|
719
|
+
const distinctContracts = contracts.filter((contract) => {
|
|
720
|
+
if (contractNamespaces.has(contract.namespace)) {
|
|
721
|
+
add(
|
|
722
|
+
"ambiguous_capability_reference",
|
|
723
|
+
`contracts.${contract.namespace}`,
|
|
724
|
+
`contract for "${contract.namespace}" is supplied more than once`
|
|
725
|
+
);
|
|
726
|
+
return false;
|
|
727
|
+
}
|
|
728
|
+
contractNamespaces.add(contract.namespace);
|
|
729
|
+
return true;
|
|
730
|
+
});
|
|
731
|
+
const seenDocumentNamespaces = /* @__PURE__ */ new Set();
|
|
732
|
+
const distinctDocuments = input.contracts.filter((document) => {
|
|
733
|
+
if (seenDocumentNamespaces.has(document.capability.namespace)) return false;
|
|
734
|
+
seenDocumentNamespaces.add(document.capability.namespace);
|
|
735
|
+
return true;
|
|
736
|
+
});
|
|
716
737
|
{
|
|
717
738
|
for (const pack of resolvedPacks) {
|
|
718
739
|
const approved = input.assembly.componentPacks.find(
|
|
@@ -764,7 +785,7 @@ function validateSduiRelease(input) {
|
|
|
764
785
|
);
|
|
765
786
|
}
|
|
766
787
|
}
|
|
767
|
-
for (const document of
|
|
788
|
+
for (const document of distinctDocuments) {
|
|
768
789
|
const approved = input.assembly.capabilities.find(
|
|
769
790
|
(capability) => capability.namespace === document.capability.namespace && capability.usageContractDigest === (0, import_assembly2.computeUsageContractDocumentDigest)(document)
|
|
770
791
|
);
|
|
@@ -784,23 +805,32 @@ function validateSduiRelease(input) {
|
|
|
784
805
|
}
|
|
785
806
|
}
|
|
786
807
|
const coreComponents = new Set(input.coreComponents ?? []);
|
|
787
|
-
const knownViews = buildKnownViews(
|
|
808
|
+
const knownViews = buildKnownViews(distinctContracts);
|
|
788
809
|
const grantedViews = buildGrantedReferences(input.grants.views, "grants.views");
|
|
789
810
|
const grantedIntents = buildGrantedReferences(input.grants.intents, "grants.intents");
|
|
790
|
-
const knownIntents = buildKnownActionIntents(
|
|
791
|
-
reportAmbiguousGrantedViews(
|
|
792
|
-
const
|
|
793
|
-
|
|
794
|
-
if (
|
|
811
|
+
const knownIntents = buildKnownActionIntents(distinctContracts, add, grantedIntents);
|
|
812
|
+
reportAmbiguousGrantedViews(distinctContracts, grantedViews, add);
|
|
813
|
+
for (const reference of grantedViews) {
|
|
814
|
+
const parsed = parseCapabilityRef(reference);
|
|
815
|
+
if (parsed && !knownViews.has(`${parsed.namespace}/${parsed.name}`)) {
|
|
795
816
|
add(
|
|
796
|
-
"
|
|
797
|
-
`
|
|
798
|
-
`
|
|
817
|
+
"unauthorized_data_ref",
|
|
818
|
+
`grants.views.${reference}`,
|
|
819
|
+
`release grants "${reference}", which no supplied capability publishes; promotion would fail to route it`
|
|
820
|
+
);
|
|
821
|
+
}
|
|
822
|
+
}
|
|
823
|
+
for (const reference of grantedIntents) {
|
|
824
|
+
const parsed = parseCapabilityRef(reference);
|
|
825
|
+
if (parsed && !knownIntents.has(`${parsed.namespace}/${parsed.name}`)) {
|
|
826
|
+
add(
|
|
827
|
+
"mutation_bypass",
|
|
828
|
+
`grants.intents.${reference}`,
|
|
829
|
+
`release grants "${reference}", which no supplied capability declares as an intent backed by a declared action; promotion would fail to route it`
|
|
799
830
|
);
|
|
800
831
|
}
|
|
801
|
-
contractNamespaces.add(contract.namespace);
|
|
802
832
|
}
|
|
803
|
-
validateIntentActionDeclarations(
|
|
833
|
+
validateIntentActionDeclarations(distinctContracts, add);
|
|
804
834
|
const fragmentGrants = /* @__PURE__ */ new Map();
|
|
805
835
|
for (const [fragmentId, declared] of Object.entries(input.grants.fragments ?? {})) {
|
|
806
836
|
for (const view of declared.views ?? []) {
|
|
@@ -1102,7 +1132,9 @@ function deriveAuthorizationGrants(contracts, held, options = {}) {
|
|
|
1102
1132
|
const reference = `capability://${contract.namespace}/${shortName(view.name, contract.namespace, "/")}`;
|
|
1103
1133
|
if (!bound || bound.views.has(reference)) views.push(reference);
|
|
1104
1134
|
}
|
|
1135
|
+
const declaredActions = new Set(contract.actions.map((action) => action.actionId));
|
|
1105
1136
|
for (const intent of actionIntentsOf(contract)) {
|
|
1137
|
+
if (!declaredActions.has(intent.actionId)) continue;
|
|
1106
1138
|
const reference = `capability://${contract.namespace}/${shortName(intent.name, contract.namespace, ".")}`;
|
|
1107
1139
|
if (!bound || bound.intents.has(reference)) intents.push(reference);
|
|
1108
1140
|
}
|